summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_coding/codecs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/libwebrtc/modules/audio_coding/codecs
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/modules/audio_coding/codecs')
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/audio_decoder.h20
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/audio_encoder.h20
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc196
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc178
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc322
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h49
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc520
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/cng/cng_unittest.cc252
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc436
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.h99
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc102
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h81
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc126
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h128
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.c59
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.h135
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g711/test/testG711.cc168
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc178
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h86
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc156
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h71
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.c104
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.h173
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/g722/test/testG722.cc155
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.c82
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.h42
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.c89
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc110
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h54
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc151
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h61
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c64
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h42
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.c44
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.h37
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.c80
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.h44
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.c81
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.h37
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c69
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h34
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c67
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.c405
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.h40
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.c115
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.h41
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.c89
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.h39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.c76
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.c51
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.h39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/complexityMeasures.m57
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.c667
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.h95
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c83
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.c261
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.h42
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.c185
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.h45
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c85
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h41
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/defines.h225
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.c309
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.h44
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.c517
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.c46
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.c112
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.h33
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.c53
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.h40
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.c382
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c50
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.c90
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.h34
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.c47
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.c105
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.c126
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h40
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.c84
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.h46
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.c111
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.h41
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.c90
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.c91
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.c288
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.h251
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc140
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.c40
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.h27
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.c45
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.h31
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.c98
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.c73
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.c48
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.h35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.c53
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.h35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.c62
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.h42
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.c73
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.h32
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c44
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h37
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c48
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c63
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h34
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.c88
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.h33
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c86
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.c56
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.c35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.h37
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.c253
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.h34
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.c32
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.h32
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.c159
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.c141
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.h44
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c133
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h48
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c96
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h37
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c62
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h34
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c49
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h37
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.c212
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.h35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.c56
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.h33
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.c53
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.c63
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.c116
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.h38
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.c121
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.h41
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.c35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.h35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/empty.cc0
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_test.c238
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testLib.c215
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testprogram.c343
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.c241
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.h39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.c64
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.c63
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.h36
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.c64
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.h35
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.c142
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.h39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h54
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h84
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h108
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h224
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/bandwidth_info.h24
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/empty.cc0
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h22
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h22
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/isacfix.h486
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines.c122
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c401
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c413
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routins.h149
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc20
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc20
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c1021
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h128
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/codec.h212
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode.c221
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c69
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_plc.c805
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/encode.c635
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c2056
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h177
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c249
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c217
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.c415
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.h39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h87
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c62
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h52
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks.c297
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c242
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c278
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc103
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters.c112
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_mips.c365
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c114
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc68
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/initialize.c173
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h106
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c1230
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice.c321
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S77
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_c.c48
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c329
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c195
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c949
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h69
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c237
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc61
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c1281
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h97
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c435
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h67
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c114
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c193
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c248
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S143
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c73
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c133
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c149
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h46
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c306
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h99
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/settings.h211
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c193
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h97
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/structs.h345
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform.c214
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_mips.c1294
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c479
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_tables.c110
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc199
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc120
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc346
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h22
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h22
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/isac.h617
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.c60
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.h67
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c291
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c303
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc20
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc20
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc61
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c1013
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h165
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/codec.h223
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.c111
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.h41
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode.c303
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode_bwe.c89
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode.c1260
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c706
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h246
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.c2066
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.h347
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.c195
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.h23
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filterbanks.c114
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/intialize.c72
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac.c2307
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_float_type.h100
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc111
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.c409
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.h45
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lattice.c219
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c496
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h46
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c136
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h50
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c158
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h66
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c247
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h81
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.c601
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.h99
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h42
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c695
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h32
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.c388
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.h42
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c104
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h48
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c277
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h116
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/settings.h196
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c139
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h79
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/structs.h448
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/transform.c126
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc942
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc425
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/simpleKenny.c461
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.c179
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.h108
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.cc88
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h53
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc179
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/DEPS5
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.cc52
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.h89
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.cc182
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.h74
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_unittest.cc148
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc128
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h64
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.cc366
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.h92
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_unittest.cc156
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc827
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h185
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc906
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc152
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc97
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc248
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_inst.h48
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc878
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.h547
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc147
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_unittest.cc978
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/BUILD.gn55
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.cc76
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.h57
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer_unittest.cc111
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.cc215
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.h127
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker_unittest.cc293
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.cc100
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.h175
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform_unittest.cc203
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc70
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h52
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc39
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h46
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.c32
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h63
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.cc29
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.h22
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc272
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h102
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc641
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc126
-rw-r--r--third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h93
358 files changed, 65553 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/audio_decoder.h b/third_party/libwebrtc/modules/audio_coding/codecs/audio_decoder.h
new file mode 100644
index 0000000000..b7b15cdd6e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/audio_decoder.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file is for backwards compatibility only! Use
+// webrtc/api/audio_codecs/audio_decoder.h instead!
+// TODO(kwiberg): Remove it.
+
+#ifndef MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_
+#define MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_
+
+#include "api/audio_codecs/audio_decoder.h"
+
+#endif // MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/audio_encoder.h b/third_party/libwebrtc/modules/audio_coding/codecs/audio_encoder.h
new file mode 100644
index 0000000000..010ae6705f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/audio_encoder.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file is for backwards compatibility only! Use
+// webrtc/api/audio_codecs/audio_encoder.h instead!
+// TODO(ossu): Remove it.
+
+#ifndef MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
+#define MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
+
+#include "api/audio_codecs/audio_encoder.h"
+
+#endif // MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc
new file mode 100644
index 0000000000..109da78eea
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_unittest.cc
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/builtin_audio_decoder_factory.h"
+
+#include <memory>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+
+TEST(AudioDecoderFactoryTest, CreateUnknownDecoder) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("rey", 8000, 1), absl::nullopt));
+}
+
+TEST(AudioDecoderFactoryTest, CreatePcmu) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // PCMu supports 8 kHz, and any number of channels.
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 0), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 1), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 2), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 3), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 16000, 1), absl::nullopt));
+}
+
+TEST(AudioDecoderFactoryTest, CreatePcma) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // PCMa supports 8 kHz, and any number of channels.
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 0), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 1), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 2), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 3), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("pcma", 16000, 1), absl::nullopt));
+}
+
+TEST(AudioDecoderFactoryTest, CreateIlbc) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // iLBC supports 8 kHz, 1 channel.
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 0), absl::nullopt));
+#ifdef WEBRTC_CODEC_ILBC
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 1), absl::nullopt));
+#endif
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 2), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 16000, 1), absl::nullopt));
+}
+
+TEST(AudioDecoderFactoryTest, CreateIsac) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // iSAC supports 16 kHz, 1 channel. The float implementation additionally
+ // supports 32 kHz, 1 channel.
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 0), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 1), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 2), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 8000, 1), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 48000, 1), absl::nullopt));
+#ifdef WEBRTC_ARCH_ARM
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 32000, 1), absl::nullopt));
+#else
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("isac", 32000, 1), absl::nullopt));
+#endif
+}
+
+TEST(AudioDecoderFactoryTest, CreateL16) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // L16 supports any clock rate and any number of channels up to 24.
+ const int clockrates[] = {8000, 16000, 32000, 48000};
+ const int num_channels[] = {1, 2, 3, 24};
+ for (int clockrate : clockrates) {
+ EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("l16", clockrate, 0),
+ absl::nullopt));
+ for (int channels : num_channels) {
+ EXPECT_TRUE(adf->MakeAudioDecoder(
+ SdpAudioFormat("l16", clockrate, channels), absl::nullopt));
+ }
+ }
+}
+
+// Tests that using more channels than the maximum does not work
+TEST(AudioDecoderFactoryTest, MaxNrOfChannels) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ std::vector<std::string> codecs = {
+#ifdef WEBRTC_CODEC_OPUS
+ "opus",
+#endif
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+ "isac",
+#endif
+#ifdef WEBRTC_CODEC_ILBC
+ "ilbc",
+#endif
+ "pcmu",
+ "pcma",
+ "l16",
+ "G722",
+ "G711",
+ };
+
+ for (auto codec : codecs) {
+ EXPECT_FALSE(adf->MakeAudioDecoder(
+ SdpAudioFormat(codec, 32000, AudioDecoder::kMaxNumberOfChannels + 1),
+ absl::nullopt));
+ }
+}
+
+TEST(AudioDecoderFactoryTest, CreateG722) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // g722 supports 8 kHz, 1-2 channels.
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 0), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 1), absl::nullopt));
+ EXPECT_TRUE(
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 2), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 3), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 16000, 1), absl::nullopt));
+ EXPECT_FALSE(
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 32000, 1), absl::nullopt));
+
+ // g722 actually uses a 16 kHz sample rate instead of the nominal 8 kHz.
+ std::unique_ptr<AudioDecoder> dec =
+ adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 1), absl::nullopt);
+ EXPECT_EQ(16000, dec->SampleRateHz());
+}
+
+TEST(AudioDecoderFactoryTest, CreateOpus) {
+ rtc::scoped_refptr<AudioDecoderFactory> adf =
+ CreateBuiltinAudioDecoderFactory();
+ ASSERT_TRUE(adf);
+ // Opus supports 48 kHz, 2 channels, and wants a "stereo" parameter whose
+ // value is either "0" or "1".
+ for (int hz : {8000, 16000, 32000, 48000}) {
+ for (int channels : {0, 1, 2, 3}) {
+ for (std::string stereo : {"XX", "0", "1", "2"}) {
+ SdpAudioFormat::Parameters params;
+ if (stereo != "XX") {
+ params["stereo"] = stereo;
+ }
+ const bool good = (hz == 48000 && channels == 2 &&
+ (stereo == "XX" || stereo == "0" || stereo == "1"));
+ EXPECT_EQ(good,
+ static_cast<bool>(adf->MakeAudioDecoder(
+ SdpAudioFormat("opus", hz, channels, std::move(params)),
+ absl::nullopt)));
+ }
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
new file mode 100644
index 0000000000..26ae1eda8a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/builtin_audio_encoder_factory.h"
+
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include "rtc_base/numerics/safe_conversions.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+class AudioEncoderFactoryTest
+ : public ::testing::TestWithParam<rtc::scoped_refptr<AudioEncoderFactory>> {
+};
+
+TEST_P(AudioEncoderFactoryTest, SupportsAtLeastOneFormat) {
+ auto factory = GetParam();
+ auto supported_encoders = factory->GetSupportedEncoders();
+ EXPECT_FALSE(supported_encoders.empty());
+}
+
+TEST_P(AudioEncoderFactoryTest, CanQueryAllSupportedFormats) {
+ auto factory = GetParam();
+ auto supported_encoders = factory->GetSupportedEncoders();
+ for (const auto& spec : supported_encoders) {
+ auto info = factory->QueryAudioEncoder(spec.format);
+ EXPECT_TRUE(info);
+ }
+}
+
+TEST_P(AudioEncoderFactoryTest, CanConstructAllSupportedEncoders) {
+ auto factory = GetParam();
+ auto supported_encoders = factory->GetSupportedEncoders();
+ for (const auto& spec : supported_encoders) {
+ auto info = factory->QueryAudioEncoder(spec.format);
+ auto encoder = factory->MakeAudioEncoder(127, spec.format, absl::nullopt);
+ EXPECT_TRUE(encoder);
+ EXPECT_EQ(encoder->SampleRateHz(), info->sample_rate_hz);
+ EXPECT_EQ(encoder->NumChannels(), info->num_channels);
+ EXPECT_EQ(encoder->RtpTimestampRateHz(), spec.format.clockrate_hz);
+ }
+}
+
+TEST_P(AudioEncoderFactoryTest, CanRunAllSupportedEncoders) {
+ constexpr int kTestPayloadType = 127;
+ auto factory = GetParam();
+ auto supported_encoders = factory->GetSupportedEncoders();
+ for (const auto& spec : supported_encoders) {
+ auto encoder =
+ factory->MakeAudioEncoder(kTestPayloadType, spec.format, absl::nullopt);
+ EXPECT_TRUE(encoder);
+ encoder->Reset();
+ const int num_samples = rtc::checked_cast<int>(
+ encoder->SampleRateHz() * encoder->NumChannels() / 100);
+ rtc::Buffer out;
+ rtc::BufferT<int16_t> audio;
+ audio.SetData(num_samples, [](rtc::ArrayView<int16_t> audio) {
+ for (size_t i = 0; i != audio.size(); ++i) {
+ // Just put some numbers in there, ensure they're within range.
+ audio[i] =
+ static_cast<int16_t>(i & std::numeric_limits<int16_t>::max());
+ }
+ return audio.size();
+ });
+ // This is here to stop the test going forever with a broken encoder.
+ constexpr int kMaxEncodeCalls = 100;
+ int blocks = 0;
+ for (; blocks < kMaxEncodeCalls; ++blocks) {
+ AudioEncoder::EncodedInfo info = encoder->Encode(
+ blocks * encoder->RtpTimestampRateHz() / 100, audio, &out);
+ EXPECT_EQ(info.encoded_bytes, out.size());
+ if (info.encoded_bytes > 0) {
+ EXPECT_EQ(0u, info.encoded_timestamp);
+ EXPECT_EQ(kTestPayloadType, info.payload_type);
+ break;
+ }
+ }
+ ASSERT_LT(blocks, kMaxEncodeCalls);
+ const unsigned int next_timestamp =
+ blocks * encoder->RtpTimestampRateHz() / 100;
+ out.Clear();
+ for (; blocks < kMaxEncodeCalls; ++blocks) {
+ AudioEncoder::EncodedInfo info = encoder->Encode(
+ blocks * encoder->RtpTimestampRateHz() / 100, audio, &out);
+ EXPECT_EQ(info.encoded_bytes, out.size());
+ if (info.encoded_bytes > 0) {
+ EXPECT_EQ(next_timestamp, info.encoded_timestamp);
+ EXPECT_EQ(kTestPayloadType, info.payload_type);
+ break;
+ }
+ }
+ ASSERT_LT(blocks, kMaxEncodeCalls);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(BuiltinAudioEncoderFactoryTest,
+ AudioEncoderFactoryTest,
+ ::testing::Values(CreateBuiltinAudioEncoderFactory()));
+
+TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
+ using ::testing::ElementsAreArray;
+ // Check that we claim to support the formats we expect from build flags, and
+ // we've ordered them correctly.
+ auto factory = CreateBuiltinAudioEncoderFactory();
+ auto specs = factory->GetSupportedEncoders();
+
+ const std::vector<SdpAudioFormat> supported_formats = [&specs] {
+ std::vector<SdpAudioFormat> formats;
+ formats.reserve(specs.size());
+ for (const auto& spec : specs) {
+ formats.push_back(spec.format);
+ }
+ return formats;
+ }();
+
+ const std::vector<SdpAudioFormat> expected_formats = {
+#ifdef WEBRTC_CODEC_OPUS
+ {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}},
+#endif
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+ {"isac", 16000, 1},
+#endif
+#ifdef WEBRTC_CODEC_ISAC
+ {"isac", 32000, 1},
+#endif
+ {"G722", 8000, 1},
+#ifdef WEBRTC_CODEC_ILBC
+ {"ilbc", 8000, 1},
+#endif
+ {"pcmu", 8000, 1},
+ {"pcma", 8000, 1}
+ };
+
+ ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats));
+}
+
+// Tests that using more channels than the maximum does not work.
+TEST(BuiltinAudioEncoderFactoryTest, MaxNrOfChannels) {
+ rtc::scoped_refptr<AudioEncoderFactory> aef =
+ CreateBuiltinAudioEncoderFactory();
+ std::vector<std::string> codecs = {
+#ifdef WEBRTC_CODEC_OPUS
+ "opus",
+#endif
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+ "isac",
+#endif
+#ifdef WEBRTC_CODEC_ILBC
+ "ilbc",
+#endif
+ "pcmu",
+ "pcma",
+ "l16",
+ "G722",
+ "G711",
+ };
+
+ for (auto codec : codecs) {
+ EXPECT_FALSE(aef->MakeAudioEncoder(
+ /*payload_type=*/111,
+ /*format=*/
+ SdpAudioFormat(codec, 32000, AudioEncoder::kMaxNumberOfChannels + 1),
+ /*codec_pair_id=*/absl::nullopt));
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
new file mode 100644
index 0000000000..7546ac178f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
+
+#include <cstdint>
+#include <memory>
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/units/time_delta.h"
+#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kMaxFrameSizeMs = 60;
+
+class AudioEncoderCng final : public AudioEncoder {
+ public:
+ explicit AudioEncoderCng(AudioEncoderCngConfig&& config);
+ ~AudioEncoderCng() override;
+
+ // Not copyable or moveable.
+ AudioEncoderCng(const AudioEncoderCng&) = delete;
+ AudioEncoderCng(AudioEncoderCng&&) = delete;
+ AudioEncoderCng& operator=(const AudioEncoderCng&) = delete;
+ AudioEncoderCng& operator=(AudioEncoderCng&&) = delete;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ int RtpTimestampRateHz() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+ void Reset() override;
+ bool SetFec(bool enable) override;
+ bool SetDtx(bool enable) override;
+ bool SetApplication(Application application) override;
+ void SetMaxPlaybackRate(int frequency_hz) override;
+ rtc::ArrayView<std::unique_ptr<AudioEncoder>> ReclaimContainedEncoders()
+ override;
+ void OnReceivedUplinkPacketLossFraction(
+ float uplink_packet_loss_fraction) override;
+ void OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+
+ private:
+ EncodedInfo EncodePassive(size_t frames_to_encode, rtc::Buffer* encoded);
+ EncodedInfo EncodeActive(size_t frames_to_encode, rtc::Buffer* encoded);
+ size_t SamplesPer10msFrame() const;
+
+ std::unique_ptr<AudioEncoder> speech_encoder_;
+ const int cng_payload_type_;
+ const int num_cng_coefficients_;
+ const int sid_frame_interval_ms_;
+ std::vector<int16_t> speech_buffer_;
+ std::vector<uint32_t> rtp_timestamps_;
+ bool last_frame_active_;
+ std::unique_ptr<Vad> vad_;
+ std::unique_ptr<ComfortNoiseEncoder> cng_encoder_;
+};
+
+AudioEncoderCng::AudioEncoderCng(AudioEncoderCngConfig&& config)
+ : speech_encoder_((static_cast<void>([&] {
+ RTC_CHECK(config.IsOk()) << "Invalid configuration.";
+ }()),
+ std::move(config.speech_encoder))),
+ cng_payload_type_(config.payload_type),
+ num_cng_coefficients_(config.num_cng_coefficients),
+ sid_frame_interval_ms_(config.sid_frame_interval_ms),
+ last_frame_active_(true),
+ vad_(config.vad ? std::unique_ptr<Vad>(config.vad)
+ : CreateVad(config.vad_mode)),
+ cng_encoder_(new ComfortNoiseEncoder(SampleRateHz(),
+ sid_frame_interval_ms_,
+ num_cng_coefficients_)) {}
+
+AudioEncoderCng::~AudioEncoderCng() = default;
+
+int AudioEncoderCng::SampleRateHz() const {
+ return speech_encoder_->SampleRateHz();
+}
+
+size_t AudioEncoderCng::NumChannels() const {
+ return 1;
+}
+
+int AudioEncoderCng::RtpTimestampRateHz() const {
+ return speech_encoder_->RtpTimestampRateHz();
+}
+
+size_t AudioEncoderCng::Num10MsFramesInNextPacket() const {
+ return speech_encoder_->Num10MsFramesInNextPacket();
+}
+
+size_t AudioEncoderCng::Max10MsFramesInAPacket() const {
+ return speech_encoder_->Max10MsFramesInAPacket();
+}
+
+int AudioEncoderCng::GetTargetBitrate() const {
+ return speech_encoder_->GetTargetBitrate();
+}
+
+AudioEncoder::EncodedInfo AudioEncoderCng::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ const size_t samples_per_10ms_frame = SamplesPer10msFrame();
+ RTC_CHECK_EQ(speech_buffer_.size(),
+ rtp_timestamps_.size() * samples_per_10ms_frame);
+ rtp_timestamps_.push_back(rtp_timestamp);
+ RTC_DCHECK_EQ(samples_per_10ms_frame, audio.size());
+ speech_buffer_.insert(speech_buffer_.end(), audio.cbegin(), audio.cend());
+ const size_t frames_to_encode = speech_encoder_->Num10MsFramesInNextPacket();
+ if (rtp_timestamps_.size() < frames_to_encode) {
+ return EncodedInfo();
+ }
+ RTC_CHECK_LE(frames_to_encode * 10, kMaxFrameSizeMs)
+ << "Frame size cannot be larger than " << kMaxFrameSizeMs
+ << " ms when using VAD/CNG.";
+
+ // Group several 10 ms blocks per VAD call. Call VAD once or twice using the
+ // following split sizes:
+ // 10 ms = 10 + 0 ms; 20 ms = 20 + 0 ms; 30 ms = 30 + 0 ms;
+ // 40 ms = 20 + 20 ms; 50 ms = 30 + 20 ms; 60 ms = 30 + 30 ms.
+ size_t blocks_in_first_vad_call =
+ (frames_to_encode > 3 ? 3 : frames_to_encode);
+ if (frames_to_encode == 4)
+ blocks_in_first_vad_call = 2;
+ RTC_CHECK_GE(frames_to_encode, blocks_in_first_vad_call);
+ const size_t blocks_in_second_vad_call =
+ frames_to_encode - blocks_in_first_vad_call;
+
+ // Check if all of the buffer is passive speech. Start with checking the first
+ // block.
+ Vad::Activity activity = vad_->VoiceActivity(
+ &speech_buffer_[0], samples_per_10ms_frame * blocks_in_first_vad_call,
+ SampleRateHz());
+ if (activity == Vad::kPassive && blocks_in_second_vad_call > 0) {
+ // Only check the second block if the first was passive.
+ activity = vad_->VoiceActivity(
+ &speech_buffer_[samples_per_10ms_frame * blocks_in_first_vad_call],
+ samples_per_10ms_frame * blocks_in_second_vad_call, SampleRateHz());
+ }
+
+ EncodedInfo info;
+ switch (activity) {
+ case Vad::kPassive: {
+ info = EncodePassive(frames_to_encode, encoded);
+ last_frame_active_ = false;
+ break;
+ }
+ case Vad::kActive: {
+ info = EncodeActive(frames_to_encode, encoded);
+ last_frame_active_ = true;
+ break;
+ }
+ default: {
+ RTC_CHECK_NOTREACHED();
+ }
+ }
+
+ speech_buffer_.erase(
+ speech_buffer_.begin(),
+ speech_buffer_.begin() + frames_to_encode * samples_per_10ms_frame);
+ rtp_timestamps_.erase(rtp_timestamps_.begin(),
+ rtp_timestamps_.begin() + frames_to_encode);
+ return info;
+}
+
+void AudioEncoderCng::Reset() {
+ speech_encoder_->Reset();
+ speech_buffer_.clear();
+ rtp_timestamps_.clear();
+ last_frame_active_ = true;
+ vad_->Reset();
+ cng_encoder_.reset(new ComfortNoiseEncoder(
+ SampleRateHz(), sid_frame_interval_ms_, num_cng_coefficients_));
+}
+
+bool AudioEncoderCng::SetFec(bool enable) {
+ return speech_encoder_->SetFec(enable);
+}
+
+bool AudioEncoderCng::SetDtx(bool enable) {
+ return speech_encoder_->SetDtx(enable);
+}
+
+bool AudioEncoderCng::SetApplication(Application application) {
+ return speech_encoder_->SetApplication(application);
+}
+
+void AudioEncoderCng::SetMaxPlaybackRate(int frequency_hz) {
+ speech_encoder_->SetMaxPlaybackRate(frequency_hz);
+}
+
+rtc::ArrayView<std::unique_ptr<AudioEncoder>>
+AudioEncoderCng::ReclaimContainedEncoders() {
+ return rtc::ArrayView<std::unique_ptr<AudioEncoder>>(&speech_encoder_, 1);
+}
+
+void AudioEncoderCng::OnReceivedUplinkPacketLossFraction(
+ float uplink_packet_loss_fraction) {
+ speech_encoder_->OnReceivedUplinkPacketLossFraction(
+ uplink_packet_loss_fraction);
+}
+
+void AudioEncoderCng::OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) {
+ speech_encoder_->OnReceivedUplinkBandwidth(target_audio_bitrate_bps,
+ bwe_period_ms);
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderCng::GetFrameLengthRange() const {
+ return speech_encoder_->GetFrameLengthRange();
+}
+
+AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive(
+ size_t frames_to_encode,
+ rtc::Buffer* encoded) {
+ bool force_sid = last_frame_active_;
+ bool output_produced = false;
+ const size_t samples_per_10ms_frame = SamplesPer10msFrame();
+ AudioEncoder::EncodedInfo info;
+
+ for (size_t i = 0; i < frames_to_encode; ++i) {
+ // It's important not to pass &info.encoded_bytes directly to
+ // WebRtcCng_Encode(), since later loop iterations may return zero in
+ // that value, in which case we don't want to overwrite any value from
+ // an earlier iteration.
+ size_t encoded_bytes_tmp =
+ cng_encoder_->Encode(rtc::ArrayView<const int16_t>(
+ &speech_buffer_[i * samples_per_10ms_frame],
+ samples_per_10ms_frame),
+ force_sid, encoded);
+
+ if (encoded_bytes_tmp > 0) {
+ RTC_CHECK(!output_produced);
+ info.encoded_bytes = encoded_bytes_tmp;
+ output_produced = true;
+ force_sid = false;
+ }
+ }
+
+ info.encoded_timestamp = rtp_timestamps_.front();
+ info.payload_type = cng_payload_type_;
+ info.send_even_if_empty = true;
+ info.speech = false;
+ return info;
+}
+
+AudioEncoder::EncodedInfo AudioEncoderCng::EncodeActive(size_t frames_to_encode,
+ rtc::Buffer* encoded) {
+ const size_t samples_per_10ms_frame = SamplesPer10msFrame();
+ AudioEncoder::EncodedInfo info;
+ for (size_t i = 0; i < frames_to_encode; ++i) {
+ info =
+ speech_encoder_->Encode(rtp_timestamps_.front(),
+ rtc::ArrayView<const int16_t>(
+ &speech_buffer_[i * samples_per_10ms_frame],
+ samples_per_10ms_frame),
+ encoded);
+ if (i + 1 == frames_to_encode) {
+ RTC_CHECK_GT(info.encoded_bytes, 0) << "Encoder didn't deliver data.";
+ } else {
+ RTC_CHECK_EQ(info.encoded_bytes, 0)
+ << "Encoder delivered data too early.";
+ }
+ }
+ return info;
+}
+
+size_t AudioEncoderCng::SamplesPer10msFrame() const {
+ return rtc::CheckedDivExact(10 * SampleRateHz(), 1000);
+}
+
+} // namespace
+
+AudioEncoderCngConfig::AudioEncoderCngConfig() = default;
+AudioEncoderCngConfig::AudioEncoderCngConfig(AudioEncoderCngConfig&&) = default;
+AudioEncoderCngConfig::~AudioEncoderCngConfig() = default;
+
+bool AudioEncoderCngConfig::IsOk() const {
+ if (num_channels != 1)
+ return false;
+ if (!speech_encoder)
+ return false;
+ if (num_channels != speech_encoder->NumChannels())
+ return false;
+ if (sid_frame_interval_ms <
+ static_cast<int>(speech_encoder->Max10MsFramesInAPacket() * 10))
+ return false;
+ if (num_cng_coefficients > WEBRTC_CNG_MAX_LPC_ORDER ||
+ num_cng_coefficients <= 0)
+ return false;
+ return true;
+}
+
+std::unique_ptr<AudioEncoder> CreateComfortNoiseEncoder(
+ AudioEncoderCngConfig&& config) {
+ return std::make_unique<AudioEncoderCng>(std::move(config));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h b/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h
new file mode 100644
index 0000000000..8a1183489f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_CNG_AUDIO_ENCODER_CNG_H_
+#define MODULES_AUDIO_CODING_CODECS_CNG_AUDIO_ENCODER_CNG_H_
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "api/audio_codecs/audio_encoder.h"
+#include "common_audio/vad/include/vad.h"
+
+namespace webrtc {
+
+struct AudioEncoderCngConfig {
+ // Moveable, not copyable.
+ AudioEncoderCngConfig();
+ AudioEncoderCngConfig(AudioEncoderCngConfig&&);
+ ~AudioEncoderCngConfig();
+
+ bool IsOk() const;
+
+ size_t num_channels = 1;
+ int payload_type = 13;
+ std::unique_ptr<AudioEncoder> speech_encoder;
+ Vad::Aggressiveness vad_mode = Vad::kVadNormal;
+ int sid_frame_interval_ms = 100;
+ int num_cng_coefficients = 8;
+ // The Vad pointer is mainly for testing. If a NULL pointer is passed, the
+ // AudioEncoderCng creates (and destroys) a Vad object internally. If an
+ // object is passed, the AudioEncoderCng assumes ownership of the Vad
+ // object.
+ Vad* vad = nullptr;
+};
+
+std::unique_ptr<AudioEncoder> CreateComfortNoiseEncoder(
+ AudioEncoderCngConfig&& config);
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_CNG_AUDIO_ENCODER_CNG_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
new file mode 100644
index 0000000000..c688004363
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
+
+#include <memory>
+#include <vector>
+
+#include "common_audio/vad/mock/mock_vad.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "test/gtest.h"
+#include "test/mock_audio_encoder.h"
+#include "test/testsupport/rtc_expect_death.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Not;
+using ::testing::Optional;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+namespace webrtc {
+
+namespace {
+static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo.
+static const size_t kMockReturnEncodedBytes = 17;
+static const int kCngPayloadType = 18;
+} // namespace
+
+class AudioEncoderCngTest : public ::testing::Test {
+ protected:
+ AudioEncoderCngTest()
+ : mock_encoder_owner_(new MockAudioEncoder),
+ mock_encoder_(mock_encoder_owner_.get()),
+ mock_vad_(new MockVad),
+ timestamp_(4711),
+ num_audio_samples_10ms_(0),
+ sample_rate_hz_(8000) {
+ memset(audio_, 0, kMaxNumSamples * 2);
+ EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
+ }
+
+ AudioEncoderCngTest(const AudioEncoderCngTest&) = delete;
+ AudioEncoderCngTest& operator=(const AudioEncoderCngTest&) = delete;
+
+ void TearDown() override {
+ EXPECT_CALL(*mock_vad_, Die()).Times(1);
+ cng_.reset();
+ }
+
+ AudioEncoderCngConfig MakeCngConfig() {
+ AudioEncoderCngConfig config;
+ config.speech_encoder = std::move(mock_encoder_owner_);
+ EXPECT_TRUE(config.speech_encoder);
+
+ // Let the AudioEncoderCng object use a MockVad instead of its internally
+ // created Vad object.
+ config.vad = mock_vad_;
+ config.payload_type = kCngPayloadType;
+
+ return config;
+ }
+
+ void CreateCng(AudioEncoderCngConfig&& config) {
+ num_audio_samples_10ms_ = static_cast<size_t>(10 * sample_rate_hz_ / 1000);
+ ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples);
+ if (config.speech_encoder) {
+ EXPECT_CALL(*mock_encoder_, SampleRateHz())
+ .WillRepeatedly(Return(sample_rate_hz_));
+ // Max10MsFramesInAPacket() is just used to verify that the SID frame
+ // period is not too small. The return value does not matter that much,
+ // as long as it is smaller than 10.
+ EXPECT_CALL(*mock_encoder_, Max10MsFramesInAPacket())
+ .WillOnce(Return(1u));
+ }
+ cng_ = CreateComfortNoiseEncoder(std::move(config));
+ }
+
+ void Encode() {
+ ASSERT_TRUE(cng_) << "Must call CreateCng() first.";
+ encoded_info_ = cng_->Encode(
+ timestamp_,
+ rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_),
+ &encoded_);
+ timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_);
+ }
+
+ // Expect `num_calls` calls to the encoder, all successful. The last call
+ // claims to have encoded `kMockReturnEncodedBytes` bytes, and all the
+ // preceding ones 0 bytes.
+ void ExpectEncodeCalls(size_t num_calls) {
+ InSequence s;
+ AudioEncoder::EncodedInfo info;
+ for (size_t j = 0; j < num_calls - 1; ++j) {
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).WillOnce(Return(info));
+ }
+ info.encoded_bytes = kMockReturnEncodedBytes;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(
+ Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
+ }
+
+ // Verifies that the cng_ object waits until it has collected
+ // `blocks_per_frame` blocks of audio, and then dispatches all of them to
+ // the underlying codec (speech or cng).
+ void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) {
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(blocks_per_frame));
+ auto config = MakeCngConfig();
+ const int num_cng_coefficients = config.num_cng_coefficients;
+ CreateCng(std::move(config));
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive));
+
+ // Don't expect any calls to the encoder yet.
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
+ for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
+ Encode();
+ EXPECT_EQ(0u, encoded_info_.encoded_bytes);
+ }
+ if (active_speech)
+ ExpectEncodeCalls(blocks_per_frame);
+ Encode();
+ if (active_speech) {
+ EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
+ } else {
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients + 1),
+ encoded_info_.encoded_bytes);
+ }
+ }
+
+ // Verifies that the audio is partitioned into larger blocks before calling
+ // the VAD.
+ void CheckVadInputSize(int input_frame_size_ms,
+ int expected_first_block_size_ms,
+ int expected_second_block_size_ms) {
+ const size_t blocks_per_frame =
+ static_cast<size_t>(input_frame_size_ms / 10);
+
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(blocks_per_frame));
+
+ // Expect nothing to happen before the last block is sent to cng_.
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)).Times(0);
+ for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
+ Encode();
+ }
+
+ // Let the VAD decision be passive, since an active decision may lead to
+ // early termination of the decision loop.
+ InSequence s;
+ EXPECT_CALL(
+ *mock_vad_,
+ VoiceActivity(_, expected_first_block_size_ms * sample_rate_hz_ / 1000,
+ sample_rate_hz_))
+ .WillOnce(Return(Vad::kPassive));
+ if (expected_second_block_size_ms > 0) {
+ EXPECT_CALL(*mock_vad_,
+ VoiceActivity(
+ _, expected_second_block_size_ms * sample_rate_hz_ / 1000,
+ sample_rate_hz_))
+ .WillOnce(Return(Vad::kPassive));
+ }
+
+ // With this call to Encode(), `mock_vad_` should be called according to the
+ // above expectations.
+ Encode();
+ }
+
+ // Tests a frame with both active and passive speech. Returns true if the
+ // decision was active speech, false if it was passive.
+ bool CheckMixedActivePassive(Vad::Activity first_type,
+ Vad::Activity second_type) {
+ // Set the speech encoder frame size to 60 ms, to ensure that the VAD will
+ // be called twice.
+ const size_t blocks_per_frame = 6;
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(blocks_per_frame));
+ InSequence s;
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillOnce(Return(first_type));
+ if (first_type == Vad::kPassive) {
+ // Expect a second call to the VAD only if the first frame was passive.
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillOnce(Return(second_type));
+ }
+ encoded_info_.payload_type = 0;
+ for (size_t i = 0; i < blocks_per_frame; ++i) {
+ Encode();
+ }
+ return encoded_info_.payload_type != kCngPayloadType;
+ }
+
+ std::unique_ptr<AudioEncoder> cng_;
+ std::unique_ptr<MockAudioEncoder> mock_encoder_owner_;
+ MockAudioEncoder* mock_encoder_;
+ MockVad* mock_vad_; // Ownership is transferred to `cng_`.
+ uint32_t timestamp_;
+ int16_t audio_[kMaxNumSamples];
+ size_t num_audio_samples_10ms_;
+ rtc::Buffer encoded_;
+ AudioEncoder::EncodedInfo encoded_info_;
+ int sample_rate_hz_;
+};
+
+TEST_F(AudioEncoderCngTest, CreateAndDestroy) {
+ CreateCng(MakeCngConfig());
+}
+
+TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) {
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillOnce(Return(17U));
+ EXPECT_EQ(17U, cng_->Num10MsFramesInNextPacket());
+}
+
+TEST_F(AudioEncoderCngTest, CheckTargetAudioBitratePropagation) {
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_,
+ OnReceivedUplinkBandwidth(4711, absl::optional<int64_t>()));
+ cng_->OnReceivedUplinkBandwidth(4711, absl::nullopt);
+}
+
+TEST_F(AudioEncoderCngTest, CheckPacketLossFractionPropagation) {
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, OnReceivedUplinkPacketLossFraction(0.5));
+ cng_->OnReceivedUplinkPacketLossFraction(0.5);
+}
+
+TEST_F(AudioEncoderCngTest, CheckGetFrameLengthRangePropagation) {
+ CreateCng(MakeCngConfig());
+ auto expected_range =
+ std::make_pair(TimeDelta::Millis(20), TimeDelta::Millis(20));
+ EXPECT_CALL(*mock_encoder_, GetFrameLengthRange())
+ .WillRepeatedly(Return(absl::make_optional(expected_range)));
+ EXPECT_THAT(cng_->GetFrameLengthRange(), Optional(Eq(expected_range)));
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCallsVad) {
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(1U));
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillOnce(Return(Vad::kPassive));
+ Encode();
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCollects1BlockPassiveSpeech) {
+ CheckBlockGrouping(1, false);
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksPassiveSpeech) {
+ CheckBlockGrouping(2, false);
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksPassiveSpeech) {
+ CheckBlockGrouping(3, false);
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCollects1BlockActiveSpeech) {
+ CheckBlockGrouping(1, true);
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksActiveSpeech) {
+ CheckBlockGrouping(2, true);
+}
+
+TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksActiveSpeech) {
+ CheckBlockGrouping(3, true);
+}
+
+TEST_F(AudioEncoderCngTest, EncodePassive) {
+ const size_t kBlocksPerFrame = 3;
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(kBlocksPerFrame));
+ auto config = MakeCngConfig();
+ const auto sid_frame_interval_ms = config.sid_frame_interval_ms;
+ const auto num_cng_coefficients = config.num_cng_coefficients;
+ CreateCng(std::move(config));
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillRepeatedly(Return(Vad::kPassive));
+ // Expect no calls at all to the speech encoder mock.
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
+ uint32_t expected_timestamp = timestamp_;
+ for (size_t i = 0; i < 100; ++i) {
+ Encode();
+ // Check if it was time to call the cng encoder. This is done once every
+ // `kBlocksPerFrame` calls.
+ if ((i + 1) % kBlocksPerFrame == 0) {
+ // Now check if a SID interval has elapsed.
+ if ((i % (sid_frame_interval_ms / 10)) < kBlocksPerFrame) {
+ // If so, verify that we got a CNG encoding.
+ EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
+ EXPECT_FALSE(encoded_info_.speech);
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
+ encoded_info_.encoded_bytes);
+ EXPECT_EQ(expected_timestamp, encoded_info_.encoded_timestamp);
+ }
+ expected_timestamp += rtc::checked_cast<uint32_t>(
+ kBlocksPerFrame * num_audio_samples_10ms_);
+ } else {
+ // Otherwise, expect no output.
+ EXPECT_EQ(0u, encoded_info_.encoded_bytes);
+ }
+ }
+}
+
+// Verifies that the correct action is taken for frames with both active and
+// passive speech.
+TEST_F(AudioEncoderCngTest, MixedActivePassive) {
+ CreateCng(MakeCngConfig());
+
+ // All of the frame is active speech.
+ ExpectEncodeCalls(6);
+ EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kActive));
+ EXPECT_TRUE(encoded_info_.speech);
+
+ // First half of the frame is active speech.
+ ExpectEncodeCalls(6);
+ EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kPassive));
+ EXPECT_TRUE(encoded_info_.speech);
+
+ // Second half of the frame is active speech.
+ ExpectEncodeCalls(6);
+ EXPECT_TRUE(CheckMixedActivePassive(Vad::kPassive, Vad::kActive));
+ EXPECT_TRUE(encoded_info_.speech);
+
+ // All of the frame is passive speech. Expect no calls to `mock_encoder_`.
+ EXPECT_FALSE(CheckMixedActivePassive(Vad::kPassive, Vad::kPassive));
+ EXPECT_FALSE(encoded_info_.speech);
+}
+
+// These tests verify that the audio is partitioned into larger blocks before
+// calling the VAD.
+// The parameters for CheckVadInputSize are:
+// CheckVadInputSize(frame_size, expected_first_block_size,
+// expected_second_block_size);
+TEST_F(AudioEncoderCngTest, VadInputSize10Ms) {
+ CreateCng(MakeCngConfig());
+ CheckVadInputSize(10, 10, 0);
+}
+TEST_F(AudioEncoderCngTest, VadInputSize20Ms) {
+ CreateCng(MakeCngConfig());
+ CheckVadInputSize(20, 20, 0);
+}
+TEST_F(AudioEncoderCngTest, VadInputSize30Ms) {
+ CreateCng(MakeCngConfig());
+ CheckVadInputSize(30, 30, 0);
+}
+TEST_F(AudioEncoderCngTest, VadInputSize40Ms) {
+ CreateCng(MakeCngConfig());
+ CheckVadInputSize(40, 20, 20);
+}
+TEST_F(AudioEncoderCngTest, VadInputSize50Ms) {
+ CreateCng(MakeCngConfig());
+ CheckVadInputSize(50, 30, 20);
+}
+TEST_F(AudioEncoderCngTest, VadInputSize60Ms) {
+ CreateCng(MakeCngConfig());
+ CheckVadInputSize(60, 30, 30);
+}
+
+// Verifies that the correct payload type is set when CNG is encoded.
+TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) {
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U));
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillOnce(Return(Vad::kPassive));
+ encoded_info_.payload_type = 0;
+ Encode();
+ EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
+}
+
+// Verifies that a SID frame is encoded immediately as the signal changes from
+// active speech to passive.
+TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
+ auto config = MakeCngConfig();
+ const auto num_cng_coefficients = config.num_cng_coefficients;
+ CreateCng(std::move(config));
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(1U));
+ // Start with encoding noise.
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .Times(2)
+ .WillRepeatedly(Return(Vad::kPassive));
+ Encode();
+ EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
+ encoded_info_.encoded_bytes);
+ // Encode again, and make sure we got no frame at all (since the SID frame
+ // period is 100 ms by default).
+ Encode();
+ EXPECT_EQ(0u, encoded_info_.encoded_bytes);
+
+ // Now encode active speech.
+ encoded_info_.payload_type = 0;
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillOnce(Return(Vad::kActive));
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(
+ Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
+ Encode();
+ EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
+
+ // Go back to noise again, and verify that a SID frame is emitted.
+ EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
+ .WillOnce(Return(Vad::kPassive));
+ Encode();
+ EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
+ encoded_info_.encoded_bytes);
+}
+
+// Resetting the CNG should reset both the VAD and the encoder.
+TEST_F(AudioEncoderCngTest, Reset) {
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, Reset()).Times(1);
+ EXPECT_CALL(*mock_vad_, Reset()).Times(1);
+ cng_->Reset();
+}
+
+#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+// This test fixture tests various error conditions that makes the
+// AudioEncoderCng die via CHECKs.
+class AudioEncoderCngDeathTest : public AudioEncoderCngTest {
+ protected:
+ AudioEncoderCngDeathTest() : AudioEncoderCngTest() {
+ EXPECT_CALL(*mock_vad_, Die()).Times(1);
+ delete mock_vad_;
+ mock_vad_ = nullptr;
+ }
+
+ // Override AudioEncoderCngTest::TearDown, since that one expects a call to
+ // the destructor of `mock_vad_`. In this case, that object is already
+ // deleted.
+ void TearDown() override { cng_.reset(); }
+
+ AudioEncoderCngConfig MakeCngConfig() {
+ // Don't provide a Vad mock object, since it would leak when the test dies.
+ auto config = AudioEncoderCngTest::MakeCngConfig();
+ config.vad = nullptr;
+ return config;
+ }
+
+ void TryWrongNumCoefficients(int num) {
+ RTC_EXPECT_DEATH(
+ [&] {
+ auto config = MakeCngConfig();
+ config.num_cng_coefficients = num;
+ CreateCng(std::move(config));
+ }(),
+ "Invalid configuration");
+ }
+};
+
+TEST_F(AudioEncoderCngDeathTest, WrongFrameSize) {
+ CreateCng(MakeCngConfig());
+ num_audio_samples_10ms_ *= 2; // 20 ms frame.
+ RTC_EXPECT_DEATH(Encode(), "");
+ num_audio_samples_10ms_ = 0; // Zero samples.
+ RTC_EXPECT_DEATH(Encode(), "");
+}
+
+TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsA) {
+ TryWrongNumCoefficients(-1);
+}
+
+TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsB) {
+ TryWrongNumCoefficients(0);
+}
+
+TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsC) {
+ TryWrongNumCoefficients(13);
+}
+
+TEST_F(AudioEncoderCngDeathTest, NullSpeechEncoder) {
+ auto config = MakeCngConfig();
+ config.speech_encoder = nullptr;
+ RTC_EXPECT_DEATH(CreateCng(std::move(config)), "");
+}
+
+TEST_F(AudioEncoderCngDeathTest, StereoEncoder) {
+ EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(2));
+ RTC_EXPECT_DEATH(CreateCng(MakeCngConfig()), "Invalid configuration");
+}
+
+TEST_F(AudioEncoderCngDeathTest, StereoConfig) {
+ RTC_EXPECT_DEATH(
+ [&] {
+ auto config = MakeCngConfig();
+ config.num_channels = 2;
+ CreateCng(std::move(config));
+ }(),
+ "Invalid configuration");
+}
+
+TEST_F(AudioEncoderCngDeathTest, EncoderFrameSizeTooLarge) {
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillRepeatedly(Return(7U));
+ for (int i = 0; i < 6; ++i)
+ Encode();
+ RTC_EXPECT_DEATH(
+ Encode(), "Frame size cannot be larger than 60 ms when using VAD/CNG.");
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/cng/cng_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/cng/cng_unittest.cc
new file mode 100644
index 0000000000..0e6ab79394
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/cng/cng_unittest.cc
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include <memory>
+#include <string>
+
+#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+
+enum {
+ kSidShortIntervalUpdate = 1,
+ kSidNormalIntervalUpdate = 100,
+ kSidLongIntervalUpdate = 10000
+};
+
+enum : size_t {
+ kCNGNumParamsLow = 0,
+ kCNGNumParamsNormal = 8,
+ kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
+ kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
+};
+
+enum { kNoSid, kForceSid };
+
+class CngTest : public ::testing::Test {
+ protected:
+ virtual void SetUp();
+
+ void TestCngEncode(int sample_rate_hz, int quality);
+
+ int16_t speech_data_[640]; // Max size of CNG internal buffers.
+};
+
+class CngDeathTest : public CngTest {};
+
+void CngTest::SetUp() {
+ FILE* input_file;
+ const std::string file_name =
+ webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+ input_file = fopen(file_name.c_str(), "rb");
+ ASSERT_TRUE(input_file != NULL);
+ ASSERT_EQ(640, static_cast<int32_t>(
+ fread(speech_data_, sizeof(int16_t), 640, input_file)));
+ fclose(input_file);
+ input_file = NULL;
+}
+
+void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
+ const size_t num_samples_10ms = rtc::CheckedDivExact(sample_rate_hz, 100);
+ rtc::Buffer sid_data;
+
+ ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
+ quality);
+ EXPECT_EQ(0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(
+ speech_data_, num_samples_10ms),
+ kNoSid, &sid_data));
+ EXPECT_EQ(static_cast<size_t>(quality + 1),
+ cng_encoder.Encode(
+ rtc::ArrayView<const int16_t>(speech_data_, num_samples_10ms),
+ kForceSid, &sid_data));
+}
+
+#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+// Create CNG encoder, init with faulty values, free CNG encoder.
+TEST_F(CngDeathTest, CngInitFail) {
+ // Call with too few parameters.
+ EXPECT_DEATH(
+ {
+ ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate, kCNGNumParamsLow);
+ },
+ "");
+ // Call with too many parameters.
+ EXPECT_DEATH(
+ {
+ ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
+ kCNGNumParamsTooHigh);
+ },
+ "");
+}
+
+// Encode Cng with too long input vector.
+TEST_F(CngDeathTest, CngEncodeTooLong) {
+ rtc::Buffer sid_data;
+
+ // Create encoder.
+ ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
+ kCNGNumParamsNormal);
+ // Run encoder with too much data.
+ EXPECT_DEATH(
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 641),
+ kNoSid, &sid_data),
+ "");
+}
+#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+TEST_F(CngTest, CngEncode8000) {
+ TestCngEncode(8000, kCNGNumParamsNormal);
+}
+
+TEST_F(CngTest, CngEncode16000) {
+ TestCngEncode(16000, kCNGNumParamsNormal);
+}
+
+TEST_F(CngTest, CngEncode32000) {
+ TestCngEncode(32000, kCNGNumParamsHigh);
+}
+
+TEST_F(CngTest, CngEncode48000) {
+ TestCngEncode(48000, kCNGNumParamsNormal);
+}
+
+TEST_F(CngTest, CngEncode64000) {
+ TestCngEncode(64000, kCNGNumParamsNormal);
+}
+
+// Update SID parameters, for both 9 and 16 parameters.
+TEST_F(CngTest, CngUpdateSid) {
+ rtc::Buffer sid_data;
+
+ // Create and initialize encoder and decoder.
+ ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+ kCNGNumParamsNormal);
+ ComfortNoiseDecoder cng_decoder;
+
+ // Run normal Encode and UpdateSid.
+ EXPECT_EQ(kCNGNumParamsNormal + 1,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kForceSid, &sid_data));
+ cng_decoder.UpdateSid(sid_data);
+
+ // Reinit with new length.
+ cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
+ cng_decoder.Reset();
+
+ // Expect 0 because of unstable parameters after switching length.
+ EXPECT_EQ(0U,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kForceSid, &sid_data));
+ EXPECT_EQ(
+ kCNGNumParamsHigh + 1,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_ + 160, 160),
+ kForceSid, &sid_data));
+ cng_decoder.UpdateSid(
+ rtc::ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
+}
+
+// Update SID parameters, with wrong parameters or without calling decode.
+TEST_F(CngTest, CngUpdateSidErroneous) {
+ rtc::Buffer sid_data;
+
+ // Encode.
+ ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+ kCNGNumParamsNormal);
+ ComfortNoiseDecoder cng_decoder;
+ EXPECT_EQ(kCNGNumParamsNormal + 1,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kForceSid, &sid_data));
+
+ // First run with valid parameters, then with too many CNG parameters.
+ // The function will operate correctly by only reading the maximum number of
+ // parameters, skipping the extra.
+ EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
+ cng_decoder.UpdateSid(sid_data);
+
+ // Make sure the input buffer is large enough. Since Encode() appends data, we
+ // need to set the size manually only afterwards, or the buffer will be bigger
+ // than anticipated.
+ sid_data.SetSize(kCNGNumParamsTooHigh + 1);
+ cng_decoder.UpdateSid(sid_data);
+}
+
+// Test to generate cng data, by forcing SID. Both normal and faulty condition.
+TEST_F(CngTest, CngGenerate) {
+ rtc::Buffer sid_data;
+ int16_t out_data[640];
+
+ // Create and initialize encoder and decoder.
+ ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+ kCNGNumParamsNormal);
+ ComfortNoiseDecoder cng_decoder;
+
+ // Normal Encode.
+ EXPECT_EQ(kCNGNumParamsNormal + 1,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kForceSid, &sid_data));
+
+ // Normal UpdateSid.
+ cng_decoder.UpdateSid(sid_data);
+
+ // Two normal Generate, one with new_period.
+ EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 1));
+ EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 0));
+
+ // Call Genereate with too much data.
+ EXPECT_FALSE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 641), 0));
+}
+
+// Test automatic SID.
+TEST_F(CngTest, CngAutoSid) {
+ rtc::Buffer sid_data;
+
+ // Create and initialize encoder and decoder.
+ ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
+ kCNGNumParamsNormal);
+ ComfortNoiseDecoder cng_decoder;
+
+ // Normal Encode, 100 msec, where no SID data should be generated.
+ for (int i = 0; i < 10; i++) {
+ EXPECT_EQ(
+ 0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kNoSid, &sid_data));
+ }
+
+ // We have reached 100 msec, and SID data should be generated.
+ EXPECT_EQ(kCNGNumParamsNormal + 1,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kNoSid, &sid_data));
+}
+
+// Test automatic SID, with very short interval.
+TEST_F(CngTest, CngAutoSidShort) {
+ rtc::Buffer sid_data;
+
+ // Create and initialize encoder and decoder.
+ ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
+ kCNGNumParamsNormal);
+ ComfortNoiseDecoder cng_decoder;
+
+ // First call will never generate SID, unless forced to.
+ EXPECT_EQ(0U,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kNoSid, &sid_data));
+
+ // Normal Encode, 100 msec, SID data should be generated all the time.
+ for (int i = 0; i < 10; i++) {
+ EXPECT_EQ(
+ kCNGNumParamsNormal + 1,
+ cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
+ kNoSid, &sid_data));
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc b/third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc
new file mode 100644
index 0000000000..48f1b8c296
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.cc
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
+
+#include <algorithm>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+namespace {
+
+const size_t kCngMaxOutsizeOrder = 640;
+
+// TODO(ossu): Rename the left-over WebRtcCng according to style guide.
+void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a);
+
+const int32_t WebRtcCng_kDbov[94] = {
+ 1081109975, 858756178, 682134279, 541838517, 430397633, 341876992,
+ 271562548, 215709799, 171344384, 136103682, 108110997, 85875618,
+ 68213428, 54183852, 43039763, 34187699, 27156255, 21570980,
+ 17134438, 13610368, 10811100, 8587562, 6821343, 5418385,
+ 4303976, 3418770, 2715625, 2157098, 1713444, 1361037,
+ 1081110, 858756, 682134, 541839, 430398, 341877,
+ 271563, 215710, 171344, 136104, 108111, 85876,
+ 68213, 54184, 43040, 34188, 27156, 21571,
+ 17134, 13610, 10811, 8588, 6821, 5418,
+ 4304, 3419, 2716, 2157, 1713, 1361,
+ 1081, 859, 682, 542, 430, 342,
+ 272, 216, 171, 136, 108, 86,
+ 68, 54, 43, 34, 27, 22,
+ 17, 14, 11, 9, 7, 5,
+ 4, 3, 3, 2, 2, 1,
+ 1, 1, 1, 1};
+
+const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = {
+ 32702, 32636, 32570, 32505, 32439, 32374,
+ 32309, 32244, 32179, 32114, 32049, 31985};
+
+} // namespace
+
+ComfortNoiseDecoder::ComfortNoiseDecoder() {
+ /* Needed to get the right function pointers in SPLIB. */
+ Reset();
+}
+
+void ComfortNoiseDecoder::Reset() {
+ dec_seed_ = 7777; /* For debugging only. */
+ dec_target_energy_ = 0;
+ dec_used_energy_ = 0;
+ for (auto& c : dec_target_reflCoefs_)
+ c = 0;
+ for (auto& c : dec_used_reflCoefs_)
+ c = 0;
+ for (auto& c : dec_filtstate_)
+ c = 0;
+ for (auto& c : dec_filtstateLow_)
+ c = 0;
+ dec_order_ = 5;
+ dec_target_scale_factor_ = 0;
+ dec_used_scale_factor_ = 0;
+}
+
+void ComfortNoiseDecoder::UpdateSid(rtc::ArrayView<const uint8_t> sid) {
+ int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER];
+ int32_t targetEnergy;
+ size_t length = sid.size();
+ /* Throw away reflection coefficients of higher order than we can handle. */
+ if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1))
+ length = WEBRTC_CNG_MAX_LPC_ORDER + 1;
+
+ dec_order_ = static_cast<uint16_t>(length - 1);
+
+ uint8_t sid0 = std::min<uint8_t>(sid[0], 93);
+ targetEnergy = WebRtcCng_kDbov[sid0];
+ /* Take down target energy to 75%. */
+ targetEnergy = targetEnergy >> 1;
+ targetEnergy += targetEnergy >> 2;
+
+ dec_target_energy_ = targetEnergy;
+
+ /* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */
+ if (dec_order_ == WEBRTC_CNG_MAX_LPC_ORDER) {
+ for (size_t i = 0; i < (dec_order_); i++) {
+ refCs[i] = sid[i + 1] << 8; /* Q7 to Q15*/
+ dec_target_reflCoefs_[i] = refCs[i];
+ }
+ } else {
+ for (size_t i = 0; i < (dec_order_); i++) {
+ refCs[i] = (sid[i + 1] - 127) * (1 << 8); /* Q7 to Q15. */
+ dec_target_reflCoefs_[i] = refCs[i];
+ }
+ }
+
+ for (size_t i = (dec_order_); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
+ refCs[i] = 0;
+ dec_target_reflCoefs_[i] = refCs[i];
+ }
+}
+
+bool ComfortNoiseDecoder::Generate(rtc::ArrayView<int16_t> out_data,
+ bool new_period) {
+ int16_t excitation[kCngMaxOutsizeOrder];
+ int16_t low[kCngMaxOutsizeOrder];
+ int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int16_t ReflBetaStd = 26214; /* 0.8 in q15. */
+ int16_t ReflBetaCompStd = 6553; /* 0.2 in q15. */
+ int16_t ReflBetaNewP = 19661; /* 0.6 in q15. */
+ int16_t ReflBetaCompNewP = 13107; /* 0.4 in q15. */
+ int16_t Beta, BetaC; /* These are in Q15. */
+ int32_t targetEnergy;
+ int16_t En;
+ int16_t temp16;
+ const size_t num_samples = out_data.size();
+
+ if (num_samples > kCngMaxOutsizeOrder) {
+ return false;
+ }
+
+ if (new_period) {
+ dec_used_scale_factor_ = dec_target_scale_factor_;
+ Beta = ReflBetaNewP;
+ BetaC = ReflBetaCompNewP;
+ } else {
+ Beta = ReflBetaStd;
+ BetaC = ReflBetaCompStd;
+ }
+
+ /* Calculate new scale factor in Q13 */
+ dec_used_scale_factor_ = rtc::checked_cast<int16_t>(
+ WEBRTC_SPL_MUL_16_16_RSFT(dec_used_scale_factor_, Beta >> 2, 13) +
+ WEBRTC_SPL_MUL_16_16_RSFT(dec_target_scale_factor_, BetaC >> 2, 13));
+
+ dec_used_energy_ = dec_used_energy_ >> 1;
+ dec_used_energy_ += dec_target_energy_ >> 1;
+
+ /* Do the same for the reflection coeffs, albeit in Q15. */
+ for (size_t i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
+ dec_used_reflCoefs_[i] =
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(dec_used_reflCoefs_[i], Beta, 15);
+ dec_used_reflCoefs_[i] +=
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(dec_target_reflCoefs_[i], BetaC, 15);
+ }
+
+ /* Compute the polynomial coefficients. */
+ WebRtcCng_K2a16(dec_used_reflCoefs_, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly);
+
+ targetEnergy = dec_used_energy_;
+
+ /* Calculate scaling factor based on filter energy. */
+ En = 8192; /* 1.0 in Q13. */
+ for (size_t i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) {
+ /* Floating point value for reference.
+ E *= 1.0 - (dec_used_reflCoefs_[i] / 32768.0) *
+ (dec_used_reflCoefs_[i] / 32768.0);
+ */
+
+ /* Same in fixed point. */
+ /* K(i).^2 in Q15. */
+ temp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(dec_used_reflCoefs_[i],
+ dec_used_reflCoefs_[i], 15);
+ /* 1 - K(i).^2 in Q15. */
+ temp16 = 0x7fff - temp16;
+ En = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15);
+ }
+
+ /* float scaling= sqrt(E * dec_target_energy_ / (1 << 24)); */
+
+ /* Calculate sqrt(En * target_energy / excitation energy) */
+ targetEnergy = WebRtcSpl_Sqrt(dec_used_energy_);
+
+ En = (int16_t)WebRtcSpl_Sqrt(En) << 6;
+ En = (En * 3) >> 1; /* 1.5 estimates sqrt(2). */
+ dec_used_scale_factor_ = (int16_t)((En * targetEnergy) >> 12);
+
+ /* Generate excitation. */
+ /* Excitation energy per sample is 2.^24 - Q13 N(0,1). */
+ for (size_t i = 0; i < num_samples; i++) {
+ excitation[i] = WebRtcSpl_RandN(&dec_seed_) >> 1;
+ }
+
+ /* Scale to correct energy. */
+ WebRtcSpl_ScaleVector(excitation, excitation, dec_used_scale_factor_,
+ num_samples, 13);
+
+ /* `lpPoly` - Coefficients in Q12.
+ * `excitation` - Speech samples.
+ * `nst->dec_filtstate` - State preservation.
+ * `out_data` - Filtered speech samples. */
+ WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation,
+ num_samples, dec_filtstate_, WEBRTC_CNG_MAX_LPC_ORDER,
+ dec_filtstateLow_, WEBRTC_CNG_MAX_LPC_ORDER,
+ out_data.data(), low, num_samples);
+
+ return true;
+}
+
+ComfortNoiseEncoder::ComfortNoiseEncoder(int fs, int interval, int quality)
+ : enc_nrOfCoefs_(quality),
+ enc_sampfreq_(fs),
+ enc_interval_(interval),
+ enc_msSinceSid_(0),
+ enc_Energy_(0),
+ enc_reflCoefs_{0},
+ enc_corrVector_{0},
+ enc_seed_(7777) /* For debugging only. */ {
+ RTC_CHECK_GT(quality, 0);
+ RTC_CHECK_LE(quality, WEBRTC_CNG_MAX_LPC_ORDER);
+}
+
+void ComfortNoiseEncoder::Reset(int fs, int interval, int quality) {
+ RTC_CHECK_GT(quality, 0);
+ RTC_CHECK_LE(quality, WEBRTC_CNG_MAX_LPC_ORDER);
+ enc_nrOfCoefs_ = quality;
+ enc_sampfreq_ = fs;
+ enc_interval_ = interval;
+ enc_msSinceSid_ = 0;
+ enc_Energy_ = 0;
+ for (auto& c : enc_reflCoefs_)
+ c = 0;
+ for (auto& c : enc_corrVector_)
+ c = 0;
+ enc_seed_ = 7777; /* For debugging only. */
+}
+
+size_t ComfortNoiseEncoder::Encode(rtc::ArrayView<const int16_t> speech,
+ bool force_sid,
+ rtc::Buffer* output) {
+ int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int16_t hanningW[kCngMaxOutsizeOrder];
+ int16_t ReflBeta = 19661; /* 0.6 in q15. */
+ int16_t ReflBetaComp = 13107; /* 0.4 in q15. */
+ int32_t outEnergy;
+ int outShifts;
+ size_t i;
+ int stab;
+ int acorrScale;
+ size_t index;
+ size_t ind, factor;
+ int32_t* bptr;
+ int32_t blo, bhi;
+ int16_t negate;
+ const int16_t* aptr;
+ int16_t speechBuf[kCngMaxOutsizeOrder];
+
+ const size_t num_samples = speech.size();
+ RTC_CHECK_LE(num_samples, kCngMaxOutsizeOrder);
+
+ for (i = 0; i < num_samples; i++) {
+ speechBuf[i] = speech[i];
+ }
+
+ factor = num_samples;
+
+ /* Calculate energy and a coefficients. */
+ outEnergy = WebRtcSpl_Energy(speechBuf, num_samples, &outShifts);
+ while (outShifts > 0) {
+ /* We can only do 5 shifts without destroying accuracy in
+ * division factor. */
+ if (outShifts > 5) {
+ outEnergy <<= (outShifts - 5);
+ outShifts = 5;
+ } else {
+ factor /= 2;
+ outShifts--;
+ }
+ }
+ outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t)factor);
+
+ if (outEnergy > 1) {
+ /* Create Hanning Window. */
+ WebRtcSpl_GetHanningWindow(hanningW, num_samples / 2);
+ for (i = 0; i < (num_samples / 2); i++)
+ hanningW[num_samples - i - 1] = hanningW[i];
+
+ WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, num_samples,
+ 14);
+
+ WebRtcSpl_AutoCorrelation(speechBuf, num_samples, enc_nrOfCoefs_,
+ corrVector, &acorrScale);
+
+ if (*corrVector == 0)
+ *corrVector = WEBRTC_SPL_WORD16_MAX;
+
+ /* Adds the bandwidth expansion. */
+ aptr = WebRtcCng_kCorrWindow;
+ bptr = corrVector;
+
+ /* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */
+ for (ind = 0; ind < enc_nrOfCoefs_; ind++) {
+ /* The below code multiplies the 16 b corrWindow values (Q15) with
+ * the 32 b corrvector (Q0) and shifts the result down 15 steps. */
+ negate = *bptr < 0;
+ if (negate)
+ *bptr = -*bptr;
+
+ blo = (int32_t)*aptr * (*bptr & 0xffff);
+ bhi = ((blo >> 16) & 0xffff) +
+ ((int32_t)(*aptr++) * ((*bptr >> 16) & 0xffff));
+ blo = (blo & 0xffff) | ((bhi & 0xffff) << 16);
+
+ *bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t)blo >> 15);
+ if (negate)
+ *bptr = -*bptr;
+ bptr++;
+ }
+ /* End of bandwidth expansion. */
+
+ stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs, enc_nrOfCoefs_);
+
+ if (!stab) {
+ /* Disregard from this frame */
+ return 0;
+ }
+
+ } else {
+ for (i = 0; i < enc_nrOfCoefs_; i++)
+ refCs[i] = 0;
+ }
+
+ if (force_sid) {
+ /* Read instantaneous values instead of averaged. */
+ for (i = 0; i < enc_nrOfCoefs_; i++)
+ enc_reflCoefs_[i] = refCs[i];
+ enc_Energy_ = outEnergy;
+ } else {
+ /* Average history with new values. */
+ for (i = 0; i < enc_nrOfCoefs_; i++) {
+ enc_reflCoefs_[i] =
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(enc_reflCoefs_[i], ReflBeta, 15);
+ enc_reflCoefs_[i] +=
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(refCs[i], ReflBetaComp, 15);
+ }
+ enc_Energy_ = (outEnergy >> 2) + (enc_Energy_ >> 1) + (enc_Energy_ >> 2);
+ }
+
+ if (enc_Energy_ < 1) {
+ enc_Energy_ = 1;
+ }
+
+ if ((enc_msSinceSid_ > (enc_interval_ - 1)) || force_sid) {
+ /* Search for best dbov value. */
+ index = 0;
+ for (i = 1; i < 93; i++) {
+ /* Always round downwards. */
+ if ((enc_Energy_ - WebRtcCng_kDbov[i]) > 0) {
+ index = i;
+ break;
+ }
+ }
+ if ((i == 93) && (index == 0))
+ index = 94;
+
+ const size_t output_coefs = enc_nrOfCoefs_ + 1;
+ output->AppendData(output_coefs, [&](rtc::ArrayView<uint8_t> output) {
+ output[0] = (uint8_t)index;
+
+ /* Quantize coefficients with tweak for WebRtc implementation of
+ * RFC3389. */
+ if (enc_nrOfCoefs_ == WEBRTC_CNG_MAX_LPC_ORDER) {
+ for (i = 0; i < enc_nrOfCoefs_; i++) {
+ /* Q15 to Q7 with rounding. */
+ output[i + 1] = ((enc_reflCoefs_[i] + 128) >> 8);
+ }
+ } else {
+ for (i = 0; i < enc_nrOfCoefs_; i++) {
+ /* Q15 to Q7 with rounding. */
+ output[i + 1] = (127 + ((enc_reflCoefs_[i] + 128) >> 8));
+ }
+ }
+
+ return output_coefs;
+ });
+
+ enc_msSinceSid_ =
+ static_cast<int16_t>((1000 * num_samples) / enc_sampfreq_);
+ return output_coefs;
+ } else {
+ enc_msSinceSid_ +=
+ static_cast<int16_t>((1000 * num_samples) / enc_sampfreq_);
+ return 0;
+ }
+}
+
+namespace {
+/* Values in `k` are Q15, and `a` Q12. */
+void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a) {
+ int16_t any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
+ int16_t* aptr;
+ int16_t* aptr2;
+ int16_t* anyptr;
+ const int16_t* kptr;
+ int m, i;
+
+ kptr = k;
+ *a = 4096; /* i.e., (Word16_MAX >> 3) + 1 */
+ *any = *a;
+ a[1] = (*k + 4) >> 3;
+ for (m = 1; m < useOrder; m++) {
+ kptr++;
+ aptr = a;
+ aptr++;
+ aptr2 = &a[m];
+ anyptr = any;
+ anyptr++;
+
+ any[m + 1] = (*kptr + 4) >> 3;
+ for (i = 0; i < m; i++) {
+ *anyptr++ =
+ (*aptr++) +
+ (int16_t)((((int32_t)(*aptr2--) * (int32_t)*kptr) + 16384) >> 15);
+ }
+
+ aptr = a;
+ anyptr = any;
+ for (i = 0; i < (m + 2); i++) {
+ *aptr++ = *anyptr++;
+ }
+ }
+}
+
+} // namespace
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.h b/third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.h
new file mode 100644
index 0000000000..7afd243f81
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/cng/webrtc_cng.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
+#define MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
+
+#include <stdint.h>
+
+#include <cstddef>
+
+#include "api/array_view.h"
+#include "rtc_base/buffer.h"
+
+#define WEBRTC_CNG_MAX_LPC_ORDER 12
+
+namespace webrtc {
+
+class ComfortNoiseDecoder {
+ public:
+ ComfortNoiseDecoder();
+ ~ComfortNoiseDecoder() = default;
+
+ ComfortNoiseDecoder(const ComfortNoiseDecoder&) = delete;
+ ComfortNoiseDecoder& operator=(const ComfortNoiseDecoder&) = delete;
+
+ void Reset();
+
+ // Updates the CN state when a new SID packet arrives.
+ // `sid` is a view of the SID packet without the headers.
+ void UpdateSid(rtc::ArrayView<const uint8_t> sid);
+
+ // Generates comfort noise.
+ // `out_data` will be filled with samples - its size determines the number of
+ // samples generated. When `new_period` is true, CNG history will be reset
+ // before any audio is generated. Returns `false` if outData is too large -
+ // currently 640 bytes (equalling 10ms at 64kHz).
+ // TODO(ossu): Specify better limits for the size of out_data. Either let it
+ // be unbounded or limit to 10ms in the current sample rate.
+ bool Generate(rtc::ArrayView<int16_t> out_data, bool new_period);
+
+ private:
+ uint32_t dec_seed_;
+ int32_t dec_target_energy_;
+ int32_t dec_used_energy_;
+ int16_t dec_target_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int16_t dec_used_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int16_t dec_filtstate_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int16_t dec_filtstateLow_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ uint16_t dec_order_;
+ int16_t dec_target_scale_factor_; /* Q29 */
+ int16_t dec_used_scale_factor_; /* Q29 */
+};
+
+class ComfortNoiseEncoder {
+ public:
+ // Creates a comfort noise encoder.
+ // `fs` selects sample rate: 8000 for narrowband or 16000 for wideband.
+ // `interval` sets the interval at which to generate SID data (in ms).
+ // `quality` selects the number of refl. coeffs. Maximum allowed is 12.
+ ComfortNoiseEncoder(int fs, int interval, int quality);
+ ~ComfortNoiseEncoder() = default;
+
+ ComfortNoiseEncoder(const ComfortNoiseEncoder&) = delete;
+ ComfortNoiseEncoder& operator=(const ComfortNoiseEncoder&) = delete;
+
+ // Resets the comfort noise encoder to its initial state.
+ // Parameters are set as during construction.
+ void Reset(int fs, int interval, int quality);
+
+ // Analyzes background noise from `speech` and appends coefficients to
+ // `output`. Returns the number of coefficients generated. If `force_sid` is
+ // true, a SID frame is forced and the internal sid interval counter is reset.
+ // Will fail if the input size is too large (> 640 samples, see
+ // ComfortNoiseDecoder::Generate).
+ size_t Encode(rtc::ArrayView<const int16_t> speech,
+ bool force_sid,
+ rtc::Buffer* output);
+
+ private:
+ size_t enc_nrOfCoefs_;
+ int enc_sampfreq_;
+ int16_t enc_interval_;
+ int16_t enc_msSinceSid_;
+ int32_t enc_Energy_;
+ int16_t enc_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ int32_t enc_corrVector_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
+ uint32_t enc_seed_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc
new file mode 100644
index 0000000000..46ac671b30
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
+
+#include <utility>
+
+#include "modules/audio_coding/codecs/g711/g711_interface.h"
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+
+namespace webrtc {
+
+void AudioDecoderPcmU::Reset() {}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderPcmU::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ return LegacyEncodedAudioFrame::SplitBySamples(
+ this, std::move(payload), timestamp, 8 * num_channels_, 8);
+}
+
+int AudioDecoderPcmU::SampleRateHz() const {
+ return 8000;
+}
+
+size_t AudioDecoderPcmU::Channels() const {
+ return num_channels_;
+}
+
+int AudioDecoderPcmU::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
+ // Adjust the encoded length down to ensure the same number of samples in each
+ // channel.
+ const size_t encoded_len_adjusted =
+ PacketDuration(encoded, encoded_len) *
+ Channels(); // 1 byte per sample per channel
+ int16_t temp_type = 1; // Default is speech.
+ size_t ret =
+ WebRtcG711_DecodeU(encoded, encoded_len_adjusted, decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return static_cast<int>(ret);
+}
+
+int AudioDecoderPcmU::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ // One encoded byte per sample per channel.
+ return static_cast<int>(encoded_len / Channels());
+}
+
+void AudioDecoderPcmA::Reset() {}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderPcmA::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ return LegacyEncodedAudioFrame::SplitBySamples(
+ this, std::move(payload), timestamp, 8 * num_channels_, 8);
+}
+
+int AudioDecoderPcmA::SampleRateHz() const {
+ return 8000;
+}
+
+size_t AudioDecoderPcmA::Channels() const {
+ return num_channels_;
+}
+
+int AudioDecoderPcmA::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
+ // Adjust the encoded length down to ensure the same number of samples in each
+ // channel.
+ const size_t encoded_len_adjusted =
+ PacketDuration(encoded, encoded_len) *
+ Channels(); // 1 byte per sample per channel
+ int16_t temp_type = 1; // Default is speech.
+ size_t ret =
+ WebRtcG711_DecodeA(encoded, encoded_len_adjusted, decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return static_cast<int>(ret);
+}
+
+int AudioDecoderPcmA::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ // One encoded byte per sample per channel.
+ return static_cast<int>(encoded_len / Channels());
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
new file mode 100644
index 0000000000..3fa42cba30
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_
+#define MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+class AudioDecoderPcmU final : public AudioDecoder {
+ public:
+ explicit AudioDecoderPcmU(size_t num_channels) : num_channels_(num_channels) {
+ RTC_DCHECK_GE(num_channels, 1);
+ }
+
+ AudioDecoderPcmU(const AudioDecoderPcmU&) = delete;
+ AudioDecoderPcmU& operator=(const AudioDecoderPcmU&) = delete;
+
+ void Reset() override;
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ const size_t num_channels_;
+};
+
+class AudioDecoderPcmA final : public AudioDecoder {
+ public:
+ explicit AudioDecoderPcmA(size_t num_channels) : num_channels_(num_channels) {
+ RTC_DCHECK_GE(num_channels, 1);
+ }
+
+ AudioDecoderPcmA(const AudioDecoderPcmA&) = delete;
+ AudioDecoderPcmA& operator=(const AudioDecoderPcmA&) = delete;
+
+ void Reset() override;
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ const size_t num_channels_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
new file mode 100644
index 0000000000..65e2da479d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
+
+#include <cstdint>
+
+#include "modules/audio_coding/codecs/g711/g711_interface.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+bool AudioEncoderPcm::Config::IsOk() const {
+ return (frame_size_ms % 10 == 0) && (num_channels >= 1);
+}
+
+AudioEncoderPcm::AudioEncoderPcm(const Config& config, int sample_rate_hz)
+ : sample_rate_hz_(sample_rate_hz),
+ num_channels_(config.num_channels),
+ payload_type_(config.payload_type),
+ num_10ms_frames_per_packet_(
+ static_cast<size_t>(config.frame_size_ms / 10)),
+ full_frame_samples_(config.num_channels * config.frame_size_ms *
+ sample_rate_hz / 1000),
+ first_timestamp_in_buffer_(0) {
+ RTC_CHECK_GT(sample_rate_hz, 0) << "Sample rate must be larger than 0 Hz";
+ RTC_CHECK_EQ(config.frame_size_ms % 10, 0)
+ << "Frame size must be an integer multiple of 10 ms.";
+ speech_buffer_.reserve(full_frame_samples_);
+}
+
+AudioEncoderPcm::~AudioEncoderPcm() = default;
+
+int AudioEncoderPcm::SampleRateHz() const {
+ return sample_rate_hz_;
+}
+
+size_t AudioEncoderPcm::NumChannels() const {
+ return num_channels_;
+}
+
+size_t AudioEncoderPcm::Num10MsFramesInNextPacket() const {
+ return num_10ms_frames_per_packet_;
+}
+
+size_t AudioEncoderPcm::Max10MsFramesInAPacket() const {
+ return num_10ms_frames_per_packet_;
+}
+
+int AudioEncoderPcm::GetTargetBitrate() const {
+ return static_cast<int>(8 * BytesPerSample() * SampleRateHz() *
+ NumChannels());
+}
+
+AudioEncoder::EncodedInfo AudioEncoderPcm::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ if (speech_buffer_.empty()) {
+ first_timestamp_in_buffer_ = rtp_timestamp;
+ }
+ speech_buffer_.insert(speech_buffer_.end(), audio.begin(), audio.end());
+ if (speech_buffer_.size() < full_frame_samples_) {
+ return EncodedInfo();
+ }
+ RTC_CHECK_EQ(speech_buffer_.size(), full_frame_samples_);
+ EncodedInfo info;
+ info.encoded_timestamp = first_timestamp_in_buffer_;
+ info.payload_type = payload_type_;
+ info.encoded_bytes = encoded->AppendData(
+ full_frame_samples_ * BytesPerSample(),
+ [&](rtc::ArrayView<uint8_t> encoded) {
+ return EncodeCall(&speech_buffer_[0], full_frame_samples_,
+ encoded.data());
+ });
+ speech_buffer_.clear();
+ info.encoder_type = GetCodecType();
+ return info;
+}
+
+void AudioEncoderPcm::Reset() {
+ speech_buffer_.clear();
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderPcm::GetFrameLengthRange() const {
+ return {{TimeDelta::Millis(num_10ms_frames_per_packet_ * 10),
+ TimeDelta::Millis(num_10ms_frames_per_packet_ * 10)}};
+}
+
+size_t AudioEncoderPcmA::EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) {
+ return WebRtcG711_EncodeA(audio, input_len, encoded);
+}
+
+size_t AudioEncoderPcmA::BytesPerSample() const {
+ return 1;
+}
+
+AudioEncoder::CodecType AudioEncoderPcmA::GetCodecType() const {
+ return AudioEncoder::CodecType::kPcmA;
+}
+
+size_t AudioEncoderPcmU::EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) {
+ return WebRtcG711_EncodeU(audio, input_len, encoded);
+}
+
+size_t AudioEncoderPcmU::BytesPerSample() const {
+ return 1;
+}
+
+AudioEncoder::CodecType AudioEncoderPcmU::GetCodecType() const {
+ return AudioEncoder::CodecType::kPcmU;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
new file mode 100644
index 0000000000..d50be4b457
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_G711_AUDIO_ENCODER_PCM_H_
+#define MODULES_AUDIO_CODING_CODECS_G711_AUDIO_ENCODER_PCM_H_
+
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/units/time_delta.h"
+
+namespace webrtc {
+
+class AudioEncoderPcm : public AudioEncoder {
+ public:
+ struct Config {
+ public:
+ bool IsOk() const;
+
+ int frame_size_ms;
+ size_t num_channels;
+ int payload_type;
+
+ protected:
+ explicit Config(int pt)
+ : frame_size_ms(20), num_channels(1), payload_type(pt) {}
+ };
+
+ ~AudioEncoderPcm() override;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+ void Reset() override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+
+ protected:
+ AudioEncoderPcm(const Config& config, int sample_rate_hz);
+
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+
+ virtual size_t EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) = 0;
+
+ virtual size_t BytesPerSample() const = 0;
+
+ // Used to set EncodedInfoLeaf::encoder_type in
+ // AudioEncoderPcm::EncodeImpl
+ virtual AudioEncoder::CodecType GetCodecType() const = 0;
+
+ private:
+ const int sample_rate_hz_;
+ const size_t num_channels_;
+ const int payload_type_;
+ const size_t num_10ms_frames_per_packet_;
+ const size_t full_frame_samples_;
+ std::vector<int16_t> speech_buffer_;
+ uint32_t first_timestamp_in_buffer_;
+};
+
+class AudioEncoderPcmA final : public AudioEncoderPcm {
+ public:
+ struct Config : public AudioEncoderPcm::Config {
+ Config() : AudioEncoderPcm::Config(8) {}
+ };
+
+ explicit AudioEncoderPcmA(const Config& config)
+ : AudioEncoderPcm(config, kSampleRateHz) {}
+
+ AudioEncoderPcmA(const AudioEncoderPcmA&) = delete;
+ AudioEncoderPcmA& operator=(const AudioEncoderPcmA&) = delete;
+
+ protected:
+ size_t EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) override;
+
+ size_t BytesPerSample() const override;
+
+ AudioEncoder::CodecType GetCodecType() const override;
+
+ private:
+ static const int kSampleRateHz = 8000;
+};
+
+class AudioEncoderPcmU final : public AudioEncoderPcm {
+ public:
+ struct Config : public AudioEncoderPcm::Config {
+ Config() : AudioEncoderPcm::Config(0) {}
+ };
+
+ explicit AudioEncoderPcmU(const Config& config)
+ : AudioEncoderPcm(config, kSampleRateHz) {}
+
+ AudioEncoderPcmU(const AudioEncoderPcmU&) = delete;
+ AudioEncoderPcmU& operator=(const AudioEncoderPcmU&) = delete;
+
+ protected:
+ size_t EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) override;
+
+ size_t BytesPerSample() const override;
+
+ AudioEncoder::CodecType GetCodecType() const override;
+
+ private:
+ static const int kSampleRateHz = 8000;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_G711_AUDIO_ENCODER_PCM_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.c b/third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.c
new file mode 100644
index 0000000000..5fe1692ccb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string.h>
+
+#include "modules/third_party/g711/g711.h"
+#include "modules/audio_coding/codecs/g711/g711_interface.h"
+
+size_t WebRtcG711_EncodeA(const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded) {
+ size_t n;
+ for (n = 0; n < len; n++)
+ encoded[n] = linear_to_alaw(speechIn[n]);
+ return len;
+}
+
+size_t WebRtcG711_EncodeU(const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded) {
+ size_t n;
+ for (n = 0; n < len; n++)
+ encoded[n] = linear_to_ulaw(speechIn[n]);
+ return len;
+}
+
+size_t WebRtcG711_DecodeA(const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType) {
+ size_t n;
+ for (n = 0; n < len; n++)
+ decoded[n] = alaw_to_linear(encoded[n]);
+ *speechType = 1;
+ return len;
+}
+
+size_t WebRtcG711_DecodeU(const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType) {
+ size_t n;
+ for (n = 0; n < len; n++)
+ decoded[n] = ulaw_to_linear(encoded[n]);
+ *speechType = 1;
+ return len;
+}
+
+int16_t WebRtcG711_Version(char* version, int16_t lenBytes) {
+ strncpy(version, "2.0.0", lenBytes);
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.h b/third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.h
new file mode 100644
index 0000000000..83f9d378ed
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/g711_interface.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
+#define MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
+
+#include <stdint.h>
+
+// Comfort noise constants
+#define G711_WEBRTC_SPEECH 1
+#define G711_WEBRTC_CNG 2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * WebRtcG711_EncodeA(...)
+ *
+ * This function encodes a G711 A-law frame and inserts it into a packet.
+ * Input speech length has be of any length.
+ *
+ * Input:
+ * - speechIn : Input speech vector
+ * - len : Samples in speechIn
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : Length (in bytes) of coded data.
+ * Always equal to len input parameter.
+ */
+
+size_t WebRtcG711_EncodeA(const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcG711_EncodeU(...)
+ *
+ * This function encodes a G711 U-law frame and inserts it into a packet.
+ * Input speech length has be of any length.
+ *
+ * Input:
+ * - speechIn : Input speech vector
+ * - len : Samples in speechIn
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : Length (in bytes) of coded data.
+ * Always equal to len input parameter.
+ */
+
+size_t WebRtcG711_EncodeU(const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcG711_DecodeA(...)
+ *
+ * This function decodes a packet G711 A-law frame.
+ *
+ * Input:
+ * - encoded : Encoded data
+ * - len : Bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ * - speechType : 1 normal, 2 CNG (for G711 it should
+ * always return 1 since G711 does not have a
+ * built-in DTX/CNG scheme)
+ *
+ * Return value : >0 - Samples in decoded vector
+ * -1 - Error
+ */
+
+size_t WebRtcG711_DecodeA(const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/****************************************************************************
+ * WebRtcG711_DecodeU(...)
+ *
+ * This function decodes a packet G711 U-law frame.
+ *
+ * Input:
+ * - encoded : Encoded data
+ * - len : Bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ * - speechType : 1 normal, 2 CNG (for G711 it should
+ * always return 1 since G711 does not have a
+ * built-in DTX/CNG scheme)
+ *
+ * Return value : >0 - Samples in decoded vector
+ * -1 - Error
+ */
+
+size_t WebRtcG711_DecodeU(const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/**********************************************************************
+ * WebRtcG711_Version(...)
+ *
+ * This function gives the version string of the G.711 codec.
+ *
+ * Input:
+ * - lenBytes: the size of Allocated space (in Bytes) where
+ * the version number is written to (in string format).
+ *
+ * Output:
+ * - version: Pointer to a buffer where the version number is
+ * written to.
+ *
+ */
+
+int16_t WebRtcG711_Version(char* version, int16_t lenBytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g711/test/testG711.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g711/test/testG711.cc
new file mode 100644
index 0000000000..f3a42f5d79
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g711/test/testG711.cc
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * testG711.cpp : Defines the entry point for the console application.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* include API */
+#include "modules/audio_coding/codecs/g711/g711_interface.h"
+
+/* Runtime statistics */
+#include <time.h>
+#define CLOCKS_PER_SEC_G711 1000
+
+/* function for reading audio data from PCM file */
+bool readframe(int16_t* data, FILE* inp, size_t length) {
+ size_t rlen = fread(data, sizeof(int16_t), length, inp);
+ if (rlen >= length)
+ return false;
+ memset(data + rlen, 0, (length - rlen) * sizeof(int16_t));
+ return true;
+}
+
+int main(int argc, char* argv[]) {
+ char inname[80], outname[40], bitname[40];
+ FILE* inp;
+ FILE* outp;
+ FILE* bitp = NULL;
+ int framecnt;
+ bool endfile;
+
+ size_t framelength = 80;
+
+ /* Runtime statistics */
+ double starttime;
+ double runtime;
+ double length_file;
+
+ size_t stream_len = 0;
+ int16_t shortdata[480];
+ int16_t decoded[480];
+ uint8_t streamdata[1000];
+ int16_t speechType[1];
+ char law[2];
+ char versionNumber[40];
+
+ /* handling wrong input arguments in the command line */
+ if ((argc != 5) && (argc != 6)) {
+ printf("\n\nWrong number of arguments or flag values.\n\n");
+
+ printf("\n");
+ printf("\nG.711 test application\n\n");
+ printf("Usage:\n\n");
+ printf("./testG711.exe framelength law infile outfile \n\n");
+ printf("framelength: Framelength in samples.\n");
+ printf("law : Coding law, A och u.\n");
+ printf("infile : Normal speech input file\n");
+ printf("outfile : Speech output file\n\n");
+ printf("outbits : Output bitstream file [optional]\n\n");
+ exit(0);
+ }
+
+ /* Get version and print */
+ WebRtcG711_Version(versionNumber, 40);
+
+ printf("-----------------------------------\n");
+ printf("G.711 version: %s\n\n", versionNumber);
+ /* Get frame length */
+ int framelength_int = atoi(argv[1]);
+ if (framelength_int < 0) {
+ printf(" G.722: Invalid framelength %d.\n", framelength_int);
+ exit(1);
+ }
+ framelength = static_cast<size_t>(framelength_int);
+
+ /* Get compression law */
+ strcpy(law, argv[2]);
+
+ /* Get Input and Output files */
+ sscanf(argv[3], "%s", inname);
+ sscanf(argv[4], "%s", outname);
+ if (argc == 6) {
+ sscanf(argv[5], "%s", bitname);
+ if ((bitp = fopen(bitname, "wb")) == NULL) {
+ printf(" G.711: Cannot read file %s.\n", bitname);
+ exit(1);
+ }
+ }
+
+ if ((inp = fopen(inname, "rb")) == NULL) {
+ printf(" G.711: Cannot read file %s.\n", inname);
+ exit(1);
+ }
+ if ((outp = fopen(outname, "wb")) == NULL) {
+ printf(" G.711: Cannot write file %s.\n", outname);
+ exit(1);
+ }
+ printf("\nInput: %s\nOutput: %s\n", inname, outname);
+ if (argc == 6) {
+ printf("\nBitfile: %s\n", bitname);
+ }
+
+ starttime = clock() / (double)CLOCKS_PER_SEC_G711; /* Runtime statistics */
+
+ /* Initialize encoder and decoder */
+ framecnt = 0;
+ endfile = false;
+ while (!endfile) {
+ framecnt++;
+ /* Read speech block */
+ endfile = readframe(shortdata, inp, framelength);
+
+ /* G.711 encoding */
+ if (!strcmp(law, "A")) {
+ /* A-law encoding */
+ stream_len = WebRtcG711_EncodeA(shortdata, framelength, streamdata);
+ if (argc == 6) {
+ /* Write bits to file */
+ if (fwrite(streamdata, sizeof(unsigned char), stream_len, bitp) !=
+ stream_len) {
+ return -1;
+ }
+ }
+ WebRtcG711_DecodeA(streamdata, stream_len, decoded, speechType);
+ } else if (!strcmp(law, "u")) {
+ /* u-law encoding */
+ stream_len = WebRtcG711_EncodeU(shortdata, framelength, streamdata);
+ if (argc == 6) {
+ /* Write bits to file */
+ if (fwrite(streamdata, sizeof(unsigned char), stream_len, bitp) !=
+ stream_len) {
+ return -1;
+ }
+ }
+ WebRtcG711_DecodeU(streamdata, stream_len, decoded, speechType);
+ } else {
+ printf("Wrong law mode\n");
+ exit(1);
+ }
+ /* Write coded speech to file */
+ if (fwrite(decoded, sizeof(short), framelength, outp) != framelength) {
+ return -1;
+ }
+ }
+
+ runtime = (double)(clock() / (double)CLOCKS_PER_SEC_G711 - starttime);
+ length_file = ((double)framecnt * (double)framelength / 8000);
+ printf("\n\nLength of speech file: %.1f s\n", length_file);
+ printf("Time to run G.711: %.2f s (%.2f %% of realtime)\n\n", runtime,
+ (100 * runtime / length_file));
+ printf("---------------------END----------------------\n");
+
+ fclose(inp);
+ fclose(outp);
+
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc
new file mode 100644
index 0000000000..1ecc9bc3d1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/g722/audio_decoder_g722.h"
+
+#include <string.h>
+
+#include <utility>
+
+#include "modules/audio_coding/codecs/g722/g722_interface.h"
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+AudioDecoderG722Impl::AudioDecoderG722Impl() {
+ WebRtcG722_CreateDecoder(&dec_state_);
+ WebRtcG722_DecoderInit(dec_state_);
+}
+
+AudioDecoderG722Impl::~AudioDecoderG722Impl() {
+ WebRtcG722_FreeDecoder(dec_state_);
+}
+
+bool AudioDecoderG722Impl::HasDecodePlc() const {
+ return false;
+}
+
+int AudioDecoderG722Impl::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
+ int16_t temp_type = 1; // Default is speech.
+ size_t ret =
+ WebRtcG722_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return static_cast<int>(ret);
+}
+
+void AudioDecoderG722Impl::Reset() {
+ WebRtcG722_DecoderInit(dec_state_);
+}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderG722Impl::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ return LegacyEncodedAudioFrame::SplitBySamples(this, std::move(payload),
+ timestamp, 8, 16);
+}
+
+int AudioDecoderG722Impl::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ // 1/2 encoded byte per sample per channel.
+ return static_cast<int>(2 * encoded_len / Channels());
+}
+
+int AudioDecoderG722Impl::SampleRateHz() const {
+ return 16000;
+}
+
+size_t AudioDecoderG722Impl::Channels() const {
+ return 1;
+}
+
+AudioDecoderG722StereoImpl::AudioDecoderG722StereoImpl() {
+ WebRtcG722_CreateDecoder(&dec_state_left_);
+ WebRtcG722_CreateDecoder(&dec_state_right_);
+ WebRtcG722_DecoderInit(dec_state_left_);
+ WebRtcG722_DecoderInit(dec_state_right_);
+}
+
+AudioDecoderG722StereoImpl::~AudioDecoderG722StereoImpl() {
+ WebRtcG722_FreeDecoder(dec_state_left_);
+ WebRtcG722_FreeDecoder(dec_state_right_);
+}
+
+int AudioDecoderG722StereoImpl::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
+ // Adjust the encoded length down to ensure the same number of samples in each
+ // channel.
+ const size_t encoded_len_adjusted = PacketDuration(encoded, encoded_len) *
+ Channels() /
+ 2; // 1/2 byte per sample per channel
+ int16_t temp_type = 1; // Default is speech.
+ // De-interleave the bit-stream into two separate payloads.
+ uint8_t* encoded_deinterleaved = new uint8_t[encoded_len_adjusted];
+ SplitStereoPacket(encoded, encoded_len_adjusted, encoded_deinterleaved);
+ // Decode left and right.
+ size_t decoded_len =
+ WebRtcG722_Decode(dec_state_left_, encoded_deinterleaved,
+ encoded_len_adjusted / 2, decoded, &temp_type);
+ size_t ret = WebRtcG722_Decode(
+ dec_state_right_, &encoded_deinterleaved[encoded_len_adjusted / 2],
+ encoded_len_adjusted / 2, &decoded[decoded_len], &temp_type);
+ if (ret == decoded_len) {
+ ret += decoded_len; // Return total number of samples.
+ // Interleave output.
+ for (size_t k = ret / 2; k < ret; k++) {
+ int16_t temp = decoded[k];
+ memmove(&decoded[2 * k - ret + 2], &decoded[2 * k - ret + 1],
+ (ret - k - 1) * sizeof(int16_t));
+ decoded[2 * k - ret + 1] = temp;
+ }
+ }
+ *speech_type = ConvertSpeechType(temp_type);
+ delete[] encoded_deinterleaved;
+ return static_cast<int>(ret);
+}
+
+int AudioDecoderG722StereoImpl::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ // 1/2 encoded byte per sample per channel. Make sure the length represents
+ // an equal number of bytes per channel. Otherwise, we cannot de-interleave
+ // the encoded data later.
+ return static_cast<int>(2 * (encoded_len / Channels()));
+}
+
+int AudioDecoderG722StereoImpl::SampleRateHz() const {
+ return 16000;
+}
+
+size_t AudioDecoderG722StereoImpl::Channels() const {
+ return 2;
+}
+
+void AudioDecoderG722StereoImpl::Reset() {
+ WebRtcG722_DecoderInit(dec_state_left_);
+ WebRtcG722_DecoderInit(dec_state_right_);
+}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderG722StereoImpl::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ return LegacyEncodedAudioFrame::SplitBySamples(this, std::move(payload),
+ timestamp, 2 * 8, 16);
+}
+
+// Split the stereo packet and place left and right channel after each other
+// in the output array.
+void AudioDecoderG722StereoImpl::SplitStereoPacket(
+ const uint8_t* encoded,
+ size_t encoded_len,
+ uint8_t* encoded_deinterleaved) {
+ // Regroup the 4 bits/sample so |l1 l2| |r1 r2| |l3 l4| |r3 r4| ...,
+ // where "lx" is 4 bits representing left sample number x, and "rx" right
+ // sample. Two samples fit in one byte, represented with |...|.
+ for (size_t i = 0; i + 1 < encoded_len; i += 2) {
+ uint8_t right_byte = ((encoded[i] & 0x0F) << 4) + (encoded[i + 1] & 0x0F);
+ encoded_deinterleaved[i] = (encoded[i] & 0xF0) + (encoded[i + 1] >> 4);
+ encoded_deinterleaved[i + 1] = right_byte;
+ }
+
+ // Move one byte representing right channel each loop, and place it at the
+ // end of the bytestream vector. After looping the data is reordered to:
+ // |l1 l2| |l3 l4| ... |l(N-1) lN| |r1 r2| |r3 r4| ... |r(N-1) r(N)|,
+ // where N is the total number of samples.
+ for (size_t i = 0; i < encoded_len / 2; i++) {
+ uint8_t right_byte = encoded_deinterleaved[i + 1];
+ memmove(&encoded_deinterleaved[i + 1], &encoded_deinterleaved[i + 2],
+ encoded_len - i - 2);
+ encoded_deinterleaved[encoded_len - 1] = right_byte;
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h
new file mode 100644
index 0000000000..5872fad5de
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
+#define MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
+
+#include "api/audio_codecs/audio_decoder.h"
+
+typedef struct WebRtcG722DecInst G722DecInst;
+
+namespace webrtc {
+
+class AudioDecoderG722Impl final : public AudioDecoder {
+ public:
+ AudioDecoderG722Impl();
+ ~AudioDecoderG722Impl() override;
+
+ AudioDecoderG722Impl(const AudioDecoderG722Impl&) = delete;
+ AudioDecoderG722Impl& operator=(const AudioDecoderG722Impl&) = delete;
+
+ bool HasDecodePlc() const override;
+ void Reset() override;
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ G722DecInst* dec_state_;
+};
+
+class AudioDecoderG722StereoImpl final : public AudioDecoder {
+ public:
+ AudioDecoderG722StereoImpl();
+ ~AudioDecoderG722StereoImpl() override;
+
+ AudioDecoderG722StereoImpl(const AudioDecoderG722StereoImpl&) = delete;
+ AudioDecoderG722StereoImpl& operator=(const AudioDecoderG722StereoImpl&) =
+ delete;
+
+ void Reset() override;
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ int SampleRateHz() const override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ // Splits the stereo-interleaved payload in `encoded` into separate payloads
+ // for left and right channels. The separated payloads are written to
+ // `encoded_deinterleaved`, which must hold at least `encoded_len` samples.
+ // The left channel starts at offset 0, while the right channel starts at
+ // offset encoded_len / 2 into `encoded_deinterleaved`.
+ void SplitStereoPacket(const uint8_t* encoded,
+ size_t encoded_len,
+ uint8_t* encoded_deinterleaved);
+
+ G722DecInst* dec_state_left_;
+ G722DecInst* dec_state_right_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
new file mode 100644
index 0000000000..b7d34ba581
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
+
+#include <cstdint>
+
+#include "modules/audio_coding/codecs/g722/g722_interface.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+namespace {
+
+const size_t kSampleRateHz = 16000;
+
+} // namespace
+
+AudioEncoderG722Impl::AudioEncoderG722Impl(const AudioEncoderG722Config& config,
+ int payload_type)
+ : num_channels_(config.num_channels),
+ payload_type_(payload_type),
+ num_10ms_frames_per_packet_(
+ static_cast<size_t>(config.frame_size_ms / 10)),
+ num_10ms_frames_buffered_(0),
+ first_timestamp_in_buffer_(0),
+ encoders_(new EncoderState[num_channels_]),
+ interleave_buffer_(2 * num_channels_) {
+ RTC_CHECK(config.IsOk());
+ const size_t samples_per_channel =
+ kSampleRateHz / 100 * num_10ms_frames_per_packet_;
+ for (size_t i = 0; i < num_channels_; ++i) {
+ encoders_[i].speech_buffer.reset(new int16_t[samples_per_channel]);
+ encoders_[i].encoded_buffer.SetSize(samples_per_channel / 2);
+ }
+ Reset();
+}
+
+AudioEncoderG722Impl::~AudioEncoderG722Impl() = default;
+
+int AudioEncoderG722Impl::SampleRateHz() const {
+ return kSampleRateHz;
+}
+
+size_t AudioEncoderG722Impl::NumChannels() const {
+ return num_channels_;
+}
+
+int AudioEncoderG722Impl::RtpTimestampRateHz() const {
+ // The RTP timestamp rate for G.722 is 8000 Hz, even though it is a 16 kHz
+ // codec.
+ return kSampleRateHz / 2;
+}
+
+size_t AudioEncoderG722Impl::Num10MsFramesInNextPacket() const {
+ return num_10ms_frames_per_packet_;
+}
+
+size_t AudioEncoderG722Impl::Max10MsFramesInAPacket() const {
+ return num_10ms_frames_per_packet_;
+}
+
+int AudioEncoderG722Impl::GetTargetBitrate() const {
+ // 4 bits/sample, 16000 samples/s/channel.
+ return static_cast<int>(64000 * NumChannels());
+}
+
+void AudioEncoderG722Impl::Reset() {
+ num_10ms_frames_buffered_ = 0;
+ for (size_t i = 0; i < num_channels_; ++i)
+ RTC_CHECK_EQ(0, WebRtcG722_EncoderInit(encoders_[i].encoder));
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderG722Impl::GetFrameLengthRange() const {
+ return {{TimeDelta::Millis(num_10ms_frames_per_packet_ * 10),
+ TimeDelta::Millis(num_10ms_frames_per_packet_ * 10)}};
+}
+
+AudioEncoder::EncodedInfo AudioEncoderG722Impl::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ if (num_10ms_frames_buffered_ == 0)
+ first_timestamp_in_buffer_ = rtp_timestamp;
+
+ // Deinterleave samples and save them in each channel's buffer.
+ const size_t start = kSampleRateHz / 100 * num_10ms_frames_buffered_;
+ for (size_t i = 0; i < kSampleRateHz / 100; ++i)
+ for (size_t j = 0; j < num_channels_; ++j)
+ encoders_[j].speech_buffer[start + i] = audio[i * num_channels_ + j];
+
+ // If we don't yet have enough samples for a packet, we're done for now.
+ if (++num_10ms_frames_buffered_ < num_10ms_frames_per_packet_) {
+ return EncodedInfo();
+ }
+
+ // Encode each channel separately.
+ RTC_CHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_);
+ num_10ms_frames_buffered_ = 0;
+ const size_t samples_per_channel = SamplesPerChannel();
+ for (size_t i = 0; i < num_channels_; ++i) {
+ const size_t bytes_encoded = WebRtcG722_Encode(
+ encoders_[i].encoder, encoders_[i].speech_buffer.get(),
+ samples_per_channel, encoders_[i].encoded_buffer.data());
+ RTC_CHECK_EQ(bytes_encoded, samples_per_channel / 2);
+ }
+
+ const size_t bytes_to_encode = samples_per_channel / 2 * num_channels_;
+ EncodedInfo info;
+ info.encoded_bytes = encoded->AppendData(
+ bytes_to_encode, [&](rtc::ArrayView<uint8_t> encoded) {
+ // Interleave the encoded bytes of the different channels. Each separate
+ // channel and the interleaved stream encodes two samples per byte, most
+ // significant half first.
+ for (size_t i = 0; i < samples_per_channel / 2; ++i) {
+ for (size_t j = 0; j < num_channels_; ++j) {
+ uint8_t two_samples = encoders_[j].encoded_buffer.data()[i];
+ interleave_buffer_.data()[j] = two_samples >> 4;
+ interleave_buffer_.data()[num_channels_ + j] = two_samples & 0xf;
+ }
+ for (size_t j = 0; j < num_channels_; ++j)
+ encoded[i * num_channels_ + j] =
+ interleave_buffer_.data()[2 * j] << 4 |
+ interleave_buffer_.data()[2 * j + 1];
+ }
+
+ return bytes_to_encode;
+ });
+ info.encoded_timestamp = first_timestamp_in_buffer_;
+ info.payload_type = payload_type_;
+ info.encoder_type = CodecType::kG722;
+ return info;
+}
+
+AudioEncoderG722Impl::EncoderState::EncoderState() {
+ RTC_CHECK_EQ(0, WebRtcG722_CreateEncoder(&encoder));
+}
+
+AudioEncoderG722Impl::EncoderState::~EncoderState() {
+ RTC_CHECK_EQ(0, WebRtcG722_FreeEncoder(encoder));
+}
+
+size_t AudioEncoderG722Impl::SamplesPerChannel() const {
+ return kSampleRateHz / 100 * num_10ms_frames_per_packet_;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h
new file mode 100644
index 0000000000..a932aa8b7d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_G722_AUDIO_ENCODER_G722_H_
+#define MODULES_AUDIO_CODING_CODECS_G722_AUDIO_ENCODER_G722_H_
+
+#include <memory>
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/audio_codecs/g722/audio_encoder_g722_config.h"
+#include "api/units/time_delta.h"
+#include "modules/audio_coding/codecs/g722/g722_interface.h"
+#include "rtc_base/buffer.h"
+
+namespace webrtc {
+
+class AudioEncoderG722Impl final : public AudioEncoder {
+ public:
+ AudioEncoderG722Impl(const AudioEncoderG722Config& config, int payload_type);
+ ~AudioEncoderG722Impl() override;
+
+ AudioEncoderG722Impl(const AudioEncoderG722Impl&) = delete;
+ AudioEncoderG722Impl& operator=(const AudioEncoderG722Impl&) = delete;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ int RtpTimestampRateHz() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+ void Reset() override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+
+ protected:
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+
+ private:
+ // The encoder state for one channel.
+ struct EncoderState {
+ G722EncInst* encoder;
+ std::unique_ptr<int16_t[]> speech_buffer; // Queued up for encoding.
+ rtc::Buffer encoded_buffer; // Already encoded.
+ EncoderState();
+ ~EncoderState();
+ };
+
+ size_t SamplesPerChannel() const;
+
+ const size_t num_channels_;
+ const int payload_type_;
+ const size_t num_10ms_frames_per_packet_;
+ size_t num_10ms_frames_buffered_;
+ uint32_t first_timestamp_in_buffer_;
+ const std::unique_ptr<EncoderState[]> encoders_;
+ rtc::Buffer interleave_buffer_;
+};
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_G722_AUDIO_ENCODER_G722_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.c b/third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.c
new file mode 100644
index 0000000000..36ee6d92be
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/g722/g722_interface.h"
+#include "modules/third_party/g722/g722_enc_dec.h"
+
+int16_t WebRtcG722_CreateEncoder(G722EncInst **G722enc_inst)
+{
+ *G722enc_inst=(G722EncInst*)malloc(sizeof(G722EncoderState));
+ if (*G722enc_inst!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+int16_t WebRtcG722_EncoderInit(G722EncInst *G722enc_inst)
+{
+ // Create and/or reset the G.722 encoder
+ // Bitrate 64 kbps and wideband mode (2)
+ G722enc_inst = (G722EncInst *) WebRtc_g722_encode_init(
+ (G722EncoderState*) G722enc_inst, 64000, 2);
+ if (G722enc_inst == NULL) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int WebRtcG722_FreeEncoder(G722EncInst *G722enc_inst)
+{
+ // Free encoder memory
+ return WebRtc_g722_encode_release((G722EncoderState*) G722enc_inst);
+}
+
+size_t WebRtcG722_Encode(G722EncInst *G722enc_inst,
+ const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded)
+{
+ unsigned char *codechar = (unsigned char*) encoded;
+ // Encode the input speech vector
+ return WebRtc_g722_encode((G722EncoderState*) G722enc_inst, codechar,
+ speechIn, len);
+}
+
+int16_t WebRtcG722_CreateDecoder(G722DecInst **G722dec_inst)
+{
+ *G722dec_inst=(G722DecInst*)malloc(sizeof(G722DecoderState));
+ if (*G722dec_inst!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+void WebRtcG722_DecoderInit(G722DecInst* inst) {
+ // Create and/or reset the G.722 decoder
+ // Bitrate 64 kbps and wideband mode (2)
+ WebRtc_g722_decode_init((G722DecoderState*)inst, 64000, 2);
+}
+
+int WebRtcG722_FreeDecoder(G722DecInst *G722dec_inst)
+{
+ // Free encoder memory
+ return WebRtc_g722_decode_release((G722DecoderState*) G722dec_inst);
+}
+
+size_t WebRtcG722_Decode(G722DecInst *G722dec_inst,
+ const uint8_t *encoded,
+ size_t len,
+ int16_t *decoded,
+ int16_t *speechType)
+{
+ // Decode the G.722 encoder stream
+ *speechType=G722_WEBRTC_SPEECH;
+ return WebRtc_g722_decode((G722DecoderState*) G722dec_inst, decoded,
+ encoded, len);
+}
+
+int16_t WebRtcG722_Version(char *versionStr, short len)
+{
+ // Get version string
+ char version[30] = "2.0.0\n";
+ if (strlen(version) < (unsigned int)len)
+ {
+ strcpy(versionStr, version);
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.h b/third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.h
new file mode 100644
index 0000000000..85c1cd02a0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/g722_interface.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_
+#define MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_
+
+#include <stdint.h>
+
+/*
+ * Solution to support multiple instances
+ */
+
+typedef struct WebRtcG722EncInst G722EncInst;
+typedef struct WebRtcG722DecInst G722DecInst;
+
+/*
+ * Comfort noise constants
+ */
+
+#define G722_WEBRTC_SPEECH 1
+#define G722_WEBRTC_CNG 2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * WebRtcG722_CreateEncoder(...)
+ *
+ * Create memory used for G722 encoder
+ *
+ * Input:
+ * - G722enc_inst : G722 instance for encoder
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int16_t WebRtcG722_CreateEncoder(G722EncInst** G722enc_inst);
+
+/****************************************************************************
+ * WebRtcG722_EncoderInit(...)
+ *
+ * This function initializes a G722 instance
+ *
+ * Input:
+ * - G722enc_inst : G722 instance, i.e. the user that should receive
+ * be initialized
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcG722_EncoderInit(G722EncInst* G722enc_inst);
+
+/****************************************************************************
+ * WebRtcG722_FreeEncoder(...)
+ *
+ * Free the memory used for G722 encoder
+ *
+ * Input:
+ * - G722enc_inst : G722 instance for encoder
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int WebRtcG722_FreeEncoder(G722EncInst* G722enc_inst);
+
+/****************************************************************************
+ * WebRtcG722_Encode(...)
+ *
+ * This function encodes G722 encoded data.
+ *
+ * Input:
+ * - G722enc_inst : G722 instance, i.e. the user that should encode
+ * a packet
+ * - speechIn : Input speech vector
+ * - len : Samples in speechIn
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : Length (in bytes) of coded data
+ */
+
+size_t WebRtcG722_Encode(G722EncInst* G722enc_inst,
+ const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcG722_CreateDecoder(...)
+ *
+ * Create memory used for G722 encoder
+ *
+ * Input:
+ * - G722dec_inst : G722 instance for decoder
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int16_t WebRtcG722_CreateDecoder(G722DecInst** G722dec_inst);
+
+/****************************************************************************
+ * WebRtcG722_DecoderInit(...)
+ *
+ * This function initializes a G722 instance
+ *
+ * Input:
+ * - inst : G722 instance
+ */
+
+void WebRtcG722_DecoderInit(G722DecInst* inst);
+
+/****************************************************************************
+ * WebRtcG722_FreeDecoder(...)
+ *
+ * Free the memory used for G722 decoder
+ *
+ * Input:
+ * - G722dec_inst : G722 instance for decoder
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int WebRtcG722_FreeDecoder(G722DecInst* G722dec_inst);
+
+/****************************************************************************
+ * WebRtcG722_Decode(...)
+ *
+ * This function decodes a packet with G729 frame(s). Output speech length
+ * will be a multiple of 80 samples (80*frames/packet).
+ *
+ * Input:
+ * - G722dec_inst : G722 instance, i.e. the user that should decode
+ * a packet
+ * - encoded : Encoded G722 frame(s)
+ * - len : Bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ * - speechType : 1 normal, 2 CNG (Since G722 does not have its own
+ * DTX/CNG scheme it should always return 1)
+ *
+ * Return value : Samples in decoded vector
+ */
+
+size_t WebRtcG722_Decode(G722DecInst* G722dec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/****************************************************************************
+ * WebRtcG722_Version(...)
+ *
+ * Get a string with the current version of the codec
+ */
+
+int16_t WebRtcG722_Version(char* versionStr, short len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/g722/test/testG722.cc b/third_party/libwebrtc/modules/audio_coding/codecs/g722/test/testG722.cc
new file mode 100644
index 0000000000..9f2155d0f7
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/g722/test/testG722.cc
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * testG722.cpp : Defines the entry point for the console application.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* include API */
+#include "modules/audio_coding/codecs/g722/g722_interface.h"
+
+/* Runtime statistics */
+#include <time.h>
+#define CLOCKS_PER_SEC_G722 100000
+
+// Forward declaration
+typedef struct WebRtcG722EncInst G722EncInst;
+typedef struct WebRtcG722DecInst G722DecInst;
+
+/* function for reading audio data from PCM file */
+bool readframe(int16_t* data, FILE* inp, size_t length) {
+ size_t rlen = fread(data, sizeof(int16_t), length, inp);
+ if (rlen >= length)
+ return false;
+ memset(data + rlen, 0, (length - rlen) * sizeof(int16_t));
+ return true;
+}
+
+int main(int argc, char* argv[]) {
+ char inname[60], outbit[40], outname[40];
+ FILE *inp, *outbitp, *outp;
+
+ int framecnt;
+ bool endfile;
+ size_t framelength = 160;
+ G722EncInst* G722enc_inst;
+ G722DecInst* G722dec_inst;
+
+ /* Runtime statistics */
+ double starttime;
+ double runtime = 0;
+ double length_file;
+
+ size_t stream_len = 0;
+ int16_t shortdata[960];
+ int16_t decoded[960];
+ uint8_t streamdata[80 * 6];
+ int16_t speechType[1];
+
+ /* handling wrong input arguments in the command line */
+ if (argc != 5) {
+ printf("\n\nWrong number of arguments or flag values.\n\n");
+
+ printf("\n");
+ printf("Usage:\n\n");
+ printf("./testG722.exe framelength infile outbitfile outspeechfile \n\n");
+ printf("with:\n");
+ printf("framelength : Framelength in samples.\n\n");
+ printf("infile : Normal speech input file\n\n");
+ printf("outbitfile : Bitstream output file\n\n");
+ printf("outspeechfile: Speech output file\n\n");
+ exit(0);
+ }
+
+ /* Get frame length */
+ int framelength_int = atoi(argv[1]);
+ if (framelength_int < 0) {
+ printf(" G.722: Invalid framelength %d.\n", framelength_int);
+ exit(1);
+ }
+ framelength = static_cast<size_t>(framelength_int);
+
+ /* Get Input and Output files */
+ sscanf(argv[2], "%s", inname);
+ sscanf(argv[3], "%s", outbit);
+ sscanf(argv[4], "%s", outname);
+
+ if ((inp = fopen(inname, "rb")) == NULL) {
+ printf(" G.722: Cannot read file %s.\n", inname);
+ exit(1);
+ }
+ if ((outbitp = fopen(outbit, "wb")) == NULL) {
+ printf(" G.722: Cannot write file %s.\n", outbit);
+ exit(1);
+ }
+ if ((outp = fopen(outname, "wb")) == NULL) {
+ printf(" G.722: Cannot write file %s.\n", outname);
+ exit(1);
+ }
+ printf("\nInput:%s\nOutput bitstream:%s\nOutput:%s\n", inname, outbit,
+ outname);
+
+ /* Create and init */
+ WebRtcG722_CreateEncoder((G722EncInst**)&G722enc_inst);
+ WebRtcG722_CreateDecoder((G722DecInst**)&G722dec_inst);
+ WebRtcG722_EncoderInit((G722EncInst*)G722enc_inst);
+ WebRtcG722_DecoderInit((G722DecInst*)G722dec_inst);
+
+ /* Initialize encoder and decoder */
+ framecnt = 0;
+ endfile = false;
+ while (!endfile) {
+ framecnt++;
+
+ /* Read speech block */
+ endfile = readframe(shortdata, inp, framelength);
+
+ /* Start clock before call to encoder and decoder */
+ starttime = clock() / (double)CLOCKS_PER_SEC_G722;
+
+ /* G.722 encoding + decoding */
+ stream_len = WebRtcG722_Encode((G722EncInst*)G722enc_inst, shortdata,
+ framelength, streamdata);
+ WebRtcG722_Decode(G722dec_inst, streamdata, stream_len, decoded,
+ speechType);
+
+ /* Stop clock after call to encoder and decoder */
+ runtime += (double)((clock() / (double)CLOCKS_PER_SEC_G722) - starttime);
+
+ /* Write coded bits to file */
+ if (fwrite(streamdata, sizeof(short), stream_len / 2, outbitp) !=
+ stream_len / 2) {
+ return -1;
+ }
+ /* Write coded speech to file */
+ if (fwrite(decoded, sizeof(short), framelength, outp) != framelength) {
+ return -1;
+ }
+ }
+
+ WebRtcG722_FreeEncoder((G722EncInst*)G722enc_inst);
+ WebRtcG722_FreeDecoder((G722DecInst*)G722dec_inst);
+
+ length_file = ((double)framecnt * (double)framelength / 16000);
+ printf("\n\nLength of speech file: %.1f s\n", length_file);
+ printf("Time to run G.722: %.2f s (%.2f %% of realtime)\n\n", runtime,
+ (100 * runtime / length_file));
+ printf("---------------------END----------------------\n");
+
+ fclose(inp);
+ fclose(outbitp);
+ fclose(outp);
+
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.c
new file mode 100644
index 0000000000..77da78ba7f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_AbsQuant.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/abs_quant.h"
+
+#include "modules/audio_coding/codecs/ilbc/abs_quant_loop.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+
+/*----------------------------------------------------------------*
+ * predictive noise shaping encoding of scaled start state
+ * (subrutine for WebRtcIlbcfix_StateSearch)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_AbsQuant(
+ IlbcEncoder *iLBCenc_inst,
+ /* (i) Encoder instance */
+ iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax
+ and idxVec, uses state_first as
+ input) */
+ int16_t *in, /* (i) vector to encode */
+ int16_t *weightDenum /* (i) denominator of synthesis filter */
+ ) {
+ int16_t *syntOut;
+ size_t quantLen[2];
+
+ /* Stack based */
+ int16_t syntOutBuf[LPC_FILTERORDER+STATE_SHORT_LEN_30MS];
+ int16_t in_weightedVec[STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
+ int16_t *in_weighted = &in_weightedVec[LPC_FILTERORDER];
+
+ /* Initialize the buffers */
+ WebRtcSpl_MemSetW16(syntOutBuf, 0, LPC_FILTERORDER+STATE_SHORT_LEN_30MS);
+ syntOut = &syntOutBuf[LPC_FILTERORDER];
+ /* Start with zero state */
+ WebRtcSpl_MemSetW16(in_weightedVec, 0, LPC_FILTERORDER);
+
+ /* Perform the quantization loop in two sections of length quantLen[i],
+ where the perceptual weighting filter is updated at the subframe
+ border */
+
+ if (iLBC_encbits->state_first) {
+ quantLen[0]=SUBL;
+ quantLen[1]=iLBCenc_inst->state_short_len-SUBL;
+ } else {
+ quantLen[0]=iLBCenc_inst->state_short_len-SUBL;
+ quantLen[1]=SUBL;
+ }
+
+ /* Calculate the weighted residual, switch perceptual weighting
+ filter at the subframe border */
+ WebRtcSpl_FilterARFastQ12(
+ in, in_weighted,
+ weightDenum, LPC_FILTERORDER+1, quantLen[0]);
+ WebRtcSpl_FilterARFastQ12(
+ &in[quantLen[0]], &in_weighted[quantLen[0]],
+ &weightDenum[LPC_FILTERORDER+1], LPC_FILTERORDER+1, quantLen[1]);
+
+ WebRtcIlbcfix_AbsQuantLoop(
+ syntOut,
+ in_weighted,
+ weightDenum,
+ quantLen,
+ iLBC_encbits->idxVec);
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.h
new file mode 100644
index 0000000000..c72e29cf29
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_AbsQuant.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * predictive noise shaping encoding of scaled start state
+ * (subrutine for WebRtcIlbcfix_StateSearch)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_AbsQuant(
+ IlbcEncoder* iLBCenc_inst,
+ /* (i) Encoder instance */
+ iLBC_bits* iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax
+ and idxVec, uses state_first as
+ input) */
+ int16_t* in, /* (i) vector to encode */
+ int16_t* weightDenum /* (i) denominator of synthesis filter */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.c
new file mode 100644
index 0000000000..cf9266299d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_AbsQuantLoop.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/abs_quant_loop.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/sort_sq.h"
+
+void WebRtcIlbcfix_AbsQuantLoop(int16_t *syntOutIN, int16_t *in_weightedIN,
+ int16_t *weightDenumIN, size_t *quantLenIN,
+ int16_t *idxVecIN ) {
+ size_t k1, k2;
+ int16_t index;
+ int32_t toQW32;
+ int32_t toQ32;
+ int16_t tmp16a;
+ int16_t xq;
+
+ int16_t *syntOut = syntOutIN;
+ int16_t *in_weighted = in_weightedIN;
+ int16_t *weightDenum = weightDenumIN;
+ size_t *quantLen = quantLenIN;
+ int16_t *idxVec = idxVecIN;
+
+ for(k1=0;k1<2;k1++) {
+ for(k2=0;k2<quantLen[k1];k2++){
+
+ /* Filter to get the predicted value */
+ WebRtcSpl_FilterARFastQ12(
+ syntOut, syntOut,
+ weightDenum, LPC_FILTERORDER+1, 1);
+
+ /* the quantizer */
+ toQW32 = (int32_t)(*in_weighted) - (int32_t)(*syntOut);
+
+ toQ32 = (((int32_t)toQW32)<<2);
+
+ if (toQ32 > 32767) {
+ toQ32 = (int32_t) 32767;
+ } else if (toQ32 < -32768) {
+ toQ32 = (int32_t) -32768;
+ }
+
+ /* Quantize the state */
+ if (toQW32<(-7577)) {
+ /* To prevent negative overflow */
+ index=0;
+ } else if (toQW32>8151) {
+ /* To prevent positive overflow */
+ index=7;
+ } else {
+ /* Find the best quantization index
+ (state_sq3Tbl is in Q13 and toQ is in Q11)
+ */
+ WebRtcIlbcfix_SortSq(&xq, &index,
+ (int16_t)toQ32,
+ WebRtcIlbcfix_kStateSq3, 8);
+ }
+
+ /* Store selected index */
+ (*idxVec++) = index;
+
+ /* Compute decoded sample and update of the prediction filter */
+ tmp16a = ((WebRtcIlbcfix_kStateSq3[index] + 2 ) >> 2);
+
+ *syntOut = (int16_t) (tmp16a + (int32_t)(*in_weighted) - toQW32);
+
+ syntOut++; in_weighted++;
+ }
+ /* Update perceptual weighting filter at subframe border */
+ weightDenum += 11;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.h
new file mode 100644
index 0000000000..841d73b9fb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/abs_quant_loop.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_AbsQuantLoop.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * predictive noise shaping encoding of scaled start state
+ * (subrutine for WebRtcIlbcfix_StateSearch)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_AbsQuantLoop(int16_t* syntOutIN,
+ int16_t* in_weightedIN,
+ int16_t* weightDenumIN,
+ size_t* quantLenIN,
+ int16_t* idxVecIN);
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc
new file mode 100644
index 0000000000..57b5abbe23
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
+
+#include <memory>
+#include <utility>
+
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+AudioDecoderIlbcImpl::AudioDecoderIlbcImpl() {
+ WebRtcIlbcfix_DecoderCreate(&dec_state_);
+ WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
+}
+
+AudioDecoderIlbcImpl::~AudioDecoderIlbcImpl() {
+ WebRtcIlbcfix_DecoderFree(dec_state_);
+}
+
+bool AudioDecoderIlbcImpl::HasDecodePlc() const {
+ return true;
+}
+
+int AudioDecoderIlbcImpl::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(sample_rate_hz, 8000);
+ int16_t temp_type = 1; // Default is speech.
+ int ret = WebRtcIlbcfix_Decode(dec_state_, encoded, encoded_len, decoded,
+ &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+size_t AudioDecoderIlbcImpl::DecodePlc(size_t num_frames, int16_t* decoded) {
+ return WebRtcIlbcfix_NetEqPlc(dec_state_, decoded, num_frames);
+}
+
+void AudioDecoderIlbcImpl::Reset() {
+ WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
+}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderIlbcImpl::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ std::vector<ParseResult> results;
+ size_t bytes_per_frame;
+ int timestamps_per_frame;
+ if (payload.size() >= 950) {
+ RTC_LOG(LS_WARNING)
+ << "AudioDecoderIlbcImpl::ParsePayload: Payload too large";
+ return results;
+ }
+ if (payload.size() % 38 == 0) {
+ // 20 ms frames.
+ bytes_per_frame = 38;
+ timestamps_per_frame = 160;
+ } else if (payload.size() % 50 == 0) {
+ // 30 ms frames.
+ bytes_per_frame = 50;
+ timestamps_per_frame = 240;
+ } else {
+ RTC_LOG(LS_WARNING)
+ << "AudioDecoderIlbcImpl::ParsePayload: Invalid payload";
+ return results;
+ }
+
+ RTC_DCHECK_EQ(0, payload.size() % bytes_per_frame);
+ if (payload.size() == bytes_per_frame) {
+ std::unique_ptr<EncodedAudioFrame> frame(
+ new LegacyEncodedAudioFrame(this, std::move(payload)));
+ results.emplace_back(timestamp, 0, std::move(frame));
+ } else {
+ size_t byte_offset;
+ uint32_t timestamp_offset;
+ for (byte_offset = 0, timestamp_offset = 0; byte_offset < payload.size();
+ byte_offset += bytes_per_frame,
+ timestamp_offset += timestamps_per_frame) {
+ std::unique_ptr<EncodedAudioFrame> frame(new LegacyEncodedAudioFrame(
+ this, rtc::Buffer(payload.data() + byte_offset, bytes_per_frame)));
+ results.emplace_back(timestamp + timestamp_offset, 0, std::move(frame));
+ }
+ }
+
+ return results;
+}
+
+int AudioDecoderIlbcImpl::SampleRateHz() const {
+ return 8000;
+}
+
+size_t AudioDecoderIlbcImpl::Channels() const {
+ return 1;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
new file mode 100644
index 0000000000..46ba755148
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "rtc_base/buffer.h"
+
+typedef struct iLBC_decinst_t_ IlbcDecoderInstance;
+
+namespace webrtc {
+
+class AudioDecoderIlbcImpl final : public AudioDecoder {
+ public:
+ AudioDecoderIlbcImpl();
+ ~AudioDecoderIlbcImpl() override;
+
+ AudioDecoderIlbcImpl(const AudioDecoderIlbcImpl&) = delete;
+ AudioDecoderIlbcImpl& operator=(const AudioDecoderIlbcImpl&) = delete;
+
+ bool HasDecodePlc() const override;
+ size_t DecodePlc(size_t num_frames, int16_t* decoded) override;
+ void Reset() override;
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ IlbcDecoderInstance* dec_state_;
+};
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
new file mode 100644
index 0000000000..9fbf42ceeb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
+
+#include <algorithm>
+#include <cstdint>
+
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kSampleRateHz = 8000;
+
+int GetIlbcBitrate(int ptime) {
+ switch (ptime) {
+ case 20:
+ case 40:
+ // 38 bytes per frame of 20 ms => 15200 bits/s.
+ return 15200;
+ case 30:
+ case 60:
+ // 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
+ return 13333;
+ default:
+ RTC_CHECK_NOTREACHED();
+ }
+}
+
+} // namespace
+
+AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config,
+ int payload_type)
+ : frame_size_ms_(config.frame_size_ms),
+ payload_type_(payload_type),
+ num_10ms_frames_per_packet_(
+ static_cast<size_t>(config.frame_size_ms / 10)),
+ encoder_(nullptr) {
+ RTC_CHECK(config.IsOk());
+ Reset();
+}
+
+AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
+ RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
+}
+
+int AudioEncoderIlbcImpl::SampleRateHz() const {
+ return kSampleRateHz;
+}
+
+size_t AudioEncoderIlbcImpl::NumChannels() const {
+ return 1;
+}
+
+size_t AudioEncoderIlbcImpl::Num10MsFramesInNextPacket() const {
+ return num_10ms_frames_per_packet_;
+}
+
+size_t AudioEncoderIlbcImpl::Max10MsFramesInAPacket() const {
+ return num_10ms_frames_per_packet_;
+}
+
+int AudioEncoderIlbcImpl::GetTargetBitrate() const {
+ return GetIlbcBitrate(rtc::dchecked_cast<int>(num_10ms_frames_per_packet_) *
+ 10);
+}
+
+AudioEncoder::EncodedInfo AudioEncoderIlbcImpl::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ // Save timestamp if starting a new packet.
+ if (num_10ms_frames_buffered_ == 0)
+ first_timestamp_in_buffer_ = rtp_timestamp;
+
+ // Buffer input.
+ std::copy(audio.cbegin(), audio.cend(),
+ input_buffer_ + kSampleRateHz / 100 * num_10ms_frames_buffered_);
+
+ // If we don't yet have enough buffered input for a whole packet, we're done
+ // for now.
+ if (++num_10ms_frames_buffered_ < num_10ms_frames_per_packet_) {
+ return EncodedInfo();
+ }
+
+ // Encode buffered input.
+ RTC_DCHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_);
+ num_10ms_frames_buffered_ = 0;
+ size_t encoded_bytes = encoded->AppendData(
+ RequiredOutputSizeBytes(), [&](rtc::ArrayView<uint8_t> encoded) {
+ const int r = WebRtcIlbcfix_Encode(
+ encoder_, input_buffer_,
+ kSampleRateHz / 100 * num_10ms_frames_per_packet_, encoded.data());
+ RTC_CHECK_GE(r, 0);
+
+ return static_cast<size_t>(r);
+ });
+
+ RTC_DCHECK_EQ(encoded_bytes, RequiredOutputSizeBytes());
+
+ EncodedInfo info;
+ info.encoded_bytes = encoded_bytes;
+ info.encoded_timestamp = first_timestamp_in_buffer_;
+ info.payload_type = payload_type_;
+ info.encoder_type = CodecType::kIlbc;
+ return info;
+}
+
+void AudioEncoderIlbcImpl::Reset() {
+ if (encoder_)
+ RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
+ RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
+ const int encoder_frame_size_ms =
+ frame_size_ms_ > 30 ? frame_size_ms_ / 2 : frame_size_ms_;
+ RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms));
+ num_10ms_frames_buffered_ = 0;
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderIlbcImpl::GetFrameLengthRange() const {
+ return {{TimeDelta::Millis(num_10ms_frames_per_packet_ * 10),
+ TimeDelta::Millis(num_10ms_frames_per_packet_ * 10)}};
+}
+
+size_t AudioEncoderIlbcImpl::RequiredOutputSizeBytes() const {
+ switch (num_10ms_frames_per_packet_) {
+ case 2:
+ return 38;
+ case 3:
+ return 50;
+ case 4:
+ return 2 * 38;
+ case 6:
+ return 2 * 50;
+ default:
+ RTC_CHECK_NOTREACHED();
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
new file mode 100644
index 0000000000..c8dfa2ca6d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
+#include "api/units/time_delta.h"
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+
+namespace webrtc {
+
+class AudioEncoderIlbcImpl final : public AudioEncoder {
+ public:
+ AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config, int payload_type);
+ ~AudioEncoderIlbcImpl() override;
+
+ AudioEncoderIlbcImpl(const AudioEncoderIlbcImpl&) = delete;
+ AudioEncoderIlbcImpl& operator=(const AudioEncoderIlbcImpl&) = delete;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+ void Reset() override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+
+ private:
+ size_t RequiredOutputSizeBytes() const;
+
+ static constexpr size_t kMaxSamplesPerPacket = 480;
+ const int frame_size_ms_;
+ const int payload_type_;
+ const size_t num_10ms_frames_per_packet_;
+ size_t num_10ms_frames_buffered_;
+ uint32_t first_timestamp_in_buffer_;
+ int16_t input_buffer_[kMaxSamplesPerPacket];
+ IlbcEncoderInstance* encoder_;
+};
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c
new file mode 100644
index 0000000000..c915a2f9f0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_AugmentedCbCorr.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_AugmentedCbCorr(
+ int16_t *target, /* (i) Target vector */
+ int16_t *buffer, /* (i) Memory buffer */
+ int16_t *interpSamples, /* (i) buffer with
+ interpolated samples */
+ int32_t *crossDot, /* (o) The cross correlation between
+ the target and the Augmented
+ vector */
+ size_t low, /* (i) Lag to start from (typically
+ 20) */
+ size_t high, /* (i) Lag to end at (typically 39) */
+ int scale) /* (i) Scale factor to use for
+ the crossDot */
+{
+ size_t lagcount;
+ size_t ilow;
+ int16_t *targetPtr;
+ int32_t *crossDotPtr;
+ int16_t *iSPtr=interpSamples;
+
+ /* Calculate the correlation between the target and the
+ interpolated codebook. The correlation is calculated in
+ 3 sections with the interpolated part in the middle */
+ crossDotPtr=crossDot;
+ for (lagcount=low; lagcount<=high; lagcount++) {
+
+ ilow = lagcount - 4;
+
+ /* Compute dot product for the first (lagcount-4) samples */
+ (*crossDotPtr) = WebRtcSpl_DotProductWithScale(target, buffer-lagcount, ilow, scale);
+
+ /* Compute dot product on the interpolated samples */
+ (*crossDotPtr) += WebRtcSpl_DotProductWithScale(target+ilow, iSPtr, 4, scale);
+ targetPtr = target + lagcount;
+ iSPtr += lagcount-ilow;
+
+ /* Compute dot product for the remaining samples */
+ (*crossDotPtr) += WebRtcSpl_DotProductWithScale(targetPtr, buffer-lagcount, SUBL-lagcount, scale);
+ crossDotPtr++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h
new file mode 100644
index 0000000000..2e9612e51a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_AugmentedCbCorr.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Calculate correlation between target and Augmented codebooks
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_AugmentedCbCorr(
+ int16_t* target, /* (i) Target vector */
+ int16_t* buffer, /* (i) Memory buffer */
+ int16_t* interpSamples, /* (i) buffer with
+ interpolated samples */
+ int32_t* crossDot, /* (o) The cross correlation between
+ the target and the Augmented
+ vector */
+ size_t low, /* (i) Lag to start from (typically
+ 20) */
+ size_t high, /* (i) Lag to end at (typically 39 */
+ int scale); /* (i) Scale factor to use for the crossDot */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.c
new file mode 100644
index 0000000000..1a9b882adf
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_BwExpand.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * lpc bandwidth expansion
+ *---------------------------------------------------------------*/
+
+/* The output is in the same domain as the input */
+void WebRtcIlbcfix_BwExpand(
+ int16_t *out, /* (o) the bandwidth expanded lpc coefficients */
+ int16_t *in, /* (i) the lpc coefficients before bandwidth
+ expansion */
+ int16_t *coef, /* (i) the bandwidth expansion factor Q15 */
+ int16_t length /* (i) the length of lpc coefficient vectors */
+ ) {
+ int i;
+
+ out[0] = in[0];
+ for (i = 1; i < length; i++) {
+ /* out[i] = coef[i] * in[i] with rounding.
+ in[] and out[] are in Q12 and coef[] is in Q15
+ */
+ out[i] = (int16_t)((coef[i] * in[i] + 16384) >> 15);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.h
new file mode 100644
index 0000000000..ff9b0b302e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/bw_expand.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_BwExpand.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * lpc bandwidth expansion
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_BwExpand(
+ int16_t* out, /* (o) the bandwidth expanded lpc coefficients */
+ int16_t* in, /* (i) the lpc coefficients before bandwidth
+ expansion */
+ int16_t* coef, /* (i) the bandwidth expansion factor Q15 */
+ int16_t length /* (i) the length of lpc coefficient vectors */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.c
new file mode 100644
index 0000000000..1e9a7040c7
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbConstruct.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_construct.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/gain_dequant.h"
+#include "modules/audio_coding/codecs/ilbc/get_cd_vec.h"
+#include "rtc_base/sanitizer.h"
+
+// An arithmetic operation that is allowed to overflow. (It's still undefined
+// behavior, so not a good idea; this just makes UBSan ignore the violation, so
+// that our old code can continue to do what it's always been doing.)
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+ OverflowingAddS32S32ToS32(int32_t a, int32_t b) {
+ return a + b;
+}
+
+/*----------------------------------------------------------------*
+ * Construct decoded vector from codebook and gains.
+ *---------------------------------------------------------------*/
+
+bool WebRtcIlbcfix_CbConstruct(
+ int16_t* decvector, /* (o) Decoded vector */
+ const int16_t* index, /* (i) Codebook indices */
+ const int16_t* gain_index, /* (i) Gain quantization indices */
+ int16_t* mem, /* (i) Buffer for codevector construction */
+ size_t lMem, /* (i) Length of buffer */
+ size_t veclen) { /* (i) Length of vector */
+ size_t j;
+ int16_t gain[CB_NSTAGES];
+ /* Stack based */
+ int16_t cbvec0[SUBL];
+ int16_t cbvec1[SUBL];
+ int16_t cbvec2[SUBL];
+ int32_t a32;
+ int16_t *gainPtr;
+
+ /* gain de-quantization */
+
+ gain[0] = WebRtcIlbcfix_GainDequant(gain_index[0], 16384, 0);
+ gain[1] = WebRtcIlbcfix_GainDequant(gain_index[1], gain[0], 1);
+ gain[2] = WebRtcIlbcfix_GainDequant(gain_index[2], gain[1], 2);
+
+ /* codebook vector construction and construction of total vector */
+
+ /* Stack based */
+ if (!WebRtcIlbcfix_GetCbVec(cbvec0, mem, (size_t)index[0], lMem, veclen))
+ return false; // Failure.
+ if (!WebRtcIlbcfix_GetCbVec(cbvec1, mem, (size_t)index[1], lMem, veclen))
+ return false; // Failure.
+ if (!WebRtcIlbcfix_GetCbVec(cbvec2, mem, (size_t)index[2], lMem, veclen))
+ return false; // Failure.
+
+ gainPtr = &gain[0];
+ for (j=0;j<veclen;j++) {
+ a32 = (*gainPtr++) * cbvec0[j];
+ a32 += (*gainPtr++) * cbvec1[j];
+ a32 = OverflowingAddS32S32ToS32(a32, (*gainPtr) * cbvec2[j]);
+ gainPtr -= 2;
+ decvector[j] = (int16_t)((a32 + 8192) >> 14);
+ }
+
+ return true; // Success.
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.h
new file mode 100644
index 0000000000..8f7c663164
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_construct.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbConstruct.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "absl/base/attributes.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Construct decoded vector from codebook and gains.
+ *---------------------------------------------------------------*/
+
+// Returns true on success, false on failure.
+ABSL_MUST_USE_RESULT
+bool WebRtcIlbcfix_CbConstruct(
+ int16_t* decvector, /* (o) Decoded vector */
+ const int16_t* index, /* (i) Codebook indices */
+ const int16_t* gain_index, /* (i) Gain quantization indices */
+ int16_t* mem, /* (i) Buffer for codevector construction */
+ size_t lMem, /* (i) Length of buffer */
+ size_t veclen /* (i) Length of vector */
+);
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.c
new file mode 100644
index 0000000000..21e4197607
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbMemEnergy.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy.h"
+
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Function WebRtcIlbcfix_CbMemEnergy computes the energy of all
+ * the vectors in the codebook memory that will be used in the
+ * following search for the best match.
+ *----------------------------------------------------------------*/
+
+void WebRtcIlbcfix_CbMemEnergy(
+ size_t range,
+ int16_t *CB, /* (i) The CB memory (1:st section) */
+ int16_t *filteredCB, /* (i) The filtered CB memory (2:nd section) */
+ size_t lMem, /* (i) Length of the CB memory */
+ size_t lTarget, /* (i) Length of the target vector */
+ int16_t *energyW16, /* (o) Energy in the CB vectors */
+ int16_t *energyShifts, /* (o) Shift value of the energy */
+ int scale, /* (i) The scaling of all energy values */
+ size_t base_size /* (i) Index to where energy values should be stored */
+ ) {
+ int16_t *ppi, *ppo, *pp;
+ int32_t energy, tmp32;
+
+ /* Compute the energy and store it in a vector. Also the
+ * corresponding shift values are stored. The energy values
+ * are reused in all three stages. */
+
+ /* Calculate the energy in the first block of 'lTarget' sampels. */
+ ppi = CB+lMem-lTarget-1;
+ ppo = CB+lMem-1;
+
+ pp=CB+lMem-lTarget;
+ energy = WebRtcSpl_DotProductWithScale( pp, pp, lTarget, scale);
+
+ /* Normalize the energy and store the number of shifts */
+ energyShifts[0] = (int16_t)WebRtcSpl_NormW32(energy);
+ tmp32 = energy << energyShifts[0];
+ energyW16[0] = (int16_t)(tmp32 >> 16);
+
+ /* Compute the energy of the rest of the cb memory
+ * by step wise adding and subtracting the next
+ * sample and the last sample respectively. */
+ WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, 0);
+
+ /* Next, precompute the energy values for the filtered cb section */
+ energy=0;
+ pp=filteredCB+lMem-lTarget;
+
+ energy = WebRtcSpl_DotProductWithScale( pp, pp, lTarget, scale);
+
+ /* Normalize the energy and store the number of shifts */
+ energyShifts[base_size] = (int16_t)WebRtcSpl_NormW32(energy);
+ tmp32 = energy << energyShifts[base_size];
+ energyW16[base_size] = (int16_t)(tmp32 >> 16);
+
+ ppi = filteredCB + lMem - 1 - lTarget;
+ ppo = filteredCB + lMem - 1;
+
+ WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, base_size);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.h
new file mode 100644
index 0000000000..17ec337dc6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbMemEnergy.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+void WebRtcIlbcfix_CbMemEnergy(
+ size_t range,
+ int16_t* CB, /* (i) The CB memory (1:st section) */
+ int16_t* filteredCB, /* (i) The filtered CB memory (2:nd section) */
+ size_t lMem, /* (i) Length of the CB memory */
+ size_t lTarget, /* (i) Length of the target vector */
+ int16_t* energyW16, /* (o) Energy in the CB vectors */
+ int16_t* energyShifts, /* (o) Shift value of the energy */
+ int scale, /* (i) The scaling of all energy values */
+ size_t base_size /* (i) Index to where energy values should be stored */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c
new file mode 100644
index 0000000000..0619bbe422
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbMemEnergyAugmentation.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_CbMemEnergyAugmentation(
+ int16_t *interpSamples, /* (i) The interpolated samples */
+ int16_t *CBmem, /* (i) The CB memory */
+ int scale, /* (i) The scaling of all energy values */
+ size_t base_size, /* (i) Index to where energy values should be stored */
+ int16_t *energyW16, /* (o) Energy in the CB vectors */
+ int16_t *energyShifts /* (o) Shift value of the energy */
+ ){
+ int32_t energy, tmp32;
+ int16_t *ppe, *pp, *interpSamplesPtr;
+ int16_t *CBmemPtr;
+ size_t lagcount;
+ int16_t *enPtr=&energyW16[base_size-20];
+ int16_t *enShPtr=&energyShifts[base_size-20];
+ int32_t nrjRecursive;
+
+ CBmemPtr = CBmem+147;
+ interpSamplesPtr = interpSamples;
+
+ /* Compute the energy for the first (low-5) noninterpolated samples */
+ nrjRecursive = WebRtcSpl_DotProductWithScale( CBmemPtr-19, CBmemPtr-19, 15, scale);
+ ppe = CBmemPtr - 20;
+
+ for (lagcount=20; lagcount<=39; lagcount++) {
+
+ /* Update the energy recursively to save complexity */
+ nrjRecursive += (*ppe * *ppe) >> scale;
+ ppe--;
+ energy = nrjRecursive;
+
+ /* interpolation */
+ energy += WebRtcSpl_DotProductWithScale(interpSamplesPtr, interpSamplesPtr, 4, scale);
+ interpSamplesPtr += 4;
+
+ /* Compute energy for the remaining samples */
+ pp = CBmemPtr - lagcount;
+ energy += WebRtcSpl_DotProductWithScale(pp, pp, SUBL-lagcount, scale);
+
+ /* Normalize the energy and store the number of shifts */
+ (*enShPtr) = (int16_t)WebRtcSpl_NormW32(energy);
+ tmp32 = energy << *enShPtr;
+ *enPtr = (int16_t)(tmp32 >> 16);
+ enShPtr++;
+ enPtr++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h
new file mode 100644
index 0000000000..d7b7a0d97e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbMemEnergyAugmentation.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+void WebRtcIlbcfix_CbMemEnergyAugmentation(
+ int16_t* interpSamples, /* (i) The interpolated samples */
+ int16_t* CBmem, /* (i) The CB memory */
+ int scale, /* (i) The scaling of all energy values */
+ size_t base_size, /* (i) Index to where energy values should be stored */
+ int16_t* energyW16, /* (o) Energy in the CB vectors */
+ int16_t* energyShifts /* (o) Shift value of the energy */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c
new file mode 100644
index 0000000000..58c0c5fe6d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbMemEnergyCalc.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/* Compute the energy of the rest of the cb memory
+ * by step wise adding and subtracting the next
+ * sample and the last sample respectively */
+void WebRtcIlbcfix_CbMemEnergyCalc(
+ int32_t energy, /* (i) input start energy */
+ size_t range, /* (i) number of iterations */
+ int16_t *ppi, /* (i) input pointer 1 */
+ int16_t *ppo, /* (i) input pointer 2 */
+ int16_t *energyW16, /* (o) Energy in the CB vectors */
+ int16_t *energyShifts, /* (o) Shift value of the energy */
+ int scale, /* (i) The scaling of all energy values */
+ size_t base_size /* (i) Index to where energy values should be stored */
+ )
+{
+ size_t j;
+ int16_t shft;
+ int32_t tmp;
+ int16_t *eSh_ptr;
+ int16_t *eW16_ptr;
+
+
+ eSh_ptr = &energyShifts[1+base_size];
+ eW16_ptr = &energyW16[1+base_size];
+
+ for (j = 0; j + 1 < range; j++) {
+
+ /* Calculate next energy by a +/-
+ operation on the edge samples */
+ tmp = (*ppi) * (*ppi) - (*ppo) * (*ppo);
+ energy += tmp >> scale;
+ energy = WEBRTC_SPL_MAX(energy, 0);
+
+ ppi--;
+ ppo--;
+
+ /* Normalize the energy into a int16_t and store
+ the number of shifts */
+
+ shft = (int16_t)WebRtcSpl_NormW32(energy);
+ *eSh_ptr++ = shft;
+
+ tmp = energy << shft;
+ *eW16_ptr++ = (int16_t)(tmp >> 16);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h
new file mode 100644
index 0000000000..1d1e8d62b9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbMemEnergyCalc.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+void WebRtcIlbcfix_CbMemEnergyCalc(
+ int32_t energy, /* (i) input start energy */
+ size_t range, /* (i) number of iterations */
+ int16_t* ppi, /* (i) input pointer 1 */
+ int16_t* ppo, /* (i) input pointer 2 */
+ int16_t* energyW16, /* (o) Energy in the CB vectors */
+ int16_t* energyShifts, /* (o) Shift value of the energy */
+ int scale, /* (i) The scaling of all energy values */
+ size_t base_size /* (i) Index to where energy values should be stored */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.c
new file mode 100644
index 0000000000..24b5292354
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbSearch.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_search.h"
+
+#include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy.h"
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h"
+#include "modules/audio_coding/codecs/ilbc/cb_search_core.h"
+#include "modules/audio_coding/codecs/ilbc/cb_update_best_index.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/energy_inverse.h"
+#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
+#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
+#include "modules/audio_coding/codecs/ilbc/interpolate_samples.h"
+
+/*----------------------------------------------------------------*
+ * Search routine for codebook encoding and gain quantization.
+ *----------------------------------------------------------------*/
+
+void WebRtcIlbcfix_CbSearch(
+ IlbcEncoder *iLBCenc_inst,
+ /* (i) the encoder state structure */
+ int16_t *index, /* (o) Codebook indices */
+ int16_t *gain_index, /* (o) Gain quantization indices */
+ int16_t *intarget, /* (i) Target vector for encoding */
+ int16_t *decResidual,/* (i) Decoded residual for codebook construction */
+ size_t lMem, /* (i) Length of buffer */
+ size_t lTarget, /* (i) Length of vector */
+ int16_t *weightDenum,/* (i) weighting filter coefficients in Q12 */
+ size_t block /* (i) the subblock number */
+ ) {
+ size_t i, range;
+ int16_t ii, j, stage;
+ int16_t *pp;
+ int16_t tmp;
+ int scale;
+ int16_t bits, temp1, temp2;
+ size_t base_size;
+ int32_t codedEner, targetEner;
+ int16_t gains[CB_NSTAGES+1];
+ int16_t *cb_vecPtr;
+ size_t indexOffset, sInd, eInd;
+ int32_t CritMax=0;
+ int16_t shTotMax=WEBRTC_SPL_WORD16_MIN;
+ size_t bestIndex=0;
+ int16_t bestGain=0;
+ size_t indexNew;
+ int16_t CritNewSh;
+ int32_t CritNew;
+ int32_t *cDotPtr;
+ size_t noOfZeros;
+ int16_t *gainPtr;
+ int32_t t32, tmpW32;
+ int16_t *WebRtcIlbcfix_kGainSq5_ptr;
+ /* Stack based */
+ int16_t CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN];
+ int32_t cDot[128];
+ int32_t Crit[128];
+ int16_t targetVec[SUBL+LPC_FILTERORDER];
+ int16_t cbvectors[CB_MEML + 1]; /* Adding one extra position for
+ Coverity warnings. */
+ int16_t codedVec[SUBL];
+ int16_t interpSamples[20*4];
+ int16_t interpSamplesFilt[20*4];
+ int16_t energyW16[CB_EXPAND*128];
+ int16_t energyShifts[CB_EXPAND*128];
+ int16_t *inverseEnergy=energyW16; /* Reuse memory */
+ int16_t *inverseEnergyShifts=energyShifts; /* Reuse memory */
+ int16_t *buf = &CBbuf[LPC_FILTERORDER];
+ int16_t *target = &targetVec[LPC_FILTERORDER];
+ int16_t *aug_vec = (int16_t*)cDot; /* length [SUBL], reuse memory */
+
+ /* Determine size of codebook sections */
+
+ base_size=lMem-lTarget+1;
+ if (lTarget==SUBL) {
+ base_size=lMem-19;
+ }
+
+ /* weighting of the CB memory */
+ noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block];
+ WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER);
+ WebRtcSpl_FilterARFastQ12(
+ decResidual+noOfZeros, buf+noOfZeros,
+ weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]);
+
+ /* weighting of the target vector */
+ WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER);
+ WebRtcSpl_FilterARFastQ12(
+ intarget, target,
+ weightDenum, LPC_FILTERORDER+1, lTarget);
+
+ /* Store target, towards the end codedVec is calculated as
+ the initial target minus the remaining target */
+ WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget);
+
+ /* Find the highest absolute value to calculate proper
+ vector scale factor (so that it uses 12 bits) */
+ temp1 = WebRtcSpl_MaxAbsValueW16(buf, lMem);
+ temp2 = WebRtcSpl_MaxAbsValueW16(target, lTarget);
+
+ if ((temp1>0)&&(temp2>0)) {
+ temp1 = WEBRTC_SPL_MAX(temp1, temp2);
+ scale = WebRtcSpl_GetSizeInBits((uint32_t)(temp1 * temp1));
+ } else {
+ /* temp1 or temp2 is negative (maximum was -32768) */
+ scale = 30;
+ }
+
+ /* Scale to so that a mul-add 40 times does not overflow */
+ scale = scale - 25;
+ scale = WEBRTC_SPL_MAX(0, scale);
+
+ /* Compute energy of the original target */
+ targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale);
+
+ /* Prepare search over one more codebook section. This section
+ is created by filtering the original buffer with a filter. */
+ WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]);
+
+ range = WebRtcIlbcfix_kSearchRange[block][0];
+
+ if(lTarget == SUBL) {
+ /* Create the interpolated samples and store them for use in all stages */
+
+ /* First section, non-filtered half of the cb */
+ WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem);
+
+ /* Second section, filtered half of the cb */
+ WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem);
+
+ /* Compute the CB vectors' energies for the first cb section (non-filtered) */
+ WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf,
+ scale, 20, energyW16, energyShifts);
+
+ /* Compute the CB vectors' energies for the second cb section (filtered cb) */
+ WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors, scale,
+ base_size + 20, energyW16,
+ energyShifts);
+
+ /* Compute the CB vectors' energies and store them in the vector
+ * energyW16. Also the corresponding shift values are stored. The
+ * energy values are used in all three stages. */
+ WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
+ lTarget, energyW16+20, energyShifts+20, scale, base_size);
+
+ } else {
+ /* Compute the CB vectors' energies and store them in the vector
+ * energyW16. Also the corresponding shift values are stored. The
+ * energy values are used in all three stages. */
+ WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
+ lTarget, energyW16, energyShifts, scale, base_size);
+
+ /* Set the energy positions 58-63 and 122-127 to zero
+ (otherwise they are uninitialized) */
+ WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range));
+ WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range));
+ }
+
+ /* Calculate Inverse Energy (energyW16 is already normalized
+ and will contain the inverse energy in Q29 after this call */
+ WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND);
+
+ /* The gain value computed in the previous stage is used
+ * as an upper limit to what the next stage gain value
+ * is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as
+ * the upper limit. */
+ gains[0] = 16384;
+
+ for (stage=0; stage<CB_NSTAGES; stage++) {
+
+ /* Set up memories */
+ range = WebRtcIlbcfix_kSearchRange[block][stage];
+
+ /* initialize search measures */
+ CritMax=0;
+ shTotMax=-100;
+ bestIndex=0;
+ bestGain=0;
+
+ /* loop over lags 40+ in the first codebook section, full search */
+ cb_vecPtr = buf+lMem-lTarget;
+
+ /* Calculate all the cross correlations (augmented part of CB) */
+ if (lTarget==SUBL) {
+ WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem,
+ interpSamples, cDot,
+ 20, 39, scale);
+ cDotPtr=&cDot[20];
+ } else {
+ cDotPtr=cDot;
+ }
+ /* Calculate all the cross correlations (main part of CB) */
+ WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1);
+
+ /* Adjust the search range for the augmented vectors */
+ if (lTarget==SUBL) {
+ range=WebRtcIlbcfix_kSearchRange[block][stage]+20;
+ } else {
+ range=WebRtcIlbcfix_kSearchRange[block][stage];
+ }
+
+ indexOffset=0;
+
+ /* Search for best index in this part of the vector */
+ WebRtcIlbcfix_CbSearchCore(
+ cDot, range, stage, inverseEnergy,
+ inverseEnergyShifts, Crit,
+ &indexNew, &CritNew, &CritNewSh);
+
+ /* Update the global best index and the corresponding gain */
+ WebRtcIlbcfix_CbUpdateBestIndex(
+ CritNew, CritNewSh, indexNew+indexOffset, cDot[indexNew+indexOffset],
+ inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
+ &CritMax, &shTotMax, &bestIndex, &bestGain);
+
+ sInd = ((CB_RESRANGE >> 1) > bestIndex) ?
+ 0 : (bestIndex - (CB_RESRANGE >> 1));
+ eInd=sInd+CB_RESRANGE;
+ if (eInd>=range) {
+ eInd=range-1;
+ sInd=eInd-CB_RESRANGE;
+ }
+
+ range = WebRtcIlbcfix_kSearchRange[block][stage];
+
+ if (lTarget==SUBL) {
+ i=sInd;
+ if (sInd<20) {
+ WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors + lMem,
+ interpSamplesFilt, cDot, sInd + 20,
+ WEBRTC_SPL_MIN(39, (eInd + 20)), scale);
+ i=20;
+ cDotPtr = &cDot[20 - sInd];
+ } else {
+ cDotPtr = cDot;
+ }
+
+ cb_vecPtr = cbvectors+lMem-20-i;
+
+ /* Calculate the cross correlations (main part of the filtered CB) */
+ WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget,
+ eInd - i + 1, scale, -1);
+
+ } else {
+ cDotPtr = cDot;
+ cb_vecPtr = cbvectors+lMem-lTarget-sInd;
+
+ /* Calculate the cross correlations (main part of the filtered CB) */
+ WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget,
+ eInd - sInd + 1, scale, -1);
+
+ }
+
+ /* Adjust the search range for the augmented vectors */
+ indexOffset=base_size+sInd;
+
+ /* Search for best index in this part of the vector */
+ WebRtcIlbcfix_CbSearchCore(
+ cDot, eInd-sInd+1, stage, inverseEnergy+indexOffset,
+ inverseEnergyShifts+indexOffset, Crit,
+ &indexNew, &CritNew, &CritNewSh);
+
+ /* Update the global best index and the corresponding gain */
+ WebRtcIlbcfix_CbUpdateBestIndex(
+ CritNew, CritNewSh, indexNew+indexOffset, cDot[indexNew],
+ inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
+ &CritMax, &shTotMax, &bestIndex, &bestGain);
+
+ index[stage] = (int16_t)bestIndex;
+
+
+ bestGain = WebRtcIlbcfix_GainQuant(bestGain,
+ (int16_t)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]);
+
+ /* Extract the best (according to measure) codebook vector
+ Also adjust the index, so that the augmented vectors are last.
+ Above these vectors were first...
+ */
+
+ if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
+
+ if((size_t)index[stage]<base_size) {
+ pp=buf+lMem-lTarget-index[stage];
+ } else {
+ pp=cbvectors+lMem-lTarget-
+ index[stage]+base_size;
+ }
+
+ } else {
+
+ if ((size_t)index[stage]<base_size) {
+ if (index[stage]>=20) {
+ /* Adjust index and extract vector */
+ index[stage]-=20;
+ pp=buf+lMem-lTarget-index[stage];
+ } else {
+ /* Adjust index and extract vector */
+ index[stage]+=(int16_t)(base_size-20);
+
+ WebRtcIlbcfix_CreateAugmentedVec(index[stage]-base_size+40,
+ buf+lMem, aug_vec);
+ pp = aug_vec;
+
+ }
+ } else {
+
+ if ((index[stage] - base_size) >= 20) {
+ /* Adjust index and extract vector */
+ index[stage]-=20;
+ pp=cbvectors+lMem-lTarget-
+ index[stage]+base_size;
+ } else {
+ /* Adjust index and extract vector */
+ index[stage]+=(int16_t)(base_size-20);
+ WebRtcIlbcfix_CreateAugmentedVec(index[stage]-2*base_size+40,
+ cbvectors+lMem, aug_vec);
+ pp = aug_vec;
+ }
+ }
+ }
+
+ /* Subtract the best codebook vector, according
+ to measure, from the target vector */
+
+ WebRtcSpl_AddAffineVectorToVector(target, pp, (int16_t)(-bestGain),
+ (int32_t)8192, (int16_t)14, lTarget);
+
+ /* record quantized gain */
+ gains[stage+1] = bestGain;
+
+ } /* end of Main Loop. for (stage=0;... */
+
+ /* Calculte the coded vector (original target - what's left) */
+ for (i=0;i<lTarget;i++) {
+ codedVec[i]-=target[i];
+ }
+
+ /* Gain adjustment for energy matching */
+ codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale);
+
+ j=gain_index[0];
+
+ temp1 = (int16_t)WebRtcSpl_NormW32(codedEner);
+ temp2 = (int16_t)WebRtcSpl_NormW32(targetEner);
+
+ if(temp1 < temp2) {
+ bits = 16 - temp1;
+ } else {
+ bits = 16 - temp2;
+ }
+
+ tmp = (int16_t)((gains[1] * gains[1]) >> 14);
+
+ targetEner = (int16_t)WEBRTC_SPL_SHIFT_W32(targetEner, -bits) * tmp;
+
+ tmpW32 = ((int32_t)(gains[1]-1))<<1;
+
+ /* Pointer to the table that contains
+ gain_sq5TblFIX * gain_sq5TblFIX in Q14 */
+ gainPtr=(int16_t*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0];
+ temp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(codedEner, -bits);
+
+ WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[j];
+
+ /* targetEner and codedEner are in Q(-2*scale) */
+ for (ii=gain_index[0];ii<32;ii++) {
+
+ /* Change the index if
+ (codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND
+ gainTbl[i] < 2*gain[0]
+ */
+
+ t32 = temp1 * *gainPtr;
+ t32 = t32 - targetEner;
+ if (t32 < 0) {
+ if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) {
+ j=ii;
+ WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[ii];
+ }
+ }
+ gainPtr++;
+ }
+ gain_index[0]=j;
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.h
new file mode 100644
index 0000000000..84a52c7868
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbSearch.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_CbSearch(
+ IlbcEncoder* iLBCenc_inst,
+ /* (i) the encoder state structure */
+ int16_t* index, /* (o) Codebook indices */
+ int16_t* gain_index, /* (o) Gain quantization indices */
+ int16_t* intarget, /* (i) Target vector for encoding */
+ int16_t* decResidual, /* (i) Decoded residual for codebook construction */
+ size_t lMem, /* (i) Length of buffer */
+ size_t lTarget, /* (i) Length of vector */
+ int16_t* weightDenum, /* (i) weighting filter coefficients in Q12 */
+ size_t block /* (i) the subblock number */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.c
new file mode 100644
index 0000000000..a75e5b0ab8
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbSearchCore.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_search_core.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_CbSearchCore(
+ int32_t *cDot, /* (i) Cross Correlation */
+ size_t range, /* (i) Search range */
+ int16_t stage, /* (i) Stage of this search */
+ int16_t *inverseEnergy, /* (i) Inversed energy */
+ int16_t *inverseEnergyShift, /* (i) Shifts of inversed energy
+ with the offset 2*16-29 */
+ int32_t *Crit, /* (o) The criteria */
+ size_t *bestIndex, /* (o) Index that corresponds to
+ maximum criteria (in this
+ vector) */
+ int32_t *bestCrit, /* (o) Value of critera for the
+ chosen index */
+ int16_t *bestCritSh) /* (o) The domain of the chosen
+ criteria */
+{
+ int32_t maxW32, tmp32;
+ int16_t max, sh, tmp16;
+ size_t i;
+ int32_t *cDotPtr;
+ int16_t cDotSqW16;
+ int16_t *inverseEnergyPtr;
+ int32_t *critPtr;
+ int16_t *inverseEnergyShiftPtr;
+
+ /* Don't allow negative values for stage 0 */
+ if (stage==0) {
+ cDotPtr=cDot;
+ for (i=0;i<range;i++) {
+ *cDotPtr=WEBRTC_SPL_MAX(0, (*cDotPtr));
+ cDotPtr++;
+ }
+ }
+
+ /* Normalize cDot to int16_t, calculate the square of cDot and store the upper int16_t */
+ maxW32 = WebRtcSpl_MaxAbsValueW32(cDot, range);
+
+ sh = (int16_t)WebRtcSpl_NormW32(maxW32);
+ cDotPtr = cDot;
+ inverseEnergyPtr = inverseEnergy;
+ critPtr = Crit;
+ inverseEnergyShiftPtr=inverseEnergyShift;
+ max=WEBRTC_SPL_WORD16_MIN;
+
+ for (i=0;i<range;i++) {
+ /* Calculate cDot*cDot and put the result in a int16_t */
+ tmp32 = *cDotPtr << sh;
+ tmp16 = (int16_t)(tmp32 >> 16);
+ cDotSqW16 = (int16_t)(((int32_t)(tmp16)*(tmp16))>>16);
+
+ /* Calculate the criteria (cDot*cDot/energy) */
+ *critPtr = cDotSqW16 * *inverseEnergyPtr;
+
+ /* Extract the maximum shift value under the constraint
+ that the criteria is not zero */
+ if ((*critPtr)!=0) {
+ max = WEBRTC_SPL_MAX((*inverseEnergyShiftPtr), max);
+ }
+
+ inverseEnergyPtr++;
+ inverseEnergyShiftPtr++;
+ critPtr++;
+ cDotPtr++;
+ }
+
+ /* If no max shifts still at initialization value, set shift to zero */
+ if (max==WEBRTC_SPL_WORD16_MIN) {
+ max = 0;
+ }
+
+ /* Modify the criterias, so that all of them use the same Q domain */
+ critPtr=Crit;
+ inverseEnergyShiftPtr=inverseEnergyShift;
+ for (i=0;i<range;i++) {
+ /* Guarantee that the shift value is less than 16
+ in order to simplify for DSP's (and guard against >31) */
+ tmp16 = WEBRTC_SPL_MIN(16, max-(*inverseEnergyShiftPtr));
+
+ (*critPtr)=WEBRTC_SPL_SHIFT_W32((*critPtr),-tmp16);
+ critPtr++;
+ inverseEnergyShiftPtr++;
+ }
+
+ /* Find the index of the best value */
+ *bestIndex = WebRtcSpl_MaxIndexW32(Crit, range);
+ *bestCrit = Crit[*bestIndex];
+
+ /* Calculate total shifts of this criteria */
+ *bestCritSh = 32 - 2*sh + max;
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.h
new file mode 100644
index 0000000000..5da70e0988
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_search_core.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbSearchCore.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+void WebRtcIlbcfix_CbSearchCore(
+ int32_t* cDot, /* (i) Cross Correlation */
+ size_t range, /* (i) Search range */
+ int16_t stage, /* (i) Stage of this search */
+ int16_t* inverseEnergy, /* (i) Inversed energy */
+ int16_t* inverseEnergyShift, /* (i) Shifts of inversed energy
+ with the offset 2*16-29 */
+ int32_t* Crit, /* (o) The criteria */
+ size_t* bestIndex, /* (o) Index that corresponds to
+ maximum criteria (in this
+ vector) */
+ int32_t* bestCrit, /* (o) Value of critera for the
+ chosen index */
+ int16_t* bestCritSh); /* (o) The domain of the chosen
+ criteria */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.c
new file mode 100644
index 0000000000..d6fa4d93d4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbUpdateBestIndex.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/cb_update_best_index.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_CbUpdateBestIndex(
+ int32_t CritNew, /* (i) New Potentially best Criteria */
+ int16_t CritNewSh, /* (i) Shift value of above Criteria */
+ size_t IndexNew, /* (i) Index of new Criteria */
+ int32_t cDotNew, /* (i) Cross dot of new index */
+ int16_t invEnergyNew, /* (i) Inversed energy new index */
+ int16_t energyShiftNew, /* (i) Energy shifts of new index */
+ int32_t *CritMax, /* (i/o) Maximum Criteria (so far) */
+ int16_t *shTotMax, /* (i/o) Shifts of maximum criteria */
+ size_t *bestIndex, /* (i/o) Index that corresponds to
+ maximum criteria */
+ int16_t *bestGain) /* (i/o) Gain in Q14 that corresponds
+ to maximum criteria */
+{
+ int16_t shOld, shNew, tmp16;
+ int16_t scaleTmp;
+ int32_t gainW32;
+
+ /* Normalize the new and old Criteria to the same domain */
+ if (CritNewSh>(*shTotMax)) {
+ shOld=WEBRTC_SPL_MIN(31,CritNewSh-(*shTotMax));
+ shNew=0;
+ } else {
+ shOld=0;
+ shNew=WEBRTC_SPL_MIN(31,(*shTotMax)-CritNewSh);
+ }
+
+ /* Compare the two criterias. If the new one is better,
+ calculate the gain and store this index as the new best one
+ */
+
+ if ((CritNew >> shNew) > (*CritMax >> shOld)) {
+
+ tmp16 = (int16_t)WebRtcSpl_NormW32(cDotNew);
+ tmp16 = 16 - tmp16;
+
+ /* Calculate the gain in Q14
+ Compensate for inverseEnergyshift in Q29 and that the energy
+ value was stored in a int16_t (shifted down 16 steps)
+ => 29-14+16 = 31 */
+
+ scaleTmp = -energyShiftNew-tmp16+31;
+ scaleTmp = WEBRTC_SPL_MIN(31, scaleTmp);
+
+ gainW32 = ((int16_t)WEBRTC_SPL_SHIFT_W32(cDotNew, -tmp16) * invEnergyNew) >>
+ scaleTmp;
+
+ /* Check if criteria satisfies Gain criteria (max 1.3)
+ if it is larger set the gain to 1.3
+ (slightly different from FLP version)
+ */
+ if (gainW32>21299) {
+ *bestGain=21299;
+ } else if (gainW32<-21299) {
+ *bestGain=-21299;
+ } else {
+ *bestGain=(int16_t)gainW32;
+ }
+
+ *CritMax=CritNew;
+ *shTotMax=CritNewSh;
+ *bestIndex = IndexNew;
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.h
new file mode 100644
index 0000000000..1a95d531e9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/cb_update_best_index.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CbUpdateBestIndex.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+void WebRtcIlbcfix_CbUpdateBestIndex(
+ int32_t CritNew, /* (i) New Potentially best Criteria */
+ int16_t CritNewSh, /* (i) Shift value of above Criteria */
+ size_t IndexNew, /* (i) Index of new Criteria */
+ int32_t cDotNew, /* (i) Cross dot of new index */
+ int16_t invEnergyNew, /* (i) Inversed energy new index */
+ int16_t energyShiftNew, /* (i) Energy shifts of new index */
+ int32_t* CritMax, /* (i/o) Maximum Criteria (so far) */
+ int16_t* shTotMax, /* (i/o) Shifts of maximum criteria */
+ size_t* bestIndex, /* (i/o) Index that corresponds to
+ maximum criteria */
+ int16_t* bestGain); /* (i/o) Gain in Q14 that corresponds
+ to maximum criteria */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.c
new file mode 100644
index 0000000000..b4eee66219
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Chebyshev.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/chebyshev.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*------------------------------------------------------------------*
+ * Calculate the Chevyshev polynomial series
+ * F(w) = 2*exp(-j5w)*C(x)
+ * C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
+ * T_i(x) is the i:th order Chebyshev polynomial
+ *------------------------------------------------------------------*/
+
+int16_t WebRtcIlbcfix_Chebyshev(
+ /* (o) Result of C(x) */
+ int16_t x, /* (i) Value to the Chevyshev polynomial */
+ int16_t *f /* (i) The coefficients in the polynomial */
+ ) {
+ int16_t b1_high, b1_low; /* Use the high, low format to increase the accuracy */
+ int32_t b2;
+ int32_t tmp1W32;
+ int32_t tmp2W32;
+ int i;
+
+ b2 = (int32_t)0x1000000; /* b2 = 1.0 (Q23) */
+ /* Calculate b1 = 2*x + f[1] */
+ tmp1W32 = (x << 10) + (f[1] << 14);
+
+ for (i = 2; i < 5; i++) {
+ tmp2W32 = tmp1W32;
+
+ /* Split b1 (in tmp1W32) into a high and low part */
+ b1_high = (int16_t)(tmp1W32 >> 16);
+ b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1);
+
+ /* Calculate 2*x*b1-b2+f[i] */
+ tmp1W32 = ((b1_high * x + ((b1_low * x) >> 15)) << 2) - b2 + (f[i] << 14);
+
+ /* Update b2 for next round */
+ b2 = tmp2W32;
+ }
+
+ /* Split b1 (in tmp1W32) into a high and low part */
+ b1_high = (int16_t)(tmp1W32 >> 16);
+ b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1);
+
+ /* tmp1W32 = x*b1 - b2 + f[i]/2 */
+ tmp1W32 = ((b1_high * x) << 1) + (((b1_low * x) >> 15) << 1) -
+ b2 + (f[i] << 13);
+
+ /* Handle overflows and set to maximum or minimum int16_t instead */
+ if (tmp1W32>((int32_t)33553408)) {
+ return(WEBRTC_SPL_WORD16_MAX);
+ } else if (tmp1W32<((int32_t)-33554432)) {
+ return(WEBRTC_SPL_WORD16_MIN);
+ } else {
+ return (int16_t)(tmp1W32 >> 10);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.h
new file mode 100644
index 0000000000..7e7742c5cc
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/chebyshev.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Chebyshev.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*------------------------------------------------------------------*
+ * Calculate the Chevyshev polynomial series
+ * F(w) = 2*exp(-j5w)*C(x)
+ * C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
+ * T_i(x) is the i:th order Chebyshev polynomial
+ *------------------------------------------------------------------*/
+
+int16_t WebRtcIlbcfix_Chebyshev(
+ /* (o) Result of C(x) */
+ int16_t x, /* (i) Value to the Chevyshev polynomial */
+ int16_t* f /* (i) The coefficients in the polynomial */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.c
new file mode 100644
index 0000000000..452bc78e3b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CompCorr.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Compute cross correlation and pitch gain for pitch prediction
+ * of last subframe at given lag.
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_CompCorr(
+ int32_t *corr, /* (o) cross correlation */
+ int32_t *ener, /* (o) energy */
+ int16_t *buffer, /* (i) signal buffer */
+ size_t lag, /* (i) pitch lag */
+ size_t bLen, /* (i) length of buffer */
+ size_t sRange, /* (i) correlation search length */
+ int16_t scale /* (i) number of rightshifts to use */
+ ){
+ int16_t *w16ptr;
+
+ w16ptr=&buffer[bLen-sRange-lag];
+
+ /* Calculate correlation and energy */
+ (*corr)=WebRtcSpl_DotProductWithScale(&buffer[bLen-sRange], w16ptr, sRange, scale);
+ (*ener)=WebRtcSpl_DotProductWithScale(w16ptr, w16ptr, sRange, scale);
+
+ /* For zero energy set the energy to 0 in order to avoid potential
+ problems for coming divisions */
+ if (*ener == 0) {
+ *corr = 0;
+ *ener = 1;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.h
new file mode 100644
index 0000000000..010c6a1ce5
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/comp_corr.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CompCorr.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Compute cross correlation and pitch gain for pitch prediction
+ * of last subframe at given lag.
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_CompCorr(int32_t* corr, /* (o) cross correlation */
+ int32_t* ener, /* (o) energy */
+ int16_t* buffer, /* (i) signal buffer */
+ size_t lag, /* (i) pitch lag */
+ size_t bLen, /* (i) length of buffer */
+ size_t sRange, /* (i) correlation search length */
+ int16_t scale /* (i) number of rightshifts to use */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/complexityMeasures.m b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/complexityMeasures.m
new file mode 100644
index 0000000000..4bda83622f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/complexityMeasures.m
@@ -0,0 +1,57 @@
+% % Copyright(c) 2011 The WebRTC project authors.All Rights Reserved.%
+ % Use of this source code is governed by a BSD
+ -
+ style license % that can be found in the LICENSE file in the root of the source
+ % tree.An additional intellectual property rights grant can be found
+ % in the file PATENTS.All contributing project authors may
+ % be found in the AUTHORS file in the root of the source tree.%
+
+ clear;
+pack;
+%
+% Enter the path to YOUR executable and remember to define the perprocessor
+% variable PRINT_MIPS te get the instructions printed to the screen.
+%
+command = '!iLBCtest.exe 30 speechAndBGnoise.pcm out1.bit out1.pcm tlm10_30ms.dat';
+cout=' > st.txt'; %saves to matlab variable 'st'
+eval(strcat(command,cout));
+if(length(cout)>3)
+ load st.txt
+else
+ disp('No cout file to load')
+end
+
+% initialize vector to zero
+index = find(st(1:end,1)==-1);
+indexnonzero = find(st(1:end,1)>0);
+frames = length(index)-indexnonzero(1)+1;
+start = indexnonzero(1) - 1;
+functionOrder=max(st(:,2));
+new=zeros(frames,functionOrder);
+
+for i = 1:frames,
+ for j = index(start-1+i)+1:(index(start+i)-1),
+ new(i,st(j,2)) = new(i,st(j,2)) + st(j,1);
+ end
+end
+
+result=zeros(functionOrder,3);
+for i=1:functionOrder
+ nonzeroelements = find(new(1:end,i)>0);
+ result(i,1)=i;
+
+ % Compute each function's mean complexity
+ % result(i,2)=(sum(new(nonzeroelements,i))/(length(nonzeroelements)*0.03))/1000000;
+
+ % Compute each function's maximum complexity in encoding
+ % and decoding respectively and then add it together:
+ % result(i,3)=(max(new(1:end,i))/0.03)/1000000;
+ result(i,3)=(max(new(1:size(new,1)/2,i))/0.03)/1000000 + (max(new(size(new,1)/2+1:end,i))/0.03)/1000000;
+end
+
+result
+
+% Compute maximum complexity for a single frame (enc/dec separately and together)
+maxEncComplexityInAFrame = (max(sum(new(1:size(new,1)/2,:),2))/0.03)/1000000
+maxDecComplexityInAFrame = (max(sum(new(size(new,1)/2+1:end,:),2))/0.03)/1000000
+totalComplexity = maxEncComplexityInAFrame + maxDecComplexityInAFrame
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.c
new file mode 100644
index 0000000000..22f2acb330
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ constants.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/* HP Filters {b[0] b[1] b[2] -a[1] -a[2]} */
+
+const int16_t WebRtcIlbcfix_kHpInCoefs[5] = {3798, -7596, 3798, 7807, -3733};
+const int16_t WebRtcIlbcfix_kHpOutCoefs[5] = {3849, -7699, 3849, 7918, -3833};
+
+/* Window in Q11 to window the energies of the 5 choises (3 for 20ms) in the choise for
+ the 80 sample start state
+*/
+const int16_t WebRtcIlbcfix_kStartSequenceEnrgWin[NSUB_MAX-1]= {
+ 1638, 1843, 2048, 1843, 1638
+};
+
+/* LP Filter coeffs used for downsampling */
+const int16_t WebRtcIlbcfix_kLpFiltCoefs[FILTERORDER_DS_PLUS1]= {
+ -273, 512, 1297, 1696, 1297, 512, -273
+};
+
+/* Constants used in the LPC calculations */
+
+/* Hanning LPC window (in Q15) */
+const int16_t WebRtcIlbcfix_kLpcWin[BLOCKL_MAX] = {
+ 6, 22, 50, 89, 139, 200, 272, 355, 449, 554, 669, 795,
+ 932, 1079, 1237, 1405, 1583, 1771, 1969, 2177, 2395, 2622, 2858, 3104,
+ 3359, 3622, 3894, 4175, 4464, 4761, 5066, 5379, 5699, 6026, 6361, 6702,
+ 7050, 7404, 7764, 8130, 8502, 8879, 9262, 9649, 10040, 10436, 10836, 11240,
+ 11647, 12058, 12471, 12887, 13306, 13726, 14148, 14572, 14997, 15423, 15850, 16277,
+ 16704, 17131, 17558, 17983, 18408, 18831, 19252, 19672, 20089, 20504, 20916, 21325,
+ 21730, 22132, 22530, 22924, 23314, 23698, 24078, 24452, 24821, 25185, 25542, 25893,
+ 26238, 26575, 26906, 27230, 27547, 27855, 28156, 28450, 28734, 29011, 29279, 29538,
+ 29788, 30029, 30261, 30483, 30696, 30899, 31092, 31275, 31448, 31611, 31764, 31906,
+ 32037, 32158, 32268, 32367, 32456, 32533, 32600, 32655, 32700, 32733, 32755, 32767,
+ 32767, 32755, 32733, 32700, 32655, 32600, 32533, 32456, 32367, 32268, 32158, 32037,
+ 31906, 31764, 31611, 31448, 31275, 31092, 30899, 30696, 30483, 30261, 30029, 29788,
+ 29538, 29279, 29011, 28734, 28450, 28156, 27855, 27547, 27230, 26906, 26575, 26238,
+ 25893, 25542, 25185, 24821, 24452, 24078, 23698, 23314, 22924, 22530, 22132, 21730,
+ 21325, 20916, 20504, 20089, 19672, 19252, 18831, 18408, 17983, 17558, 17131, 16704,
+ 16277, 15850, 15423, 14997, 14572, 14148, 13726, 13306, 12887, 12471, 12058, 11647,
+ 11240, 10836, 10436, 10040, 9649, 9262, 8879, 8502, 8130, 7764, 7404, 7050,
+ 6702, 6361, 6026, 5699, 5379, 5066, 4761, 4464, 4175, 3894, 3622, 3359,
+ 3104, 2858, 2622, 2395, 2177, 1969, 1771, 1583, 1405, 1237, 1079, 932,
+ 795, 669, 554, 449, 355, 272, 200, 139, 89, 50, 22, 6
+};
+
+/* Asymmetric LPC window (in Q15)*/
+const int16_t WebRtcIlbcfix_kLpcAsymWin[BLOCKL_MAX] = {
+ 2, 7, 15, 27, 42, 60, 81, 106, 135, 166, 201, 239,
+ 280, 325, 373, 424, 478, 536, 597, 661, 728, 798, 872, 949,
+ 1028, 1111, 1197, 1287, 1379, 1474, 1572, 1674, 1778, 1885, 1995, 2108,
+ 2224, 2343, 2465, 2589, 2717, 2847, 2980, 3115, 3254, 3395, 3538, 3684,
+ 3833, 3984, 4138, 4295, 4453, 4615, 4778, 4944, 5112, 5283, 5456, 5631,
+ 5808, 5987, 6169, 6352, 6538, 6725, 6915, 7106, 7300, 7495, 7692, 7891,
+ 8091, 8293, 8497, 8702, 8909, 9118, 9328, 9539, 9752, 9966, 10182, 10398,
+ 10616, 10835, 11055, 11277, 11499, 11722, 11947, 12172, 12398, 12625, 12852, 13080,
+ 13309, 13539, 13769, 14000, 14231, 14463, 14695, 14927, 15160, 15393, 15626, 15859,
+ 16092, 16326, 16559, 16792, 17026, 17259, 17492, 17725, 17957, 18189, 18421, 18653,
+ 18884, 19114, 19344, 19573, 19802, 20030, 20257, 20483, 20709, 20934, 21157, 21380,
+ 21602, 21823, 22042, 22261, 22478, 22694, 22909, 23123, 23335, 23545, 23755, 23962,
+ 24168, 24373, 24576, 24777, 24977, 25175, 25371, 25565, 25758, 25948, 26137, 26323,
+ 26508, 26690, 26871, 27049, 27225, 27399, 27571, 27740, 27907, 28072, 28234, 28394,
+ 28552, 28707, 28860, 29010, 29157, 29302, 29444, 29584, 29721, 29855, 29987, 30115,
+ 30241, 30364, 30485, 30602, 30717, 30828, 30937, 31043, 31145, 31245, 31342, 31436,
+ 31526, 31614, 31699, 31780, 31858, 31933, 32005, 32074, 32140, 32202, 32261, 32317,
+ 32370, 32420, 32466, 32509, 32549, 32585, 32618, 32648, 32675, 32698, 32718, 32734,
+ 32748, 32758, 32764, 32767, 32767, 32667, 32365, 31863, 31164, 30274, 29197, 27939,
+ 26510, 24917, 23170, 21281, 19261, 17121, 14876, 12540, 10126, 7650, 5126, 2571
+};
+
+/* Lag window for LPC (Q31) */
+const int32_t WebRtcIlbcfix_kLpcLagWin[LPC_FILTERORDER + 1]={
+ 2147483647, 2144885453, 2137754373, 2125918626, 2109459810,
+ 2088483140, 2063130336, 2033564590, 1999977009, 1962580174,
+ 1921610283};
+
+/* WebRtcIlbcfix_kLpcChirpSyntDenum vector in Q15 corresponding
+ * floating point vector {1 0.9025 0.9025^2 0.9025^3 ...}
+ */
+const int16_t WebRtcIlbcfix_kLpcChirpSyntDenum[LPC_FILTERORDER + 1] = {
+ 32767, 29573, 26690, 24087,
+ 21739, 19619, 17707, 15980,
+ 14422, 13016, 11747};
+
+/* WebRtcIlbcfix_kLpcChirpWeightDenum in Q15 corresponding to
+ * floating point vector {1 0.4222 0.4222^2... }
+ */
+const int16_t WebRtcIlbcfix_kLpcChirpWeightDenum[LPC_FILTERORDER + 1] = {
+ 32767, 13835, 5841, 2466, 1041, 440,
+ 186, 78, 33, 14, 6};
+
+/* LSF quantization Q13 domain */
+const int16_t WebRtcIlbcfix_kLsfCb[64 * 3 + 128 * 3 + 128 * 4] = {
+ 1273, 2238, 3696,
+ 3199, 5309, 8209,
+ 3606, 5671, 7829,
+ 2815, 5262, 8778,
+ 2608, 4027, 5493,
+ 1582, 3076, 5945,
+ 2983, 4181, 5396,
+ 2437, 4322, 6902,
+ 1861, 2998, 4613,
+ 2007, 3250, 5214,
+ 1388, 2459, 4262,
+ 2563, 3805, 5269,
+ 2036, 3522, 5129,
+ 1935, 4025, 6694,
+ 2744, 5121, 7338,
+ 2810, 4248, 5723,
+ 3054, 5405, 7745,
+ 1449, 2593, 4763,
+ 3411, 5128, 6596,
+ 2484, 4659, 7496,
+ 1668, 2879, 4818,
+ 1812, 3072, 5036,
+ 1638, 2649, 3900,
+ 2464, 3550, 4644,
+ 1853, 2900, 4158,
+ 2458, 4163, 5830,
+ 2556, 4036, 6254,
+ 2703, 4432, 6519,
+ 3062, 4953, 7609,
+ 1725, 3703, 6187,
+ 2221, 3877, 5427,
+ 2339, 3579, 5197,
+ 2021, 4633, 7037,
+ 2216, 3328, 4535,
+ 2961, 4739, 6667,
+ 2807, 3955, 5099,
+ 2788, 4501, 6088,
+ 1642, 2755, 4431,
+ 3341, 5282, 7333,
+ 2414, 3726, 5727,
+ 1582, 2822, 5269,
+ 2259, 3447, 4905,
+ 3117, 4986, 7054,
+ 1825, 3491, 5542,
+ 3338, 5736, 8627,
+ 1789, 3090, 5488,
+ 2566, 3720, 4923,
+ 2846, 4682, 7161,
+ 1950, 3321, 5976,
+ 1834, 3383, 6734,
+ 3238, 4769, 6094,
+ 2031, 3978, 5903,
+ 1877, 4068, 7436,
+ 2131, 4644, 8296,
+ 2764, 5010, 8013,
+ 2194, 3667, 6302,
+ 2053, 3127, 4342,
+ 3523, 6595, 10010,
+ 3134, 4457, 5748,
+ 3142, 5819, 9414,
+ 2223, 4334, 6353,
+ 2022, 3224, 4822,
+ 2186, 3458, 5544,
+ 2552, 4757, 6870,
+ 10905, 12917, 14578,
+ 9503, 11485, 14485,
+ 9518, 12494, 14052,
+ 6222, 7487, 9174,
+ 7759, 9186, 10506,
+ 8315, 12755, 14786,
+ 9609, 11486, 13866,
+ 8909, 12077, 13643,
+ 7369, 9054, 11520,
+ 9408, 12163, 14715,
+ 6436, 9911, 12843,
+ 7109, 9556, 11884,
+ 7557, 10075, 11640,
+ 6482, 9202, 11547,
+ 6463, 7914, 10980,
+ 8611, 10427, 12752,
+ 7101, 9676, 12606,
+ 7428, 11252, 13172,
+ 10197, 12955, 15842,
+ 7487, 10955, 12613,
+ 5575, 7858, 13621,
+ 7268, 11719, 14752,
+ 7476, 11744, 13795,
+ 7049, 8686, 11922,
+ 8234, 11314, 13983,
+ 6560, 11173, 14984,
+ 6405, 9211, 12337,
+ 8222, 12054, 13801,
+ 8039, 10728, 13255,
+ 10066, 12733, 14389,
+ 6016, 7338, 10040,
+ 6896, 8648, 10234,
+ 7538, 9170, 12175,
+ 7327, 12608, 14983,
+ 10516, 12643, 15223,
+ 5538, 7644, 12213,
+ 6728, 12221, 14253,
+ 7563, 9377, 12948,
+ 8661, 11023, 13401,
+ 7280, 8806, 11085,
+ 7723, 9793, 12333,
+ 12225, 14648, 16709,
+ 8768, 13389, 15245,
+ 10267, 12197, 13812,
+ 5301, 7078, 11484,
+ 7100, 10280, 11906,
+ 8716, 12555, 14183,
+ 9567, 12464, 15434,
+ 7832, 12305, 14300,
+ 7608, 10556, 12121,
+ 8913, 11311, 12868,
+ 7414, 9722, 11239,
+ 8666, 11641, 13250,
+ 9079, 10752, 12300,
+ 8024, 11608, 13306,
+ 10453, 13607, 16449,
+ 8135, 9573, 10909,
+ 6375, 7741, 10125,
+ 10025, 12217, 14874,
+ 6985, 11063, 14109,
+ 9296, 13051, 14642,
+ 8613, 10975, 12542,
+ 6583, 10414, 13534,
+ 6191, 9368, 13430,
+ 5742, 6859, 9260,
+ 7723, 9813, 13679,
+ 8137, 11291, 12833,
+ 6562, 8973, 10641,
+ 6062, 8462, 11335,
+ 6928, 8784, 12647,
+ 7501, 8784, 10031,
+ 8372, 10045, 12135,
+ 8191, 9864, 12746,
+ 5917, 7487, 10979,
+ 5516, 6848, 10318,
+ 6819, 9899, 11421,
+ 7882, 12912, 15670,
+ 9558, 11230, 12753,
+ 7752, 9327, 11472,
+ 8479, 9980, 11358,
+ 11418, 14072, 16386,
+ 7968, 10330, 14423,
+ 8423, 10555, 12162,
+ 6337, 10306, 14391,
+ 8850, 10879, 14276,
+ 6750, 11885, 15710,
+ 7037, 8328, 9764,
+ 6914, 9266, 13476,
+ 9746, 13949, 15519,
+ 11032, 14444, 16925,
+ 8032, 10271, 11810,
+ 10962, 13451, 15833,
+ 10021, 11667, 13324,
+ 6273, 8226, 12936,
+ 8543, 10397, 13496,
+ 7936, 10302, 12745,
+ 6769, 8138, 10446,
+ 6081, 7786, 11719,
+ 8637, 11795, 14975,
+ 8790, 10336, 11812,
+ 7040, 8490, 10771,
+ 7338, 10381, 13153,
+ 6598, 7888, 9358,
+ 6518, 8237, 12030,
+ 9055, 10763, 12983,
+ 6490, 10009, 12007,
+ 9589, 12023, 13632,
+ 6867, 9447, 10995,
+ 7930, 9816, 11397,
+ 10241, 13300, 14939,
+ 5830, 8670, 12387,
+ 9870, 11915, 14247,
+ 9318, 11647, 13272,
+ 6721, 10836, 12929,
+ 6543, 8233, 9944,
+ 8034, 10854, 12394,
+ 9112, 11787, 14218,
+ 9302, 11114, 13400,
+ 9022, 11366, 13816,
+ 6962, 10461, 12480,
+ 11288, 13333, 15222,
+ 7249, 8974, 10547,
+ 10566, 12336, 14390,
+ 6697, 11339, 13521,
+ 11851, 13944, 15826,
+ 6847, 8381, 11349,
+ 7509, 9331, 10939,
+ 8029, 9618, 11909,
+ 13973, 17644, 19647, 22474,
+ 14722, 16522, 20035, 22134,
+ 16305, 18179, 21106, 23048,
+ 15150, 17948, 21394, 23225,
+ 13582, 15191, 17687, 22333,
+ 11778, 15546, 18458, 21753,
+ 16619, 18410, 20827, 23559,
+ 14229, 15746, 17907, 22474,
+ 12465, 15327, 20700, 22831,
+ 15085, 16799, 20182, 23410,
+ 13026, 16935, 19890, 22892,
+ 14310, 16854, 19007, 22944,
+ 14210, 15897, 18891, 23154,
+ 14633, 18059, 20132, 22899,
+ 15246, 17781, 19780, 22640,
+ 16396, 18904, 20912, 23035,
+ 14618, 17401, 19510, 21672,
+ 15473, 17497, 19813, 23439,
+ 18851, 20736, 22323, 23864,
+ 15055, 16804, 18530, 20916,
+ 16490, 18196, 19990, 21939,
+ 11711, 15223, 21154, 23312,
+ 13294, 15546, 19393, 21472,
+ 12956, 16060, 20610, 22417,
+ 11628, 15843, 19617, 22501,
+ 14106, 16872, 19839, 22689,
+ 15655, 18192, 20161, 22452,
+ 12953, 15244, 20619, 23549,
+ 15322, 17193, 19926, 21762,
+ 16873, 18676, 20444, 22359,
+ 14874, 17871, 20083, 21959,
+ 11534, 14486, 19194, 21857,
+ 17766, 19617, 21338, 23178,
+ 13404, 15284, 19080, 23136,
+ 15392, 17527, 19470, 21953,
+ 14462, 16153, 17985, 21192,
+ 17734, 19750, 21903, 23783,
+ 16973, 19096, 21675, 23815,
+ 16597, 18936, 21257, 23461,
+ 15966, 17865, 20602, 22920,
+ 15416, 17456, 20301, 22972,
+ 18335, 20093, 21732, 23497,
+ 15548, 17217, 20679, 23594,
+ 15208, 16995, 20816, 22870,
+ 13890, 18015, 20531, 22468,
+ 13211, 15377, 19951, 22388,
+ 12852, 14635, 17978, 22680,
+ 16002, 17732, 20373, 23544,
+ 11373, 14134, 19534, 22707,
+ 17329, 19151, 21241, 23462,
+ 15612, 17296, 19362, 22850,
+ 15422, 19104, 21285, 23164,
+ 13792, 17111, 19349, 21370,
+ 15352, 17876, 20776, 22667,
+ 15253, 16961, 18921, 22123,
+ 14108, 17264, 20294, 23246,
+ 15785, 17897, 20010, 21822,
+ 17399, 19147, 20915, 22753,
+ 13010, 15659, 18127, 20840,
+ 16826, 19422, 22218, 24084,
+ 18108, 20641, 22695, 24237,
+ 18018, 20273, 22268, 23920,
+ 16057, 17821, 21365, 23665,
+ 16005, 17901, 19892, 23016,
+ 13232, 16683, 21107, 23221,
+ 13280, 16615, 19915, 21829,
+ 14950, 18575, 20599, 22511,
+ 16337, 18261, 20277, 23216,
+ 14306, 16477, 21203, 23158,
+ 12803, 17498, 20248, 22014,
+ 14327, 17068, 20160, 22006,
+ 14402, 17461, 21599, 23688,
+ 16968, 18834, 20896, 23055,
+ 15070, 17157, 20451, 22315,
+ 15419, 17107, 21601, 23946,
+ 16039, 17639, 19533, 21424,
+ 16326, 19261, 21745, 23673,
+ 16489, 18534, 21658, 23782,
+ 16594, 18471, 20549, 22807,
+ 18973, 21212, 22890, 24278,
+ 14264, 18674, 21123, 23071,
+ 15117, 16841, 19239, 23118,
+ 13762, 15782, 20478, 23230,
+ 14111, 15949, 20058, 22354,
+ 14990, 16738, 21139, 23492,
+ 13735, 16971, 19026, 22158,
+ 14676, 17314, 20232, 22807,
+ 16196, 18146, 20459, 22339,
+ 14747, 17258, 19315, 22437,
+ 14973, 17778, 20692, 23367,
+ 15715, 17472, 20385, 22349,
+ 15702, 18228, 20829, 23410,
+ 14428, 16188, 20541, 23630,
+ 16824, 19394, 21365, 23246,
+ 13069, 16392, 18900, 21121,
+ 12047, 16640, 19463, 21689,
+ 14757, 17433, 19659, 23125,
+ 15185, 16930, 19900, 22540,
+ 16026, 17725, 19618, 22399,
+ 16086, 18643, 21179, 23472,
+ 15462, 17248, 19102, 21196,
+ 17368, 20016, 22396, 24096,
+ 12340, 14475, 19665, 23362,
+ 13636, 16229, 19462, 22728,
+ 14096, 16211, 19591, 21635,
+ 12152, 14867, 19943, 22301,
+ 14492, 17503, 21002, 22728,
+ 14834, 16788, 19447, 21411,
+ 14650, 16433, 19326, 22308,
+ 14624, 16328, 19659, 23204,
+ 13888, 16572, 20665, 22488,
+ 12977, 16102, 18841, 22246,
+ 15523, 18431, 21757, 23738,
+ 14095, 16349, 18837, 20947,
+ 13266, 17809, 21088, 22839,
+ 15427, 18190, 20270, 23143,
+ 11859, 16753, 20935, 22486,
+ 12310, 17667, 21736, 23319,
+ 14021, 15926, 18702, 22002,
+ 12286, 15299, 19178, 21126,
+ 15703, 17491, 21039, 23151,
+ 12272, 14018, 18213, 22570,
+ 14817, 16364, 18485, 22598,
+ 17109, 19683, 21851, 23677,
+ 12657, 14903, 19039, 22061,
+ 14713, 16487, 20527, 22814,
+ 14635, 16726, 18763, 21715,
+ 15878, 18550, 20718, 22906
+};
+
+const int16_t WebRtcIlbcfix_kLsfDimCb[LSF_NSPLIT] = {3, 3, 4};
+const int16_t WebRtcIlbcfix_kLsfSizeCb[LSF_NSPLIT] = {64,128,128};
+
+const int16_t WebRtcIlbcfix_kLsfMean[LPC_FILTERORDER] = {
+ 2308, 3652, 5434, 7885,
+ 10255, 12559, 15160, 17513,
+ 20328, 22752};
+
+const int16_t WebRtcIlbcfix_kLspMean[LPC_FILTERORDER] = {
+ 31476, 29565, 25819, 18725, 10276,
+ 1236, -9049, -17600, -25884, -30618
+};
+
+/* Q14 */
+const int16_t WebRtcIlbcfix_kLsfWeight20ms[4] = {12288, 8192, 4096, 0};
+const int16_t WebRtcIlbcfix_kLsfWeight30ms[6] = {8192, 16384, 10923, 5461, 0, 0};
+
+/*
+ cos(x) in Q15
+ WebRtcIlbcfix_kCos[i] = cos(pi*i/64.0)
+ used in WebRtcIlbcfix_Lsp2Lsf()
+*/
+
+const int16_t WebRtcIlbcfix_kCos[64] = {
+ 32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
+ 30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
+ 23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
+ 12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
+ 0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
+ -12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
+ -23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
+ -30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729
+};
+
+/*
+ Derivative in Q19, used to interpolate between the
+ WebRtcIlbcfix_kCos[] values to get a more exact y = cos(x)
+*/
+const int16_t WebRtcIlbcfix_kCosDerivative[64] = {
+ -632, -1893, -3150, -4399, -5638, -6863, -8072, -9261,
+ -10428, -11570, -12684, -13767, -14817, -15832, -16808, -17744,
+ -18637, -19486, -20287, -21039, -21741, -22390, -22986, -23526,
+ -24009, -24435, -24801, -25108, -25354, -25540, -25664, -25726,
+ -25726, -25664, -25540, -25354, -25108, -24801, -24435, -24009,
+ -23526, -22986, -22390, -21741, -21039, -20287, -19486, -18637,
+ -17744, -16808, -15832, -14817, -13767, -12684, -11570, -10428,
+ -9261, -8072, -6863, -5638, -4399, -3150, -1893, -632};
+
+/*
+ Table in Q15, used for a2lsf conversion
+ WebRtcIlbcfix_kCosGrid[i] = cos((2*pi*i)/(float)(2*COS_GRID_POINTS));
+*/
+
+const int16_t WebRtcIlbcfix_kCosGrid[COS_GRID_POINTS + 1] = {
+ 32760, 32723, 32588, 32364, 32051, 31651, 31164, 30591,
+ 29935, 29196, 28377, 27481, 26509, 25465, 24351, 23170,
+ 21926, 20621, 19260, 17846, 16384, 14876, 13327, 11743,
+ 10125, 8480, 6812, 5126, 3425, 1714, 0, -1714, -3425,
+ -5126, -6812, -8480, -10125, -11743, -13327, -14876,
+ -16384, -17846, -19260, -20621, -21926, -23170, -24351,
+ -25465, -26509, -27481, -28377, -29196, -29935, -30591,
+ -31164, -31651, -32051, -32364, -32588, -32723, -32760
+};
+
+/*
+ Derivative of y = acos(x) in Q12
+ used in WebRtcIlbcfix_Lsp2Lsf()
+*/
+
+const int16_t WebRtcIlbcfix_kAcosDerivative[64] = {
+ -26887, -8812, -5323, -3813, -2979, -2444, -2081, -1811,
+ -1608, -1450, -1322, -1219, -1132, -1059, -998, -946,
+ -901, -861, -827, -797, -772, -750, -730, -713,
+ -699, -687, -677, -668, -662, -657, -654, -652,
+ -652, -654, -657, -662, -668, -677, -687, -699,
+ -713, -730, -750, -772, -797, -827, -861, -901,
+ -946, -998, -1059, -1132, -1219, -1322, -1450, -1608,
+ -1811, -2081, -2444, -2979, -3813, -5323, -8812, -26887
+};
+
+
+/* Tables for quantization of start state */
+
+/* State quantization tables */
+const int16_t WebRtcIlbcfix_kStateSq3[8] = { /* Values in Q13 */
+ -30473, -17838, -9257, -2537,
+ 3639, 10893, 19958, 32636
+};
+
+/* This table defines the limits for the selection of the freqg
+ less or equal than value 0 => index = 0
+ less or equal than value k => index = k
+*/
+const int32_t WebRtcIlbcfix_kChooseFrgQuant[64] = {
+ 118, 163, 222, 305, 425, 604,
+ 851, 1174, 1617, 2222, 3080, 4191,
+ 5525, 7215, 9193, 11540, 14397, 17604,
+ 21204, 25209, 29863, 35720, 42531, 50375,
+ 59162, 68845, 80108, 93754, 110326, 129488,
+ 150654, 174328, 201962, 233195, 267843, 308239,
+ 354503, 405988, 464251, 531550, 608652, 697516,
+ 802526, 928793, 1080145, 1258120, 1481106, 1760881,
+ 2111111, 2546619, 3078825, 3748642, 4563142, 5573115,
+ 6887601, 8582108, 10797296, 14014513, 18625760, 25529599,
+ 37302935, 58819185, 109782723, WEBRTC_SPL_WORD32_MAX
+};
+
+const int16_t WebRtcIlbcfix_kScale[64] = {
+ /* Values in Q16 */
+ 29485, 25003, 21345, 18316, 15578, 13128, 10973, 9310, 7955,
+ 6762, 5789, 4877, 4255, 3699, 3258, 2904, 2595, 2328,
+ 2123, 1932, 1785, 1631, 1493, 1370, 1260, 1167, 1083,
+ /* Values in Q21 */
+ 32081, 29611, 27262, 25229, 23432, 21803, 20226, 18883, 17609,
+ 16408, 15311, 14327, 13390, 12513, 11693, 10919, 10163, 9435,
+ 8739, 8100, 7424, 6813, 6192, 5648, 5122, 4639, 4207, 3798,
+ 3404, 3048, 2706, 2348, 2036, 1713, 1393, 1087, 747
+};
+
+/*frgq in fixpoint, but already computed like this:
+ for(i=0; i<64; i++){
+ a = (pow(10,frgq[i])/4.5);
+ WebRtcIlbcfix_kFrgQuantMod[i] = round(a);
+ }
+
+ Value 0 :36 in Q8
+ 37:58 in Q5
+ 59:63 in Q3
+*/
+const int16_t WebRtcIlbcfix_kFrgQuantMod[64] = {
+ /* First 37 values in Q8 */
+ 569, 671, 786, 916, 1077, 1278,
+ 1529, 1802, 2109, 2481, 2898, 3440,
+ 3943, 4535, 5149, 5778, 6464, 7208,
+ 7904, 8682, 9397, 10285, 11240, 12246,
+ 13313, 14382, 15492, 16735, 18131, 19693,
+ 21280, 22912, 24624, 26544, 28432, 30488,
+ 32720,
+ /* 22 values in Q5 */
+ 4383, 4684, 5012, 5363, 5739, 6146,
+ 6603, 7113, 7679, 8285, 9040, 9850,
+ 10838, 11882, 13103, 14467, 15950, 17669,
+ 19712, 22016, 24800, 28576,
+ /* 5 values in Q3 */
+ 8240, 9792, 12040, 15440, 22472
+};
+
+/* Constants for codebook search and creation */
+
+/* Expansion filter to get additional cb section.
+ * Q12 and reversed compared to flp
+ */
+const int16_t WebRtcIlbcfix_kCbFiltersRev[CB_FILTERLEN]={
+ -140, 446, -755, 3302, 2922, -590, 343, -138};
+
+/* Weighting coefficients for short lags.
+ * [0.2 0.4 0.6 0.8] in Q15 */
+const int16_t WebRtcIlbcfix_kAlpha[4]={
+ 6554, 13107, 19661, 26214};
+
+/* Ranges for search and filters at different subframes */
+
+const size_t WebRtcIlbcfix_kSearchRange[5][CB_NSTAGES]={
+ {58,58,58}, {108,44,44}, {108,108,108}, {108,108,108}, {108,108,108}};
+
+const size_t WebRtcIlbcfix_kFilterRange[5]={63, 85, 125, 147, 147};
+
+/* Gain Quantization for the codebook gains of the 3 stages */
+
+/* Q14 (one extra value (max int16_t) to simplify for the search) */
+const int16_t WebRtcIlbcfix_kGainSq3[9]={
+ -16384, -10813, -5407, 0, 4096, 8192,
+ 12288, 16384, 32767};
+
+/* Q14 (one extra value (max int16_t) to simplify for the search) */
+const int16_t WebRtcIlbcfix_kGainSq4[17]={
+ -17203, -14746, -12288, -9830, -7373, -4915,
+ -2458, 0, 2458, 4915, 7373, 9830,
+ 12288, 14746, 17203, 19661, 32767};
+
+/* Q14 (one extra value (max int16_t) to simplify for the search) */
+const int16_t WebRtcIlbcfix_kGainSq5[33]={
+ 614, 1229, 1843, 2458, 3072, 3686,
+ 4301, 4915, 5530, 6144, 6758, 7373,
+ 7987, 8602, 9216, 9830, 10445, 11059,
+ 11674, 12288, 12902, 13517, 14131, 14746,
+ 15360, 15974, 16589, 17203, 17818, 18432,
+ 19046, 19661, 32767};
+
+/* Q14 gain_sq5Tbl squared in Q14 */
+const int16_t WebRtcIlbcfix_kGainSq5Sq[32] = {
+ 23, 92, 207, 368, 576, 829,
+ 1129, 1474, 1866, 2304, 2787, 3317,
+ 3893, 4516, 5184, 5897, 6658, 7464,
+ 8318, 9216, 10160, 11151, 12187, 13271,
+ 14400, 15574, 16796, 18062, 19377, 20736,
+ 22140, 23593
+};
+
+const int16_t* const WebRtcIlbcfix_kGain[3] =
+{WebRtcIlbcfix_kGainSq5, WebRtcIlbcfix_kGainSq4, WebRtcIlbcfix_kGainSq3};
+
+
+/* Tables for the Enhancer, using upsamling factor 4 (ENH_UPS0 = 4) */
+
+const int16_t WebRtcIlbcfix_kEnhPolyPhaser[ENH_UPS0][ENH_FLO_MULT2_PLUS1]={
+ {0, 0, 0, 4096, 0, 0, 0},
+ {64, -315, 1181, 3531, -436, 77, -64},
+ {97, -509, 2464, 2464, -509, 97, -97},
+ {77, -436, 3531, 1181, -315, 64, -77}
+};
+
+const int16_t WebRtcIlbcfix_kEnhWt[3] = {
+ 4800, 16384, 27968 /* Q16 */
+};
+
+const size_t WebRtcIlbcfix_kEnhPlocs[ENH_NBLOCKS_TOT] = {
+ 160, 480, 800, 1120, 1440, 1760, 2080, 2400 /* Q(-2) */
+};
+
+/* PLC table */
+
+const int16_t WebRtcIlbcfix_kPlcPerSqr[6] = { /* Grid points for square of periodiciy in Q15 */
+ 839, 1343, 2048, 2998, 4247, 5849
+};
+
+const int16_t WebRtcIlbcfix_kPlcPitchFact[6] = { /* Value of y=(x^4-0.4)/(0.7-0.4) in grid points in Q15 */
+ 0, 5462, 10922, 16384, 21846, 27306
+};
+
+const int16_t WebRtcIlbcfix_kPlcPfSlope[6] = { /* Slope of y=(x^4-0.4)/(0.7-0.4) in Q11 */
+ 26667, 18729, 13653, 10258, 7901, 6214
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.h
new file mode 100644
index 0000000000..a8645c00db
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/constants.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ constants.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/* high pass filters */
+
+extern const int16_t WebRtcIlbcfix_kHpInCoefs[];
+extern const int16_t WebRtcIlbcfix_kHpOutCoefs[];
+
+/* Window for start state decision */
+extern const int16_t WebRtcIlbcfix_kStartSequenceEnrgWin[];
+
+/* low pass filter used for downsampling */
+extern const int16_t WebRtcIlbcfix_kLpFiltCoefs[];
+
+/* LPC analysis and quantization */
+
+extern const int16_t WebRtcIlbcfix_kLpcWin[];
+extern const int16_t WebRtcIlbcfix_kLpcAsymWin[];
+extern const int32_t WebRtcIlbcfix_kLpcLagWin[];
+extern const int16_t WebRtcIlbcfix_kLpcChirpSyntDenum[];
+extern const int16_t WebRtcIlbcfix_kLpcChirpWeightDenum[];
+extern const int16_t WebRtcIlbcfix_kLsfDimCb[];
+extern const int16_t WebRtcIlbcfix_kLsfSizeCb[];
+extern const int16_t WebRtcIlbcfix_kLsfCb[];
+extern const int16_t WebRtcIlbcfix_kLsfWeight20ms[];
+extern const int16_t WebRtcIlbcfix_kLsfWeight30ms[];
+extern const int16_t WebRtcIlbcfix_kLsfMean[];
+extern const int16_t WebRtcIlbcfix_kLspMean[];
+extern const int16_t WebRtcIlbcfix_kCos[];
+extern const int16_t WebRtcIlbcfix_kCosDerivative[];
+extern const int16_t WebRtcIlbcfix_kCosGrid[];
+extern const int16_t WebRtcIlbcfix_kAcosDerivative[];
+
+/* state quantization tables */
+
+extern const int16_t WebRtcIlbcfix_kStateSq3[];
+extern const int32_t WebRtcIlbcfix_kChooseFrgQuant[];
+extern const int16_t WebRtcIlbcfix_kScale[];
+extern const int16_t WebRtcIlbcfix_kFrgQuantMod[];
+
+/* Ranges for search and filters at different subframes */
+
+extern const size_t WebRtcIlbcfix_kSearchRange[5][CB_NSTAGES];
+extern const size_t WebRtcIlbcfix_kFilterRange[];
+
+/* gain quantization tables */
+
+extern const int16_t WebRtcIlbcfix_kGainSq3[];
+extern const int16_t WebRtcIlbcfix_kGainSq4[];
+extern const int16_t WebRtcIlbcfix_kGainSq5[];
+extern const int16_t WebRtcIlbcfix_kGainSq5Sq[];
+extern const int16_t* const WebRtcIlbcfix_kGain[];
+
+/* adaptive codebook definitions */
+
+extern const int16_t WebRtcIlbcfix_kCbFiltersRev[];
+extern const int16_t WebRtcIlbcfix_kAlpha[];
+
+/* enhancer definitions */
+
+extern const int16_t WebRtcIlbcfix_kEnhPolyPhaser[ENH_UPS0]
+ [ENH_FLO_MULT2_PLUS1];
+extern const int16_t WebRtcIlbcfix_kEnhWt[];
+extern const size_t WebRtcIlbcfix_kEnhPlocs[];
+
+/* PLC tables */
+
+extern const int16_t WebRtcIlbcfix_kPlcPerSqr[];
+extern const int16_t WebRtcIlbcfix_kPlcPitchFact[];
+extern const int16_t WebRtcIlbcfix_kPlcPfSlope[];
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
new file mode 100644
index 0000000000..7e21faee6c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CreateAugmentedVec.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/sanitizer.h"
+
+/*----------------------------------------------------------------*
+ * Recreate a specific codebook vector from the augmented part.
+ *
+ *----------------------------------------------------------------*/
+
+void WebRtcIlbcfix_CreateAugmentedVec(
+ size_t index, /* (i) Index for the augmented vector to be
+ created */
+ const int16_t* buffer, /* (i) Pointer to the end of the codebook memory
+ that is used for creation of the augmented
+ codebook */
+ int16_t* cbVec) { /* (o) The constructed codebook vector */
+ size_t ilow;
+ const int16_t *ppo, *ppi;
+ int16_t cbVecTmp[4];
+ /* Interpolation starts 4 elements before cbVec+index, but must not start
+ outside `cbVec`; clamping interp_len to stay within `cbVec`.
+ */
+ size_t interp_len = WEBRTC_SPL_MIN(index, 4);
+
+ rtc_MsanCheckInitialized(buffer - index - interp_len, sizeof(buffer[0]),
+ index + interp_len);
+
+ ilow = index - interp_len;
+
+ /* copy the first noninterpolated part */
+ ppo = buffer-index;
+ WEBRTC_SPL_MEMCPY_W16(cbVec, ppo, index);
+
+ /* interpolation */
+ ppo = buffer - interp_len;
+ ppi = buffer - index - interp_len;
+
+ /* perform cbVec[ilow+k] = ((ppi[k]*alphaTbl[k])>>15) +
+ ((ppo[k]*alphaTbl[interp_len-1-k])>>15);
+ for k = 0..interp_len-1
+ */
+ WebRtcSpl_ElementwiseVectorMult(&cbVec[ilow], ppi, WebRtcIlbcfix_kAlpha,
+ interp_len, 15);
+ WebRtcSpl_ReverseOrderMultArrayElements(
+ cbVecTmp, ppo, &WebRtcIlbcfix_kAlpha[interp_len - 1], interp_len, 15);
+ WebRtcSpl_AddVectorsAndShift(&cbVec[ilow], &cbVec[ilow], cbVecTmp, interp_len,
+ 0);
+
+ /* copy the second noninterpolated part */
+ ppo = buffer - index;
+ /* `tempbuff2` is declared in WebRtcIlbcfix_GetCbVec and is SUBL+5 elements
+ long. `buffer` points one element past the end of that vector, i.e., at
+ tempbuff2+SUBL+5. Since ppo=buffer-index, we cannot read any more than
+ `index` elements from `ppo`.
+
+ `cbVec` is declared to be SUBL elements long in WebRtcIlbcfix_CbConstruct.
+ Therefore, we can only write SUBL-index elements to cbVec+index.
+
+ These two conditions limit the number of elements to copy.
+ */
+ WEBRTC_SPL_MEMCPY_W16(cbVec+index, ppo, WEBRTC_SPL_MIN(SUBL-index, index));
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h
new file mode 100644
index 0000000000..d7e5be1c2f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_CreateAugmentedVec.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Recreate a specific codebook vector from the augmented part.
+ *
+ *----------------------------------------------------------------*/
+
+void WebRtcIlbcfix_CreateAugmentedVec(
+ size_t index, /* (i) Index for the augmented vector to be
+ created */
+ const int16_t* buffer, /* (i) Pointer to the end of the codebook memory
+ that is used for creation of the augmented
+ codebook */
+ int16_t* cbVec); /* (o) The construced codebook vector */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.c
new file mode 100644
index 0000000000..d7621d5b65
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Decode.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/decode.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/decode_residual.h"
+#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/do_plc.h"
+#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
+#include "modules/audio_coding/codecs/ilbc/hp_output.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
+#include "modules/audio_coding/codecs/ilbc/init_decode.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
+#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+#include "rtc_base/system/arch.h"
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+#include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
+#endif
+
+/*----------------------------------------------------------------*
+ * main decoder function
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_DecodeImpl(
+ int16_t *decblock, /* (o) decoded signal block */
+ const uint16_t *bytes, /* (i) encoded signal bits */
+ IlbcDecoder *iLBCdec_inst, /* (i/o) the decoder state
+ structure */
+ int16_t mode /* (i) 0: bad packet, PLC,
+ 1: normal */
+ ) {
+ const int old_mode = iLBCdec_inst->mode;
+ const int old_use_enhancer = iLBCdec_inst->use_enhancer;
+
+ size_t i;
+ int16_t order_plus_one;
+
+ int16_t last_bit;
+ int16_t *data;
+ /* Stack based */
+ int16_t decresidual[BLOCKL_MAX];
+ int16_t PLCresidual[BLOCKL_MAX + LPC_FILTERORDER];
+ int16_t syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)];
+ int16_t PLClpc[LPC_FILTERORDER + 1];
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ uint16_t swapped[NO_OF_WORDS_30MS];
+#endif
+ iLBC_bits *iLBCbits_inst = (iLBC_bits*)PLCresidual;
+
+ /* Reuse some buffers that are non overlapping in order to save stack memory */
+ data = &PLCresidual[LPC_FILTERORDER];
+
+ if (mode) { /* the data are good */
+
+ /* decode data */
+
+ /* Unpacketize bits into parameters */
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ WebRtcIlbcfix_SwapBytes(bytes, iLBCdec_inst->no_of_words, swapped);
+ last_bit = WebRtcIlbcfix_UnpackBits(swapped, iLBCbits_inst, iLBCdec_inst->mode);
+#else
+ last_bit = WebRtcIlbcfix_UnpackBits(bytes, iLBCbits_inst, iLBCdec_inst->mode);
+#endif
+
+ /* Check for bit errors */
+ if (iLBCbits_inst->startIdx<1)
+ mode = 0;
+ if ((iLBCdec_inst->mode==20) && (iLBCbits_inst->startIdx>3))
+ mode = 0;
+ if ((iLBCdec_inst->mode==30) && (iLBCbits_inst->startIdx>5))
+ mode = 0;
+ if (last_bit==1)
+ mode = 0;
+
+ if (mode) { /* No bit errors was detected, continue decoding */
+ /* Stack based */
+ int16_t lsfdeq[LPC_FILTERORDER*LPC_N_MAX];
+ int16_t weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
+
+ /* adjust index */
+ WebRtcIlbcfix_IndexConvDec(iLBCbits_inst->cb_index);
+
+ /* decode the lsf */
+ WebRtcIlbcfix_SimpleLsfDeQ(lsfdeq, (int16_t*)(iLBCbits_inst->lsf), iLBCdec_inst->lpc_n);
+ WebRtcIlbcfix_LsfCheck(lsfdeq, LPC_FILTERORDER, iLBCdec_inst->lpc_n);
+ WebRtcIlbcfix_DecoderInterpolateLsp(syntdenum, weightdenum,
+ lsfdeq, LPC_FILTERORDER, iLBCdec_inst);
+
+ /* Decode the residual using the cb and gain indexes */
+ if (!WebRtcIlbcfix_DecodeResidual(iLBCdec_inst, iLBCbits_inst,
+ decresidual, syntdenum))
+ goto error;
+
+ /* preparing the plc for a future loss! */
+ WebRtcIlbcfix_DoThePlc(
+ PLCresidual, PLClpc, 0, decresidual,
+ syntdenum + (LPC_FILTERORDER + 1) * (iLBCdec_inst->nsub - 1),
+ iLBCdec_inst->last_lag, iLBCdec_inst);
+
+ /* Use the output from doThePLC */
+ WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
+ }
+
+ }
+
+ if (mode == 0) {
+ /* the data is bad (either a PLC call
+ * was made or a bit error was detected)
+ */
+
+ /* packet loss conceal */
+
+ WebRtcIlbcfix_DoThePlc(PLCresidual, PLClpc, 1, decresidual, syntdenum,
+ iLBCdec_inst->last_lag, iLBCdec_inst);
+
+ WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
+
+ order_plus_one = LPC_FILTERORDER + 1;
+
+ for (i = 0; i < iLBCdec_inst->nsub; i++) {
+ WEBRTC_SPL_MEMCPY_W16(syntdenum+(i*order_plus_one),
+ PLClpc, order_plus_one);
+ }
+ }
+
+ if ((*iLBCdec_inst).use_enhancer == 1) { /* Enhancer activated */
+
+ /* Update the filter and filter coefficients if there was a packet loss */
+ if (iLBCdec_inst->prev_enh_pl==2) {
+ for (i=0;i<iLBCdec_inst->nsub;i++) {
+ WEBRTC_SPL_MEMCPY_W16(&(iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)]),
+ syntdenum, (LPC_FILTERORDER+1));
+ }
+ }
+
+ /* post filtering */
+ (*iLBCdec_inst).last_lag =
+ WebRtcIlbcfix_EnhancerInterface(data, decresidual, iLBCdec_inst);
+
+ /* synthesis filtering */
+
+ /* Set up the filter state */
+ WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
+
+ if (iLBCdec_inst->mode==20) {
+ /* Enhancer has 40 samples delay */
+ i=0;
+ WebRtcSpl_FilterARFastQ12(
+ data, data,
+ iLBCdec_inst->old_syntdenum + (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1),
+ LPC_FILTERORDER+1, SUBL);
+
+ for (i=1; i < iLBCdec_inst->nsub; i++) {
+ WebRtcSpl_FilterARFastQ12(
+ data+i*SUBL, data+i*SUBL,
+ syntdenum+(i-1)*(LPC_FILTERORDER+1),
+ LPC_FILTERORDER+1, SUBL);
+ }
+
+ } else if (iLBCdec_inst->mode==30) {
+ /* Enhancer has 80 samples delay */
+ for (i=0; i < 2; i++) {
+ WebRtcSpl_FilterARFastQ12(
+ data+i*SUBL, data+i*SUBL,
+ iLBCdec_inst->old_syntdenum + (i+4)*(LPC_FILTERORDER+1),
+ LPC_FILTERORDER+1, SUBL);
+ }
+ for (i=2; i < iLBCdec_inst->nsub; i++) {
+ WebRtcSpl_FilterARFastQ12(
+ data+i*SUBL, data+i*SUBL,
+ syntdenum+(i-2)*(LPC_FILTERORDER+1),
+ LPC_FILTERORDER+1, SUBL);
+ }
+ }
+
+ /* Save the filter state */
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
+
+ } else { /* Enhancer not activated */
+ size_t lag;
+
+ /* Find last lag (since the enhancer is not called to give this info) */
+ lag = 20;
+ if (iLBCdec_inst->mode==20) {
+ lag = WebRtcIlbcfix_XcorrCoef(
+ &decresidual[iLBCdec_inst->blockl-60],
+ &decresidual[iLBCdec_inst->blockl-60-lag],
+ 60,
+ 80, lag, -1);
+ } else {
+ lag = WebRtcIlbcfix_XcorrCoef(
+ &decresidual[iLBCdec_inst->blockl-ENH_BLOCKL],
+ &decresidual[iLBCdec_inst->blockl-ENH_BLOCKL-lag],
+ ENH_BLOCKL,
+ 100, lag, -1);
+ }
+
+ /* Store lag (it is needed if next packet is lost) */
+ (*iLBCdec_inst).last_lag = lag;
+
+ /* copy data and run synthesis filter */
+ WEBRTC_SPL_MEMCPY_W16(data, decresidual, iLBCdec_inst->blockl);
+
+ /* Set up the filter state */
+ WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
+
+ for (i=0; i < iLBCdec_inst->nsub; i++) {
+ WebRtcSpl_FilterARFastQ12(
+ data+i*SUBL, data+i*SUBL,
+ syntdenum + i*(LPC_FILTERORDER+1),
+ LPC_FILTERORDER+1, SUBL);
+ }
+
+ /* Save the filter state */
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
+ }
+
+ WEBRTC_SPL_MEMCPY_W16(decblock,data,iLBCdec_inst->blockl);
+
+ /* High pass filter the signal (with upscaling a factor 2 and saturation) */
+ WebRtcIlbcfix_HpOutput(decblock, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
+ iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
+ iLBCdec_inst->blockl);
+
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->old_syntdenum,
+ syntdenum, iLBCdec_inst->nsub*(LPC_FILTERORDER+1));
+
+ iLBCdec_inst->prev_enh_pl=0;
+
+ if (mode==0) { /* PLC was used */
+ iLBCdec_inst->prev_enh_pl=1;
+ }
+
+ return 0; // Success.
+
+error:
+ // The decoder got sick from eating that data. Reset it and return.
+ WebRtcIlbcfix_InitDecode(iLBCdec_inst, old_mode, old_use_enhancer);
+ return -1; // Error
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.h
new file mode 100644
index 0000000000..a7d2910115
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Decode.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
+
+#include <stdint.h>
+
+#include "absl/base/attributes.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * main decoder function
+ *---------------------------------------------------------------*/
+
+// Returns 0 on success, -1 on error.
+ABSL_MUST_USE_RESULT
+int WebRtcIlbcfix_DecodeImpl(
+ int16_t* decblock, /* (o) decoded signal block */
+ const uint16_t* bytes, /* (i) encoded signal bits */
+ IlbcDecoder* iLBCdec_inst, /* (i/o) the decoder state
+ structure */
+ int16_t mode /* (i) 0: bad packet, PLC,
+ 1: normal */
+);
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.c
new file mode 100644
index 0000000000..a9668e2889
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_DecodeResidual.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/decode_residual.h"
+
+#include <string.h>
+
+#include "modules/audio_coding/codecs/ilbc/cb_construct.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/do_plc.h"
+#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/state_construct.h"
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+
+/*----------------------------------------------------------------*
+ * frame residual decoder function (subrutine to iLBC_decode)
+ *---------------------------------------------------------------*/
+
+bool WebRtcIlbcfix_DecodeResidual(
+ IlbcDecoder *iLBCdec_inst,
+ /* (i/o) the decoder state structure */
+ iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used
+ for the decoding */
+ int16_t *decresidual, /* (o) decoded residual frame */
+ int16_t *syntdenum /* (i) the decoded synthesis filter
+ coefficients */
+ ) {
+ size_t meml_gotten, diff, start_pos;
+ size_t subcount, subframe;
+ int16_t *reverseDecresidual = iLBCdec_inst->enh_buf; /* Reversed decoded data, used for decoding backwards in time (reuse memory in state) */
+ int16_t *memVec = iLBCdec_inst->prevResidual; /* Memory for codebook and filter state (reuse memory in state) */
+ int16_t *mem = &memVec[CB_HALFFILTERLEN]; /* Memory for codebook */
+
+ diff = STATE_LEN - iLBCdec_inst->state_short_len;
+
+ if (iLBC_encbits->state_first == 1) {
+ start_pos = (iLBC_encbits->startIdx-1)*SUBL;
+ } else {
+ start_pos = (iLBC_encbits->startIdx-1)*SUBL + diff;
+ }
+
+ /* decode scalar part of start state */
+
+ WebRtcIlbcfix_StateConstruct(iLBC_encbits->idxForMax,
+ iLBC_encbits->idxVec, &syntdenum[(iLBC_encbits->startIdx-1)*(LPC_FILTERORDER+1)],
+ &decresidual[start_pos], iLBCdec_inst->state_short_len
+ );
+
+ if (iLBC_encbits->state_first) { /* put adaptive part in the end */
+
+ /* setup memory */
+
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCdec_inst->state_short_len);
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCdec_inst->state_short_len, decresidual+start_pos,
+ iLBCdec_inst->state_short_len);
+
+ /* construct decoded vector */
+
+ if (!WebRtcIlbcfix_CbConstruct(
+ &decresidual[start_pos + iLBCdec_inst->state_short_len],
+ iLBC_encbits->cb_index, iLBC_encbits->gain_index,
+ mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL, diff))
+ return false; // Error.
+
+ }
+ else {/* put adaptive part in the beginning */
+
+ /* setup memory */
+
+ meml_gotten = iLBCdec_inst->state_short_len;
+ WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
+ decresidual+start_pos, meml_gotten);
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
+
+ /* construct decoded vector */
+
+ if (!WebRtcIlbcfix_CbConstruct(reverseDecresidual, iLBC_encbits->cb_index,
+ iLBC_encbits->gain_index,
+ mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL,
+ diff))
+ return false; // Error.
+
+ /* get decoded residual from reversed vector */
+
+ WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1],
+ reverseDecresidual, diff);
+ }
+
+ /* counter for predicted subframes */
+
+ subcount=1;
+
+ /* forward prediction of subframes */
+
+ if (iLBCdec_inst->nsub > iLBC_encbits->startIdx + 1) {
+
+ /* setup memory */
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
+ decresidual+(iLBC_encbits->startIdx-1)*SUBL, STATE_LEN);
+
+ /* loop over subframes to encode */
+
+ size_t Nfor = iLBCdec_inst->nsub - iLBC_encbits->startIdx - 1;
+ for (subframe=0; subframe<Nfor; subframe++) {
+
+ /* construct decoded vector */
+ if (!WebRtcIlbcfix_CbConstruct(
+ &decresidual[(iLBC_encbits->startIdx + 1 + subframe) * SUBL],
+ iLBC_encbits->cb_index + subcount * CB_NSTAGES,
+ iLBC_encbits->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
+ SUBL))
+ return false; // Error;
+
+ /* update memory */
+ memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
+ &decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL], SUBL);
+
+ subcount++;
+ }
+
+ }
+
+ /* backward prediction of subframes */
+
+ if (iLBC_encbits->startIdx > 1) {
+
+ /* setup memory */
+
+ meml_gotten = SUBL*(iLBCdec_inst->nsub+1-iLBC_encbits->startIdx);
+ if( meml_gotten > CB_MEML ) {
+ meml_gotten=CB_MEML;
+ }
+
+ WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
+ decresidual+(iLBC_encbits->startIdx-1)*SUBL, meml_gotten);
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
+
+ /* loop over subframes to decode */
+
+ size_t Nback = iLBC_encbits->startIdx - 1;
+ for (subframe=0; subframe<Nback; subframe++) {
+
+ /* construct decoded vector */
+ if (!WebRtcIlbcfix_CbConstruct(
+ &reverseDecresidual[subframe * SUBL],
+ iLBC_encbits->cb_index + subcount * CB_NSTAGES,
+ iLBC_encbits->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
+ SUBL))
+ return false; // Error.
+
+ /* update memory */
+ memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
+ &reverseDecresidual[subframe*SUBL], SUBL);
+
+ subcount++;
+ }
+
+ /* get decoded residual from reversed vector */
+ WebRtcSpl_MemCpyReversedOrder(decresidual+SUBL*Nback-1,
+ reverseDecresidual, SUBL*Nback);
+ }
+
+ return true; // Success.
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.h
new file mode 100644
index 0000000000..d079577661
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decode_residual.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_DecodeResidual.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "absl/base/attributes.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * frame residual decoder function (subrutine to iLBC_decode)
+ *---------------------------------------------------------------*/
+
+// Returns true on success, false on failure. In case of failure, the decoder
+// state may be corrupted and needs resetting.
+ABSL_MUST_USE_RESULT
+bool WebRtcIlbcfix_DecodeResidual(
+ IlbcDecoder* iLBCdec_inst, /* (i/o) the decoder state structure */
+ iLBC_bits* iLBC_encbits, /* (i/o) Encoded bits, which are used
+ for the decoding */
+ int16_t* decresidual, /* (o) decoded residual frame */
+ int16_t* syntdenum /* (i) the decoded synthesis filter
+ coefficients */
+);
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c
new file mode 100644
index 0000000000..d96bb9b2e9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_DecoderInterpolateLsp.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
+
+#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h"
+
+/*----------------------------------------------------------------*
+ * obtain synthesis and weighting filters form lsf coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_DecoderInterpolateLsp(
+ int16_t *syntdenum, /* (o) synthesis filter coefficients */
+ int16_t *weightdenum, /* (o) weighting denumerator
+ coefficients */
+ int16_t *lsfdeq, /* (i) dequantized lsf coefficients */
+ int16_t length, /* (i) length of lsf coefficient vector */
+ IlbcDecoder *iLBCdec_inst
+ /* (i) the decoder state structure */
+ ){
+ size_t i;
+ int pos, lp_length;
+ int16_t lp[LPC_FILTERORDER + 1], *lsfdeq2;
+
+ lsfdeq2 = lsfdeq + length;
+ lp_length = length + 1;
+
+ if (iLBCdec_inst->mode==30) {
+ /* subframe 1: Interpolation between old and first LSF */
+
+ WebRtcIlbcfix_LspInterpolate2PolyDec(lp, (*iLBCdec_inst).lsfdeqold, lsfdeq,
+ WebRtcIlbcfix_kLsfWeight30ms[0], length);
+ WEBRTC_SPL_MEMCPY_W16(syntdenum,lp,lp_length);
+ WebRtcIlbcfix_BwExpand(weightdenum, lp, (int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, (int16_t)lp_length);
+
+ /* subframes 2 to 6: interpolation between first and last LSF */
+
+ pos = lp_length;
+ for (i = 1; i < 6; i++) {
+ WebRtcIlbcfix_LspInterpolate2PolyDec(lp, lsfdeq, lsfdeq2,
+ WebRtcIlbcfix_kLsfWeight30ms[i], length);
+ WEBRTC_SPL_MEMCPY_W16(syntdenum + pos,lp,lp_length);
+ WebRtcIlbcfix_BwExpand(weightdenum + pos, lp,
+ (int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, (int16_t)lp_length);
+ pos += lp_length;
+ }
+ } else { /* iLBCdec_inst->mode=20 */
+ /* subframes 1 to 4: interpolation between old and new LSF */
+ pos = 0;
+ for (i = 0; i < iLBCdec_inst->nsub; i++) {
+ WebRtcIlbcfix_LspInterpolate2PolyDec(lp, iLBCdec_inst->lsfdeqold, lsfdeq,
+ WebRtcIlbcfix_kLsfWeight20ms[i], length);
+ WEBRTC_SPL_MEMCPY_W16(syntdenum+pos,lp,lp_length);
+ WebRtcIlbcfix_BwExpand(weightdenum+pos, lp,
+ (int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, (int16_t)lp_length);
+ pos += lp_length;
+ }
+ }
+
+ /* update memory */
+
+ if (iLBCdec_inst->mode==30) {
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, lsfdeq2, length);
+ } else {
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, lsfdeq, length);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h
new file mode 100644
index 0000000000..8b08114467
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_DecoderInterpolateLsp.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * obtain synthesis and weighting filters form lsf coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_DecoderInterpolateLsp(
+ int16_t* syntdenum, /* (o) synthesis filter coefficients */
+ int16_t* weightdenum, /* (o) weighting denumerator
+ coefficients */
+ int16_t* lsfdeq, /* (i) dequantized lsf coefficients */
+ int16_t length, /* (i) length of lsf coefficient vector */
+ IlbcDecoder* iLBCdec_inst
+ /* (i) the decoder state structure */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/defines.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/defines.h
new file mode 100644
index 0000000000..64135c4887
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/defines.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ define.h
+
+******************************************************************/
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+
+/* general codec settings */
+
+#define FS 8000
+#define BLOCKL_20MS 160
+#define BLOCKL_30MS 240
+#define BLOCKL_MAX 240
+#define NSUB_20MS 4
+#define NSUB_30MS 6
+#define NSUB_MAX 6
+#define NASUB_20MS 2
+#define NASUB_30MS 4
+#define NASUB_MAX 4
+#define SUBL 40
+#define STATE_LEN 80
+#define STATE_SHORT_LEN_30MS 58
+#define STATE_SHORT_LEN_20MS 57
+
+/* LPC settings */
+
+#define LPC_FILTERORDER 10
+#define LPC_LOOKBACK 60
+#define LPC_N_20MS 1
+#define LPC_N_30MS 2
+#define LPC_N_MAX 2
+#define LPC_ASYMDIFF 20
+#define LSF_NSPLIT 3
+#define LSF_NUMBER_OF_STEPS 4
+#define LPC_HALFORDER 5
+#define COS_GRID_POINTS 60
+
+/* cb settings */
+
+#define CB_NSTAGES 3
+#define CB_EXPAND 2
+#define CB_MEML 147
+#define CB_FILTERLEN (2 * 4)
+#define CB_HALFFILTERLEN 4
+#define CB_RESRANGE 34
+#define CB_MAXGAIN_FIXQ6 83 /* error = -0.24% */
+#define CB_MAXGAIN_FIXQ14 21299
+
+/* enhancer */
+
+#define ENH_BLOCKL 80 /* block length */
+#define ENH_BLOCKL_HALF (ENH_BLOCKL / 2)
+#define ENH_HL \
+ 3 /* 2*ENH_HL+1 is number blocks \
+ in said second \
+ sequence */
+#define ENH_SLOP \
+ 2 /* max difference estimated and \
+ correct pitch period */
+#define ENH_PLOCSL \
+ 8 /* pitch-estimates and \
+ pitch-locations buffer \
+ length */
+#define ENH_OVERHANG 2
+#define ENH_UPS0 4 /* upsampling rate */
+#define ENH_FL0 3 /* 2*FLO+1 is the length of each filter */
+#define ENH_FLO_MULT2_PLUS1 7
+#define ENH_VECTL (ENH_BLOCKL + 2 * ENH_FL0)
+#define ENH_CORRDIM (2 * ENH_SLOP + 1)
+#define ENH_NBLOCKS (BLOCKL / ENH_BLOCKL)
+#define ENH_NBLOCKS_EXTRA 5
+#define ENH_NBLOCKS_TOT 8 /* ENH_NBLOCKS+ENH_NBLOCKS_EXTRA */
+#define ENH_BUFL (ENH_NBLOCKS_TOT) * ENH_BLOCKL
+#define ENH_BUFL_FILTEROVERHEAD 3
+#define ENH_A0 819 /* Q14 */
+#define ENH_A0_MINUS_A0A0DIV4 848256041 /* Q34 */
+#define ENH_A0DIV2 26843546 /* Q30 */
+
+/* PLC */
+
+/* Down sampling */
+
+#define FILTERORDER_DS_PLUS1 7
+#define DELAY_DS 3
+#define FACTOR_DS 2
+
+/* bit stream defs */
+
+#define NO_OF_BYTES_20MS 38
+#define NO_OF_BYTES_30MS 50
+#define NO_OF_WORDS_20MS 19
+#define NO_OF_WORDS_30MS 25
+#define STATE_BITS 3
+#define BYTE_LEN 8
+#define ULP_CLASSES 3
+
+/* help parameters */
+
+#define TWO_PI_FIX 25736 /* Q12 */
+
+/* Constants for codebook search and creation */
+
+#define ST_MEM_L_TBL 85
+#define MEM_LF_TBL 147
+
+/* Struct for the bits */
+typedef struct iLBC_bits_t_ {
+ int16_t lsf[LSF_NSPLIT * LPC_N_MAX];
+ int16_t cb_index[CB_NSTAGES * (NASUB_MAX + 1)]; /* First CB_NSTAGES values
+ contains extra CB index */
+ int16_t gain_index[CB_NSTAGES * (NASUB_MAX + 1)]; /* First CB_NSTAGES values
+ contains extra CB gain */
+ size_t idxForMax;
+ int16_t state_first;
+ int16_t idxVec[STATE_SHORT_LEN_30MS];
+ int16_t firstbits;
+ size_t startIdx;
+} iLBC_bits;
+
+/* type definition encoder instance */
+typedef struct IlbcEncoder_ {
+ /* flag for frame size mode */
+ int16_t mode;
+
+ /* basic parameters for different frame sizes */
+ size_t blockl;
+ size_t nsub;
+ int16_t nasub;
+ size_t no_of_bytes, no_of_words;
+ int16_t lpc_n;
+ size_t state_short_len;
+
+ /* analysis filter state */
+ int16_t anaMem[LPC_FILTERORDER];
+
+ /* Fix-point old lsf parameters for interpolation */
+ int16_t lsfold[LPC_FILTERORDER];
+ int16_t lsfdeqold[LPC_FILTERORDER];
+
+ /* signal buffer for LP analysis */
+ int16_t lpc_buffer[LPC_LOOKBACK + BLOCKL_MAX];
+
+ /* state of input HP filter */
+ int16_t hpimemx[2];
+ int16_t hpimemy[4];
+
+#ifdef SPLIT_10MS
+ int16_t weightdenumbuf[66];
+ int16_t past_samples[160];
+ uint16_t bytes[25];
+ int16_t section;
+ int16_t Nfor_flag;
+ int16_t Nback_flag;
+ int16_t start_pos;
+ size_t diff;
+#endif
+
+} IlbcEncoder;
+
+/* type definition decoder instance */
+typedef struct IlbcDecoder_ {
+ /* flag for frame size mode */
+ int16_t mode;
+
+ /* basic parameters for different frame sizes */
+ size_t blockl;
+ size_t nsub;
+ int16_t nasub;
+ size_t no_of_bytes, no_of_words;
+ int16_t lpc_n;
+ size_t state_short_len;
+
+ /* synthesis filter state */
+ int16_t syntMem[LPC_FILTERORDER];
+
+ /* old LSF for interpolation */
+ int16_t lsfdeqold[LPC_FILTERORDER];
+
+ /* pitch lag estimated in enhancer and used in PLC */
+ size_t last_lag;
+
+ /* PLC state information */
+ int consPLICount, prev_enh_pl;
+ int16_t perSquare;
+
+ int16_t prevScale, prevPLI;
+ size_t prevLag;
+ int16_t prevLpc[LPC_FILTERORDER + 1];
+ int16_t prevResidual[NSUB_MAX * SUBL];
+ int16_t seed;
+
+ /* previous synthesis filter parameters */
+
+ int16_t old_syntdenum[(LPC_FILTERORDER + 1) * NSUB_MAX];
+
+ /* state of output HP filter */
+ int16_t hpimemx[2];
+ int16_t hpimemy[4];
+
+ /* enhancer state information */
+ int use_enhancer;
+ int16_t enh_buf[ENH_BUFL + ENH_BUFL_FILTEROVERHEAD];
+ size_t enh_period[ENH_NBLOCKS_TOT];
+
+} IlbcDecoder;
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.c
new file mode 100644
index 0000000000..9ca6ca48e9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_DoThePlc.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/do_plc.h"
+
+#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Packet loss concealment routine. Conceals a residual signal
+ * and LP parameters. If no packet loss, update state.
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_DoThePlc(
+ int16_t *PLCresidual, /* (o) concealed residual */
+ int16_t *PLClpc, /* (o) concealed LP parameters */
+ int16_t PLI, /* (i) packet loss indicator
+ 0 - no PL, 1 = PL */
+ int16_t *decresidual, /* (i) decoded residual */
+ int16_t *lpc, /* (i) decoded LPC (only used for no PL) */
+ size_t inlag, /* (i) pitch lag */
+ IlbcDecoder *iLBCdec_inst
+ /* (i/o) decoder instance */
+ ){
+ size_t i;
+ int32_t cross, ener, cross_comp, ener_comp = 0;
+ int32_t measure, maxMeasure, energy;
+ int32_t noise_energy_threshold_30dB;
+ int16_t max, crossSquareMax, crossSquare;
+ size_t j, lag, randlag;
+ int16_t tmp1, tmp2;
+ int16_t shift1, shift2, shift3, shiftMax;
+ int16_t scale3;
+ size_t corrLen;
+ int32_t tmpW32, tmp2W32;
+ int16_t use_gain;
+ int16_t tot_gain;
+ int16_t max_perSquare;
+ int16_t scale1, scale2;
+ int16_t totscale;
+ int32_t nom;
+ int16_t denom;
+ int16_t pitchfact;
+ size_t use_lag;
+ int ind;
+ int16_t randvec[BLOCKL_MAX];
+
+ /* Packet Loss */
+ if (PLI == 1) {
+
+ (*iLBCdec_inst).consPLICount += 1;
+
+ /* if previous frame not lost,
+ determine pitch pred. gain */
+
+ if (iLBCdec_inst->prevPLI != 1) {
+
+ /* Maximum 60 samples are correlated, preserve as high accuracy
+ as possible without getting overflow */
+ max = WebRtcSpl_MaxAbsValueW16((*iLBCdec_inst).prevResidual,
+ iLBCdec_inst->blockl);
+ scale3 = (WebRtcSpl_GetSizeInBits(max)<<1) - 25;
+ if (scale3 < 0) {
+ scale3 = 0;
+ }
+
+ /* Store scale for use when interpolating between the
+ * concealment and the received packet */
+ iLBCdec_inst->prevScale = scale3;
+
+ /* Search around the previous lag +/-3 to find the
+ best pitch period */
+ lag = inlag - 3;
+
+ /* Guard against getting outside the frame */
+ corrLen = (size_t)WEBRTC_SPL_MIN(60, iLBCdec_inst->blockl-(inlag+3));
+
+ WebRtcIlbcfix_CompCorr( &cross, &ener,
+ iLBCdec_inst->prevResidual, lag, iLBCdec_inst->blockl, corrLen, scale3);
+
+ /* Normalize and store cross^2 and the number of shifts */
+ shiftMax = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross))-15;
+ crossSquareMax = (int16_t)((
+ (int16_t)WEBRTC_SPL_SHIFT_W32(cross, -shiftMax) *
+ (int16_t)WEBRTC_SPL_SHIFT_W32(cross, -shiftMax)) >> 15);
+
+ for (j=inlag-2;j<=inlag+3;j++) {
+ WebRtcIlbcfix_CompCorr( &cross_comp, &ener_comp,
+ iLBCdec_inst->prevResidual, j, iLBCdec_inst->blockl, corrLen, scale3);
+
+ /* Use the criteria (corr*corr)/energy to compare if
+ this lag is better or not. To avoid the division,
+ do a cross multiplication */
+ shift1 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross_comp))-15;
+ crossSquare = (int16_t)((
+ (int16_t)WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1) *
+ (int16_t)WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1)) >> 15);
+
+ shift2 = WebRtcSpl_GetSizeInBits(ener)-15;
+ measure = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, -shift2) * crossSquare;
+
+ shift3 = WebRtcSpl_GetSizeInBits(ener_comp)-15;
+ maxMeasure = (int16_t)WEBRTC_SPL_SHIFT_W32(ener_comp, -shift3) *
+ crossSquareMax;
+
+ /* Calculate shift value, so that the two measures can
+ be put in the same Q domain */
+ if(2 * shiftMax + shift3 > 2 * shift1 + shift2) {
+ tmp1 =
+ WEBRTC_SPL_MIN(31, 2 * shiftMax + shift3 - 2 * shift1 - shift2);
+ tmp2 = 0;
+ } else {
+ tmp1 = 0;
+ tmp2 =
+ WEBRTC_SPL_MIN(31, 2 * shift1 + shift2 - 2 * shiftMax - shift3);
+ }
+
+ if ((measure>>tmp1) > (maxMeasure>>tmp2)) {
+ /* New lag is better => record lag, measure and domain */
+ lag = j;
+ crossSquareMax = crossSquare;
+ cross = cross_comp;
+ shiftMax = shift1;
+ ener = ener_comp;
+ }
+ }
+
+ /* Calculate the periodicity for the lag with the maximum correlation.
+
+ Definition of the periodicity:
+ abs(corr(vec1, vec2))/(sqrt(energy(vec1))*sqrt(energy(vec2)))
+
+ Work in the Square domain to simplify the calculations
+ max_perSquare is less than 1 (in Q15)
+ */
+ tmp2W32=WebRtcSpl_DotProductWithScale(&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
+ &iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
+ corrLen, scale3);
+
+ if ((tmp2W32>0)&&(ener_comp>0)) {
+ /* norm energies to int16_t, compute the product of the energies and
+ use the upper int16_t as the denominator */
+
+ scale1=(int16_t)WebRtcSpl_NormW32(tmp2W32)-16;
+ tmp1=(int16_t)WEBRTC_SPL_SHIFT_W32(tmp2W32, scale1);
+
+ scale2=(int16_t)WebRtcSpl_NormW32(ener)-16;
+ tmp2=(int16_t)WEBRTC_SPL_SHIFT_W32(ener, scale2);
+ denom = (int16_t)((tmp1 * tmp2) >> 16); /* in Q(scale1+scale2-16) */
+
+ /* Square the cross correlation and norm it such that max_perSquare
+ will be in Q15 after the division */
+
+ totscale = scale1+scale2-1;
+ tmp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, (totscale>>1));
+ tmp2 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, totscale-(totscale>>1));
+
+ nom = tmp1 * tmp2;
+ max_perSquare = (int16_t)WebRtcSpl_DivW32W16(nom, denom);
+
+ } else {
+ max_perSquare = 0;
+ }
+ }
+
+ /* previous frame lost, use recorded lag and gain */
+
+ else {
+ lag = iLBCdec_inst->prevLag;
+ max_perSquare = iLBCdec_inst->perSquare;
+ }
+
+ /* Attenuate signal and scale down pitch pred gain if
+ several frames lost consecutively */
+
+ use_gain = 32767; /* 1.0 in Q15 */
+
+ if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) {
+ use_gain = 29491; /* 0.9 in Q15 */
+ } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>640) {
+ use_gain = 22938; /* 0.7 in Q15 */
+ } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>960) {
+ use_gain = 16384; /* 0.5 in Q15 */
+ } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>1280) {
+ use_gain = 0; /* 0.0 in Q15 */
+ }
+
+ /* Compute mixing factor of picth repeatition and noise:
+ for max_per>0.7 set periodicity to 1.0
+ 0.4<max_per<0.7 set periodicity to (maxper-0.4)/0.7-0.4)
+ max_per<0.4 set periodicity to 0.0
+ */
+
+ if (max_perSquare>7868) { /* periodicity > 0.7 (0.7^4=0.2401 in Q15) */
+ pitchfact = 32767;
+ } else if (max_perSquare>839) { /* 0.4 < periodicity < 0.7 (0.4^4=0.0256 in Q15) */
+ /* find best index and interpolate from that */
+ ind = 5;
+ while ((max_perSquare<WebRtcIlbcfix_kPlcPerSqr[ind])&&(ind>0)) {
+ ind--;
+ }
+ /* pitch fact is approximated by first order */
+ tmpW32 = (int32_t)WebRtcIlbcfix_kPlcPitchFact[ind] +
+ ((WebRtcIlbcfix_kPlcPfSlope[ind] *
+ (max_perSquare - WebRtcIlbcfix_kPlcPerSqr[ind])) >> 11);
+
+ pitchfact = (int16_t)WEBRTC_SPL_MIN(tmpW32, 32767); /* guard against overflow */
+
+ } else { /* periodicity < 0.4 */
+ pitchfact = 0;
+ }
+
+ /* avoid repetition of same pitch cycle (buzzyness) */
+ use_lag = lag;
+ if (lag<80) {
+ use_lag = 2*lag;
+ }
+
+ /* compute concealed residual */
+ noise_energy_threshold_30dB = (int32_t)iLBCdec_inst->blockl * 900;
+ energy = 0;
+ for (i=0; i<iLBCdec_inst->blockl; i++) {
+
+ /* noise component - 52 < randlagFIX < 117 */
+ iLBCdec_inst->seed = (int16_t)(iLBCdec_inst->seed * 31821 + 13849);
+ randlag = 53 + (iLBCdec_inst->seed & 63);
+ if (randlag > i) {
+ randvec[i] =
+ iLBCdec_inst->prevResidual[iLBCdec_inst->blockl + i - randlag];
+ } else {
+ randvec[i] = iLBCdec_inst->prevResidual[i - randlag];
+ }
+
+ /* pitch repeatition component */
+ if (use_lag > i) {
+ PLCresidual[i] =
+ iLBCdec_inst->prevResidual[iLBCdec_inst->blockl + i - use_lag];
+ } else {
+ PLCresidual[i] = PLCresidual[i - use_lag];
+ }
+
+ /* Attinuate total gain for each 10 ms */
+ if (i<80) {
+ tot_gain=use_gain;
+ } else if (i<160) {
+ tot_gain = (int16_t)((31130 * use_gain) >> 15); /* 0.95*use_gain */
+ } else {
+ tot_gain = (int16_t)((29491 * use_gain) >> 15); /* 0.9*use_gain */
+ }
+
+
+ /* mix noise and pitch repeatition */
+ PLCresidual[i] = (int16_t)((tot_gain *
+ ((pitchfact * PLCresidual[i] + (32767 - pitchfact) * randvec[i] +
+ 16384) >> 15)) >> 15);
+
+ /* Compute energy until threshold for noise energy is reached */
+ if (energy < noise_energy_threshold_30dB) {
+ energy += PLCresidual[i] * PLCresidual[i];
+ }
+ }
+
+ /* less than 30 dB, use only noise */
+ if (energy < noise_energy_threshold_30dB) {
+ for (i=0; i<iLBCdec_inst->blockl; i++) {
+ PLCresidual[i] = randvec[i];
+ }
+ }
+
+ /* use the old LPC */
+ WEBRTC_SPL_MEMCPY_W16(PLClpc, (*iLBCdec_inst).prevLpc, LPC_FILTERORDER+1);
+
+ /* Update state in case there are multiple frame losses */
+ iLBCdec_inst->prevLag = lag;
+ iLBCdec_inst->perSquare = max_perSquare;
+ }
+
+ /* no packet loss, copy input */
+
+ else {
+ WEBRTC_SPL_MEMCPY_W16(PLCresidual, decresidual, iLBCdec_inst->blockl);
+ WEBRTC_SPL_MEMCPY_W16(PLClpc, lpc, (LPC_FILTERORDER+1));
+ iLBCdec_inst->consPLICount = 0;
+ }
+
+ /* update state */
+ iLBCdec_inst->prevPLI = PLI;
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevLpc, PLClpc, (LPC_FILTERORDER+1));
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevResidual, PLCresidual, iLBCdec_inst->blockl);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.h
new file mode 100644
index 0000000000..c19c4eca32
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/do_plc.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_DoThePlc.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Packet loss concealment routine. Conceals a residual signal
+ * and LP parameters. If no packet loss, update state.
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_DoThePlc(
+ int16_t* PLCresidual, /* (o) concealed residual */
+ int16_t* PLClpc, /* (o) concealed LP parameters */
+ int16_t PLI, /* (i) packet loss indicator
+ 0 - no PL, 1 = PL */
+ int16_t* decresidual, /* (i) decoded residual */
+ int16_t* lpc, /* (i) decoded LPC (only used for no PL) */
+ size_t inlag, /* (i) pitch lag */
+ IlbcDecoder* iLBCdec_inst
+ /* (i/o) decoder instance */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.c
new file mode 100644
index 0000000000..8e536221cd
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Encode.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/encode.h"
+
+#include <string.h>
+
+#include "modules/audio_coding/codecs/ilbc/cb_construct.h"
+#include "modules/audio_coding/codecs/ilbc/cb_search.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
+#include "modules/audio_coding/codecs/ilbc/hp_input.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
+#include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
+#include "modules/audio_coding/codecs/ilbc/pack_bits.h"
+#include "modules/audio_coding/codecs/ilbc/state_construct.h"
+#include "modules/audio_coding/codecs/ilbc/state_search.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
+
+#ifdef SPLIT_10MS
+#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
+#endif
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+#include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
+#endif
+
+/*----------------------------------------------------------------*
+ * main encoder function
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_EncodeImpl(
+ uint16_t *bytes, /* (o) encoded data bits iLBC */
+ const int16_t *block, /* (i) speech vector to encode */
+ IlbcEncoder *iLBCenc_inst /* (i/o) the general encoder
+ state */
+ ){
+ size_t n, meml_gotten, Nfor;
+ size_t diff, start_pos;
+ size_t index;
+ size_t subcount, subframe;
+ size_t start_count, end_count;
+ int16_t *residual;
+ int32_t en1, en2;
+ int16_t scale, max;
+ int16_t *syntdenum;
+ int16_t *decresidual;
+ int16_t *reverseResidual;
+ int16_t *reverseDecresidual;
+ /* Stack based */
+ int16_t weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
+ int16_t dataVec[BLOCKL_MAX + LPC_FILTERORDER];
+ int16_t memVec[CB_MEML+CB_FILTERLEN];
+ int16_t bitsMemory[sizeof(iLBC_bits)/sizeof(int16_t)];
+ iLBC_bits *iLBCbits_inst = (iLBC_bits*)bitsMemory;
+
+
+#ifdef SPLIT_10MS
+ int16_t *weightdenumbuf = iLBCenc_inst->weightdenumbuf;
+ int16_t last_bit;
+#endif
+
+ int16_t *data = &dataVec[LPC_FILTERORDER];
+ int16_t *mem = &memVec[CB_HALFFILTERLEN];
+
+ /* Reuse som buffers to save stack memory */
+ residual = &iLBCenc_inst->lpc_buffer[LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl];
+ syntdenum = mem; /* syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX] and mem are used non overlapping in the code */
+ decresidual = residual; /* Already encoded residual is overwritten by the decoded version */
+ reverseResidual = data; /* data and reverseResidual are used non overlapping in the code */
+ reverseDecresidual = reverseResidual; /* Already encoded residual is overwritten by the decoded version */
+
+#ifdef SPLIT_10MS
+
+ WebRtcSpl_MemSetW16 ( (int16_t *) iLBCbits_inst, 0,
+ sizeof(iLBC_bits) / sizeof(int16_t) );
+
+ start_pos = iLBCenc_inst->start_pos;
+ diff = iLBCenc_inst->diff;
+
+ if (iLBCenc_inst->section != 0){
+ WEBRTC_SPL_MEMCPY_W16 (weightdenum, weightdenumbuf,
+ SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
+ /* Un-Packetize the frame into parameters */
+ last_bit = WebRtcIlbcfix_UnpackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
+ if (last_bit)
+ return;
+ /* adjust index */
+ WebRtcIlbcfix_IndexConvDec (iLBCbits_inst->cb_index);
+
+ if (iLBCenc_inst->section == 1){
+ /* Save first 80 samples of a 160/240 sample frame for 20/30msec */
+ WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples, block, 80);
+ }
+ else{ // iLBCenc_inst->section == 2 AND mode = 30ms
+ /* Save second 80 samples of a 240 sample frame for 30msec */
+ WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples + 80, block, 80);
+ }
+ }
+ else{ // iLBCenc_inst->section == 0
+ /* form a complete frame of 160/240 for 20msec/30msec mode */
+ WEBRTC_SPL_MEMCPY_W16 (data + (iLBCenc_inst->mode * 8) - 80, block, 80);
+ WEBRTC_SPL_MEMCPY_W16 (data, iLBCenc_inst->past_samples,
+ (iLBCenc_inst->mode * 8) - 80);
+ iLBCenc_inst->Nfor_flag = 0;
+ iLBCenc_inst->Nback_flag = 0;
+#else
+ /* copy input block to data*/
+ WEBRTC_SPL_MEMCPY_W16(data,block,iLBCenc_inst->blockl);
+#endif
+
+ /* high pass filtering of input signal and scale down the residual (*0.5) */
+ WebRtcIlbcfix_HpInput(data, (int16_t*)WebRtcIlbcfix_kHpInCoefs,
+ iLBCenc_inst->hpimemy, iLBCenc_inst->hpimemx,
+ iLBCenc_inst->blockl);
+
+ /* LPC of hp filtered input data */
+ WebRtcIlbcfix_LpcEncode(syntdenum, weightdenum, iLBCbits_inst->lsf, data,
+ iLBCenc_inst);
+
+ /* Set up state */
+ WEBRTC_SPL_MEMCPY_W16(dataVec, iLBCenc_inst->anaMem, LPC_FILTERORDER);
+
+ /* inverse filter to get residual */
+ for (n=0; n<iLBCenc_inst->nsub; n++ ) {
+ WebRtcSpl_FilterMAFastQ12(
+ &data[n*SUBL], &residual[n*SUBL],
+ &syntdenum[n*(LPC_FILTERORDER+1)],
+ LPC_FILTERORDER+1, SUBL);
+ }
+
+ /* Copy the state for next frame */
+ WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->anaMem, &data[iLBCenc_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
+
+ /* find state location */
+
+ iLBCbits_inst->startIdx = WebRtcIlbcfix_FrameClassify(iLBCenc_inst,residual);
+
+ /* check if state should be in first or last part of the
+ two subframes */
+
+ index = (iLBCbits_inst->startIdx-1)*SUBL;
+ max=WebRtcSpl_MaxAbsValueW16(&residual[index], 2*SUBL);
+ scale = WebRtcSpl_GetSizeInBits((uint32_t)(max * max));
+
+ /* Scale to maximum 25 bits so that the MAC won't cause overflow */
+ scale = scale - 25;
+ if(scale < 0) {
+ scale = 0;
+ }
+
+ diff = STATE_LEN - iLBCenc_inst->state_short_len;
+ en1=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
+ iLBCenc_inst->state_short_len, scale);
+ index += diff;
+ en2=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
+ iLBCenc_inst->state_short_len, scale);
+ if (en1 > en2) {
+ iLBCbits_inst->state_first = 1;
+ start_pos = (iLBCbits_inst->startIdx-1)*SUBL;
+ } else {
+ iLBCbits_inst->state_first = 0;
+ start_pos = (iLBCbits_inst->startIdx-1)*SUBL + diff;
+ }
+
+ /* scalar quantization of state */
+
+ WebRtcIlbcfix_StateSearch(iLBCenc_inst, iLBCbits_inst, &residual[start_pos],
+ &syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
+ &weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)]);
+
+ WebRtcIlbcfix_StateConstruct(iLBCbits_inst->idxForMax, iLBCbits_inst->idxVec,
+ &syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
+ &decresidual[start_pos], iLBCenc_inst->state_short_len
+ );
+
+ /* predictive quantization in state */
+
+ if (iLBCbits_inst->state_first) { /* put adaptive part in the end */
+
+ /* setup memory */
+
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCenc_inst->state_short_len);
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCenc_inst->state_short_len,
+ decresidual+start_pos, iLBCenc_inst->state_short_len);
+
+ /* encode subframes */
+
+ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
+ &residual[start_pos+iLBCenc_inst->state_short_len],
+ mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
+ &weightdenum[iLBCbits_inst->startIdx*(LPC_FILTERORDER+1)], 0);
+
+ /* construct decoded vector */
+
+ RTC_CHECK(WebRtcIlbcfix_CbConstruct(
+ &decresidual[start_pos + iLBCenc_inst->state_short_len],
+ iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
+ mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL, diff));
+
+ }
+ else { /* put adaptive part in the beginning */
+
+ /* create reversed vectors for prediction */
+
+ WebRtcSpl_MemCpyReversedOrder(&reverseResidual[diff-1],
+ &residual[(iLBCbits_inst->startIdx+1)*SUBL-STATE_LEN], diff);
+
+ /* setup memory */
+
+ meml_gotten = iLBCenc_inst->state_short_len;
+ WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[start_pos], meml_gotten);
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCenc_inst->state_short_len);
+
+ /* encode subframes */
+ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
+ reverseResidual, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
+ &weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
+ 0);
+
+ /* construct decoded vector */
+ RTC_CHECK(WebRtcIlbcfix_CbConstruct(
+ reverseDecresidual, iLBCbits_inst->cb_index,
+ iLBCbits_inst->gain_index, mem + CB_MEML - ST_MEM_L_TBL,
+ ST_MEM_L_TBL, diff));
+
+ /* get decoded residual from reversed vector */
+
+ WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1], reverseDecresidual, diff);
+ }
+
+#ifdef SPLIT_10MS
+ iLBCenc_inst->start_pos = start_pos;
+ iLBCenc_inst->diff = diff;
+ iLBCenc_inst->section++;
+ /* adjust index */
+ WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
+ /* Packetize the parameters into the frame */
+ WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
+ WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
+ SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
+ return;
+ }
+#endif
+
+ /* forward prediction of subframes */
+
+ Nfor = iLBCenc_inst->nsub-iLBCbits_inst->startIdx-1;
+
+ /* counter for predicted subframes */
+#ifdef SPLIT_10MS
+ if (iLBCenc_inst->mode == 20)
+ {
+ subcount = 1;
+ }
+ if (iLBCenc_inst->mode == 30)
+ {
+ if (iLBCenc_inst->section == 1)
+ {
+ subcount = 1;
+ }
+ if (iLBCenc_inst->section == 2)
+ {
+ subcount = 3;
+ }
+ }
+#else
+ subcount=1;
+#endif
+
+ if( Nfor > 0 ){
+
+ /* setup memory */
+
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
+ decresidual+(iLBCbits_inst->startIdx-1)*SUBL, STATE_LEN);
+
+#ifdef SPLIT_10MS
+ if (iLBCenc_inst->Nfor_flag > 0)
+ {
+ for (subframe = 0; subframe < WEBRTC_SPL_MIN (Nfor, 2); subframe++)
+ {
+ /* update memory */
+ WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
+ WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
+ &decresidual[(iLBCbits_inst->startIdx + 1 +
+ subframe) * SUBL], SUBL);
+ }
+ }
+
+ iLBCenc_inst->Nfor_flag++;
+
+ if (iLBCenc_inst->mode == 20)
+ {
+ start_count = 0;
+ end_count = Nfor;
+ }
+ if (iLBCenc_inst->mode == 30)
+ {
+ if (iLBCenc_inst->section == 1)
+ {
+ start_count = 0;
+ end_count = WEBRTC_SPL_MIN (Nfor, (size_t)2);
+ }
+ if (iLBCenc_inst->section == 2)
+ {
+ start_count = WEBRTC_SPL_MIN (Nfor, (size_t)2);
+ end_count = Nfor;
+ }
+ }
+#else
+ start_count = 0;
+ end_count = Nfor;
+#endif
+
+ /* loop over subframes to encode */
+
+ for (subframe = start_count; subframe < end_count; subframe++){
+
+ /* encode subframe */
+
+ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
+ iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
+ &residual[(iLBCbits_inst->startIdx+1+subframe)*SUBL],
+ mem, MEM_LF_TBL, SUBL,
+ &weightdenum[(iLBCbits_inst->startIdx+1+subframe)*(LPC_FILTERORDER+1)],
+ subcount);
+
+ /* construct decoded vector */
+ RTC_CHECK(WebRtcIlbcfix_CbConstruct(
+ &decresidual[(iLBCbits_inst->startIdx + 1 + subframe) * SUBL],
+ iLBCbits_inst->cb_index + subcount * CB_NSTAGES,
+ iLBCbits_inst->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
+ SUBL));
+
+ /* update memory */
+
+ memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
+ &decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], SUBL);
+
+ subcount++;
+ }
+ }
+
+#ifdef SPLIT_10MS
+ if ((iLBCenc_inst->section == 1) &&
+ (iLBCenc_inst->mode == 30) && (Nfor > 0) && (end_count == 2))
+ {
+ iLBCenc_inst->section++;
+ /* adjust index */
+ WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
+ /* Packetize the parameters into the frame */
+ WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
+ WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
+ SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
+ return;
+ }
+#endif
+
+ /* backward prediction of subframes */
+
+ if (iLBCbits_inst->startIdx > 1) {
+
+ /* create reverse order vectors
+ (The decresidual does not need to be copied since it is
+ contained in the same vector as the residual)
+ */
+
+ size_t Nback = iLBCbits_inst->startIdx - 1;
+ WebRtcSpl_MemCpyReversedOrder(&reverseResidual[Nback*SUBL-1], residual, Nback*SUBL);
+
+ /* setup memory */
+
+ meml_gotten = SUBL*(iLBCenc_inst->nsub+1-iLBCbits_inst->startIdx);
+ if( meml_gotten > CB_MEML ) {
+ meml_gotten=CB_MEML;
+ }
+
+ WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[Nback*SUBL], meml_gotten);
+ WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
+
+#ifdef SPLIT_10MS
+ if (iLBCenc_inst->Nback_flag > 0)
+ {
+ for (subframe = 0; subframe < WEBRTC_SPL_MAX (2 - Nfor, 0); subframe++)
+ {
+ /* update memory */
+ WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
+ WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
+ &reverseDecresidual[subframe * SUBL], SUBL);
+ }
+ }
+
+ iLBCenc_inst->Nback_flag++;
+
+
+ if (iLBCenc_inst->mode == 20)
+ {
+ start_count = 0;
+ end_count = Nback;
+ }
+ if (iLBCenc_inst->mode == 30)
+ {
+ if (iLBCenc_inst->section == 1)
+ {
+ start_count = 0;
+ end_count = (Nfor >= 2) ? 0 : (2 - NFor);
+ }
+ if (iLBCenc_inst->section == 2)
+ {
+ start_count = (Nfor >= 2) ? 0 : (2 - NFor);
+ end_count = Nback;
+ }
+ }
+#else
+ start_count = 0;
+ end_count = Nback;
+#endif
+
+ /* loop over subframes to encode */
+
+ for (subframe = start_count; subframe < end_count; subframe++){
+
+ /* encode subframe */
+
+ WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
+ iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &reverseResidual[subframe*SUBL],
+ mem, MEM_LF_TBL, SUBL,
+ &weightdenum[(iLBCbits_inst->startIdx-2-subframe)*(LPC_FILTERORDER+1)],
+ subcount);
+
+ /* construct decoded vector */
+ RTC_CHECK(WebRtcIlbcfix_CbConstruct(
+ &reverseDecresidual[subframe * SUBL],
+ iLBCbits_inst->cb_index + subcount * CB_NSTAGES,
+ iLBCbits_inst->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
+ SUBL));
+
+ /* update memory */
+ memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
+ WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
+ &reverseDecresidual[subframe*SUBL], SUBL);
+
+ subcount++;
+
+ }
+
+ /* get decoded residual from reversed vector */
+
+ WebRtcSpl_MemCpyReversedOrder(&decresidual[SUBL*Nback-1], reverseDecresidual, SUBL*Nback);
+ }
+ /* end encoding part */
+
+ /* adjust index */
+
+ WebRtcIlbcfix_IndexConvEnc(iLBCbits_inst->cb_index);
+
+ /* Packetize the parameters into the frame */
+
+#ifdef SPLIT_10MS
+ if( (iLBCenc_inst->mode==30) && (iLBCenc_inst->section==1) ){
+ WebRtcIlbcfix_PackBits(iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
+ }
+ else{
+ WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
+ }
+#else
+ WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
+#endif
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ /* Swap bytes for LITTLE ENDIAN since the packbits()
+ function assumes BIG_ENDIAN machine */
+#ifdef SPLIT_10MS
+ if (( (iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 20) ) ||
+ ( (iLBCenc_inst->section == 2) && (iLBCenc_inst->mode == 30) )){
+ WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
+ }
+#else
+ WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
+#endif
+#endif
+
+#ifdef SPLIT_10MS
+ if (subcount == (iLBCenc_inst->nsub - 1))
+ {
+ iLBCenc_inst->section = 0;
+ }
+ else
+ {
+ iLBCenc_inst->section++;
+ WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
+ SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
+ }
+#endif
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.h
new file mode 100644
index 0000000000..bc3e187d92
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/encode.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Encode.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * main encoder function
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_EncodeImpl(
+ uint16_t* bytes, /* (o) encoded data bits iLBC */
+ const int16_t* block, /* (i) speech vector to encode */
+ IlbcEncoder* iLBCenc_inst /* (i/o) the general encoder
+ state */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.c
new file mode 100644
index 0000000000..7f00254aea
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_EnergyInverse.c
+
+******************************************************************/
+
+/* Inverses the in vector in into Q29 domain */
+
+#include "modules/audio_coding/codecs/ilbc/energy_inverse.h"
+
+void WebRtcIlbcfix_EnergyInverse(
+ int16_t *energy, /* (i/o) Energy and inverse
+ energy (in Q29) */
+ size_t noOfEnergies) /* (i) The length of the energy
+ vector */
+{
+ int32_t Nom=(int32_t)0x1FFFFFFF;
+ int16_t *energyPtr;
+ size_t i;
+
+ /* Set the minimum energy value to 16384 to avoid overflow */
+ energyPtr=energy;
+ for (i=0; i<noOfEnergies; i++) {
+ (*energyPtr)=WEBRTC_SPL_MAX((*energyPtr),16384);
+ energyPtr++;
+ }
+
+ /* Calculate inverse energy in Q29 */
+ energyPtr=energy;
+ for (i=0; i<noOfEnergies; i++) {
+ (*energyPtr) = (int16_t)WebRtcSpl_DivW32W16(Nom, (*energyPtr));
+ energyPtr++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.h
new file mode 100644
index 0000000000..15391cf230
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/energy_inverse.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_EnergyInverse.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/* Inverses the in vector in into Q29 domain */
+
+void WebRtcIlbcfix_EnergyInverse(
+ int16_t*
+ energy, /* (i/o) Energy and inverse
+ energy (in Q29) */
+ size_t noOfEnergies); /* (i) The length of the energy
+ vector */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.c
new file mode 100644
index 0000000000..cd3d0a4db1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_EnhUpsample.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/enh_upsample.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * upsample finite array assuming zeros outside bounds
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_EnhUpsample(
+ int32_t *useq1, /* (o) upsampled output sequence */
+ int16_t *seq1 /* (i) unupsampled sequence */
+ ){
+ int j;
+ int32_t *pu1, *pu11;
+ int16_t *ps, *w16tmp;
+ const int16_t *pp;
+
+ /* filtering: filter overhangs left side of sequence */
+ pu1=useq1;
+ for (j=0;j<ENH_UPS0; j++) {
+ pu11=pu1;
+ /* i = 2 */
+ pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
+ ps=seq1+2;
+ *pu11 = (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ pu11+=ENH_UPS0;
+ /* i = 3 */
+ pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
+ ps=seq1+3;
+ *pu11 = (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ pu11+=ENH_UPS0;
+ /* i = 4 */
+ pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
+ ps=seq1+4;
+ *pu11 = (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ pu1++;
+ }
+
+ /* filtering: simple convolution=inner products
+ (not needed since the sequence is so short)
+ */
+
+ /* filtering: filter overhangs right side of sequence */
+
+ /* Code with loops, which is equivivalent to the expanded version below
+
+ filterlength = 5;
+ hf1 = 2;
+ for(j=0;j<ENH_UPS0; j++){
+ pu = useq1 + (filterlength-hfl)*ENH_UPS0 + j;
+ for(i=1; i<=hfl; i++){
+ *pu=0;
+ pp = polyp[j]+i;
+ ps = seq1+dim1-1;
+ for(k=0;k<filterlength-i;k++) {
+ *pu += (*ps--) * *pp++;
+ }
+ pu+=ENH_UPS0;
+ }
+ }
+ */
+ pu1 = useq1 + 12;
+ w16tmp = seq1+4;
+ for (j=0;j<ENH_UPS0; j++) {
+ pu11 = pu1;
+ /* i = 1 */
+ pp = WebRtcIlbcfix_kEnhPolyPhaser[j]+2;
+ ps = w16tmp;
+ *pu11 = (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ pu11+=ENH_UPS0;
+ /* i = 2 */
+ pp = WebRtcIlbcfix_kEnhPolyPhaser[j]+3;
+ ps = w16tmp;
+ *pu11 = (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ *pu11 += (*ps--) * *pp++;
+ pu11+=ENH_UPS0;
+
+ pu1++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.h
new file mode 100644
index 0000000000..b427eca50a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enh_upsample.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_EnhUpsample.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENH_UPSAMPLE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENH_UPSAMPLE_H_
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * upsample finite array assuming zeros outside bounds
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_EnhUpsample(
+ int32_t* useq1, /* (o) upsampled output sequence */
+ int16_t* seq1 /* (i) unupsampled sequence */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.c
new file mode 100644
index 0000000000..bd4e60015c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Enhancer.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/enhancer.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/get_sync_seq.h"
+#include "modules/audio_coding/codecs/ilbc/smooth.h"
+
+/*----------------------------------------------------------------*
+ * perform enhancement on idata+centerStartPos through
+ * idata+centerStartPos+ENH_BLOCKL-1
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Enhancer(
+ int16_t *odata, /* (o) smoothed block, dimension blockl */
+ int16_t *idata, /* (i) data buffer used for enhancing */
+ size_t idatal, /* (i) dimension idata */
+ size_t centerStartPos, /* (i) first sample current block within idata */
+ size_t *period, /* (i) pitch period array (pitch bward-in time) */
+ const size_t *plocs, /* (i) locations where period array values valid */
+ size_t periodl /* (i) dimension of period and plocs */
+ ){
+ /* Stack based */
+ int16_t surround[ENH_BLOCKL];
+
+ WebRtcSpl_MemSetW16(surround, 0, ENH_BLOCKL);
+
+ /* get said second sequence of segments */
+
+ WebRtcIlbcfix_GetSyncSeq(idata, idatal, centerStartPos, period, plocs,
+ periodl, ENH_HL, surround);
+
+ /* compute the smoothed output from said second sequence */
+
+ WebRtcIlbcfix_Smooth(odata, idata + centerStartPos, surround);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.h
new file mode 100644
index 0000000000..386949347a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Enhancer.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * perform enhancement on idata+centerStartPos through
+ * idata+centerStartPos+ENH_BLOCKL-1
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Enhancer(
+ int16_t* odata, /* (o) smoothed block, dimension blockl */
+ int16_t* idata, /* (i) data buffer used for enhancing */
+ size_t idatal, /* (i) dimension idata */
+ size_t centerStartPos, /* (i) first sample current block within idata */
+ size_t* period, /* (i) pitch period array (pitch bward-in time) */
+ const size_t* plocs, /* (i) locations where period array values valid */
+ size_t periodl /* (i) dimension of period and plocs */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.c
new file mode 100644
index 0000000000..ca23e19ae3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_EnhancerInterface.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/enhancer.h"
+#include "modules/audio_coding/codecs/ilbc/hp_output.h"
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+
+
+
+/*----------------------------------------------------------------*
+ * interface for enhancer
+ *---------------------------------------------------------------*/
+
+size_t // (o) Estimated lag in end of in[]
+ WebRtcIlbcfix_EnhancerInterface(
+ int16_t* out, // (o) enhanced signal
+ const int16_t* in, // (i) unenhanced signal
+ IlbcDecoder* iLBCdec_inst) { // (i) buffers etc
+ size_t iblock;
+ size_t lag=20, tlag=20;
+ size_t inLen=iLBCdec_inst->blockl+120;
+ int16_t scale, scale1;
+ size_t plc_blockl;
+ int16_t *enh_buf;
+ size_t *enh_period;
+ int32_t tmp1, tmp2, max;
+ size_t new_blocks;
+ int16_t *enh_bufPtr1;
+ size_t i;
+ size_t k;
+ int16_t EnChange;
+ int16_t SqrtEnChange;
+ int16_t inc;
+ int16_t win;
+ int16_t *tmpW16ptr;
+ size_t startPos;
+ int16_t *plc_pred;
+ const int16_t *target, *regressor;
+ int16_t max16;
+ int shifts;
+ int32_t ener;
+ int16_t enerSh;
+ int16_t corrSh;
+ size_t ind;
+ int16_t sh;
+ size_t start, stop;
+ /* Stack based */
+ int16_t totsh[3];
+ int16_t downsampled[(BLOCKL_MAX+120)>>1]; /* length 180 */
+ int32_t corr32[50];
+ int32_t corrmax[3];
+ int16_t corr16[3];
+ int16_t en16[3];
+ size_t lagmax[3];
+
+ plc_pred = downsampled; /* Reuse memory since plc_pred[ENH_BLOCKL] and
+ downsampled are non overlapping */
+ enh_buf=iLBCdec_inst->enh_buf;
+ enh_period=iLBCdec_inst->enh_period;
+
+ /* Copy in the new data into the enhancer buffer */
+ memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl],
+ (ENH_BUFL - iLBCdec_inst->blockl) * sizeof(*enh_buf));
+
+ WEBRTC_SPL_MEMCPY_W16(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in,
+ iLBCdec_inst->blockl);
+
+ /* Set variables that are dependent on frame size */
+ if (iLBCdec_inst->mode==30) {
+ plc_blockl=ENH_BLOCKL;
+ new_blocks=3;
+ startPos=320; /* Start position for enhancement
+ (640-new_blocks*ENH_BLOCKL-80) */
+ } else {
+ plc_blockl=40;
+ new_blocks=2;
+ startPos=440; /* Start position for enhancement
+ (640-new_blocks*ENH_BLOCKL-40) */
+ }
+
+ /* Update the pitch prediction for each enhancer block, move the old ones */
+ memmove(enh_period, &enh_period[new_blocks],
+ (ENH_NBLOCKS_TOT - new_blocks) * sizeof(*enh_period));
+
+ WebRtcSpl_DownsampleFast(
+ enh_buf+ENH_BUFL-inLen, /* Input samples */
+ inLen + ENH_BUFL_FILTEROVERHEAD,
+ downsampled,
+ inLen / 2,
+ (int16_t*)WebRtcIlbcfix_kLpFiltCoefs, /* Coefficients in Q12 */
+ FILTERORDER_DS_PLUS1, /* Length of filter (order-1) */
+ FACTOR_DS,
+ DELAY_DS);
+
+ /* Estimate the pitch in the down sampled domain. */
+ for(iblock = 0; iblock<new_blocks; iblock++){
+
+ /* references */
+ target = downsampled + 60 + iblock * ENH_BLOCKL_HALF;
+ regressor = target - 10;
+
+ /* scaling */
+ max16 = WebRtcSpl_MaxAbsValueW16(&regressor[-50], ENH_BLOCKL_HALF + 50 - 1);
+ shifts = WebRtcSpl_GetSizeInBits((uint32_t)(max16 * max16)) - 25;
+ shifts = WEBRTC_SPL_MAX(0, shifts);
+
+ /* compute cross correlation */
+ WebRtcSpl_CrossCorrelation(corr32, target, regressor, ENH_BLOCKL_HALF, 50,
+ shifts, -1);
+
+ /* Find 3 highest correlations that should be compared for the
+ highest (corr*corr)/ener */
+
+ for (i=0;i<2;i++) {
+ lagmax[i] = WebRtcSpl_MaxIndexW32(corr32, 50);
+ corrmax[i] = corr32[lagmax[i]];
+ start = WEBRTC_SPL_MAX(2, lagmax[i]) - 2;
+ stop = WEBRTC_SPL_MIN(47, lagmax[i]) + 2;
+ for (k = start; k <= stop; k++) {
+ corr32[k] = 0;
+ }
+ }
+ lagmax[2] = WebRtcSpl_MaxIndexW32(corr32, 50);
+ corrmax[2] = corr32[lagmax[2]];
+
+ /* Calculate normalized corr^2 and ener */
+ for (i=0;i<3;i++) {
+ corrSh = 15-WebRtcSpl_GetSizeInBits(corrmax[i]);
+ ener = WebRtcSpl_DotProductWithScale(regressor - lagmax[i],
+ regressor - lagmax[i],
+ ENH_BLOCKL_HALF, shifts);
+ enerSh = 15-WebRtcSpl_GetSizeInBits(ener);
+ corr16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(corrmax[i], corrSh);
+ corr16[i] = (int16_t)((corr16[i] * corr16[i]) >> 16);
+ en16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, enerSh);
+ totsh[i] = enerSh - 2 * corrSh;
+ }
+
+ /* Compare lagmax[0..3] for the (corr^2)/ener criteria */
+ ind = 0;
+ for (i=1; i<3; i++) {
+ if (totsh[ind] > totsh[i]) {
+ sh = WEBRTC_SPL_MIN(31, totsh[ind]-totsh[i]);
+ if (corr16[ind] * en16[i] < (corr16[i] * en16[ind]) >> sh) {
+ ind = i;
+ }
+ } else {
+ sh = WEBRTC_SPL_MIN(31, totsh[i]-totsh[ind]);
+ if ((corr16[ind] * en16[i]) >> sh < corr16[i] * en16[ind]) {
+ ind = i;
+ }
+ }
+ }
+
+ lag = lagmax[ind] + 10;
+
+ /* Store the estimated lag in the non-downsampled domain */
+ enh_period[ENH_NBLOCKS_TOT - new_blocks + iblock] = lag * 8;
+
+ /* Store the estimated lag for backward PLC */
+ if (iLBCdec_inst->prev_enh_pl==1) {
+ if (!iblock) {
+ tlag = lag * 2;
+ }
+ } else {
+ if (iblock==1) {
+ tlag = lag * 2;
+ }
+ }
+
+ lag *= 2;
+ }
+
+ if ((iLBCdec_inst->prev_enh_pl==1)||(iLBCdec_inst->prev_enh_pl==2)) {
+
+ /* Calculate the best lag of the new frame
+ This is used to interpolate backwards and mix with the PLC'd data
+ */
+
+ /* references */
+ target=in;
+ regressor=in+tlag-1;
+
+ /* scaling */
+ // Note that this is not abs-max, so we will take the absolute value below.
+ max16 = WebRtcSpl_MaxAbsElementW16(regressor, plc_blockl + 3 - 1);
+ const int16_t max_target =
+ WebRtcSpl_MaxAbsElementW16(target, plc_blockl + 3 - 1);
+ const int64_t max_val = plc_blockl * abs(max16 * max_target);
+ const int32_t factor = max_val >> 31;
+ shifts = factor == 0 ? 0 : 31 - WebRtcSpl_NormW32(factor);
+
+ /* compute cross correlation */
+ WebRtcSpl_CrossCorrelation(corr32, target, regressor, plc_blockl, 3, shifts,
+ 1);
+
+ /* find lag */
+ lag=WebRtcSpl_MaxIndexW32(corr32, 3);
+ lag+=tlag-1;
+
+ /* Copy the backward PLC to plc_pred */
+
+ if (iLBCdec_inst->prev_enh_pl==1) {
+ if (lag>plc_blockl) {
+ WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-plc_blockl], plc_blockl);
+ } else {
+ WEBRTC_SPL_MEMCPY_W16(&plc_pred[plc_blockl-lag], in, lag);
+ WEBRTC_SPL_MEMCPY_W16(
+ plc_pred, &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl+lag],
+ (plc_blockl-lag));
+ }
+ } else {
+ size_t pos;
+
+ pos = plc_blockl;
+
+ while (lag<pos) {
+ WEBRTC_SPL_MEMCPY_W16(&plc_pred[pos-lag], in, lag);
+ pos = pos - lag;
+ }
+ WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-pos], pos);
+
+ }
+
+ if (iLBCdec_inst->prev_enh_pl==1) {
+ /* limit energy change
+ if energy in backward PLC is more than 4 times higher than the forward
+ PLC, then reduce the energy in the backward PLC vector:
+ sample 1...len-16 set energy of the to 4 times forward PLC
+ sample len-15..len interpolate between 4 times fw PLC and bw PLC energy
+
+ Note: Compared to floating point code there is a slight change,
+ the window is 16 samples long instead of 10 samples to simplify the
+ calculations
+ */
+
+ max=WebRtcSpl_MaxAbsValueW16(
+ &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], plc_blockl);
+ max16=WebRtcSpl_MaxAbsValueW16(plc_pred, plc_blockl);
+ max = WEBRTC_SPL_MAX(max, max16);
+ scale=22-(int16_t)WebRtcSpl_NormW32(max);
+ scale=WEBRTC_SPL_MAX(scale,0);
+
+ tmp2 = WebRtcSpl_DotProductWithScale(
+ &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl],
+ &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl],
+ plc_blockl, scale);
+ tmp1 = WebRtcSpl_DotProductWithScale(plc_pred, plc_pred,
+ plc_blockl, scale);
+
+ /* Check the energy difference */
+ if ((tmp1>0)&&((tmp1>>2)>tmp2)) {
+ /* EnChange is now guaranteed to be <0.5
+ Calculate EnChange=tmp2/tmp1 in Q16
+ */
+
+ scale1=(int16_t)WebRtcSpl_NormW32(tmp1);
+ tmp1=WEBRTC_SPL_SHIFT_W32(tmp1, (scale1-16)); /* using 15 bits */
+
+ tmp2=WEBRTC_SPL_SHIFT_W32(tmp2, (scale1));
+ EnChange = (int16_t)WebRtcSpl_DivW32W16(tmp2,
+ (int16_t)tmp1);
+
+ /* Calculate the Sqrt of the energy in Q15 ((14+16)/2) */
+ SqrtEnChange = (int16_t)WebRtcSpl_SqrtFloor(EnChange << 14);
+
+
+ /* Multiply first part of vector with 2*SqrtEnChange */
+ WebRtcSpl_ScaleVector(plc_pred, plc_pred, SqrtEnChange, plc_blockl-16,
+ 14);
+
+ /* Calculate increase parameter for window part (16 last samples) */
+ /* (1-2*SqrtEnChange)/16 in Q15 */
+ inc = 2048 - (SqrtEnChange >> 3);
+
+ win=0;
+ tmpW16ptr=&plc_pred[plc_blockl-16];
+
+ for (i=16;i>0;i--) {
+ *tmpW16ptr = (int16_t)(
+ (*tmpW16ptr * (SqrtEnChange + (win >> 1))) >> 14);
+ /* multiply by (2.0*SqrtEnChange+win) */
+
+ win += inc;
+ tmpW16ptr++;
+ }
+ }
+
+ /* Make the linear interpolation between the forward PLC'd data
+ and the backward PLC'd data (from the new frame)
+ */
+
+ if (plc_blockl==40) {
+ inc=400; /* 1/41 in Q14 */
+ } else { /* plc_blockl==80 */
+ inc=202; /* 1/81 in Q14 */
+ }
+ win=0;
+ enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl];
+ for (i=0; i<plc_blockl; i++) {
+ win+=inc;
+ *enh_bufPtr1 = (int16_t)((*enh_bufPtr1 * win) >> 14);
+ *enh_bufPtr1 += (int16_t)(
+ ((16384 - win) * plc_pred[plc_blockl - 1 - i]) >> 14);
+ enh_bufPtr1--;
+ }
+ } else {
+ int16_t *synt = &downsampled[LPC_FILTERORDER];
+
+ enh_bufPtr1=&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl];
+ WEBRTC_SPL_MEMCPY_W16(enh_bufPtr1, plc_pred, plc_blockl);
+
+ /* Clear fileter memory */
+ WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER);
+ WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4);
+ WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2);
+
+ /* Initialize filter memory by filtering through 2 lags */
+ WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], iLBCdec_inst->syntMem,
+ LPC_FILTERORDER);
+ WebRtcSpl_FilterARFastQ12(
+ enh_bufPtr1,
+ synt,
+ &iLBCdec_inst->old_syntdenum[
+ (iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)],
+ LPC_FILTERORDER+1, lag);
+
+ WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], &synt[lag-LPC_FILTERORDER],
+ LPC_FILTERORDER);
+ WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
+ iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
+ lag);
+ WebRtcSpl_FilterARFastQ12(
+ enh_bufPtr1, synt,
+ &iLBCdec_inst->old_syntdenum[
+ (iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)],
+ LPC_FILTERORDER+1, lag);
+
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &synt[lag-LPC_FILTERORDER],
+ LPC_FILTERORDER);
+ WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
+ iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
+ lag);
+ }
+ }
+
+
+ /* Perform enhancement block by block */
+
+ for (iblock = 0; iblock<new_blocks; iblock++) {
+ WebRtcIlbcfix_Enhancer(out + iblock * ENH_BLOCKL,
+ enh_buf,
+ ENH_BUFL,
+ iblock * ENH_BLOCKL + startPos,
+ enh_period,
+ WebRtcIlbcfix_kEnhPlocs, ENH_NBLOCKS_TOT);
+ }
+
+ return (lag);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h
new file mode 100644
index 0000000000..5022a47c3a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_EnhancerInterface.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * interface for enhancer
+ *---------------------------------------------------------------*/
+
+size_t // (o) Estimated lag in end of in[]
+WebRtcIlbcfix_EnhancerInterface(int16_t* out, // (o) enhanced signal
+ const int16_t* in, // (i) unenhanced signal
+ IlbcDecoder* iLBCdec_inst); // (i) buffers etc
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c
new file mode 100644
index 0000000000..6b4f30c96b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_FilteredCbVecs.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Construct an additional codebook vector by filtering the
+ * initial codebook buffer. This vector is then used to expand
+ * the codebook with an additional section.
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_FilteredCbVecs(
+ int16_t *cbvectors, /* (o) Codebook vector for the higher section */
+ int16_t *CBmem, /* (i) Codebook memory that is filtered to create a
+ second CB section */
+ size_t lMem, /* (i) Length of codebook memory */
+ size_t samples /* (i) Number of samples to filter */
+ ) {
+
+ /* Set up the memory, start with zero state */
+ WebRtcSpl_MemSetW16(CBmem+lMem, 0, CB_HALFFILTERLEN);
+ WebRtcSpl_MemSetW16(CBmem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN);
+ WebRtcSpl_MemSetW16(cbvectors, 0, lMem-samples);
+
+ /* Filter to obtain the filtered CB memory */
+
+ WebRtcSpl_FilterMAFastQ12(
+ CBmem+CB_HALFFILTERLEN+lMem-samples, cbvectors+lMem-samples,
+ (int16_t*)WebRtcIlbcfix_kCbFiltersRev, CB_FILTERLEN, samples);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h
new file mode 100644
index 0000000000..661262e42e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_FilteredCbVecs.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Construct an additional codebook vector by filtering the
+ * initial codebook buffer. This vector is then used to expand
+ * the codebook with an additional section.
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_FilteredCbVecs(
+ int16_t* cbvectors, /* (o) Codebook vector for the higher section */
+ int16_t* CBmem, /* (i) Codebook memory that is filtered to create a
+ second CB section */
+ size_t lMem, /* (i) Length of codebook memory */
+ size_t samples /* (i) Number of samples to filter */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.c
new file mode 100644
index 0000000000..c1084b1645
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_FrameClassify.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Classification of subframes to localize start state
+ *---------------------------------------------------------------*/
+
+size_t WebRtcIlbcfix_FrameClassify(
+ /* (o) Index to the max-energy sub frame */
+ IlbcEncoder *iLBCenc_inst,
+ /* (i/o) the encoder state structure */
+ int16_t *residualFIX /* (i) lpc residual signal */
+ ){
+ int16_t max, scale;
+ int32_t ssqEn[NSUB_MAX-1];
+ int16_t *ssqPtr;
+ int32_t *seqEnPtr;
+ int32_t maxW32;
+ int16_t scale1;
+ size_t pos;
+ size_t n;
+
+ /*
+ Calculate the energy of each of the 80 sample blocks
+ in the draft the 4 first and last samples are windowed with 1/5...4/5
+ and 4/5...1/5 respectively. To simplify for the fixpoint we have changed
+ this to 0 0 1 1 and 1 1 0 0
+ */
+
+ max = WebRtcSpl_MaxAbsValueW16(residualFIX, iLBCenc_inst->blockl);
+ scale = WebRtcSpl_GetSizeInBits((uint32_t)(max * max));
+
+ /* Scale to maximum 24 bits so that it won't overflow for 76 samples */
+ scale = scale-24;
+ scale1 = WEBRTC_SPL_MAX(0, scale);
+
+ /* Calculate energies */
+ ssqPtr=residualFIX + 2;
+ seqEnPtr=ssqEn;
+ for (n=(iLBCenc_inst->nsub-1); n>0; n--) {
+ (*seqEnPtr) = WebRtcSpl_DotProductWithScale(ssqPtr, ssqPtr, 76, scale1);
+ ssqPtr += 40;
+ seqEnPtr++;
+ }
+
+ /* Scale to maximum 20 bits in order to allow for the 11 bit window */
+ maxW32 = WebRtcSpl_MaxValueW32(ssqEn, iLBCenc_inst->nsub - 1);
+ scale = WebRtcSpl_GetSizeInBits(maxW32) - 20;
+ scale1 = WEBRTC_SPL_MAX(0, scale);
+
+ /* Window each 80 block with the ssqEn_winTbl window to give higher probability for
+ the blocks in the middle
+ */
+ seqEnPtr=ssqEn;
+ if (iLBCenc_inst->mode==20) {
+ ssqPtr=(int16_t*)WebRtcIlbcfix_kStartSequenceEnrgWin+1;
+ } else {
+ ssqPtr=(int16_t*)WebRtcIlbcfix_kStartSequenceEnrgWin;
+ }
+ for (n=(iLBCenc_inst->nsub-1); n>0; n--) {
+ (*seqEnPtr)=WEBRTC_SPL_MUL(((*seqEnPtr)>>scale1), (*ssqPtr));
+ seqEnPtr++;
+ ssqPtr++;
+ }
+
+ /* Extract the best choise of start state */
+ pos = WebRtcSpl_MaxIndexW32(ssqEn, iLBCenc_inst->nsub - 1) + 1;
+
+ return(pos);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.h
new file mode 100644
index 0000000000..7615106d70
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/frame_classify.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_FrameClassify.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+size_t WebRtcIlbcfix_FrameClassify(
+ /* (o) Index to the max-energy sub frame */
+ IlbcEncoder* iLBCenc_inst,
+ /* (i/o) the encoder state structure */
+ int16_t* residualFIX /* (i) lpc residual signal */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.c
new file mode 100644
index 0000000000..1357dece33
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GainDequant.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/gain_dequant.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * decoder for quantized gains in the gain-shape coding of
+ * residual
+ *---------------------------------------------------------------*/
+
+int16_t WebRtcIlbcfix_GainDequant(
+ /* (o) quantized gain value (Q14) */
+ int16_t index, /* (i) quantization index */
+ int16_t maxIn, /* (i) maximum of unquantized gain (Q14) */
+ int16_t stage /* (i) The stage of the search */
+ ){
+ int16_t scale;
+ const int16_t *gain;
+
+ /* obtain correct scale factor */
+
+ scale=WEBRTC_SPL_ABS_W16(maxIn);
+ scale = WEBRTC_SPL_MAX(1638, scale); /* if lower than 0.1, set it to 0.1 */
+
+ /* select the quantization table and return the decoded value */
+ gain = WebRtcIlbcfix_kGain[stage];
+
+ return (int16_t)((scale * gain[index] + 8192) >> 14);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.h
new file mode 100644
index 0000000000..2b97550b6c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_dequant.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GainDequant.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * decoder for quantized gains in the gain-shape coding of
+ * residual
+ *---------------------------------------------------------------*/
+
+int16_t WebRtcIlbcfix_GainDequant(
+ /* (o) quantized gain value (Q14) */
+ int16_t index, /* (i) quantization index */
+ int16_t maxIn, /* (i) maximum of unquantized gain (Q14) */
+ int16_t stage /* (i) The stage of the search */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.c
new file mode 100644
index 0000000000..9a6d49d51a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GainQuant.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * quantizer for the gain in the gain-shape coding of residual
+ *---------------------------------------------------------------*/
+
+int16_t WebRtcIlbcfix_GainQuant( /* (o) quantized gain value */
+ int16_t gain, /* (i) gain value Q14 */
+ int16_t maxIn, /* (i) maximum of gain value Q14 */
+ int16_t stage, /* (i) The stage of the search */
+ int16_t *index /* (o) quantization index */
+ ) {
+
+ int16_t scale, cblen;
+ int32_t gainW32, measure1, measure2;
+ const int16_t *cbPtr, *cb;
+ int loc, noMoves, noChecks, i;
+
+ /* ensure a lower bound (0.1) on the scaling factor */
+
+ scale = WEBRTC_SPL_MAX(1638, maxIn);
+
+ /* select the quantization table and calculate
+ the length of the table and the number of
+ steps in the binary search that are needed */
+ cb = WebRtcIlbcfix_kGain[stage];
+ cblen = 32>>stage;
+ noChecks = 4-stage;
+
+ /* Multiply the gain with 2^14 to make the comparison
+ easier and with higher precision */
+ gainW32 = gain << 14;
+
+ /* Do a binary search, starting in the middle of the CB
+ loc - defines the current position in the table
+ noMoves - defines the number of steps to move in the CB in order
+ to get next CB location
+ */
+
+ loc = cblen>>1;
+ noMoves = loc;
+ cbPtr = cb + loc; /* Centre of CB */
+
+ for (i=noChecks;i>0;i--) {
+ noMoves>>=1;
+ measure1 = scale * *cbPtr;
+
+ /* Move up if gain is larger, otherwise move down in table */
+ measure1 = measure1 - gainW32;
+
+ if (0>measure1) {
+ cbPtr+=noMoves;
+ loc+=noMoves;
+ } else {
+ cbPtr-=noMoves;
+ loc-=noMoves;
+ }
+ }
+
+ /* Check which value is the closest one: loc-1, loc or loc+1 */
+
+ measure1 = scale * *cbPtr;
+ if (gainW32>measure1) {
+ /* Check against value above loc */
+ measure2 = scale * cbPtr[1];
+ if ((measure2-gainW32)<(gainW32-measure1)) {
+ loc+=1;
+ }
+ } else {
+ /* Check against value below loc */
+ measure2 = scale * cbPtr[-1];
+ if ((gainW32-measure2)<=(measure1-gainW32)) {
+ loc-=1;
+ }
+ }
+
+ /* Guard against getting outside the table. The calculation above can give a location
+ which is one above the maximum value (in very rare cases) */
+ loc=WEBRTC_SPL_MIN(loc, (cblen-1));
+ *index=loc;
+
+ /* Calculate and return the quantized gain value (in Q14) */
+ return (int16_t)((scale * cb[loc] + 8192) >> 14);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.h
new file mode 100644
index 0000000000..761f7d2f79
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/gain_quant.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GainQuant.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * quantizer for the gain in the gain-shape coding of residual
+ *---------------------------------------------------------------*/
+
+int16_t
+WebRtcIlbcfix_GainQuant( /* (o) quantized gain value */
+ int16_t gain, /* (i) gain value Q14 */
+ int16_t maxIn, /* (i) maximum of gain value Q14 */
+ int16_t stage, /* (i) The stage of the search */
+ int16_t* index /* (o) quantization index */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.c
new file mode 100644
index 0000000000..e9cd2008e0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GetCbVec.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/get_cd_vec.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Construct codebook vector for given index.
+ *---------------------------------------------------------------*/
+
+bool WebRtcIlbcfix_GetCbVec(
+ int16_t *cbvec, /* (o) Constructed codebook vector */
+ int16_t *mem, /* (i) Codebook buffer */
+ size_t index, /* (i) Codebook index */
+ size_t lMem, /* (i) Length of codebook buffer */
+ size_t cbveclen /* (i) Codebook vector length */
+ ){
+ size_t k, base_size;
+ size_t lag;
+ /* Stack based */
+ int16_t tempbuff2[SUBL+5];
+
+ /* Determine size of codebook sections */
+
+ base_size=lMem-cbveclen+1;
+
+ if (cbveclen==SUBL) {
+ base_size += cbveclen / 2;
+ }
+
+ /* No filter -> First codebook section */
+
+ if (index<lMem-cbveclen+1) {
+
+ /* first non-interpolated vectors */
+
+ k=index+cbveclen;
+ /* get vector */
+ WEBRTC_SPL_MEMCPY_W16(cbvec, mem+lMem-k, cbveclen);
+
+ } else if (index < base_size) {
+
+ /* Calculate lag */
+
+ k = (2 * (index - (lMem - cbveclen + 1))) + cbveclen;
+
+ lag = k / 2;
+
+ WebRtcIlbcfix_CreateAugmentedVec(lag, mem+lMem, cbvec);
+
+ }
+
+ /* Higher codebbok section based on filtering */
+
+ else {
+
+ size_t memIndTest;
+
+ /* first non-interpolated vectors */
+
+ if (index-base_size<lMem-cbveclen+1) {
+
+ /* Set up filter memory, stuff zeros outside memory buffer */
+
+ memIndTest = lMem-(index-base_size+cbveclen);
+
+ WebRtcSpl_MemSetW16(mem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN);
+ WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN);
+
+ /* do filtering to get the codebook vector */
+
+ WebRtcSpl_FilterMAFastQ12(
+ &mem[memIndTest+4], cbvec, (int16_t*)WebRtcIlbcfix_kCbFiltersRev,
+ CB_FILTERLEN, cbveclen);
+ }
+
+ /* interpolated vectors */
+
+ else {
+ if (cbveclen < SUBL) {
+ // We're going to fill in cbveclen + 5 elements of tempbuff2 in
+ // WebRtcSpl_FilterMAFastQ12, less than the SUBL + 5 elements we'll be
+ // using in WebRtcIlbcfix_CreateAugmentedVec. This error is caused by
+ // bad values in `index` (which come from the encoded stream). Tell the
+ // caller that things went south, and that the decoder state is now
+ // corrupt (because it's half-way through an update that we can't
+ // complete).
+ return false;
+ }
+
+ /* Stuff zeros outside memory buffer */
+ memIndTest = lMem-cbveclen-CB_FILTERLEN;
+ WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN);
+
+ /* do filtering */
+ WebRtcSpl_FilterMAFastQ12(
+ &mem[memIndTest+7], tempbuff2, (int16_t*)WebRtcIlbcfix_kCbFiltersRev,
+ CB_FILTERLEN, cbveclen+5);
+
+ /* Calculate lag index */
+ lag = (cbveclen<<1)-20+index-base_size-lMem-1;
+
+ WebRtcIlbcfix_CreateAugmentedVec(lag, tempbuff2+SUBL+5, cbvec);
+ }
+ }
+
+ return true; // Success.
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h
new file mode 100644
index 0000000000..99537dd0f7
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GetCbVec.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "absl/base/attributes.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+// Returns true on success, false on failure. In case of failure, the decoder
+// state may be corrupted and needs resetting.
+ABSL_MUST_USE_RESULT
+bool WebRtcIlbcfix_GetCbVec(
+ int16_t* cbvec, /* (o) Constructed codebook vector */
+ int16_t* mem, /* (i) Codebook buffer */
+ size_t index, /* (i) Codebook index */
+ size_t lMem, /* (i) Length of codebook buffer */
+ size_t cbveclen /* (i) Codebook vector length */
+);
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.c
new file mode 100644
index 0000000000..e0fb21caf0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GetLspPoly.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/get_lsp_poly.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Construct the polynomials F1(z) and F2(z) from the LSP
+ * (Computations are done in Q24)
+ *
+ * The expansion is performed using the following recursion:
+ *
+ * f[0] = 1;
+ * tmp = -2.0 * lsp[0];
+ * f[1] = tmp;
+ * for (i=2; i<=5; i++) {
+ * b = -2.0 * lsp[2*i-2];
+ * f[i] = tmp*f[i-1] + 2.0*f[i-2];
+ * for (j=i; j>=2; j--) {
+ * f[j] = f[j] + tmp*f[j-1] + f[j-2];
+ * }
+ * f[i] = f[i] + tmp;
+ * }
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_GetLspPoly(
+ int16_t *lsp, /* (i) LSP in Q15 */
+ int32_t *f) /* (o) polonymial in Q24 */
+{
+ int32_t tmpW32;
+ int i, j;
+ int16_t high, low;
+ int16_t *lspPtr;
+ int32_t *fPtr;
+
+ lspPtr = lsp;
+ fPtr = f;
+ /* f[0] = 1.0 (Q24) */
+ (*fPtr) = (int32_t)16777216;
+ fPtr++;
+
+ (*fPtr) = WEBRTC_SPL_MUL((*lspPtr), -1024);
+ fPtr++;
+ lspPtr+=2;
+
+ for(i=2; i<=5; i++)
+ {
+ (*fPtr) = fPtr[-2];
+
+ for(j=i; j>1; j--)
+ {
+ /* Compute f[j] = f[j] + tmp*f[j-1] + f[j-2]; */
+ high = (int16_t)(fPtr[-1] >> 16);
+ low = (int16_t)((fPtr[-1] & 0xffff) >> 1);
+
+ tmpW32 = 4 * high * *lspPtr + 4 * ((low * *lspPtr) >> 15);
+
+ (*fPtr) += fPtr[-2];
+ (*fPtr) -= tmpW32;
+ fPtr--;
+ }
+ *fPtr -= *lspPtr * (1 << 10);
+
+ fPtr+=i;
+ lspPtr+=2;
+ }
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.h
new file mode 100644
index 0000000000..70c9c4d4b4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_lsp_poly.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GetLspPoly.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Construct the polynomials F1(z) and F2(z) from the LSP
+ * (Computations are done in Q24)
+ *
+ * The expansion is performed using the following recursion:
+ *
+ * f[0] = 1;
+ * tmp = -2.0 * lsp[0];
+ * f[1] = tmp;
+ * for (i=2; i<=5; i++) {
+ * b = -2.0 * lsp[2*i-2];
+ * f[i] = tmp*f[i-1] + 2.0*f[i-2];
+ * for (j=i; j>=2; j--) {
+ * f[j] = f[j] + tmp*f[j-1] + f[j-2];
+ * }
+ * f[i] = f[i] + tmp;
+ * }
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_GetLspPoly(int16_t* lsp, /* (i) LSP in Q15 */
+ int32_t* f); /* (o) polonymial in Q24 */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.c
new file mode 100644
index 0000000000..68a569a40a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GetSyncSeq.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/get_sync_seq.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/nearest_neighbor.h"
+#include "modules/audio_coding/codecs/ilbc/refiner.h"
+
+/*----------------------------------------------------------------*
+ * get the pitch-synchronous sample sequence
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_GetSyncSeq(
+ int16_t *idata, /* (i) original data */
+ size_t idatal, /* (i) dimension of data */
+ size_t centerStartPos, /* (i) where current block starts */
+ size_t *period, /* (i) rough-pitch-period array (Q-2) */
+ const size_t *plocs, /* (i) where periods of period array are taken (Q-2) */
+ size_t periodl, /* (i) dimension period array */
+ size_t hl, /* (i) 2*hl+1 is the number of sequences */
+ int16_t *surround /* (i/o) The contribution from this sequence
+ summed with earlier contributions */
+ ){
+ size_t i, centerEndPos, q;
+ /* Stack based */
+ size_t lagBlock[2 * ENH_HL + 1];
+ size_t blockStartPos[2 * ENH_HL + 1]; /* The position to search around (Q2) */
+ size_t plocs2[ENH_PLOCSL];
+
+ centerEndPos = centerStartPos + ENH_BLOCKL - 1;
+
+ /* present (find predicted lag from this position) */
+
+ WebRtcIlbcfix_NearestNeighbor(lagBlock + hl,
+ plocs,
+ 2 * (centerStartPos + centerEndPos),
+ periodl);
+
+ blockStartPos[hl] = 4 * centerStartPos;
+
+ /* past (find predicted position and perform a refined
+ search to find the best sequence) */
+
+ for (q = hl; q > 0; q--) {
+ size_t qq = q - 1;
+ size_t period_q = period[lagBlock[q]];
+ /* Stop if this sequence would be outside the buffer; that means all
+ further-past sequences would also be outside the buffer. */
+ if (blockStartPos[q] < period_q + (4 * ENH_OVERHANG))
+ break;
+ blockStartPos[qq] = blockStartPos[q] - period_q;
+
+ size_t value = blockStartPos[qq] + 4 * ENH_BLOCKL_HALF;
+ value = (value > period_q) ? (value - period_q) : 0;
+ WebRtcIlbcfix_NearestNeighbor(lagBlock + qq, plocs, value, periodl);
+
+ /* Find the best possible sequence in the 4 times upsampled
+ domain around blockStartPos+q */
+ WebRtcIlbcfix_Refiner(blockStartPos + qq, idata, idatal, centerStartPos,
+ blockStartPos[qq], surround,
+ WebRtcIlbcfix_kEnhWt[qq]);
+ }
+
+ /* future (find predicted position and perform a refined
+ search to find the best sequence) */
+
+ for (i = 0; i < periodl; i++) {
+ plocs2[i] = plocs[i] - period[i];
+ }
+
+ for (q = hl + 1; q <= (2 * hl); q++) {
+
+ WebRtcIlbcfix_NearestNeighbor(
+ lagBlock + q,
+ plocs2,
+ blockStartPos[q - 1] + 4 * ENH_BLOCKL_HALF,
+ periodl);
+
+ blockStartPos[q]=blockStartPos[q-1]+period[lagBlock[q]];
+
+ if (blockStartPos[q] + 4 * (ENH_BLOCKL + ENH_OVERHANG) < 4 * idatal) {
+
+ /* Find the best possible sequence in the 4 times upsampled
+ domain around blockStartPos+q */
+ WebRtcIlbcfix_Refiner(blockStartPos + q, idata, idatal, centerStartPos,
+ blockStartPos[q], surround,
+ WebRtcIlbcfix_kEnhWt[2 * hl - q]);
+
+ } else {
+ /* Don't add anything since this sequence would
+ be outside the buffer */
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.h
new file mode 100644
index 0000000000..90962fa063
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/get_sync_seq.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_GetSyncSeq.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * get the pitch-synchronous sample sequence
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_GetSyncSeq(
+ int16_t* idata, /* (i) original data */
+ size_t idatal, /* (i) dimension of data */
+ size_t centerStartPos, /* (i) where current block starts */
+ size_t* period, /* (i) rough-pitch-period array (Q-2) */
+ const size_t* plocs, /* (i) where periods of period array are taken (Q-2) */
+ size_t periodl, /* (i) dimension period array */
+ size_t hl, /* (i) 2*hl+1 is the number of sequences */
+ int16_t* surround /* (i/o) The contribution from this sequence
+ summed with earlier contributions */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.c
new file mode 100644
index 0000000000..be582f2e23
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_HpInput.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/hp_input.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * high-pass filter of input with *0.5 and saturation
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_HpInput(
+ int16_t *signal, /* (i/o) signal vector */
+ int16_t *ba, /* (i) B- and A-coefficients (2:nd order)
+ {b[0] b[1] b[2] -a[1] -a[2]} a[0]
+ is assumed to be 1.0 */
+ int16_t *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
+ yhi[n-2] ylow[n-2] */
+ int16_t *x, /* (i/o) Filter state x[n-1] x[n-2] */
+ size_t len) /* (i) Number of samples to filter */
+{
+ size_t i;
+ int32_t tmpW32;
+ int32_t tmpW32b;
+
+ for (i=0; i<len; i++) {
+
+ /*
+ y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
+ + (-a[1])*y[i-1] + (-a[2])*y[i-2];
+ */
+
+ tmpW32 = y[1] * ba[3]; /* (-a[1])*y[i-1] (low part) */
+ tmpW32 += y[3] * ba[4]; /* (-a[2])*y[i-2] (low part) */
+ tmpW32 = (tmpW32>>15);
+ tmpW32 += y[0] * ba[3]; /* (-a[1])*y[i-1] (high part) */
+ tmpW32 += y[2] * ba[4]; /* (-a[2])*y[i-2] (high part) */
+ tmpW32 = (tmpW32<<1);
+
+ tmpW32 += signal[i] * ba[0]; /* b[0]*x[0] */
+ tmpW32 += x[0] * ba[1]; /* b[1]*x[i-1] */
+ tmpW32 += x[1] * ba[2]; /* b[2]*x[i-2] */
+
+ /* Update state (input part) */
+ x[1] = x[0];
+ x[0] = signal[i];
+
+ /* Rounding in Q(12+1), i.e. add 2^12 */
+ tmpW32b = tmpW32 + 4096;
+
+ /* Saturate (to 2^28) so that the HP filtered signal does not overflow */
+ tmpW32b = WEBRTC_SPL_SAT((int32_t)268435455, tmpW32b, (int32_t)-268435456);
+
+ /* Convert back to Q0 and multiply with 0.5 */
+ signal[i] = (int16_t)(tmpW32b >> 13);
+
+ /* Update state (filtered part) */
+ y[2] = y[0];
+ y[3] = y[1];
+
+ /* upshift tmpW32 by 3 with saturation */
+ if (tmpW32>268435455) {
+ tmpW32 = WEBRTC_SPL_WORD32_MAX;
+ } else if (tmpW32<-268435456) {
+ tmpW32 = WEBRTC_SPL_WORD32_MIN;
+ } else {
+ tmpW32 <<= 3;
+ }
+
+ y[0] = (int16_t)(tmpW32 >> 16);
+ y[1] = (int16_t)((tmpW32 - (y[0] << 16)) >> 1);
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.h
new file mode 100644
index 0000000000..9143d8efed
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_input.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_HpInput.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// clang-format off
+// Bad job here. https://bugs.llvm.org/show_bug.cgi?id=34274
+void WebRtcIlbcfix_HpInput(
+ int16_t* signal, /* (i/o) signal vector */
+ int16_t* ba, /* (i) B- and A-coefficients (2:nd order)
+ {b[0] b[1] b[2] -a[1] -a[2]}
+ a[0] is assumed to be 1.0 */
+ int16_t* y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
+ yhi[n-2] ylow[n-2] */
+ int16_t* x, /* (i/o) Filter state x[n-1] x[n-2] */
+ size_t len); /* (i) Number of samples to filter */
+// clang-format on
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.c
new file mode 100644
index 0000000000..cc5f6dcd37
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_HpOutput.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/hp_output.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * high-pass filter of output and *2 with saturation
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_HpOutput(
+ int16_t *signal, /* (i/o) signal vector */
+ int16_t *ba, /* (i) B- and A-coefficients (2:nd order)
+ {b[0] b[1] b[2] -a[1] -a[2]} a[0]
+ is assumed to be 1.0 */
+ int16_t *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
+ yhi[n-2] ylow[n-2] */
+ int16_t *x, /* (i/o) Filter state x[n-1] x[n-2] */
+ size_t len) /* (i) Number of samples to filter */
+{
+ size_t i;
+ int32_t tmpW32;
+ int32_t tmpW32b;
+
+ for (i=0; i<len; i++) {
+
+ /*
+ y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
+ + (-a[1])*y[i-1] + (-a[2])*y[i-2];
+ */
+
+ tmpW32 = y[1] * ba[3]; /* (-a[1])*y[i-1] (low part) */
+ tmpW32 += y[3] * ba[4]; /* (-a[2])*y[i-2] (low part) */
+ tmpW32 = (tmpW32>>15);
+ tmpW32 += y[0] * ba[3]; /* (-a[1])*y[i-1] (high part) */
+ tmpW32 += y[2] * ba[4]; /* (-a[2])*y[i-2] (high part) */
+ tmpW32 *= 2;
+
+ tmpW32 += signal[i] * ba[0]; /* b[0]*x[0] */
+ tmpW32 += x[0] * ba[1]; /* b[1]*x[i-1] */
+ tmpW32 += x[1] * ba[2]; /* b[2]*x[i-2] */
+
+ /* Update state (input part) */
+ x[1] = x[0];
+ x[0] = signal[i];
+
+ /* Rounding in Q(12-1), i.e. add 2^10 */
+ tmpW32b = tmpW32 + 1024;
+
+ /* Saturate (to 2^26) so that the HP filtered signal does not overflow */
+ tmpW32b = WEBRTC_SPL_SAT((int32_t)67108863, tmpW32b, (int32_t)-67108864);
+
+ /* Convert back to Q0 and multiply with 2 */
+ signal[i] = (int16_t)(tmpW32b >> 11);
+
+ /* Update state (filtered part) */
+ y[2] = y[0];
+ y[3] = y[1];
+
+ /* upshift tmpW32 by 3 with saturation */
+ if (tmpW32>268435455) {
+ tmpW32 = WEBRTC_SPL_WORD32_MAX;
+ } else if (tmpW32<-268435456) {
+ tmpW32 = WEBRTC_SPL_WORD32_MIN;
+ } else {
+ tmpW32 *= 8;
+ }
+
+ y[0] = (int16_t)(tmpW32 >> 16);
+ y[1] = (int16_t)((tmpW32 & 0xffff) >> 1);
+
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.h
new file mode 100644
index 0000000000..6d1bd3cd88
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/hp_output.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_HpOutput.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// clang-format off
+// Bad job here. https://bugs.llvm.org/show_bug.cgi?id=34274
+void WebRtcIlbcfix_HpOutput(
+ int16_t* signal, /* (i/o) signal vector */
+ int16_t* ba, /* (i) B- and A-coefficients (2:nd order)
+ {b[0] b[1] b[2] -a[1] -a[2]} a[0]
+ is assumed to be 1.0 */
+ int16_t* y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
+ yhi[n-2] ylow[n-2] */
+ int16_t* x, /* (i/o) Filter state x[n-1] x[n-2] */
+ size_t len); /* (i) Number of samples to filter */
+// clang-format on
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.c
new file mode 100644
index 0000000000..ba6c3e46c3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iLBCInterface.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+
+#include <stdlib.h>
+
+#include "modules/audio_coding/codecs/ilbc/decode.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/encode.h"
+#include "modules/audio_coding/codecs/ilbc/init_decode.h"
+#include "modules/audio_coding/codecs/ilbc/init_encode.h"
+#include "rtc_base/checks.h"
+
+int16_t WebRtcIlbcfix_EncoderAssign(IlbcEncoderInstance** iLBC_encinst,
+ int16_t* ILBCENC_inst_Addr,
+ int16_t* size) {
+ *iLBC_encinst=(IlbcEncoderInstance*)ILBCENC_inst_Addr;
+ *size=sizeof(IlbcEncoder)/sizeof(int16_t);
+ if (*iLBC_encinst!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+int16_t WebRtcIlbcfix_DecoderAssign(IlbcDecoderInstance** iLBC_decinst,
+ int16_t* ILBCDEC_inst_Addr,
+ int16_t* size) {
+ *iLBC_decinst=(IlbcDecoderInstance*)ILBCDEC_inst_Addr;
+ *size=sizeof(IlbcDecoder)/sizeof(int16_t);
+ if (*iLBC_decinst!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+int16_t WebRtcIlbcfix_EncoderCreate(IlbcEncoderInstance **iLBC_encinst) {
+ *iLBC_encinst=(IlbcEncoderInstance*)malloc(sizeof(IlbcEncoder));
+ if (*iLBC_encinst!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+int16_t WebRtcIlbcfix_DecoderCreate(IlbcDecoderInstance **iLBC_decinst) {
+ *iLBC_decinst=(IlbcDecoderInstance*)malloc(sizeof(IlbcDecoder));
+ if (*iLBC_decinst!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+int16_t WebRtcIlbcfix_EncoderFree(IlbcEncoderInstance *iLBC_encinst) {
+ free(iLBC_encinst);
+ return(0);
+}
+
+int16_t WebRtcIlbcfix_DecoderFree(IlbcDecoderInstance *iLBC_decinst) {
+ free(iLBC_decinst);
+ return(0);
+}
+
+int16_t WebRtcIlbcfix_EncoderInit(IlbcEncoderInstance* iLBCenc_inst,
+ int16_t mode) {
+ if ((mode==20)||(mode==30)) {
+ WebRtcIlbcfix_InitEncode((IlbcEncoder*) iLBCenc_inst, mode);
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+int WebRtcIlbcfix_Encode(IlbcEncoderInstance* iLBCenc_inst,
+ const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded) {
+ size_t pos = 0;
+ size_t encpos = 0;
+
+ if ((len != ((IlbcEncoder*)iLBCenc_inst)->blockl) &&
+#ifdef SPLIT_10MS
+ (len != 80) &&
+#endif
+ (len != 2*((IlbcEncoder*)iLBCenc_inst)->blockl) &&
+ (len != 3*((IlbcEncoder*)iLBCenc_inst)->blockl))
+ {
+ /* A maximum of 3 frames/packet is allowed */
+ return(-1);
+ } else {
+
+ /* call encoder */
+ while (pos<len) {
+ WebRtcIlbcfix_EncodeImpl((uint16_t*)&encoded[2 * encpos], &speechIn[pos],
+ (IlbcEncoder*)iLBCenc_inst);
+#ifdef SPLIT_10MS
+ pos += 80;
+ if(((IlbcEncoder*)iLBCenc_inst)->section == 0)
+#else
+ pos += ((IlbcEncoder*)iLBCenc_inst)->blockl;
+#endif
+ encpos += ((IlbcEncoder*)iLBCenc_inst)->no_of_words;
+ }
+ return (int)(encpos*2);
+ }
+}
+
+int16_t WebRtcIlbcfix_DecoderInit(IlbcDecoderInstance* iLBCdec_inst,
+ int16_t mode) {
+ if ((mode==20)||(mode==30)) {
+ WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, mode, 1);
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+void WebRtcIlbcfix_DecoderInit20Ms(IlbcDecoderInstance* iLBCdec_inst) {
+ WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, 20, 1);
+}
+void WebRtcIlbcfix_Decoderinit30Ms(IlbcDecoderInstance* iLBCdec_inst) {
+ WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, 30, 1);
+}
+
+
+int WebRtcIlbcfix_Decode(IlbcDecoderInstance* iLBCdec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType)
+{
+ size_t i=0;
+ /* Allow for automatic switching between the frame sizes
+ (although you do get some discontinuity) */
+ if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
+ (len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
+ (len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) {
+ /* ok, do nothing */
+ } else {
+ /* Test if the mode has changed */
+ if (((IlbcDecoder*)iLBCdec_inst)->mode==20) {
+ if ((len==NO_OF_BYTES_30MS)||
+ (len==2*NO_OF_BYTES_30MS)||
+ (len==3*NO_OF_BYTES_30MS)) {
+ WebRtcIlbcfix_InitDecode(
+ ((IlbcDecoder*)iLBCdec_inst), 30,
+ ((IlbcDecoder*)iLBCdec_inst)->use_enhancer);
+ } else {
+ /* Unsupported frame length */
+ return(-1);
+ }
+ } else {
+ if ((len==NO_OF_BYTES_20MS)||
+ (len==2*NO_OF_BYTES_20MS)||
+ (len==3*NO_OF_BYTES_20MS)) {
+ WebRtcIlbcfix_InitDecode(
+ ((IlbcDecoder*)iLBCdec_inst), 20,
+ ((IlbcDecoder*)iLBCdec_inst)->use_enhancer);
+ } else {
+ /* Unsupported frame length */
+ return(-1);
+ }
+ }
+ }
+
+ while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) {
+ if (WebRtcIlbcfix_DecodeImpl(
+ &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl],
+ (const uint16_t*)&encoded
+ [2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words],
+ (IlbcDecoder*)iLBCdec_inst, 1) == -1)
+ return -1;
+ i++;
+ }
+ /* iLBC does not support VAD/CNG yet */
+ *speechType=1;
+ return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl);
+}
+
+int WebRtcIlbcfix_Decode20Ms(IlbcDecoderInstance* iLBCdec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType)
+{
+ size_t i=0;
+ if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
+ (len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
+ (len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) {
+ /* ok, do nothing */
+ } else {
+ return(-1);
+ }
+
+ while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) {
+ if (!WebRtcIlbcfix_DecodeImpl(
+ &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl],
+ (const uint16_t*)&encoded
+ [2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words],
+ (IlbcDecoder*)iLBCdec_inst, 1))
+ return -1;
+ i++;
+ }
+ /* iLBC does not support VAD/CNG yet */
+ *speechType=1;
+ return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl);
+}
+
+int WebRtcIlbcfix_Decode30Ms(IlbcDecoderInstance* iLBCdec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType)
+{
+ size_t i=0;
+ if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
+ (len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
+ (len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) {
+ /* ok, do nothing */
+ } else {
+ return(-1);
+ }
+
+ while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) {
+ if (!WebRtcIlbcfix_DecodeImpl(
+ &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl],
+ (const uint16_t*)&encoded
+ [2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words],
+ (IlbcDecoder*)iLBCdec_inst, 1))
+ return -1;
+ i++;
+ }
+ /* iLBC does not support VAD/CNG yet */
+ *speechType=1;
+ return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl);
+}
+
+size_t WebRtcIlbcfix_DecodePlc(IlbcDecoderInstance* iLBCdec_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames) {
+ size_t i;
+ uint16_t dummy;
+
+ for (i=0;i<noOfLostFrames;i++) {
+ // PLC decoding shouldn't fail, because there is no external input data
+ // that can be bad.
+ int result = WebRtcIlbcfix_DecodeImpl(
+ &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], &dummy,
+ (IlbcDecoder*)iLBCdec_inst, 0);
+ RTC_CHECK_EQ(result, 0);
+ }
+ return (noOfLostFrames*((IlbcDecoder*)iLBCdec_inst)->blockl);
+}
+
+size_t WebRtcIlbcfix_NetEqPlc(IlbcDecoderInstance* iLBCdec_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames) {
+ /* Two input parameters not used, but needed for function pointers in NetEQ */
+ (void)(decoded = NULL);
+ (void)(noOfLostFrames = 0);
+
+ WebRtcSpl_MemSetW16(((IlbcDecoder*)iLBCdec_inst)->enh_buf, 0, ENH_BUFL);
+ ((IlbcDecoder*)iLBCdec_inst)->prev_enh_pl = 2;
+
+ return (0);
+}
+
+void WebRtcIlbcfix_version(char *version)
+{
+ strcpy((char*)version, "1.1.1");
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.h
new file mode 100644
index 0000000000..de8cfde111
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * ilbc.h
+ *
+ * This header file contains all of the API's for iLBC.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * Solution to support multiple instances
+ * Customer has to cast instance to proper type
+ */
+
+typedef struct iLBC_encinst_t_ IlbcEncoderInstance;
+
+typedef struct iLBC_decinst_t_ IlbcDecoderInstance;
+
+/*
+ * Comfort noise constants
+ */
+
+#define ILBC_SPEECH 1
+#define ILBC_CNG 2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * WebRtcIlbcfix_XxxAssign(...)
+ *
+ * These functions assigns the encoder/decoder instance to the specified
+ * memory location
+ *
+ * Input:
+ * - XXX_xxxinst : Pointer to created instance that should be
+ * assigned
+ * - ILBCXXX_inst_Addr : Pointer to the desired memory space
+ * - size : The size that this structure occupies (in Word16)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIlbcfix_EncoderAssign(IlbcEncoderInstance** iLBC_encinst,
+ int16_t* ILBCENC_inst_Addr,
+ int16_t* size);
+int16_t WebRtcIlbcfix_DecoderAssign(IlbcDecoderInstance** iLBC_decinst,
+ int16_t* ILBCDEC_inst_Addr,
+ int16_t* size);
+
+/****************************************************************************
+ * WebRtcIlbcfix_XxxAssign(...)
+ *
+ * These functions create a instance to the specified structure
+ *
+ * Input:
+ * - XXX_inst : Pointer to created instance that should be created
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIlbcfix_EncoderCreate(IlbcEncoderInstance** iLBC_encinst);
+int16_t WebRtcIlbcfix_DecoderCreate(IlbcDecoderInstance** iLBC_decinst);
+
+/****************************************************************************
+ * WebRtcIlbcfix_XxxFree(...)
+ *
+ * These functions frees the dynamic memory of a specified instance
+ *
+ * Input:
+ * - XXX_inst : Pointer to created instance that should be freed
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIlbcfix_EncoderFree(IlbcEncoderInstance* iLBC_encinst);
+int16_t WebRtcIlbcfix_DecoderFree(IlbcDecoderInstance* iLBC_decinst);
+
+/****************************************************************************
+ * WebRtcIlbcfix_EncoderInit(...)
+ *
+ * This function initializes a iLBC instance
+ *
+ * Input:
+ * - iLBCenc_inst : iLBC instance, i.e. the user that should receive
+ * be initialized
+ * - frameLen : The frame length of the codec 20/30 (ms)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIlbcfix_EncoderInit(IlbcEncoderInstance* iLBCenc_inst,
+ int16_t frameLen);
+
+/****************************************************************************
+ * WebRtcIlbcfix_Encode(...)
+ *
+ * This function encodes one iLBC frame. Input speech length has be a
+ * multiple of the frame length.
+ *
+ * Input:
+ * - iLBCenc_inst : iLBC instance, i.e. the user that should encode
+ * a package
+ * - speechIn : Input speech vector
+ * - len : Samples in speechIn (160, 240, 320 or 480)
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error
+ */
+
+int WebRtcIlbcfix_Encode(IlbcEncoderInstance* iLBCenc_inst,
+ const int16_t* speechIn,
+ size_t len,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIlbcfix_DecoderInit(...)
+ *
+ * This function initializes a iLBC instance with either 20 or 30 ms frames
+ * Alternatively the WebRtcIlbcfix_DecoderInit_XXms can be used. Then it's
+ * not needed to specify the frame length with a variable.
+ *
+ * Input:
+ * - IlbcDecoderInstance : iLBC decoder instance
+ * - frameLen : The frame length of the codec 20/30 (ms)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIlbcfix_DecoderInit(IlbcDecoderInstance* iLBCdec_inst,
+ int16_t frameLen);
+void WebRtcIlbcfix_DecoderInit20Ms(IlbcDecoderInstance* iLBCdec_inst);
+void WebRtcIlbcfix_Decoderinit30Ms(IlbcDecoderInstance* iLBCdec_inst);
+
+/****************************************************************************
+ * WebRtcIlbcfix_Decode(...)
+ *
+ * This function decodes a packet with iLBC frame(s). Output speech length
+ * will be a multiple of 160 or 240 samples ((160 or 240)*frames/packet).
+ *
+ * Input:
+ * - iLBCdec_inst : iLBC instance, i.e. the user that should decode
+ * a packet
+ * - encoded : Encoded iLBC frame(s)
+ * - len : Bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ * - speechType : 1 normal, 2 CNG
+ *
+ * Return value : >0 - Samples in decoded vector
+ * -1 - Error
+ */
+
+int WebRtcIlbcfix_Decode(IlbcDecoderInstance* iLBCdec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+int WebRtcIlbcfix_Decode20Ms(IlbcDecoderInstance* iLBCdec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+int WebRtcIlbcfix_Decode30Ms(IlbcDecoderInstance* iLBCdec_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/****************************************************************************
+ * WebRtcIlbcfix_DecodePlc(...)
+ *
+ * This function conducts PLC for iLBC frame(s). Output speech length
+ * will be a multiple of 160 or 240 samples.
+ *
+ * Input:
+ * - iLBCdec_inst : iLBC instance, i.e. the user that should perform
+ * a PLC
+ * - noOfLostFrames : Number of PLC frames to produce
+ *
+ * Output:
+ * - decoded : The "decoded" vector
+ *
+ * Return value : Samples in decoded PLC vector
+ */
+
+size_t WebRtcIlbcfix_DecodePlc(IlbcDecoderInstance* iLBCdec_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames);
+
+/****************************************************************************
+ * WebRtcIlbcfix_NetEqPlc(...)
+ *
+ * This function updates the decoder when a packet loss has occured, but it
+ * does not produce any PLC data. Function can be used if another PLC method
+ * is used (i.e NetEq).
+ *
+ * Input:
+ * - iLBCdec_inst : iLBC instance that should be updated
+ * - noOfLostFrames : Number of lost frames
+ *
+ * Output:
+ * - decoded : The "decoded" vector (nothing in this case)
+ *
+ * Return value : Samples in decoded PLC vector
+ */
+
+size_t WebRtcIlbcfix_NetEqPlc(IlbcDecoderInstance* iLBCdec_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames);
+
+/****************************************************************************
+ * WebRtcIlbcfix_version(...)
+ *
+ * This function returns the version number of iLBC
+ *
+ * Output:
+ * - version : Version number of iLBC (maximum 20 char)
+ */
+
+void WebRtcIlbcfix_version(char* version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
new file mode 100644
index 0000000000..689292f131
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
+#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+TEST(IlbcTest, BadPacket) {
+ // Get a good packet.
+ AudioEncoderIlbcConfig config;
+ config.frame_size_ms = 20; // We need 20 ms rather than the default 30 ms;
+ // otherwise, all possible values of cb_index[2]
+ // are valid.
+ AudioEncoderIlbcImpl encoder(config, 102);
+ std::vector<int16_t> samples(encoder.SampleRateHz() / 100, 4711);
+ rtc::Buffer packet;
+ int num_10ms_chunks = 0;
+ while (packet.size() == 0) {
+ encoder.Encode(0, samples, &packet);
+ num_10ms_chunks += 1;
+ }
+
+ // Break the packet by setting all bits of the unsigned 7-bit number
+ // cb_index[2] to 1, giving it a value of 127. For a 20 ms packet, this is
+ // too large.
+ EXPECT_EQ(38u, packet.size());
+ rtc::Buffer bad_packet(packet.data(), packet.size());
+ bad_packet[29] |= 0x3f; // Bits 1-6.
+ bad_packet[30] |= 0x80; // Bit 0.
+
+ // Decode the bad packet. We expect the decoder to respond by returning -1.
+ AudioDecoderIlbcImpl decoder;
+ std::vector<int16_t> decoded_samples(num_10ms_chunks * samples.size());
+ AudioDecoder::SpeechType speech_type;
+ EXPECT_EQ(-1, decoder.Decode(bad_packet.data(), bad_packet.size(),
+ encoder.SampleRateHz(),
+ sizeof(int16_t) * decoded_samples.size(),
+ decoded_samples.data(), &speech_type));
+
+ // Decode the good packet. This should work, because the failed decoding
+ // should not have left the decoder in a broken state.
+ EXPECT_EQ(static_cast<int>(decoded_samples.size()),
+ decoder.Decode(packet.data(), packet.size(), encoder.SampleRateHz(),
+ sizeof(int16_t) * decoded_samples.size(),
+ decoded_samples.data(), &speech_type));
+}
+
+class SplitIlbcTest : public ::testing::TestWithParam<std::pair<int, int> > {
+ protected:
+ virtual void SetUp() {
+ const std::pair<int, int> parameters = GetParam();
+ num_frames_ = parameters.first;
+ frame_length_ms_ = parameters.second;
+ frame_length_bytes_ = (frame_length_ms_ == 20) ? 38 : 50;
+ }
+ size_t num_frames_;
+ int frame_length_ms_;
+ size_t frame_length_bytes_;
+};
+
+TEST_P(SplitIlbcTest, NumFrames) {
+ AudioDecoderIlbcImpl decoder;
+ const size_t frame_length_samples = frame_length_ms_ * 8;
+ const auto generate_payload = [](size_t payload_length_bytes) {
+ rtc::Buffer payload(payload_length_bytes);
+ // Fill payload with increasing integers {0, 1, 2, ...}.
+ for (size_t i = 0; i < payload.size(); ++i) {
+ payload[i] = static_cast<uint8_t>(i);
+ }
+ return payload;
+ };
+
+ const auto results = decoder.ParsePayload(
+ generate_payload(frame_length_bytes_ * num_frames_), 0);
+ EXPECT_EQ(num_frames_, results.size());
+
+ size_t frame_num = 0;
+ uint8_t payload_value = 0;
+ for (const auto& result : results) {
+ EXPECT_EQ(frame_length_samples * frame_num, result.timestamp);
+ const LegacyEncodedAudioFrame* frame =
+ static_cast<const LegacyEncodedAudioFrame*>(result.frame.get());
+ const rtc::Buffer& payload = frame->payload();
+ EXPECT_EQ(frame_length_bytes_, payload.size());
+ for (size_t i = 0; i < payload.size(); ++i, ++payload_value) {
+ EXPECT_EQ(payload_value, payload[i]);
+ }
+ ++frame_num;
+ }
+}
+
+// Test 1 through 5 frames of 20 and 30 ms size.
+// Also test the maximum number of frames in one packet for 20 and 30 ms.
+// The maximum is defined by the largest payload length that can be uniquely
+// resolved to a frame size of either 38 bytes (20 ms) or 50 bytes (30 ms).
+INSTANTIATE_TEST_SUITE_P(
+ IlbcTest,
+ SplitIlbcTest,
+ ::testing::Values(std::pair<int, int>(1, 20), // 1 frame, 20 ms.
+ std::pair<int, int>(2, 20), // 2 frames, 20 ms.
+ std::pair<int, int>(3, 20), // And so on.
+ std::pair<int, int>(4, 20),
+ std::pair<int, int>(5, 20),
+ std::pair<int, int>(24, 20),
+ std::pair<int, int>(1, 30),
+ std::pair<int, int>(2, 30),
+ std::pair<int, int>(3, 30),
+ std::pair<int, int>(4, 30),
+ std::pair<int, int>(5, 30),
+ std::pair<int, int>(18, 30)));
+
+// Test too large payload size.
+TEST(IlbcTest, SplitTooLargePayload) {
+ AudioDecoderIlbcImpl decoder;
+ constexpr size_t kPayloadLengthBytes = 950;
+ const auto results =
+ decoder.ParsePayload(rtc::Buffer(kPayloadLengthBytes), 0);
+ EXPECT_TRUE(results.empty());
+}
+
+// Payload not an integer number of frames.
+TEST(IlbcTest, SplitUnevenPayload) {
+ AudioDecoderIlbcImpl decoder;
+ constexpr size_t kPayloadLengthBytes = 39; // Not an even number of frames.
+ const auto results =
+ decoder.ParsePayload(rtc::Buffer(kPayloadLengthBytes), 0);
+ EXPECT_TRUE(results.empty());
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.c
new file mode 100644
index 0000000000..d78f81a897
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_IndexConvDec.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_IndexConvDec(
+ int16_t *index /* (i/o) Codebook indexes */
+ ){
+ int k;
+
+ for (k=4;k<6;k++) {
+ /* Readjust the second and third codebook index for the first 40 sample
+ so that they look the same as the first (in terms of lag)
+ */
+ if ((index[k]>=44)&&(index[k]<108)) {
+ index[k]+=64;
+ } else if ((index[k]>=108)&&(index[k]<128)) {
+ index[k]+=128;
+ } else {
+ /* ERROR */
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.h
new file mode 100644
index 0000000000..4f08ce04df
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_dec.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_IndexConvDec.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INDEX_CONV_DEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INDEX_CONV_DEC_H_
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_IndexConvDec(int16_t* index /* (i/o) Codebook indexes */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.c
new file mode 100644
index 0000000000..83144150b4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ IiLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_IndexConvEnc.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Convert the codebook indexes to make the search easier
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_IndexConvEnc(
+ int16_t *index /* (i/o) Codebook indexes */
+ ){
+ int k;
+
+ for (k=4;k<6;k++) {
+ /* Readjust the second and third codebook index so that it is
+ packetized into 7 bits (before it was put in lag-wise the same
+ way as for the first codebook which uses 8 bits)
+ */
+ if ((index[k]>=108)&&(index[k]<172)) {
+ index[k]-=64;
+ } else if (index[k]>=236) {
+ index[k]-=128;
+ } else {
+ /* ERROR */
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.h
new file mode 100644
index 0000000000..4fbf98084e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/index_conv_enc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_IndexConvEnc.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INDEX_CONV_ENC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INDEX_CONV_ENC_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Convert the codebook indexes to make the search easier
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_IndexConvEnc(int16_t* index /* (i/o) Codebook indexes */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.c
new file mode 100644
index 0000000000..3eb41e33b0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_InitDecode.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/init_decode.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Initiation of decoder instance.
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_InitDecode( /* (o) Number of decoded samples */
+ IlbcDecoder *iLBCdec_inst, /* (i/o) Decoder instance */
+ int16_t mode, /* (i) frame size mode */
+ int use_enhancer) { /* (i) 1: use enhancer, 0: no enhancer */
+ int i;
+
+ iLBCdec_inst->mode = mode;
+
+ /* Set all the variables that are dependent on the frame size mode */
+ if (mode==30) {
+ iLBCdec_inst->blockl = BLOCKL_30MS;
+ iLBCdec_inst->nsub = NSUB_30MS;
+ iLBCdec_inst->nasub = NASUB_30MS;
+ iLBCdec_inst->lpc_n = LPC_N_30MS;
+ iLBCdec_inst->no_of_bytes = NO_OF_BYTES_30MS;
+ iLBCdec_inst->no_of_words = NO_OF_WORDS_30MS;
+ iLBCdec_inst->state_short_len=STATE_SHORT_LEN_30MS;
+ }
+ else if (mode==20) {
+ iLBCdec_inst->blockl = BLOCKL_20MS;
+ iLBCdec_inst->nsub = NSUB_20MS;
+ iLBCdec_inst->nasub = NASUB_20MS;
+ iLBCdec_inst->lpc_n = LPC_N_20MS;
+ iLBCdec_inst->no_of_bytes = NO_OF_BYTES_20MS;
+ iLBCdec_inst->no_of_words = NO_OF_WORDS_20MS;
+ iLBCdec_inst->state_short_len=STATE_SHORT_LEN_20MS;
+ }
+ else {
+ return(-1);
+ }
+
+ /* Reset all the previous LSF to mean LSF */
+ WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, WebRtcIlbcfix_kLsfMean, LPC_FILTERORDER);
+
+ /* Clear the synthesis filter memory */
+ WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER);
+
+ /* Set the old synthesis filter to {1.0 0.0 ... 0.0} */
+ WebRtcSpl_MemSetW16(iLBCdec_inst->old_syntdenum, 0, ((LPC_FILTERORDER + 1)*NSUB_MAX));
+ for (i=0; i<NSUB_MAX; i++) {
+ iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)] = 4096;
+ }
+
+ /* Clear the variables that are used for the PLC */
+ iLBCdec_inst->last_lag = 20;
+ iLBCdec_inst->consPLICount = 0;
+ iLBCdec_inst->prevPLI = 0;
+ iLBCdec_inst->perSquare = 0;
+ iLBCdec_inst->prevLag = 120;
+ iLBCdec_inst->prevLpc[0] = 4096;
+ WebRtcSpl_MemSetW16(iLBCdec_inst->prevLpc+1, 0, LPC_FILTERORDER);
+ WebRtcSpl_MemSetW16(iLBCdec_inst->prevResidual, 0, BLOCKL_MAX);
+
+ /* Initialize the seed for the random number generator */
+ iLBCdec_inst->seed = 777;
+
+ /* Set the filter state of the HP filter to 0 */
+ WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2);
+ WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4);
+
+ /* Set the variables that are used in the ehnahcer */
+ iLBCdec_inst->use_enhancer = use_enhancer;
+ WebRtcSpl_MemSetW16(iLBCdec_inst->enh_buf, 0, (ENH_BUFL+ENH_BUFL_FILTEROVERHEAD));
+ for (i=0;i<ENH_NBLOCKS_TOT;i++) {
+ iLBCdec_inst->enh_period[i]=160; /* Q(-4) */
+ }
+
+ iLBCdec_inst->prev_enh_pl = 0;
+
+ return (int)(iLBCdec_inst->blockl);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.h
new file mode 100644
index 0000000000..a2b7b91287
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_decode.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_InitDecode.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_DECODE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_DECODE_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Initiation of decoder instance.
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_InitDecode(/* (o) Number of decoded samples */
+ IlbcDecoder*
+ iLBCdec_inst, /* (i/o) Decoder instance */
+ int16_t mode, /* (i) frame size mode */
+ int use_enhancer /* (i) 1 to use enhancer
+ 0 to run without enhancer */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.c
new file mode 100644
index 0000000000..aa858e94bb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_InitEncode.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/init_encode.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Initiation of encoder instance.
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_InitEncode( /* (o) Number of bytes encoded */
+ IlbcEncoder *iLBCenc_inst, /* (i/o) Encoder instance */
+ int16_t mode) { /* (i) frame size mode */
+ iLBCenc_inst->mode = mode;
+
+ /* Set all the variables that are dependent on the frame size mode */
+ if (mode==30) {
+ iLBCenc_inst->blockl = BLOCKL_30MS;
+ iLBCenc_inst->nsub = NSUB_30MS;
+ iLBCenc_inst->nasub = NASUB_30MS;
+ iLBCenc_inst->lpc_n = LPC_N_30MS;
+ iLBCenc_inst->no_of_bytes = NO_OF_BYTES_30MS;
+ iLBCenc_inst->no_of_words = NO_OF_WORDS_30MS;
+ iLBCenc_inst->state_short_len=STATE_SHORT_LEN_30MS;
+ }
+ else if (mode==20) {
+ iLBCenc_inst->blockl = BLOCKL_20MS;
+ iLBCenc_inst->nsub = NSUB_20MS;
+ iLBCenc_inst->nasub = NASUB_20MS;
+ iLBCenc_inst->lpc_n = LPC_N_20MS;
+ iLBCenc_inst->no_of_bytes = NO_OF_BYTES_20MS;
+ iLBCenc_inst->no_of_words = NO_OF_WORDS_20MS;
+ iLBCenc_inst->state_short_len=STATE_SHORT_LEN_20MS;
+ }
+ else {
+ return(-1);
+ }
+
+ /* Clear the buffers and set the previous LSF and LSP to the mean value */
+ WebRtcSpl_MemSetW16(iLBCenc_inst->anaMem, 0, LPC_FILTERORDER);
+ WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lsfold, WebRtcIlbcfix_kLsfMean, LPC_FILTERORDER);
+ WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lsfdeqold, WebRtcIlbcfix_kLsfMean, LPC_FILTERORDER);
+ WebRtcSpl_MemSetW16(iLBCenc_inst->lpc_buffer, 0, LPC_LOOKBACK + BLOCKL_MAX);
+
+ /* Set the filter state of the HP filter to 0 */
+ WebRtcSpl_MemSetW16(iLBCenc_inst->hpimemx, 0, 2);
+ WebRtcSpl_MemSetW16(iLBCenc_inst->hpimemy, 0, 4);
+
+#ifdef SPLIT_10MS
+ /*Zeroing the past samples for 10msec Split*/
+ WebRtcSpl_MemSetW16(iLBCenc_inst->past_samples,0,160);
+ iLBCenc_inst->section = 0;
+#endif
+
+ return (int)(iLBCenc_inst->no_of_bytes);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.h
new file mode 100644
index 0000000000..4ada6a30c8
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/init_encode.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_InitEncode.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_ENCODE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_ENCODE_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * Initiation of encoder instance.
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_InitEncode(/* (o) Number of bytes encoded */
+ IlbcEncoder*
+ iLBCenc_inst, /* (i/o) Encoder instance */
+ int16_t mode /* (i) frame size mode */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.c
new file mode 100644
index 0000000000..17ed244bd4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Interpolate.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/interpolate.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * interpolation between vectors
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Interpolate(
+ int16_t *out, /* (o) output vector */
+ int16_t *in1, /* (i) first input vector */
+ int16_t *in2, /* (i) second input vector */
+ int16_t coef, /* (i) weight coefficient in Q14 */
+ int16_t length) /* (i) number of sample is vectors */
+{
+ int i;
+ int16_t invcoef;
+
+ /*
+ Performs the operation out[i] = in[i]*coef + (1-coef)*in2[i] (with rounding)
+ */
+
+ invcoef = 16384 - coef; /* 16384 = 1.0 (Q14)*/
+ for (i = 0; i < length; i++) {
+ out[i] = (int16_t)((coef * in1[i] + invcoef * in2[i] + 8192) >> 14);
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.h
new file mode 100644
index 0000000000..892082b75c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Interpolate.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * interpolation between vectors
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Interpolate(
+ int16_t* out, /* (o) output vector */
+ int16_t* in1, /* (i) first input vector */
+ int16_t* in2, /* (i) second input vector */
+ int16_t coef, /* (i) weight coefficient in Q14 */
+ int16_t length); /* (i) number of sample is vectors */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.c
new file mode 100644
index 0000000000..6dddd6fb86
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_InterpolateSamples.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/interpolate_samples.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+void WebRtcIlbcfix_InterpolateSamples(
+ int16_t *interpSamples, /* (o) The interpolated samples */
+ int16_t *CBmem, /* (i) The CB memory */
+ size_t lMem /* (i) Length of the CB memory */
+ ) {
+ int16_t *ppi, *ppo, i, j, temp1, temp2;
+ int16_t *tmpPtr;
+
+ /* Calculate the 20 vectors of interpolated samples (4 samples each)
+ that are used in the codebooks for lag 20 to 39 */
+ tmpPtr = interpSamples;
+ for (j=0; j<20; j++) {
+ temp1 = 0;
+ temp2 = 3;
+ ppo = CBmem+lMem-4;
+ ppi = CBmem+lMem-j-24;
+ for (i=0; i<4; i++) {
+
+ *tmpPtr++ = (int16_t)((WebRtcIlbcfix_kAlpha[temp2] * *ppo) >> 15) +
+ (int16_t)((WebRtcIlbcfix_kAlpha[temp1] * *ppi) >> 15);
+
+ ppo++;
+ ppi++;
+ temp1++;
+ temp2--;
+ }
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.h
new file mode 100644
index 0000000000..bc665d7854
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/interpolate_samples.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_InterpolateSamples.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_SAMPLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_SAMPLES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Construct the interpolated samples for the Augmented CB
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_InterpolateSamples(
+ int16_t* interpSamples, /* (o) The interpolated samples */
+ int16_t* CBmem, /* (i) The CB memory */
+ size_t lMem /* (i) Length of the CB memory */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.c
new file mode 100644
index 0000000000..89f6d29724
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LpcEncode.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_quant.h"
+
+/*----------------------------------------------------------------*
+ * lpc encoder
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_LpcEncode(
+ int16_t *syntdenum, /* (i/o) synthesis filter coefficients
+ before/after encoding */
+ int16_t *weightdenum, /* (i/o) weighting denumerator coefficients
+ before/after encoding */
+ int16_t *lsf_index, /* (o) lsf quantization index */
+ int16_t *data, /* (i) Speech to do LPC analysis on */
+ IlbcEncoder *iLBCenc_inst
+ /* (i/o) the encoder state structure */
+ ) {
+ /* Stack based */
+ int16_t lsf[LPC_FILTERORDER * LPC_N_MAX];
+ int16_t lsfdeq[LPC_FILTERORDER * LPC_N_MAX];
+
+ /* Calculate LSF's from the input speech */
+ WebRtcIlbcfix_SimpleLpcAnalysis(lsf, data, iLBCenc_inst);
+
+ /* Quantize the LSF's */
+ WebRtcIlbcfix_SimpleLsfQ(lsfdeq, lsf_index, lsf, iLBCenc_inst->lpc_n);
+
+ /* Stableize the LSF's if needed */
+ WebRtcIlbcfix_LsfCheck(lsfdeq, LPC_FILTERORDER, iLBCenc_inst->lpc_n);
+
+ /* Calculate the synthesis and weighting filter coefficients from
+ the optimal LSF and the dequantized LSF */
+ WebRtcIlbcfix_SimpleInterpolateLsf(syntdenum, weightdenum,
+ lsf, lsfdeq, iLBCenc_inst->lsfold,
+ iLBCenc_inst->lsfdeqold, LPC_FILTERORDER, iLBCenc_inst);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.h
new file mode 100644
index 0000000000..a67b77acbf
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lpc_encode.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LpcEncode.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LPC_ENCODE_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LPC_ENCODE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * lpc encoder
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_LpcEncode(
+ int16_t* syntdenum, /* (i/o) synthesis filter coefficients
+ before/after encoding */
+ int16_t* weightdenum, /* (i/o) weighting denumerator coefficients
+ before/after encoding */
+ int16_t* lsf_index, /* (o) lsf quantization index */
+ int16_t* data, /* (i) Speech to do LPC analysis on */
+ IlbcEncoder* iLBCenc_inst
+ /* (i/o) the encoder state structure */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.c
new file mode 100644
index 0000000000..9f0e19a2d9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LsfCheck.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * check for stability of lsf coefficients
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_LsfCheck(
+ int16_t *lsf, /* LSF parameters */
+ int dim, /* dimension of LSF */
+ int NoAn) /* No of analysis per frame */
+{
+ int k,n,m, Nit=2, change=0,pos;
+ const int16_t eps=319; /* 0.039 in Q13 (50 Hz)*/
+ const int16_t eps2=160; /* eps/2.0 in Q13;*/
+ const int16_t maxlsf=25723; /* 3.14; (4000 Hz)*/
+ const int16_t minlsf=82; /* 0.01; (0 Hz)*/
+
+ /* LSF separation check*/
+ for (n=0;n<Nit;n++) { /* Run through a 2 times */
+ for (m=0;m<NoAn;m++) { /* Number of analyses per frame */
+ for (k=0;k<(dim-1);k++) {
+ pos=m*dim+k;
+
+ /* Seperate coefficients with a safety margin of 50 Hz */
+ if ((lsf[pos+1]-lsf[pos])<eps) {
+
+ if (lsf[pos+1]<lsf[pos]) {
+ lsf[pos+1]= lsf[pos]+eps2;
+ lsf[pos]= lsf[pos+1]-eps2;
+ } else {
+ lsf[pos]-=eps2;
+ lsf[pos+1]+=eps2;
+ }
+ change=1;
+ }
+
+ /* Limit minimum and maximum LSF */
+ if (lsf[pos]<minlsf) {
+ lsf[pos]=minlsf;
+ change=1;
+ }
+
+ if (lsf[pos]>maxlsf) {
+ lsf[pos]=maxlsf;
+ change=1;
+ }
+ }
+ }
+ }
+
+ return change;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.h
new file mode 100644
index 0000000000..9ba90a31e6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_check.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LsfCheck.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_CHECK_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_CHECK_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * check for stability of lsf coefficients
+ *---------------------------------------------------------------*/
+
+int WebRtcIlbcfix_LsfCheck(int16_t* lsf, /* LSF parameters */
+ int dim, /* dimension of LSF */
+ int NoAn); /* No of analysis per frame */
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c
new file mode 100644
index 0000000000..04de5e7e6c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LspInterpolate2PolyDec.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/interpolate.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_to_poly.h"
+
+/*----------------------------------------------------------------*
+ * interpolation of lsf coefficients for the decoder
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_LspInterpolate2PolyDec(
+ int16_t *a, /* (o) lpc coefficients Q12 */
+ int16_t *lsf1, /* (i) first set of lsf coefficients Q13 */
+ int16_t *lsf2, /* (i) second set of lsf coefficients Q13 */
+ int16_t coef, /* (i) weighting coefficient to use between
+ lsf1 and lsf2 Q14 */
+ int16_t length /* (i) length of coefficient vectors */
+ ){
+ int16_t lsftmp[LPC_FILTERORDER];
+
+ /* interpolate LSF */
+ WebRtcIlbcfix_Interpolate(lsftmp, lsf1, lsf2, coef, length);
+
+ /* Compute the filter coefficients from the LSF */
+ WebRtcIlbcfix_Lsf2Poly(a, lsftmp);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h
new file mode 100644
index 0000000000..6cc9d9746d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LspInterpolate2PolyDec.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_DEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_DEC_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * interpolation of lsf coefficients for the decoder
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_LspInterpolate2PolyDec(
+ int16_t* a, /* (o) lpc coefficients Q12 */
+ int16_t* lsf1, /* (i) first set of lsf coefficients Q13 */
+ int16_t* lsf2, /* (i) second set of lsf coefficients Q13 */
+ int16_t coef, /* (i) weighting coefficient to use between
+ lsf1 and lsf2 Q14 */
+ int16_t length /* (i) length of coefficient vectors */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c
new file mode 100644
index 0000000000..618821216c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/interpolate.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_to_poly.h"
+
+/*----------------------------------------------------------------*
+ * lsf interpolator and conversion from lsf to a coefficients
+ * (subrutine to SimpleInterpolateLSF)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_LsfInterpolate2PloyEnc(
+ int16_t *a, /* (o) lpc coefficients Q12 */
+ int16_t *lsf1, /* (i) first set of lsf coefficients Q13 */
+ int16_t *lsf2, /* (i) second set of lsf coefficients Q13 */
+ int16_t coef, /* (i) weighting coefficient to use between
+ lsf1 and lsf2 Q14 */
+ int16_t length /* (i) length of coefficient vectors */
+ ) {
+ /* Stack based */
+ int16_t lsftmp[LPC_FILTERORDER];
+
+ /* interpolate LSF */
+ WebRtcIlbcfix_Interpolate(lsftmp, lsf1, lsf2, coef, length);
+
+ /* Compute the filter coefficients from the LSF */
+ WebRtcIlbcfix_Lsf2Poly(a, lsftmp);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h
new file mode 100644
index 0000000000..b278a10f4b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_ENC_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_ENC_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * lsf interpolator and conversion from lsf to a coefficients
+ * (subrutine to SimpleInterpolateLSF)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_LsfInterpolate2PloyEnc(
+ int16_t* a, /* (o) lpc coefficients Q12 */
+ int16_t* lsf1, /* (i) first set of lsf coefficients Q13 */
+ int16_t* lsf2, /* (i) second set of lsf coefficients Q13 */
+ int16_t coef, /* (i) weighting coefficient to use between
+ lsf1 and lsf2 Q14 */
+ int16_t length /* (i) length of coefficient vectors */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c
new file mode 100644
index 0000000000..ee8292f394
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Lsf2Lsp.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lsf_to_lsp.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * conversion from lsf to lsp coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Lsf2Lsp(
+ int16_t *lsf, /* (i) lsf in Q13 values between 0 and pi */
+ int16_t *lsp, /* (o) lsp in Q15 values between -1 and 1 */
+ int16_t m /* (i) number of coefficients */
+ ) {
+ int16_t i, k;
+ int16_t diff; /* difference, which is used for the
+ linear approximation (Q8) */
+ int16_t freq; /* normalized frequency in Q15 (0..1) */
+ int32_t tmpW32;
+
+ for(i=0; i<m; i++)
+ {
+ freq = (int16_t)((lsf[i] * 20861) >> 15);
+ /* 20861: 1.0/(2.0*PI) in Q17 */
+ /*
+ Upper 8 bits give the index k and
+ Lower 8 bits give the difference, which needs
+ to be approximated linearly
+ */
+ k = freq >> 8;
+ diff = (freq&0x00ff);
+
+ /* Guard against getting outside table */
+
+ if (k>63) {
+ k = 63;
+ }
+
+ /* Calculate linear approximation */
+ tmpW32 = WebRtcIlbcfix_kCosDerivative[k] * diff;
+ lsp[i] = WebRtcIlbcfix_kCos[k] + (int16_t)(tmpW32 >> 12);
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h
new file mode 100644
index 0000000000..6bc6c44dbd
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Lsf2Lsp.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_LSP_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_LSP_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * conversion from lsf to lsp coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Lsf2Lsp(
+ int16_t* lsf, /* (i) lsf in Q13 values between 0 and pi */
+ int16_t* lsp, /* (o) lsp in Q15 values between -1 and 1 */
+ int16_t m /* (i) number of coefficients */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.c
new file mode 100644
index 0000000000..8ca91d82f8
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Lsf2Poly.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lsf_to_poly.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/get_lsp_poly.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_to_lsp.h"
+
+void WebRtcIlbcfix_Lsf2Poly(
+ int16_t *a, /* (o) predictor coefficients (order = 10) in Q12 */
+ int16_t *lsf /* (i) line spectral frequencies in Q13 */
+ ) {
+ int32_t f[2][6]; /* f[0][] and f[1][] corresponds to
+ F1(z) and F2(z) respectivly */
+ int32_t *f1ptr, *f2ptr;
+ int16_t *a1ptr, *a2ptr;
+ int32_t tmpW32;
+ int16_t lsp[10];
+ int i;
+
+ /* Convert lsf to lsp */
+ WebRtcIlbcfix_Lsf2Lsp(lsf, lsp, LPC_FILTERORDER);
+
+ /* Get F1(z) and F2(z) from the lsp */
+ f1ptr=f[0];
+ f2ptr=f[1];
+ WebRtcIlbcfix_GetLspPoly(&lsp[0],f1ptr);
+ WebRtcIlbcfix_GetLspPoly(&lsp[1],f2ptr);
+
+ /* for i = 5 down to 1
+ Compute f1[i] += f1[i-1];
+ and f2[i] += f2[i-1];
+ */
+ f1ptr=&f[0][5];
+ f2ptr=&f[1][5];
+ for (i=5; i>0; i--)
+ {
+ (*f1ptr) += (*(f1ptr-1));
+ (*f2ptr) -= (*(f2ptr-1));
+ f1ptr--;
+ f2ptr--;
+ }
+
+ /* Get the A(z) coefficients
+ a[0] = 1.0
+ for i = 1 to 5
+ a[i] = (f1[i] + f2[i] + round)>>13;
+ for i = 1 to 5
+ a[11-i] = (f1[i] - f2[i] + round)>>13;
+ */
+ a[0]=4096;
+ a1ptr=&a[1];
+ a2ptr=&a[10];
+ f1ptr=&f[0][1];
+ f2ptr=&f[1][1];
+ for (i=5; i>0; i--)
+ {
+ tmpW32 = (*f1ptr) + (*f2ptr);
+ *a1ptr = (int16_t)((tmpW32 + 4096) >> 13);
+
+ tmpW32 = (*f1ptr) - (*f2ptr);
+ *a2ptr = (int16_t)((tmpW32 + 4096) >> 13);
+
+ a1ptr++;
+ a2ptr--;
+ f1ptr++;
+ f2ptr++;
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.h
new file mode 100644
index 0000000000..f26d3a8d2d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsf_to_poly.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Lsf2Poly.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_POLY_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_POLY_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Convert from LSF coefficients to A coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Lsf2Poly(
+ int16_t* a, /* (o) predictor coefficients (order = 10) in Q12 */
+ int16_t* lsf /* (i) line spectral frequencies in Q13 */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c
new file mode 100644
index 0000000000..227f4d45b4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Lsp2Lsf.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/lsp_to_lsf.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * conversion from LSP coefficients to LSF coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Lsp2Lsf(
+ int16_t *lsp, /* (i) lsp vector -1...+1 in Q15 */
+ int16_t *lsf, /* (o) Lsf vector 0...Pi in Q13
+ (ordered, so that lsf[i]<lsf[i+1]) */
+ int16_t m /* (i) Number of coefficients */
+ )
+{
+ int16_t i, k;
+ int16_t diff; /* diff between table value and desired value (Q15) */
+ int16_t freq; /* lsf/(2*pi) (Q16) */
+ int16_t *lspPtr, *lsfPtr, *cosTblPtr;
+ int16_t tmp;
+
+ /* set the index to maximum index value in WebRtcIlbcfix_kCos */
+ k = 63;
+
+ /*
+ Start with the highest LSP and then work the way down
+ For each LSP the lsf is calculated by first order approximation
+ of the acos(x) function
+ */
+ lspPtr = &lsp[9];
+ lsfPtr = &lsf[9];
+ cosTblPtr=(int16_t*)&WebRtcIlbcfix_kCos[k];
+ for(i=m-1; i>=0; i--)
+ {
+ /*
+ locate value in the table, which is just above lsp[i],
+ basically an approximation to acos(x)
+ */
+ while( (((int32_t)(*cosTblPtr)-(*lspPtr)) < 0)&&(k>0) )
+ {
+ k-=1;
+ cosTblPtr--;
+ }
+
+ /* Calculate diff, which is used in the linear approximation of acos(x) */
+ diff = (*lspPtr)-(*cosTblPtr);
+
+ /*
+ The linear approximation of acos(lsp[i]) :
+ acos(lsp[i])= k*512 + (WebRtcIlbcfix_kAcosDerivative[ind]*offset >> 11)
+ */
+
+ /* tmp (linear offset) in Q16 */
+ tmp = (int16_t)((WebRtcIlbcfix_kAcosDerivative[k] * diff) >> 11);
+
+ /* freq in Q16 */
+ freq = (k << 9) + tmp;
+
+ /* lsf = freq*2*pi */
+ (*lsfPtr) = (int16_t)(((int32_t)freq*25736)>>15);
+
+ lsfPtr--;
+ lspPtr--;
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h
new file mode 100644
index 0000000000..c2f4b7692d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Lsp2Lsf.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSP_TO_LSF_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSP_TO_LSF_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * conversion from LSP coefficients to LSF coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Lsp2Lsf(
+ int16_t* lsp, /* (i) lsp vector -1...+1 in Q15 */
+ int16_t* lsf, /* (o) Lsf vector 0...Pi in Q13
+ (ordered, so that lsf[i]<lsf[i+1]) */
+ int16_t m /* (i) Number of coefficients */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.c
new file mode 100644
index 0000000000..9b870e0ef0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_MyCorr.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/my_corr.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * compute cross correlation between sequences
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_MyCorr(
+ int32_t* corr, /* (o) correlation of seq1 and seq2 */
+ const int16_t* seq1, /* (i) first sequence */
+ size_t dim1, /* (i) dimension first seq1 */
+ const int16_t* seq2, /* (i) second sequence */
+ size_t dim2 /* (i) dimension seq2 */
+ ){
+ uint32_t max1, max2;
+ size_t loops;
+ int right_shift;
+
+ // Calculate a right shift that will let us sum dim2 pairwise products of
+ // values from the two sequences without overflowing an int32_t. (The +1 in
+ // max1 and max2 are because WebRtcSpl_MaxAbsValueW16 will return 2**15 - 1
+ // if the input array contains -2**15.)
+ max1 = WebRtcSpl_MaxAbsValueW16(seq1, dim1) + 1;
+ max2 = WebRtcSpl_MaxAbsValueW16(seq2, dim2) + 1;
+ right_shift =
+ (64 - 31) - WebRtcSpl_CountLeadingZeros64((max1 * max2) * (uint64_t)dim2);
+ if (right_shift < 0) {
+ right_shift = 0;
+ }
+
+ loops=dim1-dim2+1;
+
+ /* Calculate the cross correlations */
+ WebRtcSpl_CrossCorrelation(corr, seq2, seq1, dim2, loops, right_shift, 1);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.h
new file mode 100644
index 0000000000..c0c2fa4a48
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/my_corr.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_MyCorr.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_MY_CORR_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_MY_CORR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * compute cross correlation between sequences
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_MyCorr(int32_t* corr, /* (o) correlation of seq1 and seq2 */
+ const int16_t* seq1, /* (i) first sequence */
+ size_t dim1, /* (i) dimension first seq1 */
+ const int16_t* seq2, /* (i) second sequence */
+ size_t dim2 /* (i) dimension seq2 */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.c
new file mode 100644
index 0000000000..1ecdd96d5a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_NearestNeighbor.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/nearest_neighbor.h"
+
+void WebRtcIlbcfix_NearestNeighbor(size_t* index,
+ const size_t* array,
+ size_t value,
+ size_t arlength) {
+ size_t i;
+ size_t min_diff = (size_t)-1;
+ for (i = 0; i < arlength; i++) {
+ const size_t diff =
+ (array[i] < value) ? (value - array[i]) : (array[i] - value);
+ if (diff < min_diff) {
+ *index = i;
+ min_diff = diff;
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.h
new file mode 100644
index 0000000000..704cf2a37d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/nearest_neighbor.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_NearestNeighbor.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_NEAREST_NEIGHBOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_NEAREST_NEIGHBOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Find index in array such that the array element with said
+ * index is the element of said array closest to "value"
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_NearestNeighbor(
+ size_t* index, /* (o) index of array element closest to value */
+ const size_t* array, /* (i) data array (Q2) */
+ size_t value, /* (i) value (Q2) */
+ size_t arlength /* (i) dimension of data array (==ENH_NBLOCKS_TOT) */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.c
new file mode 100644
index 0000000000..dd44eb8fb6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_PackBits.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/pack_bits.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * unpacking of bits from bitstream, i.e., vector of bytes
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_PackBits(
+ uint16_t *bitstream, /* (o) The packetized bitstream */
+ iLBC_bits *enc_bits, /* (i) Encoded bits */
+ int16_t mode /* (i) Codec mode (20 or 30) */
+ ){
+ uint16_t *bitstreamPtr;
+ int i, k;
+ int16_t *tmpPtr;
+
+ bitstreamPtr=bitstream;
+
+ /* Class 1 bits of ULP */
+ /* First int16_t */
+ (*bitstreamPtr) = ((uint16_t)enc_bits->lsf[0])<<10; /* Bit 0..5 */
+ (*bitstreamPtr) |= (enc_bits->lsf[1])<<3; /* Bit 6..12 */
+ (*bitstreamPtr) |= (enc_bits->lsf[2]&0x70)>>4; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* Second int16_t */
+ (*bitstreamPtr) = ((uint16_t)enc_bits->lsf[2]&0xF)<<12; /* Bit 0..3 */
+
+ if (mode==20) {
+ (*bitstreamPtr) |= (enc_bits->startIdx)<<10; /* Bit 4..5 */
+ (*bitstreamPtr) |= (enc_bits->state_first)<<9; /* Bit 6 */
+ (*bitstreamPtr) |= (enc_bits->idxForMax)<<3; /* Bit 7..12 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[0])&0x70)>>4; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* Third int16_t */
+ (*bitstreamPtr) = ((enc_bits->cb_index[0])&0xE)<<12; /* Bit 0..2 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[0])&0x18)<<8; /* Bit 3..4 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[1])&0x8)<<7; /* Bit 5 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[3])&0xFE)<<2; /* Bit 6..12 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[3])&0x10)>>2; /* Bit 13 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[4])&0x8)>>2; /* Bit 14 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[6])&0x10)>>4; /* Bit 15 */
+ } else { /* mode==30 */
+ (*bitstreamPtr) |= (enc_bits->lsf[3])<<6; /* Bit 4..9 */
+ (*bitstreamPtr) |= (enc_bits->lsf[4]&0x7E)>>1; /* Bit 10..15 */
+ bitstreamPtr++;
+ /* Third int16_t */
+ (*bitstreamPtr) = ((uint16_t)enc_bits->lsf[4]&0x1)<<15; /* Bit 0 */
+ (*bitstreamPtr) |= (enc_bits->lsf[5])<<8; /* Bit 1..7 */
+ (*bitstreamPtr) |= (enc_bits->startIdx)<<5; /* Bit 8..10 */
+ (*bitstreamPtr) |= (enc_bits->state_first)<<4; /* Bit 11 */
+ (*bitstreamPtr) |= ((enc_bits->idxForMax)&0x3C)>>2; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 4:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)enc_bits->idxForMax&0x3)<<14; /* Bit 0..1 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[0]&0x78)<<7; /* Bit 2..5 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[0]&0x10)<<5; /* Bit 6 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[1]&0x8)<<5; /* Bit 7 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[3]&0xFC); /* Bit 8..13 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[3]&0x10)>>3; /* Bit 14 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[4]&0x8)>>3; /* Bit 15 */
+ }
+ /* Class 2 bits of ULP */
+ /* 4:th to 6:th int16_t for 20 ms case
+ 5:th to 7:th int16_t for 30 ms case */
+ bitstreamPtr++;
+ tmpPtr=enc_bits->idxVec;
+ for (k=0; k<3; k++) {
+ (*bitstreamPtr) = 0;
+ for (i=15; i>=0; i--) {
+ (*bitstreamPtr) |= ((uint16_t)((*tmpPtr)&0x4)>>2)<<i;
+ /* Bit 15-i */
+ tmpPtr++;
+ }
+ bitstreamPtr++;
+ }
+
+ if (mode==20) {
+ /* 7:th int16_t */
+ (*bitstreamPtr) = 0;
+ for (i=15; i>6; i--) {
+ (*bitstreamPtr) |= ((uint16_t)((*tmpPtr)&0x4)>>2)<<i;
+ /* Bit 15-i */
+ tmpPtr++;
+ }
+ (*bitstreamPtr) |= (enc_bits->gain_index[1]&0x4)<<4; /* Bit 9 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[3]&0xC)<<2; /* Bit 10..11 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[4]&0x4)<<1; /* Bit 12 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[6]&0x8)>>1; /* Bit 13 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[7]&0xC)>>2; /* Bit 14..15 */
+
+ } else { /* mode==30 */
+ /* 8:th int16_t */
+ (*bitstreamPtr) = 0;
+ for (i=15; i>5; i--) {
+ (*bitstreamPtr) |= ((uint16_t)((*tmpPtr)&0x4)>>2)<<i;
+ /* Bit 15-i */
+ tmpPtr++;
+ }
+ (*bitstreamPtr) |= (enc_bits->cb_index[0]&0x6)<<3; /* Bit 10..11 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[0]&0x8); /* Bit 12 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[1]&0x4); /* Bit 13 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[3]&0x2); /* Bit 14 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[6]&0x80)>>7; /* Bit 15 */
+ bitstreamPtr++;
+ /* 9:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)enc_bits->cb_index[6]&0x7E)<<9;/* Bit 0..5 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[9]&0xFE)<<2; /* Bit 6..12 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[12]&0xE0)>>5; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* 10:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)enc_bits->cb_index[12]&0x1E)<<11;/* Bit 0..3 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[3]&0xC)<<8; /* Bit 4..5 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[4]&0x6)<<7; /* Bit 6..7 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[6]&0x18)<<3; /* Bit 8..9 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[7]&0xC)<<2; /* Bit 10..11 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[9]&0x10)>>1; /* Bit 12 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[10]&0x8)>>1; /* Bit 13 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[12]&0x10)>>3; /* Bit 14 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[13]&0x8)>>3; /* Bit 15 */
+ }
+ bitstreamPtr++;
+ /* Class 3 bits of ULP */
+ /* 8:th to 14:th int16_t for 20 ms case
+ 11:th to 17:th int16_t for 30 ms case */
+ tmpPtr=enc_bits->idxVec;
+ for (k=0; k<7; k++) {
+ (*bitstreamPtr) = 0;
+ for (i=14; i>=0; i-=2) {
+ (*bitstreamPtr) |= ((uint16_t)((*tmpPtr)&0x3))<<i; /* Bit 15-i..14-i*/
+ tmpPtr++;
+ }
+ bitstreamPtr++;
+ }
+
+ if (mode==20) {
+ /* 15:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)((enc_bits->idxVec[56])&0x3))<<14;/* Bit 0..1 */
+ (*bitstreamPtr) |= (((enc_bits->cb_index[0])&1))<<13; /* Bit 2 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[1]))<<6; /* Bit 3..9 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[2])&0x7E)>>1; /* Bit 10..15 */
+ bitstreamPtr++;
+ /* 16:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)((enc_bits->cb_index[2])&0x1))<<15;
+ /* Bit 0 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[0])&0x7)<<12; /* Bit 1..3 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[1])&0x3)<<10; /* Bit 4..5 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[2]))<<7; /* Bit 6..8 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[3])&0x1)<<6; /* Bit 9 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[4])&0x7E)>>1; /* Bit 10..15 */
+ bitstreamPtr++;
+ /* 17:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)((enc_bits->cb_index[4])&0x1))<<15;
+ /* Bit 0 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[5])<<8; /* Bit 1..7 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[6]); /* Bit 8..15 */
+ bitstreamPtr++;
+ /* 18:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->cb_index[7]))<<8; /* Bit 0..7 */
+ (*bitstreamPtr) |= (enc_bits->cb_index[8]); /* Bit 8..15 */
+ bitstreamPtr++;
+ /* 19:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)((enc_bits->gain_index[3])&0x3))<<14;
+ /* Bit 0..1 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[4])&0x3)<<12; /* Bit 2..3 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[5]))<<9; /* Bit 4..6 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[6])&0x7)<<6; /* Bit 7..9 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[7])&0x3)<<4; /* Bit 10..11 */
+ (*bitstreamPtr) |= (enc_bits->gain_index[8])<<1; /* Bit 12..14 */
+ } else { /* mode==30 */
+ /* 18:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)((enc_bits->idxVec[56])&0x3))<<14;/* Bit 0..1 */
+ (*bitstreamPtr) |= (((enc_bits->idxVec[57])&0x3))<<12; /* Bit 2..3 */
+ (*bitstreamPtr) |= (((enc_bits->cb_index[0])&1))<<11; /* Bit 4 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[1]))<<4; /* Bit 5..11 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[2])&0x78)>>3; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 19:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->cb_index[2])&0x7)<<13;
+ /* Bit 0..2 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[0])&0x7)<<10; /* Bit 3..5 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[1])&0x3)<<8; /* Bit 6..7 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[2])&0x7)<<5; /* Bit 8..10 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[3])&0x1)<<4; /* Bit 11 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[4])&0x78)>>3; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 20:th int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->cb_index[4])&0x7)<<13;
+ /* Bit 0..2 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[5]))<<6; /* Bit 3..9 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[6])&0x1)<<5; /* Bit 10 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[7])&0xF8)>>3; /* Bit 11..15 */
+ bitstreamPtr++;
+ /* 21:st int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->cb_index[7])&0x7)<<13;
+ /* Bit 0..2 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[8]))<<5; /* Bit 3..10 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[9])&0x1)<<4; /* Bit 11 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[10])&0xF0)>>4; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 22:nd int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->cb_index[10])&0xF)<<12;
+ /* Bit 0..3 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[11]))<<4; /* Bit 4..11 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[12])&0x1)<<3; /* Bit 12 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[13])&0xE0)>>5; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* 23:rd int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->cb_index[13])&0x1F)<<11;
+ /* Bit 0..4 */
+ (*bitstreamPtr) |= ((enc_bits->cb_index[14]))<<3; /* Bit 5..12 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[3])&0x3)<<1; /* Bit 13..14 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[4])&0x1); /* Bit 15 */
+ bitstreamPtr++;
+ /* 24:rd int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->gain_index[5]))<<13;
+ /* Bit 0..2 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[6])&0x7)<<10; /* Bit 3..5 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[7])&0x3)<<8; /* Bit 6..7 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[8]))<<5; /* Bit 8..10 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[9])&0xF)<<1; /* Bit 11..14 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[10])&0x4)>>2; /* Bit 15 */
+ bitstreamPtr++;
+ /* 25:rd int16_t */
+ (*bitstreamPtr) = ((uint16_t)(enc_bits->gain_index[10])&0x3)<<14;
+ /* Bit 0..1 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[11]))<<11; /* Bit 2..4 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[12])&0xF)<<7; /* Bit 5..8 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[13])&0x7)<<4; /* Bit 9..11 */
+ (*bitstreamPtr) |= ((enc_bits->gain_index[14]))<<1; /* Bit 12..14 */
+ }
+ /* Last bit is automatically zero */
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.h
new file mode 100644
index 0000000000..8dcf41ce08
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/pack_bits.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_PackBits.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_PACK_BITS_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_PACK_BITS_H_
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * unpacking of bits from bitstream, i.e., vector of bytes
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_PackBits(
+ uint16_t* bitstream, /* (o) The packetized bitstream */
+ iLBC_bits* enc_bits, /* (i) Encoded bits */
+ int16_t mode /* (i) Codec mode (20 or 30) */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.c
new file mode 100644
index 0000000000..7192eaab49
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Poly2Lsf.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsf.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/lsp_to_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsp.h"
+
+void WebRtcIlbcfix_Poly2Lsf(
+ int16_t *lsf, /* (o) lsf coefficients (Q13) */
+ int16_t *a /* (i) A coefficients (Q12) */
+ ) {
+ int16_t lsp[10];
+ WebRtcIlbcfix_Poly2Lsp(a, lsp, (int16_t*)WebRtcIlbcfix_kLspMean);
+ WebRtcIlbcfix_Lsp2Lsf(lsp, lsf, 10);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.h
new file mode 100644
index 0000000000..363e392bb2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsf.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Poly2Lsf.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSF_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSF_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * conversion from lpc coefficients to lsf coefficients
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Poly2Lsf(int16_t* lsf, /* (o) lsf coefficients (Q13) */
+ int16_t* a /* (i) A coefficients (Q12) */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.c
new file mode 100644
index 0000000000..ad0ecd70ab
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Poly2Lsp.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsp.h"
+
+#include "modules/audio_coding/codecs/ilbc/chebyshev.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+
+/*----------------------------------------------------------------*
+ * conversion from lpc coefficients to lsp coefficients
+ * function is only for 10:th order LPC
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Poly2Lsp(
+ int16_t *a, /* (o) A coefficients in Q12 */
+ int16_t *lsp, /* (i) LSP coefficients in Q15 */
+ int16_t *old_lsp /* (i) old LSP coefficients that are used if the new
+ coefficients turn out to be unstable */
+ ) {
+ int16_t f[2][6]; /* f[0][] represents f1 and f[1][] represents f2 */
+ int16_t *a_i_ptr, *a_10mi_ptr;
+ int16_t *f1ptr, *f2ptr;
+ int32_t tmpW32;
+ int16_t x, y, xlow, ylow, xmid, ymid, xhigh, yhigh, xint;
+ int16_t shifts, sign;
+ int i, j;
+ int foundFreqs;
+ int fi_select;
+
+ /*
+ Calculate the two polynomials f1(z) and f2(z)
+ (the sum and the diff polynomial)
+ f1[0] = f2[0] = 1.0;
+ f1[i+1] = a[i+1] + a[10-i] - f1[i];
+ f2[i+1] = a[i+1] - a[10-i] - f1[i];
+ */
+
+ a_i_ptr = a + 1;
+ a_10mi_ptr = a + 10;
+ f1ptr = f[0];
+ f2ptr = f[1];
+ (*f1ptr) = 1024; /* 1.0 in Q10 */
+ (*f2ptr) = 1024; /* 1.0 in Q10 */
+ for (i = 0; i < 5; i++) {
+ *(f1ptr + 1) =
+ (int16_t)((((int32_t)(*a_i_ptr) + *a_10mi_ptr) >> 2) - *f1ptr);
+ *(f2ptr + 1) =
+ (int16_t)((((int32_t)(*a_i_ptr) - *a_10mi_ptr) >> 2) + *f2ptr);
+ a_i_ptr++;
+ a_10mi_ptr--;
+ f1ptr++;
+ f2ptr++;
+ }
+
+ /*
+ find the LSPs using the Chebychev pol. evaluation
+ */
+
+ fi_select = 0; /* selector between f1 and f2, start with f1 */
+
+ foundFreqs = 0;
+
+ xlow = WebRtcIlbcfix_kCosGrid[0];
+ ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
+
+ /*
+ Iterate until all the 10 LSP's have been found or
+ all the grid points have been tried. If the 10 LSP's can
+ not be found, set the LSP vector to previous LSP
+ */
+
+ for (j = 1; j < COS_GRID_POINTS && foundFreqs < 10; j++) {
+ xhigh = xlow;
+ yhigh = ylow;
+ xlow = WebRtcIlbcfix_kCosGrid[j];
+ ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
+
+ if (ylow * yhigh <= 0) {
+ /* Run 4 times to reduce the interval */
+ for (i = 0; i < 4; i++) {
+ /* xmid =(xlow + xhigh)/2 */
+ xmid = (xlow >> 1) + (xhigh >> 1);
+ ymid = WebRtcIlbcfix_Chebyshev(xmid, f[fi_select]);
+
+ if (ylow * ymid <= 0) {
+ yhigh = ymid;
+ xhigh = xmid;
+ } else {
+ ylow = ymid;
+ xlow = xmid;
+ }
+ }
+
+ /*
+ Calculater xint by linear interpolation:
+ xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);
+ */
+
+ x = xhigh - xlow;
+ y = yhigh - ylow;
+
+ if (y == 0) {
+ xint = xlow;
+ } else {
+ sign = y;
+ y = WEBRTC_SPL_ABS_W16(y);
+ shifts = (int16_t)WebRtcSpl_NormW32(y)-16;
+ y <<= shifts;
+ y = (int16_t)WebRtcSpl_DivW32W16(536838144, y); /* 1/(yhigh-ylow) */
+
+ tmpW32 = (x * y) >> (19 - shifts);
+
+ /* y=(xhigh-xlow)/(yhigh-ylow) */
+ y = (int16_t)(tmpW32&0xFFFF);
+
+ if (sign < 0) {
+ y = -y;
+ }
+ /* tmpW32 = ylow*(xhigh-xlow)/(yhigh-ylow) */
+ tmpW32 = (ylow * y) >> 10;
+ xint = xlow-(int16_t)(tmpW32&0xFFFF);
+ }
+
+ /* Store the calculated lsp */
+ lsp[foundFreqs] = (int16_t)xint;
+ foundFreqs++;
+
+ /* if needed, set xlow and ylow for next recursion */
+ if (foundFreqs<10) {
+ xlow = xint;
+ /* Swap between f1 and f2 (f[0][] and f[1][]) */
+ fi_select = ((fi_select+1)&0x1);
+
+ ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
+ }
+ }
+ }
+
+ /* Check if M roots found, if not then use the old LSP */
+ if (foundFreqs < 10) {
+ WEBRTC_SPL_MEMCPY_W16(lsp, old_lsp, 10);
+ }
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.h
new file mode 100644
index 0000000000..928ee4efdb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/poly_to_lsp.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Poly2Lsp.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSP_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSP_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * conversion from lpc coefficients to lsp coefficients
+ * function is only for 10:th order LPC
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Poly2Lsp(
+ int16_t* a, /* (o) A coefficients in Q12 */
+ int16_t* lsp, /* (i) LSP coefficients in Q15 */
+ int16_t* old_lsp /* (i) old LSP coefficients that are used if the new
+ coefficients turn out to be unstable */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.c
new file mode 100644
index 0000000000..5bdab7a4b0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Refiner.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/refiner.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/enh_upsample.h"
+#include "modules/audio_coding/codecs/ilbc/my_corr.h"
+
+/*----------------------------------------------------------------*
+ * find segment starting near idata+estSegPos that has highest
+ * correlation with idata+centerStartPos through
+ * idata+centerStartPos+ENH_BLOCKL-1 segment is found at a
+ * resolution of ENH_UPSO times the original of the original
+ * sampling rate
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Refiner(
+ size_t *updStartPos, /* (o) updated start point (Q-2) */
+ int16_t *idata, /* (i) original data buffer */
+ size_t idatal, /* (i) dimension of idata */
+ size_t centerStartPos, /* (i) beginning center segment */
+ size_t estSegPos, /* (i) estimated beginning other segment (Q-2) */
+ int16_t *surround, /* (i/o) The contribution from this sequence
+ summed with earlier contributions */
+ int16_t gain /* (i) Gain to use for this sequence */
+ ){
+ size_t estSegPosRounded, searchSegStartPos, searchSegEndPos, corrdim;
+ size_t tloc, tloc2, i;
+
+ int32_t maxtemp, scalefact;
+ int16_t *filtStatePtr, *polyPtr;
+ /* Stack based */
+ int16_t filt[7];
+ int32_t corrVecUps[ENH_CORRDIM*ENH_UPS0];
+ int32_t corrVecTemp[ENH_CORRDIM];
+ int16_t vect[ENH_VECTL];
+ int16_t corrVec[ENH_CORRDIM];
+
+ /* defining array bounds */
+
+ estSegPosRounded = (estSegPos - 2) >> 2;
+
+ searchSegStartPos =
+ (estSegPosRounded < ENH_SLOP) ? 0 : (estSegPosRounded - ENH_SLOP);
+
+ searchSegEndPos = estSegPosRounded + ENH_SLOP;
+ if ((searchSegEndPos + ENH_BLOCKL) >= idatal) {
+ searchSegEndPos = idatal - ENH_BLOCKL - 1;
+ }
+
+ corrdim = searchSegEndPos + 1 - searchSegStartPos;
+
+ /* compute upsampled correlation and find
+ location of max */
+
+ WebRtcIlbcfix_MyCorr(corrVecTemp, idata + searchSegStartPos,
+ corrdim + ENH_BLOCKL - 1, idata + centerStartPos,
+ ENH_BLOCKL);
+
+ /* Calculate the rescaling factor for the correlation in order to
+ put the correlation in a int16_t vector instead */
+ maxtemp = WebRtcSpl_MaxAbsValueW32(corrVecTemp, corrdim);
+
+ scalefact = WebRtcSpl_GetSizeInBits(maxtemp) - 15;
+
+ if (scalefact > 0) {
+ for (i = 0; i < corrdim; i++) {
+ corrVec[i] = (int16_t)(corrVecTemp[i] >> scalefact);
+ }
+ } else {
+ for (i = 0; i < corrdim; i++) {
+ corrVec[i] = (int16_t)corrVecTemp[i];
+ }
+ }
+ /* In order to guarantee that all values are initialized */
+ for (i = corrdim; i < ENH_CORRDIM; i++) {
+ corrVec[i] = 0;
+ }
+
+ /* Upsample the correlation */
+ WebRtcIlbcfix_EnhUpsample(corrVecUps, corrVec);
+
+ /* Find maximum */
+ tloc = WebRtcSpl_MaxIndexW32(corrVecUps, ENH_UPS0 * corrdim);
+
+ /* make vector can be upsampled without ever running outside
+ bounds */
+ *updStartPos = searchSegStartPos * 4 + tloc + 4;
+
+ tloc2 = (tloc + 3) >> 2;
+
+ /* initialize the vector to be filtered, stuff with zeros
+ when data is outside idata buffer */
+ if (ENH_FL0 > (searchSegStartPos + tloc2)) {
+ const size_t st = ENH_FL0 - searchSegStartPos - tloc2;
+ WebRtcSpl_MemSetW16(vect, 0, st);
+ WEBRTC_SPL_MEMCPY_W16(&vect[st], idata, ENH_VECTL - st);
+ } else {
+ const size_t st = searchSegStartPos + tloc2 - ENH_FL0;
+ if ((st + ENH_VECTL) > idatal) {
+ const size_t en = st + ENH_VECTL - idatal;
+ WEBRTC_SPL_MEMCPY_W16(vect, &idata[st], ENH_VECTL - en);
+ WebRtcSpl_MemSetW16(&vect[ENH_VECTL - en], 0, en);
+ } else {
+ WEBRTC_SPL_MEMCPY_W16(vect, &idata[st], ENH_VECTL);
+ }
+ }
+
+ /* compute the segment (this is actually a convolution) */
+ filtStatePtr = filt + 6;
+ polyPtr = (int16_t*)WebRtcIlbcfix_kEnhPolyPhaser[tloc2 * ENH_UPS0 - tloc];
+ for (i = 0; i < 7; i++) {
+ *filtStatePtr-- = *polyPtr++;
+ }
+
+ WebRtcSpl_FilterMAFastQ12(&vect[6], vect, filt, ENH_FLO_MULT2_PLUS1,
+ ENH_BLOCKL);
+
+ /* Add the contribution from this vector (scaled with gain) to the total
+ surround vector */
+ WebRtcSpl_AddAffineVectorToVector(surround, vect, gain, 32768, 16,
+ ENH_BLOCKL);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.h
new file mode 100644
index 0000000000..564c9d96e6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/refiner.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Refiner.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_REFINER_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_REFINER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * find segment starting near idata+estSegPos that has highest
+ * correlation with idata+centerStartPos through
+ * idata+centerStartPos+ENH_BLOCKL-1 segment is found at a
+ * resolution of ENH_UPSO times the original of the original
+ * sampling rate
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Refiner(
+ size_t* updStartPos, /* (o) updated start point (Q-2) */
+ int16_t* idata, /* (i) original data buffer */
+ size_t idatal, /* (i) dimension of idata */
+ size_t centerStartPos, /* (i) beginning center segment */
+ size_t estSegPos, /* (i) estimated beginning other segment (Q-2) */
+ int16_t* surround, /* (i/o) The contribution from this sequence
+ summed with earlier contributions */
+ int16_t gain /* (i) Gain to use for this sequence */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c
new file mode 100644
index 0000000000..7343530a5e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleInterpolateLsf.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h"
+
+#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h"
+
+/*----------------------------------------------------------------*
+ * lsf interpolator (subrutine to LPCencode)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleInterpolateLsf(
+ int16_t *syntdenum, /* (o) the synthesis filter denominator
+ resulting from the quantized
+ interpolated lsf Q12 */
+ int16_t *weightdenum, /* (o) the weighting filter denominator
+ resulting from the unquantized
+ interpolated lsf Q12 */
+ int16_t *lsf, /* (i) the unquantized lsf coefficients Q13 */
+ int16_t *lsfdeq, /* (i) the dequantized lsf coefficients Q13 */
+ int16_t *lsfold, /* (i) the unquantized lsf coefficients of
+ the previous signal frame Q13 */
+ int16_t *lsfdeqold, /* (i) the dequantized lsf coefficients of the
+ previous signal frame Q13 */
+ int16_t length, /* (i) should equate FILTERORDER */
+ IlbcEncoder *iLBCenc_inst
+ /* (i/o) the encoder state structure */
+ ) {
+ size_t i;
+ int pos, lp_length;
+
+ int16_t *lsf2, *lsfdeq2;
+ /* Stack based */
+ int16_t lp[LPC_FILTERORDER + 1];
+
+ lsf2 = lsf + length;
+ lsfdeq2 = lsfdeq + length;
+ lp_length = length + 1;
+
+ if (iLBCenc_inst->mode==30) {
+ /* subframe 1: Interpolation between old and first set of
+ lsf coefficients */
+
+ /* Calculate Analysis/Syntehsis filter from quantized LSF */
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc(lp, lsfdeqold, lsfdeq,
+ WebRtcIlbcfix_kLsfWeight30ms[0],
+ length);
+ WEBRTC_SPL_MEMCPY_W16(syntdenum, lp, lp_length);
+
+ /* Calculate Weighting filter from quantized LSF */
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc(lp, lsfold, lsf,
+ WebRtcIlbcfix_kLsfWeight30ms[0],
+ length);
+ WebRtcIlbcfix_BwExpand(weightdenum, lp,
+ (int16_t*)WebRtcIlbcfix_kLpcChirpWeightDenum,
+ (int16_t)lp_length);
+
+ /* subframe 2 to 6: Interpolation between first and second
+ set of lsf coefficients */
+
+ pos = lp_length;
+ for (i = 1; i < iLBCenc_inst->nsub; i++) {
+
+ /* Calculate Analysis/Syntehsis filter from quantized LSF */
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc(lp, lsfdeq, lsfdeq2,
+ WebRtcIlbcfix_kLsfWeight30ms[i],
+ length);
+ WEBRTC_SPL_MEMCPY_W16(syntdenum + pos, lp, lp_length);
+
+ /* Calculate Weighting filter from quantized LSF */
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc(lp, lsf, lsf2,
+ WebRtcIlbcfix_kLsfWeight30ms[i],
+ length);
+ WebRtcIlbcfix_BwExpand(weightdenum + pos, lp,
+ (int16_t*)WebRtcIlbcfix_kLpcChirpWeightDenum,
+ (int16_t)lp_length);
+
+ pos += lp_length;
+ }
+
+ /* update memory */
+
+ WEBRTC_SPL_MEMCPY_W16(lsfold, lsf2, length);
+ WEBRTC_SPL_MEMCPY_W16(lsfdeqold, lsfdeq2, length);
+
+ } else { /* iLBCenc_inst->mode==20 */
+ pos = 0;
+ for (i = 0; i < iLBCenc_inst->nsub; i++) {
+
+ /* Calculate Analysis/Syntehsis filter from quantized LSF */
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc(lp, lsfdeqold, lsfdeq,
+ WebRtcIlbcfix_kLsfWeight20ms[i],
+ length);
+ WEBRTC_SPL_MEMCPY_W16(syntdenum + pos, lp, lp_length);
+
+ /* Calculate Weighting filter from quantized LSF */
+ WebRtcIlbcfix_LsfInterpolate2PloyEnc(lp, lsfold, lsf,
+ WebRtcIlbcfix_kLsfWeight20ms[i],
+ length);
+ WebRtcIlbcfix_BwExpand(weightdenum+pos, lp,
+ (int16_t*)WebRtcIlbcfix_kLpcChirpWeightDenum,
+ (int16_t)lp_length);
+
+ pos += lp_length;
+ }
+
+ /* update memory */
+
+ WEBRTC_SPL_MEMCPY_W16(lsfold, lsf, length);
+ WEBRTC_SPL_MEMCPY_W16(lsfdeqold, lsfdeq, length);
+
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h
new file mode 100644
index 0000000000..ee53e4bd08
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleInterpolateLsf.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_INTERPOLATE_LSF_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_INTERPOLATE_LSF_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * lsf interpolator (subrutine to LPCencode)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleInterpolateLsf(
+ int16_t* syntdenum, /* (o) the synthesis filter denominator
+ resulting from the quantized
+ interpolated lsf Q12 */
+ int16_t* weightdenum, /* (o) the weighting filter denominator
+ resulting from the unquantized
+ interpolated lsf Q12 */
+ int16_t* lsf, /* (i) the unquantized lsf coefficients Q13 */
+ int16_t* lsfdeq, /* (i) the dequantized lsf coefficients Q13 */
+ int16_t* lsfold, /* (i) the unquantized lsf coefficients of
+ the previous signal frame Q13 */
+ int16_t* lsfdeqold, /* (i) the dequantized lsf coefficients of the
+ previous signal frame Q13 */
+ int16_t length, /* (i) should equate FILTERORDER */
+ IlbcEncoder* iLBCenc_inst
+ /* (i/o) the encoder state structure */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c
new file mode 100644
index 0000000000..fdc4553d95
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleLpcAnalysis.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h"
+
+#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/window32_w32.h"
+
+/*----------------------------------------------------------------*
+ * lpc analysis (subrutine to LPCencode)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleLpcAnalysis(
+ int16_t *lsf, /* (o) lsf coefficients */
+ int16_t *data, /* (i) new block of speech */
+ IlbcEncoder *iLBCenc_inst
+ /* (i/o) the encoder state structure */
+ ) {
+ int k;
+ int scale;
+ size_t is;
+ int16_t stability;
+ /* Stack based */
+ int16_t A[LPC_FILTERORDER + 1];
+ int32_t R[LPC_FILTERORDER + 1];
+ int16_t windowedData[BLOCKL_MAX];
+ int16_t rc[LPC_FILTERORDER];
+
+ is=LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl;
+ WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lpc_buffer+is,data,iLBCenc_inst->blockl);
+
+ /* No lookahead, last window is asymmetric */
+
+ for (k = 0; k < iLBCenc_inst->lpc_n; k++) {
+
+ is = LPC_LOOKBACK;
+
+ if (k < (iLBCenc_inst->lpc_n - 1)) {
+
+ /* Hanning table WebRtcIlbcfix_kLpcWin[] is in Q15-domain so the output is right-shifted 15 */
+ WebRtcSpl_ElementwiseVectorMult(windowedData, iLBCenc_inst->lpc_buffer, WebRtcIlbcfix_kLpcWin, BLOCKL_MAX, 15);
+ } else {
+
+ /* Hanning table WebRtcIlbcfix_kLpcAsymWin[] is in Q15-domain so the output is right-shifted 15 */
+ WebRtcSpl_ElementwiseVectorMult(windowedData, iLBCenc_inst->lpc_buffer+is, WebRtcIlbcfix_kLpcAsymWin, BLOCKL_MAX, 15);
+ }
+
+ /* Compute autocorrelation */
+ WebRtcSpl_AutoCorrelation(windowedData, BLOCKL_MAX, LPC_FILTERORDER, R, &scale);
+
+ /* Window autocorrelation vector */
+ WebRtcIlbcfix_Window32W32(R, R, WebRtcIlbcfix_kLpcLagWin, LPC_FILTERORDER + 1 );
+
+ /* Calculate the A coefficients from the Autocorrelation using Levinson Durbin algorithm */
+ stability=WebRtcSpl_LevinsonDurbin(R, A, rc, LPC_FILTERORDER);
+
+ /*
+ Set the filter to {1.0, 0.0, 0.0,...} if filter from Levinson Durbin algorithm is unstable
+ This should basically never happen...
+ */
+ if (stability!=1) {
+ A[0]=4096;
+ WebRtcSpl_MemSetW16(&A[1], 0, LPC_FILTERORDER);
+ }
+
+ /* Bandwidth expand the filter coefficients */
+ WebRtcIlbcfix_BwExpand(A, A, (int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, LPC_FILTERORDER+1);
+
+ /* Convert from A to LSF representation */
+ WebRtcIlbcfix_Poly2Lsf(lsf + k*LPC_FILTERORDER, A);
+ }
+
+ is=LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl;
+ WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->lpc_buffer,
+ iLBCenc_inst->lpc_buffer+LPC_LOOKBACK+BLOCKL_MAX-is, is);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h
new file mode 100644
index 0000000000..b5c839ba2a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleLpcAnalysis.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LPC_ANALYSIS_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LPC_ANALYSIS_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * lpc analysis (subrutine to LPCencode)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleLpcAnalysis(
+ int16_t* lsf, /* (o) lsf coefficients */
+ int16_t* data, /* (i) new block of speech */
+ IlbcEncoder* iLBCenc_inst
+ /* (i/o) the encoder state structure */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c
new file mode 100644
index 0000000000..e7494ceb59
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleLsfDeQ.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * obtain dequantized lsf coefficients from quantization index
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleLsfDeQ(
+ int16_t *lsfdeq, /* (o) dequantized lsf coefficients */
+ int16_t *index, /* (i) quantization index */
+ int16_t lpc_n /* (i) number of LPCs */
+ ){
+ int i, j, pos, cb_pos;
+
+ /* decode first LSF */
+
+ pos = 0;
+ cb_pos = 0;
+ for (i = 0; i < LSF_NSPLIT; i++) {
+ for (j = 0; j < WebRtcIlbcfix_kLsfDimCb[i]; j++) {
+ lsfdeq[pos + j] = WebRtcIlbcfix_kLsfCb[cb_pos + j + index[i] *
+ WebRtcIlbcfix_kLsfDimCb[i]];
+ }
+ pos += WebRtcIlbcfix_kLsfDimCb[i];
+ cb_pos += WebRtcIlbcfix_kLsfSizeCb[i] * WebRtcIlbcfix_kLsfDimCb[i];
+ }
+
+ if (lpc_n>1) {
+ /* decode last LSF */
+ pos = 0;
+ cb_pos = 0;
+ for (i = 0; i < LSF_NSPLIT; i++) {
+ for (j = 0; j < WebRtcIlbcfix_kLsfDimCb[i]; j++) {
+ lsfdeq[LPC_FILTERORDER + pos + j] = WebRtcIlbcfix_kLsfCb[
+ cb_pos + index[LSF_NSPLIT + i] * WebRtcIlbcfix_kLsfDimCb[i] + j];
+ }
+ pos += WebRtcIlbcfix_kLsfDimCb[i];
+ cb_pos += WebRtcIlbcfix_kLsfSizeCb[i] * WebRtcIlbcfix_kLsfDimCb[i];
+ }
+ }
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h
new file mode 100644
index 0000000000..6d97d3df33
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleLsfDeQ.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_DEQUANT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_DEQUANT_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * obtain dequantized lsf coefficients from quantization index
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleLsfDeQ(
+ int16_t* lsfdeq, /* (o) dequantized lsf coefficients */
+ int16_t* index, /* (i) quantization index */
+ int16_t lpc_n /* (i) number of LPCs */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c
new file mode 100644
index 0000000000..1291d1442e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleLsfQ.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_quant.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/split_vq.h"
+
+/*----------------------------------------------------------------*
+ * lsf quantizer (subrutine to LPCencode)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleLsfQ(
+ int16_t *lsfdeq, /* (o) dequantized lsf coefficients
+ (dimension FILTERORDER) Q13 */
+ int16_t *index, /* (o) quantization index */
+ int16_t *lsf, /* (i) the lsf coefficient vector to be
+ quantized (dimension FILTERORDER) Q13 */
+ int16_t lpc_n /* (i) number of lsf sets to quantize */
+ ){
+
+ /* Quantize first LSF with memoryless split VQ */
+ WebRtcIlbcfix_SplitVq( lsfdeq, index, lsf,
+ (int16_t*)WebRtcIlbcfix_kLsfCb, (int16_t*)WebRtcIlbcfix_kLsfDimCb, (int16_t*)WebRtcIlbcfix_kLsfSizeCb);
+
+ if (lpc_n==2) {
+ /* Quantize second LSF with memoryless split VQ */
+ WebRtcIlbcfix_SplitVq( lsfdeq + LPC_FILTERORDER, index + LSF_NSPLIT,
+ lsf + LPC_FILTERORDER, (int16_t*)WebRtcIlbcfix_kLsfCb,
+ (int16_t*)WebRtcIlbcfix_kLsfDimCb, (int16_t*)WebRtcIlbcfix_kLsfSizeCb);
+ }
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h
new file mode 100644
index 0000000000..66b553213a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SimpleLsfQ.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_QUANT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_QUANT_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * lsf quantizer (subrutine to LPCencode)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SimpleLsfQ(
+ int16_t* lsfdeq, /* (o) dequantized lsf coefficients
+ (dimension FILTERORDER) Q13 */
+ int16_t* index, /* (o) quantization index */
+ int16_t* lsf, /* (i) the lsf coefficient vector to be
+ quantized (dimension FILTERORDER) Q13 */
+ int16_t lpc_n /* (i) number of lsf sets to quantize */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.c
new file mode 100644
index 0000000000..631b2f432a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Smooth.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/smooth.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/smooth_out_data.h"
+
+/*----------------------------------------------------------------*
+ * find the smoothed output data
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Smooth(
+ int16_t *odata, /* (o) smoothed output */
+ int16_t *current, /* (i) the un enhanced residual for
+ this block */
+ int16_t *surround /* (i) The approximation from the
+ surrounding sequences */
+ ) {
+ int16_t scale, scale1, scale2;
+ int16_t A, B, C, denomW16;
+ int32_t B_W32, denom, num;
+ int32_t errs;
+ int32_t w00,w10,w11, endiff, crit;
+ int32_t w00prim, w10prim, w11_div_w00;
+ int16_t w11prim;
+ int16_t bitsw00, bitsw10, bitsw11;
+ int32_t w11w00, w10w10, w00w00;
+ uint32_t max1, max2, max12;
+
+ /* compute some inner products (ensure no overflow by first calculating proper scale factor) */
+
+ w00 = w10 = w11 = 0;
+
+ // Calculate a right shift that will let us sum ENH_BLOCKL pairwise products
+ // of values from the two sequences without overflowing an int32_t. (The +1
+ // in max1 and max2 are because WebRtcSpl_MaxAbsValueW16 will return 2**15 -
+ // 1 if the input array contains -2**15.)
+ max1 = WebRtcSpl_MaxAbsValueW16(current, ENH_BLOCKL) + 1;
+ max2 = WebRtcSpl_MaxAbsValueW16(surround, ENH_BLOCKL) + 1;
+ max12 = WEBRTC_SPL_MAX(max1, max2);
+ scale = (64 - 31) -
+ WebRtcSpl_CountLeadingZeros64((max12 * max12) * (uint64_t)ENH_BLOCKL);
+ scale=WEBRTC_SPL_MAX(0, scale);
+
+ w00=WebRtcSpl_DotProductWithScale(current,current,ENH_BLOCKL,scale);
+ w11=WebRtcSpl_DotProductWithScale(surround,surround,ENH_BLOCKL,scale);
+ w10=WebRtcSpl_DotProductWithScale(surround,current,ENH_BLOCKL,scale);
+
+ if (w00<0) w00 = WEBRTC_SPL_WORD32_MAX;
+ if (w11<0) w11 = WEBRTC_SPL_WORD32_MAX;
+
+ /* Rescale w00 and w11 to w00prim and w11prim, so that w00prim/w11prim
+ is in Q16 */
+
+ bitsw00 = WebRtcSpl_GetSizeInBits(w00);
+ bitsw11 = WebRtcSpl_GetSizeInBits(w11);
+ bitsw10 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(w10));
+ scale1 = 31 - bitsw00;
+ scale2 = 15 - bitsw11;
+
+ if (scale2>(scale1-16)) {
+ scale2 = scale1 - 16;
+ } else {
+ scale1 = scale2 + 16;
+ }
+
+ w00prim = w00 << scale1;
+ w11prim = (int16_t) WEBRTC_SPL_SHIFT_W32(w11, scale2);
+
+ /* Perform C = sqrt(w11/w00) (C is in Q11 since (16+6)/2=11) */
+ if (w11prim>64) {
+ endiff = WebRtcSpl_DivW32W16(w00prim, w11prim) << 6;
+ C = (int16_t)WebRtcSpl_SqrtFloor(endiff); /* C is in Q11 */
+ } else {
+ C = 1;
+ }
+
+ /* first try enhancement without power-constraint */
+
+ errs = WebRtcIlbcfix_Smooth_odata(odata, current, surround, C);
+
+
+
+ /* if constraint violated by first try, add constraint */
+
+ if ( (6-scale+scale1) > 31) {
+ crit=0;
+ } else {
+ /* crit = 0.05 * w00 (Result in Q-6) */
+ crit = WEBRTC_SPL_SHIFT_W32(
+ WEBRTC_SPL_MUL(ENH_A0, w00prim >> 14),
+ -(6-scale+scale1));
+ }
+
+ if (errs > crit) {
+
+ if( w00 < 1) {
+ w00=1;
+ }
+
+ /* Calculate w11*w00, w10*w10 and w00*w00 in the same Q domain */
+
+ scale1 = bitsw00-15;
+ scale2 = bitsw11-15;
+
+ if (scale2>scale1) {
+ scale = scale2;
+ } else {
+ scale = scale1;
+ }
+
+ w11w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w11, -scale) *
+ (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
+
+ w10w10 = (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale) *
+ (int16_t)WEBRTC_SPL_SHIFT_W32(w10, -scale);
+
+ w00w00 = (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale) *
+ (int16_t)WEBRTC_SPL_SHIFT_W32(w00, -scale);
+
+ /* Calculate (w11*w00-w10*w10)/(w00*w00) in Q16 */
+ if (w00w00>65536) {
+ endiff = (w11w00-w10w10);
+ endiff = WEBRTC_SPL_MAX(0, endiff);
+ /* denom is in Q16 */
+ denom = WebRtcSpl_DivW32W16(endiff, (int16_t)(w00w00 >> 16));
+ } else {
+ denom = 65536;
+ }
+
+ if( denom > 7){ /* eliminates numerical problems
+ for if smooth */
+
+ scale=WebRtcSpl_GetSizeInBits(denom)-15;
+
+ if (scale>0) {
+ /* denomW16 is in Q(16+scale) */
+ denomW16 = (int16_t)(denom >> scale);
+
+ /* num in Q(34-scale) */
+ num = ENH_A0_MINUS_A0A0DIV4 >> scale;
+ } else {
+ /* denomW16 is in Q16 */
+ denomW16=(int16_t)denom;
+
+ /* num in Q34 */
+ num=ENH_A0_MINUS_A0A0DIV4;
+ }
+
+ /* A sqrt( (ENH_A0-(ENH_A0^2)/4)*(w00*w00)/(w11*w00 + w10*w10) ) in Q9 */
+ A = (int16_t)WebRtcSpl_SqrtFloor(WebRtcSpl_DivW32W16(num, denomW16));
+
+ /* B_W32 is in Q30 ( B = 1 - ENH_A0/2 - A * w10/w00 ) */
+ scale1 = 31-bitsw10;
+ scale2 = 21-scale1;
+ w10prim = w10 == 0 ? 0 : w10 * (1 << scale1);
+ w00prim = WEBRTC_SPL_SHIFT_W32(w00, -scale2);
+ scale = bitsw00-scale2-15;
+
+ if (scale>0) {
+ w10prim >>= scale;
+ w00prim >>= scale;
+ }
+
+ if ((w00prim>0)&&(w10prim>0)) {
+ w11_div_w00=WebRtcSpl_DivW32W16(w10prim, (int16_t)w00prim);
+
+ if (WebRtcSpl_GetSizeInBits(w11_div_w00)+WebRtcSpl_GetSizeInBits(A)>31) {
+ B_W32 = 0;
+ } else {
+ B_W32 = (int32_t)1073741824 - (int32_t)ENH_A0DIV2 -
+ WEBRTC_SPL_MUL(A, w11_div_w00);
+ }
+ B = (int16_t)(B_W32 >> 16); /* B in Q14. */
+ } else {
+ /* No smoothing */
+ A = 0;
+ B = 16384; /* 1 in Q14 */
+ }
+ }
+ else{ /* essentially no difference between cycles;
+ smoothing not needed */
+
+ A = 0;
+ B = 16384; /* 1 in Q14 */
+ }
+
+ /* create smoothed sequence */
+
+ WebRtcSpl_ScaleAndAddVectors(surround, A, 9,
+ current, B, 14,
+ odata, ENH_BLOCKL);
+ }
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.h
new file mode 100644
index 0000000000..c8752be64f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Smooth.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * find the smoothed output data
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Smooth(int16_t* odata, /* (o) smoothed output */
+ int16_t* current, /* (i) the un enhanced residual for
+ this block */
+ int16_t* surround /* (i) The approximation from the
+ surrounding sequences */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.c
new file mode 100644
index 0000000000..9f952bfb93
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Smooth_odata.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/smooth_out_data.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/sanitizer.h"
+
+// An s32 + s32 -> s32 addition that's allowed to overflow. (It's still
+// undefined behavior, so not a good idea; this just makes UBSan ignore the
+// violation, so that our old code can continue to do what it's always been
+// doing.)
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+ OverflowingAdd_S32_S32_To_S32(int32_t a, int32_t b) {
+ return a + b;
+}
+
+int32_t WebRtcIlbcfix_Smooth_odata(
+ int16_t *odata,
+ int16_t *psseq,
+ int16_t *surround,
+ int16_t C)
+{
+ int i;
+
+ int16_t err;
+ int32_t errs;
+
+ for(i=0;i<80;i++) {
+ odata[i]= (int16_t)((C * surround[i] + 1024) >> 11);
+ }
+
+ errs=0;
+ for(i=0;i<80;i++) {
+ err = (psseq[i] - odata[i]) >> 3;
+ errs = OverflowingAdd_S32_S32_To_S32(errs, err * err); // errs in Q-6
+ }
+
+ return errs;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.h
new file mode 100644
index 0000000000..318e7b04a2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/smooth_out_data.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Smooth_odata.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_OUT_DATA_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_OUT_DATA_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * help function to WebRtcIlbcfix_Smooth()
+ *---------------------------------------------------------------*/
+
+int32_t WebRtcIlbcfix_Smooth_odata(int16_t* odata,
+ int16_t* psseq,
+ int16_t* surround,
+ int16_t C);
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.c
new file mode 100644
index 0000000000..c3a24750f0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SortSq.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/sort_sq.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * scalar quantization
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SortSq(
+ int16_t *xq, /* (o) the quantized value */
+ int16_t *index, /* (o) the quantization index */
+ int16_t x, /* (i) the value to quantize */
+ const int16_t *cb, /* (i) the quantization codebook */
+ int16_t cb_size /* (i) the size of the quantization codebook */
+ ){
+ int i;
+
+ if (x <= cb[0]) {
+ *index = 0;
+ *xq = cb[0];
+ } else {
+ i = 0;
+ while ((x > cb[i]) && (i < (cb_size-1))) {
+ i++;
+ }
+
+ if (x > (((int32_t)cb[i] + cb[i - 1] + 1) >> 1)) {
+ *index = i;
+ *xq = cb[i];
+ } else {
+ *index = i - 1;
+ *xq = cb[i - 1];
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.h
new file mode 100644
index 0000000000..02028dae93
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/sort_sq.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SortSq.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SORT_SQ_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SORT_SQ_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * scalar quantization
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SortSq(
+ int16_t* xq, /* (o) the quantized value */
+ int16_t* index, /* (o) the quantization index */
+ int16_t x, /* (i) the value to quantize */
+ const int16_t* cb, /* (i) the quantization codebook */
+ int16_t cb_size /* (i) the size of the quantization codebook */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.c
new file mode 100644
index 0000000000..c1f04d2287
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SplitVq.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/split_vq.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/vq3.h"
+#include "modules/audio_coding/codecs/ilbc/vq4.h"
+
+/*----------------------------------------------------------------*
+ * split vector quantization
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SplitVq(
+ int16_t *qX, /* (o) the quantized vector in Q13 */
+ int16_t *index, /* (o) a vector of indexes for all vector
+ codebooks in the split */
+ int16_t *X, /* (i) the vector to quantize */
+ int16_t *CB, /* (i) the quantizer codebook in Q13 */
+ int16_t *dim, /* (i) the dimension of X and qX */
+ int16_t *cbsize /* (i) the number of vectors in the codebook */
+ ) {
+
+ int16_t *qXPtr, *indexPtr, *CBPtr, *XPtr;
+
+ /* Quantize X with the 3 vectror quantization tables */
+
+ qXPtr=qX;
+ indexPtr=index;
+ CBPtr=CB;
+ XPtr=X;
+ WebRtcIlbcfix_Vq3(qXPtr, indexPtr, CBPtr, XPtr, cbsize[0]);
+
+ qXPtr+=3;
+ indexPtr+=1;
+ CBPtr+=(dim[0]*cbsize[0]);
+ XPtr+=3;
+ WebRtcIlbcfix_Vq3(qXPtr, indexPtr, CBPtr, XPtr, cbsize[1]);
+
+ qXPtr+=3;
+ indexPtr+=1;
+ CBPtr+=(dim[1]*cbsize[1]);
+ XPtr+=3;
+ WebRtcIlbcfix_Vq4(qXPtr, indexPtr, CBPtr, XPtr, cbsize[2]);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.h
new file mode 100644
index 0000000000..e4b02a2bc2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/split_vq.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SplitVq.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SPLIT_VQ_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SPLIT_VQ_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * split vector quantization
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SplitVq(
+ int16_t* qX, /* (o) the quantized vector in Q13 */
+ int16_t* index, /* (o) a vector of indexes for all vector
+ codebooks in the split */
+ int16_t* X, /* (i) the vector to quantize */
+ int16_t* CB, /* (i) the quantizer codebook in Q13 */
+ int16_t* dim, /* (i) the dimension of X and qX */
+ int16_t* cbsize /* (i) the number of vectors in the codebook */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.c
new file mode 100644
index 0000000000..c58086c03b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_StateConstruct.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/state_construct.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * decoding of the start state
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_StateConstruct(
+ size_t idxForMax, /* (i) 6-bit index for the quantization of
+ max amplitude */
+ int16_t *idxVec, /* (i) vector of quantization indexes */
+ int16_t *syntDenum, /* (i) synthesis filter denumerator */
+ int16_t *Out_fix, /* (o) the decoded state vector */
+ size_t len /* (i) length of a state vector */
+ ) {
+ size_t k;
+ int16_t maxVal;
+ int16_t *tmp1, *tmp2, *tmp3;
+ /* Stack based */
+ int16_t numerator[1+LPC_FILTERORDER];
+ int16_t sampleValVec[2*STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
+ int16_t sampleMaVec[2*STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
+ int16_t *sampleVal = &sampleValVec[LPC_FILTERORDER];
+ int16_t *sampleMa = &sampleMaVec[LPC_FILTERORDER];
+ int16_t *sampleAr = &sampleValVec[LPC_FILTERORDER];
+
+ /* initialization of coefficients */
+
+ for (k=0; k<LPC_FILTERORDER+1; k++){
+ numerator[k] = syntDenum[LPC_FILTERORDER-k];
+ }
+
+ /* decoding of the maximum value */
+
+ maxVal = WebRtcIlbcfix_kFrgQuantMod[idxForMax];
+
+ /* decoding of the sample values */
+ tmp1 = sampleVal;
+ tmp2 = &idxVec[len-1];
+
+ if (idxForMax<37) {
+ for(k=0; k<len; k++){
+ /*the shifting is due to the Q13 in sq4_fixQ13[i], also the adding of 2097152 (= 0.5 << 22)
+ maxVal is in Q8 and result is in Q(-1) */
+ *tmp1 = (int16_t)((maxVal * WebRtcIlbcfix_kStateSq3[*tmp2] + 2097152) >>
+ 22);
+ tmp1++;
+ tmp2--;
+ }
+ } else if (idxForMax<59) {
+ for(k=0; k<len; k++){
+ /*the shifting is due to the Q13 in sq4_fixQ13[i], also the adding of 262144 (= 0.5 << 19)
+ maxVal is in Q5 and result is in Q(-1) */
+ *tmp1 = (int16_t)((maxVal * WebRtcIlbcfix_kStateSq3[*tmp2] + 262144) >>
+ 19);
+ tmp1++;
+ tmp2--;
+ }
+ } else {
+ for(k=0; k<len; k++){
+ /*the shifting is due to the Q13 in sq4_fixQ13[i], also the adding of 65536 (= 0.5 << 17)
+ maxVal is in Q3 and result is in Q(-1) */
+ *tmp1 = (int16_t)((maxVal * WebRtcIlbcfix_kStateSq3[*tmp2] + 65536) >>
+ 17);
+ tmp1++;
+ tmp2--;
+ }
+ }
+
+ /* Set the rest of the data to zero */
+ WebRtcSpl_MemSetW16(&sampleVal[len], 0, len);
+
+ /* circular convolution with all-pass filter */
+
+ /* Set the state to zero */
+ WebRtcSpl_MemSetW16(sampleValVec, 0, (LPC_FILTERORDER));
+
+ /* Run MA filter + AR filter */
+ WebRtcSpl_FilterMAFastQ12(
+ sampleVal, sampleMa,
+ numerator, LPC_FILTERORDER+1, len + LPC_FILTERORDER);
+ WebRtcSpl_MemSetW16(&sampleMa[len + LPC_FILTERORDER], 0, (len - LPC_FILTERORDER));
+ WebRtcSpl_FilterARFastQ12(
+ sampleMa, sampleAr,
+ syntDenum, LPC_FILTERORDER+1, 2 * len);
+
+ tmp1 = &sampleAr[len-1];
+ tmp2 = &sampleAr[2*len-1];
+ tmp3 = Out_fix;
+ for(k=0;k<len;k++){
+ (*tmp3) = (*tmp1) + (*tmp2);
+ tmp1--;
+ tmp2--;
+ tmp3++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.h
new file mode 100644
index 0000000000..4c3011937d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_construct.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_StateConstruct.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_CONSTRUCT_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_CONSTRUCT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Generate the start state from the quantized indexes
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_StateConstruct(
+ size_t idxForMax, /* (i) 6-bit index for the quantization of
+ max amplitude */
+ int16_t* idxVec, /* (i) vector of quantization indexes */
+ int16_t* syntDenum, /* (i) synthesis filter denumerator */
+ int16_t* Out_fix, /* (o) the decoded state vector */
+ size_t len /* (i) length of a state vector */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.c
new file mode 100644
index 0000000000..7227ac9d45
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_StateSearch.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/state_search.h"
+
+#include "modules/audio_coding/codecs/ilbc/abs_quant.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * encoding of start state
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_StateSearch(
+ IlbcEncoder *iLBCenc_inst,
+ /* (i) Encoder instance */
+ iLBC_bits *iLBC_encbits,/* (i/o) Encoded bits (output idxForMax
+ and idxVec, input state_first) */
+ int16_t *residual, /* (i) target residual vector */
+ int16_t *syntDenum, /* (i) lpc synthesis filter */
+ int16_t *weightDenum /* (i) weighting filter denuminator */
+ ) {
+ size_t k, index;
+ int16_t maxVal;
+ int16_t scale, shift;
+ int32_t maxValsq;
+ int16_t scaleRes;
+ int16_t max;
+ int i;
+ /* Stack based */
+ int16_t numerator[1+LPC_FILTERORDER];
+ int16_t residualLongVec[2*STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
+ int16_t sampleMa[2*STATE_SHORT_LEN_30MS];
+ int16_t *residualLong = &residualLongVec[LPC_FILTERORDER];
+ int16_t *sampleAr = residualLong;
+
+ /* Scale to maximum 12 bits to avoid saturation in circular convolution filter */
+ max = WebRtcSpl_MaxAbsValueW16(residual, iLBCenc_inst->state_short_len);
+ scaleRes = WebRtcSpl_GetSizeInBits(max)-12;
+ scaleRes = WEBRTC_SPL_MAX(0, scaleRes);
+ /* Set up the filter coefficients for the circular convolution */
+ for (i=0; i<LPC_FILTERORDER+1; i++) {
+ numerator[i] = (syntDenum[LPC_FILTERORDER-i]>>scaleRes);
+ }
+
+ /* Copy the residual to a temporary buffer that we can filter
+ * and set the remaining samples to zero.
+ */
+ WEBRTC_SPL_MEMCPY_W16(residualLong, residual, iLBCenc_inst->state_short_len);
+ WebRtcSpl_MemSetW16(residualLong + iLBCenc_inst->state_short_len, 0, iLBCenc_inst->state_short_len);
+
+ /* Run the Zero-Pole filter (Ciurcular convolution) */
+ WebRtcSpl_MemSetW16(residualLongVec, 0, LPC_FILTERORDER);
+ WebRtcSpl_FilterMAFastQ12(residualLong, sampleMa, numerator,
+ LPC_FILTERORDER + 1,
+ iLBCenc_inst->state_short_len + LPC_FILTERORDER);
+ WebRtcSpl_MemSetW16(&sampleMa[iLBCenc_inst->state_short_len + LPC_FILTERORDER], 0, iLBCenc_inst->state_short_len - LPC_FILTERORDER);
+
+ WebRtcSpl_FilterARFastQ12(
+ sampleMa, sampleAr,
+ syntDenum, LPC_FILTERORDER+1, 2 * iLBCenc_inst->state_short_len);
+
+ for(k=0;k<iLBCenc_inst->state_short_len;k++){
+ sampleAr[k] += sampleAr[k+iLBCenc_inst->state_short_len];
+ }
+
+ /* Find maximum absolute value in the vector */
+ maxVal=WebRtcSpl_MaxAbsValueW16(sampleAr, iLBCenc_inst->state_short_len);
+
+ /* Find the best index */
+
+ if ((((int32_t)maxVal)<<scaleRes)<23170) {
+ maxValsq=((int32_t)maxVal*maxVal)<<(2+2*scaleRes);
+ } else {
+ maxValsq=(int32_t)WEBRTC_SPL_WORD32_MAX;
+ }
+
+ index=0;
+ for (i=0;i<63;i++) {
+
+ if (maxValsq>=WebRtcIlbcfix_kChooseFrgQuant[i]) {
+ index=i+1;
+ } else {
+ i=63;
+ }
+ }
+ iLBC_encbits->idxForMax=index;
+
+ /* Rescale the vector before quantization */
+ scale=WebRtcIlbcfix_kScale[index];
+
+ if (index<27) { /* scale table is in Q16, fout[] is in Q(-1) and we want the result to be in Q11 */
+ shift=4;
+ } else { /* scale table is in Q21, fout[] is in Q(-1) and we want the result to be in Q11 */
+ shift=9;
+ }
+
+ /* Set up vectors for AbsQuant and rescale it with the scale factor */
+ WebRtcSpl_ScaleVectorWithSat(sampleAr, sampleAr, scale,
+ iLBCenc_inst->state_short_len, (int16_t)(shift-scaleRes));
+
+ /* Quantize the values in fout[] */
+ WebRtcIlbcfix_AbsQuant(iLBCenc_inst, iLBC_encbits, sampleAr, weightDenum);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.h
new file mode 100644
index 0000000000..6469138a0e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/state_search.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_StateSearch.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_SEARCH_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_SEARCH_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * encoding of start state
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_StateSearch(
+ IlbcEncoder* iLBCenc_inst,
+ /* (i) Encoder instance */
+ iLBC_bits* iLBC_encbits, /* (i/o) Encoded bits (output idxForMax
+ and idxVec, input state_first) */
+ int16_t* residual, /* (i) target residual vector */
+ int16_t* syntDenum, /* (i) lpc synthesis filter */
+ int16_t* weightDenum /* (i) weighting filter denuminator */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.c
new file mode 100644
index 0000000000..bbafc1a2ed
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SwapBytes.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
+
+/*----------------------------------------------------------------*
+ * Swap bytes (to simplify operations on Little Endian machines)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SwapBytes(
+ const uint16_t* input, /* (i) the sequence to swap */
+ size_t wordLength, /* (i) number or uint16_t to swap */
+ uint16_t* output /* (o) the swapped sequence */
+ ) {
+ size_t k;
+ for (k = wordLength; k > 0; k--) {
+ *output++ = (*input >> 8)|(*input << 8);
+ input++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.h
new file mode 100644
index 0000000000..c59bf3068a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/swap_bytes.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_SwapBytes.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SWAP_BYTES_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SWAP_BYTES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Swap bytes (to simplify operations on Little Endian machines)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_SwapBytes(
+ const uint16_t* input, /* (i) the sequence to swap */
+ size_t wordLength, /* (i) number or uint16_t to swap */
+ uint16_t* output /* (o) the swapped sequence */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/empty.cc b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/empty.cc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/empty.cc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_test.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_test.c
new file mode 100644
index 0000000000..e0ca075eda
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_test.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iLBC_test.c
+
+******************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+
+/*---------------------------------------------------------------*
+ * Main program to test iLBC encoding and decoding
+ *
+ * Usage:
+ * exefile_name.exe <infile> <bytefile> <outfile> <channel>
+ *
+ * <infile> : Input file, speech for encoder (16-bit pcm file)
+ * <bytefile> : Bit stream output from the encoder
+ * <outfile> : Output file, decoded speech (16-bit pcm file)
+ * <channel> : Bit error file, optional (16-bit)
+ * 1 - Packet received correctly
+ * 0 - Packet Lost
+ *
+ *--------------------------------------------------------------*/
+
+#define BLOCKL_MAX 240
+#define ILBCNOOFWORDS_MAX 25
+
+
+int main(int argc, char* argv[])
+{
+
+ FILE *ifileid,*efileid,*ofileid, *cfileid;
+ int16_t data[BLOCKL_MAX];
+ uint8_t encoded_data[2 * ILBCNOOFWORDS_MAX];
+ int16_t decoded_data[BLOCKL_MAX];
+ int len_int, mode;
+ short pli;
+ int blockcount = 0;
+ size_t frameLen, len, len_i16s;
+ int16_t speechType;
+ IlbcEncoderInstance *Enc_Inst;
+ IlbcDecoderInstance *Dec_Inst;
+
+#ifdef __ILBC_WITH_40BITACC
+ /* Doublecheck that long long exists */
+ if (sizeof(long)>=sizeof(long long)) {
+ fprintf(stderr, "40-bit simulation is not be supported on this platform\n");
+ exit(0);
+ }
+#endif
+
+ /* get arguments and open files */
+
+ if ((argc!=5) && (argc!=6)) {
+ fprintf(stderr,
+ "\n*-----------------------------------------------*\n");
+ fprintf(stderr,
+ " %s <20,30> input encoded decoded (channel)\n\n",
+ argv[0]);
+ fprintf(stderr,
+ " mode : Frame size for the encoding/decoding\n");
+ fprintf(stderr,
+ " 20 - 20 ms\n");
+ fprintf(stderr,
+ " 30 - 30 ms\n");
+ fprintf(stderr,
+ " input : Speech for encoder (16-bit pcm file)\n");
+ fprintf(stderr,
+ " encoded : Encoded bit stream\n");
+ fprintf(stderr,
+ " decoded : Decoded speech (16-bit pcm file)\n");
+ fprintf(stderr,
+ " channel : Packet loss pattern, optional (16-bit)\n");
+ fprintf(stderr,
+ " 1 - Packet received correctly\n");
+ fprintf(stderr,
+ " 0 - Packet Lost\n");
+ fprintf(stderr,
+ "*-----------------------------------------------*\n\n");
+ exit(1);
+ }
+ mode=atoi(argv[1]);
+ if (mode != 20 && mode != 30) {
+ fprintf(stderr,"Wrong mode %s, must be 20, or 30\n",
+ argv[1]);
+ exit(2);
+ }
+ if ( (ifileid=fopen(argv[2],"rb")) == NULL) {
+ fprintf(stderr,"Cannot open input file %s\n", argv[2]);
+ exit(2);}
+ if ( (efileid=fopen(argv[3],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open encoded file file %s\n",
+ argv[3]); exit(1);}
+ if ( (ofileid=fopen(argv[4],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open decoded file %s\n",
+ argv[4]); exit(1);}
+ if (argc==6) {
+ if( (cfileid=fopen(argv[5],"rb")) == NULL) {
+ fprintf(stderr, "Cannot open channel file %s\n",
+ argv[5]);
+ exit(1);
+ }
+ } else {
+ cfileid=NULL;
+ }
+
+ /* print info */
+
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* iLBC test program *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+ fprintf(stderr,"\nMode : %2d ms\n", mode);
+ fprintf(stderr,"Input file : %s\n", argv[2]);
+ fprintf(stderr,"Encoded file : %s\n", argv[3]);
+ fprintf(stderr,"Output file : %s\n", argv[4]);
+ if (argc==6) {
+ fprintf(stderr,"Channel file : %s\n", argv[5]);
+ }
+ fprintf(stderr,"\n");
+
+ /* Create structs */
+ WebRtcIlbcfix_EncoderCreate(&Enc_Inst);
+ WebRtcIlbcfix_DecoderCreate(&Dec_Inst);
+
+
+ /* Initialization */
+
+ WebRtcIlbcfix_EncoderInit(Enc_Inst, mode);
+ WebRtcIlbcfix_DecoderInit(Dec_Inst, mode);
+ frameLen = (size_t)(mode*8);
+
+ /* loop over input blocks */
+
+ while (fread(data,sizeof(int16_t),frameLen,ifileid) == frameLen) {
+
+ blockcount++;
+
+ /* encoding */
+
+ fprintf(stderr, "--- Encoding block %i --- ",blockcount);
+ len_int = WebRtcIlbcfix_Encode(Enc_Inst, data, frameLen, encoded_data);
+ if (len_int < 0) {
+ fprintf(stderr, "Error encoding\n");
+ exit(0);
+ }
+ len = (size_t)len_int;
+ fprintf(stderr, "\r");
+
+ /* write byte file */
+
+ len_i16s = (len + 1) / sizeof(int16_t);
+ if (fwrite(encoded_data, sizeof(int16_t), len_i16s, efileid) != len_i16s) {
+ return -1;
+ }
+
+ /* get channel data if provided */
+ if (argc==6) {
+ if (fread(&pli, sizeof(int16_t), 1, cfileid)) {
+ if ((pli!=0)&&(pli!=1)) {
+ fprintf(stderr, "Error in channel file\n");
+ exit(0);
+ }
+ if (pli==0) {
+ /* Packet loss -> remove info from frame */
+ memset(encoded_data, 0,
+ sizeof(int16_t)*ILBCNOOFWORDS_MAX);
+ }
+ } else {
+ fprintf(stderr, "Error. Channel file too short\n");
+ exit(0);
+ }
+ } else {
+ pli=1;
+ }
+
+ /* decoding */
+
+ fprintf(stderr, "--- Decoding block %i --- ",blockcount);
+ if (pli==1) {
+ len_int=WebRtcIlbcfix_Decode(Dec_Inst, encoded_data,
+ len, decoded_data,&speechType);
+ if (len_int < 0) {
+ fprintf(stderr, "Error decoding\n");
+ exit(0);
+ }
+ len = (size_t)len_int;
+ } else {
+ len=WebRtcIlbcfix_DecodePlc(Dec_Inst, decoded_data, 1);
+ }
+ fprintf(stderr, "\r");
+
+ /* write output file */
+
+ if (fwrite(decoded_data, sizeof(int16_t), len, ofileid) != len) {
+ return -1;
+ }
+ }
+
+ /* close files */
+
+ fclose(ifileid); fclose(efileid); fclose(ofileid);
+ if (argc==6) {
+ fclose(cfileid);
+ }
+
+ /* Free structs */
+ WebRtcIlbcfix_EncoderFree(Enc_Inst);
+ WebRtcIlbcfix_DecoderFree(Dec_Inst);
+
+
+ printf("\nDone with simulation\n\n");
+
+ return(0);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testLib.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testLib.c
new file mode 100644
index 0000000000..132f3bdb37
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testLib.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+iLBC Speech Coder ANSI-C Source Code
+
+iLBC_test.c
+
+******************************************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+
+//#define JUNK_DATA
+#ifdef JUNK_DATA
+#define SEED_FILE "randseed.txt"
+#endif
+
+
+/*----------------------------------------------------------------*
+* Main program to test iLBC encoding and decoding
+*
+* Usage:
+* exefile_name.exe <infile> <bytefile> <outfile>
+*
+*---------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ FILE *ifileid,*efileid,*ofileid, *chfileid;
+ short encoded_data[55], data[240], speechType;
+ int len_int, mode;
+ short pli;
+ size_t len, readlen;
+ int blockcount = 0;
+
+ IlbcEncoderInstance *Enc_Inst;
+ IlbcDecoderInstance *Dec_Inst;
+#ifdef JUNK_DATA
+ size_t i;
+ FILE *seedfile;
+ unsigned int random_seed = (unsigned int) time(NULL);//1196764538
+#endif
+
+ /* Create structs */
+ WebRtcIlbcfix_EncoderCreate(&Enc_Inst);
+ WebRtcIlbcfix_DecoderCreate(&Dec_Inst);
+
+ /* get arguments and open files */
+
+ if (argc != 6 ) {
+ fprintf(stderr, "%s mode inputfile bytefile outputfile channelfile\n",
+ argv[0]);
+ fprintf(stderr, "Example:\n");
+ fprintf(stderr, "%s <30,20> in.pcm byte.dat out.pcm T30.0.dat\n", argv[0]);
+ exit(1);
+ }
+ mode=atoi(argv[1]);
+ if (mode != 20 && mode != 30) {
+ fprintf(stderr,"Wrong mode %s, must be 20, or 30\n", argv[1]);
+ exit(2);
+ }
+ if ( (ifileid=fopen(argv[2],"rb")) == NULL) {
+ fprintf(stderr,"Cannot open input file %s\n", argv[2]);
+ exit(2);}
+ if ( (efileid=fopen(argv[3],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open channelfile file %s\n",
+ argv[3]); exit(3);}
+ if( (ofileid=fopen(argv[4],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open output file %s\n",
+ argv[4]); exit(3);}
+ if ( (chfileid=fopen(argv[5],"rb")) == NULL) {
+ fprintf(stderr,"Cannot open channel file file %s\n", argv[5]);
+ exit(2);
+ }
+ /* print info */
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* iLBCtest *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+#ifdef SPLIT_10MS
+ fprintf(stderr,"\n10ms split with raw mode: %2d ms\n", mode);
+#else
+ fprintf(stderr,"\nMode : %2d ms\n", mode);
+#endif
+ fprintf(stderr,"\nInput file : %s\n", argv[2]);
+ fprintf(stderr,"Coded file : %s\n", argv[3]);
+ fprintf(stderr,"Output file : %s\n\n", argv[4]);
+ fprintf(stderr,"Channel file : %s\n\n", argv[5]);
+
+#ifdef JUNK_DATA
+ srand(random_seed);
+
+ if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
+ fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
+ }
+ else {
+ fprintf(seedfile, "%u\n", random_seed);
+ fclose(seedfile);
+ }
+#endif
+
+ /* Initialization */
+ WebRtcIlbcfix_EncoderInit(Enc_Inst, mode);
+ WebRtcIlbcfix_DecoderInit(Dec_Inst, mode);
+
+ /* loop over input blocks */
+#ifdef SPLIT_10MS
+ readlen = 80;
+#else
+ readlen = (size_t)(mode << 3);
+#endif
+ while(fread(data, sizeof(short), readlen, ifileid) == readlen) {
+ blockcount++;
+
+ /* encoding */
+ fprintf(stderr, "--- Encoding block %i --- ",blockcount);
+ len_int=WebRtcIlbcfix_Encode(Enc_Inst, data, readlen, encoded_data);
+ if (len_int < 0) {
+ fprintf(stderr, "Error encoding\n");
+ exit(0);
+ }
+ len = (size_t)len_int;
+ fprintf(stderr, "\r");
+
+#ifdef JUNK_DATA
+ for ( i = 0; i < len; i++) {
+ encoded_data[i] = (short) (encoded_data[i] + (short) rand());
+ }
+#endif
+ /* write byte file */
+ if(len != 0){ //len may be 0 in 10ms split case
+ fwrite(encoded_data,1,len,efileid);
+
+ /* get channel data if provided */
+ if (argc==6) {
+ if (fread(&pli, sizeof(int16_t), 1, chfileid)) {
+ if ((pli!=0)&&(pli!=1)) {
+ fprintf(stderr, "Error in channel file\n");
+ exit(0);
+ }
+ if (pli==0) {
+ /* Packet loss -> remove info from frame */
+ memset(encoded_data, 0, sizeof(int16_t)*25);
+ }
+ } else {
+ fprintf(stderr, "Error. Channel file too short\n");
+ exit(0);
+ }
+ } else {
+ pli=1;
+ }
+
+ /* decoding */
+ fprintf(stderr, "--- Decoding block %i --- ",blockcount);
+ if (pli==1) {
+ len_int = WebRtcIlbcfix_Decode(Dec_Inst, encoded_data, len, data,
+ &speechType);
+ if (len_int < 0) {
+ fprintf(stderr, "Error decoding\n");
+ exit(0);
+ }
+ len = (size_t)len_int;
+ } else {
+ len=WebRtcIlbcfix_DecodePlc(Dec_Inst, data, 1);
+ }
+ fprintf(stderr, "\r");
+
+ /* write output file */
+ fwrite(data,sizeof(short),len,ofileid);
+ }
+ }
+
+#ifdef JUNK_DATA
+ if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
+ fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
+ }
+ else {
+ fprintf(seedfile, "ok\n\n");
+ fclose(seedfile);
+ }
+#endif
+
+ /* free structs */
+ WebRtcIlbcfix_EncoderFree(Enc_Inst);
+ WebRtcIlbcfix_DecoderFree(Dec_Inst);
+
+ /* close files */
+ fclose(ifileid);
+ fclose(efileid);
+ fclose(ofileid);
+
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testprogram.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testprogram.c
new file mode 100644
index 0000000000..a62a42edf6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/test/iLBC_testprogram.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iLBC_test.c
+
+******************************************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/nit_encode.h"
+#include "modules/audio_coding/codecs/ilbc/encode.h"
+#include "modules/audio_coding/codecs/ilbc/init_decode.h"
+#include "modules/audio_coding/codecs/ilbc/decode.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+
+#define ILBCNOOFWORDS_MAX (NO_OF_BYTES_30MS)/2
+
+/* Runtime statistics */
+#include <time.h>
+/* #define CLOCKS_PER_SEC 1000 */
+
+/*----------------------------------------------------------------*
+ * Encoder interface function
+ *---------------------------------------------------------------*/
+
+short encode( /* (o) Number of bytes encoded */
+ IlbcEncoder *iLBCenc_inst, /* (i/o) Encoder instance */
+ int16_t *encoded_data, /* (o) The encoded bytes */
+ int16_t *data /* (i) The signal block to encode */
+ ){
+
+ /* do the actual encoding */
+ WebRtcIlbcfix_Encode((uint16_t *)encoded_data, data, iLBCenc_inst);
+
+ return (iLBCenc_inst->no_of_bytes);
+}
+
+/*----------------------------------------------------------------*
+ * Decoder interface function
+ *---------------------------------------------------------------*/
+
+short decode( /* (o) Number of decoded samples */
+ IlbcDecoder *iLBCdec_inst, /* (i/o) Decoder instance */
+ short *decoded_data, /* (o) Decoded signal block */
+ short *encoded_data, /* (i) Encoded bytes */
+ short mode /* (i) 0=PL, 1=Normal */
+ ){
+
+ /* check if mode is valid */
+
+ if (mode<0 || mode>1) {
+ printf("\nERROR - Wrong mode - 0, 1 allowed\n"); exit(3);}
+
+ /* do actual decoding of block */
+
+ WebRtcIlbcfix_Decode(decoded_data, (uint16_t *)encoded_data,
+ iLBCdec_inst, mode);
+
+ return (iLBCdec_inst->blockl);
+}
+
+/*----------------------------------------------------------------*
+ * Main program to test iLBC encoding and decoding
+ *
+ * Usage:
+ * exefile_name.exe <infile> <bytefile> <outfile> <channelfile>
+ *
+ *---------------------------------------------------------------*/
+
+#define MAXFRAMES 10000
+#define MAXFILELEN (BLOCKL_MAX*MAXFRAMES)
+
+int main(int argc, char* argv[])
+{
+
+ /* Runtime statistics */
+
+ float starttime1, starttime2;
+ float runtime1, runtime2;
+ float outtime;
+
+ FILE *ifileid,*efileid,*ofileid, *chfileid;
+ short *inputdata, *encodeddata, *decodeddata;
+ short *channeldata;
+ int blockcount = 0, noOfBlocks=0, i, noOfLostBlocks=0;
+ short mode;
+ IlbcEncoder Enc_Inst;
+ IlbcDecoder Dec_Inst;
+
+ short frameLen;
+ short count;
+#ifdef SPLIT_10MS
+ short size;
+#endif
+
+ inputdata=(short*) malloc(MAXFILELEN*sizeof(short));
+ if (inputdata==NULL) {
+ fprintf(stderr,"Could not allocate memory for vector\n");
+ exit(0);
+ }
+ encodeddata=(short*) malloc(ILBCNOOFWORDS_MAX*MAXFRAMES*sizeof(short));
+ if (encodeddata==NULL) {
+ fprintf(stderr,"Could not allocate memory for vector\n");
+ free(inputdata);
+ exit(0);
+ }
+ decodeddata=(short*) malloc(MAXFILELEN*sizeof(short));
+ if (decodeddata==NULL) {
+ fprintf(stderr,"Could not allocate memory for vector\n");
+ free(inputdata);
+ free(encodeddata);
+ exit(0);
+ }
+ channeldata=(short*) malloc(MAXFRAMES*sizeof(short));
+ if (channeldata==NULL) {
+ fprintf(stderr,"Could not allocate memory for vector\n");
+ free(inputdata);
+ free(encodeddata);
+ free(decodeddata);
+ exit(0);
+ }
+
+ /* get arguments and open files */
+
+ if (argc != 6 ) {
+ fprintf(stderr, "%s mode inputfile bytefile outputfile channelfile\n",
+ argv[0]);
+ fprintf(stderr, "Example:\n");
+ fprintf(stderr, "%s <30,20> in.pcm byte.dat out.pcm T30.0.dat\n", argv[0]);
+ exit(1);
+ }
+ mode=atoi(argv[1]);
+ if (mode != 20 && mode != 30) {
+ fprintf(stderr,"Wrong mode %s, must be 20, or 30\n", argv[1]);
+ exit(2);
+ }
+ if ( (ifileid=fopen(argv[2],"rb")) == NULL) {
+ fprintf(stderr,"Cannot open input file %s\n", argv[2]);
+ exit(2);}
+ if ( (efileid=fopen(argv[3],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open channelfile file %s\n",
+ argv[3]); exit(3);}
+ if( (ofileid=fopen(argv[4],"wb")) == NULL) {
+ fprintf(stderr, "Cannot open output file %s\n",
+ argv[4]); exit(3);}
+ if ( (chfileid=fopen(argv[5],"rb")) == NULL) {
+ fprintf(stderr,"Cannot open channel file file %s\n", argv[5]);
+ exit(2);}
+
+
+ /* print info */
+#ifndef PRINT_MIPS
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* iLBCtest *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "* *\n");
+ fprintf(stderr,
+ "*---------------------------------------------------*\n");
+#ifdef SPLIT_10MS
+ fprintf(stderr,"\n10ms split with raw mode: %2d ms\n", mode);
+#else
+ fprintf(stderr,"\nMode : %2d ms\n", mode);
+#endif
+ fprintf(stderr,"\nInput file : %s\n", argv[2]);
+ fprintf(stderr,"Coded file : %s\n", argv[3]);
+ fprintf(stderr,"Output file : %s\n\n", argv[4]);
+ fprintf(stderr,"Channel file : %s\n\n", argv[5]);
+#endif
+
+ /* Initialization */
+
+ WebRtcIlbcfix_EncoderInit(&Enc_Inst, mode);
+ WebRtcIlbcfix_DecoderInit(&Dec_Inst, mode, 1);
+
+ /* extract the input file and channel file */
+
+#ifdef SPLIT_10MS
+ frameLen = (mode==20)? 80:160;
+ fread(Enc_Inst.past_samples, sizeof(short), frameLen, ifileid);
+ Enc_Inst.section = 0;
+
+ while( fread(&inputdata[noOfBlocks*80], sizeof(short),
+ 80, ifileid) == 80 ) {
+ noOfBlocks++;
+ }
+
+ noOfBlocks += frameLen/80;
+ frameLen = 80;
+#else
+ frameLen = Enc_Inst.blockl;
+
+ while( fread(&inputdata[noOfBlocks*Enc_Inst.blockl],sizeof(short),
+ Enc_Inst.blockl,ifileid)==(uint16_t)Enc_Inst.blockl){
+ noOfBlocks++;
+ }
+#endif
+
+
+ while ((fread(&channeldata[blockcount],sizeof(short), 1,chfileid)==1)
+ && ( blockcount < noOfBlocks/(Enc_Inst.blockl/frameLen) )) {
+ blockcount++;
+ }
+
+ if ( blockcount < noOfBlocks/(Enc_Inst.blockl/frameLen) ) {
+ fprintf(stderr,"Channel file %s is too short\n", argv[4]);
+ free(inputdata);
+ free(encodeddata);
+ free(decodeddata);
+ free(channeldata);
+ exit(0);
+ }
+
+ count=0;
+
+ /* Runtime statistics */
+
+ starttime1 = clock()/(float)CLOCKS_PER_SEC;
+
+ /* Encoding loop */
+#ifdef PRINT_MIPS
+ printf("-1 -1\n");
+#endif
+
+#ifdef SPLIT_10MS
+ /* "Enc_Inst.section != 0" is to make sure we run through full
+ lengths of all vectors for 10ms split mode.
+ */
+ // while( (count < noOfBlocks) || (Enc_Inst.section != 0) ) {
+ while( count < blockcount * (Enc_Inst.blockl/frameLen) ) {
+
+ encode(&Enc_Inst, &encodeddata[Enc_Inst.no_of_words *
+ (count/(Enc_Inst.nsub/2))],
+ &inputdata[frameLen * count] );
+#else
+ while (count < noOfBlocks) {
+ encode( &Enc_Inst, &encodeddata[Enc_Inst.no_of_words * count],
+ &inputdata[frameLen * count] );
+#endif
+
+#ifdef PRINT_MIPS
+ printf("-1 -1\n");
+#endif
+
+ count++;
+ }
+
+ count=0;
+
+ /* Runtime statistics */
+
+ starttime2=clock()/(float)CLOCKS_PER_SEC;
+ runtime1 = (float)(starttime2-starttime1);
+
+ /* Decoding loop */
+
+ while (count < blockcount) {
+ if (channeldata[count]==1) {
+ /* Normal decoding */
+ decode(&Dec_Inst, &decodeddata[count * Dec_Inst.blockl],
+ &encodeddata[Dec_Inst.no_of_words * count], 1);
+ } else if (channeldata[count]==0) {
+ /* PLC */
+ short emptydata[ILBCNOOFWORDS_MAX];
+ memset(emptydata, 0, Dec_Inst.no_of_words*sizeof(short));
+ decode(&Dec_Inst, &decodeddata[count*Dec_Inst.blockl],
+ emptydata, 0);
+ noOfLostBlocks++;
+ } else {
+ printf("Error in channel file (values have to be either 1 or 0)\n");
+ exit(0);
+ }
+#ifdef PRINT_MIPS
+ printf("-1 -1\n");
+#endif
+
+ count++;
+ }
+
+ /* Runtime statistics */
+
+ runtime2 = (float)(clock()/(float)CLOCKS_PER_SEC-starttime2);
+
+ outtime = (float)((float)blockcount*
+ (float)mode/1000.0);
+
+#ifndef PRINT_MIPS
+ printf("\nLength of speech file: %.1f s\n", outtime);
+ printf("Lost frames : %.1f%%\n\n", 100*(float)noOfLostBlocks/(float)blockcount);
+
+ printf("Time to run iLBC_encode+iLBC_decode:");
+ printf(" %.1f s (%.1f%% of realtime)\n", runtime1+runtime2,
+ (100*(runtime1+runtime2)/outtime));
+
+ printf("Time in iLBC_encode :");
+ printf(" %.1f s (%.1f%% of total runtime)\n",
+ runtime1, 100.0*runtime1/(runtime1+runtime2));
+
+ printf("Time in iLBC_decode :");
+ printf(" %.1f s (%.1f%% of total runtime)\n\n",
+ runtime2, 100.0*runtime2/(runtime1+runtime2));
+#endif
+
+ /* Write data to files */
+ for (i=0; i<blockcount; i++) {
+ fwrite(&encodeddata[i*Enc_Inst.no_of_words], sizeof(short),
+ Enc_Inst.no_of_words, efileid);
+ }
+ for (i=0;i<blockcount;i++) {
+ fwrite(&decodeddata[i*Enc_Inst.blockl],sizeof(short),Enc_Inst.blockl,ofileid);
+ }
+
+ /* return memory and close files */
+
+ free(inputdata);
+ free(encodeddata);
+ free(decodeddata);
+ free(channeldata);
+ fclose(ifileid); fclose(efileid); fclose(ofileid);
+ return(0);
+ }
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.c
new file mode 100644
index 0000000000..a9a0147b9d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_UnpackBits.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * unpacking of bits from bitstream, i.e., vector of bytes
+ *---------------------------------------------------------------*/
+
+int16_t WebRtcIlbcfix_UnpackBits( /* (o) "Empty" frame indicator */
+ const uint16_t *bitstream, /* (i) The packatized bitstream */
+ iLBC_bits *enc_bits, /* (o) Paramerers from bitstream */
+ int16_t mode /* (i) Codec mode (20 or 30) */
+ ) {
+ const uint16_t *bitstreamPtr;
+ int i, k;
+ int16_t *tmpPtr;
+
+ bitstreamPtr=bitstream;
+
+ /* First int16_t */
+ enc_bits->lsf[0] = (*bitstreamPtr)>>10; /* Bit 0..5 */
+ enc_bits->lsf[1] = ((*bitstreamPtr)>>3)&0x7F; /* Bit 6..12 */
+ enc_bits->lsf[2] = ((*bitstreamPtr)&0x7)<<4; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* Second int16_t */
+ enc_bits->lsf[2] |= ((*bitstreamPtr)>>12)&0xF; /* Bit 0..3 */
+
+ if (mode==20) {
+ enc_bits->startIdx = ((*bitstreamPtr)>>10)&0x3; /* Bit 4..5 */
+ enc_bits->state_first = ((*bitstreamPtr)>>9)&0x1; /* Bit 6 */
+ enc_bits->idxForMax = ((*bitstreamPtr)>>3)&0x3F; /* Bit 7..12 */
+ enc_bits->cb_index[0] = ((*bitstreamPtr)&0x7)<<4; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* Third int16_t */
+ enc_bits->cb_index[0] |= ((*bitstreamPtr)>>12)&0xE; /* Bit 0..2 */
+ enc_bits->gain_index[0] = ((*bitstreamPtr)>>8)&0x18; /* Bit 3..4 */
+ enc_bits->gain_index[1] = ((*bitstreamPtr)>>7)&0x8; /* Bit 5 */
+ enc_bits->cb_index[3] = ((*bitstreamPtr)>>2)&0xFE; /* Bit 6..12 */
+ enc_bits->gain_index[3] = ((*bitstreamPtr)<<2)&0x10; /* Bit 13 */
+ enc_bits->gain_index[4] = ((*bitstreamPtr)<<2)&0x8; /* Bit 14 */
+ enc_bits->gain_index[6] = ((*bitstreamPtr)<<4)&0x10; /* Bit 15 */
+ } else { /* mode==30 */
+ enc_bits->lsf[3] = ((*bitstreamPtr)>>6)&0x3F; /* Bit 4..9 */
+ enc_bits->lsf[4] = ((*bitstreamPtr)<<1)&0x7E; /* Bit 10..15 */
+ bitstreamPtr++;
+ /* Third int16_t */
+ enc_bits->lsf[4] |= ((*bitstreamPtr)>>15)&0x1; /* Bit 0 */
+ enc_bits->lsf[5] = ((*bitstreamPtr)>>8)&0x7F; /* Bit 1..7 */
+ enc_bits->startIdx = ((*bitstreamPtr)>>5)&0x7; /* Bit 8..10 */
+ enc_bits->state_first = ((*bitstreamPtr)>>4)&0x1; /* Bit 11 */
+ enc_bits->idxForMax = ((*bitstreamPtr)<<2)&0x3C; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 4:th int16_t */
+ enc_bits->idxForMax |= ((*bitstreamPtr)>>14)&0x3; /* Bit 0..1 */
+ enc_bits->cb_index[0] = ((*bitstreamPtr)>>7)&0x78; /* Bit 2..5 */
+ enc_bits->gain_index[0] = ((*bitstreamPtr)>>5)&0x10; /* Bit 6 */
+ enc_bits->gain_index[1] = ((*bitstreamPtr)>>5)&0x8; /* Bit 7 */
+ enc_bits->cb_index[3] = ((*bitstreamPtr))&0xFC; /* Bit 8..13 */
+ enc_bits->gain_index[3] = ((*bitstreamPtr)<<3)&0x10; /* Bit 14 */
+ enc_bits->gain_index[4] = ((*bitstreamPtr)<<3)&0x8; /* Bit 15 */
+ }
+ /* Class 2 bits of ULP */
+ /* 4:th to 6:th int16_t for 20 ms case
+ 5:th to 7:th int16_t for 30 ms case */
+ bitstreamPtr++;
+ tmpPtr=enc_bits->idxVec;
+ for (k=0; k<3; k++) {
+ for (i=15; i>=0; i--) {
+ (*tmpPtr) = (((*bitstreamPtr)>>i)<<2)&0x4;
+ /* Bit 15-i */
+ tmpPtr++;
+ }
+ bitstreamPtr++;
+ }
+
+ if (mode==20) {
+ /* 7:th int16_t */
+ for (i=15; i>6; i--) {
+ (*tmpPtr) = (((*bitstreamPtr)>>i)<<2)&0x4;
+ /* Bit 15-i */
+ tmpPtr++;
+ }
+ enc_bits->gain_index[1] |= ((*bitstreamPtr)>>4)&0x4; /* Bit 9 */
+ enc_bits->gain_index[3] |= ((*bitstreamPtr)>>2)&0xC; /* Bit 10..11 */
+ enc_bits->gain_index[4] |= ((*bitstreamPtr)>>1)&0x4; /* Bit 12 */
+ enc_bits->gain_index[6] |= ((*bitstreamPtr)<<1)&0x8; /* Bit 13 */
+ enc_bits->gain_index[7] = ((*bitstreamPtr)<<2)&0xC; /* Bit 14..15 */
+
+ } else { /* mode==30 */
+ /* 8:th int16_t */
+ for (i=15; i>5; i--) {
+ (*tmpPtr) = (((*bitstreamPtr)>>i)<<2)&0x4;
+ /* Bit 15-i */
+ tmpPtr++;
+ }
+ enc_bits->cb_index[0] |= ((*bitstreamPtr)>>3)&0x6; /* Bit 10..11 */
+ enc_bits->gain_index[0] |= ((*bitstreamPtr))&0x8; /* Bit 12 */
+ enc_bits->gain_index[1] |= ((*bitstreamPtr))&0x4; /* Bit 13 */
+ enc_bits->cb_index[3] |= ((*bitstreamPtr))&0x2; /* Bit 14 */
+ enc_bits->cb_index[6] = ((*bitstreamPtr)<<7)&0x80; /* Bit 15 */
+ bitstreamPtr++;
+ /* 9:th int16_t */
+ enc_bits->cb_index[6] |= ((*bitstreamPtr)>>9)&0x7E; /* Bit 0..5 */
+ enc_bits->cb_index[9] = ((*bitstreamPtr)>>2)&0xFE; /* Bit 6..12 */
+ enc_bits->cb_index[12] = ((*bitstreamPtr)<<5)&0xE0; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* 10:th int16_t */
+ enc_bits->cb_index[12] |= ((*bitstreamPtr)>>11)&0x1E;/* Bit 0..3 */
+ enc_bits->gain_index[3] |= ((*bitstreamPtr)>>8)&0xC; /* Bit 4..5 */
+ enc_bits->gain_index[4] |= ((*bitstreamPtr)>>7)&0x6; /* Bit 6..7 */
+ enc_bits->gain_index[6] = ((*bitstreamPtr)>>3)&0x18; /* Bit 8..9 */
+ enc_bits->gain_index[7] = ((*bitstreamPtr)>>2)&0xC; /* Bit 10..11 */
+ enc_bits->gain_index[9] = ((*bitstreamPtr)<<1)&0x10; /* Bit 12 */
+ enc_bits->gain_index[10] = ((*bitstreamPtr)<<1)&0x8; /* Bit 13 */
+ enc_bits->gain_index[12] = ((*bitstreamPtr)<<3)&0x10; /* Bit 14 */
+ enc_bits->gain_index[13] = ((*bitstreamPtr)<<3)&0x8; /* Bit 15 */
+ }
+ bitstreamPtr++;
+ /* Class 3 bits of ULP */
+ /* 8:th to 14:th int16_t for 20 ms case
+ 11:th to 17:th int16_t for 30 ms case */
+ tmpPtr=enc_bits->idxVec;
+ for (k=0; k<7; k++) {
+ for (i=14; i>=0; i-=2) {
+ (*tmpPtr) |= ((*bitstreamPtr)>>i)&0x3; /* Bit 15-i..14-i*/
+ tmpPtr++;
+ }
+ bitstreamPtr++;
+ }
+
+ if (mode==20) {
+ /* 15:th int16_t */
+ enc_bits->idxVec[56] |= ((*bitstreamPtr)>>14)&0x3; /* Bit 0..1 */
+ enc_bits->cb_index[0] |= ((*bitstreamPtr)>>13)&0x1; /* Bit 2 */
+ enc_bits->cb_index[1] = ((*bitstreamPtr)>>6)&0x7F; /* Bit 3..9 */
+ enc_bits->cb_index[2] = ((*bitstreamPtr)<<1)&0x7E; /* Bit 10..15 */
+ bitstreamPtr++;
+ /* 16:th int16_t */
+ enc_bits->cb_index[2] |= ((*bitstreamPtr)>>15)&0x1; /* Bit 0 */
+ enc_bits->gain_index[0] |= ((*bitstreamPtr)>>12)&0x7; /* Bit 1..3 */
+ enc_bits->gain_index[1] |= ((*bitstreamPtr)>>10)&0x3; /* Bit 4..5 */
+ enc_bits->gain_index[2] = ((*bitstreamPtr)>>7)&0x7; /* Bit 6..8 */
+ enc_bits->cb_index[3] |= ((*bitstreamPtr)>>6)&0x1; /* Bit 9 */
+ enc_bits->cb_index[4] = ((*bitstreamPtr)<<1)&0x7E; /* Bit 10..15 */
+ bitstreamPtr++;
+ /* 17:th int16_t */
+ enc_bits->cb_index[4] |= ((*bitstreamPtr)>>15)&0x1; /* Bit 0 */
+ enc_bits->cb_index[5] = ((*bitstreamPtr)>>8)&0x7F; /* Bit 1..7 */
+ enc_bits->cb_index[6] = ((*bitstreamPtr))&0xFF; /* Bit 8..15 */
+ bitstreamPtr++;
+ /* 18:th int16_t */
+ enc_bits->cb_index[7] = (*bitstreamPtr)>>8; /* Bit 0..7 */
+ enc_bits->cb_index[8] = (*bitstreamPtr)&0xFF; /* Bit 8..15 */
+ bitstreamPtr++;
+ /* 19:th int16_t */
+ enc_bits->gain_index[3] |= ((*bitstreamPtr)>>14)&0x3; /* Bit 0..1 */
+ enc_bits->gain_index[4] |= ((*bitstreamPtr)>>12)&0x3; /* Bit 2..3 */
+ enc_bits->gain_index[5] = ((*bitstreamPtr)>>9)&0x7; /* Bit 4..6 */
+ enc_bits->gain_index[6] |= ((*bitstreamPtr)>>6)&0x7; /* Bit 7..9 */
+ enc_bits->gain_index[7] |= ((*bitstreamPtr)>>4)&0x3; /* Bit 10..11 */
+ enc_bits->gain_index[8] = ((*bitstreamPtr)>>1)&0x7; /* Bit 12..14 */
+ } else { /* mode==30 */
+ /* 18:th int16_t */
+ enc_bits->idxVec[56] |= ((*bitstreamPtr)>>14)&0x3; /* Bit 0..1 */
+ enc_bits->idxVec[57] |= ((*bitstreamPtr)>>12)&0x3; /* Bit 2..3 */
+ enc_bits->cb_index[0] |= ((*bitstreamPtr)>>11)&1; /* Bit 4 */
+ enc_bits->cb_index[1] = ((*bitstreamPtr)>>4)&0x7F; /* Bit 5..11 */
+ enc_bits->cb_index[2] = ((*bitstreamPtr)<<3)&0x78; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 19:th int16_t */
+ enc_bits->cb_index[2] |= ((*bitstreamPtr)>>13)&0x7; /* Bit 0..2 */
+ enc_bits->gain_index[0] |= ((*bitstreamPtr)>>10)&0x7; /* Bit 3..5 */
+ enc_bits->gain_index[1] |= ((*bitstreamPtr)>>8)&0x3; /* Bit 6..7 */
+ enc_bits->gain_index[2] = ((*bitstreamPtr)>>5)&0x7; /* Bit 8..10 */
+ enc_bits->cb_index[3] |= ((*bitstreamPtr)>>4)&0x1; /* Bit 11 */
+ enc_bits->cb_index[4] = ((*bitstreamPtr)<<3)&0x78; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 20:th int16_t */
+ enc_bits->cb_index[4] |= ((*bitstreamPtr)>>13)&0x7; /* Bit 0..2 */
+ enc_bits->cb_index[5] = ((*bitstreamPtr)>>6)&0x7F; /* Bit 3..9 */
+ enc_bits->cb_index[6] |= ((*bitstreamPtr)>>5)&0x1; /* Bit 10 */
+ enc_bits->cb_index[7] = ((*bitstreamPtr)<<3)&0xF8; /* Bit 11..15 */
+ bitstreamPtr++;
+ /* 21:st int16_t */
+ enc_bits->cb_index[7] |= ((*bitstreamPtr)>>13)&0x7; /* Bit 0..2 */
+ enc_bits->cb_index[8] = ((*bitstreamPtr)>>5)&0xFF; /* Bit 3..10 */
+ enc_bits->cb_index[9] |= ((*bitstreamPtr)>>4)&0x1; /* Bit 11 */
+ enc_bits->cb_index[10] = ((*bitstreamPtr)<<4)&0xF0; /* Bit 12..15 */
+ bitstreamPtr++;
+ /* 22:nd int16_t */
+ enc_bits->cb_index[10] |= ((*bitstreamPtr)>>12)&0xF; /* Bit 0..3 */
+ enc_bits->cb_index[11] = ((*bitstreamPtr)>>4)&0xFF; /* Bit 4..11 */
+ enc_bits->cb_index[12] |= ((*bitstreamPtr)>>3)&0x1; /* Bit 12 */
+ enc_bits->cb_index[13] = ((*bitstreamPtr)<<5)&0xE0; /* Bit 13..15 */
+ bitstreamPtr++;
+ /* 23:rd int16_t */
+ enc_bits->cb_index[13] |= ((*bitstreamPtr)>>11)&0x1F;/* Bit 0..4 */
+ enc_bits->cb_index[14] = ((*bitstreamPtr)>>3)&0xFF; /* Bit 5..12 */
+ enc_bits->gain_index[3] |= ((*bitstreamPtr)>>1)&0x3; /* Bit 13..14 */
+ enc_bits->gain_index[4] |= ((*bitstreamPtr)&0x1); /* Bit 15 */
+ bitstreamPtr++;
+ /* 24:rd int16_t */
+ enc_bits->gain_index[5] = ((*bitstreamPtr)>>13)&0x7; /* Bit 0..2 */
+ enc_bits->gain_index[6] |= ((*bitstreamPtr)>>10)&0x7; /* Bit 3..5 */
+ enc_bits->gain_index[7] |= ((*bitstreamPtr)>>8)&0x3; /* Bit 6..7 */
+ enc_bits->gain_index[8] = ((*bitstreamPtr)>>5)&0x7; /* Bit 8..10 */
+ enc_bits->gain_index[9] |= ((*bitstreamPtr)>>1)&0xF; /* Bit 11..14 */
+ enc_bits->gain_index[10] |= ((*bitstreamPtr)<<2)&0x4; /* Bit 15 */
+ bitstreamPtr++;
+ /* 25:rd int16_t */
+ enc_bits->gain_index[10] |= ((*bitstreamPtr)>>14)&0x3; /* Bit 0..1 */
+ enc_bits->gain_index[11] = ((*bitstreamPtr)>>11)&0x7; /* Bit 2..4 */
+ enc_bits->gain_index[12] |= ((*bitstreamPtr)>>7)&0xF; /* Bit 5..8 */
+ enc_bits->gain_index[13] |= ((*bitstreamPtr)>>4)&0x7; /* Bit 9..11 */
+ enc_bits->gain_index[14] = ((*bitstreamPtr)>>1)&0x7; /* Bit 12..14 */
+ }
+ /* Last bit should be zero, otherwise it's an "empty" frame */
+ if (((*bitstreamPtr)&0x1) == 1) {
+ return(1);
+ } else {
+ return(0);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.h
new file mode 100644
index 0000000000..1a63280e6b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/unpack_bits.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_UnpackBits.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_UNPACK_BITS_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_UNPACK_BITS_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * unpacking of bits from bitstream, i.e., vector of bytes
+ *---------------------------------------------------------------*/
+
+int16_t
+WebRtcIlbcfix_UnpackBits(/* (o) "Empty" frame indicator */
+ const uint16_t*
+ bitstream, /* (i) The packatized bitstream */
+ iLBC_bits*
+ enc_bits, /* (o) Paramerers from bitstream */
+ int16_t mode /* (i) Codec mode (20 or 30) */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.c
new file mode 100644
index 0000000000..d9375fb995
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Vq3.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/vq3.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+
+/*----------------------------------------------------------------*
+ * vector quantization
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Vq3(
+ int16_t *Xq, /* quantized vector (Q13) */
+ int16_t *index,
+ int16_t *CB, /* codebook in Q13 */
+ int16_t *X, /* vector to quantize (Q13) */
+ int16_t n_cb
+ ){
+ int16_t i, j;
+ int16_t pos, minindex=0;
+ int16_t tmp;
+ int32_t dist, mindist;
+
+ pos = 0;
+ mindist = WEBRTC_SPL_WORD32_MAX; /* start value */
+
+ /* Find the codebook with the lowest square distance */
+ for (j = 0; j < n_cb; j++) {
+ tmp = X[0] - CB[pos];
+ dist = tmp * tmp;
+ for (i = 1; i < 3; i++) {
+ tmp = X[i] - CB[pos + i];
+ dist += tmp * tmp;
+ }
+
+ if (dist < mindist) {
+ mindist = dist;
+ minindex = j;
+ }
+ pos += 3;
+ }
+
+ /* Store the quantized codebook and the index */
+ for (i = 0; i < 3; i++) {
+ Xq[i] = CB[minindex*3 + i];
+ }
+ *index = minindex;
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.h
new file mode 100644
index 0000000000..c946478a1a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq3.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Vq3.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ3_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ3_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Vector quantization of order 3 (based on MSE)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Vq3(
+ int16_t* Xq, /* (o) the quantized vector (Q13) */
+ int16_t* index, /* (o) the quantization index */
+ int16_t* CB, /* (i) the vector quantization codebook (Q13) */
+ int16_t* X, /* (i) the vector to quantize (Q13) */
+ int16_t n_cb /* (i) the number of vectors in the codebook */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.c
new file mode 100644
index 0000000000..c9a65aec2a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Vq4.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/vq4.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+
+/*----------------------------------------------------------------*
+ * vector quantization
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Vq4(
+ int16_t *Xq, /* quantized vector (Q13) */
+ int16_t *index,
+ int16_t *CB, /* codebook in Q13 */
+ int16_t *X, /* vector to quantize (Q13) */
+ int16_t n_cb
+ ){
+ int16_t i, j;
+ int16_t pos, minindex=0;
+ int16_t tmp;
+ int32_t dist, mindist;
+
+ pos = 0;
+ mindist = WEBRTC_SPL_WORD32_MAX; /* start value */
+
+ /* Find the codebook with the lowest square distance */
+ for (j = 0; j < n_cb; j++) {
+ tmp = X[0] - CB[pos];
+ dist = tmp * tmp;
+ for (i = 1; i < 4; i++) {
+ tmp = X[i] - CB[pos + i];
+ dist += tmp * tmp;
+ }
+
+ if (dist < mindist) {
+ mindist = dist;
+ minindex = j;
+ }
+ pos += 4;
+ }
+
+ /* Store the quantized codebook and the index */
+ for (i = 0; i < 4; i++) {
+ Xq[i] = CB[minindex*4 + i];
+ }
+ *index = minindex;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.h
new file mode 100644
index 0000000000..6d14830c03
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/vq4.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Vq4.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ4_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ4_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * Vector quantization of order 4 (based on MSE)
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Vq4(
+ int16_t* Xq, /* (o) the quantized vector (Q13) */
+ int16_t* index, /* (o) the quantization index */
+ int16_t* CB, /* (i) the vector quantization codebook (Q13) */
+ int16_t* X, /* (i) the vector to quantize (Q13) */
+ int16_t n_cb /* (i) the number of vectors in the codebook */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.c
new file mode 100644
index 0000000000..e82d167220
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Window32W32.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/window32_w32.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * window multiplication
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Window32W32(
+ int32_t *z, /* Output */
+ int32_t *x, /* Input (same domain as Output)*/
+ const int32_t *y, /* Q31 Window */
+ size_t N /* length to process */
+ ) {
+ size_t i;
+ int16_t x_low, x_hi, y_low, y_hi;
+ int16_t left_shifts;
+ int32_t temp;
+
+ left_shifts = (int16_t)WebRtcSpl_NormW32(x[0]);
+ WebRtcSpl_VectorBitShiftW32(x, N, x, (int16_t)(-left_shifts));
+
+
+ /* The double precision numbers use a special representation:
+ * w32 = hi<<16 + lo<<1
+ */
+ for (i = 0; i < N; i++) {
+ /* Extract higher bytes */
+ x_hi = (int16_t)(x[i] >> 16);
+ y_hi = (int16_t)(y[i] >> 16);
+
+ /* Extract lower bytes, defined as (w32 - hi<<16)>>1 */
+ x_low = (int16_t)((x[i] - (x_hi << 16)) >> 1);
+
+ y_low = (int16_t)((y[i] - (y_hi << 16)) >> 1);
+
+ /* Calculate z by a 32 bit multiplication using both low and high from x and y */
+ temp = ((x_hi * y_hi) << 1) + ((x_hi * y_low) >> 14);
+
+ z[i] = temp + ((x_low * y_hi) >> 14);
+ }
+
+ WebRtcSpl_VectorBitShiftW32(z, N, z, left_shifts);
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.h
new file mode 100644
index 0000000000..15d72c5ba2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/window32_w32.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_Window32W32.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_WINDOW32_W32_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_WINDOW32_W32_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * window multiplication
+ *---------------------------------------------------------------*/
+
+void WebRtcIlbcfix_Window32W32(int32_t* z, /* Output */
+ int32_t* x, /* Input (same domain as Output)*/
+ const int32_t* y, /* Q31 Window */
+ size_t N /* length to process */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.c b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.c
new file mode 100644
index 0000000000..9dc880b37e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_XcorrCoef.c
+
+******************************************************************/
+
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
+/*----------------------------------------------------------------*
+ * cross correlation which finds the optimal lag for the
+ * crossCorr*crossCorr/(energy) criteria
+ *---------------------------------------------------------------*/
+
+size_t WebRtcIlbcfix_XcorrCoef(
+ int16_t *target, /* (i) first array */
+ int16_t *regressor, /* (i) second array */
+ size_t subl, /* (i) dimension arrays */
+ size_t searchLen, /* (i) the search lenght */
+ size_t offset, /* (i) samples offset between arrays */
+ int16_t step /* (i) +1 or -1 */
+ ){
+ size_t k;
+ size_t maxlag;
+ int16_t pos;
+ int16_t max;
+ int16_t crossCorrScale, Energyscale;
+ int16_t crossCorrSqMod, crossCorrSqMod_Max;
+ int32_t crossCorr, Energy;
+ int16_t crossCorrmod, EnergyMod, EnergyMod_Max;
+ int16_t *tp, *rp;
+ int16_t *rp_beg, *rp_end;
+ int16_t totscale, totscale_max;
+ int16_t scalediff;
+ int32_t newCrit, maxCrit;
+ int shifts;
+
+ /* Initializations, to make sure that the first one is selected */
+ crossCorrSqMod_Max=0;
+ EnergyMod_Max=WEBRTC_SPL_WORD16_MAX;
+ totscale_max=-500;
+ maxlag=0;
+ pos=0;
+
+ /* Find scale value and start position */
+ if (step==1) {
+ max=WebRtcSpl_MaxAbsValueW16(regressor, subl + searchLen - 1);
+ rp_beg = regressor;
+ rp_end = regressor + subl;
+ } else { /* step==-1 */
+ max = WebRtcSpl_MaxAbsValueW16(regressor - searchLen, subl + searchLen - 1);
+ rp_beg = regressor - 1;
+ rp_end = regressor + subl - 1;
+ }
+
+ /* Introduce a scale factor on the Energy in int32_t in
+ order to make sure that the calculation does not
+ overflow */
+
+ if (max>5000) {
+ shifts=2;
+ } else {
+ shifts=0;
+ }
+
+ /* Calculate the first energy, then do a +/- to get the other energies */
+ Energy=WebRtcSpl_DotProductWithScale(regressor, regressor, subl, shifts);
+
+ for (k=0;k<searchLen;k++) {
+ tp = target;
+ rp = &regressor[pos];
+
+ crossCorr=WebRtcSpl_DotProductWithScale(tp, rp, subl, shifts);
+
+ if ((Energy>0)&&(crossCorr>0)) {
+
+ /* Put cross correlation and energy on 16 bit word */
+ crossCorrScale=(int16_t)WebRtcSpl_NormW32(crossCorr)-16;
+ crossCorrmod=(int16_t)WEBRTC_SPL_SHIFT_W32(crossCorr, crossCorrScale);
+ Energyscale=(int16_t)WebRtcSpl_NormW32(Energy)-16;
+ EnergyMod=(int16_t)WEBRTC_SPL_SHIFT_W32(Energy, Energyscale);
+
+ /* Square cross correlation and store upper int16_t */
+ crossCorrSqMod = (int16_t)((crossCorrmod * crossCorrmod) >> 16);
+
+ /* Calculate the total number of (dynamic) right shifts that have
+ been performed on (crossCorr*crossCorr)/energy
+ */
+ totscale=Energyscale-(crossCorrScale<<1);
+
+ /* Calculate the shift difference in order to be able to compare the two
+ (crossCorr*crossCorr)/energy in the same domain
+ */
+ scalediff=totscale-totscale_max;
+ scalediff=WEBRTC_SPL_MIN(scalediff,31);
+ scalediff=WEBRTC_SPL_MAX(scalediff,-31);
+
+ /* Compute the cross multiplication between the old best criteria
+ and the new one to be able to compare them without using a
+ division */
+
+ if (scalediff<0) {
+ newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max)>>(-scalediff);
+ maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod);
+ } else {
+ newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max);
+ maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod)>>scalediff;
+ }
+
+ /* Store the new lag value if the new criteria is larger
+ than previous largest criteria */
+
+ if (newCrit > maxCrit) {
+ crossCorrSqMod_Max = crossCorrSqMod;
+ EnergyMod_Max = EnergyMod;
+ totscale_max = totscale;
+ maxlag = k;
+ }
+ }
+ pos+=step;
+
+ /* Do a +/- to get the next energy */
+ Energy += step * ((*rp_end * *rp_end - *rp_beg * *rp_beg) >> shifts);
+ rp_beg+=step;
+ rp_end+=step;
+ }
+
+ return(maxlag+offset);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.h b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.h
new file mode 100644
index 0000000000..3be5a296b5
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ WebRtcIlbcfix_XcorrCoef.h
+
+******************************************************************/
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_XCORR_COEF_H_
+#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_XCORR_COEF_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------*
+ * cross correlation which finds the optimal lag for the
+ * crossCorr*crossCorr/(energy) criteria
+ *---------------------------------------------------------------*/
+
+size_t WebRtcIlbcfix_XcorrCoef(
+ int16_t* target, /* (i) first array */
+ int16_t* regressor, /* (i) second array */
+ size_t subl, /* (i) dimension arrays */
+ size_t searchLen, /* (i) the search lenght */
+ size_t offset, /* (i) samples offset between arrays */
+ int16_t step /* (i) +1 or -1 */
+ );
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
new file mode 100644
index 0000000000..aae708f295
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_decoder.h"
+#include "api/scoped_refptr.h"
+
+namespace webrtc {
+
+template <typename T>
+class AudioDecoderIsacT final : public AudioDecoder {
+ public:
+ struct Config {
+ bool IsOk() const;
+ int sample_rate_hz = 16000;
+ };
+ explicit AudioDecoderIsacT(const Config& config);
+ virtual ~AudioDecoderIsacT() override;
+
+ AudioDecoderIsacT(const AudioDecoderIsacT&) = delete;
+ AudioDecoderIsacT& operator=(const AudioDecoderIsacT&) = delete;
+
+ bool HasDecodePlc() const override;
+ size_t DecodePlc(size_t num_frames, int16_t* decoded) override;
+ void Reset() override;
+ int ErrorCode() override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ typename T::instance_type* isac_state_;
+ int sample_rate_hz_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h
new file mode 100644
index 0000000000..2e43fd317f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+template <typename T>
+bool AudioDecoderIsacT<T>::Config::IsOk() const {
+ return (sample_rate_hz == 16000 || sample_rate_hz == 32000);
+}
+
+template <typename T>
+AudioDecoderIsacT<T>::AudioDecoderIsacT(const Config& config)
+ : sample_rate_hz_(config.sample_rate_hz) {
+ RTC_CHECK(config.IsOk()) << "Unsupported sample rate "
+ << config.sample_rate_hz;
+ RTC_CHECK_EQ(0, T::Create(&isac_state_));
+ T::DecoderInit(isac_state_);
+ RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz_));
+}
+
+template <typename T>
+AudioDecoderIsacT<T>::~AudioDecoderIsacT() {
+ RTC_CHECK_EQ(0, T::Free(isac_state_));
+}
+
+template <typename T>
+int AudioDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz);
+ int16_t temp_type = 1; // Default is speech.
+ int ret =
+ T::DecodeInternal(isac_state_, encoded, encoded_len, decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+template <typename T>
+bool AudioDecoderIsacT<T>::HasDecodePlc() const {
+ return false;
+}
+
+template <typename T>
+size_t AudioDecoderIsacT<T>::DecodePlc(size_t num_frames, int16_t* decoded) {
+ return T::DecodePlc(isac_state_, decoded, num_frames);
+}
+
+template <typename T>
+void AudioDecoderIsacT<T>::Reset() {
+ T::DecoderInit(isac_state_);
+}
+
+template <typename T>
+int AudioDecoderIsacT<T>::ErrorCode() {
+ return T::GetErrorCode(isac_state_);
+}
+
+template <typename T>
+int AudioDecoderIsacT<T>::SampleRateHz() const {
+ return sample_rate_hz_;
+}
+
+template <typename T>
+size_t AudioDecoderIsacT<T>::Channels() const {
+ return 1;
+}
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_DECODER_ISAC_T_IMPL_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
new file mode 100644
index 0000000000..c382ea076e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
+
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/scoped_refptr.h"
+#include "api/units/time_delta.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+template <typename T>
+class AudioEncoderIsacT final : public AudioEncoder {
+ public:
+ // Allowed combinations of sample rate, frame size, and bit rate are
+ // - 16000 Hz, 30 ms, 10000-32000 bps
+ // - 16000 Hz, 60 ms, 10000-32000 bps
+ // - 32000 Hz, 30 ms, 10000-56000 bps (if T has super-wideband support)
+ struct Config {
+ bool IsOk() const;
+ int payload_type = 103;
+ int sample_rate_hz = 16000;
+ int frame_size_ms = 30;
+ int bit_rate = kDefaultBitRate; // Limit on the short-term average bit
+ // rate, in bits/s.
+ int max_payload_size_bytes = -1;
+ int max_bit_rate = -1;
+ };
+
+ explicit AudioEncoderIsacT(const Config& config);
+ ~AudioEncoderIsacT() override;
+
+ AudioEncoderIsacT(const AudioEncoderIsacT&) = delete;
+ AudioEncoderIsacT& operator=(const AudioEncoderIsacT&) = delete;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+ void SetTargetBitrate(int target_bps) override;
+ void OnReceivedTargetAudioBitrate(int target_bps) override;
+ void OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) override;
+ void OnReceivedUplinkAllocation(BitrateAllocationUpdate update) override;
+ void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+ void Reset() override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+
+ private:
+ // This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and
+ // STREAM_MAXW16_60MS for iSAC fix (60 ms).
+ static const size_t kSufficientEncodeBufferSizeBytes = 400;
+
+ static constexpr int kDefaultBitRate = 32000;
+ static constexpr int kMinBitrateBps = 10000;
+ static constexpr int MaxBitrateBps(int sample_rate_hz) {
+ return sample_rate_hz == 32000 ? 56000 : 32000;
+ }
+
+ void SetTargetBitrate(int target_bps, bool subtract_per_packet_overhead);
+
+ // Recreate the iSAC encoder instance with the given settings, and save them.
+ void RecreateEncoderInstance(const Config& config);
+
+ Config config_;
+ typename T::instance_type* isac_state_ = nullptr;
+
+ // Have we accepted input but not yet emitted it in a packet?
+ bool packet_in_progress_ = false;
+
+ // Timestamp of the first input of the currently in-progress packet.
+ uint32_t packet_timestamp_;
+
+ // Timestamp of the previously encoded packet.
+ uint32_t last_encoded_timestamp_;
+
+ // Cache the value of the "WebRTC-SendSideBwe-WithOverhead" field trial.
+ const bool send_side_bwe_with_overhead_ =
+ !field_trial::IsDisabled("WebRTC-SendSideBwe-WithOverhead");
+
+ // When we send a packet, expect this many bytes of headers to be added to it.
+ // Start out with a reasonable default that we can use until we receive a real
+ // value.
+ DataSize overhead_per_packet_ = DataSize::Bytes(28);
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
new file mode 100644
index 0000000000..fa84515204
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_minmax.h"
+
+namespace webrtc {
+
+template <typename T>
+bool AudioEncoderIsacT<T>::Config::IsOk() const {
+ if (max_bit_rate < 32000 && max_bit_rate != -1)
+ return false;
+ if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
+ return false;
+
+ switch (sample_rate_hz) {
+ case 16000:
+ if (max_bit_rate > 53400)
+ return false;
+ if (max_payload_size_bytes > 400)
+ return false;
+ return (frame_size_ms == 30 || frame_size_ms == 60) &&
+ (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000));
+ case 32000:
+ if (max_bit_rate > 160000)
+ return false;
+ if (max_payload_size_bytes > 600)
+ return false;
+ return T::has_swb &&
+ (frame_size_ms == 30 &&
+ (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000)));
+ default:
+ return false;
+ }
+}
+
+template <typename T>
+AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) {
+ RecreateEncoderInstance(config);
+}
+
+template <typename T>
+AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
+ RTC_CHECK_EQ(0, T::Free(isac_state_));
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::SampleRateHz() const {
+ return T::EncSampRate(isac_state_);
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::NumChannels() const {
+ return 1;
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
+ const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
+ return static_cast<size_t>(rtc::CheckedDivExact(
+ samples_in_next_packet, rtc::CheckedDivExact(SampleRateHz(), 100)));
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
+ return 6; // iSAC puts at most 60 ms in a packet.
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::GetTargetBitrate() const {
+ return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::SetTargetBitrate(int target_bps) {
+ // Set target bitrate directly without subtracting per-packet overhead,
+ // because that's what AudioEncoderOpus does.
+ SetTargetBitrate(target_bps,
+ /*subtract_per_packet_overhead=*/false);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedTargetAudioBitrate(int target_bps) {
+ // Set target bitrate directly without subtracting per-packet overhead,
+ // because that's what AudioEncoderOpus does.
+ SetTargetBitrate(target_bps,
+ /*subtract_per_packet_overhead=*/false);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> /*bwe_period_ms*/) {
+ // Set target bitrate, subtracting the per-packet overhead if
+ // WebRTC-SendSideBwe-WithOverhead is enabled, because that's what
+ // AudioEncoderOpus does.
+ SetTargetBitrate(
+ target_audio_bitrate_bps,
+ /*subtract_per_packet_overhead=*/send_side_bwe_with_overhead_);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedUplinkAllocation(
+ BitrateAllocationUpdate update) {
+ // Set target bitrate, subtracting the per-packet overhead if
+ // WebRTC-SendSideBwe-WithOverhead is enabled, because that's what
+ // AudioEncoderOpus does.
+ SetTargetBitrate(
+ update.target_bitrate.bps<int>(),
+ /*subtract_per_packet_overhead=*/send_side_bwe_with_overhead_);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::OnReceivedOverhead(
+ size_t overhead_bytes_per_packet) {
+ overhead_per_packet_ = DataSize::Bytes(overhead_bytes_per_packet);
+}
+
+template <typename T>
+AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ if (!packet_in_progress_) {
+ // Starting a new packet; remember the timestamp for later.
+ packet_in_progress_ = true;
+ packet_timestamp_ = rtp_timestamp;
+ }
+ size_t encoded_bytes = encoded->AppendData(
+ kSufficientEncodeBufferSizeBytes, [&](rtc::ArrayView<uint8_t> encoded) {
+ int r = T::Encode(isac_state_, audio.data(), encoded.data());
+
+ if (T::GetErrorCode(isac_state_) == 6450) {
+ // Isac is not able to effectively compress all types of signals. This
+ // is a limitation of the codec that cannot be easily fixed.
+ r = 0;
+ }
+ RTC_CHECK_GE(r, 0) << "Encode failed (error code "
+ << T::GetErrorCode(isac_state_) << ")";
+
+ return static_cast<size_t>(r);
+ });
+
+ if (encoded_bytes == 0)
+ return EncodedInfo();
+
+ // Got enough input to produce a packet. Return the saved timestamp from
+ // the first chunk of input that went into the packet.
+ packet_in_progress_ = false;
+ EncodedInfo info;
+ info.encoded_bytes = encoded_bytes;
+ info.encoded_timestamp = packet_timestamp_;
+ info.payload_type = config_.payload_type;
+ info.encoder_type = CodecType::kIsac;
+ return info;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::Reset() {
+ RecreateEncoderInstance(config_);
+}
+
+template <typename T>
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderIsacT<T>::GetFrameLengthRange() const {
+ return {{TimeDelta::Millis(config_.frame_size_ms),
+ TimeDelta::Millis(config_.frame_size_ms)}};
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::SetTargetBitrate(int target_bps,
+ bool subtract_per_packet_overhead) {
+ if (subtract_per_packet_overhead) {
+ const DataRate overhead_rate =
+ overhead_per_packet_ / TimeDelta::Millis(config_.frame_size_ms);
+ target_bps -= overhead_rate.bps();
+ }
+ target_bps = rtc::SafeClamp(target_bps, kMinBitrateBps,
+ MaxBitrateBps(config_.sample_rate_hz));
+ int result = T::Control(isac_state_, target_bps, config_.frame_size_ms);
+ RTC_DCHECK_EQ(result, 0);
+ config_.bit_rate = target_bps;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
+ RTC_CHECK(config.IsOk());
+ packet_in_progress_ = false;
+ if (isac_state_)
+ RTC_CHECK_EQ(0, T::Free(isac_state_));
+ RTC_CHECK_EQ(0, T::Create(&isac_state_));
+ RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, /*coding_mode=*/1));
+ RTC_CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
+ const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
+ RTC_CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
+
+ if (config.max_payload_size_bytes != -1)
+ RTC_CHECK_EQ(
+ 0, T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
+ if (config.max_bit_rate != -1)
+ RTC_CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));
+
+ // Set the decoder sample rate even though we just use the encoder. This
+ // doesn't appear to be necessary to produce a valid encoding, but without it
+ // we get an encoding that isn't bit-for-bit identical with what a combined
+ // encoder+decoder object produces.
+ RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));
+
+ config_ = config;
+}
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/bandwidth_info.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/bandwidth_info.h
new file mode 100644
index 0000000000..c3830a5f7c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/bandwidth_info.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_BANDWIDTH_INFO_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_BANDWIDTH_INFO_H_
+
+#include <stdint.h>
+
+typedef struct {
+ int in_use;
+ int32_t send_bw_avg;
+ int32_t send_max_delay_avg;
+ int16_t bottleneck_idx;
+ int16_t jitter_info;
+} IsacBandwidthInfo;
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_BANDWIDTH_INFO_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/empty.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/empty.cc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/empty.cc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h
new file mode 100644
index 0000000000..0b4eadd448
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_DECODER_ISACFIX_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_DECODER_ISACFIX_H_
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h"
+
+namespace webrtc {
+
+using AudioDecoderIsacFixImpl = AudioDecoderIsacT<IsacFix>;
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_DECODER_ISACFIX_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h
new file mode 100644
index 0000000000..f0cc038328
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_ENCODER_ISACFIX_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_ENCODER_ISACFIX_H_
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h"
+
+namespace webrtc {
+
+using AudioEncoderIsacFixImpl = AudioEncoderIsacT<IsacFix>;
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_AUDIO_ENCODER_ISACFIX_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/isacfix.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/isacfix.h
new file mode 100644
index 0000000000..dcc7b0991d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/include/isacfix.h
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_ISACFIX_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_ISACFIX_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+
+typedef struct {
+ void* dummy;
+} ISACFIX_MainStruct;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/****************************************************************************
+ * WebRtcIsacfix_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Create(ISACFIX_MainStruct** ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : a ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Free(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_EncoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - CodingMode : 0 - Bit rate and frame length are automatically
+ * adjusted to available bandwidth on
+ * transmission channel.
+ * 1 - User sets a frame length and a target bit
+ * rate which is taken as the maximum short-term
+ * average bit rate.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t CodingMode);
+
+/****************************************************************************
+ * WebRtcIsacfix_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - speechIn : input speech vector.
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * 0 - The buffer didn't reach the chosen framesize
+ * so it keeps buffering speech samples.
+ * -1 - Error
+ */
+
+int WebRtcIsacfix_Encode(ISACFIX_MainStruct* ISAC_main_inst,
+ const int16_t* speechIn,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ */
+
+void WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate1(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet in bytes.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t arr_ts);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet in bytes.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - send_ts : the send time of the packet from RTP header,
+ * in samples.
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts);
+
+/****************************************************************************
+ * WebRtcIsacfix_Decode(...)
+ *
+ * This function decodes an ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+
+int WebRtcIsacfix_Decode(ISACFIX_MainStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling).
+ * Output speech length will be "480*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames (480sample = 30ms)
+ * to produce
+ * NOTE! Maximum number is 2 (960 samples = 60ms)
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : Number of samples in decoded PLC vector
+ */
+
+size_t WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames);
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ * - encoded_len_bytes : Length of the bitstream in bytes.
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadFrameLen(const uint8_t* encoded,
+ size_t encoded_len_bytes,
+ size_t* frameLength);
+
+/****************************************************************************
+ * WebRtcIsacfix_Control(...)
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second (between 10000 and 32000)
+ * - framesize : number of milliseconds per frame (30 or 60)
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Control(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t rate,
+ int framesize);
+
+void WebRtcIsacfix_SetInitialBweBottleneck(ISACFIX_MainStruct* ISAC_main_inst,
+ int bottleneck_bits_per_second);
+
+/****************************************************************************
+ * WebRtcIsacfix_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rateBPS : initial value of bottleneck in bits/second
+ * 10000 <= rateBPS <= 32000 is accepted
+ * - frameSizeMs : number of milliseconds per frame (30 or 60)
+ * - enforceFrameSize : 1 to enforce the given frame-size through out
+ * the adaptation process, 0 to let iSAC change
+ * the frame-size if required.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t rateBPS,
+ int frameSizeMs,
+ int16_t enforceFrameSize);
+
+/****************************************************************************
+ * WebRtcIsacfix_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+void WebRtcIsacfix_version(char* version);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occured in the
+ * specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+
+int16_t WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetUplinkBw(...)
+ *
+ * This function return iSAC send bitrate
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : <0 Error code
+ * else bitrate
+ */
+
+int32_t WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 msec packets.
+ * The absolute max will be valid until next time the function is called.
+ * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 100 and 400 bytes
+ *
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t maxPayloadBytes);
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for a
+ * singel packet. The maximum rate is set in bits per second.
+ * The codec has an absolute maximum rate of 53400 bits per second (200 bytes
+ * per 30 msec).
+ * It is possible to set a maximum rate between 32000 and 53400 bits per second.
+ *
+ * The rate limit is valid until next time the function is called.
+ *
+ * NOTE! Packet size will never go above the value set if calling
+ * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRateInBytes : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct* ISAC_main_inst,
+ int32_t maxRate);
+
+/****************************************************************************
+ * WebRtcIsacfix_CreateInternal(...)
+ *
+ * This function creates the memory that is used to store data in the encoder
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_FreeInternal(...)
+ *
+ * This function frees the internal memory for storing encoder data.
+ *
+ * Input:
+ * - ISAC_main_inst : an ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : index of bandwidth estimate to put in new
+ * bitstream - scale : factor for rate change (0.4 ~=> half the
+ * rate, 1 no change).
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t bweIndex,
+ float scale,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - rateIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t* rateIndex);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ * - rateIndex : Bandwidth estimate from other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t rateIndex);
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ * - encoded_len_bytes : Length of the bitstream in bytes.
+ *
+ * Output:
+ * - rateIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadBwIndex(const uint8_t* encoded,
+ size_t encoded_len_bytes,
+ int16_t* rateIndex);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewFrameLen(...)
+ *
+ * This function return the next frame length (in samples) of iSAC.
+ *
+ * Input:
+ * -ISAC_main_inst : iSAC instance
+ *
+ * Return value : frame lenght in samples
+ */
+
+int16_t WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct* ISAC_main_inst);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INCLUDE_ISACFIX_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines.c
new file mode 100644
index 0000000000..eaeef50f04
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routins.c
+ *
+ * This C file contains a function for finalizing the bitstream
+ * after arithmetic coding.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncTerminate(...)
+ *
+ * Final call to the arithmetic coder for an encoder call. This function
+ * terminates and return byte stream.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ *
+ * Return value : number of bytes in the stream
+ */
+int16_t WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData)
+{
+ uint16_t *streamPtr;
+ uint16_t negCarry;
+
+ /* point to the right place in the stream buffer */
+ streamPtr = streamData->stream + streamData->stream_index;
+
+ /* find minimum length (determined by current interval width) */
+ if ( streamData->W_upper > 0x01FFFFFF )
+ {
+ streamData->streamval += 0x01000000;
+
+ /* if result is less than the added value we must take care of the carry */
+ if (streamData->streamval < 0x01000000)
+ {
+ /* propagate carry */
+ if (streamData->full == 0) {
+ /* Add value to current value */
+ negCarry = *streamPtr;
+ negCarry += 0x0100;
+ *streamPtr = negCarry;
+
+ /* if value is too big, propagate carry to next byte, and so on */
+ while (!(negCarry))
+ {
+ negCarry = *--streamPtr;
+ negCarry++;
+ *streamPtr = negCarry;
+ }
+ } else {
+ /* propagate carry by adding one to the previous byte in the
+ * stream if that byte is 0xFFFF we need to propagate the carry
+ * furhter back in the stream */
+ while ( !(++(*--streamPtr)) );
+ }
+
+ /* put pointer back to the old value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ }
+ /* write remaining data to bitstream, if "full == 0" first byte has data */
+ if (streamData->full == 0) {
+ *streamPtr++ += (uint16_t)(streamData->streamval >> 24);
+ streamData->full = 1;
+ } else {
+ *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
+ streamData->full = 0;
+ }
+ }
+ else
+ {
+ streamData->streamval += 0x00010000;
+
+ /* if result is less than the added value we must take care of the carry */
+ if (streamData->streamval < 0x00010000)
+ {
+ /* propagate carry */
+ if (streamData->full == 0) {
+ /* Add value to current value */
+ negCarry = *streamPtr;
+ negCarry += 0x0100;
+ *streamPtr = negCarry;
+
+ /* if value to big, propagate carry to next byte, and so on */
+ while (!(negCarry))
+ {
+ negCarry = *--streamPtr;
+ negCarry++;
+ *streamPtr = negCarry;
+ }
+ } else {
+ /* Add carry to previous byte */
+ while ( !(++(*--streamPtr)) );
+ }
+
+ /* put pointer back to the old value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ }
+ /* write remaining data (2 bytes) to bitstream */
+ if (streamData->full) {
+ *streamPtr++ = (uint16_t)(streamData->streamval >> 16);
+ } else {
+ *streamPtr++ |= (uint16_t)(streamData->streamval >> 24);
+ *streamPtr = (uint16_t)(streamData->streamval >> 8) & 0xFF00;
+ }
+ }
+
+ /* calculate stream length in bytes */
+ return (((streamPtr - streamData->stream)<<1) + !(streamData->full));
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c
new file mode 100644
index 0000000000..cad3056b37
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_hist.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routinshist.c
+ *
+ * This C file contains arithmetic encoding and decoding.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+
+
+/****************************************************************************
+ * WebRtcIsacfix_EncHistMulti(...)
+ *
+ * Encode the histogram interval
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - data : data vector
+ * - cdf : array of cdf arrays
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok
+ * <0 if error detected
+ */
+int WebRtcIsacfix_EncHistMulti(Bitstr_enc *streamData,
+ const int16_t *data,
+ const uint16_t *const *cdf,
+ const int16_t lenData)
+{
+ uint32_t W_lower;
+ uint32_t W_upper;
+ uint32_t W_upper_LSB;
+ uint32_t W_upper_MSB;
+ uint16_t *streamPtr;
+ uint16_t negCarry;
+ uint16_t *maxStreamPtr;
+ uint16_t *streamPtrCarry;
+ uint32_t cdfLo;
+ uint32_t cdfHi;
+ int k;
+
+
+ /* point to beginning of stream buffer
+ * and set maximum streamPtr value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
+
+ W_upper = streamData->W_upper;
+
+ for (k = lenData; k > 0; k--)
+ {
+ /* fetch cdf_lower and cdf_upper from cdf tables */
+ cdfLo = (uint32_t) *(*cdf + (uint32_t)*data);
+ cdfHi = (uint32_t) *(*cdf++ + (uint32_t)*data++ + 1);
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = WEBRTC_SPL_UMUL(W_upper_MSB, cdfLo);
+ W_lower += ((W_upper_LSB * cdfLo) >> 16);
+ W_upper = WEBRTC_SPL_UMUL(W_upper_MSB, cdfHi);
+ W_upper += ((W_upper_LSB * cdfHi) >> 16);
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamData->streamval += W_lower;
+
+ /* handle carry */
+ if (streamData->streamval < W_lower)
+ {
+ /* propagate carry */
+ streamPtrCarry = streamPtr;
+ if (streamData->full == 0) {
+ negCarry = *streamPtrCarry;
+ negCarry += 0x0100;
+ *streamPtrCarry = negCarry;
+ while (!(negCarry))
+ {
+ negCarry = *--streamPtrCarry;
+ negCarry++;
+ *streamPtrCarry = negCarry;
+ }
+ } else {
+ while ( !(++(*--streamPtrCarry)) );
+ }
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval
+ * W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ W_upper <<= 8;
+ if (streamData->full == 0) {
+ *streamPtr++ += (uint16_t)(streamData->streamval >> 24);
+ streamData->full = 1;
+ } else {
+ *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
+ streamData->full = 0;
+ }
+
+ if( streamPtr > maxStreamPtr ) {
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+ }
+ streamData->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistBisectMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, using
+ * method of bisection cdf tables should be of size 2^k-1 (which corresponds
+ * to an alphabet size of 2^k-2)
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - cdfSize : array of cdf table sizes+1 (power of two: 2^k)
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in the stream
+ * <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t *data,
+ Bitstr_dec *streamData,
+ const uint16_t *const *cdf,
+ const uint16_t *cdfSize,
+ const int16_t lenData)
+{
+ uint32_t W_lower = 0;
+ uint32_t W_upper;
+ uint32_t W_tmp;
+ uint32_t W_upper_LSB;
+ uint32_t W_upper_MSB;
+ uint32_t streamval;
+ const uint16_t *streamPtr;
+ const uint16_t *cdfPtr;
+ int16_t sizeTmp;
+ int k;
+
+
+ streamPtr = streamData->stream + streamData->stream_index;
+ W_upper = streamData->W_upper;
+
+ /* Error check: should not be possible in normal operation */
+ if (W_upper == 0) {
+ return -2;
+ }
+
+ /* first time decoder is called for this stream */
+ if (streamData->stream_index == 0)
+ {
+ /* read first word from bytestream */
+ streamval = (uint32_t)*streamPtr++ << 16;
+ streamval |= *streamPtr++;
+ } else {
+ streamval = streamData->streamval;
+ }
+
+ for (k = lenData; k > 0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start halfway the cdf range */
+ sizeTmp = *cdfSize++ / 2;
+ cdfPtr = *cdf + (sizeTmp - 1);
+
+ /* method of bisection */
+ for ( ;; )
+ {
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+ W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+ sizeTmp /= 2;
+ if (sizeTmp == 0) {
+ break;
+ }
+
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ cdfPtr += sizeTmp;
+ } else {
+ W_upper = W_tmp;
+ cdfPtr -= sizeTmp;
+ }
+ }
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ *data++ = cdfPtr - *cdf++;
+ } else {
+ W_upper = W_tmp;
+ *data++ = cdfPtr - *cdf++ - 1;
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ /* W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ /* read next byte from stream */
+ if (streamData->full == 0) {
+ streamval = (streamval << 8) | (*streamPtr++ & 0x00FF);
+ streamData->full = 1;
+ } else {
+ streamval = (streamval << 8) | (*streamPtr >> 8);
+ streamData->full = 0;
+ }
+ W_upper <<= 8;
+ }
+
+
+ /* Error check: should not be possible in normal operation */
+ if (W_upper == 0) {
+ return -2;
+ }
+
+ }
+
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+ streamData->streamval = streamval;
+
+ if ( W_upper > 0x01FFFFFF ) {
+ return (streamData->stream_index*2 - 3 + !streamData->full);
+ } else {
+ return (streamData->stream_index*2 - 2 + !streamData->full);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistOneStepMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, taking
+ * single step up or down at a time.
+ * cdf tables can be of arbitrary size, but large tables may take a lot of
+ * iterations.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - initIndex : vector of initial cdf table search entries
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in original stream
+ * <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t *data,
+ Bitstr_dec *streamData,
+ const uint16_t *const *cdf,
+ const uint16_t *initIndex,
+ const int16_t lenData)
+{
+ uint32_t W_lower;
+ uint32_t W_upper;
+ uint32_t W_tmp;
+ uint32_t W_upper_LSB;
+ uint32_t W_upper_MSB;
+ uint32_t streamval;
+ const uint16_t *streamPtr;
+ const uint16_t *cdfPtr;
+ int k;
+
+
+ streamPtr = streamData->stream + streamData->stream_index;
+ W_upper = streamData->W_upper;
+ /* Error check: Should not be possible in normal operation */
+ if (W_upper == 0) {
+ return -2;
+ }
+
+ /* Check if it is the first time decoder is called for this stream */
+ if (streamData->stream_index == 0)
+ {
+ /* read first word from bytestream */
+ streamval = (uint32_t)(*streamPtr++) << 16;
+ streamval |= *streamPtr++;
+ } else {
+ streamval = streamData->streamval;
+ }
+
+ for (k = lenData; k > 0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+
+ /* start at the specified table entry */
+ cdfPtr = *cdf + (*initIndex++);
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+ W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+
+ if (streamval > W_tmp)
+ {
+ for ( ;; )
+ {
+ W_lower = W_tmp;
+
+ /* range check */
+ if (cdfPtr[0] == 65535) {
+ return -3;
+ }
+
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *++cdfPtr);
+ W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+
+ if (streamval <= W_tmp) {
+ break;
+ }
+ }
+ W_upper = W_tmp;
+ *data++ = cdfPtr - *cdf++ - 1;
+ } else {
+ for ( ;; )
+ {
+ W_upper = W_tmp;
+ --cdfPtr;
+
+ /* range check */
+ if (cdfPtr < *cdf) {
+ return -3;
+ }
+
+ W_tmp = WEBRTC_SPL_UMUL_32_16(W_upper_MSB, *cdfPtr);
+ W_tmp += (W_upper_LSB * (*cdfPtr)) >> 16;
+
+ if (streamval > W_tmp) {
+ break;
+ }
+ }
+ W_lower = W_tmp;
+ *data++ = cdfPtr - *cdf++;
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ /* W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ /* read next byte from stream */
+ if (streamData->full == 0) {
+ streamval = (streamval << 8) | (*streamPtr++ & 0x00FF);
+ streamData->full = 1;
+ } else {
+ streamval = (streamval << 8) | (*streamPtr >> 8);
+ streamData->full = 0;
+ }
+ W_upper <<= 8;
+ }
+ }
+
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+ streamData->streamval = streamval;
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF ) {
+ return (streamData->stream_index*2 - 3 + !streamData->full);
+ } else {
+ return (streamData->stream_index*2 - 2 + !streamData->full);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c
new file mode 100644
index 0000000000..8e97960461
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routines_logist.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routinslogist.c
+ *
+ * This C file contains arithmetic encode and decode logistic
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+
+/* Tables for piecewise linear cdf functions: y = k*x */
+
+/* x Points for function piecewise() in Q15 */
+static const int32_t kHistEdges[51] = {
+ -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
+ -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644,
+ -65536, -52429, -39322, -26215, -13108, 0, 13107, 26214, 39321, 52428,
+ 65536, 78643, 91750, 104857, 117964, 131072, 144179, 157286, 170393, 183500,
+ 196608, 209715, 222822, 235929, 249036, 262144, 275251, 288358, 301465, 314572,
+ 327680
+};
+
+
+/* k Points for function piecewise() in Q0 */
+static const uint16_t kCdfSlope[51] = {
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 13, 23, 47, 87, 154, 315, 700, 1088,
+ 2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
+ 1095, 660, 316, 145, 86, 41, 32, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
+ 0
+};
+
+/* y Points for function piecewise() in Q0 */
+static const uint16_t kCdfLogistic[51] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 22, 24, 29, 38, 57, 92, 153, 279, 559,
+ 994, 1983, 4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
+ 64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
+ 65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
+ 65535
+};
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Piecewise(...)
+ *
+ * Piecewise linear function
+ *
+ * Input:
+ * - xinQ15 : input value x in Q15
+ *
+ * Return value : korresponding y-value in Q0
+ */
+
+
+static __inline uint16_t WebRtcIsacfix_Piecewise(int32_t xinQ15) {
+ int32_t ind;
+ int32_t qtmp1;
+ uint16_t qtmp2;
+
+ /* Find index for x-value */
+ qtmp1 = WEBRTC_SPL_SAT(kHistEdges[50],xinQ15,kHistEdges[0]);
+ ind = WEBRTC_SPL_MUL(5, qtmp1 - kHistEdges[0]);
+ ind >>= 16;
+
+ /* Calculate corresponding y-value ans return*/
+ qtmp1 = qtmp1 - kHistEdges[ind];
+ qtmp2 = (uint16_t)WEBRTC_SPL_RSHIFT_U32(
+ WEBRTC_SPL_UMUL_32_16(qtmp1,kCdfSlope[ind]), 15);
+ return (kCdfLogistic[ind] + qtmp2);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_EncLogisticMulti2(...)
+ *
+ * Arithmetic coding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - dataQ7 : data vector in Q7
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok,
+ * <0 otherwise.
+ */
+int WebRtcIsacfix_EncLogisticMulti2(Bitstr_enc *streamData,
+ int16_t *dataQ7,
+ const uint16_t *envQ8,
+ const int16_t lenData)
+{
+ uint32_t W_lower;
+ uint32_t W_upper;
+ uint16_t W_upper_LSB;
+ uint16_t W_upper_MSB;
+ uint16_t *streamPtr;
+ uint16_t *maxStreamPtr;
+ uint16_t *streamPtrCarry;
+ uint16_t negcarry;
+ uint32_t cdfLo;
+ uint32_t cdfHi;
+ int k;
+
+ /* point to beginning of stream buffer
+ * and set maximum streamPtr value */
+ streamPtr = streamData->stream + streamData->stream_index;
+ maxStreamPtr = streamData->stream + STREAM_MAXW16_60MS - 1;
+ W_upper = streamData->W_upper;
+
+ for (k = 0; k < lenData; k++)
+ {
+ /* compute cdf_lower and cdf_upper by evaluating the
+ * WebRtcIsacfix_Piecewise linear cdf */
+ cdfLo = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
+ cdfHi = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
+
+ /* test and clip if probability gets too small */
+ while ((cdfLo + 1) >= cdfHi) {
+ /* clip */
+ if (*dataQ7 > 0) {
+ *dataQ7 -= 128;
+ cdfHi = cdfLo;
+ cdfLo = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(*dataQ7 - 64, *envQ8));
+ } else {
+ *dataQ7 += 128;
+ cdfLo = cdfHi;
+ cdfHi = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(*dataQ7 + 64, *envQ8));
+ }
+ }
+
+ dataQ7++;
+ /* increment only once per 4 iterations */
+ envQ8 += (k & 1) & (k >> 1);
+
+
+ /* update interval */
+ W_upper_LSB = (uint16_t)W_upper;
+ W_upper_MSB = (uint16_t)WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+ W_lower = WEBRTC_SPL_UMUL_32_16(cdfLo, W_upper_MSB);
+ W_lower += (cdfLo * W_upper_LSB) >> 16;
+ W_upper = WEBRTC_SPL_UMUL_32_16(cdfHi, W_upper_MSB);
+ W_upper += (cdfHi * W_upper_LSB) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamData->streamval += W_lower;
+
+ /* handle carry */
+ if (streamData->streamval < W_lower)
+ {
+ /* propagate carry */
+ streamPtrCarry = streamPtr;
+ if (streamData->full == 0) {
+ negcarry = *streamPtrCarry;
+ negcarry += 0x0100;
+ *streamPtrCarry = negcarry;
+ while (!(negcarry))
+ {
+ negcarry = *--streamPtrCarry;
+ negcarry++;
+ *streamPtrCarry = negcarry;
+ }
+ } else {
+ while (!(++(*--streamPtrCarry)));
+ }
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval
+ * W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ W_upper <<= 8;
+ if (streamData->full == 0) {
+ *streamPtr++ += (uint16_t) WEBRTC_SPL_RSHIFT_U32(
+ streamData->streamval, 24);
+ streamData->full = 1;
+ } else {
+ *streamPtr = (uint16_t)((streamData->streamval >> 24) << 8);
+ streamData->full = 0;
+ }
+
+ if( streamPtr > maxStreamPtr )
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+
+ streamData->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamData->stream_index = streamPtr - streamData->stream;
+ streamData->W_upper = W_upper;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecLogisticMulti2(...)
+ *
+ * Arithmetic decoding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Input/Output:
+ * - dataQ7 : input: dither vector, output: data vector
+ *
+ * Return value : number of bytes in the stream so far
+ * -1 if error detected
+ */
+int WebRtcIsacfix_DecLogisticMulti2(int16_t *dataQ7,
+ Bitstr_dec *streamData,
+ const int32_t *envQ8,
+ const int16_t lenData)
+{
+ uint32_t W_lower;
+ uint32_t W_upper;
+ uint32_t W_tmp;
+ uint16_t W_upper_LSB;
+ uint16_t W_upper_MSB;
+ uint32_t streamVal;
+ uint16_t cdfTmp;
+ int32_t res;
+ int32_t inSqrt;
+ int32_t newRes;
+ const uint16_t *streamPtr;
+ int16_t candQ7;
+ int16_t envCount;
+ uint16_t tmpARSpecQ8 = 0;
+ int k, i;
+ int offset = 0;
+
+ /* point to beginning of stream buffer */
+ streamPtr = streamData->stream + streamData->stream_index;
+ W_upper = streamData->W_upper;
+
+ /* Check if it is first time decoder is called for this stream */
+ if (streamData->stream_index == 0)
+ {
+ /* read first word from bytestream */
+ streamVal = (uint32_t)(*streamPtr++) << 16;
+ streamVal |= *streamPtr++;
+
+ } else {
+ streamVal = streamData->streamval;
+ }
+
+
+ res = 1 << (WebRtcSpl_GetSizeInBits(envQ8[0]) >> 1);
+ envCount = 0;
+
+ /* code assumes lenData%4 == 0 */
+ for (k = 0; k < lenData; k += 4)
+ {
+ int k4;
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ inSqrt = envQ8[envCount];
+ i = 10;
+
+ /* For safty reasons */
+ if (inSqrt < 0)
+ inSqrt=-inSqrt;
+
+ newRes = (inSqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (inSqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ tmpARSpecQ8 = (uint16_t)newRes;
+
+ for(k4 = 0; k4 < 4; k4++)
+ {
+ /* find the integer *data for which streamVal lies in [W_lower+1, W_upper] */
+ W_upper_LSB = (uint16_t) (W_upper & 0x0000FFFF);
+ W_upper_MSB = (uint16_t) WEBRTC_SPL_RSHIFT_U32(W_upper, 16);
+
+ /* find first candidate by inverting the logistic cdf
+ * Input dither value collected from io-stream */
+ candQ7 = - *dataQ7 + 64;
+ cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+ W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+ if (streamVal > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+ W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+ while (streamVal > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+ W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+ /* error check */
+ if (W_lower == W_tmp) {
+ return -1;
+ }
+ }
+ W_upper = W_tmp;
+
+ /* Output value put in dataQ7: another sample decoded */
+ *dataQ7 = candQ7 - 64;
+ }
+ else
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+ W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+ while ( !(streamVal > W_tmp) )
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdfTmp = WebRtcIsacfix_Piecewise(
+ WEBRTC_SPL_MUL_16_U16(candQ7, tmpARSpecQ8));
+
+ W_tmp = (uint32_t)cdfTmp * W_upper_MSB;
+ W_tmp += ((uint32_t)cdfTmp * (uint32_t)W_upper_LSB) >> 16;
+
+ /* error check */
+ if (W_upper == W_tmp){
+ return -1;
+ }
+ }
+ W_lower = W_tmp;
+
+ /* Output value put in dataQ7: another sample decoded */
+ *dataQ7 = candQ7 + 64;
+ }
+
+ dataQ7++;
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamVal -= W_lower;
+
+ /* renormalize interval and update streamVal
+ * W_upper < 2^24 */
+ while ( !(W_upper & 0xFF000000) )
+ {
+ if (streamPtr < streamData->stream + streamData->stream_size) {
+ /* read next byte from stream */
+ if (streamData->full == 0) {
+ streamVal = (streamVal << 8) | (*streamPtr++ & 0x00FF);
+ streamData->full = 1;
+ } else {
+ streamVal = (streamVal << 8) | (*streamPtr >> 8);
+ streamData->full = 0;
+ }
+ } else {
+ /* Intending to read outside the stream. This can happen for the last
+ * two or three bytes. It is how the algorithm is implemented. Do
+ * not read from the bit stream and insert zeros instead. */
+ streamVal <<= 8;
+ if (streamData->full == 0) {
+ offset++; // We would have incremented the pointer in this case.
+ streamData->full = 1;
+ } else {
+ streamData->full = 0;
+ }
+ }
+ W_upper <<= 8;
+ }
+ }
+ envCount++;
+ }
+
+ streamData->stream_index = streamPtr + offset - streamData->stream;
+ streamData->W_upper = W_upper;
+ streamData->streamval = streamVal;
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return (streamData->stream_index*2 - 3 + !streamData->full);
+ else
+ return (streamData->stream_index*2 - 2 + !streamData->full);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routins.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routins.h
new file mode 100644
index 0000000000..d112bfe7f2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/arith_routins.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routins.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+/****************************************************************************
+ * WebRtcIsacfix_EncLogisticMulti2(...)
+ *
+ * Arithmetic coding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - dataQ7 : data vector in Q7
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok,
+ * <0 otherwise.
+ */
+int WebRtcIsacfix_EncLogisticMulti2(Bitstr_enc* streamData,
+ int16_t* dataQ7,
+ const uint16_t* env,
+ int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_EncTerminate(...)
+ *
+ * Final call to the arithmetic coder for an encoder call. This function
+ * terminates and return byte stream.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ *
+ * Return value : number of bytes in the stream
+ */
+int16_t WebRtcIsacfix_EncTerminate(Bitstr_enc* streamData);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecLogisticMulti2(...)
+ *
+ * Arithmetic decoding of spectrum.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - envQ8 : side info vector defining the width of the pdf
+ * in Q8
+ * - lenData : data vector length
+ *
+ * Input/Output:
+ * - dataQ7 : input: dither vector, output: data vector, in Q7
+ *
+ * Return value : number of bytes in the stream so far
+ * <0 if error detected
+ */
+int WebRtcIsacfix_DecLogisticMulti2(int16_t* data,
+ Bitstr_dec* streamData,
+ const int32_t* env,
+ int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_EncHistMulti(...)
+ *
+ * Encode the histogram interval
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - data : data vector
+ * - cdf : array of cdf arrays
+ * - lenData : data vector length
+ *
+ * Return value : 0 if ok
+ * <0 if error detected
+ */
+int WebRtcIsacfix_EncHistMulti(Bitstr_enc* streamData,
+ const int16_t* data,
+ const uint16_t* const* cdf,
+ int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistBisectMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, using
+ * method of bisection.
+ * C df tables should be of size 2^k-1 (which corresponds to an
+ * alphabet size of 2^k-2)
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - cdfSize : array of cdf table sizes+1 (power of two: 2^k)
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in the stream
+ * <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistBisectMulti(int16_t* data,
+ Bitstr_dec* streamData,
+ const uint16_t* const* cdf,
+ const uint16_t* cdfSize,
+ int16_t lenData);
+
+/****************************************************************************
+ * WebRtcIsacfix_DecHistOneStepMulti(...)
+ *
+ * Function to decode more symbols from the arithmetic bytestream, taking
+ * single step up or down at a time.
+ * cdf tables can be of arbitrary size, but large tables may take a lot of
+ * iterations.
+ *
+ * Input:
+ * - streamData : in-/output struct containing bitstream
+ * - cdf : array of cdf arrays
+ * - initIndex : vector of initial cdf table search entries
+ * - lenData : data vector length
+ *
+ * Output:
+ * - data : data vector
+ *
+ * Return value : number of bytes in original stream
+ * <0 if error detected
+ */
+int16_t WebRtcIsacfix_DecHistOneStepMulti(int16_t* data,
+ Bitstr_dec* streamData,
+ const uint16_t* const* cdf,
+ const uint16_t* initIndex,
+ int16_t lenData);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ARITH_ROUTINS_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc
new file mode 100644
index 0000000000..21259ee2e2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_decoder_isacfix.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h"
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioDecoderIsacT<IsacFix>;
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
new file mode 100644
index 0000000000..0190ab91b6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h"
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioEncoderIsacT<IsacFix>;
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c
new file mode 100644
index 0000000000..8845357d59
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.c
@@ -0,0 +1,1021 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ * NOTE! Castings needed for C55, do not remove!
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/checks.h"
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const int16_t kQRateTable[12] = {
+ 10000, 11115, 12355, 13733, 15265, 16967,
+ 18860, 20963, 23301, 25900, 28789, 32000
+};
+
+/* 0.1 times the values in the table kQRateTable */
+/* values are in Q16 */
+static const int32_t KQRate01[12] = {
+ 65536000, 72843264, 80969728, 90000589, 100040704, 111194931,
+ 123600896, 137383117, 152705434, 169738240, 188671590, 209715200
+};
+
+/* Bits per Bytes Seconds
+ * 8 bits/byte * 1000 msec/sec * 1/framelength (in msec)->bits/byte*sec
+ * frame length will either be 30 or 60 msec. 8738 is 1/60 in Q19 and 1/30 in Q18
+ * The following number is either in Q15 or Q14 depending on the current frame length */
+static const int32_t kBitsByteSec = 4369000;
+
+/* Received header rate. First value is for 30 ms packets and second for 60 ms */
+static const int16_t kRecHeaderRate[2] = {
+ 9333, 4666
+};
+
+/* Inverted minimum and maximum bandwidth in Q30.
+ minBwInv 30 ms, maxBwInv 30 ms,
+ minBwInv 60 ms, maxBwInv 69 ms
+*/
+static const int32_t kInvBandwidth[4] = {
+ 55539, 25978,
+ 73213, 29284
+};
+
+/* Number of samples in 25 msec */
+static const int32_t kSamplesIn25msec = 400;
+
+
+/****************************************************************************
+ * WebRtcIsacfix_InitBandwidthEstimator(...)
+ *
+ * This function initializes the struct for the bandwidth estimator
+ *
+ * Input/Output:
+ * - bweStr : Struct containing bandwidth information.
+ *
+ * Return value : 0
+ */
+int32_t WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr *bweStr)
+{
+ bweStr->prevFrameSizeMs = INIT_FRAME_LEN;
+ bweStr->prevRtpNumber = 0;
+ bweStr->prevSendTime = 0;
+ bweStr->prevArrivalTime = 0;
+ bweStr->prevRtpRate = 1;
+ bweStr->lastUpdate = 0;
+ bweStr->lastReduction = 0;
+ bweStr->countUpdates = -9;
+
+ /* INIT_BN_EST = 20000
+ * INIT_BN_EST_Q7 = 2560000
+ * INIT_HDR_RATE = 4666
+ * INIT_REC_BN_EST_Q5 = 789312
+ *
+ * recBwInv = 1/(INIT_BN_EST + INIT_HDR_RATE) in Q30
+ * recBwAvg = INIT_BN_EST + INIT_HDR_RATE in Q5
+ */
+ bweStr->recBwInv = 43531;
+ bweStr->recBw = INIT_BN_EST;
+ bweStr->recBwAvgQ = INIT_BN_EST_Q7;
+ bweStr->recBwAvg = INIT_REC_BN_EST_Q5;
+ bweStr->recJitter = (int32_t) 327680; /* 10 in Q15 */
+ bweStr->recJitterShortTerm = 0;
+ bweStr->recJitterShortTermAbs = (int32_t) 40960; /* 5 in Q13 */
+ bweStr->recMaxDelay = (int32_t) 10;
+ bweStr->recMaxDelayAvgQ = (int32_t) 5120; /* 10 in Q9 */
+ bweStr->recHeaderRate = INIT_HDR_RATE;
+ bweStr->countRecPkts = 0;
+ bweStr->sendBwAvg = INIT_BN_EST_Q7;
+ bweStr->sendMaxDelayAvg = (int32_t) 5120; /* 10 in Q9 */
+
+ bweStr->countHighSpeedRec = 0;
+ bweStr->highSpeedRec = 0;
+ bweStr->countHighSpeedSent = 0;
+ bweStr->highSpeedSend = 0;
+ bweStr->inWaitPeriod = 0;
+
+ /* Find the inverse of the max bw and min bw in Q30
+ * (1 / (MAX_ISAC_BW + INIT_HDR_RATE) in Q30
+ * (1 / (MIN_ISAC_BW + INIT_HDR_RATE) in Q30
+ */
+ bweStr->maxBwInv = kInvBandwidth[3];
+ bweStr->minBwInv = kInvBandwidth[2];
+
+ bweStr->external_bw_info.in_use = 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBwImpl(...)
+ *
+ * This function updates bottle neck rate received from other side in payload
+ * and calculates a new bottle neck to send to the other side.
+ *
+ * Input/Output:
+ * - bweStr : struct containing bandwidth information.
+ * - rtpNumber : value from RTP packet, from NetEq
+ * - frameSize : length of signal frame in ms, from iSAC decoder
+ * - sendTime : value in RTP header giving send time in samples
+ * - arrivalTime : value given by timeGetTime() time of arrival in
+ * samples of packet from NetEq
+ * - pksize : size of packet in bytes, from NetEq
+ * - Index : integer (range 0...23) indicating bottle neck &
+ * jitter as estimated by other side
+ *
+ * Return value : 0 if everything went fine,
+ * -1 otherwise
+ */
+int32_t WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr *bweStr,
+ const uint16_t rtpNumber,
+ const int16_t frameSize,
+ const uint32_t sendTime,
+ const uint32_t arrivalTime,
+ const size_t pksize,
+ const uint16_t Index)
+{
+ uint16_t weight = 0;
+ uint32_t currBwInv = 0;
+ uint16_t recRtpRate;
+ uint32_t arrTimeProj;
+ int32_t arrTimeDiff;
+ int32_t arrTimeNoise;
+ int32_t arrTimeNoiseAbs;
+ int32_t sendTimeDiff;
+
+ int32_t delayCorrFactor = DELAY_CORRECTION_MED;
+ int32_t lateDiff = 0;
+ int16_t immediateSet = 0;
+ int32_t frameSizeSampl;
+
+ int32_t temp;
+ int32_t msec;
+ uint32_t exponent;
+ uint32_t reductionFactor;
+ uint32_t numBytesInv;
+ int32_t sign;
+
+ uint32_t byteSecondsPerBit;
+ uint32_t tempLower;
+ uint32_t tempUpper;
+ int32_t recBwAvgInv;
+ int32_t numPktsExpected;
+
+ int16_t errCode;
+
+ RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+
+ /* The function also checks if Index has a valid value */
+ errCode = WebRtcIsacfix_UpdateUplinkBwRec(bweStr, Index);
+ if (errCode <0) {
+ return(errCode);
+ }
+
+
+ /* UPDATE ESTIMATES ON THIS SIDE */
+
+ /* Bits per second per byte * 1/30 or 1/60 */
+ if (frameSize == 60) {
+ /* If frameSize changed since last call, from 30 to 60, recalculate some values */
+ if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
+ bweStr->countUpdates = 10;
+ bweStr->recHeaderRate = kRecHeaderRate[1];
+
+ bweStr->maxBwInv = kInvBandwidth[3];
+ bweStr->minBwInv = kInvBandwidth[2];
+ bweStr->recBwInv = 1073741824 / (bweStr->recBw + bweStr->recHeaderRate);
+ }
+
+ /* kBitsByteSec is in Q15 */
+ recRtpRate = (int16_t)((kBitsByteSec * pksize) >> 15) +
+ bweStr->recHeaderRate;
+
+ } else {
+ /* If frameSize changed since last call, from 60 to 30, recalculate some values */
+ if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
+ bweStr->countUpdates = 10;
+ bweStr->recHeaderRate = kRecHeaderRate[0];
+
+ bweStr->maxBwInv = kInvBandwidth[1];
+ bweStr->minBwInv = kInvBandwidth[0];
+ bweStr->recBwInv = 1073741824 / (bweStr->recBw + bweStr->recHeaderRate);
+ }
+
+ /* kBitsByteSec is in Q14 */
+ recRtpRate = (uint16_t)((kBitsByteSec * pksize) >> 14) +
+ bweStr->recHeaderRate;
+ }
+
+
+ /* Check for timer wrap-around */
+ if (arrivalTime < bweStr->prevArrivalTime) {
+ bweStr->prevArrivalTime = arrivalTime;
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->lastReduction = arrivalTime + FS3;
+
+ bweStr->countRecPkts = 0;
+
+ /* store frame size */
+ bweStr->prevFrameSizeMs = frameSize;
+
+ /* store far-side transmission rate */
+ bweStr->prevRtpRate = recRtpRate;
+
+ /* store far-side RTP time stamp */
+ bweStr->prevRtpNumber = rtpNumber;
+
+ return 0;
+ }
+
+ bweStr->countRecPkts++;
+
+ /* Calculate framesize in msec */
+ frameSizeSampl = SAMPLES_PER_MSEC * frameSize;
+
+ /* Check that it's not one of the first 9 packets */
+ if ( bweStr->countUpdates > 0 ) {
+
+ /* Stay in Wait Period for 1.5 seconds (no updates in wait period) */
+ if(bweStr->inWaitPeriod) {
+ if ((arrivalTime - bweStr->startWaitPeriod)> FS_1_HALF) {
+ bweStr->inWaitPeriod = 0;
+ }
+ }
+
+ /* If not been updated for a long time, reduce the BN estimate */
+
+ /* Check send time difference between this packet and previous received */
+ sendTimeDiff = sendTime - bweStr->prevSendTime;
+ if (sendTimeDiff <= frameSizeSampl * 2) {
+
+ /* Only update if 3 seconds has past since last update */
+ if ((arrivalTime - bweStr->lastUpdate) > FS3) {
+
+ /* Calculate expected number of received packets since last update */
+ numPktsExpected = (arrivalTime - bweStr->lastUpdate) / frameSizeSampl;
+
+ /* If received number of packets is more than 90% of expected (922 = 0.9 in Q10): */
+ /* do the update, else not */
+ if ((int32_t)bweStr->countRecPkts << 10 > 922 * numPktsExpected) {
+ /* Q4 chosen to approx dividing by 16 */
+ msec = (arrivalTime - bweStr->lastReduction);
+
+ /* the number below represents 13 seconds, highly unlikely
+ but to insure no overflow when reduction factor is multiplied by recBw inverse */
+ if (msec > 208000) {
+ msec = 208000;
+ }
+
+ /* Q20 2^(negative number: - 76/1048576) = .99995
+ product is Q24 */
+ exponent = WEBRTC_SPL_UMUL(0x0000004C, msec);
+
+ /* do the approx with positive exponent so that value is actually rf^-1
+ and multiply by bw inverse */
+ reductionFactor = WEBRTC_SPL_RSHIFT_U32(0x01000000 | (exponent & 0x00FFFFFF),
+ WEBRTC_SPL_RSHIFT_U32(exponent, 24));
+
+ /* reductionFactor in Q13 */
+ reductionFactor = WEBRTC_SPL_RSHIFT_U32(reductionFactor, 11);
+
+ if ( reductionFactor != 0 ) {
+ bweStr->recBwInv = WEBRTC_SPL_MUL((int32_t)bweStr->recBwInv, (int32_t)reductionFactor);
+ bweStr->recBwInv = (int32_t)bweStr->recBwInv >> 13;
+
+ } else {
+ static const uint32_t kInitRate = INIT_BN_EST + INIT_HDR_RATE;
+ /* recBwInv = 1 / kInitRate in Q26 (Q30??)*/
+ bweStr->recBwInv = (1073741824 + kInitRate / 2) / kInitRate;
+ }
+
+ /* reset time-since-update counter */
+ bweStr->lastReduction = arrivalTime;
+ } else {
+ /* Delay last reduction with 3 seconds */
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->countRecPkts = 0;
+ }
+ }
+ } else {
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->countRecPkts = 0;
+ }
+
+
+ /* update only if previous packet was not lost */
+ if ( rtpNumber == bweStr->prevRtpNumber + 1 ) {
+ arrTimeDiff = arrivalTime - bweStr->prevArrivalTime;
+
+ if (!(bweStr->highSpeedSend && bweStr->highSpeedRec)) {
+ if (arrTimeDiff > frameSizeSampl) {
+ if (sendTimeDiff > 0) {
+ lateDiff = arrTimeDiff - sendTimeDiff - frameSizeSampl * 2;
+ } else {
+ lateDiff = arrTimeDiff - frameSizeSampl;
+ }
+
+ /* 8000 is 1/2 second (in samples at FS) */
+ if (lateDiff > 8000) {
+ delayCorrFactor = (int32_t) DELAY_CORRECTION_MAX;
+ bweStr->inWaitPeriod = 1;
+ bweStr->startWaitPeriod = arrivalTime;
+ immediateSet = 1;
+ } else if (lateDiff > 5120) {
+ delayCorrFactor = (int32_t) DELAY_CORRECTION_MED;
+ immediateSet = 1;
+ bweStr->inWaitPeriod = 1;
+ bweStr->startWaitPeriod = arrivalTime;
+ }
+ }
+ }
+
+ if ((bweStr->prevRtpRate > (int32_t)bweStr->recBwAvg >> 5) &&
+ (recRtpRate > (int32_t)bweStr->recBwAvg >> 5) &&
+ !bweStr->inWaitPeriod) {
+
+ /* test if still in initiation period and increment counter */
+ if (bweStr->countUpdates++ > 99) {
+ /* constant weight after initiation part, 0.01 in Q13 */
+ weight = (uint16_t) 82;
+ } else {
+ /* weight decreases with number of updates, 1/countUpdates in Q13 */
+ weight = (uint16_t) WebRtcSpl_DivW32W16(
+ 8192 + (bweStr->countUpdates >> 1),
+ (int16_t)bweStr->countUpdates);
+ }
+
+ /* Bottle Neck Estimation */
+
+ /* limit outliers, if more than 25 ms too much */
+ if (arrTimeDiff > frameSizeSampl + kSamplesIn25msec) {
+ arrTimeDiff = frameSizeSampl + kSamplesIn25msec;
+ }
+
+ /* don't allow it to be less than frame rate - 10 ms */
+ if (arrTimeDiff < frameSizeSampl - FRAMESAMPLES_10ms) {
+ arrTimeDiff = frameSizeSampl - FRAMESAMPLES_10ms;
+ }
+
+ /* compute inverse receiving rate for last packet, in Q19 */
+ numBytesInv = (uint16_t) WebRtcSpl_DivW32W16(
+ (int32_t)(524288 + ((pksize + HEADER_SIZE) >> 1)),
+ (int16_t)(pksize + HEADER_SIZE));
+
+ /* 8389 is ~ 1/128000 in Q30 */
+ byteSecondsPerBit = (uint32_t)(arrTimeDiff * 8389);
+
+ /* get upper N bits */
+ tempUpper = WEBRTC_SPL_RSHIFT_U32(byteSecondsPerBit, 15);
+
+ /* get lower 15 bits */
+ tempLower = byteSecondsPerBit & 0x00007FFF;
+
+ tempUpper = WEBRTC_SPL_MUL(tempUpper, numBytesInv);
+ tempLower = WEBRTC_SPL_MUL(tempLower, numBytesInv);
+ tempLower = WEBRTC_SPL_RSHIFT_U32(tempLower, 15);
+
+ currBwInv = tempUpper + tempLower;
+ currBwInv = WEBRTC_SPL_RSHIFT_U32(currBwInv, 4);
+
+ /* Limit inv rate. Note that minBwInv > maxBwInv! */
+ if(currBwInv < bweStr->maxBwInv) {
+ currBwInv = bweStr->maxBwInv;
+ } else if(currBwInv > bweStr->minBwInv) {
+ currBwInv = bweStr->minBwInv;
+ }
+
+ /* update bottle neck rate estimate */
+ bweStr->recBwInv = WEBRTC_SPL_UMUL(weight, currBwInv) +
+ WEBRTC_SPL_UMUL((uint32_t) 8192 - weight, bweStr->recBwInv);
+
+ /* Shift back to Q30 from Q40 (actual used bits shouldn't be more than 27 based on minBwInv)
+ up to 30 bits used with Q13 weight */
+ bweStr->recBwInv = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwInv, 13);
+
+ /* reset time-since-update counter */
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->countRecPkts = 0;
+
+ /* to save resolution compute the inverse of recBwAvg in Q26 by left shifting numerator to 2^31
+ and NOT right shifting recBwAvg 5 bits to an integer
+ At max 13 bits are used
+ shift to Q5 */
+ recBwAvgInv = (0x80000000 + bweStr->recBwAvg / 2) / bweStr->recBwAvg;
+
+ /* Calculate Projected arrival time difference */
+
+ /* The numerator of the quotient can be 22 bits so right shift inv by 4 to avoid overflow
+ result in Q22 */
+ arrTimeProj = WEBRTC_SPL_MUL((int32_t)8000, recBwAvgInv);
+ /* shift to Q22 */
+ arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 4);
+ /* complete calulation */
+ arrTimeProj = WEBRTC_SPL_MUL(((int32_t)pksize + HEADER_SIZE), arrTimeProj);
+ /* shift to Q10 */
+ arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 12);
+
+ /* difference between projected and actual arrival time differences */
+ /* Q9 (only shift arrTimeDiff by 5 to simulate divide by 16 (need to revisit if change sampling rate) DH */
+ if ((arrTimeDiff << 6) > (int32_t)arrTimeProj) {
+ arrTimeNoise = (arrTimeDiff << 6) - arrTimeProj;
+ sign = 1;
+ } else {
+ arrTimeNoise = arrTimeProj - (arrTimeDiff << 6);
+ sign = -1;
+ }
+
+ /* Q9 */
+ arrTimeNoiseAbs = arrTimeNoise;
+
+ /* long term averaged absolute jitter, Q15 */
+ weight >>= 3;
+ bweStr->recJitter = weight * (arrTimeNoiseAbs << 5) +
+ (1024 - weight) * bweStr->recJitter;
+
+ /* remove the fractional portion */
+ bweStr->recJitter >>= 10;
+
+ /* Maximum jitter is 10 msec in Q15 */
+ if (bweStr->recJitter > (int32_t)327680) {
+ bweStr->recJitter = (int32_t)327680;
+ }
+
+ /* short term averaged absolute jitter */
+ /* Calculation in Q13 products in Q23 */
+ bweStr->recJitterShortTermAbs = 51 * (arrTimeNoiseAbs << 3) +
+ WEBRTC_SPL_MUL(973, bweStr->recJitterShortTermAbs);
+ bweStr->recJitterShortTermAbs >>= 10;
+
+ /* short term averaged jitter */
+ /* Calculation in Q13 products in Q23 */
+ bweStr->recJitterShortTerm = 205 * (arrTimeNoise << 3) * sign +
+ WEBRTC_SPL_MUL(3891, bweStr->recJitterShortTerm);
+
+ if (bweStr->recJitterShortTerm < 0) {
+ temp = -bweStr->recJitterShortTerm;
+ temp >>= 12;
+ bweStr->recJitterShortTerm = -temp;
+ } else {
+ bweStr->recJitterShortTerm >>= 12;
+ }
+ }
+ }
+ } else {
+ /* reset time-since-update counter when receiving the first 9 packets */
+ bweStr->lastUpdate = arrivalTime;
+ bweStr->lastReduction = arrivalTime + FS3;
+ bweStr->countRecPkts = 0;
+ bweStr->countUpdates++;
+ }
+
+ /* Limit to minimum or maximum bottle neck rate (in Q30) */
+ if (bweStr->recBwInv > bweStr->minBwInv) {
+ bweStr->recBwInv = bweStr->minBwInv;
+ } else if (bweStr->recBwInv < bweStr->maxBwInv) {
+ bweStr->recBwInv = bweStr->maxBwInv;
+ }
+
+
+ /* store frame length */
+ bweStr->prevFrameSizeMs = frameSize;
+
+ /* store far-side transmission rate */
+ bweStr->prevRtpRate = recRtpRate;
+
+ /* store far-side RTP time stamp */
+ bweStr->prevRtpNumber = rtpNumber;
+
+ /* Replace bweStr->recMaxDelay by the new value (atomic operation) */
+ if (bweStr->prevArrivalTime != 0xffffffff) {
+ bweStr->recMaxDelay = WEBRTC_SPL_MUL(3, bweStr->recJitter);
+ }
+
+ /* store arrival time stamp */
+ bweStr->prevArrivalTime = arrivalTime;
+ bweStr->prevSendTime = sendTime;
+
+ /* Replace bweStr->recBw by the new value */
+ bweStr->recBw = 1073741824 / bweStr->recBwInv - bweStr->recHeaderRate;
+
+ if (immediateSet) {
+ /* delay correction factor is in Q10 */
+ bweStr->recBw = WEBRTC_SPL_UMUL(delayCorrFactor, bweStr->recBw);
+ bweStr->recBw = WEBRTC_SPL_RSHIFT_U32(bweStr->recBw, 10);
+
+ if (bweStr->recBw < (int32_t) MIN_ISAC_BW) {
+ bweStr->recBw = (int32_t) MIN_ISAC_BW;
+ }
+
+ bweStr->recBwAvg = (bweStr->recBw + bweStr->recHeaderRate) << 5;
+
+ bweStr->recBwAvgQ = bweStr->recBw << 7;
+
+ bweStr->recJitterShortTerm = 0;
+
+ bweStr->recBwInv = 1073741824 / (bweStr->recBw + bweStr->recHeaderRate);
+
+ immediateSet = 0;
+ }
+
+
+ return 0;
+}
+
+/* This function updates the send bottle neck rate */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+int16_t WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr *bweStr,
+ const int16_t Index)
+{
+ uint16_t RateInd;
+
+ RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+ if ( (Index < 0) || (Index > 23) ) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+
+ if ( Index > 11 ) {
+ RateInd = Index - 12;
+ /* compute the jitter estimate as decoded on the other side in Q9 */
+ /* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MAX_ISAC_MD */
+ bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
+ 51 * (MAX_ISAC_MD << 9);
+ bweStr->sendMaxDelayAvg >>= 9;
+
+ } else {
+ RateInd = Index;
+ /* compute the jitter estimate as decoded on the other side in Q9 */
+ /* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MIN_ISAC_MD */
+ bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
+ 51 * (MIN_ISAC_MD << 9);
+ bweStr->sendMaxDelayAvg >>= 9;
+
+ }
+
+
+ /* compute the BN estimate as decoded on the other side */
+ /* sendBwAvg = 0.9 * sendBwAvg + 0.1 * kQRateTable[RateInd]; */
+ bweStr->sendBwAvg = 461 * bweStr->sendBwAvg +
+ 51 * ((uint32_t)kQRateTable[RateInd] << 7);
+ bweStr->sendBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 9);
+
+
+ if (WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 7) > 28000 && !bweStr->highSpeedSend) {
+ bweStr->countHighSpeedSent++;
+
+ /* approx 2 seconds with 30ms frames */
+ if (bweStr->countHighSpeedSent >= 66) {
+ bweStr->highSpeedSend = 1;
+ }
+ } else if (!bweStr->highSpeedSend) {
+ bweStr->countHighSpeedSent = 0;
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
+ *
+ * This function calculates and returns the bandwidth/jitter estimation code
+ * (integer 0...23) to put in the sending iSAC payload.
+ *
+ * Input:
+ * - bweStr : BWE struct
+ *
+ * Return:
+ * bandwith and jitter index (0..23)
+ */
+uint16_t WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr *bweStr)
+{
+ int32_t rate;
+ int32_t maxDelay;
+ uint16_t rateInd;
+ uint16_t maxDelayBit;
+ int32_t tempTerm1;
+ int32_t tempTerm2;
+ int32_t tempTermX;
+ int32_t tempTermY;
+ int32_t tempMin;
+ int32_t tempMax;
+
+ if (bweStr->external_bw_info.in_use)
+ return bweStr->external_bw_info.bottleneck_idx;
+
+ /* Get Rate Index */
+
+ /* Get unquantized rate. Always returns 10000 <= rate <= 32000 */
+ rate = WebRtcIsacfix_GetDownlinkBandwidth(bweStr);
+
+ /* Compute the averaged BN estimate on this side */
+
+ /* recBwAvg = 0.9 * recBwAvg + 0.1 * (rate + bweStr->recHeaderRate), 0.9 and 0.1 in Q9 */
+ bweStr->recBwAvg = 922 * bweStr->recBwAvg +
+ 102 * (((uint32_t)rate + bweStr->recHeaderRate) << 5);
+ bweStr->recBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwAvg, 10);
+
+ /* Find quantization index that gives the closest rate after averaging.
+ * Note that we don't need to check the last value, rate <= kQRateTable[11],
+ * because we will use rateInd = 11 even if rate > kQRateTable[11]. */
+ for (rateInd = 1; rateInd < 11; rateInd++) {
+ if (rate <= kQRateTable[rateInd]){
+ break;
+ }
+ }
+
+ /* find closest quantization index, and update quantized average by taking: */
+ /* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
+
+ /* 0.9 times recBwAvgQ in Q16 */
+ /* 461/512 - 25/65536 =0.900009 */
+ tempTerm1 = WEBRTC_SPL_MUL(bweStr->recBwAvgQ, 25);
+ tempTerm1 >>= 7;
+ tempTermX = WEBRTC_SPL_UMUL(461, bweStr->recBwAvgQ) - tempTerm1;
+
+ /* rate in Q16 */
+ tempTermY = rate << 16;
+
+ /* 0.1 * kQRateTable[rateInd] = KQRate01[rateInd] */
+ tempTerm1 = tempTermX + KQRate01[rateInd] - tempTermY;
+ tempTerm2 = tempTermY - tempTermX - KQRate01[rateInd-1];
+
+ /* Compare (0.9 * recBwAvgQ + 0.1 * kQRateTable[rateInd] - rate) >
+ (rate - 0.9 * recBwAvgQ - 0.1 * kQRateTable[rateInd-1]) */
+ if (tempTerm1 > tempTerm2) {
+ rateInd--;
+ }
+
+ /* Update quantized average by taking: */
+ /* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
+
+ /* Add 0.1 times kQRateTable[rateInd], in Q16 */
+ tempTermX += KQRate01[rateInd];
+
+ /* Shift back to Q7 */
+ bweStr->recBwAvgQ = tempTermX >> 9;
+
+ /* Count consecutive received bandwidth above 28000 kbps (28000 in Q7 = 3584000) */
+ /* If 66 high estimates in a row, set highSpeedRec to one */
+ /* 66 corresponds to ~2 seconds in 30 msec mode */
+ if ((bweStr->recBwAvgQ > 3584000) && !bweStr->highSpeedRec) {
+ bweStr->countHighSpeedRec++;
+ if (bweStr->countHighSpeedRec >= 66) {
+ bweStr->highSpeedRec = 1;
+ }
+ } else if (!bweStr->highSpeedRec) {
+ bweStr->countHighSpeedRec = 0;
+ }
+
+ /* Get Max Delay Bit */
+
+ /* get unquantized max delay */
+ maxDelay = WebRtcIsacfix_GetDownlinkMaxDelay(bweStr);
+
+ /* Update quantized max delay average */
+ tempMax = 652800; /* MAX_ISAC_MD * 0.1 in Q18 */
+ tempMin = 130560; /* MIN_ISAC_MD * 0.1 in Q18 */
+ tempTermX = WEBRTC_SPL_MUL((int32_t)bweStr->recMaxDelayAvgQ, (int32_t)461);
+ tempTermY = maxDelay << 18;
+
+ tempTerm1 = tempTermX + tempMax - tempTermY;
+ tempTerm2 = tempTermY - tempTermX - tempMin;
+
+ if ( tempTerm1 > tempTerm2) {
+ maxDelayBit = 0;
+ tempTerm1 = tempTermX + tempMin;
+
+ /* update quantized average, shift back to Q9 */
+ bweStr->recMaxDelayAvgQ = tempTerm1 >> 9;
+ } else {
+ maxDelayBit = 12;
+ tempTerm1 = tempTermX + tempMax;
+
+ /* update quantized average, shift back to Q9 */
+ bweStr->recMaxDelayAvgQ = tempTerm1 >> 9;
+ }
+
+ /* Return bandwitdh and jitter index (0..23) */
+ return (uint16_t)(rateInd + maxDelayBit);
+}
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+uint16_t WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr *bweStr)
+{
+ uint32_t recBw;
+ int32_t jitter_sign; /* Q8 */
+ int32_t bw_adjust; /* Q16 */
+ int32_t rec_jitter_short_term_abs_inv; /* Q18 */
+ int32_t temp;
+
+ RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+ /* Q18 rec jitter short term abs is in Q13, multiply it by 2^13 to save precision
+ 2^18 then needs to be shifted 13 bits to 2^31 */
+ rec_jitter_short_term_abs_inv = 0x80000000u / bweStr->recJitterShortTermAbs;
+
+ /* Q27 = 9 + 18 */
+ jitter_sign = (bweStr->recJitterShortTerm >> 4) *
+ rec_jitter_short_term_abs_inv;
+
+ if (jitter_sign < 0) {
+ temp = -jitter_sign;
+ temp >>= 19;
+ jitter_sign = -temp;
+ } else {
+ jitter_sign >>= 19;
+ }
+
+ /* adjust bw proportionally to negative average jitter sign */
+ //bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+ //Q8 -> Q16 .15 +.15 * jitter^2 first term is .15 in Q16 latter term is Q8*Q8*Q8
+ //38 in Q8 ~.15 9830 in Q16 ~.15
+ temp = 9830 + ((38 * jitter_sign * jitter_sign) >> 8);
+
+ if (jitter_sign < 0) {
+ temp = WEBRTC_SPL_MUL(jitter_sign, temp);
+ temp = -temp;
+ temp >>= 8;
+ bw_adjust = (uint32_t)65536 + temp; /* (1 << 16) + temp; */
+ } else {
+ /* (1 << 16) - ((jitter_sign * temp) >> 8); */
+ bw_adjust = 65536 - ((jitter_sign * temp) >> 8);
+ }
+
+ //make sure following multiplication won't overflow
+ //bw adjust now Q14
+ bw_adjust >>= 2; // See if good resolution is maintained.
+
+ /* adjust Rate if jitter sign is mostly constant */
+ recBw = WEBRTC_SPL_UMUL(bweStr->recBw, bw_adjust);
+
+ recBw >>= 14;
+
+ /* limit range of bottle neck rate */
+ if (recBw < MIN_ISAC_BW) {
+ recBw = MIN_ISAC_BW;
+ } else if (recBw > MAX_ISAC_BW) {
+ recBw = MAX_ISAC_BW;
+ }
+
+ return (uint16_t) recBw;
+}
+
+/* Returns the mmax delay (in ms) */
+int16_t WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr *bweStr)
+{
+ int16_t recMaxDelay = (int16_t)(bweStr->recMaxDelay >> 15);
+
+ RTC_DCHECK(!bweStr->external_bw_info.in_use);
+
+ /* limit range of jitter estimate */
+ if (recMaxDelay < MIN_ISAC_MD) {
+ recMaxDelay = MIN_ISAC_MD;
+ } else if (recMaxDelay > MAX_ISAC_MD) {
+ recMaxDelay = MAX_ISAC_MD;
+ }
+
+ return recMaxDelay;
+}
+
+/* Clamp val to the closed interval [min,max]. */
+static int16_t clamp(int16_t val, int16_t min, int16_t max) {
+ RTC_DCHECK_LE(min, max);
+ return val < min ? min : (val > max ? max : val);
+}
+
+int16_t WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr* bweStr) {
+ return bweStr->external_bw_info.in_use
+ ? bweStr->external_bw_info.send_bw_avg
+ : clamp(bweStr->sendBwAvg >> 7, MIN_ISAC_BW, MAX_ISAC_BW);
+}
+
+int16_t WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr* bweStr) {
+ return bweStr->external_bw_info.in_use
+ ? bweStr->external_bw_info.send_max_delay_avg
+ : clamp(bweStr->sendMaxDelayAvg >> 9, MIN_ISAC_MD, MAX_ISAC_MD);
+}
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ * returns minimum payload size (bytes)
+ */
+uint16_t WebRtcIsacfix_GetMinBytes(RateModel *State,
+ int16_t StreamSize, /* bytes in bitstream */
+ const int16_t FrameSamples, /* samples per frame */
+ const int16_t BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const int16_t DelayBuildUp) /* max delay from bottle neck buffering (ms) */
+{
+ int32_t MinRate = 0;
+ uint16_t MinBytes;
+ int16_t TransmissionTime;
+ int32_t inv_Q12;
+ int32_t den;
+
+
+ /* first 10 packets @ low rate, then INIT_BURST_LEN packets @ fixed rate of INIT_RATE bps */
+ if (State->InitCounter > 0) {
+ if (State->InitCounter-- <= INIT_BURST_LEN) {
+ MinRate = INIT_RATE;
+ } else {
+ MinRate = 0;
+ }
+ } else {
+ /* handle burst */
+ if (State->BurstCounter) {
+ if (State->StillBuffered <
+ (((512 - 512 / BURST_LEN) * DelayBuildUp) >> 9)) {
+ /* max bps derived from BottleNeck and DelayBuildUp values */
+ inv_Q12 = 4096 / (BURST_LEN * FrameSamples);
+ MinRate = (512 + SAMPLES_PER_MSEC * ((DelayBuildUp * inv_Q12) >> 3)) *
+ BottleNeck;
+ } else {
+ /* max bps derived from StillBuffered and DelayBuildUp values */
+ inv_Q12 = 4096 / FrameSamples;
+ if (DelayBuildUp > State->StillBuffered) {
+ MinRate = (512 + SAMPLES_PER_MSEC * (((DelayBuildUp -
+ State->StillBuffered) * inv_Q12) >> 3)) * BottleNeck;
+ } else if ((den = WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, (State->StillBuffered - DelayBuildUp))) >= FrameSamples) {
+ /* MinRate will be negative here */
+ MinRate = 0;
+ } else {
+ MinRate = (512 - ((den * inv_Q12) >> 3)) * BottleNeck;
+ }
+ //if (MinRate < 1.04 * BottleNeck)
+ // MinRate = 1.04 * BottleNeck;
+ //Q9
+ if (MinRate < WEBRTC_SPL_MUL(532, BottleNeck)) {
+ MinRate += WEBRTC_SPL_MUL(22, BottleNeck);
+ }
+ }
+
+ State->BurstCounter--;
+ }
+ }
+
+
+ /* convert rate from bits/second to bytes/packet */
+ //round and shift before conversion
+ MinRate += 256;
+ MinRate >>= 9;
+ MinBytes = MinRate * FrameSamples / FS8;
+
+ /* StreamSize will be adjusted if less than MinBytes */
+ if (StreamSize < MinBytes) {
+ StreamSize = MinBytes;
+ }
+
+ /* keep track of when bottle neck was last exceeded by at least 1% */
+ //517/512 ~ 1.01
+ if ((StreamSize * (int32_t)FS8) / FrameSamples > (517 * BottleNeck) >> 9) {
+ if (State->PrevExceed) {
+ /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+ State->ExceedAgo -= BURST_INTERVAL / (BURST_LEN - 1);
+ if (State->ExceedAgo < 0) {
+ State->ExceedAgo = 0;
+ }
+ } else {
+ State->ExceedAgo += FrameSamples / SAMPLES_PER_MSEC; /* ms */
+ State->PrevExceed = 1;
+ }
+ } else {
+ State->PrevExceed = 0;
+ State->ExceedAgo += FrameSamples / SAMPLES_PER_MSEC; /* ms */
+ }
+
+ /* set burst flag if bottle neck not exceeded for long time */
+ if ((State->ExceedAgo > BURST_INTERVAL) && (State->BurstCounter == 0)) {
+ if (State->PrevExceed) {
+ State->BurstCounter = BURST_LEN - 1;
+ } else {
+ State->BurstCounter = BURST_LEN;
+ }
+ }
+
+
+ /* Update buffer delay */
+ TransmissionTime = (StreamSize * 8000) / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= FrameSamples / SAMPLES_PER_MSEC; /* ms */
+ if (State->StillBuffered < 0) {
+ State->StillBuffered = 0;
+ }
+
+ if (State->StillBuffered > 2000) {
+ State->StillBuffered = 2000;
+ }
+
+ return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsacfix_UpdateRateModel(RateModel *State,
+ int16_t StreamSize, /* bytes in bitstream */
+ const int16_t FrameSamples, /* samples per frame */
+ const int16_t BottleNeck) /* bottle neck rate; excl headers (bps) */
+{
+ const int16_t TransmissionTime = (StreamSize * 8000) / BottleNeck; /* ms */
+
+ /* avoid the initial "high-rate" burst */
+ State->InitCounter = 0;
+
+ /* Update buffer delay */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= FrameSamples >> 4; /* ms */
+ if (State->StillBuffered < 0) {
+ State->StillBuffered = 0;
+ }
+
+}
+
+
+void WebRtcIsacfix_InitRateModel(RateModel *State)
+{
+ State->PrevExceed = 0; /* boolean */
+ State->ExceedAgo = 0; /* ms */
+ State->BurstCounter = 0; /* packets */
+ State->InitCounter = INIT_BURST_LEN + 10; /* packets */
+ State->StillBuffered = 1; /* ms */
+}
+
+
+
+
+
+int16_t WebRtcIsacfix_GetNewFrameLength(int16_t bottle_neck, int16_t current_framesamples)
+{
+ int16_t new_framesamples;
+
+ new_framesamples = current_framesamples;
+
+ /* find new framelength */
+ switch(current_framesamples) {
+ case 480:
+ if (bottle_neck < Thld_30_60) {
+ new_framesamples = 960;
+ }
+ break;
+ case 960:
+ if (bottle_neck >= Thld_60_30) {
+ new_framesamples = 480;
+ }
+ break;
+ default:
+ new_framesamples = -1; /* Error */
+ }
+
+ return new_framesamples;
+}
+
+int16_t WebRtcIsacfix_GetSnr(int16_t bottle_neck, int16_t framesamples)
+{
+ int16_t s2nr = 0;
+
+ /* find new SNR value */
+ //consider BottleNeck to be in Q10 ( * 1 in Q10)
+ switch(framesamples) {
+ // TODO(bjornv): The comments below confuses me. I don't know if there is a
+ // difference between frame lengths (in which case the implementation is
+ // wrong), or if it is frame length independent in which case we should
+ // correct the comment and simplify the implementation.
+ case 480:
+ /*s2nr = -1*(a_30 << 10) + ((b_30 * bottle_neck) >> 10);*/
+ s2nr = -22500 + (int16_t)(500 * bottle_neck >> 10);
+ break;
+ case 960:
+ /*s2nr = -1*(a_60 << 10) + ((b_60 * bottle_neck) >> 10);*/
+ s2nr = -22500 + (int16_t)(500 * bottle_neck >> 10);
+ break;
+ default:
+ s2nr = -1; /* Error */
+ }
+
+ return s2nr; //return in Q10
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h
new file mode 100644
index 0000000000..f106746f14
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.h
+ *
+ * This header file contains the API for the Bandwidth Estimator
+ * designed for iSAC.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+/****************************************************************************
+ * WebRtcIsacfix_InitBandwidthEstimator(...)
+ *
+ * This function initializes the struct for the bandwidth estimator
+ *
+ * Input/Output:
+ * - bwest_str : Struct containing bandwidth information.
+ *
+ * Return value : 0
+ */
+
+int32_t WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr* bwest_str);
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBwImpl(...)
+ *
+ * This function updates bottle neck rate received from other side in payload
+ * and calculates a new bottle neck to send to the other side.
+ *
+ * Input/Output:
+ * - bweStr : struct containing bandwidth information.
+ * - rtpNumber : value from RTP packet, from NetEq
+ * - frameSize : length of signal frame in ms, from iSAC decoder
+ * - sendTime : value in RTP header giving send time in samples
+ * - arrivalTime : value given by timeGetTime() time of arrival in
+ * samples of packet from NetEq
+ * - pksize : size of packet in bytes, from NetEq
+ * - Index : integer (range 0...23) indicating bottle neck &
+ * jitter as estimated by other side
+ *
+ * Return value : 0 if everything went fine,
+ * -1 otherwise
+ */
+
+int32_t WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr* bwest_str,
+ uint16_t rtp_number,
+ int16_t frameSize,
+ uint32_t send_ts,
+ uint32_t arr_ts,
+ size_t pksize,
+ uint16_t Index);
+
+/* Update receiving estimates. Used when we only receive BWE index, no iSAC data
+ * packet. */
+int16_t WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr* bwest_str,
+ int16_t Index);
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
+ *
+ * This function calculates and returns the bandwidth/jitter estimation code
+ * (integer 0...23) to put in the sending iSAC payload.
+ *
+ * Input:
+ * - bweStr : BWE struct
+ *
+ * Return:
+ * bandwith and jitter index (0..23)
+ */
+uint16_t WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr* bwest_str);
+
+/* Returns the bandwidth estimation (in bps) */
+uint16_t WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the bandwidth that iSAC should send with in bps */
+int16_t WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay (in ms) */
+int16_t WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay value from the other side in ms */
+int16_t WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+uint16_t WebRtcIsacfix_GetMinBytes(
+ RateModel* State,
+ int16_t StreamSize, /* bytes in bitstream */
+ int16_t FrameLen, /* ms per frame */
+ int16_t BottleNeck, /* bottle neck rate; excl headers (bps) */
+ int16_t DelayBuildUp); /* max delay from bottle neck buffering (ms) */
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsacfix_UpdateRateModel(
+ RateModel* State,
+ int16_t StreamSize, /* bytes in bitstream */
+ int16_t FrameSamples, /* samples per frame */
+ int16_t BottleNeck); /* bottle neck rate; excl headers (bps) */
+
+void WebRtcIsacfix_InitRateModel(RateModel* State);
+
+/* Returns the new framelength value (input argument: bottle_neck) */
+int16_t WebRtcIsacfix_GetNewFrameLength(int16_t bottle_neck,
+ int16_t current_framelength);
+
+/* Returns the new SNR value (input argument: bottle_neck) */
+// returns snr in Q10
+int16_t WebRtcIsacfix_GetSnr(int16_t bottle_neck, int16_t framesamples);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_BANDWIDTH_ESTIMATOR_H_ \
+ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/codec.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/codec.h
new file mode 100644
index 0000000000..01d6fb907e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/codec.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * codec.h
+ *
+ * This header file contains the calls to the internal encoder
+ * and decoder functions.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr* bwest_str,
+ Bitstr_dec* streamdata,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts);
+
+int WebRtcIsacfix_DecodeImpl(int16_t* signal_out16,
+ IsacFixDecoderInstance* ISACdec_obj,
+ size_t* current_framesamples);
+
+void WebRtcIsacfix_DecodePlcImpl(int16_t* decoded,
+ IsacFixDecoderInstance* ISACdec_obj,
+ size_t* current_framesample);
+
+int WebRtcIsacfix_EncodeImpl(int16_t* in,
+ IsacFixEncoderInstance* ISACenc_obj,
+ BwEstimatorstr* bw_estimatordata,
+ int16_t CodingMode);
+
+int WebRtcIsacfix_EncodeStoredData(IsacFixEncoderInstance* ISACenc_obj,
+ int BWnumber,
+ float scale);
+
+/* initialization functions */
+
+void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc* maskdata);
+void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec* maskdata);
+
+void WebRtcIsacfix_InitPreFilterbank(PreFiltBankstr* prefiltdata);
+
+void WebRtcIsacfix_InitPostFilterbank(PostFiltBankstr* postfiltdata);
+
+void WebRtcIsacfix_InitPitchFilter(PitchFiltstr* pitchfiltdata);
+
+void WebRtcIsacfix_InitPitchAnalysis(PitchAnalysisStruct* State);
+
+void WebRtcIsacfix_InitPlc(PLCstr* State);
+
+/* transform functions */
+
+void WebRtcIsacfix_InitTransform(void);
+
+typedef void (*Time2Spec)(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int16_t* outre,
+ int16_t* outim);
+typedef void (*Spec2Time)(int16_t* inreQ7,
+ int16_t* inimQ7,
+ int32_t* outre1Q16,
+ int32_t* outre2Q16);
+
+extern Time2Spec WebRtcIsacfix_Time2Spec;
+extern Spec2Time WebRtcIsacfix_Spec2Time;
+
+void WebRtcIsacfix_Time2SpecC(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int16_t* outre,
+ int16_t* outim);
+void WebRtcIsacfix_Spec2TimeC(int16_t* inreQ7,
+ int16_t* inimQ7,
+ int32_t* outre1Q16,
+ int32_t* outre2Q16);
+
+#if defined(WEBRTC_HAS_NEON)
+void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int16_t* outre,
+ int16_t* outim);
+void WebRtcIsacfix_Spec2TimeNeon(int16_t* inreQ7,
+ int16_t* inimQ7,
+ int32_t* outre1Q16,
+ int32_t* outre2Q16);
+#endif
+
+#if defined(MIPS32_LE)
+void WebRtcIsacfix_Time2SpecMIPS(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int16_t* outre,
+ int16_t* outim);
+void WebRtcIsacfix_Spec2TimeMIPS(int16_t* inreQ7,
+ int16_t* inimQ7,
+ int32_t* outre1Q16,
+ int32_t* outre2Q16);
+#endif
+
+/* filterbank functions */
+
+void WebRtcIsacfix_SplitAndFilter1(int16_t* in,
+ int16_t* LP16,
+ int16_t* HP16,
+ PreFiltBankstr* prefiltdata);
+
+void WebRtcIsacfix_FilterAndCombine1(int16_t* tempin_ch1,
+ int16_t* tempin_ch2,
+ int16_t* out16,
+ PostFiltBankstr* postfiltdata);
+
+/* normalized lattice filters */
+
+void WebRtcIsacfix_NormLatticeFilterMa(size_t orderCoef,
+ int32_t* stateGQ15,
+ int16_t* lat_inQ0,
+ int16_t* filt_coefQ15,
+ int32_t* gain_lo_hiQ17,
+ int16_t lo_hi,
+ int16_t* lat_outQ9);
+
+void WebRtcIsacfix_NormLatticeFilterAr(size_t orderCoef,
+ int16_t* stateGQ0,
+ int32_t* lat_inQ25,
+ int16_t* filt_coefQ15,
+ int32_t* gain_lo_hiQ17,
+ int16_t lo_hi,
+ int16_t* lat_outQ0);
+
+/* TODO(kma): Remove the following functions into individual header files. */
+
+/* Internal functions in both C and ARM Neon versions */
+
+int WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
+ const int16_t* __restrict x,
+ int16_t N,
+ int16_t order,
+ int16_t* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopC(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+
+#if defined(WEBRTC_HAS_NEON)
+int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
+ const int16_t* __restrict x,
+ int16_t N,
+ int16_t order,
+ int16_t* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+#endif
+
+#if defined(MIPS32_LE)
+int WebRtcIsacfix_AutocorrMIPS(int32_t* __restrict r,
+ const int16_t* __restrict x,
+ int16_t N,
+ int16_t order,
+ int16_t* __restrict scale);
+
+void WebRtcIsacfix_FilterMaLoopMIPS(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+#endif
+
+/* Function pointers associated with the above functions. */
+
+typedef int (*AutocorrFix)(int32_t* __restrict r,
+ const int16_t* __restrict x,
+ int16_t N,
+ int16_t order,
+ int16_t* __restrict scale);
+extern AutocorrFix WebRtcIsacfix_AutocorrFix;
+
+typedef void (*FilterMaLoopFix)(int16_t input0,
+ int16_t input1,
+ int32_t input2,
+ int32_t* ptr0,
+ int32_t* ptr1,
+ int32_t* ptr2);
+extern FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode.c
new file mode 100644
index 0000000000..144208818a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode.c
+ *
+ * This C file contains the internal decoding function.
+ *
+ */
+
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+
+
+
+int WebRtcIsacfix_DecodeImpl(int16_t* signal_out16,
+ IsacFixDecoderInstance* ISACdec_obj,
+ size_t* current_framesamples)
+{
+ int k;
+ int err;
+ int16_t BWno;
+ int len = 0;
+
+ int16_t model;
+
+
+ int16_t Vector_Word16_1[FRAMESAMPLES/2];
+ int16_t Vector_Word16_2[FRAMESAMPLES/2];
+
+ int32_t Vector_Word32_1[FRAMESAMPLES/2];
+ int32_t Vector_Word32_2[FRAMESAMPLES/2];
+
+ int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
+ int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
+ int32_t gain_lo_hiQ17[2*SUBFRAMES];
+
+ int16_t PitchLags_Q7[PITCH_SUBFRAMES];
+ int16_t PitchGains_Q12[PITCH_SUBFRAMES];
+ int16_t AvgPitchGain_Q12;
+
+ int16_t tmp_1, tmp_2;
+ int32_t tmp32a;
+ int16_t gainQ13;
+
+
+ size_t frame_nb; /* counter */
+ size_t frame_mode; /* 0 for 30ms, 1 for 60ms */
+ static const size_t kProcessedSamples = 480; /* 480 (for both 30, 60 ms) */
+
+ /* PLC */
+ int16_t overlapWin[ 240 ];
+
+ (ISACdec_obj->bitstr_obj).W_upper = 0xFFFFFFFF;
+ (ISACdec_obj->bitstr_obj).streamval = 0;
+ (ISACdec_obj->bitstr_obj).stream_index = 0;
+ (ISACdec_obj->bitstr_obj).full = 1;
+
+
+ /* decode framelength and BW estimation - not used, only for stream pointer*/
+ err = WebRtcIsacfix_DecodeFrameLen(&ISACdec_obj->bitstr_obj, current_framesamples);
+ if (err<0) // error check
+ return err;
+
+ frame_mode = *current_framesamples / MAX_FRAMESAMPLES; /* 0, or 1 */
+
+ err = WebRtcIsacfix_DecodeSendBandwidth(&ISACdec_obj->bitstr_obj, &BWno);
+ if (err<0) // error check
+ return err;
+
+ /* one loop if it's one frame (30ms), two loops if two frames bundled together
+ * (60ms) */
+ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+
+ /* decode & dequantize pitch parameters */
+ err = WebRtcIsacfix_DecodePitchGain(&(ISACdec_obj->bitstr_obj), PitchGains_Q12);
+ if (err<0) // error check
+ return err;
+
+ err = WebRtcIsacfix_DecodePitchLag(&ISACdec_obj->bitstr_obj, PitchGains_Q12, PitchLags_Q7);
+ if (err<0) // error check
+ return err;
+
+ AvgPitchGain_Q12 = (int16_t)(((int32_t)PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3])>>2);
+
+ /* decode & dequantize FiltCoef */
+ err = WebRtcIsacfix_DecodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
+ &ISACdec_obj->bitstr_obj, &model);
+
+ if (err<0) // error check
+ return err;
+
+ /* decode & dequantize spectrum */
+ len = WebRtcIsacfix_DecodeSpec(&ISACdec_obj->bitstr_obj, Vector_Word16_1, Vector_Word16_2, AvgPitchGain_Q12);
+ if (len < 0) // error check
+ return len;
+
+ // Why does this need Q16 in and out? /JS
+ WebRtcIsacfix_Spec2Time(Vector_Word16_1, Vector_Word16_2, Vector_Word32_1, Vector_Word32_2);
+
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ // Q16 -> Q9.
+ Vector_Word16_1[k] = (int16_t)((Vector_Word32_1[k] + 64) >> 7);
+ }
+
+ /* ---- If this is recovery frame ---- */
+ if( (ISACdec_obj->plcstr_obj).used == PLC_WAS_USED )
+ {
+ (ISACdec_obj->plcstr_obj).used = PLC_NOT_USED;
+ if( (ISACdec_obj->plcstr_obj).B < 1000 )
+ {
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 4000;
+ }
+
+ ISACdec_obj->plcstr_obj.decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */
+ ISACdec_obj->plcstr_obj.decayCoeffNoise = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */
+ ISACdec_obj->plcstr_obj.pitchCycles = 0;
+
+ PitchGains_Q12[0] = (int16_t)(PitchGains_Q12[0] * 700 >> 10);
+
+ /* ---- Add-overlap ---- */
+ WebRtcSpl_GetHanningWindow( overlapWin, RECOVERY_OVERLAP );
+ for( k = 0; k < RECOVERY_OVERLAP; k++ )
+ Vector_Word16_1[k] = WebRtcSpl_AddSatW16(
+ (int16_t)(ISACdec_obj->plcstr_obj.overlapLP[k] *
+ overlapWin[RECOVERY_OVERLAP - k - 1] >> 14),
+ (int16_t)(Vector_Word16_1[k] * overlapWin[k] >> 14));
+
+
+
+ }
+
+ /* --- Store side info --- */
+ if( frame_nb == frame_mode )
+ {
+ /* --- LPC info */
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).lofilt_coefQ15, &lofilt_coefQ15[(SUBFRAMES-1)*ORDERLO], ORDERLO );
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).hifilt_coefQ15, &hifilt_coefQ15[(SUBFRAMES-1)*ORDERHI], ORDERHI );
+ (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0] = gain_lo_hiQ17[(SUBFRAMES-1) * 2];
+ (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1] = gain_lo_hiQ17[(SUBFRAMES-1) * 2 + 1];
+
+ /* --- LTP info */
+ (ISACdec_obj->plcstr_obj).AvgPitchGain_Q12 = PitchGains_Q12[3];
+ (ISACdec_obj->plcstr_obj).lastPitchGain_Q12 = PitchGains_Q12[3];
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = PitchLags_Q7[3];
+
+ if( PitchLags_Q7[3] < 3000 )
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 += PitchLags_Q7[3];
+
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvIn, Vector_Word16_1, FRAMESAMPLES/2 );
+
+ }
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ /* inverse pitch filter */
+ WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2, &ISACdec_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 4);
+
+ if( frame_nb == frame_mode )
+ {
+ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvOut, &(Vector_Word16_2[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10)]), PITCH_MAX_LAG );
+ }
+
+
+ /* reduce gain to compensate for pitch enhancer */
+ /* gain = 1.0f - 0.45f * AvgPitchGain; */
+ tmp32a = AvgPitchGain_Q12 * 29; // Q18
+ gainQ13 = (int16_t)((262144 - tmp32a) >> 5); // Q18 -> Q13.
+
+ for (k = 0; k < FRAMESAMPLES/2; k++)
+ {
+ Vector_Word32_1[k] = (Vector_Word16_2[k] * gainQ13) * (1 << 3); // Q25
+ }
+
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERLO, (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
+ Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
+
+ /* --- Store Highpass Residual --- */
+ for (k = 0; k < FRAMESAMPLES/2; k++)
+ Vector_Word32_1[k] = Vector_Word32_2[k] * (1 << 9); // Q16 -> Q25
+
+ for( k = 0; k < PITCH_MAX_LAG + 10; k++ )
+ (ISACdec_obj->plcstr_obj).prevHP[k] = Vector_Word32_1[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10) + k];
+
+
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERHI, (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
+ Vector_Word32_1, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
+
+ /* recombine the 2 bands */
+
+ /* Form the polyphase signals, and compensate for DC offset */
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/
+ tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k])); /* Construct a new lower channel signal*/
+ Vector_Word16_1[k] = tmp_1;
+ Vector_Word16_2[k] = tmp_2;
+ }
+
+ WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
+ Vector_Word16_2,
+ signal_out16 + frame_nb * kProcessedSamples,
+ &ISACdec_obj->postfiltbankstr_obj);
+
+ }
+ return len;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c
new file mode 100644
index 0000000000..99676504cd
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_bwe.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_bwe.c
+ *
+ * This C file contains the internal decode bandwidth estimate function.
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+
+
+
+int WebRtcIsacfix_EstimateBandwidth(BwEstimatorstr *bwest_str,
+ Bitstr_dec *streamdata,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts)
+{
+ int16_t index;
+ size_t frame_samples;
+ int err;
+
+ /* decode framelength */
+ err = WebRtcIsacfix_DecodeFrameLen(streamdata, &frame_samples);
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* decode BW estimation */
+ err = WebRtcIsacfix_DecodeSendBandwidth(streamdata, &index);
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* Update BWE with received data */
+ err = WebRtcIsacfix_UpdateUplinkBwImpl(
+ bwest_str,
+ rtp_seq_number,
+ (int16_t)(frame_samples * 1000 / FS),
+ send_ts,
+ arr_ts,
+ packet_size, /* in bytes */
+ index);
+
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* Succesful */
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_plc.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_plc.c
new file mode 100644
index 0000000000..873cf951ba
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/decode_plc.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_plc.c
+ *
+ * Packet Loss Concealment.
+ *
+ */
+
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+
+#define NO_OF_PRIMES 8
+#define NOISE_FILTER_LEN 30
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+
+static int16_t plc_filterma_Fast(
+ int16_t *In, /* (i) Vector to be filtered. InOut[-orderCoef+1]
+ to InOut[-1] contains state */
+ int16_t *Out, /* (o) Filtered vector */
+ int16_t *B, /* (i) The filter coefficients (in Q0) */
+ int16_t Blen, /* (i) Number of B coefficients */
+ int16_t len, /* (i) Number of samples to be filtered */
+ int16_t reduceDecay,
+ int16_t decay,
+ int16_t rshift )
+{
+ int i, j;
+ int32_t o;
+ int32_t lim = (1 << (15 + rshift)) - 1;
+
+ for (i = 0; i < len; i++)
+ {
+ const int16_t *b_ptr = &B[0];
+ const int16_t *x_ptr = &In[i];
+
+ o = (int32_t)0;
+
+ for (j = 0;j < Blen; j++)
+ {
+ o = WebRtcSpl_AddSatW32(o, *b_ptr * *x_ptr);
+ b_ptr++;
+ x_ptr--;
+ }
+
+ /* to round off correctly */
+ o = WebRtcSpl_AddSatW32(o, 1 << (rshift - 1));
+
+ /* saturate according to the domain of the filter coefficients */
+ o = WEBRTC_SPL_SAT((int32_t)lim, o, (int32_t)-lim);
+
+ /* o should be in the range of int16_t */
+ o >>= rshift;
+
+ /* decay the output signal; this is specific to plc */
+ *Out++ = (int16_t)((int16_t)o * decay >> 15);
+
+ /* change the decay */
+ decay -= reduceDecay;
+ if( decay < 0 )
+ decay = 0;
+ }
+ return( decay );
+}
+
+
+
+
+
+
+
+
+static __inline int32_t log2_Q8_T( uint32_t x ) {
+
+ int32_t zeros;
+ int16_t frac;
+
+ zeros=WebRtcSpl_NormU32(x);
+ frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
+
+ /* log2(magn(i)) */
+ return ((31 - zeros) << 8) + frac;
+}
+
+static __inline int16_t exp2_Q10_T(int16_t x) { // Both in and out in Q10
+
+ int16_t tmp16_1, tmp16_2;
+
+ tmp16_2=(int16_t)(0x0400|(x&0x03FF));
+ tmp16_1 = -(x >> 10);
+ if(tmp16_1>0)
+ return tmp16_2 >> tmp16_1;
+ else
+ return tmp16_2 << -tmp16_1;
+
+}
+
+
+/*
+ This is a fixed-point version of the above code with limLow = 700 and limHigh = 5000,
+ hard-coded. The values 700 and 5000 were experimentally obtained.
+
+ The function implements membership values for two sets. The mebership functions are
+ of second orders corresponding to half-bell-shapped pulses.
+*/
+static void MemshipValQ15( int16_t in, int16_t *A, int16_t *B )
+{
+ int16_t x;
+
+ in -= 700; /* translate the lowLim to 0, limHigh = 5000 - 700, M = 2150 */
+
+ if( in <= 2150 )
+ {
+ if( in > 0 )
+ {
+ /* b = in^2 / (2 * M^2), a = 1 - b in Q0.
+ We have to compute in Q15 */
+
+ /* x = in / 2150 {in Q15} = x * 15.2409 {in Q15} =
+ x*15 + (x*983)/(2^12); note that 983/2^12 = 0.23999 */
+
+ /* we are sure that x is in the range of int16_t */
+ x = (int16_t)(in * 15 + (in * 983 >> 12));
+ /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
+ be in correct domain and one more for the division by 2 */
+ *B = (int16_t)((x * x + 0x00010000) >> 17);
+ *A = WEBRTC_SPL_WORD16_MAX - *B;
+ }
+ else
+ {
+ *B = 0;
+ *A = WEBRTC_SPL_WORD16_MAX;
+ }
+ }
+ else
+ {
+ if( in < 4300 )
+ {
+ /* This is a mirror case of the above */
+ in = 4300 - in;
+ x = (int16_t)(in * 15 + (in * 983 >> 12));
+ /* b = x^2 / 2 {in Q15} so a shift of 16 is required to
+ be in correct domain and one more for the division by 2 */
+ *A = (int16_t)((x * x + 0x00010000) >> 17);
+ *B = WEBRTC_SPL_WORD16_MAX - *A;
+
+ }
+ else
+ {
+ *A = 0;
+ *B = WEBRTC_SPL_WORD16_MAX;
+ }
+ }
+}
+
+
+
+
+static void LinearResampler(int16_t* in,
+ int16_t* out,
+ size_t lenIn,
+ size_t lenOut)
+{
+ size_t n = (lenIn - 1) * RESAMP_RES;
+ int16_t resOut, relativePos, diff; /* */
+ size_t i, j;
+ uint16_t udiff;
+
+ if( lenIn == lenOut )
+ {
+ WEBRTC_SPL_MEMCPY_W16( out, in, lenIn );
+ return;
+ }
+
+ resOut = WebRtcSpl_DivW32W16ResW16( (int32_t)n, (int16_t)(lenOut-1) );
+
+ out[0] = in[0];
+ for( i = 1, j = 0, relativePos = 0; i < lenOut; i++ )
+ {
+
+ relativePos += resOut;
+ while( relativePos > RESAMP_RES )
+ {
+ j++;
+ relativePos -= RESAMP_RES;
+ }
+
+
+ /* an overflow may happen and the differce in sample values may
+ * require more than 16 bits. We like to avoid 32 bit arithmatic
+ * as much as possible */
+
+ if( (in[ j ] > 0) && (in[j + 1] < 0) )
+ {
+ udiff = (uint16_t)(in[ j ] - in[j + 1]);
+ out[ i ] = in[ j ] - (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
+ }
+ else
+ {
+ if( (in[j] < 0) && (in[j+1] > 0) )
+ {
+ udiff = (uint16_t)( in[j + 1] - in[ j ] );
+ out[ i ] = in[ j ] + (uint16_t)( ((int32_t)( udiff * relativePos )) >> RESAMP_RES_BIT);
+ }
+ else
+ {
+ diff = in[ j + 1 ] - in[ j ];
+ out[i] = in[j] + (int16_t)(diff * relativePos >> RESAMP_RES_BIT);
+ }
+ }
+ }
+}
+
+
+
+
+
+void WebRtcIsacfix_DecodePlcImpl(int16_t *signal_out16,
+ IsacFixDecoderInstance *ISACdec_obj,
+ size_t *current_framesamples )
+{
+ int subframecnt;
+
+ int16_t* Vector_Word16_1;
+ int16_t Vector_Word16_Extended_1[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
+ int16_t* Vector_Word16_2;
+ int16_t Vector_Word16_Extended_2[FRAMESAMPLES_HALF + NOISE_FILTER_LEN];
+
+ int32_t Vector_Word32_1[FRAMESAMPLES_HALF];
+ int32_t Vector_Word32_2[FRAMESAMPLES_HALF];
+
+ int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs
+ int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs
+
+ int16_t pitchLags_Q7[PITCH_SUBFRAMES];
+ int16_t pitchGains_Q12[PITCH_SUBFRAMES];
+
+ int16_t tmp_1, tmp_2;
+ int32_t tmp32a, tmp32b;
+ int16_t gainQ13;
+
+ int16_t myDecayRate;
+
+ /* ---------- PLC variables ------------ */
+ size_t lag0, i, k;
+ int16_t noiseIndex;
+ int16_t stretchPitchLP[PITCH_MAX_LAG + 10], stretchPitchLP1[PITCH_MAX_LAG + 10];
+
+ int32_t gain_lo_hiQ17[2*SUBFRAMES];
+
+ int16_t nLP, pLP, wNoisyLP, wPriodicLP, tmp16;
+ size_t minIdx;
+ int32_t nHP, pHP, wNoisyHP, wPriodicHP, corr, minCorr, maxCoeff;
+ int16_t noise1, rshift;
+
+
+ int16_t ltpGain, pitchGain, myVoiceIndicator, myAbs, maxAbs;
+ int32_t varIn, varOut, logVarIn, logVarOut, Q, logMaxAbs;
+ int rightShiftIn, rightShiftOut;
+
+
+ /* ------------------------------------- */
+
+
+ myDecayRate = (DECAY_RATE);
+ Vector_Word16_1 = &Vector_Word16_Extended_1[NOISE_FILTER_LEN];
+ Vector_Word16_2 = &Vector_Word16_Extended_2[NOISE_FILTER_LEN];
+
+
+ /* ----- Simply Copy Previous LPC parameters ------ */
+ for( subframecnt = 0; subframecnt < SUBFRAMES; subframecnt++ )
+ {
+ /* lower Band */
+ WEBRTC_SPL_MEMCPY_W16(&lofilt_coefQ15[ subframecnt * ORDERLO ],
+ (ISACdec_obj->plcstr_obj).lofilt_coefQ15, ORDERLO);
+ gain_lo_hiQ17[2*subframecnt] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0];
+
+ /* Upper Band */
+ WEBRTC_SPL_MEMCPY_W16(&hifilt_coefQ15[ subframecnt * ORDERHI ],
+ (ISACdec_obj->plcstr_obj).hifilt_coefQ15, ORDERHI);
+ gain_lo_hiQ17[2*subframecnt + 1] = (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1];
+ }
+
+
+
+
+ lag0 = (size_t)(((ISACdec_obj->plcstr_obj.lastPitchLag_Q7 + 64) >> 7) + 1);
+
+
+ if( (ISACdec_obj->plcstr_obj).used != PLC_WAS_USED )
+ {
+ (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+
+ (ISACdec_obj->plcstr_obj).lastPitchLP =
+ &((ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0]);
+ minCorr = WEBRTC_SPL_WORD32_MAX;
+
+ if ((FRAMESAMPLES_HALF - 10) > 2 * lag0)
+ {
+ minIdx = 11;
+ for( i = 0; i < 21; i++ )
+ {
+ corr = 0;
+ for( k = 0; k < lag0; k++ )
+ {
+ corr = WebRtcSpl_AddSatW32(corr, WEBRTC_SPL_ABS_W32(
+ WebRtcSpl_SubSatW16(
+ (ISACdec_obj->plcstr_obj).lastPitchLP[k],
+ (ISACdec_obj->plcstr_obj).prevPitchInvIn[
+ FRAMESAMPLES_HALF - 2*lag0 - 10 + i + k ] ) ) );
+ }
+ if( corr < minCorr )
+ {
+ minCorr = corr;
+ minIdx = i;
+ }
+ }
+ (ISACdec_obj->plcstr_obj).prevPitchLP =
+ &( (ISACdec_obj->plcstr_obj).prevPitchInvIn[
+ FRAMESAMPLES_HALF - lag0*2 - 10 + minIdx] );
+ }
+ else
+ {
+ (ISACdec_obj->plcstr_obj).prevPitchLP =
+ (ISACdec_obj->plcstr_obj).lastPitchLP;
+ }
+ pitchGain = (ISACdec_obj->plcstr_obj).lastPitchGain_Q12;
+
+ WebRtcSpl_AutoCorrelation(
+ &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF - lag0],
+ lag0, 0, &varIn, &rightShiftIn);
+ WebRtcSpl_AutoCorrelation(
+ &(ISACdec_obj->plcstr_obj).prevPitchInvOut[PITCH_MAX_LAG + 10 - lag0],
+ lag0, 0, &varOut, &rightShiftOut);
+
+ maxAbs = 0;
+ for( i = 0; i< lag0; i++)
+ {
+ myAbs = WEBRTC_SPL_ABS_W16(
+ (ISACdec_obj->plcstr_obj).prevPitchInvOut[
+ PITCH_MAX_LAG + 10 - lag0 + i] );
+ maxAbs = (myAbs > maxAbs)? myAbs:maxAbs;
+ }
+ logVarIn = log2_Q8_T( (uint32_t)( varIn ) ) +
+ (int32_t)(rightShiftIn << 8);
+ logVarOut = log2_Q8_T( (uint32_t)( varOut ) ) +
+ (int32_t)(rightShiftOut << 8);
+ logMaxAbs = log2_Q8_T( (uint32_t)( maxAbs ) );
+
+ ltpGain = (int16_t)(logVarOut - logVarIn);
+ Q = 2 * logMaxAbs - ( logVarOut - 1512 );
+
+ /*
+ * ---
+ * We are computing sqrt( (VarIn/lag0) / var( noise ) )
+ * var( noise ) is almost 256. we have already computed log2( VarIn ) in Q8
+ * so we actually compute 2^( 0.5*(log2( VarIn ) - log2( lag0 ) - log2( var(noise ) ) ).
+ * Note that put log function is in Q8 but the exponential function is in Q10.
+ * --
+ */
+
+ logVarIn -= log2_Q8_T( (uint32_t)( lag0 ) );
+ tmp16 = (int16_t)((logVarIn<<1) - (4<<10) );
+ rightShiftIn = 0;
+ if( tmp16 > 4096 )
+ {
+ tmp16 -= 4096;
+ tmp16 = exp2_Q10_T( tmp16 );
+ tmp16 >>= 6;
+ }
+ else
+ tmp16 = exp2_Q10_T( tmp16 )>>10;
+
+ (ISACdec_obj->plcstr_obj).std = tmp16 - 4;
+
+ if( (ltpGain < 110) || (ltpGain > 230) )
+ {
+ if( ltpGain < 100 && (pitchGain < 1800) )
+ {
+ (ISACdec_obj->plcstr_obj).A = WEBRTC_SPL_WORD16_MAX;
+ }
+ else
+ {
+ (ISACdec_obj->plcstr_obj).A = ((ltpGain < 110) && (Q < 800)
+ )? WEBRTC_SPL_WORD16_MAX:0;
+ }
+ (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
+ (ISACdec_obj->plcstr_obj).A;
+ }
+ else
+ {
+ if( (pitchGain < 450) || (pitchGain > 1600) )
+ {
+ (ISACdec_obj->plcstr_obj).A = ((pitchGain < 450)
+ )? WEBRTC_SPL_WORD16_MAX:0;
+ (ISACdec_obj->plcstr_obj).B = WEBRTC_SPL_WORD16_MAX -
+ (ISACdec_obj->plcstr_obj).A;
+ }
+ else
+ {
+ myVoiceIndicator = ltpGain * 2 + pitchGain;
+ MemshipValQ15( myVoiceIndicator,
+ &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
+ }
+ }
+
+
+
+ myVoiceIndicator = ltpGain * 16 + pitchGain * 2 + (pitchGain >> 8);
+ MemshipValQ15( myVoiceIndicator,
+ &(ISACdec_obj->plcstr_obj).A, &(ISACdec_obj->plcstr_obj).B );
+
+
+
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+ (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+
+ }
+ else
+ {
+ myDecayRate = (DECAY_RATE<<2);
+ }
+
+ if( (ISACdec_obj->plcstr_obj).B < 1000 )
+ {
+ myDecayRate += (DECAY_RATE<<3);
+ }
+
+ /* ------------ reconstructing the residual signal ------------------ */
+
+ LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
+ stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+ /* inverse pitch filter */
+
+ pitchLags_Q7[0] = pitchLags_Q7[1] = pitchLags_Q7[2] = pitchLags_Q7[3] =
+ (int16_t)((ISACdec_obj->plcstr_obj).stretchLag<<7);
+ pitchGains_Q12[3] = ( (ISACdec_obj->plcstr_obj).lastPitchGain_Q12);
+ pitchGains_Q12[2] = (int16_t)(pitchGains_Q12[3] * 1010 >> 10);
+ pitchGains_Q12[1] = (int16_t)(pitchGains_Q12[2] * 1010 >> 10);
+ pitchGains_Q12[0] = (int16_t)(pitchGains_Q12[1] * 1010 >> 10);
+
+
+ /* most of the time either B or A are zero so seperating */
+ if( (ISACdec_obj->plcstr_obj).B == 0 )
+ {
+ for( i = 0; i < FRAMESAMPLES_HALF; i++ )
+ {
+ /* --- Low Pass */
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_1[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+ /* --- Highpass */
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_2[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+ }
+ for( i = 1; i < NOISE_FILTER_LEN; i++ )
+ {
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_Extended_1[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ Vector_Word16_Extended_2[i] = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+ }
+ plc_filterma_Fast(Vector_Word16_1, Vector_Word16_Extended_1,
+ &(ISACdec_obj->plcstr_obj).prevPitchInvIn[FRAMESAMPLES_HALF -
+ NOISE_FILTER_LEN], (int16_t) NOISE_FILTER_LEN,
+ (int16_t) FRAMESAMPLES_HALF, (int16_t)(5),
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise, (int16_t)(6));
+
+ maxCoeff = WebRtcSpl_MaxAbsValueW32(
+ &(ISACdec_obj->plcstr_obj).prevHP[
+ PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN], NOISE_FILTER_LEN );
+
+ rshift = 0;
+ while( maxCoeff > WEBRTC_SPL_WORD16_MAX )
+ {
+ maxCoeff >>= 1;
+ rshift++;
+ }
+ for( i = 0; i < NOISE_FILTER_LEN; i++ ) {
+ Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN + i] =(int16_t)(
+ ISACdec_obj->plcstr_obj.prevHP[PITCH_MAX_LAG + 10 - NOISE_FILTER_LEN +
+ i] >> rshift);
+ }
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise = plc_filterma_Fast(
+ Vector_Word16_2,
+ Vector_Word16_Extended_2,
+ &Vector_Word16_1[FRAMESAMPLES_HALF - NOISE_FILTER_LEN],
+ (int16_t) NOISE_FILTER_LEN,
+ (int16_t) FRAMESAMPLES_HALF,
+ (int16_t) (5),
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise,
+ (int16_t) (7) );
+
+ for( i = 0; i < FRAMESAMPLES_HALF; i++ )
+ Vector_Word32_2[i] = Vector_Word16_Extended_2[i] << rshift;
+
+ Vector_Word16_1 = Vector_Word16_Extended_1;
+ }
+ else
+ {
+ if( (ISACdec_obj->plcstr_obj).A == 0 )
+ {
+ /* ------ Periodic Vector --- */
+ for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
+ {
+ /* --- Lowpass */
+ pLP = (int16_t)(stretchPitchLP[ISACdec_obj->plcstr_obj.pitchIndex] *
+ ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
+
+ /* --- Highpass */
+ pHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
+ (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
+ (ISACdec_obj->plcstr_obj).stretchLag +
+ (ISACdec_obj->plcstr_obj).pitchIndex] );
+
+ /* --- lower the muliplier (more decay at next sample) --- */
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
+ if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
+
+ (ISACdec_obj->plcstr_obj).pitchIndex++;
+
+ if( (ISACdec_obj->plcstr_obj).pitchIndex ==
+ (ISACdec_obj->plcstr_obj).stretchLag )
+ {
+ (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+ (ISACdec_obj->plcstr_obj).pitchCycles++;
+
+ if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
+ {
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
+ }
+ else
+ {
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+ }
+
+ (ISACdec_obj->plcstr_obj).stretchLag = (
+ (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
+ )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
+
+ LinearResampler( (ISACdec_obj->plcstr_obj).lastPitchLP,
+ stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ LinearResampler( (ISACdec_obj->plcstr_obj).prevPitchLP,
+ stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ switch( (ISACdec_obj->plcstr_obj).pitchCycles )
+ {
+ case 1:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (int16_t)((
+ (int32_t)stretchPitchLP[k]* 3 +
+ (int32_t)stretchPitchLP1[k])>>2);
+ }
+ break;
+ }
+ case 2:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (int16_t)((
+ (int32_t)stretchPitchLP[k] +
+ (int32_t)stretchPitchLP1[k] )>>1);
+ }
+ break;
+ }
+ case 3:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (int16_t)((stretchPitchLP[k] +
+ (int32_t)stretchPitchLP1[k]*3 )>>2);
+ }
+ break;
+ }
+ }
+
+ if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
+ {
+ myDecayRate += 35; //(myDecayRate>>1);
+ (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+ }
+
+ }
+
+ /* ------ Sum the noisy and periodic signals ------ */
+ Vector_Word16_1[i] = pLP;
+ Vector_Word32_2[i] = pHP;
+ }
+ }
+ else
+ {
+ for( i = 0, noiseIndex = 0; i < FRAMESAMPLES_HALF; i++, noiseIndex++ )
+ {
+
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+
+ noise1 = (ISACdec_obj->plcstr_obj.seed >> 10) - 16;
+
+ nLP = (int16_t)((int16_t)(noise1 * ISACdec_obj->plcstr_obj.std) *
+ ISACdec_obj->plcstr_obj.decayCoeffNoise >> 15);
+
+ /* --- Highpass */
+ (ISACdec_obj->plcstr_obj).seed = WEBRTC_SPL_RAND(
+ (ISACdec_obj->plcstr_obj).seed );
+ noise1 = (ISACdec_obj->plcstr_obj.seed >> 11) - 8;
+
+ nHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise,
+ (int32_t)(noise1*(ISACdec_obj->plcstr_obj).std) );
+
+ /* --- lower the muliplier (more decay at next sample) --- */
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise -= (myDecayRate);
+ if( (ISACdec_obj->plcstr_obj).decayCoeffNoise < 0 )
+ (ISACdec_obj->plcstr_obj).decayCoeffNoise = 0;
+
+ /* ------ Periodic Vector --- */
+ /* --- Lowpass */
+ pLP = (int16_t)(stretchPitchLP[ISACdec_obj->plcstr_obj.pitchIndex] *
+ ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
+
+ /* --- Highpass */
+ pHP = (int32_t)WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic,
+ (ISACdec_obj->plcstr_obj).prevHP[PITCH_MAX_LAG + 10 -
+ (ISACdec_obj->plcstr_obj).stretchLag +
+ (ISACdec_obj->plcstr_obj).pitchIndex] );
+
+ /* --- lower the muliplier (more decay at next sample) --- */
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic -= (myDecayRate);
+ if( (ISACdec_obj->plcstr_obj).decayCoeffPriodic < 0 )
+ {
+ (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 0;
+ }
+
+ /* ------ Weighting the noisy and periodic vectors ------- */
+ wNoisyLP = (int16_t)(ISACdec_obj->plcstr_obj.A * nLP >> 15);
+ wNoisyHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).A, (nHP) ) );
+
+ wPriodicLP = (int16_t)(ISACdec_obj->plcstr_obj.B * pLP >> 15);
+ wPriodicHP = (int32_t)(WEBRTC_SPL_MUL_16_32_RSFT15(
+ (ISACdec_obj->plcstr_obj).B, pHP));
+
+ (ISACdec_obj->plcstr_obj).pitchIndex++;
+
+ if((ISACdec_obj->plcstr_obj).pitchIndex ==
+ (ISACdec_obj->plcstr_obj).stretchLag)
+ {
+ (ISACdec_obj->plcstr_obj).pitchIndex = 0;
+ (ISACdec_obj->plcstr_obj).pitchCycles++;
+
+ if( (ISACdec_obj->plcstr_obj).stretchLag != (lag0 + 1) )
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0 + 1;
+ else
+ (ISACdec_obj->plcstr_obj).stretchLag = lag0;
+
+ (ISACdec_obj->plcstr_obj).stretchLag = (
+ (ISACdec_obj->plcstr_obj).stretchLag > PITCH_MAX_LAG
+ )? (PITCH_MAX_LAG):(ISACdec_obj->plcstr_obj).stretchLag;
+ LinearResampler(
+ (ISACdec_obj->plcstr_obj).lastPitchLP,
+ stretchPitchLP, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ LinearResampler((ISACdec_obj->plcstr_obj).prevPitchLP,
+ stretchPitchLP1, lag0, (ISACdec_obj->plcstr_obj).stretchLag );
+
+ switch((ISACdec_obj->plcstr_obj).pitchCycles)
+ {
+ case 1:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (int16_t)((
+ (int32_t)stretchPitchLP[k]* 3 +
+ (int32_t)stretchPitchLP1[k] )>>2);
+ }
+ break;
+ }
+ case 2:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (int16_t)((
+ (int32_t)stretchPitchLP[k] +
+ (int32_t)stretchPitchLP1[k])>>1);
+ }
+ break;
+ }
+ case 3:
+ {
+ for( k=0; k<(ISACdec_obj->plcstr_obj).stretchLag; k++ )
+ {
+ stretchPitchLP[k] = (int16_t)(
+ (stretchPitchLP[k] +
+ (int32_t)stretchPitchLP1[k]*3 )>>2);
+ }
+ break;
+ }
+ }
+
+ if( (ISACdec_obj->plcstr_obj).pitchCycles == 3 )
+ {
+ myDecayRate += 55; //(myDecayRate>>1);
+ (ISACdec_obj->plcstr_obj).pitchCycles = 0;
+ }
+ }
+
+ /* ------ Sum the noisy and periodic signals ------ */
+ Vector_Word16_1[i] = WebRtcSpl_AddSatW16(wNoisyLP, wPriodicLP);
+ Vector_Word32_2[i] = WebRtcSpl_AddSatW32(wNoisyHP, wPriodicHP);
+ }
+ }
+ }
+ /* ----------------- residual signal is reconstructed ------------------ */
+
+ k = (ISACdec_obj->plcstr_obj).pitchIndex;
+ /* --- Write one pitch cycle for recovery block --- */
+
+ for( i = 0; i < RECOVERY_OVERLAP; i++ )
+ {
+ ISACdec_obj->plcstr_obj.overlapLP[i] = (int16_t)(
+ stretchPitchLP[k] * ISACdec_obj->plcstr_obj.decayCoeffPriodic >> 15);
+ k = ( k < ((ISACdec_obj->plcstr_obj).stretchLag - 1) )? (k+1):0;
+ }
+
+ (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 =
+ (int16_t)((ISACdec_obj->plcstr_obj).stretchLag << 7);
+
+
+ /* --- Inverse Pitch Filter --- */
+ WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2,
+ &ISACdec_obj->pitchfiltstr_obj, pitchLags_Q7, pitchGains_Q12, 4);
+
+ /* reduce gain to compensate for pitch enhancer */
+ /* gain = 1.0f - 0.45f * AvgPitchGain; */
+ tmp32a = ISACdec_obj->plcstr_obj.AvgPitchGain_Q12 * 29; // Q18
+ tmp32b = 262144 - tmp32a; // Q18
+ gainQ13 = (int16_t) (tmp32b >> 5); // Q13
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++)
+ Vector_Word32_1[k] = (Vector_Word16_2[k] * gainQ13) << 3; // Q25
+
+
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERLO,
+ (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0,
+ Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1);
+
+ WebRtcIsacfix_NormLatticeFilterAr(ORDERHI,
+ (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0,
+ Vector_Word32_2, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2);
+
+ /* recombine the 2 bands */
+
+ /* Form the polyphase signals, and compensate for DC offset */
+ for (k=0;k<FRAMESAMPLES_HALF;k++)
+ {
+ /* Construct a new upper channel signal*/
+ tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(
+ ((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1));
+ /* Construct a new lower channel signal*/
+ tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(
+ ((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k]));
+ Vector_Word16_1[k] = tmp_1;
+ Vector_Word16_2[k] = tmp_2;
+ }
+
+
+ WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1,
+ Vector_Word16_2, signal_out16, &ISACdec_obj->postfiltbankstr_obj);
+
+ (ISACdec_obj->plcstr_obj).used = PLC_WAS_USED;
+ *current_framesamples = 480;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/encode.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/encode.c
new file mode 100644
index 0000000000..ef3e320e2c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/encode.c
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode.c
+ *
+ * Encoding function for the iSAC coder.
+ *
+ */
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+#include <stdio.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+
+int WebRtcIsacfix_EncodeImpl(int16_t *in,
+ IsacFixEncoderInstance *ISACenc_obj,
+ BwEstimatorstr *bw_estimatordata,
+ int16_t CodingMode)
+{
+ int16_t stream_length = 0;
+ int16_t usefulstr_len = 0;
+ int k;
+ int16_t BWno;
+
+ int16_t lofilt_coefQ15[(ORDERLO)*SUBFRAMES];
+ int16_t hifilt_coefQ15[(ORDERHI)*SUBFRAMES];
+ int32_t gain_lo_hiQ17[2*SUBFRAMES];
+
+ int16_t LPandHP[FRAMESAMPLES/2 + QLOOKAHEAD];
+ int16_t LP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
+ int16_t HP16a[FRAMESAMPLES/2 + QLOOKAHEAD];
+
+ int16_t PitchLags_Q7[PITCH_SUBFRAMES];
+ int16_t PitchGains_Q12[PITCH_SUBFRAMES];
+ int16_t AvgPitchGain_Q12;
+
+ int16_t frame_mode; /* 0 for 30ms, 1 for 60ms */
+ int16_t processed_samples;
+ int status;
+
+ int32_t bits_gainsQ11;
+ int16_t MinBytes;
+ int16_t bmodel;
+
+ transcode_obj transcodingParam;
+ int16_t payloadLimitBytes;
+ int16_t arithLenBeforeEncodingDFT;
+ int16_t iterCntr;
+
+ /* copy new frame length and bottle neck rate only for the first 10 ms data */
+ if (ISACenc_obj->buffer_index == 0) {
+ /* set the framelength for the next packet */
+ ISACenc_obj->current_framesamples = ISACenc_obj->new_framelength;
+ }
+
+ frame_mode = ISACenc_obj->current_framesamples/MAX_FRAMESAMPLES; /* 0 (30 ms) or 1 (60 ms) */
+ processed_samples = ISACenc_obj->current_framesamples/(frame_mode+1); /* 480 (30, 60 ms) */
+
+ /* buffer speech samples (by 10ms packet) until the framelength is reached (30 or 60 ms) */
+ /**************************************************************************************/
+ /* fill the buffer with 10ms input data */
+ for(k=0; k<FRAMESAMPLES_10ms; k++) {
+ ISACenc_obj->data_buffer_fix[k + ISACenc_obj->buffer_index] = in[k];
+ }
+ /* if buffersize is not equal to current framesize, and end of file is not reached yet, */
+ /* increase index and go back to main to get more speech samples */
+ if (ISACenc_obj->buffer_index + FRAMESAMPLES_10ms != processed_samples) {
+ ISACenc_obj->buffer_index = ISACenc_obj->buffer_index + FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* if buffer reached the right size, reset index and continue with encoding the frame */
+ ISACenc_obj->buffer_index = 0;
+
+ /* end of buffer function */
+ /**************************/
+
+ /* encoding */
+ /************/
+
+ if (frame_mode == 0 || ISACenc_obj->frame_nb == 0 )
+ {
+ /* reset bitstream */
+ ISACenc_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACenc_obj->bitstr_obj.streamval = 0;
+ ISACenc_obj->bitstr_obj.stream_index = 0;
+ ISACenc_obj->bitstr_obj.full = 1;
+
+ if (CodingMode == 0) {
+ ISACenc_obj->BottleNeck = WebRtcIsacfix_GetUplinkBandwidth(bw_estimatordata);
+ ISACenc_obj->MaxDelay = WebRtcIsacfix_GetUplinkMaxDelay(bw_estimatordata);
+ }
+ if (CodingMode == 0 && frame_mode == 0 && (ISACenc_obj->enforceFrameSize == 0)) {
+ ISACenc_obj->new_framelength = WebRtcIsacfix_GetNewFrameLength(ISACenc_obj->BottleNeck,
+ ISACenc_obj->current_framesamples);
+ }
+
+ // multiply the bottleneck by 0.88 before computing SNR, 0.88 is tuned by experimenting on TIMIT
+ // 901/1024 is 0.87988281250000
+ ISACenc_obj->s2nr = WebRtcIsacfix_GetSnr(
+ (int16_t)(ISACenc_obj->BottleNeck * 901 >> 10),
+ ISACenc_obj->current_framesamples);
+
+ /* encode frame length */
+ status = WebRtcIsacfix_EncodeFrameLen(ISACenc_obj->current_framesamples, &ISACenc_obj->bitstr_obj);
+ if (status < 0)
+ {
+ /* Wrong frame size */
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+
+ /* Save framelength for multiple packets memory */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ (ISACenc_obj->SaveEnc_ptr)->framelength=ISACenc_obj->current_framesamples;
+ }
+
+ /* bandwidth estimation and coding */
+ BWno = WebRtcIsacfix_GetDownlinkBwIndexImpl(bw_estimatordata);
+ status = WebRtcIsacfix_EncodeReceiveBandwidth(&BWno, &ISACenc_obj->bitstr_obj);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ }
+
+ /* split signal in two bands */
+ WebRtcIsacfix_SplitAndFilter1(ISACenc_obj->data_buffer_fix, LP16a, HP16a, &ISACenc_obj->prefiltbankstr_obj );
+
+ /* estimate pitch parameters and pitch-filter lookahead signal */
+ WebRtcIsacfix_PitchAnalysis(LP16a+QLOOKAHEAD, LPandHP,
+ &ISACenc_obj->pitchanalysisstr_obj, PitchLags_Q7, PitchGains_Q12); /* LPandHP = LP_lookahead_pfQ0, */
+
+ /* Set where to store data in multiple packets memory */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ if (frame_mode == 0 || ISACenc_obj->frame_nb == 0)
+ {
+ (ISACenc_obj->SaveEnc_ptr)->startIdx = 0;
+ }
+ else
+ {
+ (ISACenc_obj->SaveEnc_ptr)->startIdx = 1;
+ }
+ }
+
+ /* quantize & encode pitch parameters */
+ status = WebRtcIsacfix_EncodePitchGain(PitchGains_Q12, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ status = WebRtcIsacfix_EncodePitchLag(PitchLags_Q7 , PitchGains_Q12, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+ /* find coefficients for perceptual pre-filters */
+ WebRtcIsacfix_GetLpcCoef(LPandHP, HP16a+QLOOKAHEAD, &ISACenc_obj->maskfiltstr_obj,
+ ISACenc_obj->s2nr, PitchGains_Q12,
+ gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15); /*LPandHP = LP_lookahead_pfQ0*/
+
+ // record LPC Gains for possible bit-rate reduction
+ for(k = 0; k < KLT_ORDER_GAIN; k++)
+ {
+ transcodingParam.lpcGains[k] = gain_lo_hiQ17[k];
+ }
+
+ /* code LPC model and shape - gains not quantized yet */
+ status = WebRtcIsacfix_EncodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15,
+ &bmodel, &bits_gainsQ11, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr, &transcodingParam);
+ if (status < 0)
+ {
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ arithLenBeforeEncodingDFT = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full);
+
+ /* low-band filtering */
+ WebRtcIsacfix_NormLatticeFilterMa(ORDERLO, ISACenc_obj->maskfiltstr_obj.PreStateLoGQ15,
+ LP16a, lofilt_coefQ15, gain_lo_hiQ17, 0, LPandHP);/* LPandHP = LP16b */
+
+ /* pitch filter */
+ WebRtcIsacfix_PitchFilter(LPandHP, LP16a, &ISACenc_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 1);/* LPandHP = LP16b */
+
+ /* high-band filtering */
+ WebRtcIsacfix_NormLatticeFilterMa(ORDERHI, ISACenc_obj->maskfiltstr_obj.PreStateHiGQ15,
+ HP16a, hifilt_coefQ15, gain_lo_hiQ17, 1, LPandHP);/*LPandHP = HP16b*/
+
+ /* transform */
+ WebRtcIsacfix_Time2Spec(LP16a, LPandHP, LP16a, LPandHP); /*LPandHP = HP16b*/
+
+ /* Save data for multiple packets memory */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ (ISACenc_obj->SaveEnc_ptr)->fre[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LP16a[k];
+ (ISACenc_obj->SaveEnc_ptr)->fim[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LPandHP[k];
+ }
+ (ISACenc_obj->SaveEnc_ptr)->AvgPitchGain[(ISACenc_obj->SaveEnc_ptr)->startIdx] = AvgPitchGain_Q12;
+ }
+
+ /* quantization and lossless coding */
+ status = WebRtcIsacfix_EncodeSpec(LP16a, LPandHP, &ISACenc_obj->bitstr_obj, AvgPitchGain_Q12);
+ if((status <= -1) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) /*LPandHP = HP16b*/
+ {
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+
+ if((frame_mode == 1) && (ISACenc_obj->frame_nb == 0))
+ {
+ // it is a 60ms and we are in the first 30ms
+ // then the limit at this point should be half of the assigned value
+ payloadLimitBytes = ISACenc_obj->payloadLimitBytes60 >> 1;
+ }
+ else if (frame_mode == 0)
+ {
+ // it is a 30ms frame
+ payloadLimitBytes = (ISACenc_obj->payloadLimitBytes30) - 3;
+ }
+ else
+ {
+ // this is the second half of a 60ms frame.
+ payloadLimitBytes = ISACenc_obj->payloadLimitBytes60 - 3; // subract 3 because termination process may add 3 bytes
+ }
+
+ iterCntr = 0;
+ while((((ISACenc_obj->bitstr_obj.stream_index) << 1) > payloadLimitBytes) ||
+ (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH))
+ {
+ int16_t arithLenDFTByte;
+ int16_t bytesLeftQ5;
+ int16_t ratioQ5[8] = {0, 6, 9, 12, 16, 19, 22, 25};
+
+ // According to experiments on TIMIT the following is proper for audio, but it is not agressive enough for tonal inputs
+ // such as DTMF, sweep-sine, ...
+ //
+ // (0.55 - (0.8 - ratio[i]/32) * 5 / 6) * 2^14
+ // int16_t scaleQ14[8] = {0, 648, 1928, 3208, 4915, 6195, 7475, 8755};
+
+
+ // This is a supper-agressive scaling passed the tests (tonal inputs) tone with one iteration for payload limit
+ // of 120 (32kbps bottleneck), number of frames needed a rate-reduction was 58403
+ //
+ int16_t scaleQ14[8] = {0, 348, 828, 1408, 2015, 3195, 3500, 3500};
+ int16_t idx;
+
+ if(iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION)
+ {
+ // We were not able to limit the payload size
+
+ if((frame_mode == 1) && (ISACenc_obj->frame_nb == 0))
+ {
+ // This was the first 30ms of a 60ms frame. Although the payload is larger than it
+ // should be but we let the second 30ms be encoded. Maybe togetehr we won't exceed
+ // the limit.
+ ISACenc_obj->frame_nb = 1;
+ return 0;
+ }
+ else if((frame_mode == 1) && (ISACenc_obj->frame_nb == 1))
+ {
+ ISACenc_obj->frame_nb = 0;
+ }
+
+ if(status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)
+ {
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ }
+ else
+ {
+ return status;
+ }
+ }
+ if(status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)
+ {
+ arithLenDFTByte = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full) - arithLenBeforeEncodingDFT;
+ bytesLeftQ5 = (payloadLimitBytes - arithLenBeforeEncodingDFT) << 5;
+
+ // bytesLeft / arithLenDFTBytes indicates how much scaling is required a rough estimate (agressive)
+ // scale = 0.55 - (0.8 - bytesLeft / arithLenDFTBytes) * 5 / 6
+ // bytesLeft / arithLenDFTBytes below 0.2 will have a scale of zero and above 0.8 are treated as 0.8
+ // to avoid division we do more simplification.
+ //
+ // values of (bytesLeft / arithLenDFTBytes)*32 between ratioQ5[i] and ratioQ5[i+1] are rounded to ratioQ5[i]
+ // and the corresponding scale is chosen
+
+ // we compare bytesLeftQ5 with ratioQ5[]*arithLenDFTByte;
+ idx = 4;
+ idx += (bytesLeftQ5 >= ratioQ5[idx] * arithLenDFTByte) ? 2 : -2;
+ idx += (bytesLeftQ5 >= ratioQ5[idx] * arithLenDFTByte) ? 1 : -1;
+ idx += (bytesLeftQ5 >= ratioQ5[idx] * arithLenDFTByte) ? 0 : -1;
+ }
+ else
+ {
+ // we are here because the bit-stream did not fit into the buffer, in this case, the stream_index is not
+ // trustable, especially if the is the first 30ms of a packet. Thereforem, we will go for the most agressive
+ // case.
+ idx = 0;
+ }
+ // scale FFT coefficients to reduce the bit-rate
+ for(k = 0; k < FRAMESAMPLES_HALF; k++)
+ {
+ LP16a[k] = (int16_t)(LP16a[k] * scaleQ14[idx] >> 14);
+ LPandHP[k] = (int16_t)(LPandHP[k] * scaleQ14[idx] >> 14);
+ }
+
+ // Save data for multiple packets memory
+ if (ISACenc_obj->SaveEnc_ptr != NULL)
+ {
+ for(k = 0; k < FRAMESAMPLES_HALF; k++)
+ {
+ (ISACenc_obj->SaveEnc_ptr)->fre[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LP16a[k];
+ (ISACenc_obj->SaveEnc_ptr)->fim[k + (ISACenc_obj->SaveEnc_ptr)->startIdx*FRAMESAMPLES_HALF] = LPandHP[k];
+ }
+ }
+
+ // scale the unquantized LPC gains and save the scaled version for the future use
+ for(k = 0; k < KLT_ORDER_GAIN; k++)
+ {
+ gain_lo_hiQ17[k] = WEBRTC_SPL_MUL_16_32_RSFT14(scaleQ14[idx], transcodingParam.lpcGains[k]);//transcodingParam.lpcGains[k]; //
+ transcodingParam.lpcGains[k] = gain_lo_hiQ17[k];
+ }
+
+ // reset the bit-stream object to the state which it had before encoding LPC Gains
+ ISACenc_obj->bitstr_obj.full = transcodingParam.full;
+ ISACenc_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+ ISACenc_obj->bitstr_obj.streamval = transcodingParam.streamval;
+ ISACenc_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+ ISACenc_obj->bitstr_obj.stream[transcodingParam.stream_index-1] = transcodingParam.beforeLastWord;
+ ISACenc_obj->bitstr_obj.stream[transcodingParam.stream_index] = transcodingParam.lastWord;
+
+
+ // quantize and encode LPC gain
+ WebRtcIsacfix_EstCodeLpcGain(gain_lo_hiQ17, &ISACenc_obj->bitstr_obj, ISACenc_obj->SaveEnc_ptr);
+ arithLenBeforeEncodingDFT = (ISACenc_obj->bitstr_obj.stream_index << 1) + (1-ISACenc_obj->bitstr_obj.full);
+ status = WebRtcIsacfix_EncodeSpec(LP16a, LPandHP, &ISACenc_obj->bitstr_obj, AvgPitchGain_Q12);
+ if((status <= -1) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) /*LPandHP = HP16b*/
+ {
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ // If this is the second 30ms of a 60ms frame reset this such that in the next call
+ // encoder starts fresh.
+ ISACenc_obj->frame_nb = 0;
+ }
+ return status;
+ }
+ iterCntr++;
+ }
+
+ if (frame_mode == 1 && ISACenc_obj->frame_nb == 0)
+ /* i.e. 60 ms framesize and just processed the first 30ms, */
+ /* go back to main function to buffer the other 30ms speech frame */
+ {
+ ISACenc_obj->frame_nb = 1;
+ return 0;
+ }
+ else if (frame_mode == 1 && ISACenc_obj->frame_nb == 1)
+ {
+ ISACenc_obj->frame_nb = 0;
+ /* also update the framelength for next packet, in Adaptive mode only */
+ if (CodingMode == 0 && (ISACenc_obj->enforceFrameSize == 0)) {
+ ISACenc_obj->new_framelength = WebRtcIsacfix_GetNewFrameLength(ISACenc_obj->BottleNeck,
+ ISACenc_obj->current_framesamples);
+ }
+ }
+
+
+ /* complete arithmetic coding */
+ stream_length = WebRtcIsacfix_EncTerminate(&ISACenc_obj->bitstr_obj);
+ /* can this be negative? */
+
+ if(CodingMode == 0)
+ {
+
+ /* update rate model and get minimum number of bytes in this packet */
+ MinBytes = WebRtcIsacfix_GetMinBytes(&ISACenc_obj->rate_data_obj, (int16_t) stream_length,
+ ISACenc_obj->current_framesamples, ISACenc_obj->BottleNeck, ISACenc_obj->MaxDelay);
+
+ /* if bitstream is too short, add garbage at the end */
+
+ /* Store length of coded data */
+ usefulstr_len = stream_length;
+
+ /* Make sure MinBytes does not exceed packet size limit */
+ if ((ISACenc_obj->frame_nb == 0) && (MinBytes > ISACenc_obj->payloadLimitBytes30)) {
+ MinBytes = ISACenc_obj->payloadLimitBytes30;
+ } else if ((ISACenc_obj->frame_nb == 1) && (MinBytes > ISACenc_obj->payloadLimitBytes60)) {
+ MinBytes = ISACenc_obj->payloadLimitBytes60;
+ }
+
+ /* Make sure we don't allow more than 255 bytes of garbage data.
+ We store the length of the garbage data in 8 bits in the bitstream,
+ 255 is the max garbage lenght we can signal using 8 bits. */
+ if( MinBytes > usefulstr_len + 255 ) {
+ MinBytes = usefulstr_len + 255;
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (ISACenc_obj->SaveEnc_ptr != NULL) {
+ (ISACenc_obj->SaveEnc_ptr)->minBytes = MinBytes;
+ }
+
+ while (stream_length < MinBytes)
+ {
+ RTC_DCHECK_GE(stream_length, 0);
+ if (stream_length & 0x0001){
+ ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
+ ISACenc_obj->bitstr_obj.stream[stream_length / 2] |=
+ (uint16_t)(ISACenc_obj->bitstr_seed & 0xFF);
+ } else {
+ ISACenc_obj->bitstr_seed = WEBRTC_SPL_RAND( ISACenc_obj->bitstr_seed );
+ ISACenc_obj->bitstr_obj.stream[stream_length / 2] =
+ ((uint16_t)ISACenc_obj->bitstr_seed << 8);
+ }
+ stream_length++;
+ }
+
+ /* to get the real stream_length, without garbage */
+ if (usefulstr_len & 0x0001) {
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] &= 0xFF00;
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] += (MinBytes - usefulstr_len) & 0x00FF;
+ }
+ else {
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len>>1] &= 0x00FF;
+ ISACenc_obj->bitstr_obj.stream[usefulstr_len >> 1] +=
+ ((uint16_t)((MinBytes - usefulstr_len) & 0x00FF) << 8);
+ }
+ }
+ else
+ {
+ /* update rate model */
+ WebRtcIsacfix_UpdateRateModel(&ISACenc_obj->rate_data_obj, (int16_t) stream_length,
+ ISACenc_obj->current_framesamples, ISACenc_obj->BottleNeck);
+ }
+ return stream_length;
+}
+
+/* This function is used to create a new bitstream with new BWE.
+ The same data as previously encoded with the fucntion WebRtcIsacfix_EncodeImpl()
+ is used. The data needed is taken from the struct, where it was stored
+ when calling the encoder. */
+int WebRtcIsacfix_EncodeStoredData(IsacFixEncoderInstance *ISACenc_obj,
+ int BWnumber,
+ float scale)
+{
+ int ii;
+ int status;
+ int16_t BWno = (int16_t)BWnumber;
+ int stream_length = 0;
+
+ int16_t model;
+ const uint16_t *Q_PitchGain_cdf_ptr[1];
+ const uint16_t **cdf;
+ const IsacSaveEncoderData *SaveEnc_str;
+ int32_t tmpLPCcoeffs_g[KLT_ORDER_GAIN<<1];
+ int16_t tmpLPCindex_g[KLT_ORDER_GAIN<<1];
+ int16_t tmp_fre[FRAMESAMPLES];
+ int16_t tmp_fim[FRAMESAMPLES];
+
+ SaveEnc_str = ISACenc_obj->SaveEnc_ptr;
+
+ /* Check if SaveEnc memory exists */
+ if (SaveEnc_str == NULL) {
+ return (-1);
+ }
+
+ /* Sanity Check - possible values for BWnumber is 0 - 23 */
+ if ((BWnumber < 0) || (BWnumber > 23)) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* reset bitstream */
+ ISACenc_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACenc_obj->bitstr_obj.streamval = 0;
+ ISACenc_obj->bitstr_obj.stream_index = 0;
+ ISACenc_obj->bitstr_obj.full = 1;
+
+ /* encode frame length */
+ status = WebRtcIsacfix_EncodeFrameLen(SaveEnc_str->framelength, &ISACenc_obj->bitstr_obj);
+ if (status < 0) {
+ /* Wrong frame size */
+ return status;
+ }
+
+ /* encode bandwidth estimate */
+ status = WebRtcIsacfix_EncodeReceiveBandwidth(&BWno, &ISACenc_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Transcoding */
+ /* If scale < 1, rescale data to produce lower bitrate signal */
+ if ((0.0 < scale) && (scale < 1.0)) {
+ /* Compensate LPC gain */
+ for (ii = 0; ii < (KLT_ORDER_GAIN*(1+SaveEnc_str->startIdx)); ii++) {
+ tmpLPCcoeffs_g[ii] = (int32_t) ((scale) * (float) SaveEnc_str->LPCcoeffs_g[ii]);
+ }
+
+ /* Scale DFT */
+ for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
+ tmp_fre[ii] = (int16_t) ((scale) * (float) SaveEnc_str->fre[ii]) ;
+ tmp_fim[ii] = (int16_t) ((scale) * (float) SaveEnc_str->fim[ii]) ;
+ }
+ } else {
+ for (ii = 0; ii < (KLT_ORDER_GAIN*(1+SaveEnc_str->startIdx)); ii++) {
+ tmpLPCindex_g[ii] = SaveEnc_str->LPCindex_g[ii];
+ }
+
+ for (ii = 0; ii < (FRAMESAMPLES_HALF*(1+SaveEnc_str->startIdx)); ii++) {
+ tmp_fre[ii] = SaveEnc_str->fre[ii];
+ tmp_fim[ii] = SaveEnc_str->fim[ii];
+ }
+ }
+
+ /* Loop over number of 30 msec */
+ for (ii = 0; ii <= SaveEnc_str->startIdx; ii++)
+ {
+
+ /* encode pitch gains */
+ *Q_PitchGain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &SaveEnc_str->pitchGain_index[ii],
+ Q_PitchGain_cdf_ptr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* entropy coding of quantization pitch lags */
+ /* voicing classificiation */
+ if (SaveEnc_str->meanGain[ii] <= 819) {
+ cdf = WebRtcIsacfix_kPitchLagPtrLo;
+ } else if (SaveEnc_str->meanGain[ii] <= 1638) {
+ cdf = WebRtcIsacfix_kPitchLagPtrMid;
+ } else {
+ cdf = WebRtcIsacfix_kPitchLagPtrHi;
+ }
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj,
+ &SaveEnc_str->pitchIndex[PITCH_SUBFRAMES*ii], cdf, PITCH_SUBFRAMES);
+ if (status < 0) {
+ return status;
+ }
+
+ /* LPC */
+ /* entropy coding of model number */
+ model = 0;
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &model,
+ WebRtcIsacfix_kModelCdfPtr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* entropy coding of quantization indices - LPC shape only */
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &SaveEnc_str->LPCindex_s[KLT_ORDER_SHAPE*ii],
+ WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
+ if (status < 0) {
+ return status;
+ }
+
+ /* If transcoding, get new LPC gain indices */
+ if (scale < 1.0) {
+ WebRtcIsacfix_TranscodeLpcCoef(&tmpLPCcoeffs_g[KLT_ORDER_GAIN*ii], &tmpLPCindex_g[KLT_ORDER_GAIN*ii]);
+ }
+
+ /* entropy coding of quantization indices - LPC gain */
+ status = WebRtcIsacfix_EncHistMulti(&ISACenc_obj->bitstr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN*ii],
+ WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+ if (status < 0) {
+ return status;
+ }
+
+ /* quantization and lossless coding */
+ status = WebRtcIsacfix_EncodeSpec(&tmp_fre[ii*FRAMESAMPLES_HALF], &tmp_fim[ii*FRAMESAMPLES_HALF],
+ &ISACenc_obj->bitstr_obj, SaveEnc_str->AvgPitchGain[ii]);
+ if (status < 0) {
+ return status;
+ }
+ }
+
+ /* complete arithmetic coding */
+ stream_length = WebRtcIsacfix_EncTerminate(&ISACenc_obj->bitstr_obj);
+
+ return stream_length;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c
new file mode 100644
index 0000000000..842e77f47e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.c
@@ -0,0 +1,2056 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This file contains all functions used to arithmetically
+ * encode the iSAC bistream.
+ *
+ */
+
+#include <stddef.h>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/arith_routins.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h"
+#include "rtc_base/sanitizer.h"
+
+/*
+ * Eenumerations for arguments to functions WebRtcIsacfix_MatrixProduct1()
+ * and WebRtcIsacfix_MatrixProduct2().
+*/
+
+enum matrix_index_factor {
+ kTIndexFactor1 = 1,
+ kTIndexFactor2 = 2,
+ kTIndexFactor3 = SUBFRAMES,
+ kTIndexFactor4 = LPC_SHAPE_ORDER
+};
+
+enum matrix_index_step {
+ kTIndexStep1 = 1,
+ kTIndexStep2 = SUBFRAMES,
+ kTIndexStep3 = LPC_SHAPE_ORDER
+};
+
+enum matrixprod_loop_count {
+ kTLoopCount1 = SUBFRAMES,
+ kTLoopCount2 = 2,
+ kTLoopCount3 = LPC_SHAPE_ORDER
+};
+
+enum matrix1_shift_value {
+ kTMatrix1_shift0 = 0,
+ kTMatrix1_shift1 = 1,
+ kTMatrix1_shift5 = 5
+};
+
+enum matrixprod_init_case {
+ kTInitCase0 = 0,
+ kTInitCase1 = 1
+};
+
+/*
+ This function implements the fix-point correspondant function to lrint.
+
+ FLP: (int32_t)floor(flt+.499999999999)
+ FIP: (fixVal+roundVal)>>qDomain
+
+ where roundVal = 2^(qDomain-1) = 1<<(qDomain-1)
+
+*/
+static __inline int32_t CalcLrIntQ(int32_t fixVal, int16_t qDomain) {
+ return (fixVal + (1 << (qDomain - 1))) >> qDomain;
+}
+
+/*
+ __inline uint32_t stepwise(int32_t dinQ10) {
+
+ int32_t ind, diQ10, dtQ10;
+
+ diQ10 = dinQ10;
+ if (diQ10 < DPMIN_Q10)
+ diQ10 = DPMIN_Q10;
+ if (diQ10 >= DPMAX_Q10)
+ diQ10 = DPMAX_Q10 - 1;
+
+ dtQ10 = diQ10 - DPMIN_Q10;*/ /* Q10 + Q10 = Q10 */
+/* ind = (dtQ10 * 5) >> 10; */ /* 2^10 / 5 = 0.2 in Q10 */
+/* Q10 -> Q0 */
+
+/* return rpointsFIX_Q10[ind];
+
+ }
+*/
+
+/* logN(x) = logN(2)*log2(x) = 0.6931*log2(x). Output in Q8. */
+/* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 thimes higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+static int16_t CalcLogN(int32_t arg) {
+ int16_t zeros, log2, frac, logN;
+
+ zeros=WebRtcSpl_NormU32(arg);
+ frac = (int16_t)((uint32_t)((arg << zeros) & 0x7FFFFFFF) >> 23);
+ log2 = (int16_t)(((31 - zeros) << 8) + frac); // log2(x) in Q8
+ logN = (int16_t)(log2 * 22713 >> 15); // log(2) = 0.693147 = 22713 in Q15
+ logN=logN+11; //Scalar compensation which minimizes the (log(x)-logN(x))^2 error over all x.
+
+ return logN;
+}
+
+
+/*
+ expN(x) = 2^(a*x), where a = log2(e) ~= 1.442695
+
+ Input: Q8 (int16_t)
+ Output: Q17 (int32_t)
+
+ a = log2(e) = log2(exp(1)) ~= 1.442695 ==> a = 23637 in Q14 (1.442688)
+ To this value, 700 is added or subtracted in order to get an average error
+ nearer zero, instead of always same-sign.
+*/
+
+static int32_t CalcExpN(int16_t x) {
+ int16_t axINT, axFRAC;
+ int16_t exp16;
+ int32_t exp;
+ int16_t ax = (int16_t)(x * 23637 >> 14); // Q8
+
+ if (x>=0) {
+ axINT = ax >> 8; //Q0
+ axFRAC = ax&0x00FF;
+ exp16 = 1 << axINT; // Q0
+ axFRAC = axFRAC+256; //Q8
+ exp = exp16 * axFRAC; // Q0*Q8 = Q8
+ exp <<= 9; // Q17
+ } else {
+ ax = -ax;
+ axINT = 1 + (ax >> 8); //Q0
+ axFRAC = 0x00FF - (ax&0x00FF);
+ exp16 = (int16_t)(32768 >> axINT); // Q15
+ axFRAC = axFRAC+256; //Q8
+ exp = exp16 * axFRAC; // Q15*Q8 = Q23
+ exp >>= 6; // Q17
+ }
+
+ return exp;
+}
+
+
+/* compute correlation from power spectrum */
+static void CalcCorrelation(int32_t *PSpecQ12, int32_t *CorrQ7)
+{
+ int32_t summ[FRAMESAMPLES/8];
+ int32_t diff[FRAMESAMPLES/8];
+ int32_t sum;
+ int k, n;
+
+ for (k = 0; k < FRAMESAMPLES/8; k++) {
+ summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES / 4 - 1 - k] + 16) >> 5;
+ diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES / 4 - 1 - k] + 16) >> 5;
+ }
+
+ sum = 2;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += summ[n];
+ CorrQ7[0] = sum;
+
+ for (k = 0; k < AR_ORDER; k += 2) {
+ sum = 0;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += (WebRtcIsacfix_kCos[k][n] * diff[n] + 256) >> 9;
+ CorrQ7[k+1] = sum;
+ }
+
+ for (k=1; k<AR_ORDER; k+=2) {
+ sum = 0;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += (WebRtcIsacfix_kCos[k][n] * summ[n] + 256) >> 9;
+ CorrQ7[k+1] = sum;
+ }
+}
+
+// Some arithmetic operations that are allowed to overflow. (It's still
+// undefined behavior, so not a good idea; this just makes UBSan ignore the
+// violations, so that our old code can continue to do what it's always been
+// doing.)
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+ OverflowingMulS16S32ToS32(int16_t a, int32_t b) {
+ return a * b;
+}
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+ OverflowingAddS32S32ToS32(int32_t a, int32_t b) {
+ return a + b;
+}
+static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
+ OverflowingSubS32S32ToS32(int32_t a, int32_t b) {
+ return a - b;
+}
+
+/* compute inverse AR power spectrum */
+static void CalcInvArSpec(const int16_t *ARCoefQ12,
+ const int32_t gainQ10,
+ int32_t *CurveQ16)
+{
+ int32_t CorrQ11[AR_ORDER+1];
+ int32_t sum, tmpGain;
+ int32_t diffQ16[FRAMESAMPLES/8];
+ const int16_t *CS_ptrQ9;
+ int k, n;
+ int16_t round, shftVal = 0, sh;
+
+ sum = 0;
+ for (n = 0; n < AR_ORDER+1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]); /* Q24 */
+ sum = ((sum >> 6) * 65 + 32768) >> 16; /* Result in Q8. */
+ CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
+
+ /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
+ if(gainQ10>400000){
+ tmpGain = gainQ10 >> 3;
+ round = 32;
+ shftVal = 6;
+ } else {
+ tmpGain = gainQ10;
+ round = 256;
+ shftVal = 9;
+ }
+
+ for (k = 1; k < AR_ORDER+1; k++) {
+ sum = 16384;
+ for (n = k; n < AR_ORDER+1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]); /* Q24 */
+ sum >>= 15;
+ CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
+ }
+ sum = CorrQ11[0] << 7;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ CurveQ16[n] = sum;
+
+ for (k = 1; k < AR_ORDER; k += 2) {
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ CurveQ16[n] +=
+ (OverflowingMulS16S32ToS32(WebRtcIsacfix_kCos[k][n], CorrQ11[k + 1]) +
+ 2) >>
+ 2;
+ }
+
+ CS_ptrQ9 = WebRtcIsacfix_kCos[0];
+
+ /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
+ sh=WebRtcSpl_NormW32(CorrQ11[1]);
+ if (CorrQ11[1]==0) /* Use next correlation */
+ sh=WebRtcSpl_NormW32(CorrQ11[2]);
+
+ if (sh<9)
+ shftVal = 9 - sh;
+ else
+ shftVal = 0;
+
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
+ for (k = 2; k < AR_ORDER; k += 2) {
+ CS_ptrQ9 = WebRtcIsacfix_kCos[k];
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
+ }
+
+ for (k=0; k<FRAMESAMPLES/8; k++) {
+ int32_t diff_q16 = diffQ16[k] * (1 << shftVal);
+ CurveQ16[FRAMESAMPLES / 4 - 1 - k] =
+ OverflowingSubS32S32ToS32(CurveQ16[k], diff_q16);
+ CurveQ16[k] = OverflowingAddS32S32ToS32(CurveQ16[k], diff_q16);
+ }
+}
+
+static void CalcRootInvArSpec(const int16_t *ARCoefQ12,
+ const int32_t gainQ10,
+ uint16_t *CurveQ8)
+{
+ int32_t CorrQ11[AR_ORDER+1];
+ int32_t sum, tmpGain;
+ int32_t summQ16[FRAMESAMPLES/8];
+ int32_t diffQ16[FRAMESAMPLES/8];
+
+ const int16_t *CS_ptrQ9;
+ int k, n, i;
+ int16_t round, shftVal = 0, sh;
+ int32_t res, in_sqrt, newRes;
+
+ sum = 0;
+ for (n = 0; n < AR_ORDER+1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]); /* Q24 */
+ sum = ((sum >> 6) * 65 + 32768) >> 16; /* Result in Q8. */
+ CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
+
+ /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
+ if(gainQ10>400000){
+ tmpGain = gainQ10 >> 3;
+ round = 32;
+ shftVal = 6;
+ } else {
+ tmpGain = gainQ10;
+ round = 256;
+ shftVal = 9;
+ }
+
+ for (k = 1; k < AR_ORDER+1; k++) {
+ sum = 16384;
+ for (n = k; n < AR_ORDER+1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]); /* Q24 */
+ sum >>= 15;
+ CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
+ }
+ sum = CorrQ11[0] << 7;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ summQ16[n] = sum;
+
+ for (k = 1; k < (AR_ORDER); k += 2) {
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ summQ16[n] += ((CorrQ11[k + 1] * WebRtcIsacfix_kCos[k][n]) + 2) >> 2;
+ }
+
+ CS_ptrQ9 = WebRtcIsacfix_kCos[0];
+
+ /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
+ sh=WebRtcSpl_NormW32(CorrQ11[1]);
+ if (CorrQ11[1]==0) /* Use next correlation */
+ sh=WebRtcSpl_NormW32(CorrQ11[2]);
+
+ if (sh<9)
+ shftVal = 9 - sh;
+ else
+ shftVal = 0;
+
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
+ for (k = 2; k < AR_ORDER; k += 2) {
+ CS_ptrQ9 = WebRtcIsacfix_kCos[k];
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
+ }
+
+ in_sqrt = summQ16[0] + (diffQ16[0] << shftVal);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(in_sqrt) >> 1);
+
+ for (k = 0; k < FRAMESAMPLES/8; k++)
+ {
+ in_sqrt = summQ16[k] + (diffQ16[k] << shftVal);
+ i = 10;
+
+ /* make in_sqrt positive to prohibit sqrt of negative values */
+ if(in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ CurveQ8[k] = (int16_t)newRes;
+ }
+ for (k = FRAMESAMPLES/8; k < FRAMESAMPLES/4; k++) {
+
+ in_sqrt = summQ16[FRAMESAMPLES / 4 - 1 - k] -
+ (diffQ16[FRAMESAMPLES / 4 - 1 - k] << shftVal);
+ i = 10;
+
+ /* make in_sqrt positive to prohibit sqrt of negative values */
+ if(in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ CurveQ8[k] = (int16_t)newRes;
+ }
+
+}
+
+
+
+/* generate array of dither samples in Q7 */
+static void GenerateDitherQ7(int16_t *bufQ7,
+ uint32_t seed,
+ int16_t length,
+ int16_t AvgPitchGain_Q12)
+{
+ int k;
+ int16_t dither1_Q7, dither2_Q7, dither_gain_Q14, shft;
+
+ if (AvgPitchGain_Q12 < 614) /* this threshold should be equal to that in decode_spec() */
+ {
+ for (k = 0; k < length-2; k += 3)
+ {
+ /* new random unsigned int32_t */
+ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 (Q7) */
+ dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ /* new random unsigned int32_t */
+ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 */
+ dither2_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 15);
+ if (shft < 5)
+ {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k+1] = dither2_Q7;
+ bufQ7[k+2] = 0;
+ }
+ else if (shft < 10)
+ {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k+1] = 0;
+ bufQ7[k+2] = dither2_Q7;
+ }
+ else
+ {
+ bufQ7[k] = 0;
+ bufQ7[k+1] = dither1_Q7;
+ bufQ7[k+2] = dither2_Q7;
+ }
+ }
+ }
+ else
+ {
+ dither_gain_Q14 = (int16_t)(22528 - WEBRTC_SPL_MUL(10, AvgPitchGain_Q12));
+
+ /* dither on half of the coefficients */
+ for (k = 0; k < length-1; k += 2)
+ {
+ /* new random unsigned int32_t */
+ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 */
+ dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ /* dither sample is placed in either even or odd index */
+ shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 1); /* either 0 or 1 */
+
+ bufQ7[k + shft] = (int16_t)((dither_gain_Q14 * dither1_Q7 + 8192) >> 14);
+ bufQ7[k + 1 - shft] = 0;
+ }
+ }
+}
+
+
+
+
+/*
+ * function to decode the complex spectrum from the bitstream
+ * returns the total number of bytes in the stream
+ */
+int WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
+ int16_t *frQ7,
+ int16_t *fiQ7,
+ int16_t AvgPitchGain_Q12)
+{
+ int16_t data[FRAMESAMPLES];
+ int32_t invARSpec2_Q16[FRAMESAMPLES/4];
+ int16_t ARCoefQ12[AR_ORDER+1];
+ int16_t RCQ15[AR_ORDER];
+ int16_t gainQ10;
+ int32_t gain2_Q10;
+ int len;
+ int k;
+
+ /* create dither signal */
+ GenerateDitherQ7(data, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* Dither is output in vector 'Data' */
+
+ /* decode model parameters */
+ if (WebRtcIsacfix_DecodeRcCoef(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsacfix_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* compute inverse AR power spectrum */
+ CalcInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* arithmetic decoding of spectrum */
+ /* 'data' input and output. Input = Dither */
+ len = WebRtcIsacfix_DecLogisticMulti2(data, streamdata, invARSpec2_Q16, (int16_t)FRAMESAMPLES);
+
+ if (len<1)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* subtract dither and scale down spectral samples with low SNR */
+ if (AvgPitchGain_Q12 <= 614)
+ {
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(30 << 10,
+ (int16_t)((uint32_t)(invARSpec2_Q16[k >> 2] + 2195456) >> 16));
+ *frQ7++ = (int16_t)((data[k] * gainQ10 + 512) >> 10);
+ *fiQ7++ = (int16_t)((data[k + 1] * gainQ10 + 512) >> 10);
+ *frQ7++ = (int16_t)((data[k + 2] * gainQ10 + 512) >> 10);
+ *fiQ7++ = (int16_t)((data[k + 3] * gainQ10 + 512) >> 10);
+ }
+ }
+ else
+ {
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(36 << 10,
+ (int16_t)((uint32_t)(invARSpec2_Q16[k >> 2] + 2654208) >> 16));
+ *frQ7++ = (int16_t)((data[k] * gainQ10 + 512) >> 10);
+ *fiQ7++ = (int16_t)((data[k + 1] * gainQ10 + 512) >> 10);
+ *frQ7++ = (int16_t)((data[k + 2] * gainQ10 + 512) >> 10);
+ *fiQ7++ = (int16_t)((data[k + 3] * gainQ10 + 512) >> 10);
+ }
+ }
+
+ return len;
+}
+
+
+int WebRtcIsacfix_EncodeSpec(const int16_t *fr,
+ const int16_t *fi,
+ Bitstr_enc *streamdata,
+ int16_t AvgPitchGain_Q12)
+{
+ int16_t dataQ7[FRAMESAMPLES];
+ int32_t PSpec[FRAMESAMPLES/4];
+ uint16_t invARSpecQ8[FRAMESAMPLES/4];
+ int32_t CorrQ7[AR_ORDER+1];
+ int32_t CorrQ7_norm[AR_ORDER+1];
+ int16_t RCQ15[AR_ORDER];
+ int16_t ARCoefQ12[AR_ORDER+1];
+ int32_t gain2_Q10;
+ int16_t val;
+ int32_t nrg;
+ uint32_t sum;
+ int16_t lft_shft;
+ int16_t status;
+ int k, n, j;
+
+
+ /* create dither_float signal */
+ GenerateDitherQ7(dataQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
+
+ /* add dither and quantize, and compute power spectrum */
+ /* Vector dataQ7 contains Dither in Q7 */
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ val = ((*fr++ + dataQ7[k] + 64) & 0xFF80) - dataQ7[k]; /* Data = Dither */
+ dataQ7[k] = val; /* New value in Data */
+ sum = WEBRTC_SPL_UMUL(val, val);
+
+ val = ((*fi++ + dataQ7[k+1] + 64) & 0xFF80) - dataQ7[k+1]; /* Data = Dither */
+ dataQ7[k+1] = val; /* New value in Data */
+ sum += WEBRTC_SPL_UMUL(val, val);
+
+ val = ((*fr++ + dataQ7[k+2] + 64) & 0xFF80) - dataQ7[k+2]; /* Data = Dither */
+ dataQ7[k+2] = val; /* New value in Data */
+ sum += WEBRTC_SPL_UMUL(val, val);
+
+ val = ((*fi++ + dataQ7[k+3] + 64) & 0xFF80) - dataQ7[k+3]; /* Data = Dither */
+ dataQ7[k+3] = val; /* New value in Data */
+ sum += WEBRTC_SPL_UMUL(val, val);
+
+ PSpec[k>>2] = WEBRTC_SPL_RSHIFT_U32(sum, 2);
+ }
+
+ /* compute correlation from power spectrum */
+ CalcCorrelation(PSpec, CorrQ7);
+
+
+ /* find AR coefficients */
+ /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
+ lft_shft = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (lft_shft > 0) {
+ for (k=0; k<AR_ORDER+1; k++)
+ CorrQ7_norm[k] = CorrQ7[k] << lft_shft;
+ } else {
+ for (k=0; k<AR_ORDER+1; k++)
+ CorrQ7_norm[k] = CorrQ7[k] >> -lft_shft;
+ }
+
+ /* find RC coefficients */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* quantize & code RC Coef */
+ status = WebRtcIsacfix_EncodeRcCoef(RCQ15, streamdata);
+ if (status < 0) {
+ return status;
+ }
+
+ /* RC -> AR coefficients */
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ /* compute ARCoef' * Corr * ARCoef in Q19 */
+ nrg = 0;
+ for (j = 0; j <= AR_ORDER; j++) {
+ for (n = 0; n <= j; n++)
+ nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
+ 4) >> 3;
+ for (n = j+1; n <= AR_ORDER; n++)
+ nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
+ 4) >> 3;
+ }
+
+ if (lft_shft > 0)
+ nrg >>= lft_shft;
+ else
+ nrg <<= -lft_shft;
+
+ if(nrg>131072)
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES >> 2, nrg); /* also shifts 31 bits to the left! */
+ else
+ gain2_Q10 = FRAMESAMPLES >> 2;
+
+ /* quantize & code gain2_Q10 */
+ if (WebRtcIsacfix_EncodeGain2(&gain2_Q10, streamdata))
+ return -1;
+
+ /* compute inverse AR magnitude spectrum */
+ CalcRootInvArSpec(ARCoefQ12, gain2_Q10, invARSpecQ8);
+
+
+ /* arithmetic coding of spectrum */
+ status = WebRtcIsacfix_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (int16_t)FRAMESAMPLES);
+ if ( status )
+ return( status );
+
+ return 0;
+}
+
+
+/* Matlab's LAR definition */
+static void Rc2LarFix(const int16_t *rcQ15, int32_t *larQ17, int16_t order) {
+
+ /*
+
+ This is a piece-wise implemenetation of a rc2lar-function (all values in the comment
+ are Q15 values and are based on [0 24956/32768 30000/32768 32500/32768], i.e.
+ [0.76159667968750 0.91552734375000 0.99182128906250]
+
+ x0 x1 a k x0(again) b
+ ==================================================================================
+ 0.00 0.76: 0 2.625997508581 0 0
+ 0.76 0.91: 2.000012018559 7.284502668663 0.761596679688 -3.547841027073
+ 0.91 0.99: 3.121320351712 31.115835041229 0.915527343750 -25.366077452148
+ 0.99 1.00: 5.495270168700 686.663805654056 0.991821289063 -675.552510708011
+
+ The implementation is y(x)= a + (x-x0)*k, but this can be simplified to
+
+ y(x) = a-x0*k + x*k = b + x*k, where b = a-x0*k
+
+ akx=[0 2.625997508581 0
+ 2.000012018559 7.284502668663 0.761596679688
+ 3.121320351712 31.115835041229 0.915527343750
+ 5.495270168700 686.663805654056 0.991821289063];
+
+ b = akx(:,1) - akx(:,3).*akx(:,2)
+
+ [ 0.0
+ -3.547841027073
+ -25.366077452148
+ -675.552510708011]
+
+ */
+
+ int k;
+ int16_t rc;
+ int32_t larAbsQ17;
+
+ for (k = 0; k < order; k++) {
+
+ rc = WEBRTC_SPL_ABS_W16(rcQ15[k]); //Q15
+
+ /* Calculate larAbsQ17 in Q17 from rc in Q15 */
+
+ if (rc<24956) { //0.7615966 in Q15
+ // (Q15*Q13)>>11 = Q17
+ larAbsQ17 = rc * 21512 >> 11;
+ } else if (rc<30000) { //0.91552734375 in Q15
+ // Q17 + (Q15*Q12)>>10 = Q17
+ larAbsQ17 = -465024 + (rc * 29837 >> 10);
+ } else if (rc<32500) { //0.99182128906250 in Q15
+ // Q17 + (Q15*Q10)>>8 = Q17
+ larAbsQ17 = -3324784 + (rc * 31863 >> 8);
+ } else {
+ // Q17 + (Q15*Q5)>>3 = Q17
+ larAbsQ17 = -88546020 + (rc * 21973 >> 3);
+ }
+
+ if (rcQ15[k]>0) {
+ larQ17[k] = larAbsQ17;
+ } else {
+ larQ17[k] = -larAbsQ17;
+ }
+ }
+}
+
+
+static void Lar2RcFix(const int32_t *larQ17, int16_t *rcQ15, int16_t order) {
+
+ /*
+ This is a piece-wise implemenetation of a lar2rc-function
+ See comment in Rc2LarFix() about details.
+ */
+
+ int k;
+ int16_t larAbsQ11;
+ int32_t rc;
+
+ for (k = 0; k < order; k++) {
+
+ larAbsQ11 = (int16_t)WEBRTC_SPL_ABS_W32((larQ17[k] + 32) >> 6); // Q11
+
+ if (larAbsQ11<4097) { //2.000012018559 in Q11
+ // Q11*Q16>>12 = Q15
+ rc = larAbsQ11 * 24957 >> 12;
+ } else if (larAbsQ11<6393) { //3.121320351712 in Q11
+ // (Q11*Q17 + Q13)>>13 = Q15
+ rc = (larAbsQ11 * 17993 + 130738688) >> 13;
+ } else if (larAbsQ11<11255) { //5.495270168700 in Q11
+ // (Q11*Q19 + Q30)>>15 = Q15
+ rc = (larAbsQ11 * 16850 + 875329820) >> 15;
+ } else {
+ // (Q11*Q24>>16 + Q19)>>4 = Q15
+ rc = (((larAbsQ11 * 24433) >> 16) + 515804) >> 4;
+ }
+
+ if (larQ17[k]<=0) {
+ rc = -rc;
+ }
+
+ rcQ15[k] = (int16_t) rc; // Q15
+ }
+}
+
+static void Poly2LarFix(int16_t *lowbandQ15,
+ int16_t orderLo,
+ int16_t *hibandQ15,
+ int16_t orderHi,
+ int16_t Nsub,
+ int32_t *larsQ17) {
+
+ int k, n;
+ int32_t *outpQ17;
+ int16_t orderTot;
+ int32_t larQ17[MAX_ORDER]; // Size 7+6 is enough
+
+ orderTot = (orderLo + orderHi);
+ outpQ17 = larsQ17;
+ for (k = 0; k < Nsub; k++) {
+
+ Rc2LarFix(lowbandQ15, larQ17, orderLo);
+
+ for (n = 0; n < orderLo; n++)
+ outpQ17[n] = larQ17[n]; //Q17
+
+ Rc2LarFix(hibandQ15, larQ17, orderHi);
+
+ for (n = 0; n < orderHi; n++)
+ outpQ17[n + orderLo] = larQ17[n]; //Q17;
+
+ outpQ17 += orderTot;
+ lowbandQ15 += orderLo;
+ hibandQ15 += orderHi;
+ }
+}
+
+
+static void Lar2polyFix(int32_t *larsQ17,
+ int16_t *lowbandQ15,
+ int16_t orderLo,
+ int16_t *hibandQ15,
+ int16_t orderHi,
+ int16_t Nsub) {
+
+ int k, n;
+ int16_t orderTot;
+ int16_t *outplQ15, *outphQ15;
+ int32_t *inpQ17;
+ int16_t rcQ15[7+6];
+
+ orderTot = (orderLo + orderHi);
+ outplQ15 = lowbandQ15;
+ outphQ15 = hibandQ15;
+ inpQ17 = larsQ17;
+ for (k = 0; k < Nsub; k++) {
+
+ /* gains not handled here as in the FLP version */
+
+ /* Low band */
+ Lar2RcFix(&inpQ17[0], rcQ15, orderLo);
+ for (n = 0; n < orderLo; n++)
+ outplQ15[n] = rcQ15[n]; // Refl. coeffs
+
+ /* High band */
+ Lar2RcFix(&inpQ17[orderLo], rcQ15, orderHi);
+ for (n = 0; n < orderHi; n++)
+ outphQ15[n] = rcQ15[n]; // Refl. coeffs
+
+ inpQ17 += orderTot;
+ outplQ15 += orderLo;
+ outphQ15 += orderHi;
+ }
+}
+
+/*
+Function WebRtcIsacfix_MatrixProduct1C() does one form of matrix multiplication.
+It first shifts input data of one matrix, determines the right indexes for the
+two matrixes, multiply them, and write the results into an output buffer.
+
+Note that two factors (or, multipliers) determine the initialization values of
+the variable `matrix1_index` in the code. The relationship is
+`matrix1_index` = `matrix1_index_factor1` * `matrix1_index_factor2`, where
+`matrix1_index_factor1` is given by the argument while `matrix1_index_factor2`
+is determined by the value of argument `matrix1_index_init_case`;
+`matrix1_index_factor2` is the value of the outmost loop counter j (when
+`matrix1_index_init_case` is 0), or the value of the middle loop counter k (when
+`matrix1_index_init_case` is non-zero).
+
+`matrix0_index` is determined the same way.
+
+Arguments:
+ matrix0[]: matrix0 data in Q15 domain.
+ matrix1[]: matrix1 data.
+ matrix_product[]: output data (matrix product).
+ matrix1_index_factor1: The first of two factors determining the
+ initialization value of matrix1_index.
+ matrix0_index_factor1: The first of two factors determining the
+ initialization value of matrix0_index.
+ matrix1_index_init_case: Case number for selecting the second of two
+ factors determining the initialization value
+ of matrix1_index and matrix0_index.
+ matrix1_index_step: Incremental step for matrix1_index.
+ matrix0_index_step: Incremental step for matrix0_index.
+ inner_loop_count: Maximum count of the inner loop.
+ mid_loop_count: Maximum count of the intermediate loop.
+ shift: Left shift value for matrix1.
+*/
+void WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ const int matrix1_index_factor1,
+ const int matrix0_index_factor1,
+ const int matrix1_index_init_case,
+ const int matrix1_index_step,
+ const int matrix0_index_step,
+ const int inner_loop_count,
+ const int mid_loop_count,
+ const int shift) {
+ int j = 0, k = 0, n = 0;
+ int matrix0_index = 0, matrix1_index = 0, matrix_prod_index = 0;
+ int* matrix0_index_factor2 = &k;
+ int* matrix1_index_factor2 = &j;
+ if (matrix1_index_init_case != 0) {
+ matrix0_index_factor2 = &j;
+ matrix1_index_factor2 = &k;
+ }
+
+ for (j = 0; j < SUBFRAMES; j++) {
+ matrix_prod_index = mid_loop_count * j;
+ for (k = 0; k < mid_loop_count; k++) {
+ int32_t sum32 = 0;
+ matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
+ matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
+ for (n = 0; n < inner_loop_count; n++) {
+ sum32 += WEBRTC_SPL_MUL_16_32_RSFT16(
+ matrix0[matrix0_index], matrix1[matrix1_index] * (1 << shift));
+ matrix0_index += matrix0_index_step;
+ matrix1_index += matrix1_index_step;
+ }
+ matrix_product[matrix_prod_index] = sum32;
+ matrix_prod_index++;
+ }
+ }
+}
+
+/*
+Function WebRtcIsacfix_MatrixProduct2C() returns the product of two matrixes,
+one of which has two columns. It first has to determine the correct index of
+the first matrix before doing the actual element multiplication.
+
+Arguments:
+ matrix0[]: A matrix in Q15 domain.
+ matrix1[]: A matrix in Q21 domain.
+ matrix_product[]: Output data in Q17 domain.
+ matrix0_index_factor: A factor determining the initialization value
+ of matrix0_index.
+ matrix0_index_step: Incremental step for matrix0_index.
+*/
+void WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ const int matrix0_index_factor,
+ const int matrix0_index_step) {
+ int j = 0, n = 0;
+ int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ int32_t sum32 = 0, sum32_2 = 0;
+ matrix1_index = 0;
+ matrix0_index = matrix0_index_factor * j;
+ for (n = SUBFRAMES; n > 0; n--) {
+ sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
+ matrix1[matrix1_index]));
+ sum32_2 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
+ matrix1[matrix1_index + 1]));
+ matrix1_index += 2;
+ matrix0_index += matrix0_index_step;
+ }
+ matrix_product[matrix_prod_index] = sum32 >> 3;
+ matrix_product[matrix_prod_index + 1] = sum32_2 >> 3;
+ matrix_prod_index += 2;
+ }
+}
+
+int WebRtcIsacfix_DecodeLpc(int32_t *gain_lo_hiQ17,
+ int16_t *LPCCoef_loQ15,
+ int16_t *LPCCoef_hiQ15,
+ Bitstr_dec *streamdata,
+ int16_t *outmodel) {
+
+ int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_GAIN+KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
+ int err;
+
+ err = WebRtcIsacfix_DecodeLpcCoef(streamdata, larsQ17, gain_lo_hiQ17, outmodel);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_LPC;
+
+ Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
+
+ return 0;
+}
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
+ int32_t *LPCCoefQ17,
+ int32_t *gain_lo_hiQ17,
+ int16_t *outmodel)
+{
+ int j, k, n;
+ int err;
+ int16_t pos, pos2, posg, poss;
+ int16_t gainpos;
+ int16_t model;
+ int16_t index_QQ[KLT_ORDER_SHAPE];
+ int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ int16_t tmpcoeffs_sQ10[KLT_ORDER_SHAPE];
+ int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
+ int32_t tmpcoeffs2_sQ18[KLT_ORDER_SHAPE];
+ int32_t sumQQ;
+ int16_t sumQQ16;
+ int32_t tmp32;
+
+
+
+ /* entropy decoding of model number */
+ err = WebRtcIsacfix_DecHistOneStepMulti(&model, streamdata, WebRtcIsacfix_kModelCdfPtr, WebRtcIsacfix_kModelInitIndex, 1);
+ if (err<0) // error check
+ return err;
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfShapePtr[model], WebRtcIsacfix_kInitIndexShape[model], KLT_ORDER_SHAPE);
+ if (err<0) // error check
+ return err;
+ /* find quantization levels for coefficients */
+ for (k=0; k<KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_sQ10[WebRtcIsacfix_kSelIndShape[k]] = WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[model]+WebRtcIsacfix_kOffsetShape[model][k] + index_QQ[k]];
+ }
+
+ err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfGainPtr[model], WebRtcIsacfix_kInitIndexGain[model], KLT_ORDER_GAIN);
+ if (err<0) // error check
+ return err;
+ /* find quantization levels for coefficients */
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[model]+ WebRtcIsacfix_kOffsetGain[model][k] + index_QQ[k]];
+ }
+
+
+ /* inverse KLT */
+
+ /* left transform */ // Transpose matrix!
+ WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1GainQ15[model], tmpcoeffs_gQ17,
+ tmpcoeffs2_gQ21, kTIndexFactor2, kTIndexFactor2,
+ kTInitCase0, kTIndexStep1, kTIndexStep1,
+ kTLoopCount2, kTLoopCount2, kTMatrix1_shift5);
+
+ poss = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ for (k=0; k<LPC_SHAPE_ORDER; k++) {
+ sumQQ = 0;
+ pos = LPC_SHAPE_ORDER * j;
+ pos2 = LPC_SHAPE_ORDER * k;
+ for (n=0; n<LPC_SHAPE_ORDER; n++) {
+ sumQQ += tmpcoeffs_sQ10[pos] *
+ WebRtcIsacfix_kT1ShapeQ15[model][pos2] >> 7; // (Q10*Q15)>>7 = Q18
+ pos++;
+ pos2++;
+ }
+ tmpcoeffs2_sQ18[poss] = sumQQ; //Q18
+ poss++;
+ }
+ }
+
+ /* right transform */ // Transpose matrix
+ WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+ tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
+ WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[model],
+ tmpcoeffs2_sQ18, tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1,
+ kTInitCase1, kTIndexStep3, kTIndexStep2, kTLoopCount1, kTLoopCount3,
+ kTMatrix1_shift0);
+
+ /* scaling, mean addition, and gain restoration */
+ gainpos = 0;
+ posg = 0;poss = 0;pos=0;
+ for (k=0; k<SUBFRAMES; k++) {
+
+ /* log gains */
+ // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
+ sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
+ sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
+ sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+ gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+ gainpos++;
+ posg++;
+
+ // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
+ sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
+ sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
+ sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+ gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+ gainpos++;
+ posg++;
+
+ /* lo band LAR coeffs */
+ for (n=0; n<ORDERLO; n++, pos++, poss++) {
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+
+ /* hi band LAR coeffs */
+ for (n=0; n<ORDERHI; n++, pos++, poss++) {
+ // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
+ tmp32 =
+ WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]) * (1 << 3);
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+ }
+
+
+ *outmodel=model;
+
+ return 0;
+}
+
+/* estimate codel length of LPC Coef */
+static int EstCodeLpcCoef(int32_t *LPCCoefQ17,
+ int32_t *gain_lo_hiQ17,
+ int16_t *model,
+ int32_t *sizeQ11,
+ Bitstr_enc *streamdata,
+ IsacSaveEncoderData* encData,
+ transcode_obj *transcodingParam) {
+ int j, k, n;
+ int16_t posQQ, pos2QQ, gainpos;
+ int16_t pos, poss, posg, offsg;
+ int16_t index_gQQ[KLT_ORDER_GAIN], index_sQQ[KLT_ORDER_SHAPE];
+ int16_t index_ovr_gQQ[KLT_ORDER_GAIN], index_ovr_sQQ[KLT_ORDER_SHAPE];
+ int32_t BitsQQ;
+
+ int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
+ int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs2_sQ17[KLT_ORDER_SHAPE];
+ int32_t sumQQ;
+ int32_t tmp32;
+ int16_t sumQQ16;
+ int status = 0;
+
+ /* write LAR coefficients to statistics file */
+ /* Save data for creation of multiple bitstreams (and transcoding) */
+ if (encData != NULL) {
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
+ }
+ }
+
+ /* log gains, mean removal and scaling */
+ posg = 0;poss = 0;pos=0; gainpos=0;
+
+ for (k=0; k<SUBFRAMES; k++) {
+ /* log gains */
+
+ /* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ /* lo band LAR coeffs */
+ for (n=0; n<ORDERLO; n++, poss++, pos++) {
+ tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(17203, tmp32<<3); // tmp32 = 2.1*tmp32
+ tmpcoeffs_sQ17[poss] = tmp32; //Q17
+ }
+
+ /* hi band LAR coeffs */
+ for (n=0; n<ORDERHI; n++, poss++, pos++) {
+ tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(14746, tmp32<<1); // tmp32 = 0.45*tmp32
+ tmpcoeffs_sQ17[poss] = tmp32; //Q17
+ }
+
+ }
+
+
+ /* KLT */
+
+ /* left transform */
+ offsg = 0;
+ posg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ // Q21 = Q6 * Q15
+ sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][0] +
+ tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+
+ // Q21 = Q6 * Q15
+ sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][1] +
+ tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+
+ offsg += 2;
+ }
+
+ WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
+ tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor1, kTInitCase0,
+ kTIndexStep1, kTIndexStep3, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
+
+ /* right transform */
+ WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+ tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
+
+ WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
+ tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor3, kTInitCase1, kTIndexStep3,
+ kTIndexStep1, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
+
+ /* quantize coefficients */
+
+ BitsQQ = 0;
+ for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+ {
+ posQQ = WebRtcIsacfix_kSelIndGain[k];
+ pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+ index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+ if (index_gQQ[k] < 0) {
+ index_gQQ[k] = 0;
+ }
+ else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+ index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+ }
+ index_ovr_gQQ[k] = WebRtcIsacfix_kOffsetGain[0][k]+index_gQQ[k];
+ posQQ = WebRtcIsacfix_kOfLevelsGain[0] + index_ovr_gQQ[k];
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
+ }
+
+ /* determine number of bits */
+ sumQQ = WebRtcIsacfix_kCodeLenGainQ11[posQQ]; //Q11
+ BitsQQ += sumQQ;
+ }
+
+ for (k=0; k<KLT_ORDER_SHAPE; k++) //ATTN: ok?
+ {
+ index_sQQ[k] = (int16_t)(CalcLrIntQ(tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]], 17) + WebRtcIsacfix_kQuantMinShape[k]); //ATTN: ok?
+
+ if (index_sQQ[k] < 0)
+ index_sQQ[k] = 0;
+ else if (index_sQQ[k] > WebRtcIsacfix_kMaxIndShape[k])
+ index_sQQ[k] = WebRtcIsacfix_kMaxIndShape[k];
+ index_ovr_sQQ[k] = WebRtcIsacfix_kOffsetShape[0][k]+index_sQQ[k];
+
+ posQQ = WebRtcIsacfix_kOfLevelsShape[0] + index_ovr_sQQ[k];
+ sumQQ = WebRtcIsacfix_kCodeLenShapeQ11[posQQ]; //Q11
+ BitsQQ += sumQQ;
+ }
+
+
+
+ *model = 0;
+ *sizeQ11=BitsQQ;
+
+ /* entropy coding of model number */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, model, WebRtcIsacfix_kModelCdfPtr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* entropy coding of quantization indices - shape only */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index_sQQ, WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ for (k=0; k<KLT_ORDER_SHAPE; k++)
+ {
+ encData->LPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_sQQ[k];
+ }
+ }
+ /* save the state of the bitstream object 'streamdata' for the possible bit-rate reduction */
+ transcodingParam->full = streamdata->full;
+ transcodingParam->stream_index = streamdata->stream_index;
+ transcodingParam->streamval = streamdata->streamval;
+ transcodingParam->W_upper = streamdata->W_upper;
+ transcodingParam->beforeLastWord = streamdata->stream[streamdata->stream_index-1];
+ transcodingParam->lastWord = streamdata->stream[streamdata->stream_index];
+
+ /* entropy coding of index */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+ if (status < 0) {
+ return status;
+ }
+
+ /* find quantization levels for shape coefficients */
+ for (k=0; k<KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]] = WEBRTC_SPL_MUL(128, WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[0]+index_ovr_sQQ[k]]);
+
+ }
+ /* inverse KLT */
+
+ /* left transform */ // Transpose matrix!
+ WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
+ tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor4, kTInitCase0,
+ kTIndexStep1, kTIndexStep1, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
+
+ /* right transform */ // Transpose matrix
+ WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
+ tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1, kTInitCase1, kTIndexStep3,
+ kTIndexStep2, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
+
+ /* scaling, mean addition, and gain restoration */
+ poss = 0;pos=0;
+ for (k=0; k<SUBFRAMES; k++) {
+
+ /* lo band LAR coeffs */
+ for (n=0; n<ORDERLO; n++, pos++, poss++) {
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+
+ /* hi band LAR coeffs */
+ for (n=0; n<ORDERHI; n++, pos++, poss++) {
+ // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]) << 3;
+ tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
+ LPCCoefQ17[pos] = tmp32;
+ }
+
+ }
+
+ //to update tmpcoeffs_gQ17 to the proper state
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[0]+index_ovr_gQQ[k]];
+ }
+
+
+
+ /* find quantization levels for coefficients */
+
+ /* left transform */
+ offsg = 0;
+ posg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ // (Q15 * Q17) >> (16 - 1) = Q17; Q17 << 4 = Q21.
+ sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][0],
+ tmpcoeffs_gQ17[offsg]) << 1);
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][1],
+ tmpcoeffs_gQ17[offsg + 1]) << 1);
+ tmpcoeffs2_gQ21[posg] = sumQQ << 4;
+ posg++;
+
+ sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][2],
+ tmpcoeffs_gQ17[offsg]) << 1);
+ sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][3],
+ tmpcoeffs_gQ17[offsg + 1]) << 1);
+ tmpcoeffs2_gQ21[posg] = sumQQ << 4;
+ posg++;
+ offsg += 2;
+ }
+
+ /* right transform */ // Transpose matrix
+ WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+ tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
+
+ /* scaling, mean addition, and gain restoration */
+ posg = 0;
+ gainpos = 0;
+ for (k=0; k<2*SUBFRAMES; k++) {
+
+ // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
+ sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
+ sumQQ16 += WebRtcIsacfix_kMeansGainQ8[0][posg];
+ sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
+ gain_lo_hiQ17[gainpos] = sumQQ; //Q17
+
+ gainpos++;
+ pos++;posg++;
+ }
+
+ return 0;
+}
+
+int WebRtcIsacfix_EstCodeLpcGain(int32_t *gain_lo_hiQ17,
+ Bitstr_enc *streamdata,
+ IsacSaveEncoderData* encData) {
+ int j, k;
+ int16_t posQQ, pos2QQ, gainpos;
+ int16_t posg;
+ int16_t index_gQQ[KLT_ORDER_GAIN];
+
+ int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ int32_t sumQQ;
+ int status = 0;
+
+ /* write LAR coefficients to statistics file */
+ /* Save data for creation of multiple bitstreams (and transcoding) */
+ if (encData != NULL) {
+ for (k=0; k<KLT_ORDER_GAIN; k++) {
+ encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
+ }
+ }
+
+ /* log gains, mean removal and scaling */
+ posg = 0; gainpos = 0;
+
+ for (k=0; k<SUBFRAMES; k++) {
+ /* log gains */
+
+ /* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+ }
+
+
+ /* KLT */
+
+ /* left transform */
+ posg = 0;
+ for (j=0; j<SUBFRAMES; j++) {
+ // Q21 = Q6 * Q15
+ sumQQ = tmpcoeffs_gQ6[j * 2] * WebRtcIsacfix_kT1GainQ15[0][0] +
+ tmpcoeffs_gQ6[j * 2 + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+
+ sumQQ = tmpcoeffs_gQ6[j * 2] * WebRtcIsacfix_kT1GainQ15[0][1] +
+ tmpcoeffs_gQ6[j * 2 + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
+ tmpcoeffs2_gQ21[posg] = sumQQ;
+ posg++;
+ }
+
+ /* right transform */
+ WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+ tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
+
+ /* quantize coefficients */
+
+ for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+ {
+ posQQ = WebRtcIsacfix_kSelIndGain[k];
+ pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+ index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+ if (index_gQQ[k] < 0) {
+ index_gQQ[k] = 0;
+ }
+ else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+ index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
+ }
+ }
+
+ /* entropy coding of index */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
+ if (status < 0) {
+ return status;
+ }
+
+ return 0;
+}
+
+
+int WebRtcIsacfix_EncodeLpc(int32_t *gain_lo_hiQ17,
+ int16_t *LPCCoef_loQ15,
+ int16_t *LPCCoef_hiQ15,
+ int16_t *model,
+ int32_t *sizeQ11,
+ Bitstr_enc *streamdata,
+ IsacSaveEncoderData* encData,
+ transcode_obj *transcodeParam)
+{
+ int status = 0;
+ int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
+ // = (6+12)*6 == 108
+
+ Poly2LarFix(LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES, larsQ17);
+
+ status = EstCodeLpcCoef(larsQ17, gain_lo_hiQ17, model, sizeQ11,
+ streamdata, encData, transcodeParam);
+ if (status < 0) {
+ return (status);
+ }
+
+ Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
+
+ return 0;
+}
+
+
+/* decode & dequantize RC */
+int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata, int16_t *RCQ15)
+{
+ int k, err;
+ int16_t index[AR_ORDER];
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsacfix_DecHistOneStepMulti(index, streamdata, WebRtcIsacfix_kRcCdfPtr, WebRtcIsacfix_kRcInitInd, AR_ORDER);
+ if (err<0) // error check
+ return err;
+
+ /* find quantization levels for reflection coefficients */
+ for (k=0; k<AR_ORDER; k++)
+ {
+ RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
+ }
+
+ return 0;
+}
+
+
+
+/* quantize & code RC */
+int WebRtcIsacfix_EncodeRcCoef(int16_t *RCQ15, Bitstr_enc *streamdata)
+{
+ int k;
+ int16_t index[AR_ORDER];
+ int status;
+
+ /* quantize reflection coefficients (add noise feedback?) */
+ for (k=0; k<AR_ORDER; k++)
+ {
+ index[k] = WebRtcIsacfix_kRcInitInd[k];
+
+ if (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k]])
+ {
+ while (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k] + 1])
+ index[k]++;
+ }
+ else
+ {
+ while (RCQ15[k] < WebRtcIsacfix_kRcBound[--index[k]]) ;
+ }
+
+ RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
+ }
+
+
+ /* entropy coding of quantization indices */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index, WebRtcIsacfix_kRcCdfPtr, AR_ORDER);
+
+ /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+ return status;
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata, int32_t *gainQ10)
+{
+ int err;
+ int16_t index;
+
+ /* entropy decoding of quantization index */
+ err = WebRtcIsacfix_DecHistOneStepMulti(
+ &index,
+ streamdata,
+ WebRtcIsacfix_kGainPtr,
+ WebRtcIsacfix_kGainInitInd,
+ 1);
+ /* error check */
+ if (err<0) {
+ return err;
+ }
+
+ /* find quantization level */
+ *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
+
+ return 0;
+}
+
+
+
+/* quantize & code squared Gain */
+int WebRtcIsacfix_EncodeGain2(int32_t *gainQ10, Bitstr_enc *streamdata)
+{
+ int16_t index;
+ int status = 0;
+
+ /* find quantization index */
+ index = WebRtcIsacfix_kGainInitInd[0];
+ if (*gainQ10 > WebRtcIsacfix_kGain2Bound[index])
+ {
+ while (*gainQ10 > WebRtcIsacfix_kGain2Bound[index + 1])
+ index++;
+ }
+ else
+ {
+ while (*gainQ10 < WebRtcIsacfix_kGain2Bound[--index]) ;
+ }
+
+ /* dequantize */
+ *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
+
+ /* entropy coding of quantization index */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, &index, WebRtcIsacfix_kGainPtr, 1);
+
+ /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+ return status;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata, int16_t *PitchGains_Q12)
+{
+ int err;
+ int16_t index_comb;
+ const uint16_t *pitch_gain_cdf_ptr[1];
+
+ /* entropy decoding of quantization indices */
+ *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+ err = WebRtcIsacfix_DecHistBisectMulti(&index_comb, streamdata, pitch_gain_cdf_ptr, WebRtcIsacfix_kCdfTableSizeGain, 1);
+ /* error check, Q_mean_Gain.. tables are of size 144 */
+ if ((err < 0) || (index_comb < 0) || (index_comb >= 144))
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
+
+ /* unquantize back to pitch gains by table look-up */
+ PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
+ PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
+ PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
+ PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
+
+ return 0;
+}
+
+
+/* quantize & code Pitch Gains */
+int WebRtcIsacfix_EncodePitchGain(int16_t* PitchGains_Q12,
+ Bitstr_enc* streamdata,
+ IsacSaveEncoderData* encData) {
+ int k,j;
+ int16_t SQ15[PITCH_SUBFRAMES];
+ int16_t index[3];
+ int16_t index_comb;
+ const uint16_t *pitch_gain_cdf_ptr[1];
+ int32_t CQ17;
+ int status = 0;
+
+
+ /* get the approximate arcsine (almost linear)*/
+ for (k=0; k<PITCH_SUBFRAMES; k++)
+ SQ15[k] = (int16_t)(PitchGains_Q12[k] * 33 >> 2); // Q15
+
+
+ /* find quantization index; only for the first three transform coefficients */
+ for (k=0; k<3; k++)
+ {
+ /* transform */
+ CQ17=0;
+ for (j=0; j<PITCH_SUBFRAMES; j++) {
+ CQ17 += WebRtcIsacfix_kTransform[k][j] * SQ15[j] >> 10; // Q17
+ }
+
+ index[k] = (int16_t)((CQ17 + 8192)>>14); // Rounding and scaling with stepsize (=1/0.125=8)
+
+ /* check that the index is not outside the boundaries of the table */
+ if (index[k] < WebRtcIsacfix_kLowerlimiGain[k]) index[k] = WebRtcIsacfix_kLowerlimiGain[k];
+ else if (index[k] > WebRtcIsacfix_kUpperlimitGain[k]) index[k] = WebRtcIsacfix_kUpperlimitGain[k];
+ index[k] -= WebRtcIsacfix_kLowerlimiGain[k];
+ }
+
+ /* calculate unique overall index */
+ index_comb = (int16_t)(WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[0], index[0]) +
+ WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[1], index[1]) + index[2]);
+
+ /* unquantize back to pitch gains by table look-up */
+ // (Y)
+ PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
+ PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
+ PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
+ PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
+
+
+ /* entropy coding of quantization pitch gains */
+ *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
+ status = WebRtcIsacfix_EncHistMulti(streamdata, &index_comb, pitch_gain_cdf_ptr, 1);
+ if (status < 0) {
+ return status;
+ }
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->pitchGain_index[encData->startIdx] = index_comb;
+ }
+
+ return 0;
+}
+
+
+
+/* Pitch LAG */
+
+
+/* decode & dequantize Pitch Lags */
+int WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
+ int16_t *PitchGain_Q12,
+ int16_t *PitchLags_Q7)
+{
+ int k, err;
+ int16_t index[PITCH_SUBFRAMES];
+ const int16_t *mean_val2Q10, *mean_val4Q10;
+
+ const int16_t *lower_limit;
+ const uint16_t *init_index;
+ const uint16_t *cdf_size;
+ const uint16_t **cdf;
+
+ int32_t meangainQ12;
+ int32_t CQ11, CQ10,tmp32a,tmp32b;
+ int16_t shft;
+
+ meangainQ12=0;
+ for (k = 0; k < 4; k++)
+ meangainQ12 += PitchGain_Q12[k];
+
+ meangainQ12 >>= 2; // Get average.
+
+ /* voicing classificiation */
+ if (meangainQ12 <= 819) { // mean_gain < 0.2
+ shft = -1; // StepSize=2.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrLo;
+ cdf_size = WebRtcIsacfix_kPitchLagSizeLo;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
+ lower_limit = WebRtcIsacfix_kLowerLimitLo;
+ init_index = WebRtcIsacfix_kInitIndLo;
+ } else if (meangainQ12 <= 1638) { // mean_gain < 0.4
+ shft = 0; // StepSize=1.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrMid;
+ cdf_size = WebRtcIsacfix_kPitchLagSizeMid;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
+ lower_limit = WebRtcIsacfix_kLowerLimitMid;
+ init_index = WebRtcIsacfix_kInitIndMid;
+ } else {
+ shft = 1; // StepSize=0.5;
+ cdf = WebRtcIsacfix_kPitchLagPtrHi;
+ cdf_size = WebRtcIsacfix_kPitchLagSizeHi;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
+ lower_limit = WebRtcIsacfix_kLowerLimitHi;
+ init_index = WebRtcIsacfix_kInitIndHi;
+ }
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsacfix_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+ if ((err<0) || (index[0]<0)) // error check
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+ err = WebRtcIsacfix_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+
+ /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+ CQ11 = ((int32_t)index[0] + lower_limit[0]); // Q0
+ CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11);
+ PitchLags_Q7[k] = (int16_t)(tmp32a >> 5);
+ }
+
+ CQ10 = mean_val2Q10[index[1]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = WebRtcIsacfix_kTransform[1][k] * (int16_t)CQ10 >> 10;
+ PitchLags_Q7[k] += (int16_t)(tmp32b >> 5);
+ }
+
+ CQ10 = mean_val4Q10[index[3]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = WebRtcIsacfix_kTransform[3][k] * (int16_t)CQ10 >> 10;
+ PitchLags_Q7[k] += (int16_t)(tmp32b >> 5);
+ }
+
+ return 0;
+}
+
+
+
+/* quantize & code Pitch Lags */
+int WebRtcIsacfix_EncodePitchLag(int16_t* PitchLagsQ7,
+ int16_t* PitchGain_Q12,
+ Bitstr_enc* streamdata,
+ IsacSaveEncoderData* encData) {
+ int k, j;
+ int16_t index[PITCH_SUBFRAMES];
+ int32_t meangainQ12, CQ17;
+ int32_t CQ11, CQ10,tmp32a;
+
+ const int16_t *mean_val2Q10,*mean_val4Q10;
+ const int16_t *lower_limit, *upper_limit;
+ const uint16_t **cdf;
+ int16_t shft, tmp16b;
+ int32_t tmp32b;
+ int status = 0;
+
+ /* compute mean pitch gain */
+ meangainQ12=0;
+ for (k = 0; k < 4; k++)
+ meangainQ12 += PitchGain_Q12[k];
+
+ meangainQ12 >>= 2;
+
+ /* Save data for creation of multiple bitstreams */
+ if (encData != NULL) {
+ encData->meanGain[encData->startIdx] = meangainQ12;
+ }
+
+ /* voicing classificiation */
+ if (meangainQ12 <= 819) { // mean_gain < 0.2
+ shft = -1; // StepSize=2.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrLo;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
+ lower_limit = WebRtcIsacfix_kLowerLimitLo;
+ upper_limit = WebRtcIsacfix_kUpperLimitLo;
+ } else if (meangainQ12 <= 1638) { // mean_gain < 0.4
+ shft = 0; // StepSize=1.0;
+ cdf = WebRtcIsacfix_kPitchLagPtrMid;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
+ lower_limit = WebRtcIsacfix_kLowerLimitMid;
+ upper_limit = WebRtcIsacfix_kUpperLimitMid;
+ } else {
+ shft = 1; // StepSize=0.5;
+ cdf = WebRtcIsacfix_kPitchLagPtrHi;
+ mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
+ mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
+ lower_limit = WebRtcIsacfix_kLowerLimitHi;
+ upper_limit = WebRtcIsacfix_kUpperLimitHi;
+ }
+
+ /* find quantization index */
+ for (k=0; k<4; k++)
+ {
+ /* transform */
+ CQ17=0;
+ for (j=0; j<PITCH_SUBFRAMES; j++)
+ CQ17 += WebRtcIsacfix_kTransform[k][j] * PitchLagsQ7[j] >> 2; // Q17
+
+ CQ17 = WEBRTC_SPL_SHIFT_W32(CQ17,shft); // Scale with StepSize
+
+ /* quantize */
+ tmp16b = (int16_t)((CQ17 + 65536) >> 17);
+ index[k] = tmp16b;
+
+ /* check that the index is not outside the boundaries of the table */
+ if (index[k] < lower_limit[k]) index[k] = lower_limit[k];
+ else if (index[k] > upper_limit[k]) index[k] = upper_limit[k];
+ index[k] -= lower_limit[k];
+
+ /* Save data for creation of multiple bitstreams */
+ if(encData != NULL) {
+ encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k];
+ }
+ }
+
+ /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+ CQ11 = (index[0] + lower_limit[0]); // Q0
+ CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
+
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11); // Q12
+ PitchLagsQ7[k] = (int16_t)(tmp32a >> 5); // Q7.
+ }
+
+ CQ10 = mean_val2Q10[index[1]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = WebRtcIsacfix_kTransform[1][k] * (int16_t)CQ10 >> 10;
+ PitchLagsQ7[k] += (int16_t)(tmp32b >> 5); // Q7.
+ }
+
+ CQ10 = mean_val4Q10[index[3]];
+ for (k=0; k<PITCH_SUBFRAMES; k++) {
+ tmp32b = WebRtcIsacfix_kTransform[3][k] * (int16_t)CQ10 >> 10;
+ PitchLagsQ7[k] += (int16_t)(tmp32b >> 5); // Q7.
+ }
+
+ /* entropy coding of quantization pitch lags */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
+
+ /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
+ return status;
+}
+
+
+
+/* Routines for inband signaling of bandwitdh estimation */
+/* Histograms based on uniform distribution of indices */
+/* Move global variables later! */
+
+
+/* cdf array for frame length indicator */
+const uint16_t kFrameLenCdf[4] = {
+ 0, 21845, 43690, 65535};
+
+/* pointer to cdf array for frame length indicator */
+const uint16_t * const kFrameLenCdfPtr[1] = {kFrameLenCdf};
+
+/* initial cdf index for decoder of frame length indicator */
+const uint16_t kFrameLenInitIndex[1] = {1};
+
+
+int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
+ size_t *framesamples)
+{
+
+ int err;
+ int16_t frame_mode;
+
+ err = 0;
+ /* entropy decoding of frame length [1:30ms,2:60ms] */
+ err = WebRtcIsacfix_DecHistOneStepMulti(&frame_mode, streamdata, kFrameLenCdfPtr, kFrameLenInitIndex, 1);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
+
+ switch(frame_mode) {
+ case 1:
+ *framesamples = 480; /* 30ms */
+ break;
+ case 2:
+ *framesamples = 960; /* 60ms */
+ break;
+ default:
+ err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
+ }
+
+ return err;
+}
+
+
+int WebRtcIsacfix_EncodeFrameLen(int16_t framesamples, Bitstr_enc *streamdata) {
+
+ int status;
+ int16_t frame_mode;
+
+ status = 0;
+ frame_mode = 0;
+ /* entropy coding of frame length [1:480 samples,2:960 samples] */
+ switch(framesamples) {
+ case 480:
+ frame_mode = 1;
+ break;
+ case 960:
+ frame_mode = 2;
+ break;
+ default:
+ status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
+ }
+
+ if (status < 0)
+ return status;
+
+ status = WebRtcIsacfix_EncHistMulti(streamdata, &frame_mode, kFrameLenCdfPtr, 1);
+
+ return status;
+}
+
+/* cdf array for estimated bandwidth */
+const uint16_t kBwCdf[25] = {
+ 0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
+ 32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
+ 62804, 65535};
+
+/* pointer to cdf array for estimated bandwidth */
+const uint16_t * const kBwCdfPtr[1] = {kBwCdf};
+
+/* initial cdf index for decoder of estimated bandwidth*/
+const uint16_t kBwInitIndex[1] = {7};
+
+
+int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata, int16_t *BWno) {
+
+ int err;
+ int16_t BWno32;
+
+ /* entropy decoding of sender's BW estimation [0..23] */
+ err = WebRtcIsacfix_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr, kBwInitIndex, 1);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
+ *BWno = (int16_t)BWno32;
+ return err;
+
+}
+
+
+int WebRtcIsacfix_EncodeReceiveBandwidth(int16_t *BWno, Bitstr_enc *streamdata)
+{
+ int status = 0;
+ /* entropy encoding of receiver's BW estimation [0..23] */
+ status = WebRtcIsacfix_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
+
+ return status;
+}
+
+/* estimate codel length of LPC Coef */
+void WebRtcIsacfix_TranscodeLpcCoef(int32_t *gain_lo_hiQ17,
+ int16_t *index_gQQ) {
+ int j, k;
+ int16_t posQQ, pos2QQ;
+ int16_t posg, offsg, gainpos;
+ int32_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
+ int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
+ int32_t sumQQ;
+
+
+ /* log gains, mean removal and scaling */
+ posg = 0; gainpos=0;
+
+ for (k=0; k<SUBFRAMES; k++) {
+ /* log gains */
+
+ /* The input argument X to logN(X) is 2^17 times higher than the
+ input floating point argument Y to log(Y), since the X value
+ is a Q17 value. This can be compensated for after the call, by
+ subraction a value Z for each Q-step. One Q-step means that
+ X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
+ 177.445678 should be subtracted (since logN() returns a Q8 value).
+ For a X value in Q17, the value 177.445678*17 = 3017 should be
+ subtracted */
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
+ tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
+ posg++; gainpos++;
+
+ }
+
+
+ /* KLT */
+
+ /* left transform */
+ for (j = 0, offsg = 0; j < SUBFRAMES; j++, offsg += 2) {
+ // Q21 = Q6 * Q15
+ sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][0] +
+ tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
+ tmpcoeffs2_gQ21[offsg] = sumQQ;
+
+ // Q21 = Q6 * Q15
+ sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][1] +
+ tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
+ tmpcoeffs2_gQ21[offsg + 1] = sumQQ;
+ }
+
+ /* right transform */
+ WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
+ tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
+
+ /* quantize coefficients */
+ for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
+ {
+ posQQ = WebRtcIsacfix_kSelIndGain[k];
+ pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
+
+ index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
+ if (index_gQQ[k] < 0) {
+ index_gQQ[k] = 0;
+ }
+ else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
+ index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h
new file mode 100644
index 0000000000..ae11394f7c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file contains all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+/* decode complex spectrum (return number of bytes in stream) */
+int WebRtcIsacfix_DecodeSpec(Bitstr_dec* streamdata,
+ int16_t* frQ7,
+ int16_t* fiQ7,
+ int16_t AvgPitchGain_Q12);
+
+/* encode complex spectrum */
+int WebRtcIsacfix_EncodeSpec(const int16_t* fr,
+ const int16_t* fi,
+ Bitstr_enc* streamdata,
+ int16_t AvgPitchGain_Q12);
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec* streamdata,
+ int32_t* LPCCoefQ17,
+ int32_t* gain_lo_hiQ17,
+ int16_t* outmodel);
+
+int WebRtcIsacfix_DecodeLpc(int32_t* gain_lo_hiQ17,
+ int16_t* LPCCoef_loQ15,
+ int16_t* LPCCoef_hiQ15,
+ Bitstr_dec* streamdata,
+ int16_t* outmodel);
+
+/* quantize & code LPC Coef */
+int WebRtcIsacfix_EncodeLpc(int32_t* gain_lo_hiQ17,
+ int16_t* LPCCoef_loQ15,
+ int16_t* LPCCoef_hiQ15,
+ int16_t* model,
+ int32_t* sizeQ11,
+ Bitstr_enc* streamdata,
+ IsacSaveEncoderData* encData,
+ transcode_obj* transcodeParam);
+
+int WebRtcIsacfix_EstCodeLpcGain(int32_t* gain_lo_hiQ17,
+ Bitstr_enc* streamdata,
+ IsacSaveEncoderData* encData);
+/* decode & dequantize RC */
+int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec* streamdata, int16_t* RCQ15);
+
+/* quantize & code RC */
+int WebRtcIsacfix_EncodeRcCoef(int16_t* RCQ15, Bitstr_enc* streamdata);
+
+/* decode & dequantize squared Gain */
+int WebRtcIsacfix_DecodeGain2(Bitstr_dec* streamdata, int32_t* Gain2);
+
+/* quantize & code squared Gain (input is squared gain) */
+int WebRtcIsacfix_EncodeGain2(int32_t* gain2, Bitstr_enc* streamdata);
+
+int WebRtcIsacfix_EncodePitchGain(int16_t* PitchGains_Q12,
+ Bitstr_enc* streamdata,
+ IsacSaveEncoderData* encData);
+
+int WebRtcIsacfix_EncodePitchLag(int16_t* PitchLagQ7,
+ int16_t* PitchGain_Q12,
+ Bitstr_enc* streamdata,
+ IsacSaveEncoderData* encData);
+
+int WebRtcIsacfix_DecodePitchGain(Bitstr_dec* streamdata,
+ int16_t* PitchGain_Q12);
+
+int WebRtcIsacfix_DecodePitchLag(Bitstr_dec* streamdata,
+ int16_t* PitchGain_Q12,
+ int16_t* PitchLagQ7);
+
+int WebRtcIsacfix_DecodeFrameLen(Bitstr_dec* streamdata, size_t* framelength);
+
+int WebRtcIsacfix_EncodeFrameLen(int16_t framelength, Bitstr_enc* streamdata);
+
+int WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec* streamdata, int16_t* BWno);
+
+int WebRtcIsacfix_EncodeReceiveBandwidth(int16_t* BWno, Bitstr_enc* streamdata);
+
+void WebRtcIsacfix_TranscodeLpcCoef(int32_t* tmpcoeffs_gQ6, int16_t* index_gQQ);
+
+// Pointer functions for LPC transforms.
+
+typedef void (*MatrixProduct1)(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix1_index_factor1,
+ int matrix0_index_factor1,
+ int matrix1_index_init_case,
+ int matrix1_index_step,
+ int matrix0_index_step,
+ int inner_loop_count,
+ int mid_loop_count,
+ int shift);
+typedef void (*MatrixProduct2)(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix0_index_factor,
+ int matrix0_index_step);
+
+extern MatrixProduct1 WebRtcIsacfix_MatrixProduct1;
+extern MatrixProduct2 WebRtcIsacfix_MatrixProduct2;
+
+void WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix1_index_factor1,
+ int matrix0_index_factor1,
+ int matrix1_index_init_case,
+ int matrix1_index_step,
+ int matrix0_index_step,
+ int inner_loop_count,
+ int mid_loop_count,
+ int shift);
+void WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix0_index_factor,
+ int matrix0_index_step);
+
+#if defined(WEBRTC_HAS_NEON)
+void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix1_index_factor1,
+ int matrix0_index_factor1,
+ int matrix1_index_init_case,
+ int matrix1_index_step,
+ int matrix0_index_step,
+ int inner_loop_count,
+ int mid_loop_count,
+ int shift);
+void WebRtcIsacfix_MatrixProduct2Neon(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix0_index_factor,
+ int matrix0_index_step);
+#endif
+
+#if defined(MIPS32_LE)
+void WebRtcIsacfix_MatrixProduct1MIPS(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix1_index_factor1,
+ int matrix0_index_factor1,
+ int matrix1_index_init_case,
+ int matrix1_index_step,
+ int matrix0_index_step,
+ int inner_loop_count,
+ int mid_loop_count,
+ int shift);
+
+void WebRtcIsacfix_MatrixProduct2MIPS(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ int matrix0_index_factor,
+ int matrix0_index_step);
+#endif
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ENTROPY_CODING_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c
new file mode 100644
index 0000000000..a66a43ef99
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_mips.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// MIPS optimization of the function WebRtcIsacfix_MatrixProduct1.
+// Bit-exact with the function WebRtcIsacfix_MatrixProduct1C from
+// entropy_coding.c file.
+void WebRtcIsacfix_MatrixProduct1MIPS(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ const int matrix1_index_factor1,
+ const int matrix0_index_factor1,
+ const int matrix1_index_init_case,
+ const int matrix1_index_step,
+ const int matrix0_index_step,
+ const int inner_loop_count,
+ const int mid_loop_count,
+ const int shift) {
+ if (matrix1_index_init_case != 0) {
+ int j = SUBFRAMES, k = 0, n = 0;
+ int32_t r0, r1, r2, sum32;
+ int32_t* product_start = matrix_product;
+ int32_t* product_ptr;
+ const uint32_t product_step = 4 * mid_loop_count;
+ const uint32_t matrix0_step = 2 * matrix0_index_step;
+ const uint32_t matrix1_step = 4 * matrix1_index_step;
+ const uint32_t matrix0_step2 = 2 * matrix0_index_factor1;
+ const uint32_t matrix1_step2 = 4 * matrix1_index_factor1;
+ const int16_t* matrix0_start = matrix0;
+ const int32_t* matrix1_start = matrix1;
+ int16_t* matrix0_ptr;
+ int32_t* matrix1_ptr;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "1: \n\t"
+ "addu %[product_ptr], %[product_start], $0 \n\t"
+ "addu %[k], %[product_step], $0 \n\t"
+ "addiu %[j], %[j], -1 \n\t"
+ "addu %[matrix1_start], %[matrix1], $0 \n\t"
+ "2: \n\t"
+ "addu %[matrix1_ptr], %[matrix1_start], $0 \n\t"
+ "addu %[matrix0_ptr], %[matrix0_start], $0 \n\t"
+ "addu %[n], %[inner_loop_count], $0 \n\t"
+ "mul %[sum32], $0, $0 \n\t"
+ "3: \n\t"
+ "lw %[r0], 0(%[matrix1_ptr]) \n\t"
+ "lh %[r1], 0(%[matrix0_ptr]) \n\t"
+ "addu %[matrix1_ptr], %[matrix1_ptr], %[matrix1_step] \n\t"
+ "sllv %[r0], %[r0], %[shift] \n\t"
+ "andi %[r2], %[r0], 0xffff \n\t"
+ "sra %[r2], %[r2], 1 \n\t"
+ "mul %[r2], %[r2], %[r1] \n\t"
+ "sra %[r0], %[r0], 16 \n\t"
+ "mul %[r0], %[r0], %[r1] \n\t"
+ "addu %[matrix0_ptr], %[matrix0_ptr], %[matrix0_step] \n\t"
+ "addiu %[n], %[n], -1 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r2], %[r2], 15 \n\t"
+#else
+ "addiu %[r2], %[r2], 0x4000 \n\t"
+ "sra %[r2], %[r2], 15 \n\t"
+#endif
+ "addu %[sum32], %[sum32], %[r2] \n\t"
+ "bgtz %[n], 3b \n\t"
+ " addu %[sum32], %[sum32], %[r0] \n\t"
+ "addiu %[k], %[k], -4 \n\t"
+ "addu %[matrix1_start], %[matrix1_start], %[matrix1_step2] \n\t"
+ "sw %[sum32], 0(%[product_ptr]) \n\t"
+ "bgtz %[k], 2b \n\t"
+ " addiu %[product_ptr], %[product_ptr], 4 \n\t"
+ "addu %[matrix0_start], %[matrix0_start], %[matrix0_step2] \n\t"
+ "bgtz %[j], 1b \n\t"
+ " addu %[product_start], %[product_start], %[product_step] \n\t"
+ ".set pop \n\t"
+ : [product_ptr] "=&r" (product_ptr), [product_start] "+r" (product_start),
+ [k] "=&r" (k), [j] "+r" (j), [matrix1_start] "=&r"(matrix1_start),
+ [matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
+ [matrix0_start] "+r" (matrix0_start), [n] "=&r" (n), [r0] "=&r" (r0),
+ [sum32] "=&r" (sum32), [r1] "=&r" (r1),[r2] "=&r" (r2)
+ : [product_step] "r" (product_step), [matrix1] "r" (matrix1),
+ [inner_loop_count] "r" (inner_loop_count),
+ [matrix1_step] "r" (matrix1_step), [shift] "r" (shift),
+ [matrix0_step] "r" (matrix0_step), [matrix1_step2] "r" (matrix1_step2),
+ [matrix0_step2] "r" (matrix0_step2)
+ : "hi", "lo", "memory"
+ );
+ } else {
+ int j = SUBFRAMES, k = 0, n = 0;
+ int32_t r0, r1, r2, sum32;
+ int32_t* product_start = matrix_product;
+ int32_t* product_ptr;
+ const uint32_t product_step = 4 * mid_loop_count;
+ const uint32_t matrix0_step = 2 * matrix0_index_step;
+ const uint32_t matrix1_step = 4 * matrix1_index_step;
+ const uint32_t matrix0_step2 = 2 * matrix0_index_factor1;
+ const uint32_t matrix1_step2 = 4 * matrix1_index_factor1;
+ const int16_t* matrix0_start = matrix0;
+ const int32_t* matrix1_start = matrix1;
+ int16_t* matrix0_ptr;
+ int32_t* matrix1_ptr;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "1: \n\t"
+ "addu %[product_ptr], %[product_start], $0 \n\t"
+ "addu %[k], %[product_step], $0 \n\t"
+ "addiu %[j], %[j], -1 \n\t"
+ "addu %[matrix0_start], %[matrix0], $0 \n\t"
+ "2: \n\t"
+ "addu %[matrix1_ptr], %[matrix1_start], $0 \n\t"
+ "addu %[matrix0_ptr], %[matrix0_start], $0 \n\t"
+ "addu %[n], %[inner_loop_count], $0 \n\t"
+ "mul %[sum32], $0, $0 \n\t"
+ "3: \n\t"
+ "lw %[r0], 0(%[matrix1_ptr]) \n\t"
+ "lh %[r1], 0(%[matrix0_ptr]) \n\t"
+ "addu %[matrix1_ptr], %[matrix1_ptr], %[matrix1_step] \n\t"
+ "sllv %[r0], %[r0], %[shift] \n\t"
+ "andi %[r2], %[r0], 0xffff \n\t"
+ "sra %[r2], %[r2], 1 \n\t"
+ "mul %[r2], %[r2], %[r1] \n\t"
+ "sra %[r0], %[r0], 16 \n\t"
+ "mul %[r0], %[r0], %[r1] \n\t"
+ "addu %[matrix0_ptr], %[matrix0_ptr], %[matrix0_step] \n\t"
+ "addiu %[n], %[n], -1 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r2], %[r2], 15 \n\t"
+#else
+ "addiu %[r2], %[r2], 0x4000 \n\t"
+ "sra %[r2], %[r2], 15 \n\t"
+#endif
+ "addu %[sum32], %[sum32], %[r2] \n\t"
+ "bgtz %[n], 3b \n\t"
+ " addu %[sum32], %[sum32], %[r0] \n\t"
+ "addiu %[k], %[k], -4 \n\t"
+ "addu %[matrix0_start], %[matrix0_start], %[matrix0_step2] \n\t"
+ "sw %[sum32], 0(%[product_ptr]) \n\t"
+ "bgtz %[k], 2b \n\t"
+ " addiu %[product_ptr], %[product_ptr], 4 \n\t"
+ "addu %[matrix1_start], %[matrix1_start], %[matrix1_step2] \n\t"
+ "bgtz %[j], 1b \n\t"
+ " addu %[product_start], %[product_start], %[product_step] \n\t"
+ ".set pop \n\t"
+ : [product_ptr] "=&r" (product_ptr), [product_start] "+r" (product_start),
+ [k] "=&r" (k), [j] "+r" (j), [matrix1_start] "+r"(matrix1_start),
+ [matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
+ [matrix0_start] "=&r" (matrix0_start), [n] "=&r" (n), [r0] "=&r" (r0),
+ [sum32] "=&r" (sum32), [r1] "=&r" (r1),[r2] "=&r" (r2)
+ : [product_step] "r" (product_step), [matrix0] "r" (matrix0),
+ [inner_loop_count] "r" (inner_loop_count),
+ [matrix1_step] "r" (matrix1_step), [shift] "r" (shift),
+ [matrix0_step] "r" (matrix0_step), [matrix1_step2] "r" (matrix1_step2),
+ [matrix0_step2] "r" (matrix0_step2)
+ : "hi", "lo", "memory"
+ );
+ }
+}
+
+// MIPS optimization of the function WebRtcIsacfix_MatrixProduct2.
+// Bit-exact with the function WebRtcIsacfix_MatrixProduct2C from
+// entropy_coding.c file.
+void WebRtcIsacfix_MatrixProduct2MIPS(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ const int matrix0_index_factor,
+ const int matrix0_index_step) {
+ int j = 0, n = 0;
+ int loop_count = SUBFRAMES;
+ const int16_t* matrix0_ptr;
+ const int32_t* matrix1_ptr;
+ const int16_t* matrix0_start = matrix0;
+ const int matrix0_step = 2 * matrix0_index_step;
+ const int matrix0_step2 = 2 * matrix0_index_factor;
+ int32_t r0, r1, r2, r3, r4, sum32, sum32_2;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addu %[j], %[loop_count], $0 \n\t"
+ "addu %[matrix0_start], %[matrix0], $0 \n\t"
+ "1: \n\t"
+ "addu %[matrix1_ptr], %[matrix1], $0 \n\t"
+ "addu %[matrix0_ptr], %[matrix0_start], $0 \n\t"
+ "addu %[n], %[loop_count], $0 \n\t"
+ "mul %[sum32], $0, $0 \n\t"
+ "mul %[sum32_2], $0, $0 \n\t"
+ "2: \n\t"
+ "lw %[r0], 0(%[matrix1_ptr]) \n\t"
+ "lw %[r1], 4(%[matrix1_ptr]) \n\t"
+ "lh %[r2], 0(%[matrix0_ptr]) \n\t"
+ "andi %[r3], %[r0], 0xffff \n\t"
+ "sra %[r3], %[r3], 1 \n\t"
+ "mul %[r3], %[r3], %[r2] \n\t"
+ "andi %[r4], %[r1], 0xffff \n\t"
+ "sra %[r4], %[r4], 1 \n\t"
+ "mul %[r4], %[r4], %[r2] \n\t"
+ "sra %[r0], %[r0], 16 \n\t"
+ "mul %[r0], %[r0], %[r2] \n\t"
+ "sra %[r1], %[r1], 16 \n\t"
+ "mul %[r1], %[r1], %[r2] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r3], %[r3], 15 \n\t"
+ "shra_r.w %[r4], %[r4], 15 \n\t"
+#else
+ "addiu %[r3], %[r3], 0x4000 \n\t"
+ "sra %[r3], %[r3], 15 \n\t"
+ "addiu %[r4], %[r4], 0x4000 \n\t"
+ "sra %[r4], %[r4], 15 \n\t"
+#endif
+ "addiu %[matrix1_ptr], %[matrix1_ptr], 8 \n\t"
+ "addu %[matrix0_ptr], %[matrix0_ptr], %[matrix0_step] \n\t"
+ "addiu %[n], %[n], -1 \n\t"
+ "addu %[sum32], %[sum32], %[r3] \n\t"
+ "addu %[sum32_2], %[sum32_2], %[r4] \n\t"
+ "addu %[sum32], %[sum32], %[r0] \n\t"
+ "bgtz %[n], 2b \n\t"
+ " addu %[sum32_2], %[sum32_2], %[r1] \n\t"
+ "sra %[sum32], %[sum32], 3 \n\t"
+ "sra %[sum32_2], %[sum32_2], 3 \n\t"
+ "addiu %[j], %[j], -1 \n\t"
+ "addu %[matrix0_start], %[matrix0_start], %[matrix0_step2] \n\t"
+ "sw %[sum32], 0(%[matrix_product]) \n\t"
+ "sw %[sum32_2], 4(%[matrix_product]) \n\t"
+ "bgtz %[j], 1b \n\t"
+ " addiu %[matrix_product], %[matrix_product], 8 \n\t"
+ ".set pop \n\t"
+ : [j] "=&r" (j), [matrix0_start] "=&r" (matrix0_start),
+ [matrix1_ptr] "=&r" (matrix1_ptr), [matrix0_ptr] "=&r" (matrix0_ptr),
+ [n] "=&r" (n), [sum32] "=&r" (sum32), [sum32_2] "=&r" (sum32_2),
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [r4] "=&r" (r4), [matrix_product] "+r" (matrix_product)
+ : [loop_count] "r" (loop_count), [matrix0] "r" (matrix0),
+ [matrix1] "r" (matrix1), [matrix0_step] "r" (matrix0_step),
+ [matrix0_step2] "r" (matrix0_step2)
+ : "hi", "lo", "memory"
+ );
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c
new file mode 100644
index 0000000000..0200567880
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/entropy_coding_neon.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* This file contains WebRtcIsacfix_MatrixProduct1Neon() and
+ * WebRtcIsacfix_MatrixProduct2Neon() for ARM Neon platform. API's are in
+ * entropy_coding.c. Results are bit exact with the c code for
+ * generic platforms.
+ */
+
+#include <arm_neon.h>
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/checks.h"
+
+void WebRtcIsacfix_MatrixProduct1Neon(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ const int matrix1_index_factor1,
+ const int matrix0_index_factor1,
+ const int matrix1_index_init_case,
+ const int matrix1_index_step,
+ const int matrix0_index_step,
+ const int inner_loop_count,
+ const int mid_loop_count,
+ const int shift) {
+ int j = 0, k = 0, n = 0;
+ int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
+ int* matrix1_index_factor2 = &j;
+ int* matrix0_index_factor2 = &k;
+ if (matrix1_index_init_case != 0) {
+ matrix1_index_factor2 = &k;
+ matrix0_index_factor2 = &j;
+ }
+ int32x4_t shift32x4 = vdupq_n_s32(shift);
+ int32x2_t shift32x2 = vdup_n_s32(shift);
+ int32x4_t sum_32x4 = vdupq_n_s32(0);
+ int32x2_t sum_32x2 = vdup_n_s32(0);
+
+ RTC_DCHECK_EQ(0, inner_loop_count % 2);
+ RTC_DCHECK_EQ(0, mid_loop_count % 2);
+
+ if (matrix1_index_init_case != 0 && matrix1_index_factor1 == 1) {
+ for (j = 0; j < SUBFRAMES; j++) {
+ matrix_prod_index = mid_loop_count * j;
+ for (k = 0; k < (mid_loop_count >> 2) << 2; k += 4) {
+ sum_32x4 = veorq_s32(sum_32x4, sum_32x4); // Initialize to zeros.
+ matrix1_index = k;
+ matrix0_index = matrix0_index_factor1 * j;
+ for (n = 0; n < inner_loop_count; n++) {
+ int32x4_t matrix0_32x4 =
+ vdupq_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
+ int32x4_t matrix1_32x4 =
+ vshlq_s32(vld1q_s32(&matrix1[matrix1_index]), shift32x4);
+ int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
+ sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
+ matrix1_index += matrix1_index_step;
+ matrix0_index += matrix0_index_step;
+ }
+ vst1q_s32(&matrix_product[matrix_prod_index], sum_32x4);
+ matrix_prod_index += 4;
+ }
+ if (mid_loop_count % 4 > 1) {
+ sum_32x2 = veor_s32(sum_32x2, sum_32x2); // Initialize to zeros.
+ matrix1_index = k;
+ k += 2;
+ matrix0_index = matrix0_index_factor1 * j;
+ for (n = 0; n < inner_loop_count; n++) {
+ int32x2_t matrix0_32x2 =
+ vdup_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
+ int32x2_t matrix1_32x2 =
+ vshl_s32(vld1_s32(&matrix1[matrix1_index]), shift32x2);
+ int32x2_t multi_32x2 = vqdmulh_s32(matrix0_32x2, matrix1_32x2);
+ sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+ matrix1_index += matrix1_index_step;
+ matrix0_index += matrix0_index_step;
+ }
+ vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
+ matrix_prod_index += 2;
+ }
+ }
+ }
+ else if (matrix1_index_init_case == 0 && matrix0_index_factor1 == 1) {
+ int32x2_t multi_32x2 = vdup_n_s32(0);
+ int32x2_t matrix0_32x2 = vdup_n_s32(0);
+ for (j = 0; j < SUBFRAMES; j++) {
+ matrix_prod_index = mid_loop_count * j;
+ for (k = 0; k < (mid_loop_count >> 2) << 2; k += 4) {
+ sum_32x4 = veorq_s32(sum_32x4, sum_32x4); // Initialize to zeros.
+ matrix1_index = matrix1_index_factor1 * j;
+ matrix0_index = k;
+ for (n = 0; n < inner_loop_count; n++) {
+ int32x4_t matrix1_32x4 = vdupq_n_s32(matrix1[matrix1_index] << shift);
+ int32x4_t matrix0_32x4 =
+ vshll_n_s16(vld1_s16(&matrix0[matrix0_index]), 15);
+ int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
+ sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
+ matrix1_index += matrix1_index_step;
+ matrix0_index += matrix0_index_step;
+ }
+ vst1q_s32(&matrix_product[matrix_prod_index], sum_32x4);
+ matrix_prod_index += 4;
+ }
+ if (mid_loop_count % 4 > 1) {
+ sum_32x2 = veor_s32(sum_32x2, sum_32x2); // Initialize to zeros.
+ matrix1_index = matrix1_index_factor1 * j;
+ matrix0_index = k;
+ for (n = 0; n < inner_loop_count; n++) {
+ int32x2_t matrix1_32x2 = vdup_n_s32(matrix1[matrix1_index] << shift);
+ matrix0_32x2 =
+ vset_lane_s32((int32_t)matrix0[matrix0_index], matrix0_32x2, 0);
+ matrix0_32x2 = vset_lane_s32((int32_t)matrix0[matrix0_index + 1],
+ matrix0_32x2, 1);
+ matrix0_32x2 = vshl_n_s32(matrix0_32x2, 15);
+ multi_32x2 = vqdmulh_s32(matrix1_32x2, matrix0_32x2);
+ sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+ matrix1_index += matrix1_index_step;
+ matrix0_index += matrix0_index_step;
+ }
+ vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
+ matrix_prod_index += 2;
+ }
+ }
+ }
+ else if (matrix1_index_init_case == 0 &&
+ matrix1_index_step == 1 &&
+ matrix0_index_step == 1) {
+ int32x2_t multi_32x2 = vdup_n_s32(0);
+ int32x2_t matrix0_32x2 = vdup_n_s32(0);
+ for (j = 0; j < SUBFRAMES; j++) {
+ matrix_prod_index = mid_loop_count * j;
+ for (k = 0; k < mid_loop_count; k++) {
+ sum_32x4 = veorq_s32(sum_32x4, sum_32x4); // Initialize to zeros.
+ matrix1_index = matrix1_index_factor1 * j;
+ matrix0_index = matrix0_index_factor1 * k;
+ for (n = 0; n < (inner_loop_count >> 2) << 2; n += 4) {
+ int32x4_t matrix1_32x4 =
+ vshlq_s32(vld1q_s32(&matrix1[matrix1_index]), shift32x4);
+ int32x4_t matrix0_32x4 =
+ vshll_n_s16(vld1_s16(&matrix0[matrix0_index]), 15);
+ int32x4_t multi_32x4 = vqdmulhq_s32(matrix0_32x4, matrix1_32x4);
+ sum_32x4 = vqaddq_s32(sum_32x4, multi_32x4);
+ matrix1_index += 4;
+ matrix0_index += 4;
+ }
+ sum_32x2 = vqadd_s32(vget_low_s32(sum_32x4), vget_high_s32(sum_32x4));
+ if (inner_loop_count % 4 > 1) {
+ int32x2_t matrix1_32x2 =
+ vshl_s32(vld1_s32(&matrix1[matrix1_index]), shift32x2);
+ matrix0_32x2 =
+ vset_lane_s32((int32_t)matrix0[matrix0_index], matrix0_32x2, 0);
+ matrix0_32x2 = vset_lane_s32((int32_t)matrix0[matrix0_index + 1],
+ matrix0_32x2, 1);
+ matrix0_32x2 = vshl_n_s32(matrix0_32x2, 15);
+ multi_32x2 = vqdmulh_s32(matrix1_32x2, matrix0_32x2);
+ sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+ }
+ sum_32x2 = vpadd_s32(sum_32x2, sum_32x2);
+ vst1_lane_s32(&matrix_product[matrix_prod_index], sum_32x2, 0);
+ matrix_prod_index++;
+ }
+ }
+ }
+ else {
+ for (j = 0; j < SUBFRAMES; j++) {
+ matrix_prod_index = mid_loop_count * j;
+ for (k=0; k < mid_loop_count; k++) {
+ int32_t sum32 = 0;
+ matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
+ matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
+ for (n = 0; n < inner_loop_count; n++) {
+ sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
+ matrix1[matrix1_index] << shift));
+ matrix1_index += matrix1_index_step;
+ matrix0_index += matrix0_index_step;
+ }
+ matrix_product[matrix_prod_index] = sum32;
+ matrix_prod_index++;
+ }
+ }
+ }
+}
+
+void WebRtcIsacfix_MatrixProduct2Neon(const int16_t matrix0[],
+ const int32_t matrix1[],
+ int32_t matrix_product[],
+ const int matrix0_index_factor,
+ const int matrix0_index_step) {
+ int j = 0, n = 0;
+ int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
+ int32x2_t sum_32x2 = vdup_n_s32(0);
+ for (j = 0; j < SUBFRAMES; j++) {
+ sum_32x2 = veor_s32(sum_32x2, sum_32x2); // Initialize to zeros.
+ matrix1_index = 0;
+ matrix0_index = matrix0_index_factor * j;
+ for (n = SUBFRAMES; n > 0; n--) {
+ int32x2_t matrix0_32x2 =
+ vdup_n_s32((int32_t)(matrix0[matrix0_index]) << 15);
+ int32x2_t matrix1_32x2 = vld1_s32(&matrix1[matrix1_index]);
+ int32x2_t multi_32x2 = vqdmulh_s32(matrix0_32x2, matrix1_32x2);
+ sum_32x2 = vqadd_s32(sum_32x2, multi_32x2);
+ matrix1_index += 2;
+ matrix0_index += matrix0_index_step;
+ }
+ sum_32x2 = vshr_n_s32(sum_32x2, 3);
+ vst1_s32(&matrix_product[matrix_prod_index], sum_32x2);
+ matrix_prod_index += 2;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.c
new file mode 100644
index 0000000000..a0ed3f83ce
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * fft.c
+ *
+ * Fast Fourier Transform
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+
+static const int16_t kSortTabFft[240] = {
+ 0, 60, 120, 180, 20, 80, 140, 200, 40, 100, 160, 220,
+ 4, 64, 124, 184, 24, 84, 144, 204, 44, 104, 164, 224,
+ 8, 68, 128, 188, 28, 88, 148, 208, 48, 108, 168, 228,
+ 12, 72, 132, 192, 32, 92, 152, 212, 52, 112, 172, 232,
+ 16, 76, 136, 196, 36, 96, 156, 216, 56, 116, 176, 236,
+ 1, 61, 121, 181, 21, 81, 141, 201, 41, 101, 161, 221,
+ 5, 65, 125, 185, 25, 85, 145, 205, 45, 105, 165, 225,
+ 9, 69, 129, 189, 29, 89, 149, 209, 49, 109, 169, 229,
+ 13, 73, 133, 193, 33, 93, 153, 213, 53, 113, 173, 233,
+ 17, 77, 137, 197, 37, 97, 157, 217, 57, 117, 177, 237,
+ 2, 62, 122, 182, 22, 82, 142, 202, 42, 102, 162, 222,
+ 6, 66, 126, 186, 26, 86, 146, 206, 46, 106, 166, 226,
+ 10, 70, 130, 190, 30, 90, 150, 210, 50, 110, 170, 230,
+ 14, 74, 134, 194, 34, 94, 154, 214, 54, 114, 174, 234,
+ 18, 78, 138, 198, 38, 98, 158, 218, 58, 118, 178, 238,
+ 3, 63, 123, 183, 23, 83, 143, 203, 43, 103, 163, 223,
+ 7, 67, 127, 187, 27, 87, 147, 207, 47, 107, 167, 227,
+ 11, 71, 131, 191, 31, 91, 151, 211, 51, 111, 171, 231,
+ 15, 75, 135, 195, 35, 95, 155, 215, 55, 115, 175, 235,
+ 19, 79, 139, 199, 39, 99, 159, 219, 59, 119, 179, 239
+};
+
+/* Cosine table in Q14 */
+static const int16_t kCosTabFfftQ14[240] = {
+ 16384, 16378, 16362, 16333, 16294, 16244, 16182, 16110, 16026, 15931, 15826, 15709,
+ 15582, 15444, 15296, 15137, 14968, 14788, 14598, 14399, 14189, 13970, 13741, 13502,
+ 13255, 12998, 12733, 12458, 12176, 11885, 11585, 11278, 10963, 10641, 10311, 9974,
+ 9630, 9280, 8923, 8561, 8192, 7818, 7438, 7053, 6664, 6270, 5872, 5469,
+ 5063, 4653, 4240, 3825, 3406, 2986, 2563, 2139, 1713, 1285, 857, 429,
+ 0, -429, -857, -1285, -1713, -2139, -2563, -2986, -3406, -3825, -4240, -4653,
+ -5063, -5469, -5872, -6270, -6664, -7053, -7438, -7818, -8192, -8561, -8923, -9280,
+ -9630, -9974, -10311, -10641, -10963, -11278, -11585, -11885, -12176, -12458, -12733, -12998,
+ -13255, -13502, -13741, -13970, -14189, -14399, -14598, -14788, -14968, -15137, -15296, -15444,
+ -15582, -15709, -15826, -15931, -16026, -16110, -16182, -16244, -16294, -16333, -16362, -16378,
+ -16384, -16378, -16362, -16333, -16294, -16244, -16182, -16110, -16026, -15931, -15826, -15709,
+ -15582, -15444, -15296, -15137, -14968, -14788, -14598, -14399, -14189, -13970, -13741, -13502,
+ -13255, -12998, -12733, -12458, -12176, -11885, -11585, -11278, -10963, -10641, -10311, -9974,
+ -9630, -9280, -8923, -8561, -8192, -7818, -7438, -7053, -6664, -6270, -5872, -5469,
+ -5063, -4653, -4240, -3825, -3406, -2986, -2563, -2139, -1713, -1285, -857, -429,
+ 0, 429, 857, 1285, 1713, 2139, 2563, 2986, 3406, 3825, 4240, 4653,
+ 5063, 5469, 5872, 6270, 6664, 7053, 7438, 7818, 8192, 8561, 8923, 9280,
+ 9630, 9974, 10311, 10641, 10963, 11278, 11585, 11885, 12176, 12458, 12733, 12998,
+ 13255, 13502, 13741, 13970, 14189, 14399, 14598, 14788, 14968, 15137, 15296, 15444,
+ 15582, 15709, 15826, 15931, 16026, 16110, 16182, 16244, 16294, 16333, 16362, 16378
+};
+
+
+
+/* Uses 16x16 mul, without rounding, which is faster. Uses WEBRTC_SPL_MUL_16_16_RSFT */
+int16_t WebRtcIsacfix_FftRadix16Fastest(int16_t RexQx[], int16_t ImxQx[], int16_t iSign) {
+
+ int16_t dd, ee, ff, gg, hh, ii;
+ int16_t k0, k1, k2, k3, k4, kk;
+ int16_t tmp116, tmp216;
+
+ int16_t ccc1Q14, ccc2Q14, ccc3Q14, sss1Q14, sss2Q14, sss3Q14;
+ int16_t sss60Q14, ccc72Q14, sss72Q14;
+ int16_t aaQx, ajQx, akQx, ajmQx, ajpQx, akmQx, akpQx;
+ int16_t bbQx, bjQx, bkQx, bjmQx, bjpQx, bkmQx, bkpQx;
+
+ int16_t ReDATAQx[240], ImDATAQx[240];
+
+ sss60Q14 = kCosTabFfftQ14[20];
+ ccc72Q14 = kCosTabFfftQ14[48];
+ sss72Q14 = kCosTabFfftQ14[12];
+
+ if (iSign < 0) {
+ sss72Q14 = -sss72Q14;
+ sss60Q14 = -sss60Q14;
+ }
+ /* Complexity is: 10 cycles */
+
+ /* compute fourier transform */
+
+ // transform for factor of 4
+ for (kk=0; kk<60; kk++) {
+ k0 = kk;
+ k1 = k0 + 60;
+ k2 = k1 + 60;
+ k3 = k2 + 60;
+
+ akpQx = RexQx[k0] + RexQx[k2];
+ akmQx = RexQx[k0] - RexQx[k2];
+ ajpQx = RexQx[k1] + RexQx[k3];
+ ajmQx = RexQx[k1] - RexQx[k3];
+ bkpQx = ImxQx[k0] + ImxQx[k2];
+ bkmQx = ImxQx[k0] - ImxQx[k2];
+ bjpQx = ImxQx[k1] + ImxQx[k3];
+ bjmQx = ImxQx[k1] - ImxQx[k3];
+
+ RexQx[k0] = akpQx + ajpQx;
+ ImxQx[k0] = bkpQx + bjpQx;
+ ajpQx = akpQx - ajpQx;
+ bjpQx = bkpQx - bjpQx;
+ if (iSign < 0) {
+ akpQx = akmQx + bjmQx;
+ bkpQx = bkmQx - ajmQx;
+ akmQx -= bjmQx;
+ bkmQx += ajmQx;
+ } else {
+ akpQx = akmQx - bjmQx;
+ bkpQx = bkmQx + ajmQx;
+ akmQx += bjmQx;
+ bkmQx -= ajmQx;
+ }
+
+ ccc1Q14 = kCosTabFfftQ14[kk];
+ ccc2Q14 = kCosTabFfftQ14[2 * kk];
+ ccc3Q14 = kCosTabFfftQ14[3 * kk];
+ sss1Q14 = kCosTabFfftQ14[kk + 60];
+ sss2Q14 = kCosTabFfftQ14[2 * kk + 60];
+ sss3Q14 = kCosTabFfftQ14[3 * kk + 60];
+ if (iSign==1) {
+ sss1Q14 = -sss1Q14;
+ sss2Q14 = -sss2Q14;
+ sss3Q14 = -sss3Q14;
+ }
+
+ //Do several multiplications like Q14*Q16>>14 = Q16
+ // RexQ16[k1] = akpQ16 * ccc1Q14 - bkpQ16 * sss1Q14;
+ // RexQ16[k2] = ajpQ16 * ccc2Q14 - bjpQ16 * sss2Q14;
+ // RexQ16[k3] = akmQ16 * ccc3Q14 - bkmQ16 * sss3Q14;
+ // ImxQ16[k1] = akpQ16 * sss1Q14 + bkpQ16 * ccc1Q14;
+ // ImxQ16[k2] = ajpQ16 * sss2Q14 + bjpQ16 * ccc2Q14;
+ // ImxQ16[k3] = akmQ16 * sss3Q14 + bkmQ16 * ccc3Q14;
+
+ RexQx[k1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, akpQx, 14) -
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, bkpQx, 14); // 6 non-mul + 2 mul cycles, i.e. 8 cycles (6+2*7=20 cycles if 16x32mul)
+ RexQx[k2] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) -
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjpQx, 14);
+ RexQx[k3] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, akmQx, 14) -
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, bkmQx, 14);
+ ImxQx[k1] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss1Q14, akpQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc1Q14, bkpQx, 14);
+ ImxQx[k2] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajpQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14);
+ ImxQx[k3] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss3Q14, akmQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc3Q14, bkmQx, 14);
+ //This mul segment needs 6*8 = 48 cycles for 16x16 muls, but 6*20 = 120 cycles for 16x32 muls
+
+
+ }
+ /* Complexity is: 51+48 = 99 cycles for 16x16 muls, but 51+120 = 171 cycles for 16x32 muls*/
+
+ // transform for factor of 3
+ kk=0;
+ k1=20;
+ k2=40;
+
+ for (hh=0; hh<4; hh++) {
+ for (ii=0; ii<20; ii++) {
+ akQx = RexQx[kk];
+ bkQx = ImxQx[kk];
+ ajQx = RexQx[k1] + RexQx[k2];
+ bjQx = ImxQx[k1] + ImxQx[k2];
+ RexQx[kk] = akQx + ajQx;
+ ImxQx[kk] = bkQx + bjQx;
+ tmp116 = ajQx >> 1;
+ tmp216 = bjQx >> 1;
+ akQx = akQx - tmp116;
+ bkQx = bkQx - tmp216;
+ tmp116 = RexQx[k1] - RexQx[k2];
+ tmp216 = ImxQx[k1] - ImxQx[k2];
+
+ ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp116, 14); // Q14*Qx>>14 = Qx
+ bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss60Q14, tmp216, 14); // Q14*Qx>>14 = Qx
+ RexQx[k1] = akQx - bjQx;
+ RexQx[k2] = akQx + bjQx;
+ ImxQx[k1] = bkQx + ajQx;
+ ImxQx[k2] = bkQx - ajQx;
+
+ kk++;
+ k1++;
+ k2++;
+ }
+ /* Complexity : (31+6)*20 = 740 cycles for 16x16 muls, but (31+18)*20 = 980 cycles for 16x32 muls*/
+ kk=kk+40;
+ k1=k1+40;
+ k2=k2+40;
+ }
+ /* Complexity : 4*(740+3) = 2972 cycles for 16x16 muls, but 4*(980+3) = 3932 cycles for 16x32 muls*/
+
+ /* multiply by rotation factor for odd factor 3 or 5 (not for 4)
+ Same code (duplicated) for both ii=2 and ii=3 */
+ kk = 1;
+ ee = 0;
+ ff = 0;
+
+ for (gg=0; gg<19; gg++) {
+ kk += 20;
+ ff = ff+4;
+ for (hh=0; hh<2; hh++) {
+ ee = ff + hh * ff;
+ dd = ee + 60;
+ ccc2Q14 = kCosTabFfftQ14[ee];
+ sss2Q14 = kCosTabFfftQ14[dd];
+ if (iSign==1) {
+ sss2Q14 = -sss2Q14;
+ }
+ for (ii=0; ii<4; ii++) {
+ akQx = RexQx[kk];
+ bkQx = ImxQx[kk];
+ RexQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) - // Q14*Qx>>14 = Qx
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
+ ImxQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) + // Q14*Qx>>14 = Qx
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkQx, 14);
+
+
+ kk += 60;
+ }
+ kk = kk - 220;
+ }
+ // Complexity: 2*(13+5+4*13+2) = 144 for 16x16 muls, but 2*(13+5+4*33+2) = 304 cycles for 16x32 muls
+ kk = kk - 59;
+ }
+ // Complexity: 19*144 = 2736 for 16x16 muls, but 19*304 = 5776 cycles for 16x32 muls
+
+ // transform for factor of 5
+ kk = 0;
+ ccc2Q14 = kCosTabFfftQ14[96];
+ sss2Q14 = kCosTabFfftQ14[84];
+ if (iSign==1) {
+ sss2Q14 = -sss2Q14;
+ }
+
+ for (hh=0; hh<4; hh++) {
+ for (ii=0; ii<12; ii++) {
+ k1 = kk + 4;
+ k2 = k1 + 4;
+ k3 = k2 + 4;
+ k4 = k3 + 4;
+
+ akpQx = RexQx[k1] + RexQx[k4];
+ akmQx = RexQx[k1] - RexQx[k4];
+ bkpQx = ImxQx[k1] + ImxQx[k4];
+ bkmQx = ImxQx[k1] - ImxQx[k4];
+ ajpQx = RexQx[k2] + RexQx[k3];
+ ajmQx = RexQx[k2] - RexQx[k3];
+ bjpQx = ImxQx[k2] + ImxQx[k3];
+ bjmQx = ImxQx[k2] - ImxQx[k3];
+ aaQx = RexQx[kk];
+ bbQx = ImxQx[kk];
+ RexQx[kk] = aaQx + akpQx + ajpQx;
+ ImxQx[kk] = bbQx + bkpQx + bjpQx;
+
+ akQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, akpQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, ajpQx, 14) + aaQx;
+ bkQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bkpQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bjpQx, 14) + bbQx;
+ ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, akmQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, ajmQx, 14);
+ bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bkmQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bjmQx, 14);
+ // 32+4*8=64 or 32+4*20=112
+
+ RexQx[k1] = akQx - bjQx;
+ RexQx[k4] = akQx + bjQx;
+ ImxQx[k1] = bkQx + ajQx;
+ ImxQx[k4] = bkQx - ajQx;
+
+ akQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akpQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, ajpQx, 14) + aaQx;
+ bkQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkpQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc72Q14, bjpQx, 14) + bbQx;
+ ajQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akmQx, 14) -
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, ajmQx, 14);
+ bjQx = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkmQx, 14) -
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss72Q14, bjmQx, 14);
+ // 8+4*8=40 or 8+4*20=88
+
+ RexQx[k2] = akQx - bjQx;
+ RexQx[k3] = akQx + bjQx;
+ ImxQx[k2] = bkQx + ajQx;
+ ImxQx[k3] = bkQx - ajQx;
+
+ kk = k4 + 4;
+ }
+ // Complexity: 12*(64+40+10) = 1368 for 16x16 muls, but 12*(112+88+10) = 2520 cycles for 16x32 muls
+ kk -= 239;
+ }
+ // Complexity: 4*1368 = 5472 for 16x16 muls, but 4*2520 = 10080 cycles for 16x32 muls
+
+ /* multiply by rotation factor for odd factor 3 or 5 (not for 4)
+ Same code (duplicated) for both ii=2 and ii=3 */
+ kk = 1;
+ ee=0;
+
+ for (gg=0; gg<3; gg++) {
+ kk += 4;
+ dd = 12 + 12 * gg;
+ ff = 0;
+ for (hh=0; hh<4; hh++) {
+ ff = ff+dd;
+ ee = ff+60;
+ for (ii=0; ii<12; ii++) {
+ akQx = RexQx[kk];
+ bkQx = ImxQx[kk];
+
+ ccc2Q14 = kCosTabFfftQ14[ff];
+ sss2Q14 = kCosTabFfftQ14[ee];
+
+ if (iSign==1) {
+ sss2Q14 = -sss2Q14;
+ }
+
+ RexQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, akQx, 14) -
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, bkQx, 14);
+ ImxQx[kk] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(sss2Q14, akQx, 14) +
+ (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(ccc2Q14, bkQx, 14);
+
+ kk += 20;
+ }
+ kk = kk - 236;
+ // Complexity: 12*(12+12) = 288 for 16x16 muls, but 12*(12+32) = 528 cycles for 16x32 muls
+ }
+ kk = kk - 19;
+ // Complexity: 4*288+6 for 16x16 muls, but 4*528+6 cycles for 16x32 muls
+ }
+ // Complexity: 3*4*288+6 = 3462 for 16x16 muls, but 3*4*528+6 = 6342 cycles for 16x32 muls
+
+
+ // last transform for factor of 4 */
+ for (kk=0; kk<240; kk=kk+4) {
+ k1 = kk + 1;
+ k2 = k1 + 1;
+ k3 = k2 + 1;
+
+ akpQx = RexQx[kk] + RexQx[k2];
+ akmQx = RexQx[kk] - RexQx[k2];
+ ajpQx = RexQx[k1] + RexQx[k3];
+ ajmQx = RexQx[k1] - RexQx[k3];
+ bkpQx = ImxQx[kk] + ImxQx[k2];
+ bkmQx = ImxQx[kk] - ImxQx[k2];
+ bjpQx = ImxQx[k1] + ImxQx[k3];
+ bjmQx = ImxQx[k1] - ImxQx[k3];
+ RexQx[kk] = akpQx + ajpQx;
+ ImxQx[kk] = bkpQx + bjpQx;
+ ajpQx = akpQx - ajpQx;
+ bjpQx = bkpQx - bjpQx;
+ if (iSign < 0) {
+ akpQx = akmQx + bjmQx;
+ bkpQx = bkmQx - ajmQx;
+ akmQx -= bjmQx;
+ bkmQx += ajmQx;
+ } else {
+ akpQx = akmQx - bjmQx;
+ bkpQx = bkmQx + ajmQx;
+ akmQx += bjmQx;
+ bkmQx -= ajmQx;
+ }
+ RexQx[k1] = akpQx;
+ RexQx[k2] = ajpQx;
+ RexQx[k3] = akmQx;
+ ImxQx[k1] = bkpQx;
+ ImxQx[k2] = bjpQx;
+ ImxQx[k3] = bkmQx;
+ }
+ // Complexity: 60*45 = 2700 for 16x16 muls, but 60*45 = 2700 cycles for 16x32 muls
+
+ /* permute the results to normal order */
+ for (ii=0; ii<240; ii++) {
+ ReDATAQx[ii]=RexQx[ii];
+ ImDATAQx[ii]=ImxQx[ii];
+ }
+ // Complexity: 240*2=480 cycles
+
+ for (ii=0; ii<240; ii++) {
+ RexQx[ii]=ReDATAQx[kSortTabFft[ii]];
+ ImxQx[ii]=ImDATAQx[kSortTabFft[ii]];
+ }
+ // Complexity: 240*2*2=960 cycles
+
+ // Total complexity:
+ // 16x16 16x32
+ // Complexity: 10 10
+ // Complexity: 99 171
+ // Complexity: 2972 3932
+ // Complexity: 2736 5776
+ // Complexity: 5472 10080
+ // Complexity: 3462 6342
+ // Complexity: 2700 2700
+ // Complexity: 480 480
+ // Complexity: 960 960
+ // =======================
+ // 18891 30451
+ //
+ // If this FFT is called 2 time each frame, i.e. 67 times per second, it will correspond to
+ // a C54 complexity of 67*18891/1000000 = 1.27 MIPS with 16x16-muls, and 67*30451/1000000 =
+ // = 2.04 MIPS with 16x32-muls. Note that this routine somtimes is called 6 times during the
+ // encoding of a frame, i.e. the max complexity would be 7/2*1.27 = 4.4 MIPS for the 16x16 mul case.
+
+
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.h
new file mode 100644
index 0000000000..4fe9b96be4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/fft.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*--------------------------------*-C-*---------------------------------*
+ * File:
+ * fft.h
+ * ---------------------------------------------------------------------*
+ * Re[]: real value array
+ * Im[]: imaginary value array
+ * nTotal: total number of complex values
+ * nPass: number of elements involved in this pass of transform
+ * nSpan: nspan/nPass = number of bytes to increment pointer
+ * in Re[] and Im[]
+ * isign: exponent: +1 = forward -1 = reverse
+ * scaling: normalizing constant by which the final result is *divided*
+ * scaling == -1, normalize by total dimension of the transform
+ * scaling < -1, normalize by the square-root of the total dimension
+ *
+ * ----------------------------------------------------------------------
+ * See the comments in the code for correct usage!
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+int16_t WebRtcIsacfix_FftRadix16Fastest(int16_t RexQx[],
+ int16_t ImxQx[],
+ int16_t iSign);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FFT_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
new file mode 100644
index 0000000000..f741e6f677
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
+
+#include <stdint.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Arguments:
+ * io: Input/output, in Q0.
+ * len: Input, sample length.
+ * coefficient: Input.
+ * state: Input/output, filter state, in Q4.
+ */
+typedef void (*HighpassFilterFixDec32)(int16_t* io,
+ int16_t len,
+ const int16_t* coefficient,
+ int32_t* state);
+extern HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
+
+void WebRtcIsacfix_HighpassFilterFixDec32C(int16_t* io,
+ int16_t len,
+ const int16_t* coefficient,
+ int32_t* state);
+
+#if defined(MIPS_DSP_R1_LE)
+void WebRtcIsacfix_HighpassFilterFixDec32MIPS(int16_t* io,
+ int16_t len,
+ const int16_t* coefficient,
+ int32_t* state);
+#endif
+
+typedef void (*AllpassFilter2FixDec16)(
+ int16_t* data_ch1, // Input and output in channel 1, in Q0
+ int16_t* data_ch2, // Input and output in channel 2, in Q0
+ const int16_t* factor_ch1, // Scaling factor for channel 1, in Q15
+ const int16_t* factor_ch2, // Scaling factor for channel 2, in Q15
+ int length, // Length of the data buffers
+ int32_t* filter_state_ch1, // Filter state for channel 1, in Q16
+ int32_t* filter_state_ch2); // Filter state for channel 2, in Q16
+extern AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
+
+void WebRtcIsacfix_AllpassFilter2FixDec16C(int16_t* data_ch1,
+ int16_t* data_ch2,
+ const int16_t* factor_ch1,
+ const int16_t* factor_ch2,
+ int length,
+ int32_t* filter_state_ch1,
+ int32_t* filter_state_ch2);
+
+#if defined(WEBRTC_HAS_NEON)
+void WebRtcIsacfix_AllpassFilter2FixDec16Neon(int16_t* data_ch1,
+ int16_t* data_ch2,
+ const int16_t* factor_ch1,
+ const int16_t* factor_ch2,
+ int length,
+ int32_t* filter_state_ch1,
+ int32_t* filter_state_ch2);
+#endif
+
+#if defined(MIPS_DSP_R1_LE)
+void WebRtcIsacfix_AllpassFilter2FixDec16MIPS(int16_t* data_ch1,
+ int16_t* data_ch2,
+ const int16_t* factor_ch1,
+ const int16_t* factor_ch2,
+ int length,
+ int32_t* filter_state_ch1,
+ int32_t* filter_state_ch2);
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif
+/* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c
new file mode 100644
index 0000000000..f2dec79c2d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbank_tables.c
+ *
+ * This file contains variables that are used in
+ * filterbanks.c
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+
+/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.94895953203325f, 0.94984516000000f,
+ * -0.05101826139794f, 0.05015484000000f};
+ */
+const int16_t WebRtcIsacfix_kHpStCoeffInQ30[8] = {
+ 16189, -31932, /* Q30 lo/hi pair */
+ 17243, 15562, /* Q30 lo/hi pair */
+ -17186, -26748, /* Q35 lo/hi pair */
+ -27476, 26296 /* Q35 lo/hi pair */
+};
+
+/* HPstcoeff_out_1_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.99701049409000f, 0.99714204490000f,
+ * 0.01701049409000f, -0.01704204490000f};
+ */
+const int16_t WebRtcIsacfix_kHPStCoeffOut1Q30[8] = {
+ -1306, -32719, /* Q30 lo/hi pair */
+ 11486, 16337, /* Q30 lo/hi pair */
+ 26078, 8918, /* Q35 lo/hi pair */
+ 3956, -8935 /* Q35 lo/hi pair */
+};
+
+/* HPstcoeff_out_2_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2};
+ * In float, they are: {-1.98645294509837f, 0.98672435560000f,
+ * 0.00645294509837f, -0.00662435560000f};
+ */
+const int16_t WebRtcIsacfix_kHPStCoeffOut2Q30[8] = {
+ -2953, -32546, /* Q30 lo/hi pair */
+ 32233, 16166, /* Q30 lo/hi pair */
+ 13217, 3383, /* Q35 lo/hi pair */
+ -4597, -3473 /* Q35 lo/hi pair */
+};
+
+/* The upper channel all-pass filter factors */
+const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2] = {
+ 1137, 12537
+};
+
+/* The lower channel all-pass filter factors */
+const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2] = {
+ 5059, 24379
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
new file mode 100644
index 0000000000..01e5a7ba85
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbank_tables.h
+ *
+ * Header file for variables that are defined in
+ * filterbank_tables.c.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
+
+#include <stdint.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/********************* Coefficient Tables ************************/
+
+/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHpStCoeffInQ30[8];
+
+/* HPstcoeff_out_1_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHPStCoeffOut1Q30[8];
+
+/* HPstcoeff_out_2_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+/* [Q30lo Q30hi Q30lo Q30hi Q35lo Q35hi Q35lo Q35hi] */
+extern const int16_t WebRtcIsacfix_kHPStCoeffOut2Q30[8];
+
+/* The upper channel all-pass filter factors */
+extern const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2];
+
+/* The lower channel all-pass filter factors */
+extern const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2];
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
new file mode 100644
index 0000000000..57b3e70b89
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function
+ * WebRtcIsacfix_SplitAndFilter, and WebRtcIsacfix_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/checks.h"
+
+// Declare a function pointer.
+AllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
+
+void WebRtcIsacfix_AllpassFilter2FixDec16C(
+ int16_t *data_ch1, // Input and output in channel 1, in Q0
+ int16_t *data_ch2, // Input and output in channel 2, in Q0
+ const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15
+ const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15
+ const int length, // Length of the data buffers
+ int32_t *filter_state_ch1, // Filter state for channel 1, in Q16
+ int32_t *filter_state_ch2) { // Filter state for channel 2, in Q16
+ int n = 0;
+ int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
+ int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
+ int16_t in_out = 0;
+ int32_t a = 0, b = 0;
+
+ // Assembly file assumption.
+ RTC_DCHECK_EQ(0, length % 2);
+
+ for (n = 0; n < length; n++) {
+ // Process channel 1:
+ in_out = data_ch1[n];
+ a = factor_ch1[0] * in_out; // Q15 * Q0 = Q15
+ a *= 1 << 1; // Q15 -> Q16
+ b = WebRtcSpl_AddSatW32(a, state0_ch1);
+ a = -factor_ch1[0] * (int16_t)(b >> 16); // Q15
+ state0_ch1 =
+ WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16)); // Q16
+ in_out = (int16_t) (b >> 16); // Save as Q0
+
+ a = factor_ch1[1] * in_out; // Q15 * Q0 = Q15
+ a *= 1 << 1; // Q15 -> Q16
+ b = WebRtcSpl_AddSatW32(a, state1_ch1); // Q16
+ a = -factor_ch1[1] * (int16_t)(b >> 16); // Q15
+ state1_ch1 =
+ WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16)); // Q16
+ data_ch1[n] = (int16_t) (b >> 16); // Save as Q0
+
+ // Process channel 2:
+ in_out = data_ch2[n];
+ a = factor_ch2[0] * in_out; // Q15 * Q0 = Q15
+ a *= 1 << 1; // Q15 -> Q16
+ b = WebRtcSpl_AddSatW32(a, state0_ch2); // Q16
+ a = -factor_ch2[0] * (int16_t)(b >> 16); // Q15
+ state0_ch2 =
+ WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16)); // Q16
+ in_out = (int16_t) (b >> 16); // Save as Q0
+
+ a = factor_ch2[1] * in_out; // Q15 * Q0 = Q15
+ a *= (1 << 1); // Q15 -> Q16
+ b = WebRtcSpl_AddSatW32(a, state1_ch2); // Q16
+ a = -factor_ch2[1] * (int16_t)(b >> 16); // Q15
+ state1_ch2 =
+ WebRtcSpl_AddSatW32(a * (1 << 1), (int32_t)in_out * (1 << 16)); // Q16
+ data_ch2[n] = (int16_t) (b >> 16); // Save as Q0
+ }
+
+ filter_state_ch1[0] = state0_ch1;
+ filter_state_ch1[1] = state1_ch1;
+ filter_state_ch2[0] = state0_ch2;
+ filter_state_ch2[1] = state1_ch2;
+}
+
+// Declare a function pointer.
+HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
+
+void WebRtcIsacfix_HighpassFilterFixDec32C(int16_t *io,
+ int16_t len,
+ const int16_t *coefficient,
+ int32_t *state)
+{
+ int k;
+ int32_t a1 = 0, b1 = 0, c = 0, in = 0;
+ int32_t a2 = 0, b2 = 0;
+ int32_t state0 = state[0];
+ int32_t state1 = state[1];
+
+ for (k=0; k<len; k++) {
+ in = (int32_t)io[k];
+
+#ifdef WEBRTC_ARCH_ARM_V7
+ {
+ register int tmp_coeff0;
+ register int tmp_coeff1;
+ __asm __volatile(
+ "ldr %[tmp_coeff0], [%[coeff]]\n\t"
+ "ldr %[tmp_coeff1], [%[coeff], #4]\n\t"
+ "smmulr %[a2], %[tmp_coeff0], %[state0]\n\t"
+ "smmulr %[b2], %[tmp_coeff1], %[state1]\n\t"
+ "ldr %[tmp_coeff0], [%[coeff], #8]\n\t"
+ "ldr %[tmp_coeff1], [%[coeff], #12]\n\t"
+ "smmulr %[a1], %[tmp_coeff0], %[state0]\n\t"
+ "smmulr %[b1], %[tmp_coeff1], %[state1]\n\t"
+ :[a2]"=&r"(a2),
+ [b2]"=&r"(b2),
+ [a1]"=&r"(a1),
+ [b1]"=r"(b1),
+ [tmp_coeff0]"=&r"(tmp_coeff0),
+ [tmp_coeff1]"=&r"(tmp_coeff1)
+ :[coeff]"r"(coefficient),
+ [state0]"r"(state0),
+ [state1]"r"(state1)
+ );
+ }
+#else
+ /* Q35 * Q4 = Q39 ; shift 32 bit => Q7 */
+ a1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[5], state0) +
+ (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[4], state0) >> 16);
+ b1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[7], state1) +
+ (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[6], state1) >> 16);
+
+ /* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */
+ a2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[1], state0) +
+ (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[0], state0) >> 16);
+ b2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[3], state1) +
+ (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[2], state1) >> 16);
+#endif
+
+ c = in + ((a1 + b1) >> 7); // Q0.
+ io[k] = (int16_t)WebRtcSpl_SatW32ToW16(c); // Write output as Q0.
+
+ c = in * (1 << 2) - a2 - b2; // In Q2.
+ c = (int32_t)WEBRTC_SPL_SAT(536870911, c, -536870912);
+
+ state1 = state0;
+ state0 = c * (1 << 2); // Write state as Q4
+ }
+ state[0] = state0;
+ state[1] = state1;
+}
+
+
+void WebRtcIsacfix_SplitAndFilter1(int16_t *pin,
+ int16_t *LP16,
+ int16_t *HP16,
+ PreFiltBankstr *prefiltdata)
+{
+ /* Function WebRtcIsacfix_SplitAndFilter */
+ /* This function creates low-pass and high-pass decimated versions of part of
+ the input signal, and part of the signal in the input 'lookahead buffer'. */
+
+ int k;
+
+ int16_t tempin_ch1[FRAMESAMPLES/2 + QLOOKAHEAD];
+ int16_t tempin_ch2[FRAMESAMPLES/2 + QLOOKAHEAD];
+ int32_t tmpState_ch1[2 * (QORDER-1)]; /* 4 */
+ int32_t tmpState_ch2[2 * (QORDER-1)]; /* 4 */
+
+ /* High pass filter */
+ WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
+
+
+ /* First Channel */
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ tempin_ch1[QLOOKAHEAD + k] = pin[1 + 2 * k];
+ }
+ for (k=0;k<QLOOKAHEAD;k++) {
+ tempin_ch1[k]=prefiltdata->INLABUF1_fix[k];
+ prefiltdata->INLABUF1_fix[k] = pin[FRAMESAMPLES + 1 - 2 * (QLOOKAHEAD - k)];
+ }
+
+ /* Second Channel. This is exactly like the first channel, except that the
+ even samples are now filtered instead (lower channel). */
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ tempin_ch2[QLOOKAHEAD + k] = pin[2 * k];
+ }
+ for (k=0;k<QLOOKAHEAD;k++) {
+ tempin_ch2[k]=prefiltdata->INLABUF2_fix[k];
+ prefiltdata->INLABUF2_fix[k] = pin[FRAMESAMPLES - 2 * (QLOOKAHEAD - k)];
+ }
+
+
+ /*obtain polyphase components by forward all-pass filtering through each channel */
+ /* The all pass filtering automatically updates the filter states which are exported in the
+ prefiltdata structure */
+ WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
+ tempin_ch2,
+ WebRtcIsacfix_kUpperApFactorsQ15,
+ WebRtcIsacfix_kLowerApFactorsQ15,
+ FRAMESAMPLES/2,
+ prefiltdata->INSTAT1_fix,
+ prefiltdata->INSTAT2_fix);
+
+ for (k = 0; k < 2 * (QORDER - 1); k++) {
+ tmpState_ch1[k] = prefiltdata->INSTAT1_fix[k];
+ tmpState_ch2[k] = prefiltdata->INSTAT2_fix[k];
+ }
+ WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1 + FRAMESAMPLES/2,
+ tempin_ch2 + FRAMESAMPLES/2,
+ WebRtcIsacfix_kUpperApFactorsQ15,
+ WebRtcIsacfix_kLowerApFactorsQ15,
+ QLOOKAHEAD,
+ tmpState_ch1,
+ tmpState_ch2);
+
+ /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
+ for (k=0; k<FRAMESAMPLES/2 + QLOOKAHEAD; k++) {
+ int32_t tmp1, tmp2, tmp3;
+ tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0
+ tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0
+ tmp3 = (tmp1 + tmp2) >> 1; /* Low pass signal. */
+ LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
+ tmp3 = (tmp1 - tmp2) >> 1; /* High pass signal. */
+ HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
+ }
+
+}/*end of WebRtcIsacfix_SplitAndFilter */
+
+
+
+//////////////////////////////////////////////////////////
+////////// Combining
+/* Function WebRtcIsacfix_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+ length FRAMESAMPLES/2 input low-pass and
+ high-pass signals and creates a reconstructed fullband
+ output signal of length FRAMESAMPLES. WebRtcIsacfix_FilterAndCombine
+ is the sibling function of WebRtcIsacfix_SplitAndFilter */
+/* INPUTS:
+ inLP: a length FRAMESAMPLES/2 array of input low-pass
+ samples.
+ inHP: a length FRAMESAMPLES/2 array of input high-pass
+ samples.
+ postfiltdata: input data structure containing the filterbank
+ states from the previous decoding iteration.
+ OUTPUTS:
+ Out: a length FRAMESAMPLES array of output reconstructed
+ samples (fullband) based on the input low-pass and
+ high-pass signals.
+ postfiltdata: the input data structure containing the filterbank
+ states is updated for the next decoding iteration */
+void WebRtcIsacfix_FilterAndCombine1(int16_t *tempin_ch1,
+ int16_t *tempin_ch2,
+ int16_t *out16,
+ PostFiltBankstr *postfiltdata)
+{
+ int k;
+ int16_t in[FRAMESAMPLES];
+
+ /* all-pass filter the new upper and lower channel signal.
+ For upper channel, use the all-pass filter factors that were used as a
+ lower channel at the encoding side. So at the decoder, the corresponding
+ all-pass filter factors for each channel are swapped.
+ For lower channel signal, since all-pass filter factors at the decoder are
+ swapped from the ones at the encoder, the 'upper' channel all-pass filter
+ factors (kUpperApFactors) are used to filter this new lower channel signal.
+ */
+ WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
+ tempin_ch2,
+ WebRtcIsacfix_kLowerApFactorsQ15,
+ WebRtcIsacfix_kUpperApFactorsQ15,
+ FRAMESAMPLES/2,
+ postfiltdata->STATE_0_UPPER_fix,
+ postfiltdata->STATE_0_LOWER_fix);
+
+ /* Merge outputs to form the full length output signal.*/
+ for (k=0;k<FRAMESAMPLES/2;k++) {
+ in[2 * k] = tempin_ch2[k];
+ in[2 * k + 1] = tempin_ch1[k];
+ }
+
+ /* High pass filter */
+ WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
+ WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ out16[k] = in[k];
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c
new file mode 100644
index 0000000000..949bca70e9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_mips.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+
+// WebRtcIsacfix_AllpassFilter2FixDec16 function optimized for MIPSDSP platform.
+// Bit-exact with WebRtcIsacfix_AllpassFilter2FixDec16C from filterbanks.c.
+void WebRtcIsacfix_AllpassFilter2FixDec16MIPS(
+ int16_t* data_ch1, // Input and output in channel 1, in Q0.
+ int16_t* data_ch2, // Input and output in channel 2, in Q0.
+ const int16_t* factor_ch1, // Scaling factor for channel 1, in Q15.
+ const int16_t* factor_ch2, // Scaling factor for channel 2, in Q15.
+ const int length, // Length of the data buffers.
+ int32_t* filter_state_ch1, // Filter state for channel 1, in Q16.
+ int32_t* filter_state_ch2) { // Filter state for channel 2, in Q16.
+
+ int32_t st0_ch1, st1_ch1; // channel1 state variables.
+ int32_t st0_ch2, st1_ch2; // channel2 state variables.
+ int32_t f_ch10, f_ch11, f_ch20, f_ch21; // factor variables.
+ int32_t r0, r1, r2, r3, r4, r5; // temporary register variables.
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ // Load all the state and factor variables.
+ "lh %[f_ch10], 0(%[factor_ch1]) \n\t"
+ "lh %[f_ch20], 0(%[factor_ch2]) \n\t"
+ "lh %[f_ch11], 2(%[factor_ch1]) \n\t"
+ "lh %[f_ch21], 2(%[factor_ch2]) \n\t"
+ "lw %[st0_ch1], 0(%[filter_state_ch1]) \n\t"
+ "lw %[st1_ch1], 4(%[filter_state_ch1]) \n\t"
+ "lw %[st0_ch2], 0(%[filter_state_ch2]) \n\t"
+ "lw %[st1_ch2], 4(%[filter_state_ch2]) \n\t"
+ // Allpass filtering loop.
+ "1: \n\t"
+ "lh %[r0], 0(%[data_ch1]) \n\t"
+ "lh %[r1], 0(%[data_ch2]) \n\t"
+ "addiu %[length], %[length], -1 \n\t"
+ "mul %[r2], %[r0], %[f_ch10] \n\t"
+ "mul %[r3], %[r1], %[f_ch20] \n\t"
+ "sll %[r0], %[r0], 16 \n\t"
+ "sll %[r1], %[r1], 16 \n\t"
+ "sll %[r2], %[r2], 1 \n\t"
+ "addq_s.w %[r2], %[r2], %[st0_ch1] \n\t"
+ "sll %[r3], %[r3], 1 \n\t"
+ "addq_s.w %[r3], %[r3], %[st0_ch2] \n\t"
+ "sra %[r2], %[r2], 16 \n\t"
+ "mul %[st0_ch1], %[f_ch10], %[r2] \n\t"
+ "sra %[r3], %[r3], 16 \n\t"
+ "mul %[st0_ch2], %[f_ch20], %[r3] \n\t"
+ "mul %[r4], %[r2], %[f_ch11] \n\t"
+ "mul %[r5], %[r3], %[f_ch21] \n\t"
+ "sll %[st0_ch1], %[st0_ch1], 1 \n\t"
+ "subq_s.w %[st0_ch1], %[r0], %[st0_ch1] \n\t"
+ "sll %[st0_ch2], %[st0_ch2], 1 \n\t"
+ "subq_s.w %[st0_ch2], %[r1], %[st0_ch2] \n\t"
+ "sll %[r4], %[r4], 1 \n\t"
+ "addq_s.w %[r4], %[r4], %[st1_ch1] \n\t"
+ "sll %[r5], %[r5], 1 \n\t"
+ "addq_s.w %[r5], %[r5], %[st1_ch2] \n\t"
+ "sra %[r4], %[r4], 16 \n\t"
+ "mul %[r0], %[r4], %[f_ch11] \n\t"
+ "sra %[r5], %[r5], 16 \n\t"
+ "mul %[r1], %[r5], %[f_ch21] \n\t"
+ "sh %[r4], 0(%[data_ch1]) \n\t"
+ "sh %[r5], 0(%[data_ch2]) \n\t"
+ "addiu %[data_ch1], %[data_ch1], 2 \n\t"
+ "sll %[r2], %[r2], 16 \n\t"
+ "sll %[r0], %[r0], 1 \n\t"
+ "subq_s.w %[st1_ch1], %[r2], %[r0] \n\t"
+ "sll %[r3], %[r3], 16 \n\t"
+ "sll %[r1], %[r1], 1 \n\t"
+ "subq_s.w %[st1_ch2], %[r3], %[r1] \n\t"
+ "bgtz %[length], 1b \n\t"
+ " addiu %[data_ch2], %[data_ch2], 2 \n\t"
+ // Store channel states.
+ "sw %[st0_ch1], 0(%[filter_state_ch1]) \n\t"
+ "sw %[st1_ch1], 4(%[filter_state_ch1]) \n\t"
+ "sw %[st0_ch2], 0(%[filter_state_ch2]) \n\t"
+ "sw %[st1_ch2], 4(%[filter_state_ch2]) \n\t"
+ ".set pop \n\t"
+ : [f_ch10] "=&r" (f_ch10), [f_ch20] "=&r" (f_ch20),
+ [f_ch11] "=&r" (f_ch11), [f_ch21] "=&r" (f_ch21),
+ [st0_ch1] "=&r" (st0_ch1), [st1_ch1] "=&r" (st1_ch1),
+ [st0_ch2] "=&r" (st0_ch2), [st1_ch2] "=&r" (st1_ch2),
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
+ [r3] "=&r" (r3), [r4] "=&r" (r4), [r5] "=&r" (r5)
+ : [factor_ch1] "r" (factor_ch1), [factor_ch2] "r" (factor_ch2),
+ [filter_state_ch1] "r" (filter_state_ch1),
+ [filter_state_ch2] "r" (filter_state_ch2),
+ [data_ch1] "r" (data_ch1), [data_ch2] "r" (data_ch2),
+ [length] "r" (length)
+ : "memory", "hi", "lo"
+ );
+}
+
+// WebRtcIsacfix_HighpassFilterFixDec32 function optimized for MIPSDSP platform.
+// Bit-exact with WebRtcIsacfix_HighpassFilterFixDec32C from filterbanks.c.
+void WebRtcIsacfix_HighpassFilterFixDec32MIPS(int16_t* io,
+ int16_t len,
+ const int16_t* coefficient,
+ int32_t* state) {
+ int k;
+ int32_t a1, a2, b1, b2, in;
+ int32_t state0 = state[0];
+ int32_t state1 = state[1];
+
+ int32_t c0, c1, c2, c3;
+ int32_t c4, c5, c6, c7;
+ int32_t state0_lo, state0_hi;
+ int32_t state1_lo, state1_hi;
+ int32_t t0, t1, t2, t3, t4, t5;
+
+ __asm __volatile (
+ "lh %[c0], 0(%[coeff_ptr]) \n\t"
+ "lh %[c1], 2(%[coeff_ptr]) \n\t"
+ "lh %[c2], 4(%[coeff_ptr]) \n\t"
+ "lh %[c3], 6(%[coeff_ptr]) \n\t"
+ "sra %[state0_hi], %[state0], 16 \n\t"
+ "sra %[state1_hi], %[state1], 16 \n\t"
+ "andi %[state0_lo], %[state0], 0xFFFF \n\t"
+ "andi %[state1_lo], %[state1], 0xFFFF \n\t"
+ "lh %[c4], 8(%[coeff_ptr]) \n\t"
+ "lh %[c5], 10(%[coeff_ptr]) \n\t"
+ "lh %[c6], 12(%[coeff_ptr]) \n\t"
+ "lh %[c7], 14(%[coeff_ptr]) \n\t"
+ "sra %[state0_lo], %[state0_lo], 1 \n\t"
+ "sra %[state1_lo], %[state1_lo], 1 \n\t"
+ : [c0] "=&r" (c0), [c1] "=&r" (c1), [c2] "=&r" (c2), [c3] "=&r" (c3),
+ [c4] "=&r" (c4), [c5] "=&r" (c5), [c6] "=&r" (c6), [c7] "=&r" (c7),
+ [state0_hi] "=&r" (state0_hi), [state0_lo] "=&r" (state0_lo),
+ [state1_hi] "=&r" (state1_hi), [state1_lo] "=&r" (state1_lo)
+ : [coeff_ptr] "r" (coefficient), [state0] "r" (state0),
+ [state1] "r" (state1)
+ : "memory"
+ );
+
+ for (k = 0; k < len; k++) {
+ in = (int32_t)io[k];
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "mul %[t2], %[c4], %[state0_lo] \n\t"
+ "mul %[t0], %[c5], %[state0_lo] \n\t"
+ "mul %[t1], %[c4], %[state0_hi] \n\t"
+ "mul %[a1], %[c5], %[state0_hi] \n\t"
+ "mul %[t5], %[c6], %[state1_lo] \n\t"
+ "mul %[t3], %[c7], %[state1_lo] \n\t"
+ "mul %[t4], %[c6], %[state1_hi] \n\t"
+ "mul %[b1], %[c7], %[state1_hi] \n\t"
+ "shra_r.w %[t2], %[t2], 15 \n\t"
+ "shra_r.w %[t0], %[t0], 15 \n\t"
+ "addu %[t1], %[t1], %[t2] \n\t"
+ "addu %[a1], %[a1], %[t0] \n\t"
+ "sra %[t1], %[t1], 16 \n\t"
+ "addu %[a1], %[a1], %[t1] \n\t"
+ "shra_r.w %[t5], %[t5], 15 \n\t"
+ "shra_r.w %[t3], %[t3], 15 \n\t"
+ "addu %[t4], %[t4], %[t5] \n\t"
+ "addu %[b1], %[b1], %[t3] \n\t"
+ "sra %[t4], %[t4], 16 \n\t"
+ "addu %[b1], %[b1], %[t4] \n\t"
+ "mul %[t2], %[c0], %[state0_lo] \n\t"
+ "mul %[t0], %[c1], %[state0_lo] \n\t"
+ "mul %[t1], %[c0], %[state0_hi] \n\t"
+ "mul %[a2], %[c1], %[state0_hi] \n\t"
+ "mul %[t5], %[c2], %[state1_lo] \n\t"
+ "mul %[t3], %[c3], %[state1_lo] \n\t"
+ "mul %[t4], %[c2], %[state1_hi] \n\t"
+ "mul %[b2], %[c3], %[state1_hi] \n\t"
+ "shra_r.w %[t2], %[t2], 15 \n\t"
+ "shra_r.w %[t0], %[t0], 15 \n\t"
+ "addu %[t1], %[t1], %[t2] \n\t"
+ "addu %[a2], %[a2], %[t0] \n\t"
+ "sra %[t1], %[t1], 16 \n\t"
+ "addu %[a2], %[a2], %[t1] \n\t"
+ "shra_r.w %[t5], %[t5], 15 \n\t"
+ "shra_r.w %[t3], %[t3], 15 \n\t"
+ "addu %[t4], %[t4], %[t5] \n\t"
+ "addu %[b2], %[b2], %[t3] \n\t"
+ "sra %[t4], %[t4], 16 \n\t"
+ "addu %[b2], %[b2], %[t4] \n\t"
+ "addu %[a1], %[a1], %[b1] \n\t"
+ "sra %[a1], %[a1], 7 \n\t"
+ "addu %[a1], %[a1], %[in] \n\t"
+ "sll %[t0], %[in], 2 \n\t"
+ "addu %[a2], %[a2], %[b2] \n\t"
+ "subu %[t0], %[t0], %[a2] \n\t"
+ "shll_s.w %[a1], %[a1], 16 \n\t"
+ "shll_s.w %[t0], %[t0], 2 \n\t"
+ "sra %[a1], %[a1], 16 \n\t"
+ "addu %[state1_hi], %[state0_hi], $0 \n\t"
+ "addu %[state1_lo], %[state0_lo], $0 \n\t"
+ "sra %[state0_hi], %[t0], 16 \n\t"
+ "andi %[state0_lo], %[t0], 0xFFFF \n\t"
+ "sra %[state0_lo], %[state0_lo], 1 \n\t"
+ ".set pop \n\t"
+ : [a1] "=&r" (a1), [b1] "=&r" (b1), [a2] "=&r" (a2), [b2] "=&r" (b2),
+ [state0_hi] "+r" (state0_hi), [state0_lo] "+r" (state0_lo),
+ [state1_hi] "+r" (state1_hi), [state1_lo] "+r" (state1_lo),
+ [t0] "=&r" (t0), [t1] "=&r" (t1), [t2] "=&r" (t2),
+ [t3] "=&r" (t3), [t4] "=&r" (t4), [t5] "=&r" (t5)
+ : [c0] "r" (c0), [c1] "r" (c1), [c2] "r" (c2), [c3] "r" (c3),
+ [c4] "r" (c4), [c5] "r" (c5), [c6] "r" (c6), [c7] "r" (c7),
+ [in] "r" (in)
+ : "hi", "lo"
+ );
+ io[k] = (int16_t)a1;
+ }
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+#if !defined(MIPS_DSP_R2_LE)
+ "sll %[state0_hi], %[state0_hi], 16 \n\t"
+ "sll %[state0_lo], %[state0_lo], 1 \n\t"
+ "sll %[state1_hi], %[state1_hi], 16 \n\t"
+ "sll %[state1_lo], %[state1_lo], 1 \n\t"
+ "or %[state0_hi], %[state0_hi], %[state0_lo] \n\t"
+ "or %[state1_hi], %[state1_hi], %[state1_lo] \n\t"
+#else
+ "sll %[state0_lo], %[state0_lo], 1 \n\t"
+ "sll %[state1_lo], %[state1_lo], 1 \n\t"
+ "precr_sra.ph.w %[state0_hi], %[state0_lo], 0 \n\t"
+ "precr_sra.ph.w %[state1_hi], %[state1_lo], 0 \n\t"
+#endif
+ "sw %[state0_hi], 0(%[state]) \n\t"
+ "sw %[state1_hi], 4(%[state]) \n\t"
+ ".set pop \n\t"
+ : [state0_hi] "+r" (state0_hi), [state0_lo] "+r" (state0_lo),
+ [state1_hi] "+r" (state1_hi), [state1_lo] "+r" (state1_lo)
+ : [state] "r" (state)
+ : "memory"
+ );
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c
new file mode 100644
index 0000000000..a31cea6001
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// Contains a function for WebRtcIsacfix_AllpassFilter2FixDec16Neon()
+// in iSAC codec, optimized for ARM Neon platform. Bit exact with function
+// WebRtcIsacfix_AllpassFilter2FixDec16C() in filterbanks.c. Prototype
+// C code is at end of this file.
+
+#include <arm_neon.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "rtc_base/checks.h"
+
+void WebRtcIsacfix_AllpassFilter2FixDec16Neon(
+ int16_t* data_ch1, // Input and output in channel 1, in Q0
+ int16_t* data_ch2, // Input and output in channel 2, in Q0
+ const int16_t* factor_ch1, // Scaling factor for channel 1, in Q15
+ const int16_t* factor_ch2, // Scaling factor for channel 2, in Q15
+ const int length, // Length of the data buffers
+ int32_t* filter_state_ch1, // Filter state for channel 1, in Q16
+ int32_t* filter_state_ch2) { // Filter state for channel 2, in Q16
+ RTC_DCHECK_EQ(0, length % 2);
+ int n = 0;
+ int16x4_t factorv;
+ int16x4_t datav;
+ int32x4_t statev;
+
+ // Load factor_ch1 and factor_ch2.
+ factorv = vld1_dup_s16(factor_ch1);
+ factorv = vld1_lane_s16(factor_ch1 + 1, factorv, 1);
+ factorv = vld1_lane_s16(factor_ch2, factorv, 2);
+ factorv = vld1_lane_s16(factor_ch2 + 1, factorv, 3);
+
+ // Load filter_state_ch1[0] and filter_state_ch2[0].
+ statev = vld1q_dup_s32(filter_state_ch1);
+ statev = vld1q_lane_s32(filter_state_ch2, statev, 2);
+
+ // Loop unrolling preprocessing.
+ int32x4_t a;
+ int16x4_t tmp1, tmp2;
+
+ // Load data_ch1[0] and data_ch2[0].
+ datav = vld1_dup_s16(data_ch1);
+ datav = vld1_lane_s16(data_ch2, datav, 2);
+
+ a = vqdmlal_s16(statev, datav, factorv);
+ tmp1 = vshrn_n_s32(a, 16);
+
+ // Update filter_state_ch1[0] and filter_state_ch2[0].
+ statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp1, factorv);
+
+ // Load filter_state_ch1[1] and filter_state_ch2[1].
+ statev = vld1q_lane_s32(filter_state_ch1 + 1, statev, 1);
+ statev = vld1q_lane_s32(filter_state_ch2 + 1, statev, 3);
+
+ // Load data_ch1[1] and data_ch2[1].
+ tmp1 = vld1_lane_s16(data_ch1 + 1, tmp1, 1);
+ tmp1 = vld1_lane_s16(data_ch2 + 1, tmp1, 3);
+ datav = vrev32_s16(tmp1);
+
+ // Loop unrolling processing.
+ for (n = 0; n < length - 2; n += 2) {
+ a = vqdmlal_s16(statev, datav, factorv);
+ tmp1 = vshrn_n_s32(a, 16);
+ // Store data_ch1[n] and data_ch2[n].
+ vst1_lane_s16(data_ch1 + n, tmp1, 1);
+ vst1_lane_s16(data_ch2 + n, tmp1, 3);
+
+ // Update filter_state_ch1[0], filter_state_ch1[1]
+ // and filter_state_ch2[0], filter_state_ch2[1].
+ statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp1, factorv);
+
+ // Load data_ch1[n + 2] and data_ch2[n + 2].
+ tmp1 = vld1_lane_s16(data_ch1 + n + 2, tmp1, 1);
+ tmp1 = vld1_lane_s16(data_ch2 + n + 2, tmp1, 3);
+ datav = vrev32_s16(tmp1);
+
+ a = vqdmlal_s16(statev, datav, factorv);
+ tmp2 = vshrn_n_s32(a, 16);
+ // Store data_ch1[n + 1] and data_ch2[n + 1].
+ vst1_lane_s16(data_ch1 + n + 1, tmp2, 1);
+ vst1_lane_s16(data_ch2 + n + 1, tmp2, 3);
+
+ // Update filter_state_ch1[0], filter_state_ch1[1]
+ // and filter_state_ch2[0], filter_state_ch2[1].
+ statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp2, factorv);
+
+ // Load data_ch1[n + 3] and data_ch2[n + 3].
+ tmp2 = vld1_lane_s16(data_ch1 + n + 3, tmp2, 1);
+ tmp2 = vld1_lane_s16(data_ch2 + n + 3, tmp2, 3);
+ datav = vrev32_s16(tmp2);
+ }
+
+ // Loop unrolling post-processing.
+ a = vqdmlal_s16(statev, datav, factorv);
+ tmp1 = vshrn_n_s32(a, 16);
+ // Store data_ch1[n] and data_ch2[n].
+ vst1_lane_s16(data_ch1 + n, tmp1, 1);
+ vst1_lane_s16(data_ch2 + n, tmp1, 3);
+
+ // Update filter_state_ch1[0], filter_state_ch1[1]
+ // and filter_state_ch2[0], filter_state_ch2[1].
+ statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp1, factorv);
+ // Store filter_state_ch1[0] and filter_state_ch2[0].
+ vst1q_lane_s32(filter_state_ch1, statev, 0);
+ vst1q_lane_s32(filter_state_ch2, statev, 2);
+
+ datav = vrev32_s16(tmp1);
+ a = vqdmlal_s16(statev, datav, factorv);
+ tmp2 = vshrn_n_s32(a, 16);
+ // Store data_ch1[n + 1] and data_ch2[n + 1].
+ vst1_lane_s16(data_ch1 + n + 1, tmp2, 1);
+ vst1_lane_s16(data_ch2 + n + 1, tmp2, 3);
+
+ // Update filter_state_ch1[1] and filter_state_ch2[1].
+ statev = vqdmlsl_s16(vshll_n_s16(datav, 16), tmp2, factorv);
+ // Store filter_state_ch1[1] and filter_state_ch2[1].
+ vst1q_lane_s32(filter_state_ch1 + 1, statev, 1);
+ vst1q_lane_s32(filter_state_ch2 + 1, statev, 3);
+}
+
+// This function is the prototype for above neon optimized function.
+//void AllpassFilter2FixDec16BothChannels(
+// int16_t *data_ch1, // Input and output in channel 1, in Q0
+// int16_t *data_ch2, // Input and output in channel 2, in Q0
+// const int16_t *factor_ch1, // Scaling factor for channel 1, in Q15
+// const int16_t *factor_ch2, // Scaling factor for channel 2, in Q15
+// const int length, // Length of the data buffers
+// int32_t *filter_state_ch1, // Filter state for channel 1, in Q16
+// int32_t *filter_state_ch2) { // Filter state for channel 2, in Q16
+// int n = 0;
+// int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
+// int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
+// int16_t sample0_ch1 = 0, sample0_ch2 = 0;
+// int16_t sample1_ch1 = 0, sample1_ch2 = 0;
+// int32_t a0_ch1 = 0, a0_ch2 = 0;
+// int32_t b0_ch1 = 0, b0_ch2 = 0;
+//
+// int32_t a1_ch1 = 0, a1_ch2 = 0;
+// int32_t b1_ch1 = 0, b1_ch2 = 0;
+// int32_t b2_ch1 = 0, b2_ch2 = 0;
+//
+// // Loop unrolling preprocessing.
+//
+// sample0_ch1 = data_ch1[n];
+// sample0_ch2 = data_ch2[n];
+//
+// a0_ch1 = (factor_ch1[0] * sample0_ch1) << 1;
+// a0_ch2 = (factor_ch2[0] * sample0_ch2) << 1;
+//
+// b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state0_ch1);
+// b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state0_ch2); //Q16+Q16=Q16
+//
+// a0_ch1 = -factor_ch1[0] * (int16_t)(b0_ch1 >> 16);
+// a0_ch2 = -factor_ch2[0] * (int16_t)(b0_ch2 >> 16);
+//
+// state0_ch1 = WebRtcSpl_AddSatW32(a0_ch1 <<1, (uint32_t)sample0_ch1 << 16);
+// state0_ch2 = WebRtcSpl_AddSatW32(a0_ch2 <<1, (uint32_t)sample0_ch2 << 16);
+//
+// sample1_ch1 = data_ch1[n + 1];
+// sample0_ch1 = (int16_t) (b0_ch1 >> 16); //Save as Q0
+// sample1_ch2 = data_ch2[n + 1];
+// sample0_ch2 = (int16_t) (b0_ch2 >> 16); //Save as Q0
+//
+//
+// for (n = 0; n < length - 2; n += 2) {
+// a1_ch1 = (factor_ch1[0] * sample1_ch1) << 1;
+// a0_ch1 = (factor_ch1[1] * sample0_ch1) << 1;
+// a1_ch2 = (factor_ch2[0] * sample1_ch2) << 1;
+// a0_ch2 = (factor_ch2[1] * sample0_ch2) << 1;
+//
+// b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state0_ch1);
+// b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state1_ch1); //Q16+Q16=Q16
+// b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state0_ch2); //Q16+Q16=Q16
+// b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state1_ch2); //Q16+Q16=Q16
+//
+// a1_ch1 = -factor_ch1[0] * (int16_t)(b1_ch1 >> 16);
+// a0_ch1 = -factor_ch1[1] * (int16_t)(b0_ch1 >> 16);
+// a1_ch2 = -factor_ch2[0] * (int16_t)(b1_ch2 >> 16);
+// a0_ch2 = -factor_ch2[1] * (int16_t)(b0_ch2 >> 16);
+//
+// state0_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1 <<16);
+// state1_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1 <<16);
+// state0_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2 <<16);
+// state1_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2 <<16);
+//
+// sample0_ch1 = data_ch1[n + 2];
+// sample1_ch1 = (int16_t) (b1_ch1 >> 16); //Save as Q0
+// sample0_ch2 = data_ch2[n + 2];
+// sample1_ch2 = (int16_t) (b1_ch2 >> 16); //Save as Q0
+//
+// a0_ch1 = (factor_ch1[0] * sample0_ch1) << 1;
+// a1_ch1 = (factor_ch1[1] * sample1_ch1) << 1;
+// a0_ch2 = (factor_ch2[0] * sample0_ch2) << 1;
+// a1_ch2 = (factor_ch2[1] * sample1_ch2) << 1;
+//
+// b2_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state0_ch1);
+// b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state1_ch1); //Q16+Q16=Q16
+// b2_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state0_ch2); //Q16+Q16=Q16
+// b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state1_ch2); //Q16+Q16=Q16
+//
+// a0_ch1 = -factor_ch1[0] * (int16_t)(b2_ch1 >> 16);
+// a1_ch1 = -factor_ch1[1] * (int16_t)(b1_ch1 >> 16);
+// a0_ch2 = -factor_ch2[0] * (int16_t)(b2_ch2 >> 16);
+// a1_ch2 = -factor_ch2[1] * (int16_t)(b1_ch2 >> 16);
+//
+// state0_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1<<16);
+// state1_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1<<16);
+// state0_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2<<16);
+// state1_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2<<16);
+//
+//
+// sample1_ch1 = data_ch1[n + 3];
+// sample0_ch1 = (int16_t) (b2_ch1 >> 16); //Save as Q0
+// sample1_ch2 = data_ch2[n + 3];
+// sample0_ch2 = (int16_t) (b2_ch2 >> 16); //Save as Q0
+//
+// data_ch1[n] = (int16_t) (b0_ch1 >> 16); //Save as Q0
+// data_ch1[n + 1] = (int16_t) (b1_ch1 >> 16); //Save as Q0
+// data_ch2[n] = (int16_t) (b0_ch2 >> 16);
+// data_ch2[n + 1] = (int16_t) (b1_ch2 >> 16);
+// }
+//
+// // Loop unrolling post-processing.
+//
+// a1_ch1 = (factor_ch1[0] * sample1_ch1) << 1;
+// a0_ch1 = (factor_ch1[1] * sample0_ch1) << 1;
+// a1_ch2 = (factor_ch2[0] * sample1_ch2) << 1;
+// a0_ch2 = (factor_ch2[1] * sample0_ch2) << 1;
+//
+// b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state0_ch1);
+// b0_ch1 = WebRtcSpl_AddSatW32(a0_ch1, state1_ch1);
+// b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state0_ch2);
+// b0_ch2 = WebRtcSpl_AddSatW32(a0_ch2, state1_ch2);
+//
+// a1_ch1 = -factor_ch1[0] * (int16_t)(b1_ch1 >> 16);
+// a0_ch1 = -factor_ch1[1] * (int16_t)(b0_ch1 >> 16);
+// a1_ch2 = -factor_ch2[0] * (int16_t)(b1_ch2 >> 16);
+// a0_ch2 = -factor_ch2[1] * (int16_t)(b0_ch2 >> 16);
+//
+// state0_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1 << 16);
+// state1_ch1 = WebRtcSpl_AddSatW32(a0_ch1<<1, (uint32_t)sample0_ch1 << 16);
+// state0_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2 << 16);
+// state1_ch2 = WebRtcSpl_AddSatW32(a0_ch2<<1, (uint32_t)sample0_ch2 << 16);
+//
+// data_ch1[n] = (int16_t) (b0_ch1 >> 16); //Save as Q0
+// data_ch2[n] = (int16_t) (b0_ch2 >> 16);
+//
+// sample1_ch1 = (int16_t) (b1_ch1 >> 16); //Save as Q0
+// sample1_ch2 = (int16_t) (b1_ch2 >> 16); //Save as Q0
+//
+// a1_ch1 = (factor_ch1[1] * sample1_ch1) << 1;
+// a1_ch2 = (factor_ch2[1] * sample1_ch2) << 1;
+//
+// b1_ch1 = WebRtcSpl_AddSatW32(a1_ch1, state1_ch1); //Q16+Q16=Q16
+// b1_ch2 = WebRtcSpl_AddSatW32(a1_ch2, state1_ch2); //Q16+Q16=Q16
+//
+// a1_ch1 = -factor_ch1[1] * (int16_t)(b1_ch1 >> 16);
+// a1_ch2 = -factor_ch2[1] * (int16_t)(b1_ch2 >> 16);
+//
+// state1_ch1 = WebRtcSpl_AddSatW32(a1_ch1<<1, (uint32_t)sample1_ch1<<16);
+// state1_ch2 = WebRtcSpl_AddSatW32(a1_ch2<<1, (uint32_t)sample1_ch2<<16);
+//
+// data_ch1[n + 1] = (int16_t) (b1_ch1 >> 16); //Save as Q0
+// data_ch2[n + 1] = (int16_t) (b1_ch2 >> 16);
+//
+// filter_state_ch1[0] = state0_ch1;
+// filter_state_ch1[1] = state1_ch1;
+// filter_state_ch2[0] = state0_ch2;
+// filter_state_ch2[1] = state1_ch2;
+//}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
new file mode 100644
index 0000000000..4a3db2324a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/sanitizer.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+class FilterBanksTest : public ::testing::Test {
+ protected:
+ // Pass a function pointer to the Tester function.
+ void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5513
+ CalculateResidualEnergyTester(
+ AllpassFilter2FixDec16 AllpassFilter2FixDec16Function) {
+ const int kSamples = QLOOKAHEAD;
+ const int kState = 2;
+ int16_t data_ch1[kSamples] = {0};
+ int16_t data_ch2[kSamples] = {0};
+ int32_t state_ch1[kState] = {0};
+ int32_t state_ch2[kState] = {0};
+ const int32_t out_state_ch1[kState] = {-809122714, 1645972152};
+ const int32_t out_state_ch2[kState] = {428019288, 1057309936};
+ const int32_t out_data_ch1[kSamples] = {
+ 0, 0, 347, 10618, 16718, -7089, 32767, 16913,
+ 27042, 8377, -22973, -28372, -27603, -14804, 398, -25332,
+ -11200, 18044, 25223, -6839, 1116, -23984, 32717, 7364};
+ const int32_t out_data_ch2[kSamples] = {
+ 0, 0, 3010, 22351, 21106, 16969, -2095, -664,
+ 3513, -30980, 32767, -23839, 13335, 20289, -6831, 339,
+ -17207, 32767, 4959, 6177, 32767, 16599, -4747, 20504};
+ int sign = 1;
+
+ for (int i = 0; i < kSamples; i++) {
+ sign *= -1;
+ data_ch1[i] = sign * WEBRTC_SPL_WORD32_MAX / (i * i + 1);
+ data_ch2[i] = sign * WEBRTC_SPL_WORD32_MIN / (i * i + 1);
+ // UBSan: -1 * -2147483648 cannot be represented in type 'int'
+ };
+
+ AllpassFilter2FixDec16Function(
+ data_ch1, data_ch2, WebRtcIsacfix_kUpperApFactorsQ15,
+ WebRtcIsacfix_kLowerApFactorsQ15, kSamples, state_ch1, state_ch2);
+
+ for (int i = 0; i < kSamples; i++) {
+ EXPECT_EQ(out_data_ch1[i], data_ch1[i]);
+ EXPECT_EQ(out_data_ch2[i], data_ch2[i]);
+ }
+ for (int i = 0; i < kState; i++) {
+ EXPECT_EQ(out_state_ch1[i], state_ch1[i]);
+ EXPECT_EQ(out_state_ch2[i], state_ch2[i]);
+ }
+ }
+};
+
+TEST_F(FilterBanksTest, AllpassFilter2FixDec16Test) {
+ CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16C);
+#if defined(WEBRTC_HAS_NEON)
+ CalculateResidualEnergyTester(WebRtcIsacfix_AllpassFilter2FixDec16Neon);
+#endif
+}
+
+TEST_F(FilterBanksTest, HighpassFilterFixDec32Test) {
+ const int kSamples = 20;
+ int16_t in[kSamples];
+ int32_t state[2] = {12345, 987654};
+#ifdef WEBRTC_ARCH_ARM_V7
+ int32_t out[kSamples] = {-1040, -1035, -22875, -1397, -27604, 20018, 7917,
+ -1279, -8552, -14494, -7558, -23537, -27258, -30554,
+ -32768, -3432, -32768, 25215, -27536, 22436};
+#else
+ int32_t out[kSamples] = {-1040, -1035, -22875, -1397, -27604, 20017, 7915,
+ -1280, -8554, -14496, -7561, -23541, -27263, -30560,
+ -32768, -3441, -32768, 25203, -27550, 22419};
+#endif
+ HighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
+#if defined(MIPS_DSP_R1_LE)
+ WebRtcIsacfix_HighpassFilterFixDec32 =
+ WebRtcIsacfix_HighpassFilterFixDec32MIPS;
+#else
+ WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
+#endif
+
+ for (int i = 0; i < kSamples; i++) {
+ in[i] = WEBRTC_SPL_WORD32_MAX / (i + 1);
+ }
+
+ WebRtcIsacfix_HighpassFilterFixDec32(in, kSamples,
+ WebRtcIsacfix_kHPStCoeffOut1Q30, state);
+
+ for (int i = 0; i < kSamples; i++) {
+ EXPECT_EQ(out[i], in[i]);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters.c
new file mode 100644
index 0000000000..838ba4b3e8
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+// Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrC(int32_t* __restrict r,
+ const int16_t* __restrict x,
+ int16_t N,
+ int16_t order,
+ int16_t* __restrict scale) {
+ int i = 0;
+ int j = 0;
+ int16_t scaling = 0;
+ int32_t sum = 0;
+ uint32_t temp = 0;
+ int64_t prod = 0;
+
+ // The ARM assembly code assumptoins.
+ RTC_DCHECK_EQ(0, N % 4);
+ RTC_DCHECK_GE(N, 8);
+
+ // Calculate r[0].
+ for (i = 0; i < N; i++) {
+ prod += x[i] * x[i];
+ }
+
+ // Calculate scaling (the value of shifting).
+ temp = (uint32_t)(prod >> 31);
+ if(temp == 0) {
+ scaling = 0;
+ } else {
+ scaling = 32 - WebRtcSpl_NormU32(temp);
+ }
+ r[0] = (int32_t)(prod >> scaling);
+
+ // Perform the actual correlation calculation.
+ for (i = 1; i < order + 1; i++) {
+ prod = 0;
+ for (j = 0; j < N - i; j++) {
+ prod += x[j] * x[i + j];
+ }
+ sum = (int32_t)(prod >> scaling);
+ r[i] = sum;
+ }
+
+ *scale = scaling;
+
+ return(order + 1);
+}
+
+static const int32_t kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 };
+static const int32_t kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 };
+
+
+static void AllpassFilterForDec32(int16_t *InOut16, //Q0
+ const int32_t *APSectionFactors, //Q15
+ int16_t lengthInOut,
+ int32_t *FilterState) //Q16
+{
+ int n, j;
+ int32_t a, b;
+
+ for (j=0; j<ALLPASSSECTIONS; j++) {
+ for (n=0;n<lengthInOut;n+=2){
+ a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15
+ a <<= 1; // Q15 -> Q16
+ b = WebRtcSpl_AddSatW32(a, FilterState[j]); //Q16+Q16=Q16
+ // `a` in Q15 (Q0*Q31=Q31 shifted 16 gives Q15).
+ a = WEBRTC_SPL_MUL_16_32_RSFT16(b >> 16, -APSectionFactors[j]);
+ // FilterState[j]: Q15<<1 + Q0<<16 = Q16 + Q16 = Q16
+ FilterState[j] = WebRtcSpl_AddSatW32(a << 1, (uint32_t)InOut16[n] << 16);
+ InOut16[n] = (int16_t)(b >> 16); // Save as Q0.
+ }
+ }
+}
+
+
+
+
+void WebRtcIsacfix_DecimateAllpass32(const int16_t *in,
+ int32_t *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ int16_t N, /* number of input samples */
+ int16_t *out) /* array of size N/2 */
+{
+ int n;
+ int16_t data_vec[PITCH_FRAME_LEN];
+
+ /* copy input */
+ memcpy(data_vec + 1, in, sizeof(int16_t) * (N - 1));
+
+ data_vec[0] = (int16_t)(state_in[2 * ALLPASSSECTIONS] >> 16); // z^-1 state.
+ state_in[2 * ALLPASSSECTIONS] = (uint32_t)in[N - 1] << 16;
+
+
+
+ AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in);
+ AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS);
+
+ for (n=0;n<N/2;n++) {
+ out[n] = WebRtcSpl_AddSatW16(data_vec[2 * n], data_vec[2 * n + 1]);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_mips.c
new file mode 100644
index 0000000000..ded3d03209
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_mips.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+// MIPS optimized implementation of the Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrMIPS(int32_t* __restrict r,
+ const int16_t* __restrict x,
+ int16_t N,
+ int16_t order,
+ int16_t* __restrict scale) {
+ int i = 0;
+ int16_t scaling = 0;
+ int16_t* in = (int16_t*)x;
+ int loop_size = (int)(N >> 3);
+ int count = (int)(N & 7);
+ // Declare temporary variables used as registry values.
+ int32_t r0, r1, r2, r3;
+#if !defined(MIPS_DSP_R2_LE)
+ // For non-DSPR2 optimizations 4 more registers are used.
+ int32_t r4, r5, r6, r7;
+#endif
+
+ // Calculate r[0] and scaling needed.
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "mult $0, $0 \n\t"
+ // Loop is unrolled 8 times, set accumulator to zero in branch delay slot.
+ "beqz %[loop_size], 2f \n\t"
+ " mult $0, $0 \n\t"
+ "1: \n\t"
+ // Load 8 samples per loop iteration.
+#if defined(MIPS_DSP_R2_LE)
+ "ulw %[r0], 0(%[in]) \n\t"
+ "ulw %[r1], 4(%[in]) \n\t"
+ "ulw %[r2], 8(%[in]) \n\t"
+ "ulw %[r3], 12(%[in]) \n\t"
+#else
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 2(%[in]) \n\t"
+ "lh %[r2], 4(%[in]) \n\t"
+ "lh %[r3], 6(%[in]) \n\t"
+ "lh %[r4], 8(%[in]) \n\t"
+ "lh %[r5], 10(%[in]) \n\t"
+ "lh %[r6], 12(%[in]) \n\t"
+ "lh %[r7], 14(%[in]) \n\t"
+#endif
+ "addiu %[loop_size], %[loop_size], -1 \n\t"
+ // Multiply and accumulate.
+#if defined(MIPS_DSP_R2_LE)
+ "dpa.w.ph $ac0, %[r0], %[r0] \n\t"
+ "dpa.w.ph $ac0, %[r1], %[r1] \n\t"
+ "dpa.w.ph $ac0, %[r2], %[r2] \n\t"
+ "dpa.w.ph $ac0, %[r3], %[r3] \n\t"
+#else
+ "madd %[r0], %[r0] \n\t"
+ "madd %[r1], %[r1] \n\t"
+ "madd %[r2], %[r2] \n\t"
+ "madd %[r3], %[r3] \n\t"
+ "madd %[r4], %[r4] \n\t"
+ "madd %[r5], %[r5] \n\t"
+ "madd %[r6], %[r6] \n\t"
+ "madd %[r7], %[r7] \n\t"
+#endif
+ "bnez %[loop_size], 1b \n\t"
+ " addiu %[in], %[in], 16 \n\t"
+ "2: \n\t"
+ "beqz %[count], 4f \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ " extr.w %[r0], $ac0, 31 \n\t"
+#else
+ " mfhi %[r2] \n\t"
+#endif
+ // Process remaining samples (if any).
+ "3: \n\t"
+ "lh %[r0], 0(%[in]) \n\t"
+ "addiu %[count], %[count], -1 \n\t"
+ "madd %[r0], %[r0] \n\t"
+ "bnez %[count], 3b \n\t"
+ " addiu %[in], %[in], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "extr.w %[r0], $ac0, 31 \n\t"
+#else
+ "mfhi %[r2] \n\t"
+#endif
+ "4: \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+ "mflo %[r3] \n\t"
+ "sll %[r0], %[r2], 1 \n\t"
+ "srl %[r1], %[r3], 31 \n\t"
+ "addu %[r0], %[r0], %[r1] \n\t"
+#endif
+ // Calculate scaling (the value of shifting).
+ "clz %[r1], %[r0] \n\t"
+ "addiu %[r1], %[r1], -32 \n\t"
+ "subu %[scaling], $0, %[r1] \n\t"
+ "slti %[r1], %[r0], 0x1 \n\t"
+ "movn %[scaling], $0, %[r1] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "extrv.w %[r0], $ac0, %[scaling] \n\t"
+ "mfhi %[r2], $ac0 \n\t"
+#else
+ "addiu %[r1], %[scaling], -32 \n\t"
+ "subu %[r1], $0, %[r1] \n\t"
+ "sllv %[r1], %[r2], %[r1] \n\t"
+ "srlv %[r0], %[r3], %[scaling] \n\t"
+ "addu %[r0], %[r0], %[r1] \n\t"
+#endif
+ "slti %[r1], %[scaling], 32 \n\t"
+ "movz %[r0], %[r2], %[r1] \n\t"
+ ".set pop \n\t"
+ : [loop_size] "+r" (loop_size), [in] "+r" (in), [r0] "=&r" (r0),
+ [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+#if !defined(MIPS_DSP_R2_LE)
+ [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+ [count] "+r" (count), [scaling] "=r" (scaling)
+ : [N] "r" (N)
+ : "memory", "hi", "lo"
+ );
+ r[0] = r0;
+
+ // Correlation calculation is divided in 3 cases depending on the scaling
+ // value (different accumulator manipulation needed). Three slightly different
+ // loops are written in order to avoid branches inside the loop.
+ if (scaling == 0) {
+ // In this case, the result will be in low part of the accumulator.
+ for (i = 1; i < order + 1; i++) {
+ in = (int16_t*)x;
+ int16_t* in1 = (int16_t*)x + i;
+ count = N - i;
+ loop_size = (count) >> 2;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "mult $0, $0 \n\t"
+ "beqz %[loop_size], 2f \n\t"
+ " andi %[count], %[count], 0x3 \n\t"
+ // Loop processing 4 pairs of samples per iteration.
+ "1: \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "ulw %[r0], 0(%[in]) \n\t"
+ "ulw %[r1], 0(%[in1]) \n\t"
+ "ulw %[r2], 4(%[in]) \n\t"
+ "ulw %[r3], 4(%[in1]) \n\t"
+#else
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 0(%[in1]) \n\t"
+ "lh %[r2], 2(%[in]) \n\t"
+ "lh %[r3], 2(%[in1]) \n\t"
+ "lh %[r4], 4(%[in]) \n\t"
+ "lh %[r5], 4(%[in1]) \n\t"
+ "lh %[r6], 6(%[in]) \n\t"
+ "lh %[r7], 6(%[in1]) \n\t"
+#endif
+ "addiu %[loop_size], %[loop_size], -1 \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "dpa.w.ph $ac0, %[r0], %[r1] \n\t"
+ "dpa.w.ph $ac0, %[r2], %[r3] \n\t"
+#else
+ "madd %[r0], %[r1] \n\t"
+ "madd %[r2], %[r3] \n\t"
+ "madd %[r4], %[r5] \n\t"
+ "madd %[r6], %[r7] \n\t"
+#endif
+ "addiu %[in], %[in], 8 \n\t"
+ "bnez %[loop_size], 1b \n\t"
+ " addiu %[in1], %[in1], 8 \n\t"
+ "2: \n\t"
+ "beqz %[count], 4f \n\t"
+ " mflo %[r0] \n\t"
+ // Process remaining samples (if any).
+ "3: \n\t"
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 0(%[in1]) \n\t"
+ "addiu %[count], %[count], -1 \n\t"
+ "addiu %[in], %[in], 2 \n\t"
+ "madd %[r0], %[r1] \n\t"
+ "bnez %[count], 3b \n\t"
+ " addiu %[in1], %[in1], 2 \n\t"
+ "mflo %[r0] \n\t"
+ "4: \n\t"
+ ".set pop \n\t"
+ : [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
+#if !defined(MIPS_DSP_R2_LE)
+ [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [count] "+r" (count)
+ :
+ : "memory", "hi", "lo"
+ );
+ r[i] = r0;
+ }
+ } else if (scaling == 32) {
+ // In this case, the result will be high part of the accumulator.
+ for (i = 1; i < order + 1; i++) {
+ in = (int16_t*)x;
+ int16_t* in1 = (int16_t*)x + i;
+ count = N - i;
+ loop_size = (count) >> 2;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "mult $0, $0 \n\t"
+ "beqz %[loop_size], 2f \n\t"
+ " andi %[count], %[count], 0x3 \n\t"
+ // Loop processing 4 pairs of samples per iteration.
+ "1: \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "ulw %[r0], 0(%[in]) \n\t"
+ "ulw %[r1], 0(%[in1]) \n\t"
+ "ulw %[r2], 4(%[in]) \n\t"
+ "ulw %[r3], 4(%[in1]) \n\t"
+#else
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 0(%[in1]) \n\t"
+ "lh %[r2], 2(%[in]) \n\t"
+ "lh %[r3], 2(%[in1]) \n\t"
+ "lh %[r4], 4(%[in]) \n\t"
+ "lh %[r5], 4(%[in1]) \n\t"
+ "lh %[r6], 6(%[in]) \n\t"
+ "lh %[r7], 6(%[in1]) \n\t"
+#endif
+ "addiu %[loop_size], %[loop_size], -1 \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "dpa.w.ph $ac0, %[r0], %[r1] \n\t"
+ "dpa.w.ph $ac0, %[r2], %[r3] \n\t"
+#else
+ "madd %[r0], %[r1] \n\t"
+ "madd %[r2], %[r3] \n\t"
+ "madd %[r4], %[r5] \n\t"
+ "madd %[r6], %[r7] \n\t"
+#endif
+ "addiu %[in], %[in], 8 \n\t"
+ "bnez %[loop_size], 1b \n\t"
+ " addiu %[in1], %[in1], 8 \n\t"
+ "2: \n\t"
+ "beqz %[count], 4f \n\t"
+ " mfhi %[r0] \n\t"
+ // Process remaining samples (if any).
+ "3: \n\t"
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 0(%[in1]) \n\t"
+ "addiu %[count], %[count], -1 \n\t"
+ "addiu %[in], %[in], 2 \n\t"
+ "madd %[r0], %[r1] \n\t"
+ "bnez %[count], 3b \n\t"
+ " addiu %[in1], %[in1], 2 \n\t"
+ "mfhi %[r0] \n\t"
+ "4: \n\t"
+ ".set pop \n\t"
+ : [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
+#if !defined(MIPS_DSP_R2_LE)
+ [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [count] "+r" (count)
+ :
+ : "memory", "hi", "lo"
+ );
+ r[i] = r0;
+ }
+ } else {
+ // In this case, the result is obtained by combining low and high parts
+ // of the accumulator.
+#if !defined(MIPS_DSP_R1_LE)
+ int32_t tmp_shift = 32 - scaling;
+#endif
+ for (i = 1; i < order + 1; i++) {
+ in = (int16_t*)x;
+ int16_t* in1 = (int16_t*)x + i;
+ count = N - i;
+ loop_size = (count) >> 2;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "mult $0, $0 \n\t"
+ "beqz %[loop_size], 2f \n\t"
+ " andi %[count], %[count], 0x3 \n\t"
+ "1: \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "ulw %[r0], 0(%[in]) \n\t"
+ "ulw %[r1], 0(%[in1]) \n\t"
+ "ulw %[r2], 4(%[in]) \n\t"
+ "ulw %[r3], 4(%[in1]) \n\t"
+#else
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 0(%[in1]) \n\t"
+ "lh %[r2], 2(%[in]) \n\t"
+ "lh %[r3], 2(%[in1]) \n\t"
+ "lh %[r4], 4(%[in]) \n\t"
+ "lh %[r5], 4(%[in1]) \n\t"
+ "lh %[r6], 6(%[in]) \n\t"
+ "lh %[r7], 6(%[in1]) \n\t"
+#endif
+ "addiu %[loop_size], %[loop_size], -1 \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "dpa.w.ph $ac0, %[r0], %[r1] \n\t"
+ "dpa.w.ph $ac0, %[r2], %[r3] \n\t"
+#else
+ "madd %[r0], %[r1] \n\t"
+ "madd %[r2], %[r3] \n\t"
+ "madd %[r4], %[r5] \n\t"
+ "madd %[r6], %[r7] \n\t"
+#endif
+ "addiu %[in], %[in], 8 \n\t"
+ "bnez %[loop_size], 1b \n\t"
+ " addiu %[in1], %[in1], 8 \n\t"
+ "2: \n\t"
+ "beqz %[count], 4f \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ " extrv.w %[r0], $ac0, %[scaling] \n\t"
+#else
+ " mfhi %[r0] \n\t"
+#endif
+ "3: \n\t"
+ "lh %[r0], 0(%[in]) \n\t"
+ "lh %[r1], 0(%[in1]) \n\t"
+ "addiu %[count], %[count], -1 \n\t"
+ "addiu %[in], %[in], 2 \n\t"
+ "madd %[r0], %[r1] \n\t"
+ "bnez %[count], 3b \n\t"
+ " addiu %[in1], %[in1], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "extrv.w %[r0], $ac0, %[scaling] \n\t"
+#else
+ "mfhi %[r0] \n\t"
+#endif
+ "4: \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+ "mflo %[r1] \n\t"
+ "sllv %[r0], %[r0], %[tmp_shift] \n\t"
+ "srlv %[r1], %[r1], %[scaling] \n\t"
+ "addu %[r0], %[r0], %[r1] \n\t"
+#endif
+ ".set pop \n\t"
+ : [loop_size] "+r" (loop_size), [in] "+r" (in), [in1] "+r" (in1),
+#if !defined(MIPS_DSP_R2_LE)
+ [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+#endif
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [count] "+r" (count)
+ : [scaling] "r" (scaling)
+#if !defined(MIPS_DSP_R1_LE)
+ , [tmp_shift] "r" (tmp_shift)
+#endif
+ : "memory", "hi", "lo"
+ );
+ r[i] = r0;
+ }
+ }
+ *scale = scaling;
+
+ return (order + 1);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
new file mode 100644
index 0000000000..1734a969cb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+
+// Autocorrelation function in fixed point.
+// NOTE! Different from SPLIB-version in how it scales the signal.
+int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
+ const int16_t* x,
+ int16_t n,
+ int16_t order,
+ int16_t* __restrict scale) {
+ int i = 0;
+ int16_t scaling = 0;
+ uint32_t temp = 0;
+ int64_t prod = 0;
+ int64_t prod_tail = 0;
+
+ RTC_DCHECK_EQ(0, n % 4);
+ RTC_DCHECK_GE(n, 8);
+
+ // Calculate r[0].
+ int16x4_t x0_v;
+ int32x4_t tmpa0_v;
+ int64x2_t tmpb_v;
+
+ tmpb_v = vdupq_n_s64(0);
+ const int16_t* x_start = x;
+ const int16_t* x_end0 = x_start + n;
+ while (x_start < x_end0) {
+ x0_v = vld1_s16(x_start);
+ tmpa0_v = vmull_s16(x0_v, x0_v);
+ tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
+ x_start += 4;
+ }
+
+#ifdef WEBRTC_ARCH_ARM64
+ prod = vaddvq_s64(tmpb_v);
+#else
+ prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
+ 0);
+#endif
+ // Calculate scaling (the value of shifting).
+ temp = (uint32_t)(prod >> 31);
+
+ scaling = temp ? 32 - WebRtcSpl_NormU32(temp) : 0;
+ r[0] = (int32_t)(prod >> scaling);
+
+ int16x8_t x1_v;
+ int16x8_t y_v;
+ int32x4_t tmpa1_v;
+ // Perform the actual correlation calculation.
+ for (i = 1; i < order + 1; i++) {
+ tmpb_v = vdupq_n_s64(0);
+ int rest = (n - i) % 8;
+ x_start = x;
+ x_end0 = x_start + n - i - rest;
+ const int16_t* y_start = x_start + i;
+ while (x_start < x_end0) {
+ x1_v = vld1q_s16(x_start);
+ y_v = vld1q_s16(y_start);
+ tmpa0_v = vmull_s16(vget_low_s16(x1_v), vget_low_s16(y_v));
+#ifdef WEBRTC_ARCH_ARM64
+ tmpa1_v = vmull_high_s16(x1_v, y_v);
+#else
+ tmpa1_v = vmull_s16(vget_high_s16(x1_v), vget_high_s16(y_v));
+#endif
+ tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
+ tmpb_v = vpadalq_s32(tmpb_v, tmpa1_v);
+ x_start += 8;
+ y_start += 8;
+ }
+ // The remaining calculation.
+ const int16_t* x_end1 = x + n - i;
+ if (rest >= 4) {
+ int16x4_t x2_v = vld1_s16(x_start);
+ int16x4_t y2_v = vld1_s16(y_start);
+ tmpa0_v = vmull_s16(x2_v, y2_v);
+ tmpb_v = vpadalq_s32(tmpb_v, tmpa0_v);
+ x_start += 4;
+ y_start += 4;
+ }
+#ifdef WEBRTC_ARCH_ARM64
+ prod = vaddvq_s64(tmpb_v);
+#else
+ prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
+ 0);
+#endif
+
+ prod_tail = 0;
+ while (x_start < x_end1) {
+ prod_tail += *x_start * *y_start;
+ ++x_start;
+ ++y_start;
+ }
+
+ r[i] = (int32_t)((prod + prod_tail) >> scaling);
+ }
+
+ *scale = scaling;
+
+ return order + 1;
+}
+
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
new file mode 100644
index 0000000000..192ef89f9f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+class FiltersTest : public ::testing::Test {
+ protected:
+ // Pass a function pointer to the Tester function.
+ void FiltersTester(AutocorrFix WebRtcIsacfix_AutocorrFixFunction) {
+ const int kOrder = 12;
+ const int kBuffer = 40;
+ int16_t scale = 0;
+ int32_t r_buffer[kOrder + 2] = {0};
+
+ // Test an overflow case.
+ const int16_t x_buffer_0[kBuffer] = {
+ 0, 0, 3010, 22351, 21106, 16969, -2095, -664,
+ 3513, -30980, 32767, -23839, 13335, 20289, -6831, 339,
+ -17207, 32767, 4959, 6177, 32767, 16599, -4747, 20504,
+ 3513, -30980, 32767, -23839, 13335, 20289, 0, -16969,
+ -2095, -664, 3513, 31981, 32767, -13839, 23336, 30281};
+ const int32_t r_expected_0[kOrder + 2] = {
+ 1872498461, -224288754, 203789985, 483400487, -208272635,
+ 2436500, 137785322, 266600814, -208486262, 329510080,
+ 137949184, -161738972, -26894267, 237630192};
+
+ WebRtcIsacfix_AutocorrFixFunction(r_buffer, x_buffer_0, kBuffer, kOrder + 1,
+ &scale);
+ for (int i = 0; i < kOrder + 2; i++) {
+ EXPECT_EQ(r_expected_0[i], r_buffer[i]);
+ }
+ EXPECT_EQ(3, scale);
+
+ // Test a no-overflow case.
+ const int16_t x_buffer_1[kBuffer] = {
+ 0, 0, 300, 21, 206, 169, -295, -664, 3513, -300,
+ 327, -29, 15, 289, -6831, 339, -107, 37, 59, 6177,
+ 327, 169, -4747, 204, 313, -980, 767, -9, 135, 289,
+ 0, -6969, -2095, -664, 0, 1, 7, -39, 236, 281};
+ const int32_t r_expected_1[kOrder + 2] = {
+ 176253864, 8126617, 1983287, -26196788, -3487363,
+ -42839676, -24644043, 3469813, 30559879, 31905045,
+ 5101567, 29328896, -55787438, -13163978};
+
+ WebRtcIsacfix_AutocorrFixFunction(r_buffer, x_buffer_1, kBuffer, kOrder + 1,
+ &scale);
+ for (int i = 0; i < kOrder + 2; i++) {
+ EXPECT_EQ(r_expected_1[i], r_buffer[i]);
+ }
+ EXPECT_EQ(0, scale);
+ }
+};
+
+TEST_F(FiltersTest, AutocorrFixTest) {
+ FiltersTester(WebRtcIsacfix_AutocorrC);
+#if defined(WEBRTC_HAS_NEON)
+ FiltersTester(WebRtcIsacfix_AutocorrNeon);
+#endif
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/initialize.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/initialize.c
new file mode 100644
index 0000000000..1b82958883
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/initialize.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * initialize.c
+ *
+ * Internal initfunctions
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+
+void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc *maskdata) {
+
+ int k;
+
+ for (k = 0; k < WINLEN; k++) {
+ maskdata->DataBufferLoQ0[k] = (int16_t) 0;
+ maskdata->DataBufferHiQ0[k] = (int16_t) 0;
+ }
+ for (k = 0; k < ORDERLO+1; k++) {
+ maskdata->CorrBufLoQQ[k] = (int32_t) 0;
+ maskdata->CorrBufLoQdom[k] = 0;
+
+ maskdata->PreStateLoGQ15[k] = 0;
+
+ }
+ for (k = 0; k < ORDERHI+1; k++) {
+ maskdata->CorrBufHiQQ[k] = (int32_t) 0;
+ maskdata->CorrBufHiQdom[k] = 0;
+ maskdata->PreStateHiGQ15[k] = 0;
+ }
+
+ maskdata->OldEnergy = 10;
+
+ return;
+}
+
+void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec *maskdata) {
+
+ int k;
+
+ for (k = 0; k < ORDERLO+1; k++)
+ {
+ maskdata->PostStateLoGQ0[k] = 0;
+ }
+ for (k = 0; k < ORDERHI+1; k++)
+ {
+ maskdata->PostStateHiGQ0[k] = 0;
+ }
+
+ maskdata->OldEnergy = 10;
+
+ return;
+}
+
+
+
+
+
+
+
+void WebRtcIsacfix_InitPreFilterbank(PreFiltBankstr *prefiltdata)
+{
+ int k;
+
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ prefiltdata->INLABUF1_fix[k] = 0;
+ prefiltdata->INLABUF2_fix[k] = 0;
+ }
+ for (k = 0; k < 2 * (QORDER - 1); k++) {
+ prefiltdata->INSTAT1_fix[k] = 0;
+ prefiltdata->INSTAT2_fix[k] = 0;
+ }
+
+ /* High pass filter states */
+ prefiltdata->HPstates_fix[0] = 0;
+ prefiltdata->HPstates_fix[1] = 0;
+
+ return;
+}
+
+void WebRtcIsacfix_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+ int k;
+
+ for (k = 0; k < 2 * POSTQORDER; k++) {
+ postfiltdata->STATE_0_LOWER_fix[k] = 0;
+ postfiltdata->STATE_0_UPPER_fix[k] = 0;
+ }
+
+ /* High pass filter states */
+
+ postfiltdata->HPstates1_fix[0] = 0;
+ postfiltdata->HPstates1_fix[1] = 0;
+
+ postfiltdata->HPstates2_fix[0] = 0;
+ postfiltdata->HPstates2_fix[1] = 0;
+
+ return;
+}
+
+
+void WebRtcIsacfix_InitPitchFilter(PitchFiltstr *pitchfiltdata)
+{
+ int k;
+
+ for (k = 0; k < PITCH_BUFFSIZE; k++)
+ pitchfiltdata->ubufQQ[k] = 0;
+ for (k = 0; k < (PITCH_DAMPORDER); k++)
+ pitchfiltdata->ystateQQ[k] = 0;
+
+ pitchfiltdata->oldlagQ7 = 6400; /* 50.0 in Q7 */
+ pitchfiltdata->oldgainQ12 = 0;
+}
+
+void WebRtcIsacfix_InitPitchAnalysis(PitchAnalysisStruct *State)
+{
+ int k;
+
+ for (k = 0; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k++) {
+ State->dec_buffer16[k] = 0;
+ }
+ for (k = 0; k < 2 * ALLPASSSECTIONS + 1; k++) {
+ State->decimator_state32[k] = 0;
+ }
+
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = 0;
+
+ WebRtcIsacfix_InitPitchFilter(&(State->PFstr_wght));
+
+ WebRtcIsacfix_InitPitchFilter(&(State->PFstr));
+}
+
+
+void WebRtcIsacfix_InitPlc( PLCstr *State )
+{
+ State->decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX;
+ State->decayCoeffNoise = WEBRTC_SPL_WORD16_MAX;
+
+ State->used = PLC_WAS_USED;
+
+ WebRtcSpl_ZerosArrayW16(State->overlapLP, RECOVERY_OVERLAP);
+ WebRtcSpl_ZerosArrayW16(State->lofilt_coefQ15, ORDERLO);
+ WebRtcSpl_ZerosArrayW16(State->hifilt_coefQ15, ORDERHI );
+
+ State->AvgPitchGain_Q12 = 0;
+ State->lastPitchGain_Q12 = 0;
+ State->lastPitchLag_Q7 = 0;
+ State->gain_lo_hiQ17[0]=State->gain_lo_hiQ17[1] = 0;
+ WebRtcSpl_ZerosArrayW16(State->prevPitchInvIn, FRAMESAMPLES/2);
+ WebRtcSpl_ZerosArrayW16(State->prevPitchInvOut, PITCH_MAX_LAG + 10 );
+ WebRtcSpl_ZerosArrayW32(State->prevHP, PITCH_MAX_LAG + 10 );
+ State->pitchCycles = 0;
+ State->A = 0;
+ State->B = 0;
+ State->pitchIndex = 0;
+ State->stretchLag = 240;
+ State->seed = 4447;
+
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h
new file mode 100644
index 0000000000..512911a8bb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isac_fix_type.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ISAC_FIX_TYPE_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ISAC_FIX_TYPE_H_
+
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+class IsacFix {
+ public:
+ using instance_type = ISACFIX_MainStruct;
+ static const bool has_swb = false;
+ static inline int16_t Control(instance_type* inst,
+ int32_t rate,
+ int framesize) {
+ return WebRtcIsacfix_Control(inst, rate, framesize);
+ }
+ static inline int16_t ControlBwe(instance_type* inst,
+ int32_t rate_bps,
+ int frame_size_ms,
+ int16_t enforce_frame_size) {
+ return WebRtcIsacfix_ControlBwe(inst, rate_bps, frame_size_ms,
+ enforce_frame_size);
+ }
+ static inline int16_t Create(instance_type** inst) {
+ return WebRtcIsacfix_Create(inst);
+ }
+ static inline int DecodeInternal(instance_type* inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speech_type) {
+ return WebRtcIsacfix_Decode(inst, encoded, len, decoded, speech_type);
+ }
+ static inline size_t DecodePlc(instance_type* inst,
+ int16_t* decoded,
+ size_t num_lost_frames) {
+ return WebRtcIsacfix_DecodePlc(inst, decoded, num_lost_frames);
+ }
+ static inline void DecoderInit(instance_type* inst) {
+ WebRtcIsacfix_DecoderInit(inst);
+ }
+ static inline int Encode(instance_type* inst,
+ const int16_t* speech_in,
+ uint8_t* encoded) {
+ return WebRtcIsacfix_Encode(inst, speech_in, encoded);
+ }
+ static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
+ return WebRtcIsacfix_EncoderInit(inst, coding_mode);
+ }
+ static inline uint16_t EncSampRate(instance_type* inst) {
+ return kFixSampleRate;
+ }
+
+ static inline int16_t Free(instance_type* inst) {
+ return WebRtcIsacfix_Free(inst);
+ }
+ static inline int16_t GetErrorCode(instance_type* inst) {
+ return WebRtcIsacfix_GetErrorCode(inst);
+ }
+
+ static inline int16_t GetNewFrameLen(instance_type* inst) {
+ return WebRtcIsacfix_GetNewFrameLen(inst);
+ }
+ static inline int16_t SetDecSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ RTC_DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+ return 0;
+ }
+ static inline int16_t SetEncSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ RTC_DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+ return 0;
+ }
+ static inline void SetEncSampRateInDecoder(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ RTC_DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+ }
+ static inline void SetInitialBweBottleneck(instance_type* inst,
+ int bottleneck_bits_per_second) {
+ WebRtcIsacfix_SetInitialBweBottleneck(inst, bottleneck_bits_per_second);
+ }
+ static inline int16_t SetMaxPayloadSize(instance_type* inst,
+ int16_t max_payload_size_bytes) {
+ return WebRtcIsacfix_SetMaxPayloadSize(inst, max_payload_size_bytes);
+ }
+ static inline int16_t SetMaxRate(instance_type* inst, int32_t max_bit_rate) {
+ return WebRtcIsacfix_SetMaxRate(inst, max_bit_rate);
+ }
+
+ private:
+ enum { kFixSampleRate = 16000 };
+};
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_ISAC_FIX_TYPE_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c
new file mode 100644
index 0000000000..a7d44e883d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c
@@ -0,0 +1,1230 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * isacfix.c
+ *
+ * This C file contains the functions for the ISAC API
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+
+#include <stdlib.h>
+
+#include "rtc_base/checks.h"
+#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+// Declare function pointers.
+FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
+Spec2Time WebRtcIsacfix_Spec2Time;
+Time2Spec WebRtcIsacfix_Time2Spec;
+MatrixProduct1 WebRtcIsacfix_MatrixProduct1;
+MatrixProduct2 WebRtcIsacfix_MatrixProduct2;
+
+/* This method assumes that `stream_size_bytes` is in valid range,
+ * i.e. >= 0 && <= STREAM_MAXW16_60MS
+ */
+static void InitializeDecoderBitstream(size_t stream_size_bytes,
+ Bitstr_dec* bitstream) {
+ bitstream->W_upper = 0xFFFFFFFF;
+ bitstream->streamval = 0;
+ bitstream->stream_index = 0;
+ bitstream->full = 1;
+ bitstream->stream_size = (stream_size_bytes + 1) >> 1;
+ memset(bitstream->stream, 0, sizeof(bitstream->stream));
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_Create(...)
+ *
+ * This function creates a ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Create(ISACFIX_MainStruct **ISAC_main_inst)
+{
+ ISACFIX_SubStruct *tempo;
+ tempo = malloc(1 * sizeof(ISACFIX_SubStruct));
+ *ISAC_main_inst = (ISACFIX_MainStruct *)tempo;
+ if (*ISAC_main_inst!=NULL) {
+ (*(ISACFIX_SubStruct**)ISAC_main_inst)->errorcode = 0;
+ (*(ISACFIX_SubStruct**)ISAC_main_inst)->initflag = 0;
+ (*(ISACFIX_SubStruct**)ISAC_main_inst)->ISACenc_obj.SaveEnc_ptr = NULL;
+ WebRtcIsacfix_InitBandwidthEstimator(&tempo->bwestimator_obj);
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_CreateInternal(...)
+ *
+ * This function creates the memory that is used to store data in the encoder
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_CreateInternal(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Allocate memory for storing encoder data */
+ ISAC_inst->ISACenc_obj.SaveEnc_ptr = malloc(1 * sizeof(IsacSaveEncoderData));
+
+ if (ISAC_inst->ISACenc_obj.SaveEnc_ptr!=NULL) {
+ return(0);
+ } else {
+ return(-1);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : a ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Free(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ free(ISAC_main_inst);
+ return(0);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_FreeInternal(...)
+ *
+ * This function frees the internal memory for storing encoder data.
+ *
+ * Input:
+ * - ISAC_main_inst : a ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Release memory */
+ free(ISAC_inst->ISACenc_obj.SaveEnc_ptr);
+
+ return(0);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_InitNeon(...)
+ *
+ * This function initializes function pointers for ARM Neon platform.
+ */
+
+#if defined(WEBRTC_HAS_NEON)
+static void WebRtcIsacfix_InitNeon(void) {
+ WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrNeon;
+ WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopNeon;
+ WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeNeon;
+ WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecNeon;
+ WebRtcIsacfix_AllpassFilter2FixDec16 =
+ WebRtcIsacfix_AllpassFilter2FixDec16Neon;
+ WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1Neon;
+ WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2Neon;
+}
+#endif
+
+/****************************************************************************
+ * WebRtcIsacfix_InitMIPS(...)
+ *
+ * This function initializes function pointers for MIPS platform.
+ */
+
+#if defined(MIPS32_LE)
+static void WebRtcIsacfix_InitMIPS(void) {
+ WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrMIPS;
+ WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopMIPS;
+ WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeMIPS;
+ WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecMIPS;
+ WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1MIPS;
+ WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2MIPS;
+#if defined(MIPS_DSP_R1_LE)
+ WebRtcIsacfix_AllpassFilter2FixDec16 =
+ WebRtcIsacfix_AllpassFilter2FixDec16MIPS;
+ WebRtcIsacfix_HighpassFilterFixDec32 =
+ WebRtcIsacfix_HighpassFilterFixDec32MIPS;
+#endif
+#if defined(MIPS_DSP_R2_LE)
+ WebRtcIsacfix_CalculateResidualEnergy =
+ WebRtcIsacfix_CalculateResidualEnergyMIPS;
+#endif
+}
+#endif
+
+static void InitFunctionPointers(void) {
+ WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC;
+ WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC;
+ WebRtcIsacfix_CalculateResidualEnergy =
+ WebRtcIsacfix_CalculateResidualEnergyC;
+ WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C;
+ WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
+ WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC;
+ WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC;
+ WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C;
+ WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C;
+
+#if defined(WEBRTC_HAS_NEON)
+ WebRtcIsacfix_InitNeon();
+#endif
+
+#if defined(MIPS32_LE)
+ WebRtcIsacfix_InitMIPS();
+#endif
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_EncoderInit(...)
+ *
+ * This function initializes a ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - CodingMode : 0 -> Bit rate and frame length are automatically
+ * adjusted to available bandwidth on
+ * transmission channel.
+ * 1 -> User sets a frame length and a target bit
+ * rate which is taken as the maximum short-term
+ * average bit rate.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
+ int16_t CodingMode)
+{
+ int k;
+ int16_t statusInit;
+ ISACFIX_SubStruct *ISAC_inst;
+
+ statusInit = 0;
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* flag encoder init */
+ ISAC_inst->initflag |= 2;
+
+ if (CodingMode == 0)
+ /* Adaptive mode */
+ ISAC_inst->ISACenc_obj.new_framelength = INITIAL_FRAMESAMPLES;
+ else if (CodingMode == 1)
+ /* Instantaneous mode */
+ ISAC_inst->ISACenc_obj.new_framelength = 480; /* default for I-mode */
+ else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_CODING_MODE;
+ statusInit = -1;
+ }
+
+ ISAC_inst->CodingMode = CodingMode;
+
+ WebRtcIsacfix_InitMaskingEnc(&ISAC_inst->ISACenc_obj.maskfiltstr_obj);
+ WebRtcIsacfix_InitPreFilterbank(&ISAC_inst->ISACenc_obj.prefiltbankstr_obj);
+ WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACenc_obj.pitchfiltstr_obj);
+ WebRtcIsacfix_InitPitchAnalysis(&ISAC_inst->ISACenc_obj.pitchanalysisstr_obj);
+
+ WebRtcIsacfix_InitRateModel(&ISAC_inst->ISACenc_obj.rate_data_obj);
+
+
+ ISAC_inst->ISACenc_obj.buffer_index = 0;
+ ISAC_inst->ISACenc_obj.frame_nb = 0;
+ ISAC_inst->ISACenc_obj.BottleNeck = 32000; /* default for I-mode */
+ ISAC_inst->ISACenc_obj.MaxDelay = 10; /* default for I-mode */
+ ISAC_inst->ISACenc_obj.current_framesamples = 0;
+ ISAC_inst->ISACenc_obj.s2nr = 0;
+ ISAC_inst->ISACenc_obj.MaxBits = 0;
+ ISAC_inst->ISACenc_obj.bitstr_seed = 4447;
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = STREAM_MAXW16_30MS << 1;
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = STREAM_MAXW16_60MS << 1;
+ ISAC_inst->ISACenc_obj.maxPayloadBytes = STREAM_MAXW16_60MS << 1;
+ ISAC_inst->ISACenc_obj.maxRateInBytes = STREAM_MAXW16_30MS << 1;
+ ISAC_inst->ISACenc_obj.enforceFrameSize = 0;
+
+ /* Init the bistream data area to zero */
+ for (k=0; k<STREAM_MAXW16_60MS; k++){
+ ISAC_inst->ISACenc_obj.bitstr_obj.stream[k] = 0;
+ }
+
+ InitFunctionPointers();
+
+ return statusInit;
+}
+
+/* Read the given number of bytes of big-endian 16-bit integers from `src` and
+ write them to `dest` in host endian. If `nbytes` is odd, the number of
+ output elements is rounded up, and the least significant byte of the last
+ element is set to 0. */
+static void read_be16(const uint8_t* src, size_t nbytes, uint16_t* dest) {
+ size_t i;
+ for (i = 0; i < nbytes / 2; ++i)
+ dest[i] = src[2 * i] << 8 | src[2 * i + 1];
+ if (nbytes % 2 == 1)
+ dest[nbytes / 2] = src[nbytes - 1] << 8;
+}
+
+/* Read the given number of bytes of host-endian 16-bit integers from `src` and
+ write them to `dest` in big endian. If `nbytes` is odd, the number of source
+ elements is rounded up (but only the most significant byte of the last
+ element is used), and the number of output bytes written will be
+ nbytes + 1. */
+static void write_be16(const uint16_t* src, size_t nbytes, uint8_t* dest) {
+ size_t i;
+ for (i = 0; i < nbytes / 2; ++i) {
+ dest[2 * i] = src[i] >> 8;
+ dest[2 * i + 1] = src[i];
+ }
+ if (nbytes % 2 == 1) {
+ dest[nbytes - 1] = src[nbytes / 2] >> 8;
+ dest[nbytes] = 0;
+ }
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - speechIn : input speech vector.
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : 0 - The buffer didn't reach the chosen framesize
+ * so it keeps buffering speech samples.
+ * : -1 - Error
+ */
+
+int WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst,
+ const int16_t *speechIn,
+ uint8_t* encoded)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ int stream_len;
+
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ stream_len = WebRtcIsacfix_EncodeImpl((int16_t*)speechIn,
+ &ISAC_inst->ISACenc_obj,
+ &ISAC_inst->bwestimator_obj,
+ ISAC_inst->CodingMode);
+ if (stream_len<0) {
+ ISAC_inst->errorcode = -(int16_t)stream_len;
+ return -1;
+ }
+
+ write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, (size_t)stream_len,
+ encoded);
+ return stream_len;
+
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : index of bandwidth estimate to put in new bitstream
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : -1 - Error
+ */
+
+int16_t WebRtcIsacfix_GetNewBitStream(ISACFIX_MainStruct *ISAC_main_inst,
+ int16_t bweIndex,
+ float scale,
+ uint8_t* encoded)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ int16_t stream_len;
+
+ /* typecast pointer to rela structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ stream_len = WebRtcIsacfix_EncodeStoredData(&ISAC_inst->ISACenc_obj,
+ bweIndex,
+ scale);
+ if (stream_len<0) {
+ ISAC_inst->errorcode = - stream_len;
+ return -1;
+ }
+
+ write_be16(ISAC_inst->ISACenc_obj.bitstr_obj.stream, stream_len, encoded);
+ return stream_len;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecoderInit(...)
+ *
+ * This function initializes a ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ */
+
+void WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ InitFunctionPointers();
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* flag decoder init */
+ ISAC_inst->initflag |= 1;
+
+ WebRtcIsacfix_InitMaskingDec(&ISAC_inst->ISACdec_obj.maskfiltstr_obj);
+ WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACdec_obj.postfiltbankstr_obj);
+ WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACdec_obj.pitchfiltstr_obj);
+
+ /* TS */
+ WebRtcIsacfix_InitPlc( &ISAC_inst->ISACdec_obj.plcstr_obj );
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate1(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t arr_ts)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ Bitstr_dec streamdata;
+ int16_t err;
+ const size_t kRequiredEncodedLenBytes = 10;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Sanity check of packet length */
+ if (packet_size == 0) {
+ /* return error code if the packet length is null or less */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ } else if (packet_size > (STREAM_MAXW16<<1)) {
+ /* return error code if length of stream is too long */
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ InitializeDecoderBitstream(packet_size, &streamdata);
+
+ read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+ err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
+ &streamdata,
+ packet_size,
+ rtp_seq_number,
+ 0,
+ arr_ts);
+
+
+ if (err < 0)
+ {
+ /* return error code if something went wrong */
+ ISAC_inst->errorcode = -err;
+ return -1;
+ }
+
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - send_ts : Send Time Stamp from RTP header
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ Bitstr_dec streamdata;
+ int16_t err;
+ const size_t kRequiredEncodedLenBytes = 10;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Sanity check of packet length */
+ if (packet_size == 0) {
+ /* return error code if the packet length is null or less */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ } else if (packet_size < kRequiredEncodedLenBytes) {
+ ISAC_inst->errorcode = ISAC_PACKET_TOO_SHORT;
+ return -1;
+ } else if (packet_size > (STREAM_MAXW16<<1)) {
+ /* return error code if length of stream is too long */
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ InitializeDecoderBitstream(packet_size, &streamdata);
+
+ read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+ err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
+ &streamdata,
+ packet_size,
+ rtp_seq_number,
+ send_ts,
+ arr_ts);
+
+ if (err < 0)
+ {
+ /* return error code if something went wrong */
+ ISAC_inst->errorcode = -err;
+ return -1;
+ }
+
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_Decode(...)
+ *
+ * This function decodes a ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+
+
+int WebRtcIsacfix_Decode(ISACFIX_MainStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* number of samples (480 or 960), output from decoder */
+ /* that were actually used in the encoder/decoder (determined on the fly) */
+ size_t number_of_samples;
+ int declen_int = 0;
+ size_t declen;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* check if decoder initiated */
+ if ((ISAC_inst->initflag & 1) != 1) {
+ ISAC_inst->errorcode = ISAC_DECODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ /* Sanity check of packet length */
+ if (len == 0) {
+ /* return error code if the packet length is null or less */
+ ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
+ return -1;
+ } else if (len > (STREAM_MAXW16<<1)) {
+ /* return error code if length of stream is too long */
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ InitializeDecoderBitstream(len, &ISAC_inst->ISACdec_obj.bitstr_obj);
+
+ read_be16(encoded, len, ISAC_inst->ISACdec_obj.bitstr_obj.stream);
+
+ /* added for NetEq purposes (VAD/DTX related) */
+ *speechType=1;
+
+ declen_int = WebRtcIsacfix_DecodeImpl(decoded, &ISAC_inst->ISACdec_obj,
+ &number_of_samples);
+ if (declen_int < 0) {
+ /* Some error inside the decoder */
+ ISAC_inst->errorcode = -(int16_t)declen_int;
+ memset(decoded, 0, sizeof(int16_t) * MAX_FRAMESAMPLES);
+ return -1;
+ }
+ declen = (size_t)declen_int;
+
+ /* error check */
+
+ if (declen & 1) {
+ if (len != declen &&
+ len != declen +
+ ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) & 0xFF)) {
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ memset(decoded, 0, sizeof(int16_t) * number_of_samples);
+ return -1;
+ }
+ } else {
+ if (len != declen &&
+ len != declen +
+ ((ISAC_inst->ISACdec_obj.bitstr_obj.stream[declen >> 1]) >> 8)) {
+ ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
+ memset(decoded, 0, sizeof(int16_t) * number_of_samples);
+ return -1;
+ }
+ }
+
+ return (int)number_of_samples;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s) in wide-band (16kHz sampling).
+ * Output speech length will be "480*noOfLostFrames" samples
+ * that is equevalent of "30*noOfLostFrames" millisecond.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames (480sample = 30ms)
+ * to produce
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : Number of samples in decoded PLC vector
+ */
+
+size_t WebRtcIsacfix_DecodePlc(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames)
+{
+
+ size_t no_of_samples, declen, k;
+ int16_t outframe16[MAX_FRAMESAMPLES];
+
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */
+ if (noOfLostFrames > 2) {
+ noOfLostFrames = 2;
+ }
+ k = 0;
+ declen = 0;
+ while( noOfLostFrames > 0 )
+ {
+ WebRtcIsacfix_DecodePlcImpl(&(outframe16[k*480]), &ISAC_inst->ISACdec_obj,
+ &no_of_samples);
+ declen += no_of_samples;
+ noOfLostFrames--;
+ k++;
+ }
+
+ for (k=0;k<declen;k++) {
+ decoded[k] = outframe16[k];
+ }
+
+ return declen;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_Control(...)
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second (between 10000 and 32000)
+ * - framesize : number of milliseconds per frame (30 or 60)
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_Control(ISACFIX_MainStruct *ISAC_main_inst,
+ int16_t rate,
+ int framesize)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ if (ISAC_inst->CodingMode == 0)
+ {
+ /* in adaptive mode */
+ ISAC_inst->errorcode = ISAC_MODE_MISMATCH;
+ return -1;
+ }
+
+
+ if (rate >= 10000 && rate <= 32000)
+ ISAC_inst->ISACenc_obj.BottleNeck = rate;
+ else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK;
+ return -1;
+ }
+
+
+
+ if (framesize == 30 || framesize == 60)
+ ISAC_inst->ISACenc_obj.new_framelength = (int16_t)((FS/1000) * framesize);
+ else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+
+ return 0;
+}
+
+void WebRtcIsacfix_SetInitialBweBottleneck(ISACFIX_MainStruct* ISAC_main_inst,
+ int bottleneck_bits_per_second) {
+ ISACFIX_SubStruct* inst = (ISACFIX_SubStruct*)ISAC_main_inst;
+ RTC_DCHECK_GE(bottleneck_bits_per_second, 10000);
+ RTC_DCHECK_LE(bottleneck_bits_per_second, 32000);
+ inst->bwestimator_obj.sendBwAvg = ((uint32_t)bottleneck_bits_per_second) << 7;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rateBPS : initial value of bottleneck in bits/second
+ * 10000 <= rateBPS <= 32000 is accepted
+ * For default bottleneck set rateBPS = 0
+ * - frameSizeMs : number of milliseconds per frame (30 or 60)
+ * - enforceFrameSize : 1 to enforce the given frame-size through out
+ * the adaptation process, 0 to let iSAC change
+ * the frame-size if required.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsacfix_ControlBwe(ISACFIX_MainStruct *ISAC_main_inst,
+ int16_t rateBPS,
+ int frameSizeMs,
+ int16_t enforceFrameSize)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* Typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if ((ISAC_inst->initflag & 2) != 2) {
+ ISAC_inst->errorcode = ISAC_ENCODER_NOT_INITIATED;
+ return (-1);
+ }
+
+ /* Check that we are in channel-adaptive mode, otherwise, return -1 */
+ if (ISAC_inst->CodingMode != 0) {
+ ISAC_inst->errorcode = ISAC_MODE_MISMATCH;
+ return (-1);
+ }
+
+ /* Set struct variable if enforceFrameSize is set. ISAC will then keep the */
+ /* chosen frame size. */
+ ISAC_inst->ISACenc_obj.enforceFrameSize = (enforceFrameSize != 0)? 1:0;
+
+ /* Set initial rate, if value between 10000 and 32000, */
+ /* if rateBPS is 0, keep the default initial bottleneck value (15000) */
+ if ((rateBPS >= 10000) && (rateBPS <= 32000)) {
+ ISAC_inst->bwestimator_obj.sendBwAvg = (((uint32_t)rateBPS) << 7);
+ } else if (rateBPS != 0) {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_BOTTLENECK;
+ return -1;
+ }
+
+ /* Set initial framesize. If enforceFrameSize is set the frame size will not change */
+ if ((frameSizeMs == 30) || (frameSizeMs == 60)) {
+ ISAC_inst->ISACenc_obj.new_framelength = (int16_t)((FS/1000) * frameSizeMs);
+ } else {
+ ISAC_inst->errorcode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst: iSAC struct
+ *
+ * Output:
+ * - rateIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_GetDownLinkBwIndex(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t* rateIndex)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Call function to get Bandwidth Estimate */
+ *rateIndex = WebRtcIsacfix_GetDownlinkBwIndexImpl(&ISAC_inst->bwestimator_obj);
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ * - ISAC_main_inst: iSAC struct
+ * - rateIndex : Bandwidth estimate from other side.
+ *
+ */
+
+int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
+ int16_t rateIndex)
+{
+ int16_t err = 0;
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ /* Call function to update BWE with received Bandwidth Estimate */
+ err = WebRtcIsacfix_UpdateUplinkBwRec(&ISAC_inst->bwestimator_obj, rateIndex);
+ if (err < 0) {
+ ISAC_inst->errorcode = -err;
+ return (-1);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadFrameLen(const uint8_t* encoded,
+ size_t encoded_len_bytes,
+ size_t* frameLength)
+{
+ Bitstr_dec streamdata;
+ int16_t err;
+ const size_t kRequiredEncodedLenBytes = 10;
+
+ if (encoded_len_bytes < kRequiredEncodedLenBytes) {
+ return -1;
+ }
+
+ InitializeDecoderBitstream(encoded_len_bytes, &streamdata);
+
+ read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+ /* decode frame length */
+ err = WebRtcIsacfix_DecodeFrameLen(&streamdata, frameLength);
+ if (err<0) // error check
+ return err;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ * - rateIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+int16_t WebRtcIsacfix_ReadBwIndex(const uint8_t* encoded,
+ size_t encoded_len_bytes,
+ int16_t* rateIndex)
+{
+ Bitstr_dec streamdata;
+ int16_t err;
+ const size_t kRequiredEncodedLenBytes = 10;
+
+ if (encoded_len_bytes < kRequiredEncodedLenBytes) {
+ return -1;
+ }
+
+ InitializeDecoderBitstream(encoded_len_bytes, &streamdata);
+
+ read_be16(encoded, kRequiredEncodedLenBytes, streamdata.stream);
+
+ /* decode frame length, needed to get to the rateIndex in the bitstream */
+ size_t frameLength;
+ err = WebRtcIsacfix_DecodeFrameLen(&streamdata, &frameLength);
+ if (err<0) // error check
+ return err;
+
+ /* decode BW estimation */
+ err = WebRtcIsacfix_DecodeSendBandwidth(&streamdata, rateIndex);
+ if (err<0) // error check
+ return err;
+
+ return 0;
+}
+
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occured in the
+ * specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+
+int16_t WebRtcIsacfix_GetErrorCode(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ return ISAC_inst->errorcode;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_GetUplinkBw(...)
+ *
+ * This function returns the inst quantized iSAC send bitrate
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : bitrate
+ */
+
+int32_t WebRtcIsacfix_GetUplinkBw(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+ BwEstimatorstr * bw = (BwEstimatorstr*)&(ISAC_inst->bwestimator_obj);
+
+ return (int32_t) WebRtcIsacfix_GetUplinkBandwidth(bw);
+}
+
+/****************************************************************************
+ * WebRtcIsacfix_GetNewFrameLen(...)
+ *
+ * This function return the next frame length (in samples) of iSAC.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : frame lenght in samples
+ */
+
+int16_t WebRtcIsacfix_GetNewFrameLen(ISACFIX_MainStruct *ISAC_main_inst)
+{
+ ISACFIX_SubStruct *ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+ return ISAC_inst->ISACenc_obj.new_framelength;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 msec packets.
+ * The absolute max will be valid until next time the function is called.
+ * NOTE! This function may override the function WebRtcIsacfix_SetMaxRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 100 and 400 bytes
+ *
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_MainStruct *ISAC_main_inst,
+ int16_t maxPayloadBytes)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ if((maxPayloadBytes < 100) || (maxPayloadBytes > 400))
+ {
+ /* maxPayloadBytes is out of valid range */
+ return -1;
+ }
+ else
+ {
+ /* Set new absolute max, which will not change unless this function
+ is called again with a new value */
+ ISAC_inst->ISACenc_obj.maxPayloadBytes = maxPayloadBytes;
+
+ /* Set new maximum values for 30 and 60 msec packets */
+ if (maxPayloadBytes < ISAC_inst->ISACenc_obj.maxRateInBytes) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxPayloadBytes;
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxRateInBytes;
+ }
+
+ if ( maxPayloadBytes < (ISAC_inst->ISACenc_obj.maxRateInBytes << 1)) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = maxPayloadBytes;
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (ISAC_inst->ISACenc_obj.maxRateInBytes << 1);
+ }
+ }
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsacfix_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for a
+ * singel packet. The maximum rate is set in bits per second.
+ * The codec has an absolute maximum rate of 53400 bits per second (200 bytes
+ * per 30 msec).
+ * It is possible to set a maximum rate between 32000 and 53400 bits per second.
+ *
+ * The rate limit is valid until next time the function is called.
+ *
+ * NOTE! Packet size will never go above the value set if calling
+ * WebRtcIsacfix_SetMaxPayloadSize() (default max packet size is 400 bytes).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRateInBytes : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits
+ *
+ * Return value : 0 if sucessful
+ * -1 if error happens
+ */
+
+int16_t WebRtcIsacfix_SetMaxRate(ISACFIX_MainStruct *ISAC_main_inst,
+ int32_t maxRate)
+{
+ ISACFIX_SubStruct *ISAC_inst;
+ int16_t maxRateInBytes;
+
+ /* typecast pointer to real structure */
+ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
+
+ if((maxRate < 32000) || (maxRate > 53400))
+ {
+ /* maxRate is out of valid range */
+ return -1;
+ }
+ else
+ {
+ /* Calculate maximum number of bytes per 30 msec packets for the given
+ maximum rate. Multiply with 30/1000 to get number of bits per 30 msec,
+ divide by 8 to get number of bytes per 30 msec:
+ maxRateInBytes = floor((maxRate * 30/1000) / 8); */
+ maxRateInBytes = (int16_t)( WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_MUL(maxRate, 3), 800) );
+
+ /* Store the value for usage in the WebRtcIsacfix_SetMaxPayloadSize-function */
+ ISAC_inst->ISACenc_obj.maxRateInBytes = maxRateInBytes;
+
+ /* For 30 msec packets: if the new limit is below the maximum
+ payload size, set a new limit */
+ if (maxRateInBytes < ISAC_inst->ISACenc_obj.maxPayloadBytes) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = maxRateInBytes;
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes30 = ISAC_inst->ISACenc_obj.maxPayloadBytes;
+ }
+
+ /* For 60 msec packets: if the new limit (times 2) is below the
+ maximum payload size, set a new limit */
+ if ( (maxRateInBytes << 1) < ISAC_inst->ISACenc_obj.maxPayloadBytes) {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = (maxRateInBytes << 1);
+ } else {
+ ISAC_inst->ISACenc_obj.payloadLimitBytes60 = ISAC_inst->ISACenc_obj.maxPayloadBytes;
+ }
+ }
+
+ return 0;
+}
+
+
+
+/****************************************************************************
+ * WebRtcIsacfix_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+void WebRtcIsacfix_version(char *version)
+{
+ strcpy(version, "3.6.0");
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice.c
new file mode 100644
index 0000000000..7bbf4e054a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lattice.c
+ *
+ * Contains the normalized lattice filter routines (MA and AR) for iSAC codec
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/sanitizer.h"
+
+#define LATTICE_MUL_32_32_RSFT16(a32a, a32b, b32) \
+ ((int32_t)(WEBRTC_SPL_MUL(a32a, b32) + (WEBRTC_SPL_MUL_16_32_RSFT16(a32b, b32))))
+/* This macro is FORBIDDEN to use elsewhere than in a function in this file and
+ its corresponding neon version. It might give unpredictable results, since a
+ general int32_t*int32_t multiplication results in a 64 bit value.
+ The result is then shifted just 16 steps to the right, giving need for 48
+ bits, i.e. in the generel case, it will NOT fit in a int32_t. In the
+ cases used in here, the int32_t will be enough, since (for a good
+ reason) the involved multiplicands aren't big enough to overflow a
+ int32_t after shifting right 16 bits. I have compared the result of a
+ multiplication between t32 and tmp32, done in two ways:
+ 1) Using (int32_t) (((float)(tmp32))*((float)(tmp32b))/65536.0);
+ 2) Using LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+ By running 25 files, I haven't found any bigger diff than 64 - this was in the
+ case when method 1) gave 650235648 and 2) gave 650235712.
+*/
+
+/* Function prototype: filtering ar_g_Q0[] and ar_f_Q0[] through an AR filter
+ with coefficients cth_Q15[] and sth_Q15[].
+ Implemented for both generic and ARMv7 platforms.
+ */
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0,
+ int16_t* ar_f_Q0,
+ int16_t* cth_Q15,
+ int16_t* sth_Q15,
+ size_t order_coef);
+
+/* Inner loop used for function WebRtcIsacfix_NormLatticeFilterMa(). It does:
+ for 0 <= n < HALF_SUBFRAMELEN - 1:
+ *ptr2 = input2 * (*ptr2) + input0 * (*ptr0));
+ *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+ Note, function WebRtcIsacfix_FilterMaLoopNeon and WebRtcIsacfix_FilterMaLoopC
+ are not bit-exact. The accuracy by the ARM Neon function is same or better.
+*/
+void WebRtcIsacfix_FilterMaLoopC(int16_t input0, // Filter coefficient
+ int16_t input1, // Filter coefficient
+ int32_t input2, // Inverse coeff. (1/input1)
+ int32_t* ptr0, // Sample buffer
+ int32_t* ptr1, // Sample buffer
+ int32_t* ptr2) { // Sample buffer
+ int n = 0;
+
+ // Separate the 32-bit variable input2 into two 16-bit integers (high 16 and
+ // low 16 bits), for using LATTICE_MUL_32_32_RSFT16 in the loop.
+ int16_t t16a = (int16_t)(input2 >> 16);
+ int16_t t16b = (int16_t)input2;
+ if (t16b < 0) t16a++;
+
+ // The loop filtering the samples *ptr0, *ptr1, *ptr2 with filter coefficients
+ // input0, input1, and input2.
+ for(n = 0; n < HALF_SUBFRAMELEN - 1; n++, ptr0++, ptr1++, ptr2++) {
+ int32_t tmp32a = 0;
+ int32_t tmp32b = 0;
+
+ // Calculate *ptr2 = input2 * (*ptr2 + input0 * (*ptr0));
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr0); // Q15 * Q15 >> 15 = Q15
+ tmp32b = *ptr2 + tmp32a; // Q15 + Q15 = Q15
+ *ptr2 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+
+ // Calculate *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input1, *ptr0); // Q15*Q15>>15 = Q15
+ tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr2); // Q15*Q15>>15 = Q15
+ *ptr1 = tmp32a + tmp32b; // Q15 + Q15 = Q15
+ }
+}
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsacfix_NormLatticeFilterMa(size_t orderCoef,
+ int32_t *stateGQ15,
+ int16_t *lat_inQ0,
+ int16_t *filt_coefQ15,
+ int32_t *gain_lo_hiQ17,
+ int16_t lo_hi,
+ int16_t *lat_outQ9)
+{
+ int16_t sthQ15[MAX_AR_MODEL_ORDER];
+ int16_t cthQ15[MAX_AR_MODEL_ORDER];
+
+ int u, n;
+ size_t i, k;
+ int16_t temp2,temp3;
+ size_t ord_1 = orderCoef+1;
+ int32_t inv_cthQ16[MAX_AR_MODEL_ORDER];
+
+ int32_t gain32, fQtmp;
+ int16_t gain16;
+ int16_t gain_sh;
+
+ int32_t tmp32, tmp32b;
+ int32_t fQ15vec[HALF_SUBFRAMELEN];
+ int32_t gQ15[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ int16_t sh;
+ int16_t t16a;
+ int16_t t16b;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ int32_t temp1 = u * HALF_SUBFRAMELEN;
+
+ /* set the Direct Form coefficients */
+ temp2 = (int16_t)(u * orderCoef);
+ temp3 = (int16_t)(2 * u + lo_hi);
+
+ /* compute lattice filter coefficients */
+ memcpy(sthQ15, &filt_coefQ15[temp2], orderCoef * sizeof(int16_t));
+
+ WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);
+
+ /* compute the gain */
+ gain32 = gain_lo_hiQ17[temp3];
+ gain_sh = WebRtcSpl_NormW32(gain32);
+ gain32 <<= gain_sh; // Q(17+gain_sh)
+
+ for (k=0;k<orderCoef;k++)
+ {
+ gain32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], gain32); //Q15*Q(17+gain_sh)>>15 = Q(17+gain_sh)
+ inv_cthQ16[k] = WebRtcSpl_DivW32W16((int32_t)2147483647, cthQ15[k]); // 1/cth[k] in Q31/Q15 = Q16
+ }
+ gain16 = (int16_t)(gain32 >> 16); // Q(1+gain_sh).
+
+ /* normalized lattice filter */
+ /*****************************/
+
+ /* initial conditions */
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ fQ15vec[i] = lat_inQ0[i + temp1] << 15; // Q15
+ gQ15[0][i] = lat_inQ0[i + temp1] << 15; // Q15
+ }
+
+
+ fQtmp = fQ15vec[0];
+
+ /* get the state of f&g for the first input, for all orders */
+ for (i=1;i<ord_1;i++)
+ {
+ // Calculate f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], stateGQ15[i-1]);//Q15*Q15>>15 = Q15
+ tmp32b= fQtmp + tmp32; //Q15+Q15=Q15
+ tmp32 = inv_cthQ16[i-1]; //Q16
+ t16a = (int16_t)(tmp32 >> 16);
+ t16b = (int16_t)(tmp32 - (t16a << 16));
+ if (t16b<0) t16a++;
+ tmp32 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
+ fQtmp = tmp32; // Q15
+
+ // Calculate g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[i-1], stateGQ15[i-1]); //Q15*Q15>>15 = Q15
+ tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], fQtmp); //Q15*Q15>>15 = Q15
+ tmp32 = tmp32 + tmp32b;//Q15+Q15 = Q15
+ gQ15[i][0] = tmp32; // Q15
+ }
+
+ /* filtering */
+ /* save the states */
+ for(k=0;k<orderCoef;k++)
+ {
+ // for 0 <= n < HALF_SUBFRAMELEN - 1:
+ // f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
+ // g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
+ WebRtcIsacfix_FilterMaLoopFix(sthQ15[k], cthQ15[k], inv_cthQ16[k],
+ &gQ15[k][0], &gQ15[k+1][1], &fQ15vec[1]);
+ }
+
+ fQ15vec[0] = fQtmp;
+
+ for(n=0;n<HALF_SUBFRAMELEN;n++)
+ {
+ //gain32 >>= gain_sh; // Q(17+gain_sh) -> Q17
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(gain16, fQ15vec[n]); //Q(1+gain_sh)*Q15>>16 = Q(gain_sh)
+ sh = 9-gain_sh; //number of needed shifts to reach Q9
+ t16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh);
+ lat_outQ9[n + temp1] = t16a;
+ }
+
+ /* save the states */
+ for (i=0;i<ord_1;i++)
+ {
+ stateGQ15[i] = gQ15[i][HALF_SUBFRAMELEN-1];
+ }
+ //process next frame
+ }
+
+ return;
+}
+
+// Left shift of an int32_t that's allowed to overflow. (It's still undefined
+// behavior, so not a good idea; this just makes UBSan ignore the violation, so
+// that our old code can continue to do what it's always been doing.)
+static inline int32_t RTC_NO_SANITIZE("shift")
+ OverflowingLShiftS32(int32_t x, int shift) {
+ return x << shift;
+}
+
+/* ----------------AR filter-------------------------*/
+/* filter the signal using normalized lattice filter */
+void WebRtcIsacfix_NormLatticeFilterAr(size_t orderCoef,
+ int16_t *stateGQ0,
+ int32_t *lat_inQ25,
+ int16_t *filt_coefQ15,
+ int32_t *gain_lo_hiQ17,
+ int16_t lo_hi,
+ int16_t *lat_outQ0)
+{
+ size_t ii, k, i;
+ int n, u;
+ int16_t sthQ15[MAX_AR_MODEL_ORDER];
+ int16_t cthQ15[MAX_AR_MODEL_ORDER];
+ int32_t tmp32;
+
+
+ int16_t tmpAR;
+ int16_t ARfQ0vec[HALF_SUBFRAMELEN];
+ int16_t ARgQ0vec[MAX_AR_MODEL_ORDER+1];
+
+ int32_t inv_gain32;
+ int16_t inv_gain16;
+ int16_t den16;
+ int16_t sh;
+
+ int16_t temp2,temp3;
+ size_t ord_1 = orderCoef+1;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ int32_t temp1 = u * HALF_SUBFRAMELEN;
+
+ //set the denominator and numerator of the Direct Form
+ temp2 = (int16_t)(u * orderCoef);
+ temp3 = (int16_t)(2 * u + lo_hi);
+
+ for (ii=0; ii<orderCoef; ii++) {
+ sthQ15[ii] = filt_coefQ15[temp2+ii];
+ }
+
+ WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);
+
+ // Originally, this line was assumed to never overflow, since "[s]imulation
+ // of the 25 files shows that maximum value in the vector gain_lo_hiQ17[]
+ // is 441344, which means that it is log2((2^31)/441344) = 12.2 shifting
+ // bits from saturation. Therefore, it should be safe to use Q27 instead of
+ // Q17." However, a fuzzer test succeeded in provoking an overflow here,
+ // which we ignore on the theory that only "abnormal" inputs cause
+ // overflow.
+ tmp32 = OverflowingLShiftS32(gain_lo_hiQ17[temp3], 10); // Q27
+
+ for (k=0;k<orderCoef;k++) {
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], tmp32); // Q15*Q27>>15 = Q27
+ }
+
+ sh = WebRtcSpl_NormW32(tmp32); // tmp32 is the gain
+ den16 = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh-16); //Q(27+sh-16) = Q(sh+11) (all 16 bits are value bits)
+ inv_gain32 = WebRtcSpl_DivW32W16((int32_t)2147483647, den16); // 1/gain in Q31/Q(sh+11) = Q(20-sh)
+
+ //initial conditions
+ inv_gain16 = (int16_t)(inv_gain32 >> 2); // 1/gain in Q(20-sh-2) = Q(18-sh)
+
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ tmp32 = OverflowingLShiftS32(lat_inQ25[i + temp1], 1); // Q25->Q26
+ tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(inv_gain16, tmp32); //lat_in[]*inv_gain in (Q(18-sh)*Q26)>>16 = Q(28-sh)
+ tmp32 = WEBRTC_SPL_SHIFT_W32(tmp32, -(28-sh)); // lat_in[]*inv_gain in Q0
+
+ ARfQ0vec[i] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+ }
+
+ // Get the state of f & g for the first input, for all orders.
+ for (i = orderCoef; i > 0; i--)
+ {
+ tmp32 = (cthQ15[i - 1] * ARfQ0vec[0] - sthQ15[i - 1] * stateGQ0[i - 1] +
+ 16384) >> 15;
+ tmpAR = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+
+ tmp32 = (sthQ15[i - 1] * ARfQ0vec[0] + cthQ15[i - 1] * stateGQ0[i - 1] +
+ 16384) >> 15;
+ ARgQ0vec[i] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
+ ARfQ0vec[0] = tmpAR;
+ }
+ ARgQ0vec[0] = ARfQ0vec[0];
+
+ // Filter ARgQ0vec[] and ARfQ0vec[] through coefficients cthQ15[] and sthQ15[].
+ WebRtcIsacfix_FilterArLoop(ARgQ0vec, ARfQ0vec, cthQ15, sthQ15, orderCoef);
+
+ for(n=0;n<HALF_SUBFRAMELEN;n++)
+ {
+ lat_outQ0[n + temp1] = ARfQ0vec[n];
+ }
+
+
+ /* cannot use memcpy in the following */
+
+ for (i=0;i<ord_1;i++)
+ {
+ stateGQ0[i] = ARgQ0vec[i];
+ }
+ }
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S
new file mode 100644
index 0000000000..4c63227d7d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_armv7.S
@@ -0,0 +1,77 @@
+@
+@ Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+@
+@ Use of this source code is governed by a BSD-style license
+@ that can be found in the LICENSE file in the root of the source
+@ tree. An additional intellectual property rights grant can be found
+@ in the file PATENTS. All contributing project authors may
+@ be found in the AUTHORS file in the root of the source tree.
+@
+
+@ Contains a function for the core loop in the normalized lattice AR
+@ filter routine for iSAC codec, optimized for ARMv7 platforms.
+@
+@ Output is bit-exact with the reference C code in lattic_c.c
+@
+@ Register usage:
+@
+@ r0: &ar_g_Q0
+@ r1: &ar_f_Q0
+@ r2: &cth_Q15
+@ r3: &sth_Q15
+@ r4: out loop counter
+@ r5: tmpAR
+@ r9: inner loop counter
+@ r12: constant #16384
+@ r6, r7, r8, r10, r11: scratch
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/system/asm_defines.h"
+
+GLOBAL_FUNCTION WebRtcIsacfix_FilterArLoop
+.align 2
+DEFINE_FUNCTION WebRtcIsacfix_FilterArLoop
+ push {r4-r11}
+
+ add r1, #2 @ &ar_f_Q0[1]
+ mov r12, #16384
+ mov r4, #HALF_SUBFRAMELEN
+ sub r4, #1 @ Outer loop counter = HALF_SUBFRAMELEN - 1
+
+HALF_SUBFRAME_LOOP: @ for (n = 0; n < HALF_SUBFRAMELEN - 1; n++)
+
+ ldr r9, [sp, #32] @ Restore the inner loop counter to order_coef
+ ldrh r5, [r1] @ tmpAR = ar_f_Q0[n+1]
+ add r0, r9, asl #1 @ Restore r0 to &ar_g_Q0[order_coef]
+ add r2, r9, asl #1 @ Restore r2 to &cth_Q15[order_coef]
+ add r3, r9, asl #1 @ Restore r3 to &sth_Q15[order_coef]
+
+ORDER_COEF_LOOP: @ for (k = order_coef; k > 0; k--)
+
+ ldrh r7, [r3, #-2]! @ sth_Q15[k - 1]
+ ldrh r6, [r2, #-2]! @ cth_Q15[k - 1]
+
+ ldrh r8, [r0, #-2] @ ar_g_Q0[k - 1]
+ smlabb r11, r7, r5, r12 @ sth_Q15[k - 1] * tmpAR + 16384
+ smlabb r10, r6, r5, r12 @ cth_Q15[k - 1] * tmpAR + 16384
+ smulbb r7, r7, r8 @ sth_Q15[k - 1] * ar_g_Q0[k - 1]
+ smlabb r11, r6, r8, r11 @ cth_Q15[k - 1] * ar_g_Q0[k - 1] +
+ @ (sth_Q15[k - 1] * tmpAR + 16384)
+
+ sub r10, r10, r7 @ cth_Q15[k - 1] * tmpAR + 16384 -
+ @ (sth_Q15[k - 1] * ar_g_Q0[k - 1])
+ ssat r11, #16, r11, asr #15
+ ssat r5, #16, r10, asr #15
+ strh r11, [r0], #-2 @ Output: ar_g_Q0[k]
+
+ subs r9, #1
+ bgt ORDER_COEF_LOOP
+
+ strh r5, [r0] @ Output: ar_g_Q0[0] = tmpAR;
+ strh r5, [r1], #2 @ Output: ar_f_Q0[n+1] = tmpAR;
+
+ subs r4, #1
+ bne HALF_SUBFRAME_LOOP
+
+ pop {r4-r11}
+ bx lr
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_c.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
new file mode 100644
index 0000000000..43406612e8
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * Contains the core loop function for the lattice filter AR routine
+ * for iSAC codec.
+ *
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
+ * cth_Q15[] and sth_Q15[].
+ */
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0, // Input samples
+ int16_t* ar_f_Q0, // Input samples
+ int16_t* cth_Q15, // Filter coefficients
+ int16_t* sth_Q15, // Filter coefficients
+ size_t order_coef) { // order of the filter
+ int n = 0;
+
+ for (n = 0; n < HALF_SUBFRAMELEN - 1; n++) {
+ size_t k = 0;
+ int16_t tmpAR = 0;
+ int32_t tmp32 = 0;
+ int32_t tmp32_2 = 0;
+
+ tmpAR = ar_f_Q0[n + 1];
+ for (k = order_coef; k > 0; k--) {
+ tmp32 = (cth_Q15[k - 1] * tmpAR - sth_Q15[k - 1] * ar_g_Q0[k - 1] +
+ 16384) >> 15;
+ tmp32_2 = (sth_Q15[k - 1] * tmpAR + cth_Q15[k - 1] * ar_g_Q0[k - 1] +
+ 16384) >> 15;
+ tmpAR = (int16_t)WebRtcSpl_SatW32ToW16(tmp32);
+ ar_g_Q0[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32_2);
+ }
+ ar_f_Q0[n + 1] = tmpAR;
+ ar_g_Q0[0] = tmpAR;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
new file mode 100644
index 0000000000..3189726629
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
+// cth_Q15[] and sth_Q15[].
+void WebRtcIsacfix_FilterArLoop(int16_t* ar_g_Q0, // Input samples
+ int16_t* ar_f_Q0, // Input samples
+ int16_t* cth_Q15, // Filter coefficients
+ int16_t* sth_Q15, // Filter coefficients
+ size_t order_coef) { // order of the filter
+ int n = 0;
+
+ for (n = 0; n < HALF_SUBFRAMELEN - 1; n++) {
+ int count = (int)(order_coef - 1);
+ int offset;
+#if !defined(MIPS_DSP_R1_LE)
+ int16_t* tmp_cth;
+ int16_t* tmp_sth;
+ int16_t* tmp_arg;
+ int32_t max_q16 = 0x7fff;
+ int32_t min_q16 = 0xffff8000;
+#endif
+ // Declare variables used as temporary registers.
+ int32_t r0, r1, r2, t0, t1, t2, t_ar;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "bltz %[count], 2f \n\t"
+ " lh %[t_ar], 0(%[tmp]) \n\t"
+ // Inner loop
+ "1: \n\t"
+ "sll %[offset], %[count], 1 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "lhx %[r0], %[offset](%[cth_Q15]) \n\t"
+ "lhx %[r1], %[offset](%[sth_Q15]) \n\t"
+ "lhx %[r2], %[offset](%[ar_g_Q0]) \n\t"
+#else
+ "addu %[tmp_cth], %[cth_Q15], %[offset] \n\t"
+ "addu %[tmp_sth], %[sth_Q15], %[offset] \n\t"
+ "addu %[tmp_arg], %[ar_g_Q0], %[offset] \n\t"
+ "lh %[r0], 0(%[tmp_cth]) \n\t"
+ "lh %[r1], 0(%[tmp_sth]) \n\t"
+ "lh %[r2], 0(%[tmp_arg]) \n\t"
+#endif
+ "mul %[t0], %[r0], %[t_ar] \n\t"
+ "mul %[t1], %[r1], %[t_ar] \n\t"
+ "mul %[t2], %[r1], %[r2] \n\t"
+ "mul %[r0], %[r0], %[r2] \n\t"
+ "subu %[t0], %[t0], %[t2] \n\t"
+ "addu %[t1], %[t1], %[r0] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[t1], %[t1], 15 \n\t"
+ "shra_r.w %[t0], %[t0], 15 \n\t"
+#else
+ "addiu %[t1], %[t1], 0x4000 \n\t"
+ "sra %[t1], %[t1], 15 \n\t"
+ "addiu %[t0], %[t0], 0x4000 \n\t"
+ "sra %[t0], %[t0], 15 \n\t"
+#endif
+ "addiu %[offset], %[offset], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shll_s.w %[t1], %[t1], 16 \n\t"
+ "shll_s.w %[t_ar], %[t0], 16 \n\t"
+#else
+ "slt %[r0], %[t1], %[max_q16] \n\t"
+ "slt %[r1], %[t0], %[max_q16] \n\t"
+ "movz %[t1], %[max_q16], %[r0] \n\t"
+ "movz %[t0], %[max_q16], %[r1] \n\t"
+#endif
+ "addu %[offset], %[offset], %[ar_g_Q0] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "sra %[t1], %[t1], 16 \n\t"
+ "sra %[t_ar], %[t_ar], 16 \n\t"
+#else
+ "slt %[r0], %[t1], %[min_q16] \n\t"
+ "slt %[r1], %[t0], %[min_q16] \n\t"
+ "movn %[t1], %[min_q16], %[r0] \n\t"
+ "movn %[t0], %[min_q16], %[r1] \n\t"
+ "addu %[t_ar], $zero, %[t0] \n\t"
+#endif
+ "sh %[t1], 0(%[offset]) \n\t"
+ "bgtz %[count], 1b \n\t"
+ " addiu %[count], %[count], -1 \n\t"
+ "2: \n\t"
+ "sh %[t_ar], 0(%[tmp]) \n\t"
+ "sh %[t_ar], 0(%[ar_g_Q0]) \n\t"
+ ".set pop \n\t"
+ : [t_ar] "=&r" (t_ar), [count] "+r" (count), [offset] "=&r" (offset),
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [t0] "=&r" (t0),
+#if !defined(MIPS_DSP_R1_LE)
+ [tmp_cth] "=&r" (tmp_cth), [tmp_sth] "=&r" (tmp_sth),
+ [tmp_arg] "=&r" (tmp_arg),
+#endif
+ [t1] "=&r" (t1), [t2] "=&r" (t2)
+ : [tmp] "r" (&ar_f_Q0[n+1]), [cth_Q15] "r" (cth_Q15),
+#if !defined(MIPS_DSP_R1_LE)
+ [max_q16] "r" (max_q16), [min_q16] "r" (min_q16),
+#endif
+ [sth_Q15] "r" (sth_Q15), [ar_g_Q0] "r" (ar_g_Q0)
+ : "memory", "hi", "lo"
+ );
+ }
+}
+
+// MIPS optimization of the inner loop used for function
+// WebRtcIsacfix_NormLatticeFilterMa(). It does:
+//
+// for 0 <= n < HALF_SUBFRAMELEN - 1:
+// *ptr2 = input2 * (*ptr2) + input0 * (*ptr0));
+// *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+//
+// Note, function WebRtcIsacfix_FilterMaLoopMIPS and WebRtcIsacfix_FilterMaLoopC
+// are not bit-exact. The accuracy of the MIPS function is same or better.
+void WebRtcIsacfix_FilterMaLoopMIPS(int16_t input0, // Filter coefficient
+ int16_t input1, // Filter coefficient
+ int32_t input2, // Inverse coeff (1/input1)
+ int32_t* ptr0, // Sample buffer
+ int32_t* ptr1, // Sample buffer
+ int32_t* ptr2) { // Sample buffer
+#if defined(MIPS_DSP_R2_LE)
+ // MIPS DSPR2 version. 4 available accumulators allows loop unrolling 4 times.
+ // This variant is not bit-exact with WebRtcIsacfix_FilterMaLoopC, since we
+ // are exploiting 64-bit accumulators. The accuracy of the MIPS DSPR2 function
+ // is same or better.
+ int n = (HALF_SUBFRAMELEN - 1) >> 2;
+ int m = (HALF_SUBFRAMELEN - 1) & 3;
+
+ int r0, r1, r2, r3;
+ int t0, t1, t2, t3;
+ int s0, s1, s2, s3;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "1: \n\t"
+ "lw %[r0], 0(%[ptr0]) \n\t"
+ "lw %[r1], 4(%[ptr0]) \n\t"
+ "lw %[r2], 8(%[ptr0]) \n\t"
+ "lw %[r3], 12(%[ptr0]) \n\t"
+ "mult $ac0, %[r0], %[input0] \n\t"
+ "mult $ac1, %[r1], %[input0] \n\t"
+ "mult $ac2, %[r2], %[input0] \n\t"
+ "mult $ac3, %[r3], %[input0] \n\t"
+ "lw %[t0], 0(%[ptr2]) \n\t"
+ "extr_rs.w %[s0], $ac0, 15 \n\t"
+ "extr_rs.w %[s1], $ac1, 15 \n\t"
+ "extr_rs.w %[s2], $ac2, 15 \n\t"
+ "extr_rs.w %[s3], $ac3, 15 \n\t"
+ "lw %[t1], 4(%[ptr2]) \n\t"
+ "lw %[t2], 8(%[ptr2]) \n\t"
+ "lw %[t3], 12(%[ptr2]) \n\t"
+ "addu %[t0], %[t0], %[s0] \n\t"
+ "addu %[t1], %[t1], %[s1] \n\t"
+ "addu %[t2], %[t2], %[s2] \n\t"
+ "addu %[t3], %[t3], %[s3] \n\t"
+ "mult $ac0, %[t0], %[input2] \n\t"
+ "mult $ac1, %[t1], %[input2] \n\t"
+ "mult $ac2, %[t2], %[input2] \n\t"
+ "mult $ac3, %[t3], %[input2] \n\t"
+ "addiu %[ptr0], %[ptr0], 16 \n\t"
+ "extr_rs.w %[t0], $ac0, 16 \n\t"
+ "extr_rs.w %[t1], $ac1, 16 \n\t"
+ "extr_rs.w %[t2], $ac2, 16 \n\t"
+ "extr_rs.w %[t3], $ac3, 16 \n\t"
+ "addiu %[n], %[n], -1 \n\t"
+ "mult $ac0, %[r0], %[input1] \n\t"
+ "mult $ac1, %[r1], %[input1] \n\t"
+ "mult $ac2, %[r2], %[input1] \n\t"
+ "mult $ac3, %[r3], %[input1] \n\t"
+ "sw %[t0], 0(%[ptr2]) \n\t"
+ "extr_rs.w %[s0], $ac0, 15 \n\t"
+ "extr_rs.w %[s1], $ac1, 15 \n\t"
+ "extr_rs.w %[s2], $ac2, 15 \n\t"
+ "extr_rs.w %[s3], $ac3, 15 \n\t"
+ "sw %[t1], 4(%[ptr2]) \n\t"
+ "sw %[t2], 8(%[ptr2]) \n\t"
+ "sw %[t3], 12(%[ptr2]) \n\t"
+ "mult $ac0, %[t0], %[input0] \n\t"
+ "mult $ac1, %[t1], %[input0] \n\t"
+ "mult $ac2, %[t2], %[input0] \n\t"
+ "mult $ac3, %[t3], %[input0] \n\t"
+ "addiu %[ptr2], %[ptr2], 16 \n\t"
+ "extr_rs.w %[t0], $ac0, 15 \n\t"
+ "extr_rs.w %[t1], $ac1, 15 \n\t"
+ "extr_rs.w %[t2], $ac2, 15 \n\t"
+ "extr_rs.w %[t3], $ac3, 15 \n\t"
+ "addu %[t0], %[t0], %[s0] \n\t"
+ "addu %[t1], %[t1], %[s1] \n\t"
+ "addu %[t2], %[t2], %[s2] \n\t"
+ "addu %[t3], %[t3], %[s3] \n\t"
+ "sw %[t0], 0(%[ptr1]) \n\t"
+ "sw %[t1], 4(%[ptr1]) \n\t"
+ "sw %[t2], 8(%[ptr1]) \n\t"
+ "sw %[t3], 12(%[ptr1]) \n\t"
+ "bgtz %[n], 1b \n\t"
+ " addiu %[ptr1], %[ptr1], 16 \n\t"
+ "beq %[m], %0, 3f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+ "lw %[r0], 0(%[ptr0]) \n\t"
+ "lw %[t0], 0(%[ptr2]) \n\t"
+ "addiu %[ptr0], %[ptr0], 4 \n\t"
+ "mult $ac0, %[r0], %[input0] \n\t"
+ "mult $ac1, %[r0], %[input1] \n\t"
+ "extr_rs.w %[r1], $ac0, 15 \n\t"
+ "extr_rs.w %[t1], $ac1, 15 \n\t"
+ "addu %[t0], %[t0], %[r1] \n\t"
+ "mult $ac0, %[t0], %[input2] \n\t"
+ "extr_rs.w %[t0], $ac0, 16 \n\t"
+ "sw %[t0], 0(%[ptr2]) \n\t"
+ "mult $ac0, %[t0], %[input0] \n\t"
+ "addiu %[ptr2], %[ptr2], 4 \n\t"
+ "addiu %[m], %[m], -1 \n\t"
+ "extr_rs.w %[t0], $ac0, 15 \n\t"
+ "addu %[t0], %[t0], %[t1] \n\t"
+ "sw %[t0], 0(%[ptr1]) \n\t"
+ "bgtz %[m], 2b \n\t"
+ " addiu %[ptr1], %[ptr1], 4 \n\t"
+ "3: \n\t"
+ ".set pop \n\t"
+ : [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
+ [r3] "=&r" (r3), [t0] "=&r" (t0), [t1] "=&r" (t1),
+ [t2] "=&r" (t2), [t3] "=&r" (t3), [s0] "=&r" (s0),
+ [s1] "=&r" (s1), [s2] "=&r" (s2), [s3] "=&r" (s3),
+ [ptr0] "+r" (ptr0), [ptr1] "+r" (ptr1), [m] "+r" (m),
+ [ptr2] "+r" (ptr2), [n] "+r" (n)
+ : [input0] "r" (input0), [input1] "r" (input1),
+ [input2] "r" (input2)
+ : "memory", "hi", "lo", "$ac1hi", "$ac1lo", "$ac2hi",
+ "$ac2lo", "$ac3hi", "$ac3lo"
+ );
+#else
+ // Non-DSPR2 version of the function. Avoiding the accumulator usage due to
+ // large latencies. This variant is bit-exact with C code.
+ int n = HALF_SUBFRAMELEN - 1;
+ int32_t t16a, t16b;
+ int32_t r0, r1, r2, r3, r4;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "sra %[t16a], %[input2], 16 \n\t"
+ "andi %[t16b], %[input2], 0xFFFF \n\t"
+#if defined(MIPS32R2_LE)
+ "seh %[t16b], %[t16b] \n\t"
+ "seh %[input0], %[input0] \n\t"
+ "seh %[input1], %[input1] \n\t"
+#else
+ "sll %[t16b], %[t16b], 16 \n\t"
+ "sra %[t16b], %[t16b], 16 \n\t"
+ "sll %[input0], %[input0], 16 \n\t"
+ "sra %[input0], %[input0], 16 \n\t"
+ "sll %[input1], %[input1], 16 \n\t"
+ "sra %[input1], %[input1], 16 \n\t"
+#endif
+ "addiu %[r0], %[t16a], 1 \n\t"
+ "slt %[r1], %[t16b], $zero \n\t"
+ "movn %[t16a], %[r0], %[r1] \n\t"
+ "1: \n\t"
+ "lw %[r0], 0(%[ptr0]) \n\t"
+ "lw %[r1], 0(%[ptr2]) \n\t"
+ "addiu %[ptr0], %[ptr0], 4 \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "mul %[r3], %[r2], %[input0] \n\t"
+ "mul %[r4], %[r0], %[input0] \n\t"
+ "mul %[r2], %[r2], %[input1] \n\t"
+ "mul %[r0], %[r0], %[input1] \n\t"
+ "addiu %[ptr2], %[ptr2], 4 \n\t"
+ "sll %[r3], %[r3], 1 \n\t"
+ "sra %[r4], %[r4], 1 \n\t"
+ "addiu %[r4], %[r4], 0x2000 \n\t"
+ "sra %[r4], %[r4], 14 \n\t"
+ "addu %[r3], %[r3], %[r4] \n\t"
+ "addu %[r1], %[r1], %[r3] \n\t"
+ "sra %[r3], %[r1], 16 \n\t"
+ "andi %[r4], %[r1], 0xFFFF \n\t"
+ "sra %[r4], %[r4], 1 \n\t"
+ "mul %[r1], %[r1], %[t16a] \n\t"
+ "mul %[r3], %[r3], %[t16b] \n\t"
+ "mul %[r4], %[r4], %[t16b] \n\t"
+ "sll %[r2], %[r2], 1 \n\t"
+ "sra %[r0], %[r0], 1 \n\t"
+ "addiu %[r0], %[r0], 0x2000 \n\t"
+ "sra %[r0], %[r0], 14 \n\t"
+ "addu %[r0], %[r0], %[r2] \n\t"
+ "addiu %[n], %[n], -1 \n\t"
+ "addu %[r1], %[r1], %[r3] \n\t"
+ "addiu %[r4], %[r4], 0x4000 \n\t"
+ "sra %[r4], %[r4], 15 \n\t"
+ "addu %[r1], %[r1], %[r4] \n\t"
+ "sra %[r2], %[r1], 16 \n\t"
+ "andi %[r3], %[r1], 0xFFFF \n\t"
+ "mul %[r3], %[r3], %[input0] \n\t"
+ "mul %[r2], %[r2], %[input0] \n\t"
+ "sw %[r1], -4(%[ptr2]) \n\t"
+ "sra %[r3], %[r3], 1 \n\t"
+ "addiu %[r3], %[r3], 0x2000 \n\t"
+ "sra %[r3], %[r3], 14 \n\t"
+ "addu %[r0], %[r0], %[r3] \n\t"
+ "sll %[r2], %[r2], 1 \n\t"
+ "addu %[r0], %[r0], %[r2] \n\t"
+ "sw %[r0], 0(%[ptr1]) \n\t"
+ "bgtz %[n], 1b \n\t"
+ " addiu %[ptr1], %[ptr1], 4 \n\t"
+ ".set pop \n\t"
+ : [t16a] "=&r" (t16a), [t16b] "=&r" (t16b), [r0] "=&r" (r0),
+ [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [r4] "=&r" (r4), [ptr0] "+r" (ptr0), [ptr1] "+r" (ptr1),
+ [ptr2] "+r" (ptr2), [n] "+r" (n)
+ : [input0] "r" (input0), [input1] "r" (input1),
+ [input2] "r" (input2)
+ : "hi", "lo", "memory"
+ );
+#endif
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c
new file mode 100644
index 0000000000..8ea9b63578
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// Contains a function for the core loop in the normalized lattice MA
+// filter routine for iSAC codec, optimized for ARM Neon platform.
+// It does:
+// for 0 <= n < HALF_SUBFRAMELEN - 1:
+// *ptr2 = input2 * ((*ptr2) + input0 * (*ptr0));
+// *ptr1 = input1 * (*ptr0) + input0 * (*ptr2);
+// Output is not bit-exact with the reference C code, due to the replacement
+// of WEBRTC_SPL_MUL_16_32_RSFT15 and LATTICE_MUL_32_32_RSFT16 with Neon
+// instructions. The difference should not be bigger than 1.
+void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0, // Filter coefficient
+ int16_t input1, // Filter coefficient
+ int32_t input2, // Inverse coefficient
+ int32_t* ptr0, // Sample buffer
+ int32_t* ptr1, // Sample buffer
+ int32_t* ptr2) // Sample buffer
+{
+ int n = 0;
+ int loop = (HALF_SUBFRAMELEN - 1) >> 3;
+ int loop_tail = (HALF_SUBFRAMELEN - 1) & 0x7;
+
+ int32x4_t input0_v = vdupq_n_s32((int32_t)input0 << 16);
+ int32x4_t input1_v = vdupq_n_s32((int32_t)input1 << 16);
+ int32x4_t input2_v = vdupq_n_s32(input2);
+ int32x4_t tmp0a, tmp1a, tmp2a, tmp3a;
+ int32x4_t tmp0b, tmp1b, tmp2b, tmp3b;
+ int32x4_t ptr0va, ptr1va, ptr2va;
+ int32x4_t ptr0vb, ptr1vb, ptr2vb;
+
+ int64x2_t tmp2al_low, tmp2al_high, tmp2bl_low, tmp2bl_high;
+ // Unroll to process 8 samples at once.
+ for (n = 0; n < loop; n++) {
+ ptr0va = vld1q_s32(ptr0);
+ ptr0vb = vld1q_s32(ptr0 + 4);
+ ptr0 += 8;
+
+ ptr2va = vld1q_s32(ptr2);
+ ptr2vb = vld1q_s32(ptr2 + 4);
+
+ // Calculate tmp0 = (*ptr0) * input0.
+ tmp0a = vqrdmulhq_s32(ptr0va, input0_v);
+ tmp0b = vqrdmulhq_s32(ptr0vb, input0_v);
+
+ // Calculate tmp1 = (*ptr0) * input1.
+ tmp1a = vqrdmulhq_s32(ptr0va, input1_v);
+ tmp1b = vqrdmulhq_s32(ptr0vb, input1_v);
+
+ // Calculate tmp2 = tmp0 + *(ptr2).
+ tmp2a = vaddq_s32(tmp0a, ptr2va);
+ tmp2b = vaddq_s32(tmp0b, ptr2vb);
+
+ // Calculate *ptr2 = input2 * tmp2.
+ tmp2al_low = vmull_s32(vget_low_s32(tmp2a), vget_low_s32(input2_v));
+#if defined(WEBRTC_ARCH_ARM64)
+ tmp2al_high = vmull_high_s32(tmp2a, input2_v);
+#else
+ tmp2al_high = vmull_s32(vget_high_s32(tmp2a), vget_high_s32(input2_v));
+#endif
+ ptr2va = vcombine_s32(vrshrn_n_s64(tmp2al_low, 16),
+ vrshrn_n_s64(tmp2al_high, 16));
+
+ tmp2bl_low = vmull_s32(vget_low_s32(tmp2b), vget_low_s32(input2_v));
+#if defined(WEBRTC_ARCH_ARM64)
+ tmp2bl_high = vmull_high_s32(tmp2b, input2_v);
+#else
+ tmp2bl_high = vmull_s32(vget_high_s32(tmp2b), vget_high_s32(input2_v));
+#endif
+ ptr2vb = vcombine_s32(vrshrn_n_s64(tmp2bl_low, 16),
+ vrshrn_n_s64(tmp2bl_high, 16));
+
+ vst1q_s32(ptr2, ptr2va);
+ vst1q_s32(ptr2 + 4, ptr2vb);
+ ptr2 += 8;
+
+ // Calculate tmp3 = ptr2v * input0.
+ tmp3a = vqrdmulhq_s32(ptr2va, input0_v);
+ tmp3b = vqrdmulhq_s32(ptr2vb, input0_v);
+
+ // Calculate *ptr1 = tmp1 + tmp3.
+ ptr1va = vaddq_s32(tmp1a, tmp3a);
+ ptr1vb = vaddq_s32(tmp1b, tmp3b);
+
+ vst1q_s32(ptr1, ptr1va);
+ vst1q_s32(ptr1 + 4, ptr1vb);
+ ptr1 += 8;
+ }
+
+ // Process four more samples.
+ if (loop_tail & 0x4) {
+ ptr0va = vld1q_s32(ptr0);
+ ptr2va = vld1q_s32(ptr2);
+ ptr0 += 4;
+
+ // Calculate tmp0 = (*ptr0) * input0.
+ tmp0a = vqrdmulhq_s32(ptr0va, input0_v);
+
+ // Calculate tmp1 = (*ptr0) * input1.
+ tmp1a = vqrdmulhq_s32(ptr0va, input1_v);
+
+ // Calculate tmp2 = tmp0 + *(ptr2).
+ tmp2a = vaddq_s32(tmp0a, ptr2va);
+
+ // Calculate *ptr2 = input2 * tmp2.
+ tmp2al_low = vmull_s32(vget_low_s32(tmp2a), vget_low_s32(input2_v));
+
+#if defined(WEBRTC_ARCH_ARM64)
+ tmp2al_high = vmull_high_s32(tmp2a, input2_v);
+#else
+ tmp2al_high = vmull_s32(vget_high_s32(tmp2a), vget_high_s32(input2_v));
+#endif
+ ptr2va = vcombine_s32(vrshrn_n_s64(tmp2al_low, 16),
+ vrshrn_n_s64(tmp2al_high, 16));
+
+ vst1q_s32(ptr2, ptr2va);
+ ptr2 += 4;
+
+ // Calculate tmp3 = *(ptr2) * input0.
+ tmp3a = vqrdmulhq_s32(ptr2va, input0_v);
+
+ // Calculate *ptr1 = tmp1 + tmp3.
+ ptr1va = vaddq_s32(tmp1a, tmp3a);
+
+ vst1q_s32(ptr1, ptr1va);
+ ptr1 += 4;
+ }
+
+ // Process two more samples.
+ if (loop_tail & 0x2) {
+ int32x2_t ptr0v_tail, ptr2v_tail, ptr1v_tail;
+ int32x2_t tmp0_tail, tmp1_tail, tmp2_tail, tmp3_tail;
+ int64x2_t tmp2l_tail;
+ ptr0v_tail = vld1_s32(ptr0);
+ ptr2v_tail = vld1_s32(ptr2);
+ ptr0 += 2;
+
+ // Calculate tmp0 = (*ptr0) * input0.
+ tmp0_tail = vqrdmulh_s32(ptr0v_tail, vget_low_s32(input0_v));
+
+ // Calculate tmp1 = (*ptr0) * input1.
+ tmp1_tail = vqrdmulh_s32(ptr0v_tail, vget_low_s32(input1_v));
+
+ // Calculate tmp2 = tmp0 + *(ptr2).
+ tmp2_tail = vadd_s32(tmp0_tail, ptr2v_tail);
+
+ // Calculate *ptr2 = input2 * tmp2.
+ tmp2l_tail = vmull_s32(tmp2_tail, vget_low_s32(input2_v));
+ ptr2v_tail = vrshrn_n_s64(tmp2l_tail, 16);
+
+ vst1_s32(ptr2, ptr2v_tail);
+ ptr2 += 2;
+
+ // Calculate tmp3 = *(ptr2) * input0.
+ tmp3_tail = vqrdmulh_s32(ptr2v_tail, vget_low_s32(input0_v));
+
+ // Calculate *ptr1 = tmp1 + tmp3.
+ ptr1v_tail = vadd_s32(tmp1_tail, tmp3_tail);
+
+ vst1_s32(ptr1, ptr1v_tail);
+ ptr1 += 2;
+ }
+
+ // Process one more sample.
+ if (loop_tail & 0x1) {
+ int16_t t16a = (int16_t)(input2 >> 16);
+ int16_t t16b = (int16_t)input2;
+ if (t16b < 0) t16a++;
+ int32_t tmp32a;
+ int32_t tmp32b;
+
+ // Calculate *ptr2 = input2 * (*ptr2 + input0 * (*ptr0)).
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr0);
+ tmp32b = *ptr2 + tmp32a;
+ *ptr2 = (int32_t)(WEBRTC_SPL_MUL(t16a, tmp32b) +
+ (WEBRTC_SPL_MUL_16_32_RSFT16(t16b, tmp32b)));
+
+ // Calculate *ptr1 = input1 * (*ptr0) + input0 * (*ptr2).
+ tmp32a = WEBRTC_SPL_MUL_16_32_RSFT15(input1, *ptr0);
+ tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(input0, *ptr2);
+ *ptr1 = tmp32a + tmp32b;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c
new file mode 100644
index 0000000000..f151cd1c88
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_masking_model.c
+ *
+ * LPC analysis and filtering functions
+ *
+ */
+
+#include "lpc_masking_model.h"
+
+#include <limits.h> /* For LLONG_MAX and LLONG_MIN. */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* The conversion is implemented by the step-down algorithm */
+void WebRtcSpl_AToK_JSK(
+ int16_t *a16, /* Q11 */
+ int16_t useOrder,
+ int16_t *k16 /* Q15 */
+ )
+{
+ int m, k;
+ int32_t tmp32[MAX_AR_MODEL_ORDER];
+ int32_t tmp32b;
+ int32_t tmp_inv_denum32;
+ int16_t tmp_inv_denum16;
+
+ k16[useOrder-1] = a16[useOrder] << 4; // Q11<<4 => Q15
+
+ for (m=useOrder-1; m>0; m--) {
+ // (1 - k^2) in Q30
+ tmp_inv_denum32 = 1073741823 - k16[m] * k16[m];
+ tmp_inv_denum16 = (int16_t)(tmp_inv_denum32 >> 15); // (1 - k^2) in Q15.
+
+ for (k=1; k<=m; k++) {
+ tmp32b = (a16[k] << 16) - ((k16[m] * a16[m - k + 1]) << 1);
+
+ tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12
+ }
+
+ for (k=1; k<m; k++) {
+ a16[k] = (int16_t)(tmp32[k] >> 1); // Q12>>1 => Q11
+ }
+
+ tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092);
+ k16[m - 1] = (int16_t)(tmp32[m] << 3); // Q12<<3 => Q15
+ }
+
+ return;
+}
+
+
+
+
+
+int16_t WebRtcSpl_LevinsonW32_JSK(
+ int32_t *R, /* (i) Autocorrelation of length >= order+1 */
+ int16_t *A, /* (o) A[0..order] LPC coefficients (Q11) */
+ int16_t *K, /* (o) K[0...order-1] Reflection coefficients (Q15) */
+ int16_t order /* (i) filter order */
+ ) {
+ int16_t i, j;
+ int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
+ /* Aurocorr coefficients in high precision */
+ int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
+ /* LPC coefficients in high precicion */
+ int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
+ /* LPC coefficients for next iteration */
+ int16_t K_hi, K_low; /* reflection coefficient in high precision */
+ int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
+ and with scale factor */
+ int16_t tmp_hi, tmp_low;
+ int32_t temp1W32, temp2W32, temp3W32;
+ int16_t norm;
+
+ /* Normalize the autocorrelation R[0]...R[order+1] */
+
+ norm = WebRtcSpl_NormW32(R[0]);
+
+ for (i=order;i>=0;i--) {
+ temp1W32 = R[i] << norm;
+ /* Put R in hi and low format */
+ R_hi[i] = (int16_t)(temp1W32 >> 16);
+ R_low[i] = (int16_t)((temp1W32 - ((int32_t)R_hi[i] << 16)) >> 1);
+ }
+
+ /* K = A[1] = -R[1] / R[0] */
+
+ temp2W32 = (R_hi[1] << 16) + (R_low[1] << 1); /* R[1] in Q31 */
+ temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); /* abs R[1] */
+ temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */
+ /* Put back the sign on R[1] */
+ if (temp2W32 > 0) {
+ temp1W32 = -temp1W32;
+ }
+
+ /* Put K in hi and low format */
+ K_hi = (int16_t)(temp1W32 >> 16);
+ K_low = (int16_t)((temp1W32 - ((int32_t)K_hi << 16)) >> 1);
+
+ /* Store first reflection coefficient */
+ K[0] = K_hi;
+
+ temp1W32 >>= 4; /* A[1] in Q27. */
+
+ /* Put A[1] in hi and low format */
+ A_hi[1] = (int16_t)(temp1W32 >> 16);
+ A_low[1] = (int16_t)((temp1W32 - ((int32_t)A_hi[1] << 16)) >> 1);
+
+ /* Alpha = R[0] * (1-K^2) */
+
+ temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1; /* = k^2 in Q31 */
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */
+ temp1W32 = (int32_t)0x7fffffffL - temp1W32; /* temp1W32 = (1 - K[0]*K[0]) in Q31 */
+
+ /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */
+ tmp_hi = (int16_t)(temp1W32 >> 16);
+ tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1);
+
+ /* Calculate Alpha in Q31 */
+ temp1W32 = (R_hi[0] * tmp_hi + ((R_hi[0] * tmp_low) >> 15) +
+ ((R_low[0] * tmp_hi) >> 15)) << 1;
+
+ /* Normalize Alpha and put it in hi and low format */
+
+ Alpha_exp = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 <<= Alpha_exp;
+ Alpha_hi = (int16_t)(temp1W32 >> 16);
+ Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi<< 16)) >> 1);
+
+ /* Perform the iterative calculations in the
+ Levinson Durbin algorithm */
+
+ for (i=2; i<=order; i++)
+ {
+
+ /* ----
+ \
+ temp1W32 = R[i] + > R[j]*A[i-j]
+ /
+ ----
+ j=1..i-1
+ */
+
+ temp1W32 = 0;
+
+ for(j=1; j<i; j++) {
+ /* temp1W32 is in Q31 */
+ temp1W32 += ((R_hi[j] * A_hi[i - j]) << 1) +
+ ((((R_hi[j] * A_low[i - j]) >> 15) +
+ ((R_low[j] * A_hi[i - j]) >> 15)) << 1);
+ }
+
+ temp1W32 <<= 4;
+ temp1W32 += (R_hi[i] << 16) + (R_low[i] << 1);
+
+ /* K = -temp1W32 / Alpha */
+ temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* abs(temp1W32) */
+ temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */
+
+ /* Put the sign of temp1W32 back again */
+ if (temp1W32 > 0) {
+ temp3W32 = -temp3W32;
+ }
+
+ /* Use the Alpha shifts from earlier to denormalize */
+ norm = WebRtcSpl_NormW32(temp3W32);
+ if ((Alpha_exp <= norm)||(temp3W32==0)) {
+ temp3W32 <<= Alpha_exp;
+ } else {
+ if (temp3W32 > 0)
+ {
+ temp3W32 = (int32_t)0x7fffffffL;
+ } else
+ {
+ temp3W32 = (int32_t)0x80000000L;
+ }
+ }
+
+ /* Put K on hi and low format */
+ K_hi = (int16_t)(temp3W32 >> 16);
+ K_low = (int16_t)((temp3W32 - ((int32_t)K_hi << 16)) >> 1);
+
+ /* Store Reflection coefficient in Q15 */
+ K[i-1] = K_hi;
+
+ /* Test for unstable filter. If unstable return 0 and let the
+ user decide what to do in that case
+ */
+
+ if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32740) {
+ return(-i); /* Unstable filter */
+ }
+
+ /*
+ Compute updated LPC coefficient: Anew[i]
+ Anew[j]= A[j] + K*A[i-j] for j=1..i-1
+ Anew[i]= K
+ */
+
+ for(j=1; j<i; j++)
+ {
+ temp1W32 = (A_hi[j] << 16) + (A_low[j] << 1); // temp1W32 = A[j] in Q27
+
+ temp1W32 += (K_hi * A_hi[i - j] + ((K_hi * A_low[i - j]) >> 15) +
+ ((K_low * A_hi[i - j]) >> 15)) << 1; // temp1W32 += K*A[i-j] in Q27.
+
+ /* Put Anew in hi and low format */
+ A_upd_hi[j] = (int16_t)(temp1W32 >> 16);
+ A_upd_low[j] = (int16_t)((temp1W32 - ((int32_t)A_upd_hi[j] << 16)) >> 1);
+ }
+
+ temp3W32 >>= 4; /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */
+
+ /* Store Anew in hi and low format */
+ A_upd_hi[i] = (int16_t)(temp3W32 >> 16);
+ A_upd_low[i] = (int16_t)((temp3W32 - ((int32_t)A_upd_hi[i] << 16)) >> 1);
+
+ /* Alpha = Alpha * (1-K^2) */
+
+ temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1; /* K*K in Q31 */
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */
+ temp1W32 = (int32_t)0x7fffffffL - temp1W32; /* 1 - K*K in Q31 */
+
+ /* Convert 1- K^2 in hi and low format */
+ tmp_hi = (int16_t)(temp1W32 >> 16);
+ tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1);
+
+ /* Calculate Alpha = Alpha * (1-K^2) in Q31 */
+ temp1W32 = (Alpha_hi * tmp_hi + ((Alpha_hi * tmp_low) >> 15) +
+ ((Alpha_low * tmp_hi) >> 15)) << 1;
+
+ /* Normalize Alpha and store it on hi and low format */
+
+ norm = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 <<= norm;
+
+ Alpha_hi = (int16_t)(temp1W32 >> 16);
+ Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi << 16)) >> 1);
+
+ /* Update the total nomalization of Alpha */
+ Alpha_exp = Alpha_exp + norm;
+
+ /* Update A[] */
+
+ for(j=1; j<=i; j++)
+ {
+ A_hi[j] =A_upd_hi[j];
+ A_low[j] =A_upd_low[j];
+ }
+ }
+
+ /*
+ Set A[0] to 1.0 and store the A[i] i=1...order in Q12
+ (Convert from Q27 and use rounding)
+ */
+
+ A[0] = 2048;
+
+ for(i=1; i<=order; i++) {
+ /* temp1W32 in Q27 */
+ temp1W32 = (A_hi[i] << 16) + (A_low[i] << 1);
+ /* Round and store upper word */
+ A[i] = (int16_t)((temp1W32 + 32768) >> 16);
+ }
+ return(1); /* Stable filters */
+}
+
+
+
+
+
+/* window */
+/* Matlab generation of floating point code:
+ * t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
+ * for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
+ * All values are multiplyed with 2^21 in fixed point code.
+ */
+static const int16_t kWindowAutocorr[WINLEN] = {
+ 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5, 6,
+ 8, 10, 12, 14, 17, 20, 24, 28, 33, 38, 43, 49,
+ 56, 63, 71, 79, 88, 98, 108, 119, 131, 143, 157, 171,
+ 186, 202, 219, 237, 256, 275, 296, 318, 341, 365, 390, 416,
+ 444, 472, 502, 533, 566, 600, 635, 671, 709, 748, 789, 831,
+ 875, 920, 967, 1015, 1065, 1116, 1170, 1224, 1281, 1339, 1399, 1461,
+ 1525, 1590, 1657, 1726, 1797, 1870, 1945, 2021, 2100, 2181, 2263, 2348,
+ 2434, 2523, 2614, 2706, 2801, 2898, 2997, 3099, 3202, 3307, 3415, 3525,
+ 3637, 3751, 3867, 3986, 4106, 4229, 4354, 4481, 4611, 4742, 4876, 5012,
+ 5150, 5291, 5433, 5578, 5725, 5874, 6025, 6178, 6333, 6490, 6650, 6811,
+ 6974, 7140, 7307, 7476, 7647, 7820, 7995, 8171, 8349, 8529, 8711, 8894,
+ 9079, 9265, 9453, 9642, 9833, 10024, 10217, 10412, 10607, 10803, 11000, 11199,
+ 11398, 11597, 11797, 11998, 12200, 12401, 12603, 12805, 13008, 13210, 13412, 13614,
+ 13815, 14016, 14216, 14416, 14615, 14813, 15009, 15205, 15399, 15591, 15782, 15971,
+ 16157, 16342, 16524, 16704, 16881, 17056, 17227, 17395, 17559, 17720, 17877, 18030,
+ 18179, 18323, 18462, 18597, 18727, 18851, 18970, 19082, 19189, 19290, 19384, 19471,
+ 19551, 19623, 19689, 19746, 19795, 19835, 19867, 19890, 19904, 19908, 19902, 19886,
+ 19860, 19823, 19775, 19715, 19644, 19561, 19465, 19357, 19237, 19102, 18955, 18793,
+ 18618, 18428, 18223, 18004, 17769, 17518, 17252, 16970, 16672, 16357, 16025, 15677,
+ 15311, 14929, 14529, 14111, 13677, 13225, 12755, 12268, 11764, 11243, 10706, 10152,
+ 9583, 8998, 8399, 7787, 7162, 6527, 5883, 5231, 4576, 3919, 3265, 2620,
+ 1990, 1386, 825, 333
+};
+
+
+/* By using a hearing threshold level in dB of -28 dB (higher value gives more noise),
+ the H_T_H (in float) can be calculated as:
+ H_T_H = pow(10.0, 0.05 * (-28.0)) = 0.039810717055350
+ In Q19, H_T_H becomes round(0.039810717055350*2^19) ~= 20872, i.e.
+ H_T_H = 20872/524288.0, and H_T_HQ19 = 20872;
+*/
+
+
+/* The bandwidth expansion vectors are created from:
+ kPolyVecLo=[0.900000,0.810000,0.729000,0.656100,0.590490,0.531441,0.478297,0.430467,0.387420,0.348678,0.313811,0.282430];
+ kPolyVecHi=[0.800000,0.640000,0.512000,0.409600,0.327680,0.262144];
+ round(kPolyVecLo*32768)
+ round(kPolyVecHi*32768)
+*/
+static const int16_t kPolyVecLo[12] = {
+ 29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255
+};
+static const int16_t kPolyVecHi[6] = {
+ 26214, 20972, 16777, 13422, 10737, 8590
+};
+
+static __inline int32_t log2_Q8_LPC( uint32_t x ) {
+
+ int32_t zeros;
+ int16_t frac;
+
+ zeros=WebRtcSpl_NormU32(x);
+ frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
+
+ /* log2(x) */
+ return ((31 - zeros) << 8) + frac;
+}
+
+static const int16_t kMulPitchGain = -25; /* 200/256 in Q5 */
+static const int16_t kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */
+static const int16_t kExp2 = 11819; /* 1/log(2) */
+const int kShiftLowerBand = 11; /* Shift value for lower band in Q domain. */
+const int kShiftHigherBand = 12; /* Shift value for higher band in Q domain. */
+
+void WebRtcIsacfix_GetVars(const int16_t *input, const int16_t *pitchGains_Q12,
+ uint32_t *oldEnergy, int16_t *varscale)
+{
+ int k;
+ uint32_t nrgQ[4];
+ int16_t nrgQlog[4];
+ int16_t tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3;
+ int32_t expPg32;
+ int16_t expPg, divVal;
+ int16_t tmp16_1, tmp16_2;
+
+ /* Calculate energies of first and second frame halfs */
+ nrgQ[0]=0;
+ for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES/4 + QLOOKAHEAD) / 2; k++) {
+ nrgQ[0] += (uint32_t)(input[k] * input[k]);
+ }
+ nrgQ[1]=0;
+ for ( ; k < (FRAMESAMPLES/2 + QLOOKAHEAD) / 2; k++) {
+ nrgQ[1] += (uint32_t)(input[k] * input[k]);
+ }
+ nrgQ[2]=0;
+ for ( ; k < (FRAMESAMPLES * 3 / 4 + QLOOKAHEAD) / 2; k++) {
+ nrgQ[2] += (uint32_t)(input[k] * input[k]);
+ }
+ nrgQ[3]=0;
+ for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+ nrgQ[3] += (uint32_t)(input[k] * input[k]);
+ }
+
+ for ( k=0; k<4; k++) {
+ nrgQlog[k] = (int16_t)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */
+ }
+ oldNrgQlog = (int16_t)log2_Q8_LPC(*oldEnergy);
+
+ /* Calculate average level change */
+ chng1 = WEBRTC_SPL_ABS_W16(nrgQlog[3]-nrgQlog[2]);
+ chng2 = WEBRTC_SPL_ABS_W16(nrgQlog[2]-nrgQlog[1]);
+ chng3 = WEBRTC_SPL_ABS_W16(nrgQlog[1]-nrgQlog[0]);
+ chng4 = WEBRTC_SPL_ABS_W16(nrgQlog[0]-oldNrgQlog);
+ tmp = chng1+chng2+chng3+chng4;
+ chngQ = (int16_t)(tmp * kChngFactor >> 10); /* Q12 */
+ chngQ += 2926; /* + 1.0/1.4 in Q12 */
+
+ /* Find average pitch gain */
+ pgQ = 0;
+ for (k=0; k<4; k++)
+ {
+ pgQ += pitchGains_Q12[k];
+ }
+
+ pg3 = (int16_t)(pgQ * pgQ >> 11); // pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17
+ pg3 = (int16_t)(pgQ * pg3 >> 13); /* Q14*Q17>>13 =>Q18 */
+ /* kMulPitchGain = -25 = -200 in Q-3. */
+ pg3 = (int16_t)(pg3 * kMulPitchGain >> 5); // Q10
+ tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,pg3,13);/* Q13*Q10>>13 => Q10*/
+ if (tmp16<0) {
+ tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
+ tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3; /* Gives result in Q14 */
+ if (tmp16_1<0)
+ expPg = -(tmp16_2 << -tmp16_1);
+ else
+ expPg = -(tmp16_2 >> tmp16_1);
+ } else
+ expPg = (int16_t) -16384; /* 1 in Q14, since 2^0=1 */
+
+ expPg32 = (int32_t)expPg << 8; /* Q22 */
+ divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */
+
+ tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,divVal,13);/* Q13*Q10>>13 => Q10*/
+ if (tmp16<0) {
+ tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
+ tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3; /* Gives result in Q14 */
+ if (tmp16_1<0)
+ expPg = tmp16_2 << -tmp16_1;
+ else
+ expPg = tmp16_2 >> tmp16_1;
+ } else
+ expPg = (int16_t) 16384; /* 1 in Q14, since 2^0=1 */
+
+ *varscale = expPg-1;
+ *oldEnergy = nrgQ[3];
+}
+
+
+
+static __inline int16_t exp2_Q10_T(int16_t x) { // Both in and out in Q10
+
+ int16_t tmp16_1, tmp16_2;
+
+ tmp16_2=(int16_t)(0x0400|(x&0x03FF));
+ tmp16_1 = -(x >> 10);
+ if(tmp16_1>0)
+ return tmp16_2 >> tmp16_1;
+ else
+ return tmp16_2 << -tmp16_1;
+
+}
+
+
+// Declare function pointers.
+AutocorrFix WebRtcIsacfix_AutocorrFix;
+CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
+
+/* This routine calculates the residual energy for LPC.
+ * Formula as shown in comments inside.
+ */
+int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy) {
+ int i = 0, j = 0;
+ int shift_internal = 0, shift_norm = 0;
+ int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
+ int64_t sum64 = 0, sum64_tmp = 0;
+
+ for (i = 0; i <= lpc_order; i++) {
+ for (j = i; j <= lpc_order; j++) {
+ /* For the case of i == 0: residual_energy +=
+ * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
+ * For the case of i != 0: residual_energy +=
+ * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
+ */
+
+ tmp32 = a_polynomial[j] * a_polynomial[j - i];
+ /* tmp32 in Q(q_val_polynomial * 2). */
+ if (i != 0) {
+ tmp32 <<= 1;
+ }
+ sum64_tmp = (int64_t)tmp32 * (int64_t)corr_coeffs[i];
+ sum64_tmp >>= shift_internal;
+
+ /* Test overflow and sum the result. */
+ if(((sum64_tmp > 0 && sum64 > 0) && (LLONG_MAX - sum64 < sum64_tmp)) ||
+ ((sum64_tmp < 0 && sum64 < 0) && (LLONG_MIN - sum64 > sum64_tmp))) {
+ /* Shift right for overflow. */
+ shift_internal += 1;
+ sum64 >>= 1;
+ sum64 += sum64_tmp >> 1;
+ } else {
+ sum64 += sum64_tmp;
+ }
+ }
+ }
+
+ word32_high = (int32_t)(sum64 >> 32);
+ word32_low = (int32_t)sum64;
+
+ // Calculate the value of shifting (shift_norm) for the 64-bit sum.
+ if(word32_high != 0) {
+ shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
+ residual_energy = (int32_t)(sum64 >> shift_norm);
+ } else {
+ if((word32_low & 0x80000000) != 0) {
+ shift_norm = 1;
+ residual_energy = (uint32_t)word32_low >> 1;
+ } else {
+ shift_norm = WebRtcSpl_NormW32(word32_low);
+ residual_energy = word32_low << shift_norm;
+ shift_norm = -shift_norm;
+ }
+ }
+
+ /* Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm
+ * = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2)
+ */
+ *q_val_residual_energy = q_val_corr - shift_internal - shift_norm
+ + q_val_polynomial * 2;
+
+ return residual_energy;
+}
+
+void WebRtcIsacfix_GetLpcCoef(int16_t *inLoQ0,
+ int16_t *inHiQ0,
+ MaskFiltstr_enc *maskdata,
+ int16_t snrQ10,
+ const int16_t *pitchGains_Q12,
+ int32_t *gain_lo_hiQ17,
+ int16_t *lo_coeffQ15,
+ int16_t *hi_coeffQ15)
+{
+ int k, n, ii;
+ int pos1, pos2;
+ int sh_lo, sh_hi, sh, ssh, shMem;
+ int16_t varscaleQ14;
+
+ int16_t tmpQQlo, tmpQQhi;
+ int32_t tmp32;
+ int16_t tmp16,tmp16b;
+
+ int16_t polyHI[ORDERHI+1];
+ int16_t rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI];
+
+
+ int16_t DataLoQ6[WINLEN], DataHiQ6[WINLEN];
+ int32_t corrloQQ[ORDERLO+2];
+ int32_t corrhiQQ[ORDERHI+1];
+ int32_t corrlo2QQ[ORDERLO+1];
+ int16_t scale;
+ int16_t QdomLO, QdomHI, newQdomHI, newQdomLO;
+
+ int32_t res_nrgQQ;
+ int32_t sqrt_nrg;
+
+ /* less-noise-at-low-frequencies factor */
+ int16_t aaQ14;
+
+ /* Multiplication with 1/sqrt(12) ~= 0.28901734104046 can be done by convertion to
+ Q15, i.e. round(0.28901734104046*32768) = 9471, and use 9471/32768.0 ~= 0.289032
+ */
+ int16_t snrq;
+ int shft;
+
+ int16_t tmp16a;
+ int32_t tmp32a, tmp32b, tmp32c;
+
+ int16_t a_LOQ11[ORDERLO+1];
+ int16_t k_vecloQ15[ORDERLO];
+ int16_t a_HIQ12[ORDERHI+1];
+ int16_t k_vechiQ15[ORDERHI];
+
+ int16_t stab;
+
+ snrq=snrQ10;
+
+ /* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/
+ tmp16 = (int16_t)(snrq * 172 >> 10); // Q10
+ tmp16b = exp2_Q10_T(tmp16); // Q10
+ snrq = (int16_t)(tmp16b * 285 >> 10); // Q10
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsacfix_GetVars(inLoQ0, pitchGains_Q12, &(maskdata->OldEnergy), &varscaleQ14);
+
+ /* less-noise-at-low-frequencies factor */
+ /* Calculation of 0.35 * (0.5 + 0.5 * varscale) in fixpoint:
+ With 0.35 in Q16 (0.35 ~= 22938/65536.0 = 0.3500061) and varscaleQ14 in Q14,
+ we get Q16*Q14>>16 = Q14
+ */
+ aaQ14 = (int16_t)((22938 * (8192 + (varscaleQ14 >> 1)) + 32768) >> 16);
+
+ /* Calculate tmp = (1.0 + aa*aa); in Q12 */
+ tmp16 = (int16_t)(aaQ14 * aaQ14 >> 15); // Q14*Q14>>15 = Q13
+ tmpQQlo = 4096 + (tmp16 >> 1); // Q12 + Q13>>1 = Q12.
+
+ /* Calculate tmp = (1.0+aa) * (1.0+aa); */
+ tmp16 = 8192 + (aaQ14 >> 1); // 1+a in Q13.
+ tmpQQhi = (int16_t)(tmp16 * tmp16 >> 14); // Q13*Q13>>14 = Q12
+
+ /* replace data in buffer by new look-ahead data */
+ for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++) {
+ maskdata->DataBufferLoQ0[pos1 + WINLEN - QLOOKAHEAD] = inLoQ0[pos1];
+ }
+
+ for (k = 0; k < SUBFRAMES; k++) {
+
+ /* Update input buffer and multiply signal with window */
+ for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+ maskdata->DataBufferLoQ0[pos1] = maskdata->DataBufferLoQ0[pos1 + UPDATE/2];
+ maskdata->DataBufferHiQ0[pos1] = maskdata->DataBufferHiQ0[pos1 + UPDATE/2];
+ DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] *
+ kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6
+ DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] *
+ kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6
+ }
+ pos2 = (int16_t)(k * UPDATE / 2);
+ for (n = 0; n < UPDATE/2; n++, pos1++) {
+ maskdata->DataBufferLoQ0[pos1] = inLoQ0[QLOOKAHEAD + pos2];
+ maskdata->DataBufferHiQ0[pos1] = inHiQ0[pos2++];
+ DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] *
+ kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6
+ DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] *
+ kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6
+ }
+
+ /* Get correlation coefficients */
+ /* The highest absolute value measured inside DataLo in the test set
+ For DataHi, corresponding value was 160.
+
+ This means that it should be possible to represent the input values
+ to WebRtcSpl_AutoCorrelation() as Q6 values (since 307*2^6 =
+ 19648). Of course, Q0 will also work, but due to the low energy in
+ DataLo and DataHi, the outputted autocorrelation will be more accurate
+ and mimic the floating point code better, by being in an high as possible
+ Q-domain.
+ */
+
+ WebRtcIsacfix_AutocorrFix(corrloQQ,DataLoQ6,WINLEN, ORDERLO+1, &scale);
+ QdomLO = 12-scale; // QdomLO is the Q-domain of corrloQQ
+ sh_lo = WebRtcSpl_NormW32(corrloQQ[0]);
+ QdomLO += sh_lo;
+ for (ii=0; ii<ORDERLO+2; ii++) {
+ corrloQQ[ii] <<= sh_lo;
+ }
+ /* It is investigated whether it was possible to use 16 bits for the
+ 32-bit vector corrloQQ, but it didn't work. */
+
+ WebRtcIsacfix_AutocorrFix(corrhiQQ,DataHiQ6,WINLEN, ORDERHI, &scale);
+
+ QdomHI = 12-scale; // QdomHI is the Q-domain of corrhiQQ
+ sh_hi = WebRtcSpl_NormW32(corrhiQQ[0]);
+ QdomHI += sh_hi;
+ for (ii=0; ii<ORDERHI+1; ii++) {
+ corrhiQQ[ii] <<= sh_hi;
+ }
+
+ /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+
+ /* Calculate corrlo2[0] = tmpQQlo * corrlo[0] - 2.0*tmpQQlo * corrlo[1];*/
+ // `corrlo2QQ` in Q(QdomLO-5).
+ corrlo2QQ[0] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[0]) >> 1) -
+ (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, corrloQQ[1]) >> 2);
+
+ /* Calculate corrlo2[n] = tmpQQlo * corrlo[n] - tmpQQlo * (corrlo[n-1] + corrlo[n+1]);*/
+ for (n = 1; n <= ORDERLO; n++) {
+
+ tmp32 = (corrloQQ[n - 1] >> 1) + (corrloQQ[n + 1] >> 1); // Q(QdomLO-1).
+ corrlo2QQ[n] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[n]) >> 1) -
+ (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, tmp32) >> 2);
+ }
+ QdomLO -= 5;
+
+ /* Calculate corrhi[n] = tmpQQhi * corrhi[n]; */
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhiQQ[n] = WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQhi, corrhiQQ[n]); // Q(12+QdomHI-16) = Q(QdomHI-4)
+ }
+ QdomHI -= 4;
+
+ /* add white noise floor */
+ /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) */
+ /* Calculate corrlo2[0] += 9.5367431640625e-7; and
+ corrhi[0] += 9.5367431640625e-7, where the constant is 1/2^20 */
+
+ tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomLO-20);
+ corrlo2QQ[0] += tmp32;
+ tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomHI-20);
+ corrhiQQ[0] += tmp32;
+
+ /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) before the following
+ code segment, where we want to make sure we get a 1-bit margin */
+ for (n = 0; n <= ORDERLO; n++) {
+ corrlo2QQ[n] >>= 1; // Make sure we have a 1-bit margin.
+ }
+ QdomLO -= 1; // Now, corrlo2QQ is in Q(QdomLO), with a 1-bit margin
+
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhiQQ[n] >>= 1; // Make sure we have a 1-bit margin.
+ }
+ QdomHI -= 1; // Now, corrhiQQ is in Q(QdomHI), with a 1-bit margin
+
+
+ newQdomLO = QdomLO;
+
+ for (n = 0; n <= ORDERLO; n++) {
+ int32_t tmp, tmpB, tmpCorr;
+ int16_t alpha=328; //0.01 in Q15
+ int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
+ int16_t gamma=32440; //(1-0.01)=0.99 in Q15
+
+ if (maskdata->CorrBufLoQQ[n] != 0) {
+ shMem=WebRtcSpl_NormW32(maskdata->CorrBufLoQQ[n]);
+ sh = QdomLO - maskdata->CorrBufLoQdom[n];
+ if (sh<=shMem) {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], sh); // Get CorrBufLoQQ to same domain as corrlo2
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
+ } else if ((sh-shMem)<7){
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufLoQQ as much as possible
+ // Shift `alpha` the number of times required to get `tmp` in QdomLO.
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp);
+ } else {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+ // Shift `alpha` as much as possible without overflow the number of
+ // times required to get `tmp` in QdomLO.
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp);
+ tmpCorr = corrloQQ[n] >> (sh - shMem - 6);
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufLoQQ[n] = tmp;
+ newQdomLO = QdomLO-(sh-shMem-6);
+ maskdata->CorrBufLoQdom[n] = newQdomLO;
+ }
+ } else
+ tmp = 0;
+
+ tmp = tmp + corrlo2QQ[n];
+
+ maskdata->CorrBufLoQQ[n] = tmp;
+ maskdata->CorrBufLoQdom[n] = QdomLO;
+
+ tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
+ tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, corrlo2QQ[n]);
+ corrlo2QQ[n] = tmp + tmpB;
+ }
+ if( newQdomLO!=QdomLO) {
+ for (n = 0; n <= ORDERLO; n++) {
+ if (maskdata->CorrBufLoQdom[n] != newQdomLO)
+ corrloQQ[n] >>= maskdata->CorrBufLoQdom[n] - newQdomLO;
+ }
+ QdomLO = newQdomLO;
+ }
+
+
+ newQdomHI = QdomHI;
+
+ for (n = 0; n <= ORDERHI; n++) {
+ int32_t tmp, tmpB, tmpCorr;
+ int16_t alpha=328; //0.01 in Q15
+ int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
+ int16_t gamma=32440; //(1-0.01)=0.99 in Q1
+ if (maskdata->CorrBufHiQQ[n] != 0) {
+ shMem=WebRtcSpl_NormW32(maskdata->CorrBufHiQQ[n]);
+ sh = QdomHI - maskdata->CorrBufHiQdom[n];
+ if (sh<=shMem) {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], sh); // Get CorrBufHiQQ to same domain as corrhi
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
+ tmpCorr = corrhiQQ[n];
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ maskdata->CorrBufHiQdom[n] = QdomHI;
+ } else if ((sh-shMem)<7) {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+ // Shift `alpha` the number of times required to get `tmp` in QdomHI.
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp);
+ tmpCorr = corrhiQQ[n];
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ maskdata->CorrBufHiQdom[n] = QdomHI;
+ } else {
+ tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
+ // Shift `alpha` as much as possible without overflow the number of
+ // times required to get `tmp` in QdomHI.
+ tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp);
+ tmpCorr = corrhiQQ[n] >> (sh - shMem - 6);
+ tmp = tmp + tmpCorr;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ newQdomHI = QdomHI-(sh-shMem-6);
+ maskdata->CorrBufHiQdom[n] = newQdomHI;
+ }
+ } else {
+ tmp = corrhiQQ[n];
+ tmpCorr = tmp;
+ maskdata->CorrBufHiQQ[n] = tmp;
+ maskdata->CorrBufHiQdom[n] = QdomHI;
+ }
+
+ tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
+ tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, tmpCorr);
+ corrhiQQ[n] = tmp + tmpB;
+ }
+
+ if( newQdomHI!=QdomHI) {
+ for (n = 0; n <= ORDERHI; n++) {
+ if (maskdata->CorrBufHiQdom[n] != newQdomHI)
+ corrhiQQ[n] >>= maskdata->CorrBufHiQdom[n] - newQdomHI;
+ }
+ QdomHI = newQdomHI;
+ }
+
+ stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, ORDERLO);
+
+ if (stab<0) { // If unstable use lower order
+ a_LOQ11[0]=2048;
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LOQ11[n]=0;
+ }
+
+ stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, 8);
+ }
+
+
+ WebRtcSpl_LevinsonDurbin(corrhiQQ, a_HIQ12, k_vechiQ15, ORDERHI);
+
+ /* bandwidth expansion */
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LOQ11[n] = (int16_t)((kPolyVecLo[n - 1] * a_LOQ11[n] + (1 << 14)) >>
+ 15);
+ }
+
+
+ polyHI[0] = a_HIQ12[0];
+ for (n = 1; n <= ORDERHI; n++) {
+ a_HIQ12[n] = (int16_t)(((int32_t)(kPolyVecHi[n - 1] * a_HIQ12[n]) +
+ (1 << 14)) >> 15);
+ polyHI[n] = a_HIQ12[n];
+ }
+
+ /* Normalize the corrlo2 vector */
+ sh = WebRtcSpl_NormW32(corrlo2QQ[0]);
+ for (n = 0; n <= ORDERLO; n++) {
+ corrlo2QQ[n] <<= sh;
+ }
+ QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */
+
+
+ /* residual energy */
+
+ sh_lo = 31;
+ res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO,
+ kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo);
+
+ /* Convert to reflection coefficients */
+ WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo);
+
+ if (sh_lo & 0x0001) {
+ res_nrgQQ >>= 1;
+ sh_lo-=1;
+ }
+
+
+ if( res_nrgQQ > 0 )
+ {
+ sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
+
+ /* add hearing threshold and compute the gain */
+ /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
+
+ tmp32a = varscaleQ14 >> 1; // H_T_HQ19=65536 (16-17=-1)
+ ssh = sh_lo >> 1; // sqrt_nrg is in Qssh.
+ sh = ssh - 14;
+ tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
+ tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator)
+ tmp32a = varscaleQ14 * snrq; // Q24 (numerator)
+
+ sh = WebRtcSpl_NormW32(tmp32c);
+ shft = 16 - sh;
+ tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator)
+
+ tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
+ sh = ssh-shft-7;
+ *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17
+ }
+ else
+ {
+ *gain_lo_hiQ17 = 100; // Gains in Q17
+ }
+ gain_lo_hiQ17++;
+
+ /* copy coefficients to output array */
+ for (n = 0; n < ORDERLO; n++) {
+ *lo_coeffQ15 = (int16_t) (rcQ15_lo[n]);
+ lo_coeffQ15++;
+ }
+ /* residual energy */
+ sh_hi = 31;
+ res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI,
+ kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi);
+
+ /* Convert to reflection coefficients */
+ WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi);
+
+ if (sh_hi & 0x0001) {
+ res_nrgQQ >>= 1;
+ sh_hi-=1;
+ }
+
+
+ if( res_nrgQQ > 0 )
+ {
+ sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
+
+
+ /* add hearing threshold and compute the gain */
+ /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
+
+ tmp32a = varscaleQ14 >> 1; // H_T_HQ19=65536 (16-17=-1)
+
+ ssh = sh_hi >> 1; // `sqrt_nrg` is in Qssh.
+ sh = ssh - 14;
+ tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
+ tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator)
+ tmp32a = varscaleQ14 * snrq; // Q24 (numerator)
+
+ sh = WebRtcSpl_NormW32(tmp32c);
+ shft = 16 - sh;
+ tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator)
+
+ tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
+ sh = ssh-shft-7;
+ *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17
+ }
+ else
+ {
+ *gain_lo_hiQ17 = 100; // Gains in Q17
+ }
+ gain_lo_hiQ17++;
+
+
+ /* copy coefficients to output array */
+ for (n = 0; n < ORDERHI; n++) {
+ *hi_coeffQ15 = rcQ15_hi[n];
+ hi_coeffQ15++;
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h
new file mode 100644
index 0000000000..40a99e8a77
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_masking_model.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+void WebRtcIsacfix_GetVars(const int16_t* input,
+ const int16_t* pitchGains_Q12,
+ uint32_t* oldEnergy,
+ int16_t* varscale);
+
+void WebRtcIsacfix_GetLpcCoef(int16_t* inLoQ0,
+ int16_t* inHiQ0,
+ MaskFiltstr_enc* maskdata,
+ int16_t snrQ10,
+ const int16_t* pitchGains_Q12,
+ int32_t* gain_lo_hiQ17,
+ int16_t* lo_coeffQ15,
+ int16_t* hi_coeffQ15);
+
+typedef int32_t (*CalculateResidualEnergy)(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy);
+extern CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
+
+int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy);
+
+#if defined(MIPS_DSP_R2_LE)
+int32_t WebRtcIsacfix_CalculateResidualEnergyMIPS(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy);
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_MASKING_MODEL_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c
new file mode 100644
index 0000000000..727008da32
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_mips.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+
+// MIPS DSPR2 optimization for function WebRtcIsacfix_CalculateResidualEnergy
+// Bit-exact with WebRtcIsacfix_CalculateResidualEnergyC from file
+// lpc_masking_model.c
+int32_t WebRtcIsacfix_CalculateResidualEnergyMIPS(int lpc_order,
+ int32_t q_val_corr,
+ int q_val_polynomial,
+ int16_t* a_polynomial,
+ int32_t* corr_coeffs,
+ int* q_val_residual_energy) {
+
+ int i = 0, j = 0;
+ int shift_internal = 0, shift_norm = 0;
+ int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
+ int32_t tmp_corr_c = corr_coeffs[0];
+ int16_t* tmp_a_poly = &a_polynomial[0];
+ int32_t sum64_hi = 0;
+ int32_t sum64_lo = 0;
+
+ for (j = 0; j <= lpc_order; j++) {
+ // For the case of i == 0:
+ // residual_energy +=
+ // a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
+
+ int32_t tmp2, tmp3;
+ int16_t sign_1;
+ int16_t sign_2;
+ int16_t sign_3;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "lh %[tmp2], 0(%[tmp_a_poly]) \n\t"
+ "mul %[tmp32], %[tmp2], %[tmp2] \n\t"
+ "addiu %[tmp_a_poly], %[tmp_a_poly], 2 \n\t"
+ "sra %[sign_2], %[sum64_hi], 31 \n\t"
+ "mult $ac0, %[tmp32], %[tmp_corr_c] \n\t"
+ "shilov $ac0, %[shift_internal] \n\t"
+ "mfhi %[tmp2], $ac0 \n\t"
+ "mflo %[tmp3], $ac0 \n\t"
+ "sra %[sign_1], %[tmp2], 31 \n\t"
+ "xor %[sign_3], %[sign_1], %[sign_2] \n\t"
+ ".set pop \n\t"
+ : [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp32] "=&r" (tmp32),
+ [tmp_a_poly] "+r" (tmp_a_poly), [sign_1] "=&r" (sign_1),
+ [sign_3] "=&r" (sign_3), [sign_2] "=&r" (sign_2),
+ [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ : [tmp_corr_c] "r" (tmp_corr_c), [shift_internal] "r" (shift_internal)
+ : "hi", "lo", "memory"
+ );
+
+ if (sign_3 != 0) {
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
+ "addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
+ ".set pop \n\t"
+ : [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ : [tmp2] "r" (tmp2), [tmp3] "r" (tmp3)
+ : "hi", "lo", "memory"
+ );
+ } else {
+ if (((!(sign_1 || sign_2)) && (0x7FFFFFFF - sum64_hi < tmp2)) ||
+ ((sign_1 && sign_2) && (sum64_hi + tmp2 > 0))) {
+ // Shift right for overflow.
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[shift_internal], %[shift_internal], 1 \n\t"
+ "prepend %[sum64_lo], %[sum64_hi], 1 \n\t"
+ "sra %[sum64_hi], %[sum64_hi], 1 \n\t"
+ "prepend %[tmp3], %[tmp2], 1 \n\t"
+ "sra %[tmp2], %[tmp2], 1 \n\t"
+ "addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
+ "addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
+ ".set pop \n\t"
+ : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
+ [shift_internal] "+r" (shift_internal),
+ [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ :
+ : "hi", "lo", "memory"
+ );
+ } else {
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
+ "addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
+ ".set pop \n\t"
+ : [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ : [tmp2] "r" (tmp2), [tmp3] "r" (tmp3)
+ : "hi", "lo", "memory"
+ );
+ }
+ }
+ }
+
+ for (i = 1; i <= lpc_order; i++) {
+ tmp_corr_c = corr_coeffs[i];
+ int16_t* tmp_a_poly_j = &a_polynomial[i];
+ int16_t* tmp_a_poly_j_i = &a_polynomial[0];
+ for (j = i; j <= lpc_order; j++) {
+ // For the case of i = 1 .. lpc_order:
+ // residual_energy +=
+ // a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
+
+ int32_t tmp2, tmp3;
+ int16_t sign_1;
+ int16_t sign_2;
+ int16_t sign_3;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "lh %[tmp3], 0(%[tmp_a_poly_j]) \n\t"
+ "lh %[tmp2], 0(%[tmp_a_poly_j_i]) \n\t"
+ "addiu %[tmp_a_poly_j], %[tmp_a_poly_j], 2 \n\t"
+ "addiu %[tmp_a_poly_j_i], %[tmp_a_poly_j_i], 2 \n\t"
+ "mul %[tmp32], %[tmp3], %[tmp2] \n\t"
+ "sll %[tmp32], %[tmp32], 1 \n\t"
+ "mult $ac0, %[tmp32], %[tmp_corr_c] \n\t"
+ "shilov $ac0, %[shift_internal] \n\t"
+ "mfhi %[tmp2], $ac0 \n\t"
+ "mflo %[tmp3], $ac0 \n\t"
+ "sra %[sign_1], %[tmp2], 31 \n\t"
+ "sra %[sign_2], %[sum64_hi], 31 \n\t"
+ "xor %[sign_3], %[sign_1], %[sign_2] \n\t"
+ ".set pop \n\t"
+ : [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp32] "=&r" (tmp32),
+ [tmp_a_poly_j] "+r" (tmp_a_poly_j), [sign_1] "=&r" (sign_1),
+ [tmp_a_poly_j_i] "+r" (tmp_a_poly_j_i), [sign_2] "=&r" (sign_2),
+ [sign_3] "=&r" (sign_3), [sum64_hi] "+r" (sum64_hi),
+ [sum64_lo] "+r" (sum64_lo)
+ : [tmp_corr_c] "r" (tmp_corr_c), [shift_internal] "r" (shift_internal)
+ : "hi", "lo", "memory"
+ );
+ if (sign_3 != 0) {
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
+ "addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
+ ".set pop \n\t"
+ : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3), [sum64_hi] "+r" (sum64_hi),
+ [sum64_lo] "+r" (sum64_lo)
+ :
+ :"memory"
+ );
+ } else {
+ // Test overflow and sum the result.
+ if (((!(sign_1 || sign_2)) && (0x7FFFFFFF - sum64_hi < tmp2)) ||
+ ((sign_1 && sign_2) && (sum64_hi + tmp2 > 0))) {
+ // Shift right for overflow.
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[shift_internal], %[shift_internal], 1 \n\t"
+ "prepend %[sum64_lo], %[sum64_hi], 1 \n\t"
+ "sra %[sum64_hi], %[sum64_hi], 1 \n\t"
+ "prepend %[tmp3], %[tmp2], 1 \n\t"
+ "sra %[tmp2], %[tmp2], 1 \n\t"
+ "addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
+ "addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
+ ".set pop \n\t"
+ : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
+ [shift_internal] "+r" (shift_internal),
+ [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ :
+ : "hi", "lo", "memory"
+ );
+ } else {
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addsc %[sum64_lo], %[sum64_lo], %[tmp3] \n\t"
+ "addwc %[sum64_hi], %[sum64_hi], %[tmp2] \n\t"
+ ".set pop \n\t"
+ : [tmp2] "+r" (tmp2), [tmp3] "+r" (tmp3),
+ [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ :
+ : "hi", "lo", "memory"
+ );
+ }
+ }
+ }
+ }
+ word32_high = sum64_hi;
+ word32_low = sum64_lo;
+
+ // Calculate the value of shifting (shift_norm) for the 64-bit sum.
+ if (word32_high != 0) {
+ shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
+ int tmp1;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "srl %[residual_energy], %[sum64_lo], %[shift_norm] \n\t"
+ "li %[tmp1], 32 \n\t"
+ "subu %[tmp1], %[tmp1], %[shift_norm] \n\t"
+ "sll %[tmp1], %[sum64_hi], %[tmp1] \n\t"
+ "or %[residual_energy], %[residual_energy], %[tmp1] \n\t"
+ ".set pop \n\t"
+ : [residual_energy] "=&r" (residual_energy), [tmp1]"=&r"(tmp1),
+ [sum64_hi] "+r" (sum64_hi), [sum64_lo] "+r" (sum64_lo)
+ : [shift_norm] "r" (shift_norm)
+ : "memory"
+ );
+ } else {
+ if ((word32_low & 0x80000000) != 0) {
+ shift_norm = 1;
+ residual_energy = (uint32_t)word32_low >> 1;
+ } else {
+ shift_norm = WebRtcSpl_NormW32(word32_low);
+ residual_energy = word32_low << shift_norm;
+ shift_norm = -shift_norm;
+ }
+ }
+
+ // Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm
+ // = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2)
+ *q_val_residual_energy =
+ q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2;
+
+ return residual_energy;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
new file mode 100644
index 0000000000..82793f1344
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
+
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+class LpcMaskingModelTest : public ::testing::Test {
+ protected:
+ // Pass a function pointer to the Tester function.
+ void CalculateResidualEnergyTester(
+ CalculateResidualEnergy CalculateResidualEnergyFunction) {
+ const int kIntOrder = 10;
+ const int32_t kInt32QDomain = 5;
+ const int kIntShift = 11;
+ int16_t a[kIntOrder + 1] = {32760, 122, 7, 0, -32760, -3958,
+ -48, 18745, 498, 9, 23456};
+ int32_t corr[kIntOrder + 1] = {11443647, -27495, 0, 98745, -11443600, 1,
+ 1, 498, 9, 888, 23456};
+ int q_shift_residual = 0;
+ int32_t residual_energy = 0;
+
+ // Test the code path where (residual_energy >= 0x10000).
+ residual_energy = CalculateResidualEnergyFunction(
+ kIntOrder, kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+ EXPECT_EQ(1789023310, residual_energy);
+ EXPECT_EQ(2, q_shift_residual);
+
+ // Test the code path where (residual_energy < 0x10000)
+ // and ((energy & 0x8000) != 0).
+ for (int i = 0; i < kIntOrder + 1; i++) {
+ a[i] = 24575 >> i;
+ corr[i] = i;
+ }
+ residual_energy = CalculateResidualEnergyFunction(
+ kIntOrder, kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+ EXPECT_EQ(1595279092, residual_energy);
+ EXPECT_EQ(26, q_shift_residual);
+
+ // Test the code path where (residual_energy <= 0x7fff).
+ for (int i = 0; i < kIntOrder + 1; i++) {
+ a[i] = 2457 >> i;
+ }
+ residual_energy = CalculateResidualEnergyFunction(
+ kIntOrder, kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
+ EXPECT_EQ(2029266944, residual_energy);
+ EXPECT_EQ(33, q_shift_residual);
+ }
+};
+
+TEST_F(LpcMaskingModelTest, CalculateResidualEnergyTest) {
+ CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyC);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c
new file mode 100644
index 0000000000..d495d29235
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.c
@@ -0,0 +1,1281 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.c
+ *
+ * Coding tables for the KLT coefficients
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/lpc_tables.h"
+
+/* indices of KLT coefficients used */
+const uint16_t WebRtcIsacfix_kSelIndGain[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11};
+
+const uint16_t WebRtcIsacfix_kSelIndShape[108] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107
+};
+
+/* cdf array for model indicator */
+const uint16_t WebRtcIsacfix_kModelCdf[4] = {
+ 0, 15434, 37548, 65535
+};
+
+/* pointer to cdf array for model indicator */
+const uint16_t *WebRtcIsacfix_kModelCdfPtr[1] = {
+ WebRtcIsacfix_kModelCdf
+};
+
+/* initial cdf index for decoder of model indicator */
+const uint16_t WebRtcIsacfix_kModelInitIndex[1] = {
+ 1
+};
+
+/* offset to go from rounded value to quantization index */
+const int16_t WebRtcIsacfix_kQuantMinGain[12] ={
+ 3, 6, 4, 6, 6, 9, 5, 16, 11, 34, 32, 47
+};
+
+const int16_t WebRtcIsacfix_kQuantMinShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 2, 2, 3, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 4, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 3, 4,
+ 4, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 2, 3, 2, 3, 4, 4, 5, 7, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 6, 7, 11, 9, 13, 12, 26
+};
+
+/* maximum quantization index */
+const uint16_t WebRtcIsacfix_kMaxIndGain[12] = {
+ 6, 12, 8, 14, 10, 19, 12, 31, 22, 56, 52, 138
+};
+
+const uint16_t WebRtcIsacfix_kMaxIndShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 2, 2, 2, 2, 4, 4, 5, 6, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 2, 2,
+ 2, 2, 3, 4, 5, 7, 0, 0, 0, 0,
+ 2, 0, 2, 2, 2, 2, 3, 2, 2, 4,
+ 4, 6, 6, 9, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 3, 2, 4, 4, 7, 7,
+ 9, 13, 0, 0, 2, 2, 2, 2, 2, 2,
+ 3, 4, 5, 4, 6, 8, 8, 10, 16, 25,
+ 0, 2, 2, 4, 5, 4, 4, 4, 7, 8,
+ 9, 10, 13, 19, 17, 23, 25, 49
+};
+
+/* index offset */
+const uint16_t WebRtcIsacfix_kOffsetGain[3][12] = {
+ { 0, 7, 20, 29, 44, 55, 75, 88, 120, 143, 200, 253},
+ { 0, 7, 19, 27, 42, 53, 73, 86, 117, 140, 197, 249},
+ { 0, 7, 20, 28, 44, 55, 75, 89, 121, 145, 202, 257}
+};
+
+const uint16_t WebRtcIsacfix_kOffsetShape[3][108] = {
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 11, 14, 17, 20, 23, 28, 33, 39, 46, 47,
+ 48, 49, 50, 52, 53, 54, 55, 56, 58, 61,
+ 64, 67, 70, 74, 79, 85, 93, 94, 95, 96,
+ 97, 100, 101, 104, 107, 110, 113, 117, 120, 123,
+ 128, 133, 140, 147, 157, 158, 159, 160, 161, 164,
+ 167, 170, 173, 176, 179, 183, 186, 191, 196, 204,
+ 212, 222, 236, 237, 238, 241, 244, 247, 250, 253,
+ 256, 260, 265, 271, 276, 283, 292, 301, 312, 329,
+ 355, 356, 359, 362, 367, 373, 378, 383, 388, 396,
+ 405, 415, 426, 440, 460, 478, 502, 528
+ },
+ {
+ 0, 1, 2, 3, 4, 6, 7, 8, 9, 11,
+ 13, 16, 19, 22, 26, 29, 34, 39, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 55, 57, 60,
+ 63, 66, 70, 73, 78, 84, 91, 92, 93, 94,
+ 95, 96, 97, 99, 102, 105, 108, 111, 114, 118,
+ 123, 128, 134, 141, 151, 152, 153, 154, 156, 159,
+ 162, 165, 168, 171, 174, 177, 181, 186, 194, 200,
+ 208, 218, 233, 234, 235, 236, 239, 242, 245, 248,
+ 251, 254, 258, 263, 270, 277, 288, 297, 308, 324,
+ 349, 351, 354, 357, 361, 366, 372, 378, 383, 390,
+ 398, 407, 420, 431, 450, 472, 496, 524
+ },
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 11,
+ 14, 17, 20, 23, 26, 29, 34, 40, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 58, 61, 64,
+ 67, 70, 73, 77, 82, 88, 96, 97, 98, 99,
+ 101, 102, 104, 107, 110, 113, 116, 119, 122, 125,
+ 129, 134, 141, 150, 160, 161, 162, 163, 166, 168,
+ 171, 174, 177, 180, 183, 186, 190, 195, 201, 208,
+ 216, 226, 243, 244, 245, 248, 251, 254, 257, 260,
+ 263, 268, 273, 278, 284, 291, 299, 310, 323, 340,
+ 366, 368, 371, 374, 379, 383, 389, 394, 399, 406,
+ 414, 422, 433, 445, 461, 480, 505, 533
+ }
+};
+
+/* initial cdf index for KLT coefficients */
+const uint16_t WebRtcIsacfix_kInitIndexGain[3][12] = {
+ { 3, 6, 4, 7, 5, 10, 6, 16, 11, 28, 26, 69},
+ { 3, 6, 4, 7, 5, 10, 6, 15, 11, 28, 26, 69},
+ { 3, 6, 4, 8, 5, 10, 7, 16, 12, 28, 27, 70}
+};
+
+const uint16_t WebRtcIsacfix_kInitIndexShape[3][108] = {
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 3, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 2, 1, 1, 2,
+ 2, 3, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 4, 4,
+ 5, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 3, 2, 3, 4, 4, 5, 8, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 5, 7, 10, 9, 12, 13, 25
+ },
+ {
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 1, 1, 1, 2, 1, 2, 2, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 2, 1, 2, 3, 3, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 3, 3, 5, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 4, 3, 4,
+ 5, 7, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 2, 2, 3, 3, 5, 4, 5, 8, 12,
+ 1, 1, 1, 2, 2, 3, 3, 2, 3, 4,
+ 4, 6, 5, 9, 11, 12, 14, 25
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 2, 3, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 3, 4, 5, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 3, 3, 4,
+ 5, 8, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 3, 3, 4, 5, 6, 8, 13,
+ 1, 1, 1, 2, 2, 3, 2, 2, 3, 4,
+ 4, 5, 6, 8, 9, 12, 14, 25
+ }
+};
+
+/* offsets for quantizer representation levels*/
+const uint16_t WebRtcIsacfix_kOfLevelsGain[3] = {
+ 0, 392, 779
+};
+
+const uint16_t WebRtcIsacfix_kOfLevelsShape[3] = {
+ 0, 578, 1152
+};
+
+/* quantizer representation levels */
+
+
+
+const int32_t WebRtcIsacfix_kLevelsGainQ17[1176] = {
+ -364547,-231664,-102123,-573,104807,238257,368823,-758583,-640135,-510291
+ ,-377662,-252785,-113177,2627,112906,248601,389461,522691,644517,763974
+ ,-538963,-368179,-245823,-106095,-890,104299,241111,350730,493190,-800763
+ ,-646230,-510239,-382115,-248623,-111829,-2983,113852,251105,388114,519757
+ ,644048,774712,896334,1057931,-770009,-635310,-503690,-375087,-248106,-108525
+ ,-105,108259,243472,377948,519271,-1160885,-1032044,-914636,-777593,-647891
+ ,-518408,-388028,-254321,-115293,-598,117849,251296,385367,515510,652727
+ ,777432,920363,1038625,1153637,1316836,-632287,-505430,-379430,-248458,-118013
+ ,-888,118762,250266,381650,513327,652169,766471,932113,-2107480,-1971030
+ ,-1827020,-1698263,-1558670,-1436314,-1305377,-1172252,-1047355,-914202,-779651,-651001
+ ,-520999,-390394,-255761,-123490,-1893,126839,256703,385493,518607,651760
+ ,782750,908693,1044131,1163865,1311066,1424177,1582628,1709823,1831740,1955391
+ ,-1423044,-1288917,-1181281,-1043222,-911770,-780354,-646799,-522664,-386721,-258266
+ ,-128060,-1101,128233,259996,390336,519590,649290,778701,908010,1040796
+ ,1161235,1306889,1441882,-4446002,-4301031,-4194304,-4080591,-3947740,-3808975,-3686530
+ ,-3567839,-3383251,-3287089,-3136577,-3017405,-2869860,-2751321,-2619984,-2482932,-2354790
+ ,-2223147,-2090669,-1964135,-1831208,-1706697,-1570817,-1446008,-1305386,-1175773,-1046066
+ ,-915356,-785120,-653614,-524331,-393767,-260442,-130187,-799,128841,261466
+ ,393616,520542,652117,784613,914159,1045399,1181072,1308971,1442502,1570346
+ ,1693912,1843986,1966014,2090474,2224869,2364593,2475934,2628403,2752512,2856640
+ ,-4192441,-4063232,-3917821,-3799195,-3666233,-3519199,-3411021,-3269192,-3135684,-3008826
+ ,-2880875,-2747342,-2620981,-2494872,-2354979,-2229718,-2098939,-1964971,-1835399,-1703452
+ ,-1572806,-1440482,-1311794,-1179338,-1046521,-919823,-785914,-655335,-523416,-395507
+ ,-264833,-132184,-2546,131698,256217,391372,522688,651248,789964,909618
+ ,1035305,1179145,1313824,1436934,1552353,1693722,1815508,1972826,2096328,2228224
+ ,2359296,2490368,2598848,-6160384,-6029312,-5881382,-5767168,-5636096,-5505024,-5373952
+ ,-5228418,-5110384,-4954923,-4880576,-4710990,-4587364,-4471340,-4333905,-4211513,-4051293
+ ,-3907927,-3800105,-3675961,-3538640,-3413663,-3271148,-3152105,-3019103,-2869647,-2744015
+ ,-2620639,-2479385,-2364211,-2227611,-2095427,-1974497,-1834168,-1703561,-1568961,-1439826
+ ,-1309192,-1174050,-1050191,-917836,-786015,-656943,-518934,-394831,-257708,-128041
+ ,1610,128991,264442,393977,521383,653849,788164,918641,1049122,1181971
+ ,1308934,1439505,1571808,1706305,1836318,1966235,2097269,2228990,2357005,2490292
+ ,2617400,2749680,2881234,3014880,3145637,3276467,3409099,3536637,3671493,3802918
+ ,3929740,4065036,4194143,4325999,4456126,4586857,4717194,4843923,4978676,5110913
+ ,5245281,5371394,5499780,5633779,5762611,5897682,6028688,6167546,6296465,6421682
+ ,6548882,6682074,6809432,6941956,7078143,7204509,7334296,7475137,7609896,7732044
+ ,7861604,8002039,8131670,8259222,8390299,8522399,8650037,8782348,8908402,9037815
+ ,9164594,9300338,9434679,9574500,9699702,9833934,9948152,10083972,10244937,10332822
+ ,10485760,10600122,10760754,10892964,11010048,11111004,11272192,11403264,11525091,11624984
+ ,11796480,11915146,-393216,-262144,-101702,-740,100568,262144,393216,-786432
+ ,-655360,-524288,-383907,-243301,-94956,-156,95547,269629,416691,524288
+ ,655360,-393216,-262144,-88448,-37,87318,262144,393216,524288,-917504
+ ,-786432,-655360,-495894,-373308,-267503,-93211,4119,91308,250895,393216
+ ,526138,655360,786432,917504,-786432,-655360,-524288,-393216,-262144,-83497
+ ,222,86893,240922,393216,524288,-1048576,-917504,-790472,-655360,-508639
+ ,-383609,-262016,-95550,-3775,96692,256797,364847,534906,655360,786432
+ ,889679,1048576,1179648,1310720,1441792,-655360,-524288,-377684,-248408,-93690
+ ,1261,95441,227519,393216,524288,655360,786432,917504,-2097152,-1966080
+ ,-1809470,-1703936,-1572864,-1441792,-1314289,-1195149,-1056205,-917504,-809951,-657769
+ ,-521072,-383788,-248747,-106350,-2944,105550,243408,388548,521064,628732
+ ,786432,885456,1064548,1179648,1310720,1441792,1572864,1703936,1835008,-1441792
+ ,-1310720,-1179648,-1037570,-888492,-767774,-646634,-519935,-373458,-248029,-111915
+ ,760,111232,247735,379432,507672,672699,786432,917504,1048576,1179648
+ ,1310720,1441792,-4456448,-4325376,-4194304,-4063232,-3932160,-3801088,-3670016,-3538944
+ ,-3407872,-3276800,-3145728,-3014656,-2883584,-2752512,-2647002,-2490368,-2359296,-2228224
+ ,-2097152,-1951753,-1835008,-1703936,-1594177,-1462001,-1289150,-1160774,-1025917,-924928
+ ,-782509,-641294,-516191,-386630,-251910,-118886,5210,121226,253949,386008
+ ,517973,649374,780064,917783,1052462,1183856,1290593,1419389,1556641,1699884
+ ,1835008,1988314,2090470,2228224,2359296,2490368,2621440,2752512,2883584,-3801088
+ ,-3643514,-3539937,-3409931,-3263294,-3145658,-3012952,-2879230,-2752359,-2622556,-2483471
+ ,-2357556,-2226500,-2093112,-1965892,-1833664,-1701035,-1567767,-1440320,-1310556,-1178339
+ ,-1049625,-916812,-786477,-655277,-525050,-393773,-264828,-130696,-480,132126
+ ,260116,394197,527846,652294,785563,917183,1049511,1175958,1308161,1438759
+ ,1572253,1698835,1828535,1967072,2089391,2212798,2348901,2461547,2621440,2752512
+ ,2883584,-7309870,-7203780,-7062699,-6939106,-6790819,-6672036,-6553600,-6422317,-6288422
+ ,-6164694,-6026456,-5901410,-5754168,-5621459,-5502710,-5369686,-5240454,-5120712,-4976140
+ ,-4847970,-4723070,-4589083,-4450923,-4324680,-4189892,-4065551,-3931803,-3800209,-3668539
+ ,-3539395,-3404801,-3277470,-3141389,-3016710,-2885724,-2752612,-2618541,-2486762,-2354153
+ ,-2225059,-2094984,-1968194,-1830895,-1699508,-1575743,-1444516,-1308683,-1179714,-1053088
+ ,-917981,-783707,-653900,-524980,-395409,-260309,-131948,-3452,132113,263241
+ ,392185,522597,654134,788288,919810,1045795,1179210,1314201,1444235,1574447
+ ,1705193,1834009,1967332,2098102,2229019,2359147,2489859,2619878,2754966,2879671
+ ,3014438,3146143,3276733,3405958,3542196,3667493,3798815,3932961,4062458,4187125
+ ,4322346,4454875,4587752,4716809,4848274,4975027,5111957,5242215,5373085,5501158
+ ,5640140,5762918,5895358,6024008,6157906,6290628,6422713,6546339,6675888,6815606
+ ,6955288,7077501,7211630,7337893,7473635,7607175,7728310,7866475,7999658,8127888
+ ,8241758,8386483,8522550,8641582,8771915,8922139,9038632,9179385,9313426,9437184
+ ,9568256,9699328,9830400,9952933,10120004,10223616,10354688,10474645,10616832,-393216
+ ,-262144,-85425,-121,82533,262144,393216,-786432,-655360,-524288,-379928
+ ,-222821,-95200,287,95541,227093,393216,493567,655360,786432,-393216
+ ,-262144,-86805,510,86722,262144,393216,524288,-1048576,-917504,-786432
+ ,-624456,-529951,-395071,-241627,-101168,81,99975,241605,393216,524288
+ ,655360,786432,917504,-786432,-655360,-524288,-393216,-230359,-95619,-137
+ ,94425,226222,393216,524288,-1179648,-1048576,-917504,-773841,-655360,-492258
+ ,-379715,-244707,-103621,-434,104523,242680,381575,523659,650565,786432
+ ,917504,1048576,1179648,1310720,-786432,-629344,-524288,-376757,-242858,-101932
+ ,-2715,107155,239212,366480,514943,655360,786432,917504,-2228224,-2097152
+ ,-1966080,-1835008,-1703936,-1572864,-1441792,-1284584,-1179648,-1048819,-934658,-777181
+ ,-626371,-515660,-377493,-248975,-113036,436,113584,248354,379718,512475
+ ,653932,796494,917504,1048576,1179648,1310720,1441792,1572864,1703936,1835008
+ ,-1572864,-1441792,-1297608,-1161159,-1032316,-917092,-779770,-647384,-515529,-384269
+ ,-250003,-119252,1053,118111,249512,380545,512039,648101,770656,907003
+ ,1021725,1178082,1310720,1441792,-4587520,-4456448,-4325376,-4194304,-4063232,-3932160
+ ,-3801088,-3670016,-3538944,-3407872,-3276800,-3145728,-2999335,-2883584,-2752512,-2621440
+ ,-2490368,-2359296,-2228224,-2112691,-1966080,-1848781,-1709830,-1566109,-1438427,-1303530
+ ,-1176124,-1040936,-913876,-784585,-652025,-518361,-385267,-256342,-127297,-2733
+ ,125422,257792,389363,519911,651106,783805,909407,1044143,1174156,1309267
+ ,1436173,1553771,1708958,1814083,1967036,2095386,2255169,2359296,2478303,2621440
+ ,2752512,-4456448,-4325376,-4194304,-4063232,-3932160,-3797524,-3670016,-3560250,-3413217
+ ,-3257719,-3166416,-2986626,-2878000,-2781144,-2625383,-2495465,-2346792,-2230930,-2077063
+ ,-1949225,-1819274,-1697261,-1568664,-1443074,-1304302,-1175289,-1043794,-913423,-785561
+ ,-652104,-522835,-392667,-260517,-130088,-2,129509,260990,391931,522470
+ ,655770,784902,917093,1046445,1176951,1303121,1441362,1565401,1702022,1822856
+ ,1952852,2090384,2214607,2338436,2457483,2621440,-8781824,-8650752,-8519680,-8388608
+ ,-8260828,-8126464,-8003337,-7859030,-7750057,-7602176,-7471104,-7340032,-7193045,-7090588
+ ,-6946816,-6843344,-6676635,-6557575,-6447804,-6277614,-6159736,-6035729,-5884723,-5739567
+ ,-5634818,-5489867,-5372864,-5243300,-5098939,-4988639,-4856258,-4728494,-4591717,-4447428
+ ,-4322409,-4192918,-4062638,-3934141,-3797545,-3673373,-3531587,-3407391,-3277404,-3147797
+ ,-3013578,-2886548,-2749811,-2616428,-2490949,-2361301,-2228482,-2096883,-1964343,-1831754
+ ,-1702201,-1572495,-1442012,-1309242,-1182451,-1048996,-916905,-786510,-657079,-524730
+ ,-393672,-261313,-128743,166,130678,261334,393287,524155,655570,786839
+ ,917353,1052167,1179013,1309360,1442634,1571153,1703961,1832027,1965014,2097912
+ ,2224861,2355341,2490455,2623051,2753484,2877015,3015783,3144157,3273705,3405255
+ ,3542006,3669580,3802417,3935413,4065088,4190896,4333521,4456355,4579781,4713832
+ ,4845707,4978625,5113278,5243817,5382318,5500592,5638135,5761179,5900822,6029270
+ ,6186398,6297816,6436435,6559163,6666389,6806548,6950461,7086078,7195777,7350973
+ ,7480132,7614852,7743514,7847288,8014762,8126464,8257536,8388608,8519680,8650752
+ ,8781824,8912896,9043968,9175040,9306112,9437184
+};
+
+
+
+const int16_t WebRtcIsacfix_kLevelsShapeQ10[1735] = {
+ 0, 0, -1, 0, 0, 1, 0, 1, 0, -821
+ , 1, -763, -1, 656, -620, 0, 633, -636, 4, 615
+ , -630, 1, 649, -1773, -670, 5, 678, 1810, -1876, -676
+ , 0, 691, 1843, -1806, -743, -1, 749, 1795, 2920, -2872
+ , -1761, -772, -3, 790, 1763, 2942, 0, 0, 0, 0
+ , -792, 2, 0, 0, 1, 0, -854, 0, -702, -1
+ , 662, -624, -5, 638, -611, -6, 638, -647, 0, 651
+ , -685, -4, 679, 2123, -1814, -693, 0, 664, 1791, -1735
+ , -737, 0, 771, 1854, 2873, -2867, -1842, -793, -1, 821
+ , 1826, 2805, 3922, 0, 0, 0, -1, -779, 1, 786
+ , 1, -708, 0, 789, -799, 1, 797, -663, 2, 646
+ , -600, 3, 609, -600, 1, 658, 1807, -627, -3, 612
+ , -625, 3, 632, -1732, -674, 1, 672, 2048, -1768, -715
+ , 0, 724, 1784, -3881, -3072, -1774, -719, -1, 730, 1811
+ , -2963, -1829, -806, -1, 816, 1795, 3050, -5389, -3784, -2942
+ , -1893, -865, -12, 867, 1885, 2945, 3928, -2, 1, 4
+ , 0, -694, 2, 665, -598, 5, 587, -599, -1, 661
+ , -656, -7, 611, -607, 5, 603, -618, -4, 620, -1794
+ , -645, -2, 654, -655, -1, 658, -1801, -700, 5, 707
+ , 1927, -1752, -745, -8, 752, 1843, -2838, -1781, -801, 11
+ , 796, 1811, 2942, 3866, -3849, -3026, -1848, -819, 2, 827
+ , 1825, 2963, -3873, -2904, -1869, -910, -6, 903, 1902, 2885
+ , 3978, 5286, -7168, -6081, -4989, -3968, -2963, -1970, -943, -2
+ , 953, 1951, 2968, 3974, 5009, 6032, -2, 3, -1024, 2
+ , 1024, -637, 1, 669, -613, -7, 630, -603, 4, 612
+ , -612, 0, 590, -645, -11, 627, -657, -2, 671, 1849
+ , -1853, -694, 2, 702, 1838, -3304, -1780, -736, -8, 732
+ , 1772, -1709, -755, -6, 760, 1780, -2994, -1780, -800, 8
+ , 819, 1830, 2816, -4096, -2822, -1881, -851, -4, 855, 1872
+ , 2840, 3899, -3908, -2904, -1878, -887, 6, 897, 1872, 2942
+ , 4008, -4992, -3881, -2933, -1915, -928, 1, 937, 1919, 2900
+ , 4009, 4881, -6848, -6157, -5065, -3981, -2983, -1972, -978, -1
+ , 968, 1979, 2988, 4008, 5007, 6108, 7003, 8051, 9027,-13272
+ ,-12012,-11228,-10213, -9261, -8084, -7133, -6075, -5052, -4050, -3036
+ , -2014, -996, -4, 1007, 2031, 3038, 4049, 5074, 6134, 7069
+ , 8094, 9069, 10212, 11049, 12104, 51, -1024, -13, 1024, -609
+ , -107, 613, -2048, -687, -95, 667, 2048, -3072, -1724, -785
+ , -34, 732, 1819, -2048, -703, -26, 681, 2048, -2048, -686
+ , -9, 665, 2048, -2048, -702, 37, 748, 1723, -4096, -2786
+ , -1844, -837, 37, 811, 1742, 3072, -4096, -2783, -1848, -881
+ , 39, 898, 1843, 2792, 3764, -5120, -4096, -2923, -1833, -852
+ , -14, 862, 1824, 2834, 4096, -6144, -5120, -3914, -2842, -1870
+ , -886, -27, 888, 1929, 2931, 4051, -7168, -6144, -5120, -3866
+ , -2933, -1915, -927, 64, 933, 1902, 2929, 3912, 5063, 6144
+ ,-11264,-10240, -9216, -8192, -7086, -6144, -5039, -3972, -2943, -1929
+ , -941, 3, 938, 1942, 2959, 3933, 4905, 6088, 6983, 8192
+ , -9216, -8192, -7202, -6088, -4983, -4019, -2955, -1975, -966, 17
+ , 997, 1981, 2967, 3990, 4948, 6022, 6967, 8192,-13312,-12288
+ ,-11264,-10240, -9216, -8049, -6997, -6040, -5026, -4043, -3029, -2034
+ , -1015, -23, 984, 1997, 3010, 4038, 5002, 6015, 6946, 8061
+ , 9216, 10240,-12381,-11264,-10240, -9060, -8058, -7153, -6085, -5075
+ , -4051, -3042, -2037, -1017, -5, 1007, 2028, 3035, 4050, 5088
+ , 6111, 7160, 8156, 9215, 10095, 11229, 12202, 13016,-26624,-25600
+ ,-24582,-23671,-22674,-21400,-20355,-19508,-18315,-17269,-16361,-15299
+ ,-14363,-13294,-12262,-11237,-10203, -9227, -8165, -7156, -6116, -5122
+ , -4076, -3056, -2043, -1020, -8, 1027, 2047, 3065, 4110, 5130
+ , 6125, 7168, 8195, 9206, 10230, 11227, 12256, 13304, 14281, 15316
+ , 16374, 17382, 18428, 19388, 20361, 21468, 22448, 23781, 0, 0
+ , -1, 0, -2, 1024, 0, 0, 0, -1, 1024, -1024
+ , 1, -1024, 4, 1024, -1024, 2, 1024, -1024, 2, 1024
+ , -2048, -1024, -4, 1024, -1024, 2, 1024, -2048, -1024, -3
+ , 1024, 2048, -2048, -1024, 4, 1024, 2048, -3072, -2048, -1024
+ , -1, 662, 2048, 0, 1, 0, 0, 1, -2, -2
+ , 0, 2, 1024, -1, 1024, -1024, 4, 1024, -1024, 1
+ , 1024, -1024, 1, 1024, -2048, -781, -4, 844, -807, -5
+ , 866, -2048, -726, -13, 777, 2048, -2048, -643, -4, 617
+ , 2048, 3072, -3072, -2048, -629, 1, 630, 2048, 3072, 0
+ , -1, 1, -2, 2, 1, -1024, 5, -1024, 6, 1024
+ , -1024, 4, 1024, -1024, 1, 1024, -1024, -9, 1024, -673
+ , -7, 655, -2048, -665, -15, 716, -2048, -647, 4, 640
+ , 2048, -2048, -615, -1, 635, 2048, -2048, -613, 10, 637
+ , 2048, 3072, -3072, -2048, -647, -3, 641, 2048, 3072, -5120
+ , -4096, -3072, -2048, -681, 6, 685, 2048, 3072, 4096, 1
+ , 1, 0, -1, 1024, -1024, -3, 1024, -1024, 6, 1024
+ , -1024, -1, 769, -733, 0, 1024, -876, -2, 653, -1024
+ , -4, 786, -596, -13, 595, -634, -2, 638, 2048, -2048
+ , -620, -5, 620, 2048, -4096, -3072, -2048, -639, 11, 655
+ , 2048, 3072, -3072, -2048, -659, 5, 663, 2048, -3072, -1823
+ , -687, 22, 695, 2048, 3072, 4096, -4096, -3072, -1848, -715
+ , -3, 727, 1816, 3072, 4096, 5120, -8192, -7168, -6144, -5120
+ , -4096, -2884, -1771, -756, -14, 775, 1844, 3072, 4096, 5120
+ , 6144, -1, 1, 0, -1024, 2, 815, -768, 2, 708
+ , -1024, -3, 693, -661, -7, 607, -643, -5, 609, -624
+ , 3, 631, -682, -3, 691, 2048, -2048, -640, 5, 650
+ , 2048, -3072, -2048, -701, 9, 704, 2048, 3072, -3072, -2048
+ , -670, 10, 674, 2048, 3072, -5120, -4096, -3072, -1749, -738
+ , 0, 733, 1811, 3072, 4096, 5120, -4096, -3072, -1873, -753
+ , 0, 756, 1874, 3072, 4096, -5120, -4096, -2900, -1838, -793
+ , -6, 793, 1868, 2837, 4096, 5120, -7168, -6144, -5120, -4096
+ , -2832, -1891, -828, 1, 828, 1901, 2823, 3912, 5120, 6144
+ , 7168, 8192,-13312,-12288,-11264,-10240, -9216, -8192, -7168, -6144
+ , -5120, -3976, -3004, -1911, -869, 7, 869, 1932, 3024, 3992
+ , 5009, 6144, 7168, 8192, 9216, 10240, 11264, -4, 1024, -629
+ , -22, 609, -623, 9, 640, -2048, -768, 1, 682, -2048
+ , -741, 49, 722, 2048, -3072, -1706, -808, -20, 768, 1750
+ , -1684, -727, -29, 788, 1840, 3033, -1758, -784, 0, 801
+ , 1702, -3072, -1813, -814, 38, 820, 1884, 2927, -4096, -3241
+ , -1839, -922, 25, 882, 1886, 2812, -4096, -2982, -1923, -894
+ , 84, 912, 1869, 2778, 4096, -4928, -3965, -2902, -1920, -883
+ , 3, 917, 1953, 2921, 3957, 4922, 6144, 7168, -5120, -3916
+ , -2897, -1949, -930, 31, 959, 1934, 2901, 3851, 5120, -9216
+ , -8192, -7046, -6029, -5030, -4034, -2980, -1969, -1013, -76, 963
+ , 1963, 2901, 3929, 4893, 6270, 7168, 8192, 9216,-12288,-11264
+ ,-10240, -9216, -8192, -6846, -6123, -5108, -4008, -3000, -1963, -954
+ , -6, 958, 1992, 3009, 4020, 5085, 6097, 7168, 8192, 9216
+ ,-11264,-10139, -9194, -8127, -7156, -6102, -5053, -4049, -3036, -2025
+ , -1009, -34, 974, 1984, 3034, 4028, 5138, 6000, 7057, 8166
+ , 9070, 10033, 11360, 12288,-13312,-12288,-10932,-10190, -9120, -8123
+ , -7128, -6103, -5074, -4081, -3053, -2029, -989, -4, 1010, 2028
+ , 3051, 4073, 5071, 6099, 7132, 8147, 9295, 10159, 11023, 12263
+ , 13312, 14336,-25600,-24576,-23552,-22529,-21504,-20480,-19456,-18637
+ ,-17425,-16165,-15316,-14327,-13606,-12135,-11182,-10107, -9153, -8144
+ , -7146, -6160, -5129, -4095, -3064, -2038, -1025, 1, 1031, 2072
+ , 3074, 4088, 5123, 6149, 7157, 8173, 9198, 10244, 11250, 12268
+ , 13263, 14289, 15351, 16370, 17402, 18413, 19474, 20337, 21386, 22521
+ , 23367, 24350, 0, 0, 0, 0, 0, 0, 0, 0
+ , -1024, 0, 1024, -1024, 0, 1024, -1024, 0, 1024, -1024
+ , 0, 1024, -1024, 0, 1024, -773, 0, 1024, -674, 0
+ , 645, -2048, -745, 0, 628, 2048, -2048, -712, 0, 681
+ , 2048, 3072, -3072, -2048, -673, 0, 682, 1964, 3257, 0
+ , 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024
+ , -1024, 0, 1024, -1024, 0, 1024, -705, 0, 623, -771
+ , 0, 1024, -786, 0, 688, -631, 0, 652, 2048, -2048
+ , -627, -1, 666, 2048, -3072, -1756, -694, 0, 674, 2048
+ , -3098, -1879, -720, 5, 694, 1886, 2958, 4096, 0, 0
+ , 0, 0, 1024, 0, 0, 1024, -769, 0, 1024, -1024
+ , 0, 1024, -1024, 0, 1024, -817, 0, 734, -786, 0
+ , 651, -638, 0, 637, -623, 0, 671, -652, 0, 619
+ , 2048, -2048, -670, -1, 663, 2048, -1908, -680, 1, 686
+ , 2048, 3072, 4096, -4096, -3072, -1833, -711, 0, 727, 1747
+ , 3072, 4096, -4096, -2971, -1826, -762, 2, 766, 1832, 2852
+ , 3928, 5079, 0, 0, 0, -1024, 0, 1024, -1024, 0
+ , -656, 0, 1024, -599, 0, 620, -1024, 0, 1024, -603
+ , 0, 622, -643, 0, 660, -599, 0, 611, -641, -1
+ , 651, 2048, -2048, -648, -2, 647, 1798, -3072, -2048, -672
+ , 2, 670, 2048, -3072, -1780, -694, -1, 706, 1751, 3072
+ , -3072, -1862, -757, 7, 739, 1798, 3072, 4096, -5120, -4096
+ , -3253, -1811, -787, 3, 782, 1887, 3123, 4096, -7252, -6144
+ , -5354, -4060, -2864, -1863, -820, -11, 847, 1903, 2970, 3851
+ , 4921, 5957, 7168, 8192, 9306, 0, 0, -1024, 0, 1024
+ , -726, 0, 706, -692, 0, 593, -598, 0, 616, -624
+ , 0, 616, -605, 0, 613, -2048, -652, 1, 635, 2048
+ , -2048, -647, -1, 660, 2048, -1811, -668, -2, 685, 2048
+ , -1796, -731, -2, 730, 1702, 3072, -3072, -1766, -747, -4
+ , 756, 1770, 3072, -4096, -3024, -1762, -783, 4, 771, 1781
+ , 3072, -5120, -4057, -2807, -1832, -822, 0, 816, 1804, 2851
+ , 3949, 5120, -6144, -4899, -3927, -2920, -1893, -874, -2, 868
+ , 1881, 2905, 3960, 4912, 6144, -9216, -8192, -7168, -6225, -4963
+ , -3943, -2956, -1890, -902, 0, 897, 1914, 2916, 3984, 4990
+ , 6050, 7168,-11264,-10217, -9114, -8132, -7035, -5988, -4984, -4000
+ , -2980, -1962, -927, 7, 931, 1956, 2981, 4031, 4972, 6213
+ , 7227, 8192, 9216, 10240, 11170, 12288, 13312, 14336, 0, 1024
+ , -557, 1, 571, -606, -4, 612, -1676, -707, 10, 673
+ , 2048, -2048, -727, 5, 686, -3072, -1772, -755, 12, 716
+ , 1877, -1856, -786, 2, 786, 1712, -1685, -818, -16, 863
+ , 1729, -3072, -1762, -857, 3, 866, 1838, 2841, -3862, -2816
+ , -1864, -925, -2, 923, 1897, 2779, -2782, -1838, -920, -28
+ , 931, 1951, 2835, 3804, -4815, -4001, -2940, -1934, -959, -22
+ , 975, 1957, 2904, 3971, 4835, -5148, -3892, -2944, -1953, -986
+ , -11, 989, 1968, 2939, 3949, 4947, 5902, -9216, -8192, -6915
+ , -6004, -4965, -4013, -3009, -1977, -987, -1, 982, 1972, 3000
+ , 3960, 4939, 5814, -8976, -7888, -7084, -5955, -5043, -4009, -2991
+ , -2002, -1000, -8, 993, 2011, 3023, 4026, 5028, 6023, 7052
+ , 8014, 9216,-11240,-10036, -9125, -8118, -7105, -6062, -5048, -4047
+ , -3044, -2025, -1009, -1, 1011, 2023, 3042, 4074, 5085, 6108
+ , 7119, 8142, 9152, 10114, 11141, 12250, 13307,-15360,-14099,-13284
+ ,-12291,-11223,-10221, -9152, -8147, -7128, -6104, -5077, -4072, -3062
+ , -2033, -1020, 7, 1018, 2038, 3059, 4081, 5084, 6109, 7102
+ , 8128, 9134, 10125, 11239, 12080,-23552,-22528,-21504,-20480,-19456
+ ,-18159,-17240,-16291,-15364,-14285,-13305,-12271,-11233,-10217, -9198
+ , -8175, -7157, -6134, -5122, -4089, -3071, -2047, -1018, 3, 1026
+ , 2041, 3077, 4090, 5108, 6131, 7150, 8172, 9175, 10196, 11272
+ , 12303, 13273, 14328, 15332, 16334, 17381, 18409, 19423, 20423, 21451
+ , 22679, 23391, 24568, 25600, 26589
+};
+
+/* cdf tables for quantizer indices */
+const uint16_t WebRtcIsacfix_kCdfGain[1212] = {
+ 0, 13, 301, 3730, 61784, 65167, 65489, 65535, 0, 17,
+ 142, 314, 929, 2466, 7678, 56450, 63463, 64740, 65204, 65426,
+ 65527, 65535, 0, 8, 100, 724, 6301, 60105, 65125, 65510,
+ 65531, 65535, 0, 13, 117, 368, 1068, 3010, 11928, 53603,
+ 61177, 63404, 64505, 65108, 65422, 65502, 65531, 65535, 0, 4,
+ 17, 96, 410, 1859, 12125, 54361, 64103, 65305, 65497, 65535,
+ 0, 4, 88, 230, 469, 950, 1746, 3228, 6092, 16592,
+ 44756, 56848, 61256, 63308, 64325, 64920, 65309, 65460, 65502, 65522,
+ 65535, 0, 88, 352, 1675, 6339, 20749, 46686, 59284, 63525,
+ 64949, 65359, 65502, 65527, 65535, 0, 13, 38, 63, 117,
+ 234, 381, 641, 929, 1407, 2043, 2809, 4032, 5753, 8792,
+ 14407, 24308, 38941, 48947, 55403, 59293, 61411, 62688, 63630, 64329,
+ 64840, 65188, 65376, 65472, 65506, 65527, 65531, 65535, 0, 8,
+ 29, 75, 222, 615, 1327, 2801, 5623, 9931, 16094, 24966,
+ 34419, 43458, 50676, 56186, 60055, 62500, 63936, 64765, 65225, 65435,
+ 65514, 65535, 0, 8, 13, 15, 17, 21, 33, 59,
+ 71, 92, 151, 243, 360, 456, 674, 934, 1223, 1583,
+ 1989, 2504, 3031, 3617, 4354, 5154, 6163, 7411, 8780, 10747,
+ 12874, 15591, 18974, 23027, 27436, 32020, 36948, 41830, 46205, 49797,
+ 53042, 56094, 58418, 60360, 61763, 62818, 63559, 64103, 64509, 64798,
+ 65045, 65162, 65288, 65363, 65447, 65506, 65522, 65531, 65533, 65535,
+ 0, 4, 6, 25, 38, 71, 138, 264, 519, 808,
+ 1227, 1825, 2516, 3408, 4279, 5560, 7092, 9197, 11420, 14108,
+ 16947, 20300, 23926, 27459, 31164, 34827, 38575, 42178, 45540, 48747,
+ 51444, 54090, 56426, 58460, 60080, 61595, 62734, 63668, 64275, 64673,
+ 64936, 65112, 65217, 65334, 65426, 65464, 65477, 65489, 65518, 65527,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 8, 10, 12,
+ 14, 16, 21, 33, 50, 71, 84, 92, 105, 138,
+ 180, 255, 318, 377, 435, 473, 511, 590, 682, 758,
+ 913, 1097, 1256, 1449, 1671, 1884, 2169, 2445, 2772, 3157,
+ 3563, 3944, 4375, 4848, 5334, 5820, 6448, 7101, 7716, 8378,
+ 9102, 9956, 10752, 11648, 12707, 13670, 14758, 15910, 17187, 18472,
+ 19627, 20649, 21951, 23169, 24283, 25552, 26862, 28227, 29391, 30764,
+ 31882, 33213, 34432, 35600, 36910, 38116, 39464, 40729, 41872, 43144,
+ 44371, 45514, 46762, 47813, 48968, 50069, 51032, 51974, 52908, 53737,
+ 54603, 55445, 56282, 56990, 57572, 58191, 58840, 59410, 59887, 60264,
+ 60607, 60946, 61269, 61516, 61771, 61960, 62198, 62408, 62558, 62776,
+ 62985, 63207, 63408, 63546, 63739, 63906, 64070, 64237, 64371, 64551,
+ 64677, 64836, 64999, 65095, 65213, 65284, 65338, 65380, 65426, 65447,
+ 65472, 65485, 65487, 65489, 65502, 65510, 65512, 65514, 65516, 65518,
+ 65522, 65531, 65533, 65535, 0, 2, 4, 6, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 10, 222, 65321,
+ 65513, 65528, 65531, 65533, 65535, 0, 2, 4, 50, 65476,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8, 12,
+ 38, 544, 64936, 65509, 65523, 65525, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 10, 1055, 64508, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 10, 12, 123,
+ 3956, 62999, 65372, 65495, 65515, 65521, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 12, 53, 4707, 59445,
+ 65467, 65525, 65527, 65529, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 38, 40, 50, 67,
+ 96, 234, 929, 14345, 55750, 64866, 65389, 65462, 65514, 65517,
+ 65519, 65521, 65523, 65525, 65527, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 15, 35, 91, 377, 1946,
+ 13618, 52565, 63714, 65184, 65465, 65520, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 14, 16, 18, 20, 22, 24, 26, 28, 30, 32,
+ 34, 36, 38, 40, 42, 44, 46, 48, 50, 52,
+ 54, 82, 149, 362, 751, 1701, 4239, 12893, 38627, 55072,
+ 60875, 63071, 64158, 64702, 65096, 65283, 65412, 65473, 65494, 65505,
+ 65508, 65517, 65519, 65521, 65523, 65525, 65527, 65529, 65531, 65533,
+ 65535, 0, 2, 15, 23, 53, 143, 260, 418, 698,
+ 988, 1353, 1812, 2411, 3144, 4015, 5143, 6401, 7611, 8999,
+ 10653, 12512, 14636, 16865, 19404, 22154, 24798, 27521, 30326, 33102,
+ 35790, 38603, 41415, 43968, 46771, 49435, 52152, 54715, 57143, 59481,
+ 61178, 62507, 63603, 64489, 64997, 65257, 65427, 65473, 65503, 65520,
+ 65529, 65531, 65533, 65535, 0, 3, 6, 9, 26, 32,
+ 44, 46, 64, 94, 111, 164, 205, 254, 327, 409,
+ 506, 608, 733, 885, 1093, 1292, 1482, 1742, 1993, 2329,
+ 2615, 3029, 3374, 3798, 4257, 4870, 5405, 5992, 6618, 7225,
+ 7816, 8418, 9051, 9761, 10532, 11380, 12113, 13010, 13788, 14594,
+ 15455, 16361, 17182, 18088, 18997, 20046, 20951, 21968, 22947, 24124,
+ 25296, 26547, 27712, 28775, 29807, 30835, 31709, 32469, 33201, 34014,
+ 34876, 35773, 36696, 37620, 38558, 39547, 40406, 41277, 42367, 43290,
+ 44445, 45443, 46510, 47684, 48973, 50157, 51187, 52242, 53209, 54083,
+ 55006, 55871, 56618, 57293, 57965, 58556, 59222, 59722, 60180, 60554,
+ 60902, 61250, 61554, 61837, 62100, 62372, 62631, 62856, 63078, 63324,
+ 63557, 63768, 63961, 64089, 64235, 64352, 64501, 64633, 64770, 64887,
+ 65001, 65059, 65121, 65188, 65246, 65302, 65346, 65390, 65428, 65463,
+ 65477, 65506, 65515, 65517, 65519, 65521, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 109, 65332, 65531, 65533,
+ 65535, 0, 2, 4, 6, 8, 25, 1817, 63874, 65511,
+ 65527, 65529, 65531, 65533, 65535, 0, 2, 4, 907, 65014,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8, 10,
+ 12, 132, 2743, 62708, 65430, 65525, 65527, 65529, 65531, 65533,
+ 65535, 0, 2, 4, 6, 8, 35, 3743, 61666, 65485,
+ 65531, 65533, 65535, 0, 2, 4, 6, 8, 10, 23,
+ 109, 683, 6905, 58417, 64911, 65398, 65497, 65518, 65525, 65527,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 53, 510,
+ 10209, 55212, 64573, 65441, 65522, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 32, 90, 266, 1037, 3349, 14468, 50488, 62394, 64685,
+ 65341, 65480, 65514, 65519, 65521, 65523, 65525, 65527, 65529, 65531,
+ 65533, 65535, 0, 2, 4, 6, 9, 16, 37, 106,
+ 296, 748, 1868, 5733, 18897, 45553, 60165, 63949, 64926, 65314,
+ 65441, 65508, 65524, 65529, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+ 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 83, 175, 344, 667, 1293, 2337, 4357,
+ 8033, 14988, 28600, 43244, 52011, 57042, 59980, 61779, 63065, 63869,
+ 64390, 64753, 64988, 65164, 65326, 65422, 65462, 65492, 65506, 65522,
+ 65524, 65526, 65531, 65533, 65535, 0, 2, 4, 6, 8,
+ 10, 12, 14, 16, 25, 39, 48, 55, 62, 65,
+ 85, 106, 139, 169, 194, 252, 323, 485, 688, 1074,
+ 1600, 2544, 3863, 5733, 8303, 11397, 15529, 20273, 25734, 31455,
+ 36853, 41891, 46410, 50306, 53702, 56503, 58673, 60479, 61880, 62989,
+ 63748, 64404, 64852, 65124, 65309, 65424, 65480, 65524, 65528, 65533,
+ 65535, 0, 2, 4, 6, 8, 10, 12, 14, 21,
+ 23, 25, 27, 29, 31, 39, 41, 43, 48, 60,
+ 72, 79, 106, 136, 166, 187, 224, 252, 323, 381,
+ 427, 478, 568, 660, 783, 912, 1046, 1175, 1365, 1567,
+ 1768, 2024, 2347, 2659, 3049, 3529, 4033, 4623, 5281, 5925,
+ 6726, 7526, 8417, 9468, 10783, 12141, 13571, 15222, 16916, 18659,
+ 20350, 22020, 23725, 25497, 27201, 29026, 30867, 32632, 34323, 36062,
+ 37829, 39466, 41144, 42654, 43981, 45343, 46579, 47759, 49013, 50171,
+ 51249, 52283, 53245, 54148, 54938, 55669, 56421, 57109, 57791, 58464,
+ 59092, 59674, 60105, 60653, 61083, 61407, 61757, 62095, 62388, 62649,
+ 62873, 63157, 63358, 63540, 63725, 63884, 64046, 64155, 64278, 64426,
+ 64548, 64654, 64806, 64906, 64994, 65077, 65137, 65215, 65277, 65324,
+ 65354, 65409, 65437, 65455, 65462, 65490, 65495, 65499, 65508, 65511,
+ 65513, 65515, 65517, 65519, 65521, 65523, 65525, 65527, 65529, 65531,
+ 65533, 65535
+};
+
+const uint16_t WebRtcIsacfix_kCdfShape[2059] = {
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4,
+ 65535, 0, 8, 65514, 65535, 0, 29, 65481, 65535, 0,
+ 121, 65439, 65535, 0, 239, 65284, 65535, 0, 8, 779,
+ 64999, 65527, 65535, 0, 8, 888, 64693, 65522, 65535, 0,
+ 29, 2604, 62843, 65497, 65531, 65535, 0, 25, 176, 4576,
+ 61164, 65275, 65527, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 4, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 4, 65535, 0, 33, 65502, 65535,
+ 0, 54, 65481, 65535, 0, 251, 65309, 65535, 0, 611,
+ 65074, 65535, 0, 1273, 64292, 65527, 65535, 0, 4, 1809,
+ 63940, 65518, 65535, 0, 88, 4392, 60603, 65426, 65531, 65535,
+ 0, 25, 419, 7046, 57756, 64961, 65514, 65531, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4, 65531,
+ 65535, 0, 65535, 0, 8, 65531, 65535, 0, 4, 65527,
+ 65535, 0, 17, 65510, 65535, 0, 42, 65481, 65535, 0,
+ 197, 65342, 65531, 65535, 0, 385, 65154, 65535, 0, 1005,
+ 64522, 65535, 0, 8, 1985, 63469, 65533, 65535, 0, 38,
+ 3119, 61884, 65514, 65535, 0, 4, 6, 67, 4961, 60804,
+ 65472, 65535, 0, 17, 565, 9182, 56538, 65087, 65514, 65535,
+ 0, 8, 63, 327, 2118, 14490, 52774, 63839, 65376, 65522,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 17, 65522, 65535, 0, 59, 65489, 65535, 0, 50, 65522,
+ 65535, 0, 54, 65489, 65535, 0, 310, 65179, 65535, 0,
+ 615, 64836, 65535, 0, 4, 1503, 63965, 65535, 0, 2780,
+ 63383, 65535, 0, 21, 3919, 61051, 65527, 65535, 0, 84,
+ 6674, 59929, 65435, 65535, 0, 4, 255, 7976, 55784, 65150,
+ 65518, 65531, 65535, 0, 4, 8, 582, 10726, 53465, 64949,
+ 65518, 65535, 0, 29, 339, 3006, 17555, 49517, 62956, 65200,
+ 65497, 65531, 65535, 0, 2, 33, 138, 565, 2324, 7670,
+ 22089, 45966, 58949, 63479, 64966, 65380, 65518, 65535, 0, 65535,
+ 0, 65535, 0, 2, 65533, 65535, 0, 46, 65514, 65535,
+ 0, 414, 65091, 65535, 0, 540, 64911, 65535, 0, 419,
+ 65162, 65535, 0, 976, 64790, 65535, 0, 2977, 62495, 65531,
+ 65535, 0, 4, 3852, 61034, 65527, 65535, 0, 4, 29,
+ 6021, 60243, 65468, 65535, 0, 84, 6711, 58066, 65418, 65535,
+ 0, 13, 281, 9550, 54917, 65125, 65506, 65535, 0, 2,
+ 63, 984, 12108, 52644, 64342, 65435, 65527, 65535, 0, 29,
+ 251, 2014, 14871, 47553, 62881, 65229, 65518, 65535, 0, 13,
+ 142, 749, 4220, 18497, 45200, 60913, 64823, 65426, 65527, 65535,
+ 0, 13, 71, 264, 1176, 3789, 10500, 24480, 43488, 56324,
+ 62315, 64493, 65242, 65464, 65514, 65522, 65531, 65535, 0, 4,
+ 13, 38, 109, 205, 448, 850, 1708, 3429, 6276, 11371,
+ 19221, 29734, 40955, 49391, 55411, 59460, 62102, 63793, 64656, 65150,
+ 65401, 65485, 65522, 65531, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 1160, 65476, 65535, 0, 2, 6640, 64763, 65533,
+ 65535, 0, 2, 38, 9923, 61009, 65527, 65535, 0, 2,
+ 4949, 63092, 65533, 65535, 0, 2, 3090, 63398, 65533, 65535,
+ 0, 2, 2520, 58744, 65510, 65535, 0, 2, 13, 544,
+ 8784, 51403, 65148, 65533, 65535, 0, 2, 25, 1017, 10412,
+ 43550, 63651, 65489, 65527, 65535, 0, 2, 4, 29, 783,
+ 13377, 52462, 64524, 65495, 65533, 65535, 0, 2, 4, 6,
+ 100, 1817, 18451, 52590, 63559, 65376, 65531, 65535, 0, 2,
+ 4, 6, 46, 385, 2562, 11225, 37416, 60488, 65026, 65487,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 42, 222, 971, 5221, 19811, 45048, 60312, 64486, 65294, 65474,
+ 65525, 65529, 65533, 65535, 0, 2, 4, 8, 71, 167,
+ 666, 2533, 7875, 19622, 38082, 54359, 62108, 64633, 65290, 65495,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 13,
+ 109, 586, 1930, 4949, 11600, 22641, 36125, 48312, 56899, 61495,
+ 63927, 64932, 65389, 65489, 65518, 65531, 65533, 65535, 0, 4,
+ 6, 8, 67, 209, 712, 1838, 4195, 8432, 14432, 22834,
+ 31723, 40523, 48139, 53929, 57865, 60657, 62403, 63584, 64363, 64907,
+ 65167, 65372, 65472, 65514, 65535, 0, 2, 4, 13, 25,
+ 42, 46, 50, 75, 113, 147, 281, 448, 657, 909,
+ 1185, 1591, 1976, 2600, 3676, 5317, 7398, 9914, 12941, 16169,
+ 19477, 22885, 26464, 29851, 33360, 37228, 41139, 44802, 48654, 52058,
+ 55181, 57676, 59581, 61022, 62190, 63107, 63676, 64199, 64547, 64924,
+ 65158, 65313, 65430, 65481, 65518, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65533, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65533, 65535, 0, 2, 65535, 0,
+ 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533,
+ 65535, 0, 2, 4, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 4, 65531, 65533, 65535, 0, 2, 4, 65531,
+ 65533, 65535, 0, 2, 4, 6, 65524, 65533, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65533, 65535, 0, 65533,
+ 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0,
+ 2, 65533, 65535, 0, 2, 4, 65532, 65535, 0, 6,
+ 65523, 65535, 0, 2, 15, 65530, 65533, 65535, 0, 2,
+ 35, 65493, 65531, 65533, 65535, 0, 2, 4, 158, 65382,
+ 65531, 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 2, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 9, 65512, 65535, 0, 2,
+ 12, 65529, 65535, 0, 2, 73, 65434, 65533, 65535, 0,
+ 2, 240, 65343, 65533, 65535, 0, 2, 476, 65017, 65531,
+ 65533, 65535, 0, 2, 4, 1046, 64686, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 1870, 63898, 65529, 65531, 65533,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65532, 65535, 0, 6, 65533, 65535, 0, 6, 65523, 65535,
+ 0, 2, 65532, 65535, 0, 137, 65439, 65535, 0, 576,
+ 64899, 65533, 65535, 0, 2, 289, 65299, 65533, 65535, 0,
+ 2, 4, 6, 880, 64134, 65531, 65533, 65535, 0, 2,
+ 4, 1853, 63347, 65533, 65535, 0, 2, 6, 2516, 61762,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 9, 3980, 61380,
+ 65503, 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8,
+ 10, 12, 61, 6393, 59859, 65466, 65527, 65529, 65531, 65533,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 2, 65532,
+ 65535, 0, 3, 65529, 65535, 0, 2, 65529, 65535, 0,
+ 61, 65453, 65535, 0, 234, 65313, 65535, 0, 503, 65138,
+ 65535, 0, 155, 65402, 65533, 65535, 0, 2, 1058, 64554,
+ 65533, 65535, 0, 2, 4, 3138, 62109, 65531, 65533, 65535,
+ 0, 2, 4, 2031, 63339, 65531, 65533, 65535, 0, 2,
+ 4, 6, 9, 4155, 60778, 65523, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 41, 6189, 59269, 65490, 65531, 65533, 65535,
+ 0, 2, 4, 6, 210, 8789, 57043, 65400, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 26, 453, 10086,
+ 55499, 64948, 65483, 65524, 65527, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 114, 1014, 11202, 52670, 64226, 65356, 65503, 65514, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 0, 65533, 65535, 0, 15,
+ 65301, 65535, 0, 152, 64807, 65535, 0, 2, 3328, 63308,
+ 65535, 0, 2, 4050, 59730, 65533, 65535, 0, 2, 164,
+ 10564, 61894, 65529, 65535, 0, 15, 6712, 59831, 65076, 65532,
+ 65535, 0, 32, 7712, 57449, 65459, 65535, 0, 2, 210,
+ 7849, 53110, 65021, 65523, 65535, 0, 2, 12, 1081, 13883,
+ 48262, 62870, 65477, 65535, 0, 2, 88, 847, 6145, 37852,
+ 62012, 65454, 65533, 65535, 0, 9, 47, 207, 1823, 14522,
+ 45521, 61069, 64891, 65481, 65528, 65531, 65533, 65535, 0, 2,
+ 9, 488, 2881, 12758, 38703, 58412, 64420, 65410, 65533, 65535,
+ 0, 2, 4, 6, 61, 333, 1891, 6486, 19720, 43188,
+ 57547, 62472, 64796, 65421, 65497, 65523, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 10, 12, 29, 117, 447,
+ 1528, 6138, 21242, 43133, 56495, 62432, 64746, 65362, 65500, 65529,
+ 65531, 65533, 65535, 0, 2, 18, 105, 301, 760, 1490,
+ 3472, 7568, 15002, 26424, 40330, 53029, 60048, 62964, 64274, 64890,
+ 65337, 65445, 65489, 65513, 65527, 65530, 65533, 65535, 0, 2,
+ 4, 6, 41, 102, 409, 853, 2031, 4316, 7302, 11328,
+ 16869, 24825, 34926, 43481, 50877, 56126, 59874, 62103, 63281, 63857,
+ 64166, 64675, 65382, 65522, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 29, 38, 53,
+ 58, 96, 181, 503, 1183, 2849, 5590, 8600, 11379, 13942,
+ 16478, 19453, 22638, 26039, 29411, 32921, 37596, 41433, 44998, 48560,
+ 51979, 55106, 57666, 59892, 61485, 62616, 63484, 64018, 64375, 64685,
+ 64924, 65076, 65278, 65395, 65471, 65509, 65529, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0, 7,
+ 65519, 65535, 0, 2, 14, 65491, 65533, 65535, 0, 2,
+ 81, 65427, 65531, 65533, 65535, 0, 2, 4, 312, 65293,
+ 65528, 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533,
+ 65535, 0, 5, 65523, 65535, 0, 2, 65533, 65535, 0,
+ 7, 65526, 65535, 0, 46, 65464, 65533, 65535, 0, 2,
+ 120, 65309, 65533, 65535, 0, 2, 5, 362, 65097, 65533,
+ 65535, 0, 2, 18, 1164, 64785, 65528, 65531, 65533, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65533, 65535, 0,
+ 65535, 0, 65533, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65530, 65535,
+ 0, 2, 65523, 65535, 0, 69, 65477, 65535, 0, 141,
+ 65459, 65535, 0, 194, 65325, 65533, 65535, 0, 2, 543,
+ 64912, 65533, 65535, 0, 5, 1270, 64301, 65529, 65531, 65533,
+ 65535, 0, 2, 4, 12, 2055, 63538, 65508, 65531, 65533,
+ 65535, 0, 2, 7, 102, 3775, 61970, 65429, 65526, 65528,
+ 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65535, 0, 9, 65533, 65535, 0,
+ 25, 65512, 65535, 0, 2, 65533, 65535, 0, 44, 65480,
+ 65535, 0, 48, 65475, 65535, 0, 162, 65373, 65535, 0,
+ 637, 64806, 65533, 65535, 0, 2, 935, 64445, 65533, 65535,
+ 0, 2, 4, 1662, 64083, 65533, 65535, 0, 2, 12,
+ 3036, 62469, 65521, 65533, 65535, 0, 2, 120, 5405, 60468,
+ 65469, 65531, 65533, 65535, 0, 2, 4, 18, 254, 6663,
+ 58999, 65272, 65528, 65533, 65535, 0, 2, 4, 9, 12,
+ 67, 591, 8981, 56781, 64564, 65365, 65508, 65524, 65526, 65529,
+ 65531, 65533, 65535, 0, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 9, 65526, 65535, 0, 14, 65503, 65535, 0,
+ 127, 65390, 65535, 0, 517, 64990, 65535, 0, 178, 65330,
+ 65535, 0, 2, 1055, 64533, 65533, 65535, 0, 2, 1558,
+ 63942, 65533, 65535, 0, 2, 2205, 63173, 65533, 65535, 0,
+ 25, 4493, 60862, 65505, 65533, 65535, 0, 2, 48, 5890,
+ 59442, 65482, 65533, 65535, 0, 2, 4, 127, 7532, 58191,
+ 65394, 65533, 65535, 0, 2, 5, 32, 550, 10388, 54924,
+ 65046, 65510, 65531, 65533, 65535, 0, 2, 4, 30, 150,
+ 1685, 14340, 51375, 63619, 65288, 65503, 65528, 65533, 65535, 0,
+ 2, 4, 6, 8, 28, 97, 473, 2692, 15407, 50020,
+ 62880, 65064, 65445, 65508, 65531, 65533, 65535, 0, 2, 4,
+ 12, 32, 79, 150, 372, 907, 2184, 5868, 18207, 45431,
+ 59856, 64031, 65096, 65401, 65481, 65507, 65521, 65523, 65525, 65527,
+ 65529, 65531, 65533, 65535, 0, 65533, 65535, 0, 182, 65491,
+ 65535, 0, 877, 64286, 65535, 0, 9, 2708, 63612, 65533,
+ 65535, 0, 2, 6038, 59532, 65535, 0, 2, 92, 5500,
+ 60539, 65533, 65535, 0, 268, 8908, 56512, 65385, 65535, 0,
+ 129, 13110, 52742, 65036, 65535, 0, 2, 806, 14003, 51929,
+ 64732, 65523, 65535, 0, 7, 92, 2667, 18159, 47678, 62610,
+ 65355, 65535, 0, 32, 1836, 19676, 48237, 61677, 64960, 65526,
+ 65535, 0, 21, 159, 967, 5668, 22782, 44709, 58317, 64020,
+ 65406, 65528, 65535, 0, 7, 162, 1838, 8328, 23929, 43014,
+ 56394, 63374, 65216, 65484, 65521, 65535, 0, 2, 4, 6,
+ 28, 268, 1120, 3613, 10688, 24185, 40989, 54917, 61684, 64510,
+ 65403, 65530, 65535, 0, 2, 16, 44, 139, 492, 1739,
+ 5313, 13558, 26766, 41566, 52446, 58937, 62815, 64480, 65201, 65454,
+ 65524, 65533, 65535, 0, 7, 25, 76, 263, 612, 1466,
+ 3325, 6832, 12366, 20152, 29466, 39255, 47360, 53506, 57740, 60726,
+ 62845, 64131, 64882, 65260, 65459, 65521, 65528, 65530, 65535, 0,
+ 2, 4, 14, 48, 136, 312, 653, 1240, 2369, 4327,
+ 7028, 10759, 15449, 21235, 28027, 35386, 42938, 49562, 54990, 59119,
+ 62086, 63916, 64863, 65249, 65445, 65493, 65523, 65535, 0, 2,
+ 4, 6, 8, 10, 12, 21, 83, 208, 409, 723,
+ 1152, 1868, 2951, 4463, 6460, 8979, 11831, 15195, 18863, 22657,
+ 26762, 30881, 34963, 39098, 43054, 47069, 50620, 53871, 56821, 59386,
+ 61340, 62670, 63512, 64023, 64429, 64750, 64944, 65126, 65279, 65366,
+ 65413, 65445, 65473, 65505, 65510, 65521, 65528, 65530, 65535
+};
+
+/* pointers to cdf tables for quantizer indices */
+const uint16_t *WebRtcIsacfix_kCdfGainPtr[3][12] = {
+ { WebRtcIsacfix_kCdfGain +0 +0, WebRtcIsacfix_kCdfGain +0 +8, WebRtcIsacfix_kCdfGain +0 +22,
+ WebRtcIsacfix_kCdfGain +0 +32, WebRtcIsacfix_kCdfGain +0 +48, WebRtcIsacfix_kCdfGain +0 +60,
+ WebRtcIsacfix_kCdfGain +0 +81, WebRtcIsacfix_kCdfGain +0 +95, WebRtcIsacfix_kCdfGain +0 +128,
+ WebRtcIsacfix_kCdfGain +0 +152, WebRtcIsacfix_kCdfGain +0 +210, WebRtcIsacfix_kCdfGain +0 +264
+ },
+ { WebRtcIsacfix_kCdfGain +404 +0, WebRtcIsacfix_kCdfGain +404 +8, WebRtcIsacfix_kCdfGain +404 +21,
+ WebRtcIsacfix_kCdfGain +404 +30, WebRtcIsacfix_kCdfGain +404 +46, WebRtcIsacfix_kCdfGain +404 +58,
+ WebRtcIsacfix_kCdfGain +404 +79, WebRtcIsacfix_kCdfGain +404 +93, WebRtcIsacfix_kCdfGain +404 +125,
+ WebRtcIsacfix_kCdfGain +404 +149, WebRtcIsacfix_kCdfGain +404 +207, WebRtcIsacfix_kCdfGain +404 +260
+ },
+ { WebRtcIsacfix_kCdfGain +803 +0, WebRtcIsacfix_kCdfGain +803 +8, WebRtcIsacfix_kCdfGain +803 +22,
+ WebRtcIsacfix_kCdfGain +803 +31, WebRtcIsacfix_kCdfGain +803 +48, WebRtcIsacfix_kCdfGain +803 +60,
+ WebRtcIsacfix_kCdfGain +803 +81, WebRtcIsacfix_kCdfGain +803 +96, WebRtcIsacfix_kCdfGain +803 +129,
+ WebRtcIsacfix_kCdfGain +803 +154, WebRtcIsacfix_kCdfGain +803 +212, WebRtcIsacfix_kCdfGain +803 +268
+ }
+};
+
+const uint16_t *WebRtcIsacfix_kCdfShapePtr[3][108] = {
+ { WebRtcIsacfix_kCdfShape +0 +0, WebRtcIsacfix_kCdfShape +0 +2, WebRtcIsacfix_kCdfShape +0 +4,
+ WebRtcIsacfix_kCdfShape +0 +6, WebRtcIsacfix_kCdfShape +0 +8, WebRtcIsacfix_kCdfShape +0 +10,
+ WebRtcIsacfix_kCdfShape +0 +12, WebRtcIsacfix_kCdfShape +0 +14, WebRtcIsacfix_kCdfShape +0 +16,
+ WebRtcIsacfix_kCdfShape +0 +18, WebRtcIsacfix_kCdfShape +0 +21, WebRtcIsacfix_kCdfShape +0 +25,
+ WebRtcIsacfix_kCdfShape +0 +29, WebRtcIsacfix_kCdfShape +0 +33, WebRtcIsacfix_kCdfShape +0 +37,
+ WebRtcIsacfix_kCdfShape +0 +43, WebRtcIsacfix_kCdfShape +0 +49, WebRtcIsacfix_kCdfShape +0 +56,
+ WebRtcIsacfix_kCdfShape +0 +64, WebRtcIsacfix_kCdfShape +0 +66, WebRtcIsacfix_kCdfShape +0 +68,
+ WebRtcIsacfix_kCdfShape +0 +70, WebRtcIsacfix_kCdfShape +0 +72, WebRtcIsacfix_kCdfShape +0 +75,
+ WebRtcIsacfix_kCdfShape +0 +77, WebRtcIsacfix_kCdfShape +0 +79, WebRtcIsacfix_kCdfShape +0 +81,
+ WebRtcIsacfix_kCdfShape +0 +83, WebRtcIsacfix_kCdfShape +0 +86, WebRtcIsacfix_kCdfShape +0 +90,
+ WebRtcIsacfix_kCdfShape +0 +94, WebRtcIsacfix_kCdfShape +0 +98, WebRtcIsacfix_kCdfShape +0 +102,
+ WebRtcIsacfix_kCdfShape +0 +107, WebRtcIsacfix_kCdfShape +0 +113, WebRtcIsacfix_kCdfShape +0 +120,
+ WebRtcIsacfix_kCdfShape +0 +129, WebRtcIsacfix_kCdfShape +0 +131, WebRtcIsacfix_kCdfShape +0 +133,
+ WebRtcIsacfix_kCdfShape +0 +135, WebRtcIsacfix_kCdfShape +0 +137, WebRtcIsacfix_kCdfShape +0 +141,
+ WebRtcIsacfix_kCdfShape +0 +143, WebRtcIsacfix_kCdfShape +0 +147, WebRtcIsacfix_kCdfShape +0 +151,
+ WebRtcIsacfix_kCdfShape +0 +155, WebRtcIsacfix_kCdfShape +0 +159, WebRtcIsacfix_kCdfShape +0 +164,
+ WebRtcIsacfix_kCdfShape +0 +168, WebRtcIsacfix_kCdfShape +0 +172, WebRtcIsacfix_kCdfShape +0 +178,
+ WebRtcIsacfix_kCdfShape +0 +184, WebRtcIsacfix_kCdfShape +0 +192, WebRtcIsacfix_kCdfShape +0 +200,
+ WebRtcIsacfix_kCdfShape +0 +211, WebRtcIsacfix_kCdfShape +0 +213, WebRtcIsacfix_kCdfShape +0 +215,
+ WebRtcIsacfix_kCdfShape +0 +217, WebRtcIsacfix_kCdfShape +0 +219, WebRtcIsacfix_kCdfShape +0 +223,
+ WebRtcIsacfix_kCdfShape +0 +227, WebRtcIsacfix_kCdfShape +0 +231, WebRtcIsacfix_kCdfShape +0 +235,
+ WebRtcIsacfix_kCdfShape +0 +239, WebRtcIsacfix_kCdfShape +0 +243, WebRtcIsacfix_kCdfShape +0 +248,
+ WebRtcIsacfix_kCdfShape +0 +252, WebRtcIsacfix_kCdfShape +0 +258, WebRtcIsacfix_kCdfShape +0 +264,
+ WebRtcIsacfix_kCdfShape +0 +273, WebRtcIsacfix_kCdfShape +0 +282, WebRtcIsacfix_kCdfShape +0 +293,
+ WebRtcIsacfix_kCdfShape +0 +308, WebRtcIsacfix_kCdfShape +0 +310, WebRtcIsacfix_kCdfShape +0 +312,
+ WebRtcIsacfix_kCdfShape +0 +316, WebRtcIsacfix_kCdfShape +0 +320, WebRtcIsacfix_kCdfShape +0 +324,
+ WebRtcIsacfix_kCdfShape +0 +328, WebRtcIsacfix_kCdfShape +0 +332, WebRtcIsacfix_kCdfShape +0 +336,
+ WebRtcIsacfix_kCdfShape +0 +341, WebRtcIsacfix_kCdfShape +0 +347, WebRtcIsacfix_kCdfShape +0 +354,
+ WebRtcIsacfix_kCdfShape +0 +360, WebRtcIsacfix_kCdfShape +0 +368, WebRtcIsacfix_kCdfShape +0 +378,
+ WebRtcIsacfix_kCdfShape +0 +388, WebRtcIsacfix_kCdfShape +0 +400, WebRtcIsacfix_kCdfShape +0 +418,
+ WebRtcIsacfix_kCdfShape +0 +445, WebRtcIsacfix_kCdfShape +0 +447, WebRtcIsacfix_kCdfShape +0 +451,
+ WebRtcIsacfix_kCdfShape +0 +455, WebRtcIsacfix_kCdfShape +0 +461, WebRtcIsacfix_kCdfShape +0 +468,
+ WebRtcIsacfix_kCdfShape +0 +474, WebRtcIsacfix_kCdfShape +0 +480, WebRtcIsacfix_kCdfShape +0 +486,
+ WebRtcIsacfix_kCdfShape +0 +495, WebRtcIsacfix_kCdfShape +0 +505, WebRtcIsacfix_kCdfShape +0 +516,
+ WebRtcIsacfix_kCdfShape +0 +528, WebRtcIsacfix_kCdfShape +0 +543, WebRtcIsacfix_kCdfShape +0 +564,
+ WebRtcIsacfix_kCdfShape +0 +583, WebRtcIsacfix_kCdfShape +0 +608, WebRtcIsacfix_kCdfShape +0 +635
+ },
+ { WebRtcIsacfix_kCdfShape +686 +0, WebRtcIsacfix_kCdfShape +686 +2, WebRtcIsacfix_kCdfShape +686 +4,
+ WebRtcIsacfix_kCdfShape +686 +6, WebRtcIsacfix_kCdfShape +686 +8, WebRtcIsacfix_kCdfShape +686 +11,
+ WebRtcIsacfix_kCdfShape +686 +13, WebRtcIsacfix_kCdfShape +686 +15, WebRtcIsacfix_kCdfShape +686 +17,
+ WebRtcIsacfix_kCdfShape +686 +20, WebRtcIsacfix_kCdfShape +686 +23, WebRtcIsacfix_kCdfShape +686 +27,
+ WebRtcIsacfix_kCdfShape +686 +31, WebRtcIsacfix_kCdfShape +686 +35, WebRtcIsacfix_kCdfShape +686 +40,
+ WebRtcIsacfix_kCdfShape +686 +44, WebRtcIsacfix_kCdfShape +686 +50, WebRtcIsacfix_kCdfShape +686 +56,
+ WebRtcIsacfix_kCdfShape +686 +63, WebRtcIsacfix_kCdfShape +686 +65, WebRtcIsacfix_kCdfShape +686 +67,
+ WebRtcIsacfix_kCdfShape +686 +69, WebRtcIsacfix_kCdfShape +686 +71, WebRtcIsacfix_kCdfShape +686 +73,
+ WebRtcIsacfix_kCdfShape +686 +75, WebRtcIsacfix_kCdfShape +686 +77, WebRtcIsacfix_kCdfShape +686 +79,
+ WebRtcIsacfix_kCdfShape +686 +82, WebRtcIsacfix_kCdfShape +686 +85, WebRtcIsacfix_kCdfShape +686 +89,
+ WebRtcIsacfix_kCdfShape +686 +93, WebRtcIsacfix_kCdfShape +686 +97, WebRtcIsacfix_kCdfShape +686 +102,
+ WebRtcIsacfix_kCdfShape +686 +106, WebRtcIsacfix_kCdfShape +686 +112, WebRtcIsacfix_kCdfShape +686 +119,
+ WebRtcIsacfix_kCdfShape +686 +127, WebRtcIsacfix_kCdfShape +686 +129, WebRtcIsacfix_kCdfShape +686 +131,
+ WebRtcIsacfix_kCdfShape +686 +133, WebRtcIsacfix_kCdfShape +686 +135, WebRtcIsacfix_kCdfShape +686 +137,
+ WebRtcIsacfix_kCdfShape +686 +139, WebRtcIsacfix_kCdfShape +686 +142, WebRtcIsacfix_kCdfShape +686 +146,
+ WebRtcIsacfix_kCdfShape +686 +150, WebRtcIsacfix_kCdfShape +686 +154, WebRtcIsacfix_kCdfShape +686 +158,
+ WebRtcIsacfix_kCdfShape +686 +162, WebRtcIsacfix_kCdfShape +686 +167, WebRtcIsacfix_kCdfShape +686 +173,
+ WebRtcIsacfix_kCdfShape +686 +179, WebRtcIsacfix_kCdfShape +686 +186, WebRtcIsacfix_kCdfShape +686 +194,
+ WebRtcIsacfix_kCdfShape +686 +205, WebRtcIsacfix_kCdfShape +686 +207, WebRtcIsacfix_kCdfShape +686 +209,
+ WebRtcIsacfix_kCdfShape +686 +211, WebRtcIsacfix_kCdfShape +686 +214, WebRtcIsacfix_kCdfShape +686 +218,
+ WebRtcIsacfix_kCdfShape +686 +222, WebRtcIsacfix_kCdfShape +686 +226, WebRtcIsacfix_kCdfShape +686 +230,
+ WebRtcIsacfix_kCdfShape +686 +234, WebRtcIsacfix_kCdfShape +686 +238, WebRtcIsacfix_kCdfShape +686 +242,
+ WebRtcIsacfix_kCdfShape +686 +247, WebRtcIsacfix_kCdfShape +686 +253, WebRtcIsacfix_kCdfShape +686 +262,
+ WebRtcIsacfix_kCdfShape +686 +269, WebRtcIsacfix_kCdfShape +686 +278, WebRtcIsacfix_kCdfShape +686 +289,
+ WebRtcIsacfix_kCdfShape +686 +305, WebRtcIsacfix_kCdfShape +686 +307, WebRtcIsacfix_kCdfShape +686 +309,
+ WebRtcIsacfix_kCdfShape +686 +311, WebRtcIsacfix_kCdfShape +686 +315, WebRtcIsacfix_kCdfShape +686 +319,
+ WebRtcIsacfix_kCdfShape +686 +323, WebRtcIsacfix_kCdfShape +686 +327, WebRtcIsacfix_kCdfShape +686 +331,
+ WebRtcIsacfix_kCdfShape +686 +335, WebRtcIsacfix_kCdfShape +686 +340, WebRtcIsacfix_kCdfShape +686 +346,
+ WebRtcIsacfix_kCdfShape +686 +354, WebRtcIsacfix_kCdfShape +686 +362, WebRtcIsacfix_kCdfShape +686 +374,
+ WebRtcIsacfix_kCdfShape +686 +384, WebRtcIsacfix_kCdfShape +686 +396, WebRtcIsacfix_kCdfShape +686 +413,
+ WebRtcIsacfix_kCdfShape +686 +439, WebRtcIsacfix_kCdfShape +686 +442, WebRtcIsacfix_kCdfShape +686 +446,
+ WebRtcIsacfix_kCdfShape +686 +450, WebRtcIsacfix_kCdfShape +686 +455, WebRtcIsacfix_kCdfShape +686 +461,
+ WebRtcIsacfix_kCdfShape +686 +468, WebRtcIsacfix_kCdfShape +686 +475, WebRtcIsacfix_kCdfShape +686 +481,
+ WebRtcIsacfix_kCdfShape +686 +489, WebRtcIsacfix_kCdfShape +686 +498, WebRtcIsacfix_kCdfShape +686 +508,
+ WebRtcIsacfix_kCdfShape +686 +522, WebRtcIsacfix_kCdfShape +686 +534, WebRtcIsacfix_kCdfShape +686 +554,
+ WebRtcIsacfix_kCdfShape +686 +577, WebRtcIsacfix_kCdfShape +686 +602, WebRtcIsacfix_kCdfShape +686 +631
+ },
+ { WebRtcIsacfix_kCdfShape +1368 +0, WebRtcIsacfix_kCdfShape +1368 +2, WebRtcIsacfix_kCdfShape +1368 +4,
+ WebRtcIsacfix_kCdfShape +1368 +6, WebRtcIsacfix_kCdfShape +1368 +8, WebRtcIsacfix_kCdfShape +1368 +10,
+ WebRtcIsacfix_kCdfShape +1368 +12, WebRtcIsacfix_kCdfShape +1368 +14, WebRtcIsacfix_kCdfShape +1368 +16,
+ WebRtcIsacfix_kCdfShape +1368 +20, WebRtcIsacfix_kCdfShape +1368 +24, WebRtcIsacfix_kCdfShape +1368 +28,
+ WebRtcIsacfix_kCdfShape +1368 +32, WebRtcIsacfix_kCdfShape +1368 +36, WebRtcIsacfix_kCdfShape +1368 +40,
+ WebRtcIsacfix_kCdfShape +1368 +44, WebRtcIsacfix_kCdfShape +1368 +50, WebRtcIsacfix_kCdfShape +1368 +57,
+ WebRtcIsacfix_kCdfShape +1368 +65, WebRtcIsacfix_kCdfShape +1368 +67, WebRtcIsacfix_kCdfShape +1368 +69,
+ WebRtcIsacfix_kCdfShape +1368 +71, WebRtcIsacfix_kCdfShape +1368 +73, WebRtcIsacfix_kCdfShape +1368 +75,
+ WebRtcIsacfix_kCdfShape +1368 +77, WebRtcIsacfix_kCdfShape +1368 +79, WebRtcIsacfix_kCdfShape +1368 +81,
+ WebRtcIsacfix_kCdfShape +1368 +85, WebRtcIsacfix_kCdfShape +1368 +89, WebRtcIsacfix_kCdfShape +1368 +93,
+ WebRtcIsacfix_kCdfShape +1368 +97, WebRtcIsacfix_kCdfShape +1368 +101, WebRtcIsacfix_kCdfShape +1368 +105,
+ WebRtcIsacfix_kCdfShape +1368 +110, WebRtcIsacfix_kCdfShape +1368 +116, WebRtcIsacfix_kCdfShape +1368 +123,
+ WebRtcIsacfix_kCdfShape +1368 +132, WebRtcIsacfix_kCdfShape +1368 +134, WebRtcIsacfix_kCdfShape +1368 +136,
+ WebRtcIsacfix_kCdfShape +1368 +138, WebRtcIsacfix_kCdfShape +1368 +141, WebRtcIsacfix_kCdfShape +1368 +143,
+ WebRtcIsacfix_kCdfShape +1368 +146, WebRtcIsacfix_kCdfShape +1368 +150, WebRtcIsacfix_kCdfShape +1368 +154,
+ WebRtcIsacfix_kCdfShape +1368 +158, WebRtcIsacfix_kCdfShape +1368 +162, WebRtcIsacfix_kCdfShape +1368 +166,
+ WebRtcIsacfix_kCdfShape +1368 +170, WebRtcIsacfix_kCdfShape +1368 +174, WebRtcIsacfix_kCdfShape +1368 +179,
+ WebRtcIsacfix_kCdfShape +1368 +185, WebRtcIsacfix_kCdfShape +1368 +193, WebRtcIsacfix_kCdfShape +1368 +203,
+ WebRtcIsacfix_kCdfShape +1368 +214, WebRtcIsacfix_kCdfShape +1368 +216, WebRtcIsacfix_kCdfShape +1368 +218,
+ WebRtcIsacfix_kCdfShape +1368 +220, WebRtcIsacfix_kCdfShape +1368 +224, WebRtcIsacfix_kCdfShape +1368 +227,
+ WebRtcIsacfix_kCdfShape +1368 +231, WebRtcIsacfix_kCdfShape +1368 +235, WebRtcIsacfix_kCdfShape +1368 +239,
+ WebRtcIsacfix_kCdfShape +1368 +243, WebRtcIsacfix_kCdfShape +1368 +247, WebRtcIsacfix_kCdfShape +1368 +251,
+ WebRtcIsacfix_kCdfShape +1368 +256, WebRtcIsacfix_kCdfShape +1368 +262, WebRtcIsacfix_kCdfShape +1368 +269,
+ WebRtcIsacfix_kCdfShape +1368 +277, WebRtcIsacfix_kCdfShape +1368 +286, WebRtcIsacfix_kCdfShape +1368 +297,
+ WebRtcIsacfix_kCdfShape +1368 +315, WebRtcIsacfix_kCdfShape +1368 +317, WebRtcIsacfix_kCdfShape +1368 +319,
+ WebRtcIsacfix_kCdfShape +1368 +323, WebRtcIsacfix_kCdfShape +1368 +327, WebRtcIsacfix_kCdfShape +1368 +331,
+ WebRtcIsacfix_kCdfShape +1368 +335, WebRtcIsacfix_kCdfShape +1368 +339, WebRtcIsacfix_kCdfShape +1368 +343,
+ WebRtcIsacfix_kCdfShape +1368 +349, WebRtcIsacfix_kCdfShape +1368 +355, WebRtcIsacfix_kCdfShape +1368 +361,
+ WebRtcIsacfix_kCdfShape +1368 +368, WebRtcIsacfix_kCdfShape +1368 +376, WebRtcIsacfix_kCdfShape +1368 +385,
+ WebRtcIsacfix_kCdfShape +1368 +397, WebRtcIsacfix_kCdfShape +1368 +411, WebRtcIsacfix_kCdfShape +1368 +429,
+ WebRtcIsacfix_kCdfShape +1368 +456, WebRtcIsacfix_kCdfShape +1368 +459, WebRtcIsacfix_kCdfShape +1368 +463,
+ WebRtcIsacfix_kCdfShape +1368 +467, WebRtcIsacfix_kCdfShape +1368 +473, WebRtcIsacfix_kCdfShape +1368 +478,
+ WebRtcIsacfix_kCdfShape +1368 +485, WebRtcIsacfix_kCdfShape +1368 +491, WebRtcIsacfix_kCdfShape +1368 +497,
+ WebRtcIsacfix_kCdfShape +1368 +505, WebRtcIsacfix_kCdfShape +1368 +514, WebRtcIsacfix_kCdfShape +1368 +523,
+ WebRtcIsacfix_kCdfShape +1368 +535, WebRtcIsacfix_kCdfShape +1368 +548, WebRtcIsacfix_kCdfShape +1368 +565,
+ WebRtcIsacfix_kCdfShape +1368 +585, WebRtcIsacfix_kCdfShape +1368 +611, WebRtcIsacfix_kCdfShape +1368 +640
+ }
+};
+
+/* code length for all coefficients using different models */
+
+const int16_t WebRtcIsacfix_kCodeLenGainQ11[392] = {
+ 25189, 16036, 8717, 358, 8757, 15706, 21456, 24397, 18502, 17559
+ , 13794, 11088, 7480, 873, 6603, 11636, 14627, 16805, 19132, 26624
+ , 26624, 19408, 13751, 7280, 583, 7591, 15178, 23773, 28672, 25189
+ , 19045, 16442, 13412, 10397, 5893, 1338, 6376, 9992, 12074, 13853
+ , 15781, 19821, 22819, 28672, 28672, 25189, 19858, 15781, 11262, 5477
+ , 1298, 5632, 11814, 17234, 22020, 28672, 19677, 18125, 16587, 14521
+ , 13032, 11196, 9249, 5411, 2495, 4994, 7975, 10234, 12308, 13892
+ , 15148, 17944, 21725, 23917, 25189, 19539, 16293, 11531, 7808, 4475
+ , 2739, 4872, 8089, 11314, 14992, 18105, 23257, 26624, 25189, 23257
+ , 23257, 20982, 18697, 18023, 16338, 16036, 14539, 13695, 13146, 11763
+ , 10754, 9074, 7260, 5584, 4430, 5553, 6848, 8344, 10141, 11636
+ , 12535, 13416, 14342, 15477, 17296, 19282, 22349, 23773, 28672, 28672
+ , 26624, 23773, 21456, 18023, 15118, 13362, 11212, 9293, 8043, 6985
+ , 5908, 5721, 5853, 6518, 7316, 8360, 9716, 11289, 12912, 14652
+ , 16969, 19858, 23773, 26624, 28013, 30720, 30720, 28672, 25426, 23141
+ , 25426, 23773, 20720, 19408, 18697, 19282, 16859, 16338, 16026, 15377
+ , 15021, 14319, 14251, 13937, 13260, 13017, 12332, 11703, 11430, 10359
+ , 10128, 9405, 8757, 8223, 7974, 7859, 7646, 7673, 7997, 8580
+ , 8880, 9061, 9866, 10397, 11358, 12200, 13244, 14157, 15021, 16026
+ , 16490, 18697, 18479, 20011, 19677, 20720, 24576, 26276, 30720, 30720
+ , 28672, 30720, 24068, 25189, 22437, 20345, 18479, 16396, 16026, 14928
+ , 13877, 13450, 12696, 12766, 11626, 11098, 10159, 9998, 9437, 9275
+ , 8783, 8552, 8629, 8488, 8522, 8454, 8571, 8775, 8915, 9427
+ , 9483, 9851, 10260, 10933, 11131, 11974, 12560, 13833, 15080, 16304
+ , 17491, 19017, 18697, 19408, 22020, 25189, 25426, 22819, 26276, 30720
+ , 30720, 30720, 30720, 30720, 30720, 28672, 30720, 30720, 30720, 30720
+ , 28013, 25426, 24397, 23773, 25189, 26624, 25189, 22437, 21725, 20011
+ , 20527, 20720, 20771, 22020, 22020, 19858, 19408, 19972, 17866, 17360
+ , 17791, 17219, 16805, 16927, 16067, 16162, 15661, 15178, 15021, 15209
+ , 14845, 14570, 14490, 14490, 13733, 13617, 13794, 13577, 13312, 12824
+ , 13032, 12683, 12189, 12469, 12109, 11940, 11636, 11617, 11932, 12294
+ , 11578, 11775, 12039, 11654, 11560, 11439, 11909, 11421, 12029, 11513
+ , 11773, 11899, 11560, 11805, 11476, 11664, 11963, 11647, 11754, 11963
+ , 11703, 12211, 11932, 12074, 12469, 12535, 12560, 12912, 12783, 12866
+ , 12884, 13378, 13957, 13775, 13635, 14019, 14545, 15240, 15520, 15554
+ , 15697, 16490, 16396, 17281, 16599, 16969, 17963, 16859, 16983, 16805
+ , 17099, 18210, 17219, 17646, 17700, 17646, 18297, 17425, 18479, 17791
+ , 17718, 19282, 18672, 20173, 20982, 21725, 21456, 23773, 23257, 25189
+ , 30720, 30720, 25189, 26624, 30720, 30720, 30720, 30720, 28672, 26276
+ , 30720, 30720
+};
+
+const int16_t WebRtcIsacfix_kCodeLenShapeQ11[578] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 28672
+ , 0, 26624, 1, 23773, 22819, 4, 20982, 18598, 10, 19282
+ , 16587, 22, 16442, 26624, 13126, 60, 14245, 26624, 26624, 12736
+ , 79, 12912, 25189, 22819, 9563, 249, 9474, 22349, 28672, 23257
+ , 17944, 7980, 434, 8181, 16431, 26624, 0, 0, 0, 0
+ , 28672, 0, 0, 0, 0, 0, 28672, 0, 22437, 3
+ , 22437, 20982, 5, 20982, 16442, 22, 16752, 13814, 49, 14646
+ , 11645, 116, 11734, 26624, 28672, 10613, 158, 11010, 24397, 19539
+ , 8046, 453, 7709, 19017, 28672, 23257, 15110, 6770, 758, 6523
+ , 14108, 24397, 28672, 0, 0, 0, 0, 28672, 0, 28672
+ , 0, 26624, 1, 28672, 28672, 1, 26624, 24397, 2, 23257
+ , 21725, 4, 20982, 17158, 18, 17281, 28672, 15178, 35, 15209
+ , 12343, 92, 12320, 26624, 10344, 189, 10217, 30720, 22020, 9033
+ , 322, 8549, 23773, 28672, 30720, 20622, 7666, 473, 7806, 20527
+ , 24397, 14135, 5995, 960, 6018, 14872, 23773, 26624, 20928, 16293
+ , 10636, 4926, 1588, 5256, 11088, 18043, 25189, 0, 0, 0
+ , 0, 24397, 1, 25189, 20720, 5, 21456, 21209, 3, 25189
+ , 20982, 5, 21456, 15818, 30, 15410, 13794, 60, 13416, 28672
+ , 11162, 142, 11025, 9337, 231, 10094, 23773, 8338, 405, 7930
+ , 26624, 19677, 6787, 613, 7318, 19161, 28672, 16442, 6319, 932
+ , 5748, 15312, 25189, 28672, 28672, 28672, 13998, 5513, 1263, 5146
+ , 14024, 24397, 22819, 15818, 9460, 4447, 2122, 4681, 9970, 15945
+ , 22349, 28672, 30720, 22622, 19017, 14872, 10689, 7405, 4473, 2983
+ , 4783, 7894, 11186, 14964, 18210, 24397, 0, 0, 30720, 0
+ , 30720, 21456, 3, 23773, 14964, 39, 14757, 14179, 53, 13751
+ , 14928, 36, 15272, 12430, 79, 13228, 9135, 285, 9077, 28672
+ , 28672, 8377, 403, 7919, 26624, 28672, 23257, 7068, 560, 7473
+ , 20345, 19677, 6770, 720, 6464, 18697, 25189, 16249, 5779, 1087
+ , 5494, 15209, 22819, 30720, 20622, 12601, 5240, 1419, 5091, 12095
+ , 19408, 26624, 22819, 16805, 10683, 4812, 2056, 4293, 9836, 16026
+ , 24397, 25189, 18409, 13833, 8681, 4503, 2653, 4220, 8329, 13853
+ , 19132, 26624, 25189, 20771, 17219, 12630, 9520, 6733, 4565, 3657
+ , 4817, 7069, 10058, 13212, 16805, 21209, 26624, 26276, 28672, 28672
+ , 26276, 23257, 20173, 19282, 16538, 15051, 12811, 10754, 9267, 7547
+ , 6270, 5407, 5214, 6057, 7054, 8226, 9488, 10806, 12793, 14442
+ , 16442, 19677, 22099, 26276, 28672, 0, 30720, 0, 30720, 11920
+ , 56, 20720, 30720, 6766, 355, 13130, 30720, 30720, 22180, 5589
+ , 736, 7902, 26624, 30720, 7634, 354, 9721, 30720, 30720, 9027
+ , 246, 10117, 30720, 30720, 9630, 453, 6709, 23257, 30720, 25683
+ , 14228, 6127, 1271, 4615, 15178, 30720, 30720, 23504, 12382, 5739
+ , 2015, 3492, 10560, 22020, 26624, 30720, 30720, 23257, 13192, 4873
+ , 1527, 5001, 12445, 22020, 30720, 30720, 30720, 30720, 19344, 10761
+ , 4051, 1927, 5281, 10594, 17866, 28672, 30720, 30720, 30720, 21869
+ , 15554, 10060, 5979, 2710, 3085, 7889, 14646, 21725, 28672, 30720
+ , 30720, 30720, 30720, 30720, 30720, 30720, 22719, 17425, 13212, 8083
+ , 4439, 2820, 4305, 8136, 12988, 17425, 21151, 28672, 28672, 30720
+ , 30720, 30720, 28672, 20527, 19282, 14412, 10513, 7407, 5079, 3744
+ , 4115, 6308, 9621, 13599, 17040, 22349, 28672, 30720, 30720, 30720
+ , 30720, 30720, 30720, 29522, 19282, 14545, 11485, 9093, 6760, 5262
+ , 4672, 4970, 6005, 7852, 9732, 12343, 14672, 19161, 22819, 25189
+ , 30720, 30720, 28672, 30720, 30720, 20720, 18125, 14388, 12007, 9825
+ , 8092, 7064, 6069, 5903, 5932, 6359, 7169, 8310, 9324, 10711
+ , 11867, 13096, 14157, 16338, 17040, 19161, 21725, 23773, 30720, 30720
+ , 26276, 25426, 24397, 28672, 28672, 23257, 22020, 22349, 18297, 17646
+ , 16983, 16431, 16162, 15021, 15178, 13751, 12142, 10895, 10193, 9632
+ , 9086, 8896, 8823, 8735, 8591, 8754, 8649, 8361, 8329, 8522
+ , 8373, 8739, 8993, 9657, 10454, 11279, 11899, 12614, 14024, 14273
+ , 15477, 15240, 16649, 17866, 18697, 21151, 22099, 0
+ // The final 0 was added due to http://bugs.webrtc.org/10584.
+};
+
+/* left KLT transforms */
+const int16_t WebRtcIsacfix_kT1GainQ15[3][4] = {
+ { -26130, 19773, 19773, 26130 },
+ { -26664, 19046, 19046, 26664 },
+ { -23538, 22797, 22797, 23538 }
+};
+
+
+
+const int16_t WebRtcIsacfix_kT1ShapeQ15[3][324] = {
+ { 52,16,168,7,439,-138,-89,306,671,882,
+ 157,1301,291,1598,-3571,-1943,-1119,32404,96,-12,
+ 379,-64,-307,345,-836,539,1045,2541,-2865,-992,
+ 1683,-4717,5808,7427,30599,2319,183,-73,451,481,
+ 933,-198,781,-397,1244,-777,3690,-2414,149,-1356,
+ -2593,-31140,8289,-1737,-202,-14,-214,360,501,450,
+ -245,-7,797,3638,-2804,3042,-337,22137,-22103,2264,
+ 6838,-3381,305,172,263,-195,-355,351,179,513,
+ 2234,3343,5509,7531,19075,-17740,-16836,2244,-629,-1505,
+ -153,108,124,-324,2694,-124,1492,-850,5347,4285,
+ 7439,-10229,-22822,-12467,-12891,3645,822,-232,131,13,
+ 374,565,536,4681,1294,-1935,1926,-5734,-10643,26462,
+ -12480,-5589,-1038,-2468,964,-704,-247,-106,186,-558,
+ -4050,3760,2972,2141,-7393,6294,26740,11991,-3251,5461,
+ 5341,1574,2208,-51,-552,-297,-753,-154,2068,-5371,
+ 3578,4106,28043,-10533,8041,2353,2389,4609,3410,1906,
+ 351,-249,18,-15,1117,539,2870,9084,17585,-24528,
+ -366,-6490,2009,-3170,2942,1116,-232,1672,1065,606,
+ -399,-388,-518,38,3728,28948,-11936,4543,4104,-4441,
+ 1545,-4044,1485,622,-68,186,-473,135,-280,125,
+ -546,-1813,6989,6606,23711,19376,-2636,2870,-4553,-1687,
+ 878,-375,205,-208,-409,-108,-200,-45,-1670,-337,
+ 8213,-5524,-2334,5240,-12939,-26205,5937,-1582,-592,-959,
+ -5374,2449,3400,559,349,-492,668,12379,-27684,3419,
+ 5117,4415,-297,-8270,-1252,-3490,-1272,-1199,-3159,191,
+ 630,488,-797,-3071,12912,-27783,-10249,1047,647,619,
+ 111,-3722,-915,-1055,-502,5,-1384,-306,221,68,
+ 5219,13173,-26474,-11663,-5626,927,806,-1127,236,-589,
+ -522,-230,-312,-315,-428,-573,426,192,-11830,-26883,
+ -14121,-2785,-1429,-109,410,-832,-302,539,-459,104,
+ 1,-530,-202,-289,153,116,30082,-12944,-671,20,
+ 649,98,103,215,234,0,280,-51,-169,298,
+ 31,230,-73,-51
+ },
+ { -154,-7,-192,61,-739,-389,-947,-162,-60,94,
+ 511,-716,1520,-1428,4168,-2214,1816,32270,-123,-77,
+ -199,-99,-42,-588,203,-240,-930,-35,1580,234,
+ 3206,-5507,-1495,-10946,30000,-2667,-136,-176,-240,-175,
+ -204,-661,-1796,-1039,-1271,498,3143,734,2663,2699,
+ -8127,29333,10495,2356,-72,113,-91,118,-2840,-723,
+ -1733,-1158,-389,-2116,-3054,-3,-5179,8071,29546,6308,
+ 5657,-3178,-186,-294,-473,-635,1213,-983,-1437,-1715,
+ -1094,1280,-92,-9573,948,29576,-7060,-5921,2954,1349,
+ -337,-108,-1099,962,418,-413,-1149,-334,1241,3975,
+ -6825,26725,-14377,7051,-4772,-1707,2335,2008,-150,570,
+ 1371,42,-1649,-619,2039,3369,-1225,1583,-2755,-15207,
+ -27504,-4855,-4304,1495,2733,1324,15,-448,403,353,
+ 3016,-1242,2338,2673,2064,-7496,-30447,-3686,5833,-1301,
+ -2455,2122,1519,608,43,-653,773,-3072,912,-1537,
+ 4505,10284,30237,1549,3200,-691,205,1702,658,1014,
+ 1499,148,79,-322,-1162,-4639,-813,7536,3204,29109,
+ -10747,-26,1611,2286,2114,2561,1022,372,348,207,
+ 1062,-1088,-443,-9849,2381,5671,29097,-7612,-2927,3853,
+ 194,1155,275,1438,1438,1312,581,888,-784,906,
+ 112,-11103,25104,14438,-9311,-3068,1210,368,370,-940,
+ -2434,-1148,1925,392,657,258,-526,1475,-2281,-4265,
+ -1880,1534,2185,-1472,959,-30934,6306,3114,-4109,1768,
+ -2612,-703,45,644,2185,2033,5670,7211,19114,-22427,
+ 6432,5150,-4090,-2694,3860,1245,-596,293,1829,369,
+ -319,229,-3256,2170,-6374,-26216,-4570,-16053,-5766,-262,
+ -2006,2873,-1477,147,378,-1544,-344,-544,-985,-481,
+ 4210,4542,30757,-7291,-4863,1529,-2079,-628,-603,-783,
+ -408,1646,697,808,-620,-292,181,158,-13313,-29173,
+ 5984,-1262,859,-1776,-558,-24,-883,-1421,739,210,
+ -531,-285,131,-160,-246,-56,29345,-13706,-2859,-2966,
+ -300,-970,-2382,-268,-103,-636,-12,-62,-691,-253,
+ -147,-127,27,66
+ },
+ { 55,-212,-198,489,-274,81,682,399,328,-934,
+ -389,-37,1357,-3632,5276,6581,-9493,-29921,29,-45,
+ 2,190,172,-15,311,-130,-1085,-25,324,-684,
+ 3223,-6580,4485,-5280,-29521,9933,82,-320,-530,229,
+ -705,-533,-414,848,-1842,-4473,1390,-857,6717,-6692,
+ 4648,29397,576,8339,-68,-85,238,-330,264,-1012,
+ -381,-203,-3384,-3329,3906,6810,3790,-6250,28312,-8078,
+ 8089,1565,160,-569,-612,-613,-1063,-1928,-1125,3421,
+ -7481,-7484,4942,-6984,4330,-25591,-10574,-6982,5682,-1781,
+ -308,89,178,-1715,-420,-3530,-5776,1219,-8617,-7137,
+ 7015,4981,24875,12657,-5408,-3356,-785,-1972,326,-858,
+ -506,-3382,-986,-6258,-2259,4015,-8374,-10482,3127,23826,
+ -14126,-514,-5417,2178,-2912,-17,-587,80,67,-5881,
+ -1702,-5351,-4481,398,-10156,-225,20727,-15460,-11603,7752,
+ 3660,1714,-2001,-359,499,-527,-1225,-7820,-1297,-6326,
+ -8526,7900,-18328,13311,-17488,-2926,-196,-17,2281,873,
+ 480,-160,-624,471,780,-8729,1707,-14262,-20647,1721,
+ 18590,-2206,-1214,-1066,312,-2602,783,-412,-113,49,
+ -119,1305,-2371,-15132,-1833,-18252,20295,-8316,2227,341,
+ -2074,-702,3082,-262,-465,-198,430,30,-70,-788,
+ 2342,-25132,-4863,19783,-484,2137,2811,-1906,799,1586,
+ 962,-734,-191,-30,-129,-93,-1126,1729,5860,-2030,
+ 8953,603,-3338,-10869,-1144,22070,12130,10513,3191,-6881,
+ -3514,2090,711,-666,1843,-5997,-5681,2921,-17641,-2801,
+ 4969,18590,7169,12214,8587,4405,3008,-1074,-371,-77,
+ 253,331,-5611,5014,13152,-1985,18483,-1696,8043,20463,
+ 2381,-393,1688,-1205,618,1220,457,248,-83,176,
+ 7920,-13676,-22139,-3038,17402,2036,844,3258,994,719,
+ 2087,-44,426,494,12,-91,46,5,-14204,22912,
+ -18156,-361,442,2298,-829,2229,386,1433,1335,1323,
+ 55,-592,-139,49,-12,-57,27783,17134,350,-282,
+ 552,158,142,2488,465,329,1087,118,143,10,
+ 56,65,-15,-31
+ }
+};
+
+/* right KLT transforms */
+const int16_t WebRtcIsacfix_kT2GainQ15[3][36] = {
+ { 4775, -14892, 20313, -17104, 10533, -3613, -6782, 16044, -8889,
+ -11019, 21330, -10720, 13193, -15678, -11101, 14461, 12250, -13096,
+ -16951, 2167, 16066, 15569, -702, -16754, -19195, -12823, -4321,
+ 5128, 13348, 17825, 13232, 13404, 13494, 13490, 13383, 13261
+ },
+ { -3725, 11408, -18493, 20031, -13097, 3865, 9344, -19294, 10740,
+ 8856, -18432, 8982, 13975, -14444, -11930, 11774, 14285, -13594,
+ -16323, -4, 16340, 15609, 359, -17220, -18401, -13471, -4643,
+ 5225, 13375, 18053, 13124, 13463, 13621, 13583, 13393, 13072
+ },
+ { -3513, 11402, -17883, 19504, -14399, 4885, 8702, -19513, 12046,
+ 8533, -18110, 8447, 12778, -14838, -12444, 13177, 14107, -12759,
+ -17268, 914, 15822, 15661, 838, -16686, -18907, -12936, -4820,
+ 4175, 12398, 18830, 12913, 13215, 13433, 13572, 13601, 13518
+ }
+};
+
+const int16_t WebRtcIsacfix_kT2ShapeQ15[3][36] = {
+ { 4400, -11512, 17205, -19470, 14770, -5345, 9784, -19222, 11228,
+ 6842, -18371, 9909, 14191, -13496, -11563, 14015, 11827, -14839,
+ -15439, 948, 17802, 14827, -2053, -17132, 18723, 14516, 4135,
+ -6822, -13869, -16016, 12975, 13341, 13563, 13603, 13478, 13296
+ },
+ { 5420, -14215, 19060, -18073, 11709, -3911, 9645, -18335, 7717,
+ 10842, -19283, 9777, 14898, -12555, -13661, 11668, 13520, -13733,
+ -15936, -1358, 15671, 16728, 328, -17100, 17527, 13973, 5587,
+ -5194, -14165, -17677, 12970, 13446, 13693, 13660, 13462, 13015
+ },
+ { 4386, -12426, 18019, -18895, 13894, -5034, 9713, -19270, 10283,
+ 8692, -18439, 9317, 13992, -13454, -13241, 12850, 13366, -13336,
+ -16334, -498, 15976, 16213, -114, -16987, 18191, 13659, 4958,
+ -5116, -13444, -18021, 12911, 13424, 13718, 13674, 13464, 13054
+ }
+};
+
+/* means of log gains and LAR coefficients*/
+const int16_t WebRtcIsacfix_kMeansGainQ8[3][12] = {
+ { -1758, -1370, -1758, -1373, -1757, -1375,
+ -1758, -1374, -1758, -1373, -1755, -1370
+ },
+ { -1569, -1224, -1569, -1225, -1569, -1227,
+ -1569, -1226, -1567, -1225, -1565, -1224
+ },
+ { -1452, -957, -1447, -951, -1438, -944,
+ -1431, -938, -1419, -931, -1406, -926
+ }
+};
+
+
+const int32_t WebRtcIsacfix_kMeansShapeQ17[3][108] = {
+ { -119581, 34418, -44193, 11112, -4428, 18906, 9222, 8068, 1953, 5425,
+ 1871, 1689, 109933, 33751, 10471, -2566, 1090, 2320, -119219, 33728,
+ -43759, 11450, -4870, 19117, 9174, 8037, 1972, 5331, 1872, 1843,
+ 109899, 34301, 10629, -2316, 1272, 2562, -118608, 32318, -44012, 11591,
+ -4914, 18932, 9456, 8088, 1900, 5419, 1723, 1853, 109963, 35059,
+ 10745, -2335, 1161, 2520, -119174, 32107, -44462, 11635, -4694, 18611,
+ 9757, 8108, 1969, 5486, 1673, 1777, 109636, 34907, 10643, -2406,
+ 1034, 2420, -118597, 32320, -44590, 10854, -4569, 18821, 9701, 7866,
+ 2003, 5577, 1732, 1626, 109913, 34448, 10714, -2752, 990, 2228,
+ -118138, 32996, -44352, 10334, -3772, 18488, 9464, 7865, 2208, 5540,
+ 1745, 1664, 109880, 33381, 10640, -2779, 980, 2054
+ },
+ { -146328, 46370, 1047, 26431, 10035, 13933, 6415, 14359, -2368, 6661,
+ 2269, 1764, 96623, 7802, 4163, 10742, 1643, 2954, -146871, 46561, 1127,
+ 26225, 10113, 14096, 6771, 14323, -2037, 6788, 2297, 1761, 96324, 8382,
+ 4309, 10450, 1695, 3016, -146502, 46475, 1580, 26118, 10487, 14179, 6622,
+ 14439, -2034, 6757, 2342, 1761, 95869, 8966, 4347, 10358, 1999, 2855,
+ -146958, 47717, 826, 25952, 10263, 14061, 5266, 13681, -2417, 6582, 2047,
+ 1608, 96257, 9107, 4452, 10301, 1792, 2676, -146992, 47123, 446, 25822,
+ 10405, 14292, 5140, 13804, -2403, 6496, 1834, 1735, 97489, 9253, 4414,
+ 10684, 1549, 2721, -145811, 46182, 901, 26482, 10241, 14524, 6075, 14514,
+ -2147, 6691, 2196, 1899, 97011, 8178, 4102, 10758, 1638, 2869
+ },
+ { -166617, 46969, -43908, 17726, 6330, 25615, 6913, 5450, -2301, 1984,
+ 507, 2883, 149998, 28709, 19333, 16703, 11093, 8965, -168254, 46604,
+ -44315, 17862, 6474, 25746, 7018, 5373, -2343, 1930, 513, 2819, 150391,
+ 28627, 19194, 16678, 10998, 8929, -169093, 46084, -44767, 17427, 6401,
+ 25674, 7147, 5472, -2336, 1820, 491, 2802, 149860, 28430, 19064, 16524,
+ 10898, 8875, -170205, 46189, -44877, 17403, 6190, 25209, 7035, 5673, -2173,
+ 1894, 574, 2756, 148830, 28230, 18819, 16418, 10789, 8811, -171263, 45045,
+ -44834, 16858, 6103, 24726, 7014, 5713, -2103, 1877, 518, 2729, 147073,
+ 27744, 18629, 16277, 10690, 8703, -171720, 44153, -45062, 15951, 5872,
+ 24429, 7044, 5585, -2082, 1807, 519, 2769, 144791, 27402, 18490, 16126,
+ 10548, 8635
+ }
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
new file mode 100644
index 0000000000..6965822952
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
+
+#include <stdint.h>
+
+/* indices of KLT coefficients used */
+extern const uint16_t WebRtcIsacfix_kSelIndGain[12];
+
+extern const uint16_t WebRtcIsacfix_kSelIndShape[108];
+
+/* cdf array for model indicator */
+extern const uint16_t WebRtcIsacfix_kModelCdf[KLT_NUM_MODELS + 1];
+
+/* pointer to cdf array for model indicator */
+extern const uint16_t* WebRtcIsacfix_kModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const uint16_t WebRtcIsacfix_kModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const int16_t WebRtcIsacfix_kQuantMinGain[12];
+
+extern const int16_t WebRtcIsacfix_kQuantMinShape[108];
+
+/* maximum quantization index */
+extern const uint16_t WebRtcIsacfix_kMaxIndGain[12];
+
+extern const uint16_t WebRtcIsacfix_kMaxIndShape[108];
+
+/* index offset */
+extern const uint16_t WebRtcIsacfix_kOffsetGain[KLT_NUM_MODELS][12];
+
+extern const uint16_t WebRtcIsacfix_kOffsetShape[KLT_NUM_MODELS][108];
+
+/* initial cdf index for KLT coefficients */
+extern const uint16_t WebRtcIsacfix_kInitIndexGain[KLT_NUM_MODELS][12];
+
+extern const uint16_t WebRtcIsacfix_kInitIndexShape[KLT_NUM_MODELS][108];
+
+/* offsets for quantizer representation levels */
+extern const uint16_t WebRtcIsacfix_kOfLevelsGain[3];
+
+extern const uint16_t WebRtcIsacfix_kOfLevelsShape[3];
+
+/* quantizer representation levels */
+extern const int32_t WebRtcIsacfix_kLevelsGainQ17[1176];
+
+extern const int16_t WebRtcIsacfix_kLevelsShapeQ10[1735];
+
+/* cdf tables for quantizer indices */
+extern const uint16_t WebRtcIsacfix_kCdfGain[1212];
+
+extern const uint16_t WebRtcIsacfix_kCdfShape[2059];
+
+/* pointers to cdf tables for quantizer indices */
+extern const uint16_t* WebRtcIsacfix_kCdfGainPtr[KLT_NUM_MODELS][12];
+
+extern const uint16_t* WebRtcIsacfix_kCdfShapePtr[KLT_NUM_MODELS][108];
+
+/* code length for all coefficients using different models */
+extern const int16_t WebRtcIsacfix_kCodeLenGainQ11[392];
+
+extern const int16_t WebRtcIsacfix_kCodeLenShapeQ11[578];
+
+/* left KLT transforms */
+extern const int16_t WebRtcIsacfix_kT1GainQ15[KLT_NUM_MODELS][4];
+
+extern const int16_t WebRtcIsacfix_kT1ShapeQ15[KLT_NUM_MODELS][324];
+
+/* right KLT transforms */
+extern const int16_t WebRtcIsacfix_kT2GainQ15[KLT_NUM_MODELS][36];
+
+extern const int16_t WebRtcIsacfix_kT2ShapeQ15[KLT_NUM_MODELS][36];
+
+/* means of log gains and LAR coefficients */
+extern const int16_t WebRtcIsacfix_kMeansGainQ8[KLT_NUM_MODELS][12];
+
+extern const int32_t WebRtcIsacfix_kMeansShapeQ17[3][108];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c
new file mode 100644
index 0000000000..78cb93f7ae
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/compile_assert_c.h"
+
+/* log2[0.2, 0.5, 0.98] in Q8 */
+static const int16_t kLogLagWinQ8[3] = {
+ -594, -256, -7
+};
+
+/* [1 -0.75 0.25] in Q12 */
+static const int16_t kACoefQ12[3] = {
+ 4096, -3072, 1024
+};
+
+int32_t WebRtcIsacfix_Log2Q8(uint32_t x) {
+ int32_t zeros;
+ int16_t frac;
+
+ zeros=WebRtcSpl_NormU32(x);
+ frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23);
+ /* log2(magn(i)) */
+
+ return ((31 - zeros) << 8) + frac;
+}
+
+static __inline int16_t Exp2Q10(int16_t x) { // Both in and out in Q10
+
+ int16_t tmp16_1, tmp16_2;
+
+ tmp16_2=(int16_t)(0x0400|(x&0x03FF));
+ tmp16_1 = -(x >> 10);
+ if(tmp16_1>0)
+ return tmp16_2 >> tmp16_1;
+ else
+ return tmp16_2 << -tmp16_1;
+
+}
+
+
+
+/* 1D parabolic interpolation . All input and output values are in Q8 */
+static __inline void Intrp1DQ8(int32_t *x, int32_t *fx, int32_t *y, int32_t *fy) {
+
+ int16_t sign1=1, sign2=1;
+ int32_t r32, q32, t32, nom32, den32;
+ int16_t t16, tmp16, tmp16_1;
+
+ if ((fx[0]>0) && (fx[2]>0)) {
+ r32=fx[1]-fx[2];
+ q32=fx[0]-fx[1];
+ nom32=q32+r32;
+ den32 = (q32 - r32) * 2;
+ if (nom32<0)
+ sign1=-1;
+ if (den32<0)
+ sign2=-1;
+
+ /* t = (q32+r32)/(2*(q32-r32)) = (fx[0]-fx[1] + fx[1]-fx[2])/(2 * fx[0]-fx[1] - (fx[1]-fx[2]))*/
+ /* (Signs are removed because WebRtcSpl_DivResultInQ31 can't handle negative numbers) */
+ /* t in Q31, without signs */
+ t32 = WebRtcSpl_DivResultInQ31(nom32 * sign1, den32 * sign2);
+
+ t16 = (int16_t)(t32 >> 23); /* Q8 */
+ t16=t16*sign1*sign2; /* t in Q8 with signs */
+
+ *y = x[0]+t16; /* Q8 */
+ // *y = x[1]+t16; /* Q8 */
+
+ /* The following code calculates fy in three steps */
+ /* fy = 0.5 * t * (t-1) * fx[0] + (1-t*t) * fx[1] + 0.5 * t * (t+1) * fx[2]; */
+
+ /* Part I: 0.5 * t * (t-1) * fx[0] */
+ tmp16_1 = (int16_t)(t16 * t16); /* Q8*Q8=Q16 */
+ tmp16_1 >>= 2; /* Q16>>2 = Q14 */
+ t16 <<= 6; /* Q8<<6 = Q14 */
+ tmp16 = tmp16_1-t16;
+ *fy = WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[0]); /* (Q14 * Q8 >>15)/2 = Q8 */
+
+ /* Part II: (1-t*t) * fx[1] */
+ tmp16 = 16384-tmp16_1; /* 1 in Q14 - Q14 */
+ *fy += WEBRTC_SPL_MUL_16_32_RSFT14(tmp16, fx[1]);/* Q14 * Q8 >> 14 = Q8 */
+
+ /* Part III: 0.5 * t * (t+1) * fx[2] */
+ tmp16 = tmp16_1+t16;
+ *fy += WEBRTC_SPL_MUL_16_32_RSFT15(tmp16, fx[2]);/* (Q14 * Q8 >>15)/2 = Q8 */
+ } else {
+ *y = x[0];
+ *fy= fx[1];
+ }
+}
+
+
+static void FindFour32(int32_t *in, int16_t length, int16_t *bestind)
+{
+ int32_t best[4]= {-100, -100, -100, -100};
+ int16_t k;
+
+ for (k=0; k<length; k++) {
+ if (in[k] > best[3]) {
+ if (in[k] > best[2]) {
+ if (in[k] > best[1]) {
+ if (in[k] > best[0]) { // The Best
+ best[3] = best[2];
+ bestind[3] = bestind[2];
+ best[2] = best[1];
+ bestind[2] = bestind[1];
+ best[1] = best[0];
+ bestind[1] = bestind[0];
+ best[0] = in[k];
+ bestind[0] = k;
+ } else { // 2nd best
+ best[3] = best[2];
+ bestind[3] = bestind[2];
+ best[2] = best[1];
+ bestind[2] = bestind[1];
+ best[1] = in[k];
+ bestind[1] = k;
+ }
+ } else { // 3rd best
+ best[3] = best[2];
+ bestind[3] = bestind[2];
+ best[2] = in[k];
+ bestind[2] = k;
+ }
+ } else { // 4th best
+ best[3] = in[k];
+ bestind[3] = k;
+ }
+ }
+ }
+}
+
+
+
+
+
+extern void WebRtcIsacfix_PCorr2Q32(const int16_t *in, int32_t *logcorQ8);
+
+
+
+void WebRtcIsacfix_InitialPitch(const int16_t *in, /* Q0 */
+ PitchAnalysisStruct *State,
+ int16_t *lagsQ7 /* Q7 */
+ )
+{
+ int16_t buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
+ int32_t *crrvecQ8_1,*crrvecQ8_2;
+ int32_t cv1q[PITCH_LAG_SPAN2+2],cv2q[PITCH_LAG_SPAN2+2], peakvq[PITCH_LAG_SPAN2+2];
+ int k;
+ int16_t peaks_indq;
+ int16_t peakiq[PITCH_LAG_SPAN2];
+ int32_t corr;
+ int32_t corr32, corr_max32, corr_max_o32;
+ int16_t npkq;
+ int16_t best4q[4]={0,0,0,0};
+ int32_t xq[3],yq[1],fyq[1];
+ int32_t *fxq;
+ int32_t best_lag1q, best_lag2q;
+ int32_t tmp32a,tmp32b,lag32,ratq;
+ int16_t start;
+ int16_t oldgQ12, tmp16a, tmp16b, gain_bias16,tmp16c, tmp16d, bias16;
+ int32_t tmp32c,tmp32d, tmp32e;
+ int16_t old_lagQ;
+ int32_t old_lagQ8;
+ int32_t lagsQ8[4];
+
+ old_lagQ = State->PFstr_wght.oldlagQ7; // Q7
+ old_lagQ8 = old_lagQ << 1; // Q8
+
+ oldgQ12= State->PFstr_wght.oldgainQ12;
+
+ crrvecQ8_1=&cv1q[1];
+ crrvecQ8_2=&cv2q[1];
+
+
+ /* copy old values from state buffer */
+ memcpy(buf_dec16, State->dec_buffer16, sizeof(State->dec_buffer16));
+
+ /* decimation; put result after the old values */
+ WebRtcIsacfix_DecimateAllpass32(in, State->decimator_state32, PITCH_FRAME_LEN,
+ &buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
+
+ /* low-pass filtering */
+ start= PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2;
+ WebRtcSpl_FilterARFastQ12(&buf_dec16[start],&buf_dec16[start],(int16_t*)kACoefQ12,3, PITCH_FRAME_LEN/2);
+
+ /* copy end part back into state buffer */
+ for (k = 0; k < (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2); k++)
+ State->dec_buffer16[k] = buf_dec16[k+PITCH_FRAME_LEN/2];
+
+
+ /* compute correlation for first and second half of the frame */
+ WebRtcIsacfix_PCorr2Q32(buf_dec16, crrvecQ8_1);
+ WebRtcIsacfix_PCorr2Q32(buf_dec16 + PITCH_CORR_STEP2, crrvecQ8_2);
+
+
+ /* bias towards pitch lag of previous frame */
+ tmp32a = WebRtcIsacfix_Log2Q8((uint32_t) old_lagQ8) - 2304;
+ // log2(0.5*oldlag) in Q8
+ tmp32b = oldgQ12 * oldgQ12 >> 10; // Q12 & * 4.0;
+ gain_bias16 = (int16_t) tmp32b; //Q12
+ if (gain_bias16 > 3276) gain_bias16 = 3276; // 0.8 in Q12
+
+
+ for (k = 0; k < PITCH_LAG_SPAN2; k++)
+ {
+ if (crrvecQ8_1[k]>0) {
+ tmp32b = WebRtcIsacfix_Log2Q8((uint32_t) (k + (PITCH_MIN_LAG/2-2)));
+ tmp16a = (int16_t) (tmp32b - tmp32a); // Q8 & fabs(ratio)<4
+ tmp32c = tmp16a * tmp16a >> 6; // Q10
+ tmp16b = (int16_t) tmp32c; // Q10 & <8
+ tmp32d = tmp16b * 177 >> 8; // mult with ln2 in Q8
+ tmp16c = (int16_t) tmp32d; // Q10 & <4
+ tmp16d = Exp2Q10((int16_t) -tmp16c); //Q10
+ tmp32c = gain_bias16 * tmp16d >> 13; // Q10 & * 0.5
+ bias16 = (int16_t) (1024 + tmp32c); // Q10
+ tmp32b = WebRtcIsacfix_Log2Q8((uint32_t)bias16) - 2560;
+ // Q10 in -> Q8 out with 10*2^8 offset
+ crrvecQ8_1[k] += tmp32b ; // -10*2^8 offset
+ }
+ }
+
+ /* taper correlation functions */
+ for (k = 0; k < 3; k++) {
+ crrvecQ8_1[k] += kLogLagWinQ8[k];
+ crrvecQ8_2[k] += kLogLagWinQ8[k];
+
+ crrvecQ8_1[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
+ crrvecQ8_2[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k];
+ }
+
+
+ /* Make zeropadded corr vectors */
+ cv1q[0]=0;
+ cv2q[0]=0;
+ cv1q[PITCH_LAG_SPAN2+1]=0;
+ cv2q[PITCH_LAG_SPAN2+1]=0;
+ corr_max32 = 0;
+
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+
+
+ corr32=crrvecQ8_1[k-1];
+ if (corr32 > corr_max32)
+ corr_max32 = corr32;
+
+ corr32=crrvecQ8_2[k-1];
+ corr32 += -4; // Compensate for later (log2(0.99))
+
+ if (corr32 > corr_max32)
+ corr_max32 = corr32;
+
+ }
+
+ /* threshold value to qualify as a peak */
+ // corr_max32 += -726; // log(0.14)/log(2.0) in Q8
+ corr_max32 += -1000; // log(0.14)/log(2.0) in Q8
+ corr_max_o32 = corr_max32;
+
+
+ /* find peaks in corr1 */
+ peaks_indq = 0;
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+ corr32=cv1q[k];
+ if (corr32>corr_max32) { // Disregard small peaks
+ if ((corr32>=cv1q[k-1]) && (corr32>cv1q[k+1])) { // Peak?
+ peakvq[peaks_indq] = corr32;
+ peakiq[peaks_indq++] = k;
+ }
+ }
+ }
+
+
+ /* find highest interpolated peak */
+ corr_max32=0;
+ best_lag1q =0;
+ if (peaks_indq > 0) {
+ FindFour32(peakvq, (int16_t) peaks_indq, best4q);
+ npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
+
+ for (k=0;k<npkq;k++) {
+
+ lag32 = peakiq[best4q[k]];
+ fxq = &cv1q[peakiq[best4q[k]]-1];
+ xq[0]= lag32;
+ xq[0] <<= 8;
+ Intrp1DQ8(xq, fxq, yq, fyq);
+
+ tmp32a= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
+ /* Bias towards short lags */
+ /* log(pow(0.8, log(2.0 * *y )))/log(2.0) */
+ tmp32b = (int16_t)tmp32a * -42 >> 8;
+ tmp32c= tmp32b + 256;
+ *fyq += tmp32c;
+ if (*fyq > corr_max32) {
+ corr_max32 = *fyq;
+ best_lag1q = *yq;
+ }
+ }
+ tmp32b = (best_lag1q - OFFSET_Q8) * 2;
+ lagsQ8[0] = tmp32b + PITCH_MIN_LAG_Q8;
+ lagsQ8[1] = lagsQ8[0];
+ } else {
+ lagsQ8[0] = old_lagQ8;
+ lagsQ8[1] = lagsQ8[0];
+ }
+
+ /* Bias towards constant pitch */
+ tmp32a = lagsQ8[0] - PITCH_MIN_LAG_Q8;
+ ratq = (tmp32a >> 1) + OFFSET_Q8;
+
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+ tmp32a = k << 7; // 0.5*k Q8
+ tmp32b = tmp32a * 2 - ratq; // Q8
+ tmp32c = (int16_t)tmp32b * (int16_t)tmp32b >> 8; // Q8
+
+ tmp32b = tmp32c + (ratq >> 1);
+ // (k-r)^2 + 0.5 * r Q8
+ tmp32c = WebRtcIsacfix_Log2Q8((uint32_t)tmp32a) - 2048;
+ // offset 8*2^8 , log2(0.5*k) Q8
+ tmp32d = WebRtcIsacfix_Log2Q8((uint32_t)tmp32b) - 2048;
+ // offset 8*2^8 , log2(0.5*k) Q8
+ tmp32e = tmp32c - tmp32d;
+
+ cv2q[k] += tmp32e >> 1;
+
+ }
+
+ /* find peaks in corr2 */
+ corr_max32 = corr_max_o32;
+ peaks_indq = 0;
+
+ for (k = 1; k <= PITCH_LAG_SPAN2; k++)
+ {
+ corr=cv2q[k];
+ if (corr>corr_max32) { // Disregard small peaks
+ if ((corr>=cv2q[k-1]) && (corr>cv2q[k+1])) { // Peak?
+ peakvq[peaks_indq] = corr;
+ peakiq[peaks_indq++] = k;
+ }
+ }
+ }
+
+
+
+ /* find highest interpolated peak */
+ corr_max32 = 0;
+ best_lag2q =0;
+ if (peaks_indq > 0) {
+
+ FindFour32(peakvq, (int16_t) peaks_indq, best4q);
+ npkq = WEBRTC_SPL_MIN(peaks_indq, 4);
+ for (k=0;k<npkq;k++) {
+
+ lag32 = peakiq[best4q[k]];
+ fxq = &cv2q[peakiq[best4q[k]]-1];
+
+ xq[0]= lag32;
+ xq[0] <<= 8;
+ Intrp1DQ8(xq, fxq, yq, fyq);
+
+ /* Bias towards short lags */
+ /* log(pow(0.8, log(2.0f * *y )))/log(2.0f) */
+ tmp32a= WebRtcIsacfix_Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8
+ tmp32b = (int16_t)tmp32a * -82 >> 8;
+ tmp32c= tmp32b + 256;
+ *fyq += tmp32c;
+ if (*fyq > corr_max32) {
+ corr_max32 = *fyq;
+ best_lag2q = *yq;
+ }
+ }
+
+ tmp32b = (best_lag2q - OFFSET_Q8) * 2;
+ lagsQ8[2] = tmp32b + PITCH_MIN_LAG_Q8;
+ lagsQ8[3] = lagsQ8[2];
+ } else {
+ lagsQ8[2] = lagsQ8[0];
+ lagsQ8[3] = lagsQ8[0];
+ }
+
+ lagsQ7[0] = (int16_t)(lagsQ8[0] >> 1);
+ lagsQ7[1] = (int16_t)(lagsQ8[1] >> 1);
+ lagsQ7[2] = (int16_t)(lagsQ8[2] >> 1);
+ lagsQ7[3] = (int16_t)(lagsQ8[3] >> 1);
+}
+
+
+
+void WebRtcIsacfix_PitchAnalysis(const int16_t *inn, /* PITCH_FRAME_LEN samples */
+ int16_t *outQ0, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ int16_t *PitchLags_Q7,
+ int16_t *PitchGains_Q12)
+{
+ int16_t inbufQ0[PITCH_FRAME_LEN + QLOOKAHEAD];
+ int16_t k;
+
+ /* inital pitch estimate */
+ WebRtcIsacfix_InitialPitch(inn, State, PitchLags_Q7);
+
+
+ /* Calculate gain */
+ WebRtcIsacfix_PitchFilterGains(inn, &(State->PFstr_wght), PitchLags_Q7, PitchGains_Q12);
+
+ /* concatenate previous input's end and current input */
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ inbufQ0[k] = State->inbuf[k];
+ }
+ for (k = 0; k < PITCH_FRAME_LEN; k++) {
+ inbufQ0[k+QLOOKAHEAD] = (int16_t) inn[k];
+ }
+
+ /* lookahead pitch filtering for masking analysis */
+ WebRtcIsacfix_PitchFilter(inbufQ0, outQ0, &(State->PFstr), PitchLags_Q7,PitchGains_Q12, 2);
+
+
+ /* store last part of input */
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ State->inbuf[k] = inbufQ0[k + PITCH_FRAME_LEN];
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h
new file mode 100644
index 0000000000..4303c82711
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_estimator.h
+ *
+ * Pitch functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_
+
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+
+void WebRtcIsacfix_PitchAnalysis(
+ const int16_t* in, /* PITCH_FRAME_LEN samples */
+ int16_t* outQ0, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct* State,
+ int16_t* lagsQ7,
+ int16_t* PitchGains_Q12);
+
+void WebRtcIsacfix_InitialPitch(const int16_t* in,
+ PitchAnalysisStruct* State,
+ int16_t* qlags);
+
+void WebRtcIsacfix_PitchFilter(int16_t* indatFix,
+ int16_t* outdatQQ,
+ PitchFiltstr* pfp,
+ int16_t* lagsQ7,
+ int16_t* gainsQ12,
+ int16_t type);
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+ int16_t gain,
+ size_t index,
+ int16_t sign,
+ int16_t* inputState,
+ int16_t* outputBuff2,
+ const int16_t* coefficient,
+ int16_t* inputBuf,
+ int16_t* outputBuf,
+ int* index2);
+
+void WebRtcIsacfix_PitchFilterGains(const int16_t* indatQ0,
+ PitchFiltstr* pfp,
+ int16_t* lagsQ7,
+ int16_t* gainsQ12);
+
+void WebRtcIsacfix_DecimateAllpass32(
+ const int16_t* in,
+ int32_t* state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ int16_t N, /* number of input samples */
+ int16_t* out); /* array of size N/2 */
+
+int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
+
+void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_ESTIMATOR_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c
new file mode 100644
index 0000000000..c4af9ab32a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_c.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+#ifdef WEBRTC_HAS_NEON
+#include <arm_neon.h>
+#endif
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/compile_assert_c.h"
+
+extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
+
+void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
+ int16_t scaling,n,k;
+ int32_t csum32, lys, lcs;
+ int64_t ysum64;
+ const int32_t oneQ8 = 1 << 8; // 1.00 in Q8
+ const int16_t* x;
+ const int16_t* inptr;
+
+ x = in + PITCH_MAX_LAG / 2 + 2;
+ scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
+ PITCH_CORR_LEN2,
+ PITCH_CORR_LEN2);
+ ysum64 = 1;
+ csum32 = 0;
+ x = in + PITCH_MAX_LAG / 2 + 2;
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ ysum64 += in[n] * in[n] >> scaling; // Q0
+ csum32 += x[n] * in[n] >> scaling; // Q0
+ }
+ logcorQ8 += PITCH_LAG_SPAN2 - 1;
+ lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum64) >> 1; // Q8, sqrt(ysum)
+ if (csum32 > 0) {
+ lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32); // 2log(csum) in Q8
+ if (lcs > (lys + oneQ8)) { // csum/sqrt(ysum) > 2 in Q8
+ *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum))
+ } else {
+ *logcorQ8 = oneQ8; // 1.00
+ }
+ } else {
+ *logcorQ8 = 0;
+ }
+
+
+ for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+ inptr = &in[k];
+ ysum64 -= in[k - 1] * in[k - 1] >> scaling;
+ ysum64 += (int32_t)(in[PITCH_CORR_LEN2 + k - 1])
+ * in[PITCH_CORR_LEN2 + k - 1] >> scaling;
+
+#ifdef WEBRTC_HAS_NEON
+ {
+ int32_t vbuff[4];
+ int32x4_t int_32x4_sum = vmovq_n_s32(0);
+ // Can't shift a Neon register to right with a non-constant shift value.
+ int32x4_t int_32x4_scale = vdupq_n_s32(-scaling);
+ // Assert a codition used in loop unrolling at compile-time.
+ RTC_COMPILE_ASSERT(PITCH_CORR_LEN2 %4 == 0);
+
+ for (n = 0; n < PITCH_CORR_LEN2; n += 4) {
+ int16x4_t int_16x4_x = vld1_s16(&x[n]);
+ int16x4_t int_16x4_in = vld1_s16(&inptr[n]);
+ int32x4_t int_32x4 = vmull_s16(int_16x4_x, int_16x4_in);
+ int_32x4 = vshlq_s32(int_32x4, int_32x4_scale);
+ int_32x4_sum = vaddq_s32(int_32x4_sum, int_32x4);
+ }
+
+ // Use vector store to avoid long stall from data trasferring
+ // from vector to general register.
+ vst1q_s32(vbuff, int_32x4_sum);
+ csum32 = vbuff[0] + vbuff[1];
+ csum32 += vbuff[2];
+ csum32 += vbuff[3];
+ }
+#else
+ int64_t csum64_tmp = 0;
+ if(scaling == 0) {
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ csum64_tmp += (int32_t)(x[n]) * inptr[n];
+ }
+ } else {
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ csum64_tmp += ((int32_t)(x[n]) * inptr[n]) >> scaling;
+ }
+ }
+ csum32 = csum64_tmp;
+#endif
+
+ logcorQ8--;
+
+ lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum64) >> 1; // Q8, sqrt(ysum)
+
+ if (csum32 > 0) {
+ lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32); // 2log(csum) in Q8
+ if (lcs > (lys + oneQ8)) { // csum/sqrt(ysum) > 2
+ *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum))
+ } else {
+ *logcorQ8 = oneQ8; // 1.00
+ }
+ } else {
+ *logcorQ8 = 0;
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c
new file mode 100644
index 0000000000..4ead84c492
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator_mips.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/compile_assert_c.h"
+
+extern int32_t WebRtcIsacfix_Log2Q8(uint32_t x);
+
+void WebRtcIsacfix_PCorr2Q32(const int16_t* in, int32_t* logcorQ8) {
+ int16_t scaling,n,k;
+ int32_t ysum32,csum32, lys, lcs;
+ const int32_t oneQ8 = 1 << 8; // 1.00 in Q8
+ const int16_t* x;
+ const int16_t* inptr;
+
+ x = in + PITCH_MAX_LAG / 2 + 2;
+ scaling = WebRtcSpl_GetScalingSquare((int16_t*)in,
+ PITCH_CORR_LEN2,
+ PITCH_CORR_LEN2);
+ ysum32 = 1;
+ csum32 = 0;
+ x = in + PITCH_MAX_LAG / 2 + 2;
+ {
+ const int16_t* tmp_x = x;
+ const int16_t* tmp_in = in;
+ int32_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+ n = PITCH_CORR_LEN2;
+ RTC_COMPILE_ASSERT(PITCH_CORR_LEN2 % 4 == 0);
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "1: \n\t"
+ "lh %[tmp1], 0(%[tmp_in]) \n\t"
+ "lh %[tmp2], 2(%[tmp_in]) \n\t"
+ "lh %[tmp3], 4(%[tmp_in]) \n\t"
+ "lh %[tmp4], 6(%[tmp_in]) \n\t"
+ "lh %[tmp5], 0(%[tmp_x]) \n\t"
+ "lh %[tmp6], 2(%[tmp_x]) \n\t"
+ "lh %[tmp7], 4(%[tmp_x]) \n\t"
+ "lh %[tmp8], 6(%[tmp_x]) \n\t"
+ "mul %[tmp5], %[tmp1], %[tmp5] \n\t"
+ "mul %[tmp1], %[tmp1], %[tmp1] \n\t"
+ "mul %[tmp6], %[tmp2], %[tmp6] \n\t"
+ "mul %[tmp2], %[tmp2], %[tmp2] \n\t"
+ "mul %[tmp7], %[tmp3], %[tmp7] \n\t"
+ "mul %[tmp3], %[tmp3], %[tmp3] \n\t"
+ "mul %[tmp8], %[tmp4], %[tmp8] \n\t"
+ "mul %[tmp4], %[tmp4], %[tmp4] \n\t"
+ "addiu %[n], %[n], -4 \n\t"
+ "srav %[tmp5], %[tmp5], %[scaling] \n\t"
+ "srav %[tmp1], %[tmp1], %[scaling] \n\t"
+ "srav %[tmp6], %[tmp6], %[scaling] \n\t"
+ "srav %[tmp2], %[tmp2], %[scaling] \n\t"
+ "srav %[tmp7], %[tmp7], %[scaling] \n\t"
+ "srav %[tmp3], %[tmp3], %[scaling] \n\t"
+ "srav %[tmp8], %[tmp8], %[scaling] \n\t"
+ "srav %[tmp4], %[tmp4], %[scaling] \n\t"
+ "addu %[ysum32], %[ysum32], %[tmp1] \n\t"
+ "addu %[csum32], %[csum32], %[tmp5] \n\t"
+ "addu %[ysum32], %[ysum32], %[tmp2] \n\t"
+ "addu %[csum32], %[csum32], %[tmp6] \n\t"
+ "addu %[ysum32], %[ysum32], %[tmp3] \n\t"
+ "addu %[csum32], %[csum32], %[tmp7] \n\t"
+ "addu %[ysum32], %[ysum32], %[tmp4] \n\t"
+ "addu %[csum32], %[csum32], %[tmp8] \n\t"
+ "addiu %[tmp_in], %[tmp_in], 8 \n\t"
+ "bgtz %[n], 1b \n\t"
+ " addiu %[tmp_x], %[tmp_x], 8 \n\t"
+ ".set pop \n\t"
+ : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
+ [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
+ [tmp7] "=&r" (tmp7), [tmp8] "=&r" (tmp8), [tmp_in] "+r" (tmp_in),
+ [ysum32] "+r" (ysum32), [tmp_x] "+r" (tmp_x), [csum32] "+r" (csum32),
+ [n] "+r" (n)
+ : [scaling] "r" (scaling)
+ : "memory", "hi", "lo"
+ );
+ }
+ logcorQ8 += PITCH_LAG_SPAN2 - 1;
+ lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32) >> 1; // Q8, sqrt(ysum)
+ if (csum32 > 0) {
+ lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32); // 2log(csum) in Q8
+ if (lcs > (lys + oneQ8)) { // csum/sqrt(ysum) > 2 in Q8
+ *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum))
+ } else {
+ *logcorQ8 = oneQ8; // 1.00
+ }
+ } else {
+ *logcorQ8 = 0;
+ }
+
+ for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+ inptr = &in[k];
+ const int16_t* tmp_in1 = &in[k - 1];
+ const int16_t* tmp_in2 = &in[PITCH_CORR_LEN2 + k - 1];
+ const int16_t* tmp_x = x;
+ int32_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+ n = PITCH_CORR_LEN2;
+ csum32 = 0;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "lh %[tmp1], 0(%[tmp_in1]) \n\t"
+ "lh %[tmp2], 0(%[tmp_in2]) \n\t"
+ "mul %[tmp1], %[tmp1], %[tmp1] \n\t"
+ "mul %[tmp2], %[tmp2], %[tmp2] \n\t"
+ "srav %[tmp1], %[tmp1], %[scaling] \n\t"
+ "srav %[tmp2], %[tmp2], %[scaling] \n\t"
+ "subu %[ysum32], %[ysum32], %[tmp1] \n\t"
+ "bnez %[scaling], 2f \n\t"
+ " addu %[ysum32], %[ysum32], %[tmp2] \n\t"
+ "1: \n\t"
+ "lh %[tmp1], 0(%[inptr]) \n\t"
+ "lh %[tmp2], 0(%[tmp_x]) \n\t"
+ "lh %[tmp3], 2(%[inptr]) \n\t"
+ "lh %[tmp4], 2(%[tmp_x]) \n\t"
+ "lh %[tmp5], 4(%[inptr]) \n\t"
+ "lh %[tmp6], 4(%[tmp_x]) \n\t"
+ "lh %[tmp7], 6(%[inptr]) \n\t"
+ "lh %[tmp8], 6(%[tmp_x]) \n\t"
+ "mul %[tmp1], %[tmp1], %[tmp2] \n\t"
+ "mul %[tmp2], %[tmp3], %[tmp4] \n\t"
+ "mul %[tmp3], %[tmp5], %[tmp6] \n\t"
+ "mul %[tmp4], %[tmp7], %[tmp8] \n\t"
+ "addiu %[n], %[n], -4 \n\t"
+ "addiu %[inptr], %[inptr], 8 \n\t"
+ "addiu %[tmp_x], %[tmp_x], 8 \n\t"
+ "addu %[csum32], %[csum32], %[tmp1] \n\t"
+ "addu %[csum32], %[csum32], %[tmp2] \n\t"
+ "addu %[csum32], %[csum32], %[tmp3] \n\t"
+ "bgtz %[n], 1b \n\t"
+ " addu %[csum32], %[csum32], %[tmp4] \n\t"
+ "b 3f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+ "lh %[tmp1], 0(%[inptr]) \n\t"
+ "lh %[tmp2], 0(%[tmp_x]) \n\t"
+ "lh %[tmp3], 2(%[inptr]) \n\t"
+ "lh %[tmp4], 2(%[tmp_x]) \n\t"
+ "lh %[tmp5], 4(%[inptr]) \n\t"
+ "lh %[tmp6], 4(%[tmp_x]) \n\t"
+ "lh %[tmp7], 6(%[inptr]) \n\t"
+ "lh %[tmp8], 6(%[tmp_x]) \n\t"
+ "mul %[tmp1], %[tmp1], %[tmp2] \n\t"
+ "mul %[tmp2], %[tmp3], %[tmp4] \n\t"
+ "mul %[tmp3], %[tmp5], %[tmp6] \n\t"
+ "mul %[tmp4], %[tmp7], %[tmp8] \n\t"
+ "addiu %[n], %[n], -4 \n\t"
+ "addiu %[inptr], %[inptr], 8 \n\t"
+ "addiu %[tmp_x], %[tmp_x], 8 \n\t"
+ "srav %[tmp1], %[tmp1], %[scaling] \n\t"
+ "srav %[tmp2], %[tmp2], %[scaling] \n\t"
+ "srav %[tmp3], %[tmp3], %[scaling] \n\t"
+ "srav %[tmp4], %[tmp4], %[scaling] \n\t"
+ "addu %[csum32], %[csum32], %[tmp1] \n\t"
+ "addu %[csum32], %[csum32], %[tmp2] \n\t"
+ "addu %[csum32], %[csum32], %[tmp3] \n\t"
+ "bgtz %[n], 2b \n\t"
+ " addu %[csum32], %[csum32], %[tmp4] \n\t"
+ "3: \n\t"
+ ".set pop \n\t"
+ : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3),
+ [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6),
+ [tmp7] "=&r" (tmp7), [tmp8] "=&r" (tmp8), [inptr] "+r" (inptr),
+ [csum32] "+r" (csum32), [tmp_x] "+r" (tmp_x), [ysum32] "+r" (ysum32),
+ [n] "+r" (n)
+ : [tmp_in1] "r" (tmp_in1), [tmp_in2] "r" (tmp_in2),
+ [scaling] "r" (scaling)
+ : "memory", "hi", "lo"
+ );
+
+ logcorQ8--;
+ lys = WebRtcIsacfix_Log2Q8((uint32_t)ysum32) >> 1; // Q8, sqrt(ysum)
+ if (csum32 > 0) {
+ lcs = WebRtcIsacfix_Log2Q8((uint32_t)csum32); // 2log(csum) in Q8
+ if (lcs > (lys + oneQ8)) { // csum/sqrt(ysum) > 2
+ *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum))
+ } else {
+ *logcorQ8 = oneQ8; // 1.00
+ }
+ } else {
+ *logcorQ8 = 0;
+ }
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
new file mode 100644
index 0000000000..735533020e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
+#include "rtc_base/compile_assert_c.h"
+
+// Number of segments in a pitch subframe.
+static const int kSegments = 5;
+
+// A division factor of 1/5 in Q15.
+static const int16_t kDivFactor = 6553;
+
+// Interpolation coefficients; generated by design_pitch_filter.m.
+// Coefficients are stored in Q14.
+static const int16_t kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
+ {-367, 1090, -2706, 9945, 10596, -3318, 1626, -781, 287},
+ {-325, 953, -2292, 7301, 12963, -3320, 1570, -743, 271},
+ {-240, 693, -1622, 4634, 14809, -2782, 1262, -587, 212},
+ {-125, 358, -817, 2144, 15982, -1668, 721, -329, 118},
+ { 0, 0, -1, 1, 16380, 1, -1, 0, 0},
+ { 118, -329, 721, -1668, 15982, 2144, -817, 358, -125},
+ { 212, -587, 1262, -2782, 14809, 4634, -1622, 693, -240},
+ { 271, -743, 1570, -3320, 12963, 7301, -2292, 953, -325}
+};
+
+static __inline size_t CalcLrIntQ(int16_t fixVal,
+ int16_t qDomain) {
+ int32_t roundVal = 1 << (qDomain - 1);
+
+ return (fixVal + roundVal) >> qDomain;
+}
+
+void WebRtcIsacfix_PitchFilter(int16_t* indatQQ, // Q10 if type is 1 or 4,
+ // Q0 if type is 2.
+ int16_t* outdatQQ,
+ PitchFiltstr* pfp,
+ int16_t* lagsQ7,
+ int16_t* gainsQ12,
+ int16_t type) {
+ int k, ind, cnt;
+ int16_t sign = 1;
+ int16_t inystateQQ[PITCH_DAMPORDER];
+ int16_t ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD];
+ const int16_t Gain = 21299; // 1.3 in Q14
+ int16_t oldLagQ7;
+ int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12;
+ size_t frcQQ = 0;
+ int32_t indW32 = 0;
+ const int16_t* fracoeffQQ = NULL;
+
+ // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM().
+ RTC_COMPILE_ASSERT(PITCH_FRACORDER == 9);
+ RTC_COMPILE_ASSERT(PITCH_DAMPORDER == 5);
+
+ // Set up buffer and states.
+ memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ));
+ memcpy(inystateQQ, pfp->ystateQQ, sizeof(inystateQQ));
+
+ // Get old lag and gain value from memory.
+ oldLagQ7 = pfp->oldlagQ7;
+ oldGainQ12 = pfp->oldgainQ12;
+
+ if (type == 4) {
+ sign = -1;
+
+ // Make output more periodic.
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ gainsQ12[k] = (int16_t)(gainsQ12[k] * Gain >> 14);
+ }
+ }
+
+ // No interpolation if pitch lag step is big.
+ if (((lagsQ7[0] * 3 >> 1) < oldLagQ7) || (lagsQ7[0] > (oldLagQ7 * 3 >> 1))) {
+ oldLagQ7 = lagsQ7[0];
+ oldGainQ12 = gainsQ12[0];
+ }
+
+ ind = 0;
+
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ // Calculate interpolation steps.
+ lagdeltaQ7 = lagsQ7[k] - oldLagQ7;
+ lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+ lagdeltaQ7, kDivFactor, 15);
+ curLagQ7 = oldLagQ7;
+ gaindeltaQ12 = gainsQ12[k] - oldGainQ12;
+ gaindeltaQ12 = (int16_t)(gaindeltaQ12 * kDivFactor >> 15);
+
+ curGainQ12 = oldGainQ12;
+ oldLagQ7 = lagsQ7[k];
+ oldGainQ12 = gainsQ12[k];
+
+ // Each frame has 4 60-sample pitch subframes, and each subframe has 5
+ // 12-sample segments. Each segment need to be processed with
+ // newly-updated parameters, so we break the pitch filtering into
+ // two for-loops (5 x 12) below. It's also why kDivFactor = 0.2 (in Q15).
+ for (cnt = 0; cnt < kSegments; cnt++) {
+ // Update parameters for each segment.
+ curGainQ12 += gaindeltaQ12;
+ curLagQ7 += lagdeltaQ7;
+ indW32 = CalcLrIntQ(curLagQ7, 7);
+ if (indW32 < PITCH_FRACORDER - 2) {
+ // WebRtcIsacfix_PitchFilterCore requires indW32 >= PITCH_FRACORDER -
+ // 2; otherwise, it will read from entries of ubufQQ that haven't been
+ // written yet. (This problem has only been seen in fuzzer tests, not
+ // in real life.) See Chromium bug 581901.
+ indW32 = PITCH_FRACORDER - 2;
+ }
+ frcQQ = ((indW32 << 7) + 64 - curLagQ7) >> 4;
+
+ if (frcQQ >= PITCH_FRACS) {
+ frcQQ = 0;
+ }
+ fracoeffQQ = kIntrpCoef[frcQQ];
+
+ // Pitch filtering.
+ WebRtcIsacfix_PitchFilterCore(PITCH_SUBFRAME_LEN / kSegments, curGainQ12,
+ indW32, sign, inystateQQ, ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind);
+ }
+ }
+
+ // Export buffer and states.
+ memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ));
+ memcpy(pfp->ystateQQ, inystateQQ, sizeof(pfp->ystateQQ));
+
+ pfp->oldlagQ7 = oldLagQ7;
+ pfp->oldgainQ12 = oldGainQ12;
+
+ if (type == 2) {
+ // Filter look-ahead segment.
+ WebRtcIsacfix_PitchFilterCore(QLOOKAHEAD, curGainQ12, indW32, 1, inystateQQ,
+ ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind);
+ }
+}
+
+
+void WebRtcIsacfix_PitchFilterGains(const int16_t* indatQ0,
+ PitchFiltstr* pfp,
+ int16_t* lagsQ7,
+ int16_t* gainsQ12) {
+ int k, n, m;
+ size_t ind, pos, pos3QQ;
+
+ int16_t ubufQQ[PITCH_INTBUFFSIZE];
+ int16_t oldLagQ7, lagdeltaQ7, curLagQ7;
+ const int16_t* fracoeffQQ = NULL;
+ int16_t scale;
+ int16_t cnt = 0, tmpW16;
+ size_t frcQQ, indW16 = 0;
+ int32_t tmpW32, tmp2W32, csum1QQ, esumxQQ;
+
+ // Set up buffer and states.
+ memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ));
+ oldLagQ7 = pfp->oldlagQ7;
+
+ // No interpolation if pitch lag step is big.
+ if (((lagsQ7[0] * 3 >> 1) < oldLagQ7) || (lagsQ7[0] > (oldLagQ7 * 3 >> 1))) {
+ oldLagQ7 = lagsQ7[0];
+ }
+
+ ind = 0;
+ pos = ind + PITCH_BUFFSIZE;
+ scale = 0;
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+
+ // Calculate interpolation steps.
+ lagdeltaQ7 = lagsQ7[k] - oldLagQ7;
+ lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+ lagdeltaQ7, kDivFactor, 15);
+ curLagQ7 = oldLagQ7;
+ oldLagQ7 = lagsQ7[k];
+
+ csum1QQ = 1;
+ esumxQQ = 1;
+
+ // Same as function WebRtcIsacfix_PitchFilter(), we break the pitch
+ // filtering into two for-loops (5 x 12) below.
+ for (cnt = 0; cnt < kSegments; cnt++) {
+ // Update parameters for each segment.
+ curLagQ7 += lagdeltaQ7;
+ indW16 = CalcLrIntQ(curLagQ7, 7);
+ frcQQ = ((indW16 << 7) + 64 - curLagQ7) >> 4;
+
+ if (frcQQ >= PITCH_FRACS) {
+ frcQQ = 0;
+ }
+ fracoeffQQ = kIntrpCoef[frcQQ];
+
+ pos3QQ = pos - (indW16 + 4);
+
+ for (n = 0; n < PITCH_SUBFRAME_LEN / kSegments; n++) {
+ // Filter to get fractional pitch.
+
+ tmpW32 = 0;
+ for (m = 0; m < PITCH_FRACORDER; m++) {
+ tmpW32 += ubufQQ[pos3QQ + m] * fracoeffQQ[m];
+ }
+
+ // Subtract from input and update buffer.
+ ubufQQ[pos] = indatQ0[ind];
+
+ tmp2W32 = WEBRTC_SPL_MUL_16_32_RSFT14(indatQ0[ind], tmpW32);
+ tmpW32 += 8192;
+ tmpW16 = tmpW32 >> 14;
+ tmpW32 = tmpW16 * tmpW16;
+
+ if ((tmp2W32 > 1073700000) || (csum1QQ > 1073700000) ||
+ (tmpW32 > 1073700000) || (esumxQQ > 1073700000)) { // 2^30
+ scale++;
+ csum1QQ >>= 1;
+ esumxQQ >>= 1;
+ }
+ csum1QQ += tmp2W32 >> scale;
+ esumxQQ += tmpW32 >> scale;
+
+ ind++;
+ pos++;
+ pos3QQ++;
+ }
+ }
+
+ if (csum1QQ < esumxQQ) {
+ tmp2W32 = WebRtcSpl_DivResultInQ31(csum1QQ, esumxQQ);
+
+ // Gain should be half the correlation.
+ tmpW32 = tmp2W32 >> 20;
+ } else {
+ tmpW32 = 4096;
+ }
+ gainsQ12[k] = (int16_t)WEBRTC_SPL_SAT(PITCH_MAX_GAIN_Q12, tmpW32, 0);
+ }
+
+ // Export buffer and states.
+ memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ));
+ pfp->oldlagQ7 = lagsQ7[PITCH_SUBFRAMES - 1];
+ pfp->oldgainQ12 = gainsQ12[PITCH_SUBFRAMES - 1];
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S
new file mode 100644
index 0000000000..065946856f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_armv6.S
@@ -0,0 +1,143 @@
+@
+@ Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+@
+@ Use of this source code is governed by a BSD-style license
+@ that can be found in the LICENSE file in the root of the source
+@ tree. An additional intellectual property rights grant can be found
+@ in the file PATENTS. All contributing project authors may
+@ be found in the AUTHORS file in the root of the source tree.
+@
+
+@ Contains the core loop routine for the pitch filter function in iSAC,
+@ optimized for ARMv7 platforms.
+@
+@ Output is bit-exact with the reference C code in pitch_filter.c.
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "rtc_base/system/asm_defines.h"
+
+GLOBAL_FUNCTION WebRtcIsacfix_PitchFilterCore
+.align 2
+
+@ void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+@ int16_t gain,
+@ size_t index,
+@ int16_t sign,
+@ int16_t* inputState,
+@ int16_t* outputBuf2,
+@ const int16_t* coefficient,
+@ int16_t* inputBuf,
+@ int16_t* outputBuf,
+@ int* index2) {
+DEFINE_FUNCTION WebRtcIsacfix_PitchFilterCore
+ push {r4-r11}
+ sub sp, #8
+
+ str r0, [sp] @ loopNumber
+ str r3, [sp, #4] @ sign
+ ldr r3, [sp, #44] @ outputBuf2
+ ldr r6, [sp, #60] @ index2
+ ldr r7, [r6] @ *index2
+ ldr r8, [sp, #52] @ inputBuf
+ ldr r12, [sp, #56] @ outputBuf
+
+ add r4, r7, r0
+ str r4, [r6] @ Store return value to index2.
+
+ mov r10, r7, asl #1
+ add r12, r10 @ &outputBuf[*index2]
+ add r8, r10 @ &inputBuf[*index2]
+
+ add r4, r7, #PITCH_BUFFSIZE @ *index2 + PITCH_BUFFSIZE
+ add r6, r3, r4, lsl #1 @ &outputBuf2[*index2 + PITCH_BUFFSIZE]
+ sub r4, r2 @ r2: index
+ sub r4, #2 @ *index2 + PITCH_BUFFSIZE - index - 2
+ add r3, r4, lsl #1 @ &ubufQQpos2[*index2]
+ ldr r9, [sp, #48] @ coefficient
+
+LOOP:
+@ Usage of registers in the loop:
+@ r0: loop counter
+@ r1: gain
+@ r2: tmpW32
+@ r3: &ubufQQpos2[]
+@ r6: &outputBuf2[]
+@ r8: &inputBuf[]
+@ r9: &coefficient[]
+@ r12: &outputBuf[]
+@ r4, r5, r7, r10, r11: scratch
+
+ @ Filter to get fractional pitch.
+ @ The pitch filter loop here is unrolled with 9 multipications.
+ pld [r3]
+ ldr r10, [r3], #4 @ ubufQQpos2[*index2 + 0, *index2 + 1]
+ ldr r4, [r9], #4 @ coefficient[0, 1]
+ ldr r11, [r3], #4
+ ldr r5, [r9], #4
+ smuad r2, r10, r4
+ smlad r2, r11, r5, r2
+
+ ldr r10, [r3], #4
+ ldr r4, [r9], #4
+ ldr r11, [r3], #4
+ ldr r5, [r9], #4
+ smlad r2, r10, r4, r2
+ ldrh r10, [r3], #-14 @ r3 back to &ubufQQpos2[*index2].
+ ldrh r4, [r9], #-16 @ r9 back to &coefficient[0].
+ smlad r2, r11, r5, r2
+ smlabb r2, r10, r4, r2
+
+ @ Saturate to avoid overflow in tmpW16.
+ asr r2, #1
+ add r4, r2, #0x1000
+ ssat r7, #16, r4, asr #13
+
+ @ Shift low pass filter state, and excute the low pass filter.
+ @ The memmove() and the low pass filter loop are unrolled and mixed.
+ smulbb r5, r1, r7
+ add r7, r5, #0x800
+ asr r7, #12 @ Get the value for inputState[0].
+ ldr r11, [sp, #40] @ inputState
+ pld [r11]
+ adr r10, kDampFilter
+ ldrsh r4, [r10], #2 @ kDampFilter[0]
+ mul r2, r7, r4
+ ldr r4, [r11] @ inputState[0, 1], before shift.
+ strh r7, [r11] @ inputState[0], after shift.
+ ldr r5, [r11, #4] @ inputState[2, 3], before shift.
+ ldr r7, [r10], #4 @ kDampFilter[1, 2]
+ ldr r10, [r10] @ kDampFilter[3, 4]
+ str r4, [r11, #2] @ inputState[1, 2], after shift.
+ str r5, [r11, #6] @ inputState[3, 4], after shift.
+ smlad r2, r4, r7, r2
+ smlad r2, r5, r10, r2
+
+ @ Saturate to avoid overflow.
+ @ First shift the sample to the range of [0xC0000000, 0x3FFFFFFF],
+ @ to avoid overflow in the next saturation step.
+ asr r2, #1
+ add r10, r2, #0x2000
+ ssat r10, #16, r10, asr #14
+
+ @ Subtract from input and update buffer.
+ ldr r11, [sp, #4] @ sign
+ ldrsh r4, [r8]
+ ldrsh r7, [r8], #2 @ inputBuf[*index2]
+ smulbb r5, r11, r10
+ subs r0, #1
+ sub r4, r5
+ ssat r2, #16, r4
+ strh r2, [r12], #2 @ outputBuf[*index2]
+
+ add r2, r7
+ ssat r2, #16, r2
+ strh r2, [r6], #2 @ outputBuff2[*index2 + PITCH_BUFFSIZE]
+ bgt LOOP
+
+ add sp, #8
+ pop {r4-r11}
+ bx lr
+
+.align 2
+kDampFilter:
+ .short -2294, 8192, 20972, 8192, -2294
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c
new file mode 100644
index 0000000000..f23d19de9c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+/* Filter coefficicients in Q15. */
+static const int16_t kDampFilter[PITCH_DAMPORDER] = {
+ -2294, 8192, 20972, 8192, -2294
+};
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+ int16_t gain,
+ size_t index,
+ int16_t sign,
+ int16_t* inputState,
+ int16_t* outputBuf2,
+ const int16_t* coefficient,
+ int16_t* inputBuf,
+ int16_t* outputBuf,
+ int* index2) {
+ int i = 0, j = 0; /* Loop counters. */
+ int16_t* ubufQQpos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)];
+ int16_t tmpW16 = 0;
+
+ for (i = 0; i < loopNumber; i++) {
+ int32_t tmpW32 = 0;
+
+ /* Filter to get fractional pitch. */
+ for (j = 0; j < PITCH_FRACORDER; j++) {
+ tmpW32 += ubufQQpos2[*index2 + j] * coefficient[j];
+ }
+
+ /* Saturate to avoid overflow in tmpW16. */
+ tmpW32 = WEBRTC_SPL_SAT(536862719, tmpW32, -536879104);
+ tmpW32 += 8192;
+ tmpW16 = (int16_t)(tmpW32 >> 14);
+
+ /* Shift low pass filter state. */
+ memmove(&inputState[1], &inputState[0],
+ (PITCH_DAMPORDER - 1) * sizeof(int16_t));
+ inputState[0] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
+ gain, tmpW16, 12);
+
+ /* Low pass filter. */
+ tmpW32 = 0;
+ /* TODO(kma): Define a static inline function WebRtcSpl_DotProduct()
+ in spl_inl.h to replace this and other similar loops. */
+ for (j = 0; j < PITCH_DAMPORDER; j++) {
+ tmpW32 += inputState[j] * kDampFilter[j];
+ }
+
+ /* Saturate to avoid overflow in tmpW16. */
+ tmpW32 = WEBRTC_SPL_SAT(1073725439, tmpW32, -1073758208);
+ tmpW32 += 16384;
+ tmpW16 = (int16_t)(tmpW32 >> 15);
+
+ /* Subtract from input and update buffer. */
+ tmpW32 = inputBuf[*index2] - sign * tmpW16;
+ outputBuf[*index2] = WebRtcSpl_SatW32ToW16(tmpW32);
+ tmpW32 = inputBuf[*index2] + outputBuf[*index2];
+ outputBuf2[*index2 + PITCH_BUFFSIZE] = WebRtcSpl_SatW32ToW16(tmpW32);
+
+ (*index2)++;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c
new file mode 100644
index 0000000000..785fd9464f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_mips.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
+
+void WebRtcIsacfix_PitchFilterCore(int loopNumber,
+ int16_t gain,
+ size_t index,
+ int16_t sign,
+ int16_t* inputState,
+ int16_t* outputBuf2,
+ const int16_t* coefficient,
+ int16_t* inputBuf,
+ int16_t* outputBuf,
+ int* index2) {
+ int ind2t = *index2;
+ int i = 0;
+ int16_t* out2_pos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)] + ind2t;
+ int32_t w1, w2, w3, w4, w5, gain32, sign32;
+ int32_t coef1, coef2, coef3, coef4, coef5 = 0;
+ // Define damp factors as int32_t (pair of int16_t)
+ int32_t kDampF0 = 0x0000F70A;
+ int32_t kDampF1 = 0x51EC2000;
+ int32_t kDampF2 = 0xF70A2000;
+ int16_t* input1 = inputBuf + ind2t;
+ int16_t* output1 = outputBuf + ind2t;
+ int16_t* output2 = outputBuf2 + ind2t + PITCH_BUFFSIZE;
+
+ // Load coefficients outside the loop and sign-extend gain and sign
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "lwl %[coef1], 3(%[coefficient]) \n\t"
+ "lwl %[coef2], 7(%[coefficient]) \n\t"
+ "lwl %[coef3], 11(%[coefficient]) \n\t"
+ "lwl %[coef4], 15(%[coefficient]) \n\t"
+ "lwr %[coef1], 0(%[coefficient]) \n\t"
+ "lwr %[coef2], 4(%[coefficient]) \n\t"
+ "lwr %[coef3], 8(%[coefficient]) \n\t"
+ "lwr %[coef4], 12(%[coefficient]) \n\t"
+ "lhu %[coef5], 16(%[coefficient]) \n\t"
+ "seh %[gain32], %[gain] \n\t"
+ "seh %[sign32], %[sign] \n\t"
+ ".set pop \n\t"
+ : [coef1] "=&r" (coef1), [coef2] "=&r" (coef2), [coef3] "=&r" (coef3),
+ [coef4] "=&r" (coef4), [coef5] "=&r" (coef5), [gain32] "=&r" (gain32),
+ [sign32] "=&r" (sign32)
+ : [coefficient] "r" (coefficient), [gain] "r" (gain),
+ [sign] "r" (sign)
+ : "memory"
+ );
+
+ for (i = 0; i < loopNumber; i++) {
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ // Filter to get fractional pitch
+ "li %[w1], 8192 \n\t"
+ "mtlo %[w1] \n\t"
+ "mthi $0 \n\t"
+ "lwl %[w1], 3(%[out2_pos2]) \n\t"
+ "lwl %[w2], 7(%[out2_pos2]) \n\t"
+ "lwl %[w3], 11(%[out2_pos2]) \n\t"
+ "lwl %[w4], 15(%[out2_pos2]) \n\t"
+ "lwr %[w1], 0(%[out2_pos2]) \n\t"
+ "lwr %[w2], 4(%[out2_pos2]) \n\t"
+ "lwr %[w3], 8(%[out2_pos2]) \n\t"
+ "lwr %[w4], 12(%[out2_pos2]) \n\t"
+ "lhu %[w5], 16(%[out2_pos2]) \n\t"
+ "dpa.w.ph $ac0, %[w1], %[coef1] \n\t"
+ "dpa.w.ph $ac0, %[w2], %[coef2] \n\t"
+ "dpa.w.ph $ac0, %[w3], %[coef3] \n\t"
+ "dpa.w.ph $ac0, %[w4], %[coef4] \n\t"
+ "dpa.w.ph $ac0, %[w5], %[coef5] \n\t"
+ "addiu %[out2_pos2], %[out2_pos2], 2 \n\t"
+ "mthi $0, $ac1 \n\t"
+ "lwl %[w2], 3(%[inputState]) \n\t"
+ "lwl %[w3], 7(%[inputState]) \n\t"
+ // Fractional pitch shift & saturation
+ "extr_s.h %[w1], $ac0, 14 \n\t"
+ "li %[w4], 16384 \n\t"
+ "lwr %[w2], 0(%[inputState]) \n\t"
+ "lwr %[w3], 4(%[inputState]) \n\t"
+ "mtlo %[w4], $ac1 \n\t"
+ // Shift low pass filter state
+ "swl %[w2], 5(%[inputState]) \n\t"
+ "swl %[w3], 9(%[inputState]) \n\t"
+ "mul %[w1], %[gain32], %[w1] \n\t"
+ "swr %[w2], 2(%[inputState]) \n\t"
+ "swr %[w3], 6(%[inputState]) \n\t"
+ // Low pass filter accumulation
+ "dpa.w.ph $ac1, %[kDampF1], %[w2] \n\t"
+ "dpa.w.ph $ac1, %[kDampF2], %[w3] \n\t"
+ "lh %[w4], 0(%[input1]) \n\t"
+ "addiu %[input1], %[input1], 2 \n\t"
+ "shra_r.w %[w1], %[w1], 12 \n\t"
+ "sh %[w1], 0(%[inputState]) \n\t"
+ "dpa.w.ph $ac1, %[kDampF0], %[w1] \n\t"
+ // Low pass filter shift & saturation
+ "extr_s.h %[w2], $ac1, 15 \n\t"
+ "mul %[w2], %[w2], %[sign32] \n\t"
+ // Buffer update
+ "subu %[w2], %[w4], %[w2] \n\t"
+ "shll_s.w %[w2], %[w2], 16 \n\t"
+ "sra %[w2], %[w2], 16 \n\t"
+ "sh %[w2], 0(%[output1]) \n\t"
+ "addu %[w2], %[w2], %[w4] \n\t"
+ "shll_s.w %[w2], %[w2], 16 \n\t"
+ "addiu %[output1], %[output1], 2 \n\t"
+ "sra %[w2], %[w2], 16 \n\t"
+ "sh %[w2], 0(%[output2]) \n\t"
+ "addiu %[output2], %[output2], 2 \n\t"
+ ".set pop \n\t"
+ : [w1] "=&r" (w1), [w2] "=&r" (w2), [w3] "=&r" (w3), [w4] "=&r" (w4),
+ [w5] "=&r" (w5), [input1] "+r" (input1), [out2_pos2] "+r" (out2_pos2),
+ [output1] "+r" (output1), [output2] "+r" (output2)
+ : [coefficient] "r" (coefficient), [inputState] "r" (inputState),
+ [gain32] "r" (gain32), [sign32] "r" (sign32), [kDampF0] "r" (kDampF0),
+ [kDampF1] "r" (kDampF1), [kDampF2] "r" (kDampF2),
+ [coef1] "r" (coef1), [coef2] "r" (coef2), [coef3] "r" (coef3),
+ [coef4] "r" (coef4), [coef5] "r" (coef5)
+ : "hi", "lo", "$ac1hi", "$ac1lo", "memory"
+ );
+ }
+ (*index2) += loopNumber;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c
new file mode 100644
index 0000000000..bfbab1950d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.c
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* cdf for quantized pitch filter gains */
+const uint16_t WebRtcIsacfix_kPitchGainCdf[255] = {
+ 0, 2, 4, 6, 64, 901, 903, 905, 16954, 16956,
+ 16961, 17360, 17362, 17364, 17366, 17368, 17370, 17372, 17374, 17411,
+ 17514, 17516, 17583, 18790, 18796, 18802, 20760, 20777, 20782, 21722,
+ 21724, 21728, 21738, 21740, 21742, 21744, 21746, 21748, 22224, 22227,
+ 22230, 23214, 23229, 23239, 25086, 25108, 25120, 26088, 26094, 26098,
+ 26175, 26177, 26179, 26181, 26183, 26185, 26484, 26507, 26522, 27705,
+ 27731, 27750, 29767, 29799, 29817, 30866, 30883, 30885, 31025, 31029,
+ 31031, 31033, 31035, 31037, 31114, 31126, 31134, 32687, 32722, 32767,
+ 35718, 35742, 35757, 36943, 36952, 36954, 37115, 37128, 37130, 37132,
+ 37134, 37136, 37143, 37145, 37152, 38843, 38863, 38897, 47458, 47467,
+ 47474, 49040, 49061, 49063, 49145, 49157, 49159, 49161, 49163, 49165,
+ 49167, 49169, 49171, 49757, 49770, 49782, 61333, 61344, 61346, 62860,
+ 62883, 62885, 62887, 62889, 62891, 62893, 62895, 62897, 62899, 62901,
+ 62903, 62905, 62907, 62909, 65496, 65498, 65500, 65521, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerlimiGain[3] = {
+ -7, -2, -1
+};
+
+const int16_t WebRtcIsacfix_kUpperlimitGain[3] = {
+ 0, 3, 1
+};
+
+const uint16_t WebRtcIsacfix_kMultsGain[2] = {
+ 18, 3
+};
+
+/* size of cdf table */
+const uint16_t WebRtcIsacfix_kCdfTableSizeGain[1] = {
+ 256
+};
+
+/* mean values of pitch filter gains in FIXED point Q12 */
+const int16_t WebRtcIsacfix_kPitchGain1[144] = {
+ 843, 1092, 1336, 1222, 1405, 1656, 1500, 1815, 1843, 1838, 1839,
+ 1843, 1843, 1843, 1843, 1843, 1843, 1843, 814, 846, 1092, 1013,
+ 1174, 1383, 1391, 1511, 1584, 1734, 1753, 1843, 1843, 1843, 1843,
+ 1843, 1843, 1843, 524, 689, 777, 845, 947, 1069, 1090, 1263,
+ 1380, 1447, 1559, 1676, 1645, 1749, 1843, 1843, 1843, 1843, 81,
+ 477, 563, 611, 706, 806, 849, 1012, 1192, 1128, 1330, 1489,
+ 1425, 1576, 1826, 1741, 1843, 1843, 0, 290, 305, 356, 488,
+ 575, 602, 741, 890, 835, 1079, 1196, 1182, 1376, 1519, 1506,
+ 1680, 1843, 0, 47, 97, 69, 289, 381, 385, 474, 617,
+ 664, 803, 1079, 935, 1160, 1269, 1265, 1506, 1741, 0, 0,
+ 0, 0, 112, 120, 190, 283, 442, 343, 526, 809, 684,
+ 935, 1134, 1020, 1265, 1506, 0, 0, 0, 0, 0, 0,
+ 0, 111, 256, 87, 373, 597, 430, 684, 935, 770, 1020,
+ 1265
+};
+
+const int16_t WebRtcIsacfix_kPitchGain2[144] = {
+ 1760, 1525, 1285, 1747, 1671, 1393, 1843, 1826, 1555, 1843, 1784,
+ 1606, 1843, 1843, 1711, 1843, 1843, 1814, 1389, 1275, 1040, 1564,
+ 1414, 1252, 1610, 1495, 1343, 1753, 1592, 1405, 1804, 1720, 1475,
+ 1843, 1814, 1581, 1208, 1061, 856, 1349, 1148, 994, 1390, 1253,
+ 1111, 1495, 1343, 1178, 1770, 1465, 1234, 1814, 1581, 1342, 1040,
+ 793, 713, 1053, 895, 737, 1128, 1003, 861, 1277, 1094, 981,
+ 1475, 1192, 1019, 1581, 1342, 1098, 855, 570, 483, 833, 648,
+ 540, 948, 744, 572, 1009, 844, 636, 1234, 934, 685, 1342,
+ 1217, 984, 537, 318, 124, 603, 423, 350, 687, 479, 322,
+ 791, 581, 430, 987, 671, 488, 1098, 849, 597, 283, 27,
+ 0, 397, 222, 38, 513, 271, 124, 624, 325, 157, 737,
+ 484, 233, 849, 597, 343, 27, 0, 0, 141, 0, 0,
+ 256, 69, 0, 370, 87, 0, 484, 229, 0, 597, 343,
+ 87
+};
+
+const int16_t WebRtcIsacfix_kPitchGain3[144] = {
+ 1843, 1843, 1711, 1843, 1818, 1606, 1843, 1827, 1511, 1814, 1639,
+ 1393, 1760, 1525, 1285, 1656, 1419, 1176, 1835, 1718, 1475, 1841,
+ 1650, 1387, 1648, 1498, 1287, 1600, 1411, 1176, 1522, 1299, 1040,
+ 1419, 1176, 928, 1773, 1461, 1128, 1532, 1355, 1202, 1429, 1260,
+ 1115, 1398, 1151, 1025, 1172, 1080, 790, 1176, 928, 677, 1475,
+ 1147, 1019, 1276, 1096, 922, 1214, 1010, 901, 1057, 893, 800,
+ 1040, 796, 734, 928, 677, 424, 1137, 897, 753, 1120, 830,
+ 710, 875, 751, 601, 795, 642, 583, 790, 544, 475, 677,
+ 474, 140, 987, 750, 482, 697, 573, 450, 691, 487, 303,
+ 661, 394, 332, 537, 303, 220, 424, 168, 0, 737, 484,
+ 229, 624, 348, 153, 441, 261, 136, 397, 166, 51, 283,
+ 27, 0, 168, 0, 0, 484, 229, 0, 370, 57, 0,
+ 256, 43, 0, 141, 0, 0, 27, 0, 0, 0, 0,
+ 0
+};
+
+
+const int16_t WebRtcIsacfix_kPitchGain4[144] = {
+ 1843, 1843, 1843, 1843, 1841, 1843, 1500, 1821, 1843, 1222, 1434,
+ 1656, 843, 1092, 1336, 504, 757, 1007, 1843, 1843, 1843, 1838,
+ 1791, 1843, 1265, 1505, 1599, 965, 1219, 1425, 730, 821, 1092,
+ 249, 504, 757, 1783, 1819, 1843, 1351, 1567, 1727, 1096, 1268,
+ 1409, 805, 961, 1131, 444, 670, 843, 0, 249, 504, 1425,
+ 1655, 1743, 1096, 1324, 1448, 822, 1019, 1199, 490, 704, 867,
+ 81, 450, 555, 0, 0, 249, 1247, 1428, 1530, 881, 1073,
+ 1283, 610, 759, 939, 278, 464, 645, 0, 200, 270, 0,
+ 0, 0, 935, 1163, 1410, 528, 790, 1068, 377, 499, 717,
+ 173, 240, 274, 0, 43, 62, 0, 0, 0, 684, 935,
+ 1182, 343, 551, 735, 161, 262, 423, 0, 55, 27, 0,
+ 0, 0, 0, 0, 0, 430, 684, 935, 87, 377, 597,
+ 0, 46, 256, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+
+
+/* transform matrix in Q12*/
+const int16_t WebRtcIsacfix_kTransform[4][4] = {
+ { -2048, -2048, -2048, -2048 },
+ { 2748, 916, -916, -2748 },
+ { 2048, -2048, -2048, 2048 },
+ { 916, -2748, 2748, -916 }
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
new file mode 100644
index 0000000000..59e1738bce
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include <stdint.h>
+
+/********************* Pitch Filter Gain Coefficient Tables
+ * ************************/
+/* cdf for quantized pitch filter gains */
+extern const uint16_t WebRtcIsacfix_kPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerlimiGain[3];
+extern const int16_t WebRtcIsacfix_kUpperlimitGain[3];
+extern const uint16_t WebRtcIsacfix_kMultsGain[2];
+
+/* mean values of pitch filter gains in Q12*/
+extern const int16_t WebRtcIsacfix_kPitchGain1[144];
+extern const int16_t WebRtcIsacfix_kPitchGain2[144];
+extern const int16_t WebRtcIsacfix_kPitchGain3[144];
+extern const int16_t WebRtcIsacfix_kPitchGain4[144];
+
+/* size of cdf table */
+extern const uint16_t WebRtcIsacfix_kCdfTableSizeGain[1];
+
+/* transform matrix */
+extern const int16_t WebRtcIsacfix_kTransform[4][4];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c
new file mode 100644
index 0000000000..894716e739
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.c
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h"
+
+
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsacfix_kPitchLagCdf1Lo[127] = {
+ 0, 134, 336, 549, 778, 998, 1264, 1512, 1777, 2070,
+ 2423, 2794, 3051, 3361, 3708, 3979, 4315, 4610, 4933, 5269,
+ 5575, 5896, 6155, 6480, 6816, 7129, 7477, 7764, 8061, 8358,
+ 8718, 9020, 9390, 9783, 10177, 10543, 10885, 11342, 11795, 12213,
+ 12680, 13096, 13524, 13919, 14436, 14903, 15349, 15795, 16267, 16734,
+ 17266, 17697, 18130, 18632, 19080, 19447, 19884, 20315, 20735, 21288,
+ 21764, 22264, 22723, 23193, 23680, 24111, 24557, 25022, 25537, 26082,
+ 26543, 27090, 27620, 28139, 28652, 29149, 29634, 30175, 30692, 31273,
+ 31866, 32506, 33059, 33650, 34296, 34955, 35629, 36295, 36967, 37726,
+ 38559, 39458, 40364, 41293, 42256, 43215, 44231, 45253, 46274, 47359,
+ 48482, 49678, 50810, 51853, 53016, 54148, 55235, 56263, 57282, 58363,
+ 59288, 60179, 61076, 61806, 62474, 63129, 63656, 64160, 64533, 64856,
+ 65152, 65535, 65535, 65535, 65535, 65535, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf2Lo[20] = {
+ 0, 429, 3558, 5861, 8558, 11639, 15210, 19502, 24773, 31983,
+ 42602, 48567, 52601, 55676, 58160, 60172, 61889, 63235, 65383, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf3Lo[2] = {
+ 0, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf4Lo[10] = {
+ 0, 2966, 6368, 11182, 19431, 37793, 48532, 55353, 60626, 65535
+};
+
+const uint16_t *WebRtcIsacfix_kPitchLagPtrLo[4] = {
+ WebRtcIsacfix_kPitchLagCdf1Lo,
+ WebRtcIsacfix_kPitchLagCdf2Lo,
+ WebRtcIsacfix_kPitchLagCdf3Lo,
+ WebRtcIsacfix_kPitchLagCdf4Lo
+};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsacfix_kPitchLagSizeLo[1] = {
+ 128
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerLimitLo[4] = {
+ -140, -9, 0, -4
+};
+
+const int16_t WebRtcIsacfix_kUpperLimitLo[4] = {
+ -20, 9, 0, 4
+};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsacfix_kInitIndLo[3] = {
+ 10, 1, 5
+};
+
+/* mean values of pitch filter lags in Q10 */
+
+const int16_t WebRtcIsacfix_kMeanLag2Lo[19] = {
+ -17627, -16207, -14409, -12319, -10253, -8200, -6054, -3986, -1948, -19,
+ 1937, 3974, 6064, 8155, 10229, 12270, 14296, 16127, 17520
+};
+
+const int16_t WebRtcIsacfix_kMeanLag4Lo[9] = {
+ -7949, -6063, -4036, -1941, 38, 1977, 4060, 6059
+};
+
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsacfix_kPitchLagCdf1Mid[255] = {
+ 0, 28, 61, 88, 121, 149, 233, 331, 475, 559,
+ 624, 661, 689, 712, 745, 791, 815, 843, 866, 922,
+ 959, 1024, 1061, 1117, 1178, 1238, 1280, 1350, 1453, 1513,
+ 1564, 1625, 1671, 1741, 1788, 1904, 2072, 2421, 2626, 2770,
+ 2840, 2900, 2942, 3012, 3068, 3115, 3147, 3194, 3254, 3319,
+ 3366, 3520, 3678, 3780, 3850, 3911, 3957, 4032, 4106, 4185,
+ 4292, 4474, 4683, 4842, 5019, 5191, 5321, 5428, 5540, 5675,
+ 5763, 5847, 5959, 6127, 6304, 6564, 6839, 7090, 7263, 7421,
+ 7556, 7728, 7872, 7984, 8142, 8361, 8580, 8743, 8938, 9227,
+ 9409, 9539, 9674, 9795, 9930, 10060, 10177, 10382, 10614, 10861,
+ 11038, 11271, 11415, 11629, 11792, 12044, 12193, 12416, 12574, 12821,
+ 13007, 13235, 13445, 13654, 13901, 14134, 14488, 15000, 15703, 16285,
+ 16504, 16797, 17086, 17328, 17579, 17807, 17998, 18268, 18538, 18836,
+ 19087, 19274, 19474, 19716, 19935, 20270, 20833, 21303, 21532, 21741,
+ 21978, 22207, 22523, 22770, 23054, 23613, 23943, 24204, 24399, 24651,
+ 24832, 25074, 25270, 25549, 25759, 26015, 26150, 26424, 26713, 27048,
+ 27342, 27504, 27681, 27854, 28021, 28207, 28412, 28664, 28859, 29064,
+ 29278, 29548, 29748, 30107, 30377, 30656, 30856, 31164, 31452, 31755,
+ 32011, 32328, 32626, 32919, 33319, 33789, 34329, 34925, 35396, 35973,
+ 36443, 36964, 37551, 38156, 38724, 39357, 40023, 40908, 41587, 42602,
+ 43924, 45037, 45810, 46597, 47421, 48291, 49092, 50051, 51448, 52719,
+ 53440, 54241, 54944, 55977, 56676, 57299, 57872, 58389, 59059, 59688,
+ 60237, 60782, 61094, 61573, 61890, 62290, 62658, 63030, 63217, 63454,
+ 63622, 63882, 64003, 64273, 64427, 64529, 64581, 64697, 64758, 64902,
+ 65414, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf2Mid[36] = {
+ 0, 71, 335, 581, 836, 1039, 1323, 1795, 2258, 2608,
+ 3005, 3591, 4243, 5344, 7163, 10583, 16848, 28078, 49448, 57007,
+ 60357, 61850, 62837, 63437, 63872, 64188, 64377, 64614, 64774, 64949,
+ 65039, 65115, 65223, 65360, 65474, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf3Mid[2] = {
+ 0, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf4Mid[20] = {
+ 0, 28, 246, 459, 667, 1045, 1523, 2337, 4337, 11347,
+ 44231, 56709, 60781, 62243, 63161, 63969, 64608, 65062, 65502, 65535
+};
+
+const uint16_t *WebRtcIsacfix_kPitchLagPtrMid[4] = {
+ WebRtcIsacfix_kPitchLagCdf1Mid,
+ WebRtcIsacfix_kPitchLagCdf2Mid,
+ WebRtcIsacfix_kPitchLagCdf3Mid,
+ WebRtcIsacfix_kPitchLagCdf4Mid
+};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsacfix_kPitchLagSizeMid[1] = {
+ 256
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerLimitMid[4] = {
+ -280, -17, 0, -9
+};
+
+const int16_t WebRtcIsacfix_kUpperLimitMid[4] = {
+ -40, 17, 0, 9
+};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsacfix_kInitIndMid[3] = {
+ 18, 1, 10
+};
+
+/* mean values of pitch filter lags in Q10 */
+
+const int16_t WebRtcIsacfix_kMeanLag2Mid[35] = {
+ -17297, -16250, -15416, -14343, -13341, -12363, -11270,
+ -10355, -9122, -8217, -7172, -6083, -5102, -4004, -3060,
+ -1982, -952, -18, 935, 1976, 3040, 4032,
+ 5082, 6065, 7257, 8202, 9264, 10225, 11242,
+ 12234, 13337, 14336, 15374, 16187, 17347
+};
+
+
+const int16_t WebRtcIsacfix_kMeanLag4Mid[19] = {
+ -8811, -8081, -7203, -6003, -5057, -4025, -2983, -1964,
+ -891, 29, 921, 1920, 2988, 4064, 5187, 6079, 7173, 8074, 8849
+};
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsacfix_kPitchLagCdf1Hi[511] = {
+ 0, 7, 18, 33, 69, 105, 156, 228, 315, 612,
+ 680, 691, 709, 724, 735, 738, 742, 746, 749, 753,
+ 756, 760, 764, 774, 782, 785, 789, 796, 800, 803,
+ 807, 814, 818, 822, 829, 832, 847, 854, 858, 869,
+ 876, 883, 898, 908, 934, 977, 1010, 1050, 1060, 1064,
+ 1075, 1078, 1086, 1089, 1093, 1104, 1111, 1122, 1133, 1136,
+ 1151, 1162, 1183, 1209, 1252, 1281, 1339, 1364, 1386, 1401,
+ 1411, 1415, 1426, 1430, 1433, 1440, 1448, 1455, 1462, 1477,
+ 1487, 1495, 1502, 1506, 1509, 1516, 1524, 1531, 1535, 1542,
+ 1553, 1556, 1578, 1589, 1611, 1625, 1639, 1643, 1654, 1665,
+ 1672, 1687, 1694, 1705, 1708, 1719, 1730, 1744, 1752, 1759,
+ 1791, 1795, 1820, 1867, 1886, 1915, 1936, 1943, 1965, 1987,
+ 2041, 2099, 2161, 2175, 2200, 2211, 2226, 2233, 2244, 2251,
+ 2266, 2280, 2287, 2298, 2309, 2316, 2331, 2342, 2356, 2378,
+ 2403, 2418, 2447, 2497, 2544, 2602, 2863, 2895, 2903, 2935,
+ 2950, 2971, 3004, 3011, 3018, 3029, 3040, 3062, 3087, 3127,
+ 3152, 3170, 3199, 3243, 3293, 3322, 3340, 3377, 3402, 3427,
+ 3474, 3518, 3543, 3579, 3601, 3637, 3659, 3706, 3731, 3760,
+ 3818, 3847, 3869, 3901, 3920, 3952, 4068, 4169, 4220, 4271,
+ 4524, 4571, 4604, 4632, 4672, 4730, 4777, 4806, 4857, 4904,
+ 4951, 5002, 5031, 5060, 5107, 5150, 5212, 5266, 5331, 5382,
+ 5432, 5490, 5544, 5610, 5700, 5762, 5812, 5874, 5972, 6022,
+ 6091, 6163, 6232, 6305, 6402, 6540, 6685, 6880, 7090, 7271,
+ 7379, 7452, 7542, 7625, 7687, 7770, 7843, 7911, 7966, 8024,
+ 8096, 8190, 8252, 8320, 8411, 8501, 8585, 8639, 8751, 8842,
+ 8918, 8986, 9066, 9127, 9203, 9269, 9345, 9406, 9464, 9536,
+ 9612, 9667, 9735, 9844, 9931, 10036, 10119, 10199, 10260, 10358,
+ 10441, 10514, 10666, 10734, 10872, 10951, 11053, 11125, 11223, 11324,
+ 11516, 11664, 11737, 11816, 11892, 12008, 12120, 12200, 12280, 12392,
+ 12490, 12576, 12685, 12812, 12917, 13003, 13108, 13210, 13300, 13384,
+ 13470, 13579, 13673, 13771, 13879, 13999, 14136, 14201, 14368, 14614,
+ 14759, 14867, 14958, 15030, 15121, 15189, 15280, 15385, 15461, 15555,
+ 15653, 15768, 15884, 15971, 16069, 16145, 16210, 16279, 16380, 16463,
+ 16539, 16615, 16688, 16818, 16919, 17017, 18041, 18338, 18523, 18649,
+ 18790, 18917, 19047, 19167, 19315, 19460, 19601, 19731, 19858, 20068,
+ 20173, 20318, 20466, 20625, 20741, 20911, 21045, 21201, 21396, 21588,
+ 21816, 22022, 22305, 22547, 22786, 23072, 23322, 23600, 23879, 24168,
+ 24433, 24769, 25120, 25511, 25895, 26289, 26792, 27219, 27683, 28077,
+ 28566, 29094, 29546, 29977, 30491, 30991, 31573, 32105, 32594, 33173,
+ 33788, 34497, 35181, 35833, 36488, 37255, 37921, 38645, 39275, 39894,
+ 40505, 41167, 41790, 42431, 43096, 43723, 44385, 45134, 45858, 46607,
+ 47349, 48091, 48768, 49405, 49955, 50555, 51167, 51985, 52611, 53078,
+ 53494, 53965, 54435, 54996, 55601, 56125, 56563, 56838, 57244, 57566,
+ 57967, 58297, 58771, 59093, 59419, 59647, 59886, 60143, 60461, 60693,
+ 60917, 61170, 61416, 61634, 61891, 62122, 62310, 62455, 62632, 62839,
+ 63103, 63436, 63639, 63805, 63906, 64015, 64192, 64355, 64475, 64558,
+ 64663, 64742, 64811, 64865, 64916, 64956, 64981, 65025, 65068, 65115,
+ 65195, 65314, 65419, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf2Hi[68] = {
+ 0, 7, 11, 22, 37, 52, 56, 59, 81, 85,
+ 89, 96, 115, 130, 137, 152, 170, 181, 193, 200,
+ 207, 233, 237, 259, 289, 318, 363, 433, 592, 992,
+ 1607, 3062, 6149, 12206, 25522, 48368, 58223, 61918, 63640, 64584,
+ 64943, 65098, 65206, 65268, 65294, 65335, 65350, 65372, 65387, 65402,
+ 65413, 65420, 65428, 65435, 65439, 65450, 65454, 65468, 65472, 65476,
+ 65483, 65491, 65498, 65505, 65516, 65520, 65528, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf3Hi[2] = {
+ 0, 65535
+};
+
+const uint16_t WebRtcIsacfix_kPitchLagCdf4Hi[35] = {
+ 0, 7, 19, 30, 41, 48, 63, 74, 82, 96,
+ 122, 152, 215, 330, 701, 2611, 10931, 48106, 61177, 64341,
+ 65112, 65238, 65309, 65338, 65364, 65379, 65401, 65427, 65453,
+ 65465, 65476, 65490, 65509, 65528, 65535
+};
+
+const uint16_t *WebRtcIsacfix_kPitchLagPtrHi[4] = {
+ WebRtcIsacfix_kPitchLagCdf1Hi,
+ WebRtcIsacfix_kPitchLagCdf2Hi,
+ WebRtcIsacfix_kPitchLagCdf3Hi,
+ WebRtcIsacfix_kPitchLagCdf4Hi
+};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsacfix_kPitchLagSizeHi[1] = {
+ 512
+};
+
+/* index limits and ranges */
+const int16_t WebRtcIsacfix_kLowerLimitHi[4] = {
+ -552, -34, 0, -16
+};
+
+const int16_t WebRtcIsacfix_kUpperLimitHi[4] = {
+ -80, 32, 0, 17
+};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsacfix_kInitIndHi[3] = {
+ 34, 1, 18
+};
+
+/* mean values of pitch filter lags */
+
+const int16_t WebRtcIsacfix_kMeanLag2Hi[67] = {
+ -17482, -16896, -16220, -15929, -15329, -14848, -14336, -13807, -13312, -12800, -12218, -11720,
+ -11307, -10649, -10396, -9742, -9148, -8668, -8297, -7718, -7155, -6656, -6231, -5600, -5129,
+ -4610, -4110, -3521, -3040, -2525, -2016, -1506, -995, -477, -5, 469, 991, 1510, 2025, 2526, 3079,
+ 3555, 4124, 4601, 5131, 5613, 6194, 6671, 7140, 7645, 8207, 8601, 9132, 9728, 10359, 10752, 11302,
+ 11776, 12288, 12687, 13204, 13759, 14295, 14810, 15360, 15764, 16350
+};
+
+
+const int16_t WebRtcIsacfix_kMeanLag4Hi[34] = {
+ -8175, -7659, -7205, -6684, -6215, -5651, -5180, -4566, -4087, -3536, -3096,
+ -2532, -1990, -1482, -959, -440, 11, 451, 954, 1492, 2020, 2562, 3059,
+ 3577, 4113, 4618, 5134, 5724, 6060, 6758, 7015, 7716, 8066, 8741
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
new file mode 100644
index 0000000000..228da26731
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
+
+#include <stdint.h>
+
+/********************* Pitch Filter Lag Coefficient Tables
+ * ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Lo[127];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Lo[20];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Lo[2];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Lo[10];
+
+extern const uint16_t* WebRtcIsacfix_kPitchLagPtrLo[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsacfix_kPitchLagSizeLo[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerLimitLo[4];
+extern const int16_t WebRtcIsacfix_kUpperLimitLo[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsacfix_kInitIndLo[3];
+
+/* mean values of pitch filter lags */
+extern const int16_t WebRtcIsacfix_kMeanLag2Lo[19];
+extern const int16_t WebRtcIsacfix_kMeanLag4Lo[9];
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Mid[255];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Mid[36];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Mid[2];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Mid[20];
+
+extern const uint16_t* WebRtcIsacfix_kPitchLagPtrMid[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsacfix_kPitchLagSizeMid[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerLimitMid[4];
+extern const int16_t WebRtcIsacfix_kUpperLimitMid[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsacfix_kInitIndMid[3];
+
+/* mean values of pitch filter lags */
+extern const int16_t WebRtcIsacfix_kMeanLag2Mid[35];
+extern const int16_t WebRtcIsacfix_kMeanLag4Mid[19];
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf1Hi[511];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf2Hi[68];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf3Hi[2];
+extern const uint16_t WebRtcIsacfix_kPitchLagCdf4Hi[35];
+
+extern const uint16_t* WebRtcIsacfix_kPitchLagPtrHi[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsacfix_kPitchLagSizeHi[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsacfix_kLowerLimitHi[4];
+extern const int16_t WebRtcIsacfix_kUpperLimitHi[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsacfix_kInitIndHi[3];
+
+/* mean values of pitch filter lags */
+extern const int16_t WebRtcIsacfix_kMeanLag2Hi[67];
+extern const int16_t WebRtcIsacfix_kMeanLag4Hi[34];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/settings.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/settings.h
new file mode 100644
index 0000000000..03a2d05457
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/settings.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * settings.h
+ *
+ * Declaration of #defines used in the iSAC codec
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_
+
+/* sampling frequency (Hz) */
+#define FS 16000
+/* 1.5 times Sampling frequency */
+#define FS_1_HALF (uint32_t)24000
+/* Three times Sampling frequency */
+#define FS3 (uint32_t)48000
+/* Eight times Sampling frequency */
+#define FS8 (uint32_t)128000
+
+/* number of samples per frame (either 480 (30ms) or 960 (60ms)) */
+#define INITIAL_FRAMESAMPLES 960
+
+/* miliseconds */
+#define FRAMESIZE 30
+/* number of samples per frame processed in the encoder (30ms) */
+#define FRAMESAMPLES 480 /* ((FRAMESIZE*FS)/1000) */
+#define FRAMESAMPLES_HALF 240
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms 160 /* ((10*FS)/1000) */
+/* Number of samples per 1 ms */
+#define SAMPLES_PER_MSEC 16
+/* number of subframes */
+#define SUBFRAMES 6
+/* length of a subframe */
+#define UPDATE 80
+/* length of half a subframe (low/high band) */
+#define HALF_SUBFRAMELEN 40 /* (UPDATE/2) */
+/* samples of look ahead (in a half-band, so actually half the samples of look
+ * ahead @ FS) */
+#define QLOOKAHEAD 24 /* 3 ms */
+
+/* order of AR model in spectral entropy coder */
+#define AR_ORDER 6
+#define MAX_ORDER 13
+#define LEVINSON_MAX_ORDER 12
+
+/* window length (masking analysis) */
+#define WINLEN 256
+/* order of low-band pole filter used to approximate masking curve */
+#define ORDERLO 12
+/* order of hi-band pole filter used to approximate masking curve */
+#define ORDERHI 6
+
+#define KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_SHAPE_ORDER 18 /* (ORDERLO + ORDERHI) */
+
+#define KLT_ORDER_GAIN 12 /* (2 * SUBFRAMES) */
+#define KLT_ORDER_SHAPE 108 /* (LPC_SHAPE_ORDER * SUBFRAMES) */
+
+/* order for post_filter_bank */
+#define POSTQORDER 3
+/* order for pre-filterbank */
+#define QORDER 3
+/* for decimator */
+#define ALLPASSSECTIONS 2
+/* The number of composite all-pass filter factors */
+#define NUMBEROFCOMPOSITEAPSECTIONS 4
+
+/* The number of all-pass filter factors in an upper or lower channel*/
+#define NUMBEROFCHANNELAPSECTIONS 2
+
+#define DPMIN_Q10 -10240 /* -10.00 in Q10 */
+#define DPMAX_Q10 10240 /* 10.00 in Q10 */
+#define MINBITS_Q10 10240 /* 10.0 in Q10 */
+
+/* array size for byte stream in number of Word16. */
+#define STREAM_MAXW16 \
+ 300 /* The old maximum size still needed for the decoding */
+#define STREAM_MAXW16_30MS \
+ 100 /* 100 Word16 = 200 bytes = 53.4 kbit/s @ 30 ms.framelength */
+#define STREAM_MAXW16_60MS \
+ 200 /* 200 Word16 = 400 bytes = 53.4 kbit/s @ 60 ms.framelength */
+/* This is used only at the decoder bit-stream struct.
+ * - The encoder and decoder bitstream containers are of different size because
+ * old iSAC limited the encoded bitstream to 600 bytes. But newer versions
+ * restrict to shorter bitstream.
+ * - We add 10 bytes of guards to the internal bitstream container. The reason
+ * is that entropy decoder might read few bytes (3 according to our
+ * observations) more than the actual size of the bitstream. To avoid reading
+ * outside memory, in rare occasion of full-size bitstream we add 10 bytes
+ * of guard. */
+#define INTERNAL_STREAM_SIZE_W16 (STREAM_MAXW16 + 5)
+
+/* storage size for bit counts */
+//#define BIT_COUNTER_SIZE 30
+/* maximum order of any AR model or filter */
+#define MAX_AR_MODEL_ORDER 12
+
+/* Maximum number of iterations allowed to limit payload size */
+#define MAX_PAYLOAD_LIMIT_ITERATION 1
+
+/* Bandwidth estimator */
+
+#define MIN_ISAC_BW 10000 /* Minimum bandwidth in bits per sec */
+#define MAX_ISAC_BW 32000 /* Maxmum bandwidth in bits per sec */
+#define MIN_ISAC_MD 5 /* Minimum Max Delay in ?? */
+#define MAX_ISAC_MD 25 /* Maxmum Max Delay in ?? */
+#define DELAY_CORRECTION_MAX 717
+#define DELAY_CORRECTION_MED 819
+#define Thld_30_60 18000
+#define Thld_60_30 27000
+
+/* assumed header size; we don't know the exact number (header compression may
+ * be used) */
+#define HEADER_SIZE 35 /* bytes */
+#define INIT_FRAME_LEN 60
+#define INIT_BN_EST 20000
+#define INIT_BN_EST_Q7 2560000 /* 20 kbps in Q7 */
+#define INIT_REC_BN_EST_Q5 789312 /* INIT_BN_EST + INIT_HDR_RATE in Q5 */
+
+/* 8738 in Q18 is ~ 1/30 */
+/* #define INIT_HDR_RATE (((HEADER_SIZE * 8 * 1000) * 8738) >> NUM_BITS_TO_SHIFT
+ * (INIT_FRAME_LEN)) */
+#define INIT_HDR_RATE 4666
+/* number of packets in a row for a high rate burst */
+#define BURST_LEN 3
+/* ms, max time between two full bursts */
+#define BURST_INTERVAL 800
+/* number of packets in a row for initial high rate burst */
+#define INIT_BURST_LEN 5
+/* bits/s, rate for the first BURST_LEN packets */
+#define INIT_RATE 10240000 /* INIT_BN_EST in Q9 */
+
+/* For pitch analysis */
+#define PITCH_FRAME_LEN 240 /* (FRAMESAMPLES/2) 30 ms */
+#define PITCH_MAX_LAG 140 /* 57 Hz */
+#define PITCH_MIN_LAG 20 /* 400 Hz */
+#define PITCH_MIN_LAG_Q8 5120 /* 256 * PITCH_MIN_LAG */
+#define OFFSET_Q8 768 /* 256 * 3 */
+
+#define PITCH_MAX_GAIN_Q12 1843 /* 0.45 */
+#define PITCH_LAG_SPAN2 65 /* (PITCH_MAX_LAG/2-PITCH_MIN_LAG/2+5) */
+#define PITCH_CORR_LEN2 60 /* 15 ms */
+#define PITCH_CORR_STEP2 60 /* (PITCH_FRAME_LEN/4) */
+#define PITCH_SUBFRAMES 4
+#define PITCH_SUBFRAME_LEN 60 /* (PITCH_FRAME_LEN/PITCH_SUBFRAMES) */
+
+/* For pitch filter */
+#define PITCH_BUFFSIZE \
+ 190 /* (PITCH_MAX_LAG + 50) Extra 50 for fraction and LP filters */
+#define PITCH_INTBUFFSIZE 430 /* (PITCH_FRAME_LEN+PITCH_BUFFSIZE) */
+#define PITCH_FRACS 8
+#define PITCH_FRACORDER 9
+#define PITCH_DAMPORDER 5
+
+/* Order of high pass filter */
+#define HPORDER 2
+
+/* PLC */
+#define DECAY_RATE \
+ 10 /* Q15, 20% of decay every lost frame apllied linearly sample by sample*/
+#define PLC_WAS_USED 1
+#define PLC_NOT_USED 3
+#define RECOVERY_OVERLAP 80
+#define RESAMP_RES 256
+#define RESAMP_RES_BIT 8
+
+/* Define Error codes */
+/* 6000 General */
+#define ISAC_MEMORY_ALLOCATION_FAILED 6010
+#define ISAC_MODE_MISMATCH 6020
+#define ISAC_DISALLOWED_BOTTLENECK 6030
+#define ISAC_DISALLOWED_FRAME_LENGTH 6040
+/* 6200 Bandwidth estimator */
+#define ISAC_RANGE_ERROR_BW_ESTIMATOR 6240
+/* 6400 Encoder */
+#define ISAC_ENCODER_NOT_INITIATED 6410
+#define ISAC_DISALLOWED_CODING_MODE 6420
+#define ISAC_DISALLOWED_FRAME_MODE_ENCODER 6430
+#define ISAC_DISALLOWED_BITSTREAM_LENGTH 6440
+#define ISAC_PAYLOAD_LARGER_THAN_LIMIT 6450
+/* 6600 Decoder */
+#define ISAC_DECODER_NOT_INITIATED 6610
+#define ISAC_EMPTY_PACKET 6620
+#define ISAC_PACKET_TOO_SHORT 6625
+#define ISAC_DISALLOWED_FRAME_MODE_DECODER 6630
+#define ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH 6640
+#define ISAC_RANGE_ERROR_DECODE_BANDWIDTH 6650
+#define ISAC_RANGE_ERROR_DECODE_PITCH_GAIN 6660
+#define ISAC_RANGE_ERROR_DECODE_PITCH_LAG 6670
+#define ISAC_RANGE_ERROR_DECODE_LPC 6680
+#define ISAC_RANGE_ERROR_DECODE_SPECTRUM 6690
+#define ISAC_LENGTH_MISMATCH 6730
+/* 6800 Call setup formats */
+#define ISAC_INCOMPATIBLE_FORMATS 6810
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SETTINGS_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c
new file mode 100644
index 0000000000..4ef9a338cc
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.c
+ *
+ * This file contains tables with AR coefficients, Gain coefficients
+ * and cosine tables.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/********************* AR Coefficient Tables ************************/
+
+/* cdf for quantized reflection coefficient 1 */
+const uint16_t WebRtcIsacfix_kRc1Cdf[12] = {
+ 0, 2, 4, 129, 7707, 57485, 65495, 65527, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 2 */
+const uint16_t WebRtcIsacfix_kRc2Cdf[12] = {
+ 0, 2, 4, 7, 531, 25298, 64525, 65526, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 3 */
+const uint16_t WebRtcIsacfix_kRc3Cdf[12] = {
+ 0, 2, 4, 6, 620, 22898, 64843, 65527, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 4 */
+const uint16_t WebRtcIsacfix_kRc4Cdf[12] = {
+ 0, 2, 4, 6, 35, 10034, 60733, 65506, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 5 */
+const uint16_t WebRtcIsacfix_kRc5Cdf[12] = {
+ 0, 2, 4, 6, 36, 7567, 56727, 65385, 65529, 65531,
+ 65533, 65535
+};
+
+/* cdf for quantized reflection coefficient 6 */
+const uint16_t WebRtcIsacfix_kRc6Cdf[12] = {
+ 0, 2, 4, 6, 14, 6579, 57360, 65409, 65529, 65531,
+ 65533, 65535
+};
+
+/* representation levels for quantized reflection coefficient 1 */
+const int16_t WebRtcIsacfix_kRc1Levels[11] = {
+ -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const int16_t WebRtcIsacfix_kRc2Levels[11] = {
+ -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const int16_t WebRtcIsacfix_kRc3Levels[11] = {
+ -32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const int16_t WebRtcIsacfix_kRc4Levels[11] = {
+ -32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const int16_t WebRtcIsacfix_kRc5Levels[11] = {
+ -32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const int16_t WebRtcIsacfix_kRc6Levels[11] = {
+ -32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const int16_t WebRtcIsacfix_kRcBound[12] = {
+ -32768, -31441, -27566, -21458, -13612, -4663,
+ 4663, 13612, 21458, 27566, 31441, 32767
+};
+
+/* initial index for AR reflection coefficient quantizer and cdf table search */
+const uint16_t WebRtcIsacfix_kRcInitInd[6] = {
+ 5, 5, 5, 5, 5, 5
+};
+
+/* pointers to AR cdf tables */
+const uint16_t *WebRtcIsacfix_kRcCdfPtr[AR_ORDER] = {
+ WebRtcIsacfix_kRc1Cdf,
+ WebRtcIsacfix_kRc2Cdf,
+ WebRtcIsacfix_kRc3Cdf,
+ WebRtcIsacfix_kRc4Cdf,
+ WebRtcIsacfix_kRc5Cdf,
+ WebRtcIsacfix_kRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const int16_t *WebRtcIsacfix_kRcLevPtr[AR_ORDER] = {
+ WebRtcIsacfix_kRc1Levels,
+ WebRtcIsacfix_kRc2Levels,
+ WebRtcIsacfix_kRc3Levels,
+ WebRtcIsacfix_kRc4Levels,
+ WebRtcIsacfix_kRc5Levels,
+ WebRtcIsacfix_kRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+
+/* cdf for Gain coefficient */
+const uint16_t WebRtcIsacfix_kGainCdf[19] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 1172,
+ 11119, 29411, 51699, 64445, 65527, 65529, 65531, 65533, 65535
+};
+
+/* representation levels for quantized squared Gain coefficient */
+const int32_t WebRtcIsacfix_kGain2Lev[18] = {
+ 128, 128, 128, 128, 128, 215, 364, 709, 1268,
+ 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000
+};
+
+/* quantization boundary levels for squared Gain coefficient */
+const int32_t WebRtcIsacfix_kGain2Bound[19] = {
+ 0, 21, 35, 59, 99, 166, 280, 475, 815, 1414,
+ 2495, 4505, 8397, 16405, 34431, 81359, 240497, 921600, 0x7FFFFFFF
+};
+
+/* pointers to Gain cdf table */
+const uint16_t *WebRtcIsacfix_kGainPtr[1] = {
+ WebRtcIsacfix_kGainCdf
+};
+
+/* gain initial index for gain quantizer and cdf table search */
+const uint16_t WebRtcIsacfix_kGainInitInd[1] = {
+ 11
+};
+
+
+/************************* Cosine Tables ****************************/
+
+/* cosine table */
+const int16_t WebRtcIsacfix_kCos[6][60] = {
+ { 512, 512, 511, 510, 508, 507, 505, 502, 499, 496,
+ 493, 489, 485, 480, 476, 470, 465, 459, 453, 447,
+ 440, 433, 426, 418, 410, 402, 394, 385, 376, 367,
+ 357, 348, 338, 327, 317, 306, 295, 284, 273, 262,
+ 250, 238, 226, 214, 202, 190, 177, 165, 152, 139,
+ 126, 113, 100, 87, 73, 60, 47, 33, 20, 7 },
+ { 512, 510, 508, 503, 498, 491, 483, 473, 462, 450,
+ 437, 422, 406, 389, 371, 352, 333, 312, 290, 268,
+ 244, 220, 196, 171, 145, 120, 93, 67, 40, 13,
+ -13, -40, -67, -93, -120, -145, -171, -196, -220, -244,
+ -268, -290, -312, -333, -352, -371, -389, -406, -422, -437,
+ -450, -462, -473, -483, -491, -498, -503, -508, -510, -512 },
+ { 512, 508, 502, 493, 480, 465, 447, 426, 402, 376,
+ 348, 317, 284, 250, 214, 177, 139, 100, 60, 20,
+ -20, -60, -100, -139, -177, -214, -250, -284, -317, -348,
+ -376, -402, -426, -447, -465, -480, -493, -502, -508, -512,
+ -512, -508, -502, -493, -480, -465, -447, -426, -402, -376,
+ -348, -317, -284, -250, -214, -177, -139, -100, -60, -20 },
+ { 511, 506, 495, 478, 456, 429, 398, 362, 322, 279,
+ 232, 183, 133, 80, 27, -27, -80, -133, -183, -232,
+ -279, -322, -362, -398, -429, -456, -478, -495, -506, -511,
+ -511, -506, -495, -478, -456, -429, -398, -362, -322, -279,
+ -232, -183, -133, -80, -27, 27, 80, 133, 183, 232,
+ 279, 322, 362, 398, 429, 456, 478, 495, 506, 511 },
+ { 511, 502, 485, 459, 426, 385, 338, 284, 226, 165,
+ 100, 33, -33, -100, -165, -226, -284, -338, -385, -426,
+ -459, -485, -502, -511, -511, -502, -485, -459, -426, -385,
+ -338, -284, -226, -165, -100, -33, 33, 100, 165, 226,
+ 284, 338, 385, 426, 459, 485, 502, 511, 511, 502,
+ 485, 459, 426, 385, 338, 284, 226, 165, 100, 33 },
+ { 510, 498, 473, 437, 389, 333, 268, 196, 120, 40,
+ -40, -120, -196, -268, -333, -389, -437, -473, -498, -510,
+ -510, -498, -473, -437, -389, -333, -268, -196, -120, -40,
+ 40, 120, 196, 268, 333, 389, 437, 473, 498, 510,
+ 510, 498, 473, 437, 389, 333, 268, 196, 120, 40,
+ -40, -120, -196, -268, -333, -389, -437, -473, -498, -510 }
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
new file mode 100644
index 0000000000..2282a369cb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.h
+ *
+ * This file contains definitions of tables with AR coefficients,
+ * Gain coefficients and cosine tables.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const uint16_t WebRtcIsacfix_kRc1Cdf[12];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const uint16_t WebRtcIsacfix_kRc2Cdf[12];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const uint16_t WebRtcIsacfix_kRc3Cdf[12];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const uint16_t WebRtcIsacfix_kRc4Cdf[12];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const uint16_t WebRtcIsacfix_kRc5Cdf[12];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const uint16_t WebRtcIsacfix_kRc6Cdf[12];
+
+/* representation levels for quantized reflection coefficient 1 */
+extern const int16_t WebRtcIsacfix_kRc1Levels[11];
+
+/* representation levels for quantized reflection coefficient 2 */
+extern const int16_t WebRtcIsacfix_kRc2Levels[11];
+
+/* representation levels for quantized reflection coefficient 3 */
+extern const int16_t WebRtcIsacfix_kRc3Levels[11];
+
+/* representation levels for quantized reflection coefficient 4 */
+extern const int16_t WebRtcIsacfix_kRc4Levels[11];
+
+/* representation levels for quantized reflection coefficient 5 */
+extern const int16_t WebRtcIsacfix_kRc5Levels[11];
+
+/* representation levels for quantized reflection coefficient 6 */
+extern const int16_t WebRtcIsacfix_kRc6Levels[11];
+
+/* quantization boundary levels for reflection coefficients */
+extern const int16_t WebRtcIsacfix_kRcBound[12];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search
+ */
+extern const uint16_t WebRtcIsacfix_kRcInitInd[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const uint16_t* WebRtcIsacfix_kRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const int16_t* WebRtcIsacfix_kRcLevPtr[AR_ORDER];
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const uint16_t WebRtcIsacfix_kGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const int32_t WebRtcIsacfix_kGain2Lev[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const int32_t WebRtcIsacfix_kGain2Bound[19];
+
+/* pointer to Gain cdf table */
+extern const uint16_t* WebRtcIsacfix_kGainPtr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const uint16_t WebRtcIsacfix_kGainInitInd[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const int16_t WebRtcIsacfix_kCos[6][60];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ \
+ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/structs.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/structs.h
new file mode 100644
index 0000000000..3044d5176b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/structs.h
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * structs.h
+ *
+ * This header file contains all the structs used in the ISAC codec
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* Bitstream struct for decoder */
+typedef struct Bitstreamstruct_dec {
+ uint16_t stream[INTERNAL_STREAM_SIZE_W16]; /* Array bytestream to decode */
+ uint32_t W_upper; /* Upper boundary of interval W */
+ uint32_t streamval;
+ uint16_t stream_index; /* Index to the current position in bytestream */
+ int16_t full; /* 0 - first byte in memory filled, second empty*/
+ /* 1 - both bytes are empty (we just filled the previous memory */
+
+ size_t stream_size; /* The size of stream in bytes. */
+} Bitstr_dec;
+
+/* Bitstream struct for encoder */
+typedef struct Bitstreamstruct_enc {
+ uint16_t
+ stream[STREAM_MAXW16_60MS]; /* Vector for adding encoded bytestream */
+ uint32_t W_upper; /* Upper boundary of interval W */
+ uint32_t streamval;
+ uint16_t stream_index; /* Index to the current position in bytestream */
+ int16_t full; /* 0 - first byte in memory filled, second empty*/
+ /* 1 - both bytes are empty (we just filled the previous memory */
+
+} Bitstr_enc;
+
+typedef struct {
+ int16_t DataBufferLoQ0[WINLEN];
+ int16_t DataBufferHiQ0[WINLEN];
+
+ int32_t CorrBufLoQQ[ORDERLO + 1];
+ int32_t CorrBufHiQQ[ORDERHI + 1];
+
+ int16_t CorrBufLoQdom[ORDERLO + 1];
+ int16_t CorrBufHiQdom[ORDERHI + 1];
+
+ int32_t PreStateLoGQ15[ORDERLO + 1];
+ int32_t PreStateHiGQ15[ORDERHI + 1];
+
+ uint32_t OldEnergy;
+
+} MaskFiltstr_enc;
+
+typedef struct {
+ int16_t PostStateLoGQ0[ORDERLO + 1];
+ int16_t PostStateHiGQ0[ORDERHI + 1];
+
+ uint32_t OldEnergy;
+
+} MaskFiltstr_dec;
+
+typedef struct {
+ // state vectors for each of the two analysis filters
+
+ int32_t INSTAT1_fix[2 * (QORDER - 1)];
+ int32_t INSTAT2_fix[2 * (QORDER - 1)];
+ int16_t INLABUF1_fix[QLOOKAHEAD];
+ int16_t INLABUF2_fix[QLOOKAHEAD];
+
+ /* High pass filter */
+ int32_t HPstates_fix[HPORDER];
+
+} PreFiltBankstr;
+
+typedef struct {
+ // state vectors for each of the two analysis filters
+ int32_t STATE_0_LOWER_fix[2 * POSTQORDER];
+ int32_t STATE_0_UPPER_fix[2 * POSTQORDER];
+
+ /* High pass filter */
+
+ int32_t HPstates1_fix[HPORDER];
+ int32_t HPstates2_fix[HPORDER];
+
+} PostFiltBankstr;
+
+typedef struct {
+ /* data buffer for pitch filter */
+ int16_t ubufQQ[PITCH_BUFFSIZE];
+
+ /* low pass state vector */
+ int16_t ystateQQ[PITCH_DAMPORDER];
+
+ /* old lag and gain */
+ int16_t oldlagQ7;
+ int16_t oldgainQ12;
+
+} PitchFiltstr;
+
+typedef struct {
+ // for inital estimator
+ int16_t dec_buffer16[PITCH_CORR_LEN2 + PITCH_CORR_STEP2 + PITCH_MAX_LAG / 2 -
+ PITCH_FRAME_LEN / 2 + 2];
+ int32_t decimator_state32[2 * ALLPASSSECTIONS + 1];
+ int16_t inbuf[QLOOKAHEAD];
+
+ PitchFiltstr PFstr_wght;
+ PitchFiltstr PFstr;
+
+} PitchAnalysisStruct;
+
+typedef struct {
+ /* Parameters used in PLC to avoid re-computation */
+
+ /* --- residual signals --- */
+ int16_t prevPitchInvIn[FRAMESAMPLES / 2];
+ int16_t prevPitchInvOut[PITCH_MAX_LAG + 10]; // [FRAMESAMPLES/2]; save 90
+ int32_t prevHP[PITCH_MAX_LAG + 10]; // [FRAMESAMPLES/2]; save 90
+
+ int16_t decayCoeffPriodic; /* how much to supress a sample */
+ int16_t decayCoeffNoise;
+ int16_t used; /* if PLC is used */
+
+ int16_t* lastPitchLP; // [FRAMESAMPLES/2]; saved 240;
+
+ /* --- LPC side info --- */
+ int16_t lofilt_coefQ15[ORDERLO];
+ int16_t hifilt_coefQ15[ORDERHI];
+ int32_t gain_lo_hiQ17[2];
+
+ /* --- LTP side info --- */
+ int16_t AvgPitchGain_Q12;
+ int16_t lastPitchGain_Q12;
+ int16_t lastPitchLag_Q7;
+
+ /* --- Add-overlap in recovery packet --- */
+ int16_t overlapLP[RECOVERY_OVERLAP]; // [FRAMESAMPLES/2]; saved 160
+
+ int16_t pitchCycles;
+ int16_t A;
+ int16_t B;
+ size_t pitchIndex;
+ size_t stretchLag;
+ int16_t* prevPitchLP; // [ FRAMESAMPLES/2 ]; saved 240
+ int16_t seed;
+
+ int16_t std;
+} PLCstr;
+
+/* Have instance of struct together with other iSAC structs */
+typedef struct {
+ int16_t prevFrameSizeMs; /* Previous frame size (in ms) */
+ uint16_t prevRtpNumber; /* Previous RTP timestamp from received packet */
+ /* (in samples relative beginning) */
+ uint32_t prevSendTime; /* Send time for previous packet, from RTP header */
+ uint32_t prevArrivalTime; /* Arrival time for previous packet (in ms using
+ timeGetTime()) */
+ uint16_t prevRtpRate; /* rate of previous packet, derived from RTP timestamps
+ (in bits/s) */
+ uint32_t lastUpdate; /* Time since the last update of the Bottle Neck estimate
+ (in samples) */
+ uint32_t lastReduction; /* Time sinse the last reduction (in samples) */
+ int32_t countUpdates; /* How many times the estimate was update in the
+ beginning */
+
+ /* The estimated bottle neck rate from there to here (in bits/s) */
+ uint32_t recBw;
+ uint32_t recBwInv;
+ uint32_t recBwAvg;
+ uint32_t recBwAvgQ;
+
+ uint32_t minBwInv;
+ uint32_t maxBwInv;
+
+ /* The estimated mean absolute jitter value, as seen on this side (in ms) */
+ int32_t recJitter;
+ int32_t recJitterShortTerm;
+ int32_t recJitterShortTermAbs;
+ int32_t recMaxDelay;
+ int32_t recMaxDelayAvgQ;
+
+ int16_t recHeaderRate; /* (assumed) bitrate for headers (bps) */
+
+ uint32_t sendBwAvg; /* The estimated bottle neck rate from here to there (in
+ bits/s) */
+ int32_t sendMaxDelayAvg; /* The estimated mean absolute jitter value, as seen
+ on the other siee (in ms) */
+
+ int16_t countRecPkts; /* number of packets received since last update */
+ int16_t highSpeedRec; /* flag for marking that a high speed network has been
+ detected downstream */
+
+ /* number of consecutive pkts sent during which the bwe estimate has
+ remained at a value greater than the downstream threshold for determining
+ highspeed network */
+ int16_t countHighSpeedRec;
+
+ /* flag indicating bwe should not adjust down immediately for very late pckts
+ */
+ int16_t inWaitPeriod;
+
+ /* variable holding the time of the start of a window of time when
+ bwe should not adjust down immediately for very late pckts */
+ uint32_t startWaitPeriod;
+
+ /* number of consecutive pkts sent during which the bwe estimate has
+ remained at a value greater than the upstream threshold for determining
+ highspeed network */
+ int16_t countHighSpeedSent;
+
+ /* flag indicated the desired number of packets over threshold rate have been
+ sent and bwe will assume the connection is over broadband network */
+ int16_t highSpeedSend;
+
+ IsacBandwidthInfo external_bw_info;
+} BwEstimatorstr;
+
+typedef struct {
+ /* boolean, flags if previous packet exceeded B.N. */
+ int16_t PrevExceed;
+ /* ms */
+ int16_t ExceedAgo;
+ /* packets left to send in current burst */
+ int16_t BurstCounter;
+ /* packets */
+ int16_t InitCounter;
+ /* ms remaining in buffer when next packet will be sent */
+ int16_t StillBuffered;
+
+} RateModel;
+
+/* The following strutc is used to store data from encoding, to make it
+ fast and easy to construct a new bitstream with a different Bandwidth
+ estimate. All values (except framelength and minBytes) is double size to
+ handle 60 ms of data.
+*/
+typedef struct {
+ /* Used to keep track of if it is first or second part of 60 msec packet */
+ int startIdx;
+
+ /* Frame length in samples */
+ int16_t framelength;
+
+ /* Pitch Gain */
+ int16_t pitchGain_index[2];
+
+ /* Pitch Lag */
+ int32_t meanGain[2];
+ int16_t pitchIndex[PITCH_SUBFRAMES * 2];
+
+ /* LPC */
+ int32_t LPCcoeffs_g[12 * 2]; /* KLT_ORDER_GAIN = 12 */
+ int16_t LPCindex_s[108 * 2]; /* KLT_ORDER_SHAPE = 108 */
+ int16_t LPCindex_g[12 * 2]; /* KLT_ORDER_GAIN = 12 */
+
+ /* Encode Spec */
+ int16_t fre[FRAMESAMPLES];
+ int16_t fim[FRAMESAMPLES];
+ int16_t AvgPitchGain[2];
+
+ /* Used in adaptive mode only */
+ int minBytes;
+
+} IsacSaveEncoderData;
+
+typedef struct {
+ Bitstr_enc bitstr_obj;
+ MaskFiltstr_enc maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PitchAnalysisStruct pitchanalysisstr_obj;
+ RateModel rate_data_obj;
+
+ int16_t buffer_index;
+ int16_t current_framesamples;
+
+ int16_t data_buffer_fix[FRAMESAMPLES]; // the size was MAX_FRAMESAMPLES
+
+ int16_t frame_nb;
+ int16_t BottleNeck;
+ int16_t MaxDelay;
+ int16_t new_framelength;
+ int16_t s2nr;
+ uint16_t MaxBits;
+
+ int16_t bitstr_seed;
+
+ IsacSaveEncoderData* SaveEnc_ptr;
+ int16_t payloadLimitBytes30; /* Maximum allowed number of bits for a 30 msec
+ packet */
+ int16_t payloadLimitBytes60; /* Maximum allowed number of bits for a 30 msec
+ packet */
+ int16_t maxPayloadBytes; /* Maximum allowed number of bits for both 30 and 60
+ msec packet */
+ int16_t maxRateInBytes; /* Maximum allowed rate in bytes per 30 msec packet */
+ int16_t enforceFrameSize; /* If set iSAC will never change packet size */
+
+} IsacFixEncoderInstance;
+
+typedef struct {
+ Bitstr_dec bitstr_obj;
+ MaskFiltstr_dec maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PLCstr plcstr_obj; /* TS; for packet loss concealment */
+} IsacFixDecoderInstance;
+
+typedef struct {
+ IsacFixEncoderInstance ISACenc_obj;
+ IsacFixDecoderInstance ISACdec_obj;
+ BwEstimatorstr bwestimator_obj;
+ int16_t CodingMode; /* 0 = adaptive; 1 = instantaneous */
+ int16_t errorcode;
+ int16_t initflag; /* 0 = nothing initiated; 1 = encoder or decoder */
+ /* not initiated; 2 = all initiated */
+} ISACFIX_SubStruct;
+
+typedef struct {
+ int32_t lpcGains[12]; /* 6 lower-band & 6 upper-band we may need to double it
+ for 60*/
+ /* */
+ uint32_t W_upper; /* Upper boundary of interval W */
+ uint32_t streamval;
+ uint16_t stream_index; /* Index to the current position in bytestream */
+ int16_t full; /* 0 - first byte in memory filled, second empty*/
+ /* 1 - both bytes are empty (we just filled the previous memory */
+ uint16_t beforeLastWord;
+ uint16_t lastWord;
+} transcode_obj;
+
+// Bitstr_enc myBitStr;
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_STRUCTS_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform.c
new file mode 100644
index 0000000000..80b244b5f1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * WebRtcIsacfix_kTransform.c
+ *
+ * Transform functions
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/third_party/fft/fft.h"
+
+/* Tables are defined in transform_tables.c file or ARM assembly files. */
+/* Cosine table 1 in Q14 */
+extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
+/* Sine table 1 in Q14 */
+extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
+/* Sine table 2 in Q14 */
+extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
+
+void WebRtcIsacfix_Time2SpecC(int16_t *inre1Q9,
+ int16_t *inre2Q9,
+ int16_t *outreQ7,
+ int16_t *outimQ7)
+{
+
+ int k;
+ int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
+ int16_t tmp1rQ14, tmp1iQ14;
+ int32_t xrQ16, xiQ16, yrQ16, yiQ16;
+ int32_t v1Q16, v2Q16;
+ int16_t factQ19, sh;
+
+ /* Multiply with complex exponentials and combine into one complex vector */
+ factQ19 = 16921; // 0.5/sqrt(240) in Q19 is round(.5/sqrt(240)*(2^19)) = 16921
+ for (k = 0; k < FRAMESAMPLES/2; k++) {
+ tmp1rQ14 = WebRtcIsacfix_kCosTab1[k];
+ tmp1iQ14 = WebRtcIsacfix_kSinTab1[k];
+ xrQ16 = (tmp1rQ14 * inre1Q9[k] + tmp1iQ14 * inre2Q9[k]) >> 7;
+ xiQ16 = (tmp1rQ14 * inre2Q9[k] - tmp1iQ14 * inre1Q9[k]) >> 7;
+ // Q-domains below: (Q16*Q19>>16)>>3 = Q16
+ tmpreQ16[k] = (WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xrQ16) + 4) >> 3;
+ tmpimQ16[k] = (WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xiQ16) + 4) >> 3;
+ }
+
+
+ xrQ16 = WebRtcSpl_MaxAbsValueW32(tmpreQ16, FRAMESAMPLES/2);
+ yrQ16 = WebRtcSpl_MaxAbsValueW32(tmpimQ16, FRAMESAMPLES/2);
+ if (yrQ16>xrQ16) {
+ xrQ16 = yrQ16;
+ }
+
+ sh = WebRtcSpl_NormW32(xrQ16);
+ sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
+ //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ inre1Q9[k] = (int16_t)(tmpreQ16[k] << sh); // Q(16+sh)
+ inre2Q9[k] = (int16_t)(tmpimQ16[k] << sh); // Q(16+sh)
+ }
+ } else {
+ int32_t round = 1 << (-sh - 1);
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ inre1Q9[k] = (int16_t)((tmpreQ16[k] + round) >> -sh); // Q(16+sh)
+ inre2Q9[k] = (int16_t)((tmpimQ16[k] + round) >> -sh); // Q(16+sh)
+ }
+ }
+
+ /* Get DFT */
+ WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ tmpreQ16[k] = inre1Q9[k] >> sh; // Q(16+sh) -> Q16
+ tmpimQ16[k] = inre2Q9[k] >> sh; // Q(16+sh) -> Q16
+ }
+ } else {
+ for (k=0; k<FRAMESAMPLES/2; k++) {
+ tmpreQ16[k] = inre1Q9[k] << -sh; // Q(16+sh) -> Q16
+ tmpimQ16[k] = inre2Q9[k] << -sh; // Q(16+sh) -> Q16
+ }
+ }
+
+
+ /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+ for (k = 0; k < FRAMESAMPLES/4; k++) {
+ xrQ16 = tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
+ yiQ16 = -tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
+ xiQ16 = tmpimQ16[k] - tmpimQ16[FRAMESAMPLES/2 - 1 - k];
+ yrQ16 = tmpimQ16[k] + tmpimQ16[FRAMESAMPLES/2 - 1 - k];
+ tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k];
+ tmp1iQ14 = WebRtcIsacfix_kSinTab2[k];
+ v1Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xiQ16);
+ v2Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xiQ16);
+ outreQ7[k] = (int16_t)(v1Q16 >> 9);
+ outimQ7[k] = (int16_t)(v2Q16 >> 9);
+ v1Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yiQ16);
+ v2Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yiQ16);
+ // CalcLrIntQ(v1Q16, 9);
+ outreQ7[FRAMESAMPLES / 2 - 1 - k] = (int16_t)(v1Q16 >> 9);
+ // CalcLrIntQ(v2Q16, 9);
+ outimQ7[FRAMESAMPLES / 2 - 1 - k] = (int16_t)(v2Q16 >> 9);
+
+ }
+}
+
+
+void WebRtcIsacfix_Spec2TimeC(int16_t *inreQ7, int16_t *inimQ7, int32_t *outre1Q16, int32_t *outre2Q16)
+{
+
+ int k;
+ int16_t tmp1rQ14, tmp1iQ14;
+ int32_t xrQ16, xiQ16, yrQ16, yiQ16;
+ int32_t tmpInRe, tmpInIm, tmpInRe2, tmpInIm2;
+ int16_t factQ11;
+ int16_t sh;
+
+ for (k = 0; k < FRAMESAMPLES/4; k++) {
+ /* Move zero in time to beginning of frames */
+ tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k];
+ tmp1iQ14 = WebRtcIsacfix_kSinTab2[k];
+
+ tmpInRe = inreQ7[k] * (1 << 9); // Q7 -> Q16
+ tmpInIm = inimQ7[k] * (1 << 9); // Q7 -> Q16
+ tmpInRe2 = inreQ7[FRAMESAMPLES / 2 - 1 - k] * (1 << 9); // Q7 -> Q16
+ tmpInIm2 = inimQ7[FRAMESAMPLES / 2 - 1 - k] * (1 << 9); // Q7 -> Q16
+
+ xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm);
+ xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe);
+ yrQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm2) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe2);
+ yiQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe2) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm2);
+
+ /* Combine into one vector, z = x + j * y */
+ outre1Q16[k] = xrQ16 - yiQ16;
+ outre1Q16[FRAMESAMPLES/2 - 1 - k] = xrQ16 + yiQ16;
+ outre2Q16[k] = xiQ16 + yrQ16;
+ outre2Q16[FRAMESAMPLES/2 - 1 - k] = -xiQ16 + yrQ16;
+ }
+
+ /* Get IDFT */
+ tmpInRe = WebRtcSpl_MaxAbsValueW32(outre1Q16, 240);
+ tmpInIm = WebRtcSpl_MaxAbsValueW32(outre2Q16, 240);
+ if (tmpInIm>tmpInRe) {
+ tmpInRe = tmpInIm;
+ }
+
+ sh = WebRtcSpl_NormW32(tmpInRe);
+ sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
+ //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<240; k++) {
+ inreQ7[k] = (int16_t)(outre1Q16[k] << sh); // Q(16+sh)
+ inimQ7[k] = (int16_t)(outre2Q16[k] << sh); // Q(16+sh)
+ }
+ } else {
+ int32_t round = 1 << (-sh - 1);
+ for (k=0; k<240; k++) {
+ inreQ7[k] = (int16_t)((outre1Q16[k] + round) >> -sh); // Q(16+sh)
+ inimQ7[k] = (int16_t)((outre2Q16[k] + round) >> -sh); // Q(16+sh)
+ }
+ }
+
+ WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call
+
+ //"Fastest" vectors
+ if (sh>=0) {
+ for (k=0; k<240; k++) {
+ outre1Q16[k] = inreQ7[k] >> sh; // Q(16+sh) -> Q16
+ outre2Q16[k] = inimQ7[k] >> sh; // Q(16+sh) -> Q16
+ }
+ } else {
+ for (k=0; k<240; k++) {
+ outre1Q16[k] = inreQ7[k] * (1 << -sh); // Q(16+sh) -> Q16
+ outre2Q16[k] = inimQ7[k] * (1 << -sh); // Q(16+sh) -> Q16
+ }
+ }
+
+ /* Divide through by the normalizing constant: */
+ /* scale all values with 1/240, i.e. with 273 in Q16 */
+ /* 273/65536 ~= 0.0041656 */
+ /* 1/240 ~= 0.0041666 */
+ for (k=0; k<240; k++) {
+ outre1Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre1Q16[k]);
+ outre2Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k]);
+ }
+
+ /* Demodulate and separate */
+ factQ11 = 31727; // sqrt(240) in Q11 is round(15.49193338482967*2048) = 31727
+ for (k = 0; k < FRAMESAMPLES/2; k++) {
+ tmp1rQ14 = WebRtcIsacfix_kCosTab1[k];
+ tmp1iQ14 = WebRtcIsacfix_kSinTab1[k];
+ xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre1Q16[k]) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre2Q16[k]);
+ xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre2Q16[k]) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre1Q16[k]);
+ xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16);
+ xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16);
+ outre2Q16[k] = xiQ16;
+ outre1Q16[k] = xrQ16;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_mips.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_mips.c
new file mode 100644
index 0000000000..a87b3b54f2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_mips.c
@@ -0,0 +1,1294 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// The tables are defined in transform_tables.c file.
+extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
+extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
+extern const int16_t WebRtcIsacfix_kCosTab2[FRAMESAMPLES/4];
+extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
+
+// MIPS DSPr2 version of the WebRtcIsacfix_Time2Spec function
+// is not bit-exact with the C version.
+// The accuracy of the MIPS DSPr2 version is same or better.
+void WebRtcIsacfix_Time2SpecMIPS(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int16_t* outreQ7,
+ int16_t* outimQ7) {
+ int k = FRAMESAMPLES / 2;
+ int32_t tmpreQ16[FRAMESAMPLES / 2], tmpimQ16[FRAMESAMPLES / 2];
+ int32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
+ int32_t inre1, inre2, tmpre, tmpim, factor, max, max1;
+ int16_t* cosptr;
+ int16_t* sinptr;
+
+ cosptr = (int16_t*)WebRtcIsacfix_kCosTab1;
+ sinptr = (int16_t*)WebRtcIsacfix_kSinTab1;
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[inre1], %[inre1Q9], 0 \n\t"
+ "addiu %[inre2], %[inre2Q9], 0 \n\t"
+ "addiu %[tmpre], %[tmpreQ16], 0 \n\t"
+ "addiu %[tmpim], %[tmpimQ16], 0 \n\t"
+ "addiu %[factor], $zero, 16921 \n\t"
+ "mul %[max], $zero, $zero \n\t"
+ // Multiply with complex exponentials and combine into one complex vector.
+ // Also, calculate the maximal absolute value in the same loop.
+ "1: \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "lwl %[r0], 0(%[inre1]) \n\t"
+ "lwl %[r2], 0(%[cosptr]) \n\t"
+ "lwl %[r3], 0(%[sinptr]) \n\t"
+ "lwl %[r1], 0(%[inre2]) \n\t"
+ "lwr %[r0], 0(%[inre1]) \n\t"
+ "lwr %[r2], 0(%[cosptr]) \n\t"
+ "lwr %[r3], 0(%[sinptr]) \n\t"
+ "lwr %[r1], 0(%[inre2]) \n\t"
+ "muleq_s.w.phr %[r4], %[r2], %[r0] \n\t"
+ "muleq_s.w.phr %[r5], %[r3], %[r0] \n\t"
+ "muleq_s.w.phr %[r6], %[r3], %[r1] \n\t"
+ "muleq_s.w.phr %[r7], %[r2], %[r1] \n\t"
+ "muleq_s.w.phl %[r8], %[r2], %[r0] \n\t"
+ "muleq_s.w.phl %[r0], %[r3], %[r0] \n\t"
+ "muleq_s.w.phl %[r3], %[r3], %[r1] \n\t"
+ "muleq_s.w.phl %[r1], %[r2], %[r1] \n\t"
+ "addiu %[k], %[k], -2 \n\t"
+ "addu %[r4], %[r4], %[r6] \n\t"
+ "subu %[r5], %[r7], %[r5] \n\t"
+ "sra %[r4], %[r4], 8 \n\t"
+ "sra %[r5], %[r5], 8 \n\t"
+ "mult $ac0, %[factor], %[r4] \n\t"
+ "mult $ac1, %[factor], %[r5] \n\t"
+ "addu %[r3], %[r8], %[r3] \n\t"
+ "subu %[r0], %[r1], %[r0] \n\t"
+ "sra %[r3], %[r3], 8 \n\t"
+ "sra %[r0], %[r0], 8 \n\t"
+ "mult $ac2, %[factor], %[r3] \n\t"
+ "mult $ac3, %[factor], %[r0] \n\t"
+ "extr_r.w %[r4], $ac0, 16 \n\t"
+ "extr_r.w %[r5], $ac1, 16 \n\t"
+ "addiu %[inre1], %[inre1], 4 \n\t"
+ "addiu %[inre2], %[inre2], 4 \n\t"
+ "extr_r.w %[r6], $ac2, 16 \n\t"
+ "extr_r.w %[r7], $ac3, 16 \n\t"
+ "addiu %[cosptr], %[cosptr], 4 \n\t"
+ "addiu %[sinptr], %[sinptr], 4 \n\t"
+ "shra_r.w %[r4], %[r4], 3 \n\t"
+ "shra_r.w %[r5], %[r5], 3 \n\t"
+ "sw %[r4], 0(%[tmpre]) \n\t"
+ "absq_s.w %[r4], %[r4] \n\t"
+ "sw %[r5], 0(%[tmpim]) \n\t"
+ "absq_s.w %[r5], %[r5] \n\t"
+ "shra_r.w %[r6], %[r6], 3 \n\t"
+ "shra_r.w %[r7], %[r7], 3 \n\t"
+ "sw %[r6], 4(%[tmpre]) \n\t"
+ "absq_s.w %[r6], %[r6] \n\t"
+ "sw %[r7], 4(%[tmpim]) \n\t"
+ "absq_s.w %[r7], %[r7] \n\t"
+ "slt %[r0], %[r4], %[r5] \n\t"
+ "movn %[r4], %[r5], %[r0] \n\t"
+ "slt %[r1], %[r6], %[r7] \n\t"
+ "movn %[r6], %[r7], %[r1] \n\t"
+ "slt %[r0], %[max], %[r4] \n\t"
+ "movn %[max], %[r4], %[r0] \n\t"
+ "slt %[r1], %[max], %[r6] \n\t"
+ "movn %[max], %[r6], %[r1] \n\t"
+ "addiu %[tmpre], %[tmpre], 8 \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[tmpim], %[tmpim], 8 \n\t"
+#else // #if defined(MIPS_DSP_R2_LE)
+ "lh %[r0], 0(%[inre1]) \n\t"
+ "lh %[r1], 0(%[inre2]) \n\t"
+ "lh %[r2], 0(%[cosptr]) \n\t"
+ "lh %[r3], 0(%[sinptr]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "mul %[r4], %[r0], %[r2] \n\t"
+ "mul %[r5], %[r1], %[r3] \n\t"
+ "mul %[r0], %[r0], %[r3] \n\t"
+ "mul %[r2], %[r1], %[r2] \n\t"
+ "addiu %[inre1], %[inre1], 2 \n\t"
+ "addiu %[inre2], %[inre2], 2 \n\t"
+ "addiu %[cosptr], %[cosptr], 2 \n\t"
+ "addiu %[sinptr], %[sinptr], 2 \n\t"
+ "addu %[r1], %[r4], %[r5] \n\t"
+ "sra %[r1], %[r1], 7 \n\t"
+ "sra %[r3], %[r1], 16 \n\t"
+ "andi %[r1], %[r1], 0xFFFF \n\t"
+ "sra %[r1], %[r1], 1 \n\t"
+ "mul %[r1], %[factor], %[r1] \n\t"
+ "mul %[r3], %[factor], %[r3] \n\t"
+ "subu %[r0], %[r2], %[r0] \n\t"
+ "sra %[r0], %[r0], 7 \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "sra %[r0], %[r0], 1 \n\t"
+ "mul %[r0], %[factor], %[r0] \n\t"
+ "mul %[r2], %[factor], %[r2] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r1], %[r1], 15 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r1], %[r1], 0x4000 \n\t"
+ "sra %[r1], %[r1], 15 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r1], %[r3], %[r1] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r1], %[r1], 3 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r1], %[r1], 4 \n\t"
+ "sra %[r1], %[r1], 3 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sw %[r1], 0(%[tmpre]) \n\t"
+ "addiu %[tmpre], %[tmpre], 4 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "absq_s.w %[r1], %[r1] \n\t"
+ "shra_r.w %[r0], %[r0], 15 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "negu %[r4], %[r1] \n\t"
+ "slt %[r3], %[r1], $zero \n\t"
+ "movn %[r1], %[r4], %[r3] \n\t"
+ "addiu %[r0], %[r0], 0x4000 \n\t"
+ "sra %[r0], %[r0], 15 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r2] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r0], %[r0], 3 \n\t"
+ "sw %[r0], 0(%[tmpim]) \n\t"
+ "absq_s.w %[r0], %[r0] \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r0], %[r0], 4 \n\t"
+ "sra %[r0], %[r0], 3 \n\t"
+ "sw %[r0], 0(%[tmpim]) \n\t"
+ "negu %[r2], %[r0] \n\t"
+ "slt %[r3], %[r0], $zero \n\t"
+ "movn %[r0], %[r2], %[r3] \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "slt %[r2], %[max], %[r1] \n\t"
+ "movn %[max], %[r1], %[r2] \n\t"
+ "slt %[r2], %[max], %[r0] \n\t"
+ "movn %[max], %[r0], %[r2] \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[tmpim], %[tmpim], 4 \n\t"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ // Calculate WebRtcSpl_NormW32(max).
+ // If max gets value >=0, we should shift max steps to the left, and the
+ // domain will be Q(16+shift). If max gets value <0, we should shift -max
+ // steps to the right, and the domain will be Q(16+max)
+ "clz %[max], %[max] \n\t"
+ "addiu %[max], %[max], -25 \n\t"
+ ".set pop \n\t"
+ : [k] "+r" (k), [inre1] "=&r" (inre1), [inre2] "=&r" (inre2),
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2),
+ [r3] "=&r" (r3), [r4] "=&r" (r4), [tmpre] "=&r" (tmpre),
+ [tmpim] "=&r" (tmpim), [max] "=&r" (max), [factor] "=&r" (factor),
+#if defined(MIPS_DSP_R2_LE)
+ [r6] "=&r" (r6), [r7] "=&r" (r7), [r8] "=&r" (r8),
+#endif // #if defined(MIPS_DSP_R2_LE)
+ [r5] "=&r" (r5)
+ : [inre1Q9] "r" (inre1Q9), [inre2Q9] "r" (inre2Q9),
+ [tmpreQ16] "r" (tmpreQ16), [tmpimQ16] "r" (tmpimQ16),
+ [cosptr] "r" (cosptr), [sinptr] "r" (sinptr)
+ : "hi", "lo", "memory"
+#if defined(MIPS_DSP_R2_LE)
+ , "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ );
+
+ // "Fastest" vectors
+ k = FRAMESAMPLES / 4;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[tmpre], %[tmpreQ16], 0 \n\t"
+ "addiu %[tmpim], %[tmpimQ16], 0 \n\t"
+ "addiu %[inre1], %[inre1Q9], 0 \n\t"
+ "addiu %[inre2], %[inre2Q9], 0 \n\t"
+ "blez %[max], 2f \n\t"
+ " subu %[max1], $zero, %[max] \n\t"
+ "1: \n\t"
+ "lw %[r0], 0(%[tmpre]) \n\t"
+ "lw %[r1], 0(%[tmpim]) \n\t"
+ "lw %[r2], 4(%[tmpre]) \n\t"
+ "lw %[r3], 4(%[tmpim]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "sllv %[r0], %[r0], %[max] \n\t"
+ "sllv %[r1], %[r1], %[max] \n\t"
+ "sllv %[r2], %[r2], %[max] \n\t"
+ "sllv %[r3], %[r3], %[max] \n\t"
+ "addiu %[tmpre], %[tmpre], 8 \n\t"
+ "addiu %[tmpim], %[tmpim], 8 \n\t"
+ "sh %[r0], 0(%[inre1]) \n\t"
+ "sh %[r1], 0(%[inre2]) \n\t"
+ "sh %[r2], 2(%[inre1]) \n\t"
+ "sh %[r3], 2(%[inre2]) \n\t"
+ "addiu %[inre1], %[inre1], 4 \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[inre2], %[inre2], 4 \n\t"
+ "b 4f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+ "addiu %[r4], %[max1], -1 \n\t"
+ "addiu %[r5], $zero, 1 \n\t"
+ "sllv %[r4], %[r5], %[r4] \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ "3: \n\t"
+ "lw %[r0], 0(%[tmpre]) \n\t"
+ "lw %[r1], 0(%[tmpim]) \n\t"
+ "lw %[r2], 4(%[tmpre]) \n\t"
+ "lw %[r3], 4(%[tmpim]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shrav_r.w %[r0], %[r0], %[max1] \n\t"
+ "shrav_r.w %[r1], %[r1], %[max1] \n\t"
+ "shrav_r.w %[r2], %[r2], %[max1] \n\t"
+ "shrav_r.w %[r3], %[r3], %[max1] \n\t"
+#else // #if !defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r4] \n\t"
+ "addu %[r1], %[r1], %[r4] \n\t"
+ "addu %[r2], %[r2], %[r4] \n\t"
+ "addu %[r3], %[r3], %[r4] \n\t"
+ "srav %[r0], %[r0], %[max1] \n\t"
+ "srav %[r1], %[r1], %[max1] \n\t"
+ "srav %[r2], %[r2], %[max1] \n\t"
+ "srav %[r3], %[r3], %[max1] \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ "addiu %[tmpre], %[tmpre], 8 \n\t"
+ "addiu %[tmpim], %[tmpim], 8 \n\t"
+ "sh %[r0], 0(%[inre1]) \n\t"
+ "sh %[r1], 0(%[inre2]) \n\t"
+ "sh %[r2], 2(%[inre1]) \n\t"
+ "sh %[r3], 2(%[inre2]) \n\t"
+ "addiu %[inre1], %[inre1], 4 \n\t"
+ "bgtz %[k], 3b \n\t"
+ " addiu %[inre2], %[inre2], 4 \n\t"
+ "4: \n\t"
+ ".set pop \n\t"
+ : [tmpre] "=&r" (tmpre), [tmpim] "=&r" (tmpim), [inre1] "=&r" (inre1),
+ [inre2] "=&r" (inre2), [k] "+r" (k), [max1] "=&r" (max1),
+#if !defined(MIPS_DSP_R1_LE)
+ [r4] "=&r" (r4), [r5] "=&r" (r5),
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3)
+ : [tmpreQ16] "r" (tmpreQ16), [tmpimQ16] "r" (tmpimQ16),
+ [inre1Q9] "r" (inre1Q9), [inre2Q9] "r" (inre2Q9), [max] "r" (max)
+ : "memory"
+ );
+
+ // Get DFT
+ WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call
+
+ // "Fastest" vectors and
+ // Use symmetry to separate into two complex vectors
+ // and center frames in time around zero
+ // merged into one loop
+ cosptr = (int16_t*)WebRtcIsacfix_kCosTab2;
+ sinptr = (int16_t*)WebRtcIsacfix_kSinTab2;
+ k = FRAMESAMPLES / 4;
+ factor = FRAMESAMPLES - 2; // offset for FRAMESAMPLES / 2 - 1 array member
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[inre1], %[inre1Q9], 0 \n\t"
+ "addiu %[inre2], %[inre2Q9], 0 \n\t"
+ "addiu %[tmpre], %[outreQ7], 0 \n\t"
+ "addiu %[tmpim], %[outimQ7], 0 \n\t"
+ "bltz %[max], 2f \n\t"
+ " subu %[max1], $zero, %[max] \n\t"
+ "1: \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+ "addu %[r4], %[inre1], %[offset] \n\t"
+ "addu %[r5], %[inre2], %[offset] \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ "lh %[r0], 0(%[inre1]) \n\t"
+ "lh %[r1], 0(%[inre2]) \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "lhx %[r2], %[offset](%[inre1]) \n\t"
+ "lhx %[r3], %[offset](%[inre2]) \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "lh %[r2], 0(%[r4]) \n\t"
+ "lh %[r3], 0(%[r5]) \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "srav %[r0], %[r0], %[max] \n\t"
+ "srav %[r1], %[r1], %[max] \n\t"
+ "srav %[r2], %[r2], %[max] \n\t"
+ "srav %[r3], %[r3], %[max] \n\t"
+ "addu %[r4], %[r0], %[r2] \n\t"
+ "subu %[r0], %[r2], %[r0] \n\t"
+ "subu %[r2], %[r1], %[r3] \n\t"
+ "addu %[r1], %[r1], %[r3] \n\t"
+ "lh %[r3], 0(%[cosptr]) \n\t"
+ "lh %[r5], 0(%[sinptr]) \n\t"
+ "andi %[r6], %[r4], 0xFFFF \n\t"
+ "sra %[r4], %[r4], 16 \n\t"
+ "mul %[r7], %[r3], %[r6] \n\t"
+ "mul %[r8], %[r3], %[r4] \n\t"
+ "mul %[r6], %[r5], %[r6] \n\t"
+ "mul %[r4], %[r5], %[r4] \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "addiu %[inre1], %[inre1], 2 \n\t"
+ "addiu %[inre2], %[inre2], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r7], %[r7], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r7], %[r7], 0x2000 \n\t"
+ "sra %[r7], %[r7], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r8], %[r8], 2 \n\t"
+ "addu %[r8], %[r8], %[r7] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r6], %[r6], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r6], %[r6], 0x2000 \n\t"
+ "sra %[r6], %[r6], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r4], %[r4], 2 \n\t"
+ "addu %[r4], %[r4], %[r6] \n\t"
+ "andi %[r6], %[r2], 0xFFFF \n\t"
+ "sra %[r2], %[r2], 16 \n\t"
+ "mul %[r7], %[r5], %[r6] \n\t"
+ "mul %[r9], %[r5], %[r2] \n\t"
+ "mul %[r6], %[r3], %[r6] \n\t"
+ "mul %[r2], %[r3], %[r2] \n\t"
+ "addiu %[cosptr], %[cosptr], 2 \n\t"
+ "addiu %[sinptr], %[sinptr], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r7], %[r7], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r7], %[r7], 0x2000 \n\t"
+ "sra %[r7], %[r7], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r9], %[r9], 2 \n\t"
+ "addu %[r9], %[r7], %[r9] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r6], %[r6], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r6], %[r6], 0x2000 \n\t"
+ "sra %[r6], %[r6], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r2], %[r2], 2 \n\t"
+ "addu %[r2], %[r6], %[r2] \n\t"
+ "subu %[r8], %[r8], %[r9] \n\t"
+ "sra %[r8], %[r8], 9 \n\t"
+ "addu %[r2], %[r4], %[r2] \n\t"
+ "sra %[r2], %[r2], 9 \n\t"
+ "sh %[r8], 0(%[tmpre]) \n\t"
+ "sh %[r2], 0(%[tmpim]) \n\t"
+
+ "andi %[r4], %[r1], 0xFFFF \n\t"
+ "sra %[r1], %[r1], 16 \n\t"
+ "andi %[r6], %[r0], 0xFFFF \n\t"
+ "sra %[r0], %[r0], 16 \n\t"
+ "mul %[r7], %[r5], %[r4] \n\t"
+ "mul %[r9], %[r5], %[r1] \n\t"
+ "mul %[r4], %[r3], %[r4] \n\t"
+ "mul %[r1], %[r3], %[r1] \n\t"
+ "mul %[r8], %[r3], %[r0] \n\t"
+ "mul %[r3], %[r3], %[r6] \n\t"
+ "mul %[r6], %[r5], %[r6] \n\t"
+ "mul %[r0], %[r5], %[r0] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r7], %[r7], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r7], %[r7], 0x2000 \n\t"
+ "sra %[r7], %[r7], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r9], %[r9], 2 \n\t"
+ "addu %[r9], %[r9], %[r7] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r4], %[r4], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r4], %[r4], 0x2000 \n\t"
+ "sra %[r4], %[r4], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r1], %[r1], 2 \n\t"
+ "addu %[r1], %[r1], %[r4] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r3], %[r3], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r3], %[r3], 0x2000 \n\t"
+ "sra %[r3], %[r3], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r8], %[r8], 2 \n\t"
+ "addu %[r8], %[r8], %[r3] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r6], %[r6], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r6], %[r6], 0x2000 \n\t"
+ "sra %[r6], %[r6], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r0], %[r0], 2 \n\t"
+ "addu %[r0], %[r0], %[r6] \n\t"
+ "addu %[r3], %[tmpre], %[offset] \n\t"
+ "addu %[r2], %[tmpim], %[offset] \n\t"
+ "addu %[r9], %[r9], %[r8] \n\t"
+ "negu %[r9], %[r9] \n\t"
+ "sra %[r9], %[r9], 9 \n\t"
+ "subu %[r0], %[r0], %[r1] \n\t"
+ "addiu %[offset], %[offset], -4 \n\t"
+ "sh %[r9], 0(%[r3]) \n\t"
+ "sh %[r0], 0(%[r2]) \n\t"
+ "addiu %[tmpre], %[tmpre], 2 \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[tmpim], %[tmpim], 2 \n\t"
+ "b 3f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+ "addu %[r4], %[inre1], %[offset] \n\t"
+ "addu %[r5], %[inre2], %[offset] \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ "lh %[r0], 0(%[inre1]) \n\t"
+ "lh %[r1], 0(%[inre2]) \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "lhx %[r2], %[offset](%[inre1]) \n\t"
+ "lhx %[r3], %[offset](%[inre2]) \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "lh %[r2], 0(%[r4]) \n\t"
+ "lh %[r3], 0(%[r5]) \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sllv %[r0], %[r0], %[max1] \n\t"
+ "sllv %[r1], %[r1], %[max1] \n\t"
+ "sllv %[r2], %[r2], %[max1] \n\t"
+ "sllv %[r3], %[r3], %[max1] \n\t"
+ "addu %[r4], %[r0], %[r2] \n\t"
+ "subu %[r0], %[r2], %[r0] \n\t"
+ "subu %[r2], %[r1], %[r3] \n\t"
+ "addu %[r1], %[r1], %[r3] \n\t"
+ "lh %[r3], 0(%[cosptr]) \n\t"
+ "lh %[r5], 0(%[sinptr]) \n\t"
+ "andi %[r6], %[r4], 0xFFFF \n\t"
+ "sra %[r4], %[r4], 16 \n\t"
+ "mul %[r7], %[r3], %[r6] \n\t"
+ "mul %[r8], %[r3], %[r4] \n\t"
+ "mul %[r6], %[r5], %[r6] \n\t"
+ "mul %[r4], %[r5], %[r4] \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "addiu %[inre1], %[inre1], 2 \n\t"
+ "addiu %[inre2], %[inre2], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r7], %[r7], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r7], %[r7], 0x2000 \n\t"
+ "sra %[r7], %[r7], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r8], %[r8], 2 \n\t"
+ "addu %[r8], %[r8], %[r7] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r6], %[r6], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r6], %[r6], 0x2000 \n\t"
+ "sra %[r6], %[r6], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r4], %[r4], 2 \n\t"
+ "addu %[r4], %[r4], %[r6] \n\t"
+ "andi %[r6], %[r2], 0xFFFF \n\t"
+ "sra %[r2], %[r2], 16 \n\t"
+ "mul %[r7], %[r5], %[r6] \n\t"
+ "mul %[r9], %[r5], %[r2] \n\t"
+ "mul %[r6], %[r3], %[r6] \n\t"
+ "mul %[r2], %[r3], %[r2] \n\t"
+ "addiu %[cosptr], %[cosptr], 2 \n\t"
+ "addiu %[sinptr], %[sinptr], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r7], %[r7], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r7], %[r7], 0x2000 \n\t"
+ "sra %[r7], %[r7], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r9], %[r9], 2 \n\t"
+ "addu %[r9], %[r7], %[r9] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r6], %[r6], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r6], %[r6], 0x2000 \n\t"
+ "sra %[r6], %[r6], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r2], %[r2], 2 \n\t"
+ "addu %[r2], %[r6], %[r2] \n\t"
+ "subu %[r8], %[r8], %[r9] \n\t"
+ "sra %[r8], %[r8], 9 \n\t"
+ "addu %[r2], %[r4], %[r2] \n\t"
+ "sra %[r2], %[r2], 9 \n\t"
+ "sh %[r8], 0(%[tmpre]) \n\t"
+ "sh %[r2], 0(%[tmpim]) \n\t"
+ "andi %[r4], %[r1], 0xFFFF \n\t"
+ "sra %[r1], %[r1], 16 \n\t"
+ "andi %[r6], %[r0], 0xFFFF \n\t"
+ "sra %[r0], %[r0], 16 \n\t"
+ "mul %[r7], %[r5], %[r4] \n\t"
+ "mul %[r9], %[r5], %[r1] \n\t"
+ "mul %[r4], %[r3], %[r4] \n\t"
+ "mul %[r1], %[r3], %[r1] \n\t"
+ "mul %[r8], %[r3], %[r0] \n\t"
+ "mul %[r3], %[r3], %[r6] \n\t"
+ "mul %[r6], %[r5], %[r6] \n\t"
+ "mul %[r0], %[r5], %[r0] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r7], %[r7], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r7], %[r7], 0x2000 \n\t"
+ "sra %[r7], %[r7], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r9], %[r9], 2 \n\t"
+ "addu %[r9], %[r9], %[r7] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r4], %[r4], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r4], %[r4], 0x2000 \n\t"
+ "sra %[r4], %[r4], 14 \n\t"
+#endif
+ "sll %[r1], %[r1], 2 \n\t"
+ "addu %[r1], %[r1], %[r4] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r3], %[r3], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r3], %[r3], 0x2000 \n\t"
+ "sra %[r3], %[r3], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r8], %[r8], 2 \n\t"
+ "addu %[r8], %[r8], %[r3] \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r6], %[r6], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r6], %[r6], 0x2000 \n\t"
+ "sra %[r6], %[r6], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "sll %[r0], %[r0], 2 \n\t"
+ "addu %[r0], %[r0], %[r6] \n\t"
+ "addu %[r3], %[tmpre], %[offset] \n\t"
+ "addu %[r2], %[tmpim], %[offset] \n\t"
+ "addu %[r9], %[r9], %[r8] \n\t"
+ "negu %[r9], %[r9] \n\t"
+ "sra %[r9], %[r9], 9 \n\t"
+ "subu %[r0], %[r0], %[r1] \n\t"
+ "sra %[r0], %[r0], 9 \n\t"
+ "addiu %[offset], %[offset], -4 \n\t"
+ "sh %[r9], 0(%[r3]) \n\t"
+ "sh %[r0], 0(%[r2]) \n\t"
+ "addiu %[tmpre], %[tmpre], 2 \n\t"
+ "bgtz %[k], 2b \n\t"
+ " addiu %[tmpim], %[tmpim], 2 \n\t"
+ "3: \n\t"
+ ".set pop \n\t"
+ : [inre1] "=&r" (inre1), [inre2] "=&r" (inre2), [tmpre] "=&r" (tmpre),
+ [tmpim] "=&r" (tmpim), [offset] "+r" (factor), [k] "+r" (k),
+ [r0] "=&r" (r0), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+ [r8] "=&r" (r8), [r9] "=&r" (r9), [max1] "=&r" (max1)
+ : [inre1Q9] "r" (inre1Q9), [inre2Q9] "r" (inre2Q9),
+ [outreQ7] "r" (outreQ7), [outimQ7] "r" (outimQ7),
+ [max] "r" (max), [cosptr] "r" (cosptr), [sinptr] "r" (sinptr)
+ : "hi", "lo", "memory"
+ );
+}
+
+void WebRtcIsacfix_Spec2TimeMIPS(int16_t *inreQ7,
+ int16_t *inimQ7,
+ int32_t *outre1Q16,
+ int32_t *outre2Q16) {
+ int k = FRAMESAMPLES / 4;
+ int16_t* inre;
+ int16_t* inim;
+ int32_t* outre1;
+ int32_t* outre2;
+ int16_t* cosptr = (int16_t*)WebRtcIsacfix_kCosTab2;
+ int16_t* sinptr = (int16_t*)WebRtcIsacfix_kSinTab2;
+ int32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, max, max1;
+#if defined(MIPS_DSP_R1_LE)
+ int32_t offset = FRAMESAMPLES - 4;
+#else // #if defined(MIPS_DSP_R1_LE)
+ int32_t offset = FRAMESAMPLES - 2;
+#endif // #if defined(MIPS_DSP_R1_LE)
+
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[inre], %[inreQ7], 0 \n\t"
+ "addiu %[inim] , %[inimQ7], 0 \n\t"
+ "addiu %[outre1], %[outre1Q16], 0 \n\t"
+ "addiu %[outre2], %[outre2Q16], 0 \n\t"
+ "mul %[max], $zero, $zero \n\t"
+ "1: \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ // Process two samples in one iteration avoiding left shift before
+ // multiplication. MaxAbsValueW32 function inlined into the loop.
+ "addu %[r8], %[inre], %[offset] \n\t"
+ "addu %[r9], %[inim], %[offset] \n\t"
+ "lwl %[r4], 0(%[r8]) \n\t"
+ "lwl %[r5], 0(%[r9]) \n\t"
+ "lwl %[r0], 0(%[inre]) \n\t"
+ "lwl %[r1], 0(%[inim]) \n\t"
+ "lwl %[r2], 0(%[cosptr]) \n\t"
+ "lwl %[r3], 0(%[sinptr]) \n\t"
+ "lwr %[r4], 0(%[r8]) \n\t"
+ "lwr %[r5], 0(%[r9]) \n\t"
+ "lwr %[r0], 0(%[inre]) \n\t"
+ "lwr %[r1], 0(%[inim]) \n\t"
+ "lwr %[r2], 0(%[cosptr]) \n\t"
+ "lwr %[r3], 0(%[sinptr]) \n\t"
+ "packrl.ph %[r4], %[r4], %[r4] \n\t"
+ "packrl.ph %[r5], %[r5], %[r5] \n\t"
+ "muleq_s.w.phr %[r6], %[r0], %[r2] \n\t"
+ "muleq_s.w.phr %[r7], %[r1], %[r3] \n\t"
+ "muleq_s.w.phr %[r8], %[r4], %[r2] \n\t"
+ "muleq_s.w.phr %[r9], %[r5], %[r3] \n\t"
+ "addiu %[k], %[k], -2 \n\t"
+ "addiu %[cosptr], %[cosptr], 4 \n\t"
+ "addiu %[sinptr], %[sinptr], 4 \n\t"
+ "addiu %[inre], %[inre], 4 \n\t"
+ "addiu %[inim], %[inim], 4 \n\t"
+ "shra_r.w %[r6], %[r6], 6 \n\t"
+ "shra_r.w %[r7], %[r7], 6 \n\t"
+ "shra_r.w %[r8], %[r8], 6 \n\t"
+ "shra_r.w %[r9], %[r9], 6 \n\t"
+ "addu %[r6], %[r6], %[r7] \n\t"
+ "subu %[r9], %[r9], %[r8] \n\t"
+ "subu %[r7], %[r6], %[r9] \n\t"
+ "addu %[r6], %[r6], %[r9] \n\t"
+ "sw %[r7], 0(%[outre1]) \n\t"
+ "absq_s.w %[r7], %[r7] \n\t"
+ "slt %[r8], %[max], %[r7] \n\t"
+ "movn %[max], %[r7], %[r8] \n\t"
+ "sll %[r7], %[offset], 1 \n\t"
+ "addu %[r7], %[outre1], %[r7] \n\t"
+ "sw %[r6], 4(%[r7]) \n\t"
+ "absq_s.w %[r6], %[r6] \n\t"
+ "slt %[r8], %[max], %[r6] \n\t"
+ "movn %[max], %[r6], %[r8] \n\t"
+ "muleq_s.w.phl %[r6], %[r0], %[r2] \n\t"
+ "muleq_s.w.phl %[r7], %[r1], %[r3] \n\t"
+ "muleq_s.w.phl %[r8], %[r4], %[r2] \n\t"
+ "muleq_s.w.phl %[r9], %[r5], %[r3] \n\t"
+ "shra_r.w %[r6], %[r6], 6 \n\t"
+ "shra_r.w %[r7], %[r7], 6 \n\t"
+ "shra_r.w %[r8], %[r8], 6 \n\t"
+ "shra_r.w %[r9], %[r9], 6 \n\t"
+ "addu %[r6], %[r6], %[r7] \n\t"
+ "subu %[r9], %[r9], %[r8] \n\t"
+ "subu %[r7], %[r6], %[r9] \n\t"
+ "addu %[r6], %[r6], %[r9] \n\t"
+ "sw %[r7], 4(%[outre1]) \n\t"
+ "absq_s.w %[r7], %[r7] \n\t"
+ "slt %[r8], %[max], %[r7] \n\t"
+ "movn %[max], %[r7], %[r8] \n\t"
+ "sll %[r7], %[offset], 1 \n\t"
+ "addu %[r7], %[outre1], %[r7] \n\t"
+ "sw %[r6], 0(%[r7]) \n\t"
+ "absq_s.w %[r6], %[r6] \n\t"
+ "slt %[r8], %[max], %[r6] \n\t"
+ "movn %[max], %[r6], %[r8] \n\t"
+ "muleq_s.w.phr %[r6], %[r1], %[r2] \n\t"
+ "muleq_s.w.phr %[r7], %[r0], %[r3] \n\t"
+ "muleq_s.w.phr %[r8], %[r5], %[r2] \n\t"
+ "muleq_s.w.phr %[r9], %[r4], %[r3] \n\t"
+ "addiu %[outre1], %[outre1], 8 \n\t"
+ "shra_r.w %[r6], %[r6], 6 \n\t"
+ "shra_r.w %[r7], %[r7], 6 \n\t"
+ "shra_r.w %[r8], %[r8], 6 \n\t"
+ "shra_r.w %[r9], %[r9], 6 \n\t"
+ "subu %[r6], %[r6], %[r7] \n\t"
+ "addu %[r9], %[r9], %[r8] \n\t"
+ "subu %[r7], %[r6], %[r9] \n\t"
+ "addu %[r6], %[r9], %[r6] \n\t"
+ "negu %[r6], %[r6] \n\t"
+ "sw %[r7], 0(%[outre2]) \n\t"
+ "absq_s.w %[r7], %[r7] \n\t"
+ "slt %[r8], %[max], %[r7] \n\t"
+ "movn %[max], %[r7], %[r8] \n\t"
+ "sll %[r7], %[offset], 1 \n\t"
+ "addu %[r7], %[outre2], %[r7] \n\t"
+ "sw %[r6], 4(%[r7]) \n\t"
+ "absq_s.w %[r6], %[r6] \n\t"
+ "slt %[r8], %[max], %[r6] \n\t"
+ "movn %[max], %[r6], %[r8] \n\t"
+ "muleq_s.w.phl %[r6], %[r1], %[r2] \n\t"
+ "muleq_s.w.phl %[r7], %[r0], %[r3] \n\t"
+ "muleq_s.w.phl %[r8], %[r5], %[r2] \n\t"
+ "muleq_s.w.phl %[r9], %[r4], %[r3] \n\t"
+ "addiu %[offset], %[offset], -8 \n\t"
+ "shra_r.w %[r6], %[r6], 6 \n\t"
+ "shra_r.w %[r7], %[r7], 6 \n\t"
+ "shra_r.w %[r8], %[r8], 6 \n\t"
+ "shra_r.w %[r9], %[r9], 6 \n\t"
+ "subu %[r6], %[r6], %[r7] \n\t"
+ "addu %[r9], %[r9], %[r8] \n\t"
+ "subu %[r7], %[r6], %[r9] \n\t"
+ "addu %[r6], %[r9], %[r6] \n\t"
+ "negu %[r6], %[r6] \n\t"
+ "sw %[r7], 4(%[outre2]) \n\t"
+ "absq_s.w %[r7], %[r7] \n\t"
+ "slt %[r8], %[max], %[r7] \n\t"
+ "movn %[max], %[r7], %[r8] \n\t"
+ "sll %[r7], %[offset], 1 \n\t"
+ "addu %[r7], %[outre2], %[r7] \n\t"
+ "sw %[r6], 0(%[r7]) \n\t"
+ "absq_s.w %[r6], %[r6] \n\t"
+ "slt %[r8], %[max], %[r6] \n\t"
+ "movn %[max], %[r6], %[r8] \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[outre2], %[outre2], 8 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "lh %[r0], 0(%[inre]) \n\t"
+ "lh %[r1], 0(%[inim]) \n\t"
+ "lh %[r4], 0(%[cosptr]) \n\t"
+ "lh %[r5], 0(%[sinptr]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "mul %[r2], %[r0], %[r4] \n\t"
+ "mul %[r0], %[r0], %[r5] \n\t"
+ "mul %[r3], %[r1], %[r5] \n\t"
+ "mul %[r1], %[r1], %[r4] \n\t"
+ "addiu %[cosptr], %[cosptr], 2 \n\t"
+ "addiu %[sinptr], %[sinptr], 2 \n\t"
+ "addu %[r8], %[inre], %[offset] \n\t"
+ "addu %[r9], %[inim], %[offset] \n\t"
+ "addiu %[r2], %[r2], 16 \n\t"
+ "sra %[r2], %[r2], 5 \n\t"
+ "addiu %[r0], %[r0], 16 \n\t"
+ "sra %[r0], %[r0], 5 \n\t"
+ "addiu %[r3], %[r3], 16 \n\t"
+ "sra %[r3], %[r3], 5 \n\t"
+ "lh %[r6], 0(%[r8]) \n\t"
+ "lh %[r7], 0(%[r9]) \n\t"
+ "addiu %[r1], %[r1], 16 \n\t"
+ "sra %[r1], %[r1], 5 \n\t"
+ "mul %[r8], %[r7], %[r4] \n\t"
+ "mul %[r7], %[r7], %[r5] \n\t"
+ "mul %[r9], %[r6], %[r4] \n\t"
+ "mul %[r6], %[r6], %[r5] \n\t"
+ "addu %[r2], %[r2], %[r3] \n\t"
+ "subu %[r1], %[r1], %[r0] \n\t"
+ "sll %[r0], %[offset], 1 \n\t"
+ "addu %[r4], %[outre1], %[r0] \n\t"
+ "addu %[r5], %[outre2], %[r0] \n\t"
+ "addiu %[r8], %[r8], 16 \n\t"
+ "sra %[r8], %[r8], 5 \n\t"
+ "addiu %[r7], %[r7], 16 \n\t"
+ "sra %[r7], %[r7], 5 \n\t"
+ "addiu %[r6], %[r6], 16 \n\t"
+ "sra %[r6], %[r6], 5 \n\t"
+ "addiu %[r9], %[r9], 16 \n\t"
+ "sra %[r9], %[r9], 5 \n\t"
+ "addu %[r8], %[r8], %[r6] \n\t"
+ "negu %[r8], %[r8] \n\t"
+ "subu %[r7], %[r7], %[r9] \n\t"
+ "subu %[r6], %[r2], %[r7] \n\t"
+ "addu %[r0], %[r2], %[r7] \n\t"
+ "addu %[r3], %[r1], %[r8] \n\t"
+ "subu %[r1], %[r8], %[r1] \n\t"
+ "sw %[r6], 0(%[outre1]) \n\t"
+ "sw %[r0], 0(%[r4]) \n\t"
+ "sw %[r3], 0(%[outre2]) \n\t"
+ "sw %[r1], 0(%[r5]) \n\t"
+ "addiu %[outre1], %[outre1], 4 \n\t"
+ "addiu %[offset], %[offset], -4 \n\t"
+ "addiu %[inre], %[inre], 2 \n\t"
+ "addiu %[inim], %[inim], 2 \n\t"
+ // Inlined WebRtcSpl_MaxAbsValueW32
+ "negu %[r5], %[r6] \n\t"
+ "slt %[r2], %[r6], $zero \n\t"
+ "movn %[r6], %[r5], %[r2] \n\t"
+ "negu %[r5], %[r0] \n\t"
+ "slt %[r2], %[r0], $zero \n\t"
+ "movn %[r0], %[r5], %[r2] \n\t"
+ "negu %[r5], %[r3] \n\t"
+ "slt %[r2], %[r3], $zero \n\t"
+ "movn %[r3], %[r5], %[r2] \n\t"
+ "negu %[r5], %[r1] \n\t"
+ "slt %[r2], %[r1], $zero \n\t"
+ "movn %[r1], %[r5], %[r2] \n\t"
+ "slt %[r2], %[r6], %[r0] \n\t"
+ "slt %[r5], %[r3], %[r1] \n\t"
+ "movn %[r6], %[r0], %[r2] \n\t"
+ "movn %[r3], %[r1], %[r5] \n\t"
+ "slt %[r2], %[r6], %[r3] \n\t"
+ "movn %[r6], %[r3], %[r2] \n\t"
+ "slt %[r2], %[max], %[r6] \n\t"
+ "movn %[max], %[r6], %[r2] \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[outre2], %[outre2], 4 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "clz %[max], %[max] \n\t"
+ "addiu %[max], %[max], -25 \n\t"
+ ".set pop \n\t"
+ : [inre] "=&r" (inre), [inim] "=&r" (inim),
+ [outre1] "=&r" (outre1), [outre2] "=&r" (outre2),
+ [offset] "+r" (offset), [k] "+r" (k), [r0] "=&r" (r0),
+ [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3),
+ [r4] "=&r" (r4), [r5] "=&r" (r5), [r6] "=&r" (r6),
+ [r7] "=&r" (r7), [r8] "=&r" (r8), [r9] "=&r" (r9),
+ [max] "=&r" (max)
+ : [inreQ7] "r" (inreQ7), [inimQ7] "r" (inimQ7),
+ [cosptr] "r" (cosptr), [sinptr] "r" (sinptr),
+ [outre1Q16] "r" (outre1Q16), [outre2Q16] "r" (outre2Q16)
+ : "hi", "lo", "memory"
+ );
+
+ // "Fastest" vectors
+ k = FRAMESAMPLES / 4;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[inre], %[inreQ7], 0 \n\t"
+ "addiu %[inim], %[inimQ7], 0 \n\t"
+ "addiu %[outre1], %[outre1Q16], 0 \n\t"
+ "addiu %[outre2], %[outre2Q16], 0 \n\t"
+ "bltz %[max], 2f \n\t"
+ " subu %[max1], $zero, %[max] \n\t"
+ "1: \n\t"
+ "lw %[r0], 0(%[outre1]) \n\t"
+ "lw %[r1], 0(%[outre2]) \n\t"
+ "lw %[r2], 4(%[outre1]) \n\t"
+ "lw %[r3], 4(%[outre2]) \n\t"
+ "sllv %[r0], %[r0], %[max] \n\t"
+ "sllv %[r1], %[r1], %[max] \n\t"
+ "sllv %[r2], %[r2], %[max] \n\t"
+ "sllv %[r3], %[r3], %[max] \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "addiu %[outre1], %[outre1], 8 \n\t"
+ "addiu %[outre2], %[outre2], 8 \n\t"
+ "sh %[r0], 0(%[inre]) \n\t"
+ "sh %[r1], 0(%[inim]) \n\t"
+ "sh %[r2], 2(%[inre]) \n\t"
+ "sh %[r3], 2(%[inim]) \n\t"
+ "addiu %[inre], %[inre], 4 \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[inim], %[inim], 4 \n\t"
+ "b 4f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+#if !defined(MIPS_DSP_R1_LE)
+ "addiu %[r4], $zero, 1 \n\t"
+ "addiu %[r5], %[max1], -1 \n\t"
+ "sllv %[r4], %[r4], %[r5] \n\t"
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ "3: \n\t"
+ "lw %[r0], 0(%[outre1]) \n\t"
+ "lw %[r1], 0(%[outre2]) \n\t"
+ "lw %[r2], 4(%[outre1]) \n\t"
+ "lw %[r3], 4(%[outre2]) \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shrav_r.w %[r0], %[r0], %[max1] \n\t"
+ "shrav_r.w %[r1], %[r1], %[max1] \n\t"
+ "shrav_r.w %[r2], %[r2], %[max1] \n\t"
+ "shrav_r.w %[r3], %[r3], %[max1] \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r4] \n\t"
+ "addu %[r1], %[r1], %[r4] \n\t"
+ "addu %[r2], %[r2], %[r4] \n\t"
+ "addu %[r3], %[r3], %[r4] \n\t"
+ "srav %[r0], %[r0], %[max1] \n\t"
+ "srav %[r1], %[r1], %[max1] \n\t"
+ "srav %[r2], %[r2], %[max1] \n\t"
+ "srav %[r3], %[r3], %[max1] \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[outre1], %[outre1], 8 \n\t"
+ "addiu %[outre2], %[outre2], 8 \n\t"
+ "sh %[r0], 0(%[inre]) \n\t"
+ "sh %[r1], 0(%[inim]) \n\t"
+ "sh %[r2], 2(%[inre]) \n\t"
+ "sh %[r3], 2(%[inim]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "addiu %[inre], %[inre], 4 \n\t"
+ "bgtz %[k], 3b \n\t"
+ " addiu %[inim], %[inim], 4 \n\t"
+ "4: \n\t"
+ ".set pop \n\t"
+ : [k] "+r" (k), [max1] "=&r" (max1), [r0] "=&r" (r0),
+ [inre] "=&r" (inre), [inim] "=&r" (inim),
+ [outre1] "=&r" (outre1), [outre2] "=&r" (outre2),
+#if !defined(MIPS_DSP_R1_LE)
+ [r4] "=&r" (r4), [r5] "=&r" (r5),
+#endif // #if !defined(MIPS_DSP_R1_LE)
+ [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3)
+ : [max] "r" (max), [inreQ7] "r" (inreQ7),
+ [inimQ7] "r" (inimQ7), [outre1Q16] "r" (outre1Q16),
+ [outre2Q16] "r" (outre2Q16)
+ : "memory"
+ );
+
+ WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call
+
+ // All the remaining processing is done inside a single loop to avoid
+ // unnecessary memory accesses. MIPS DSPr2 version processes two samples
+ // at a time.
+ cosptr = (int16_t*)WebRtcIsacfix_kCosTab1;
+ sinptr = (int16_t*)WebRtcIsacfix_kSinTab1;
+ k = FRAMESAMPLES / 2;
+ __asm __volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "addiu %[inre], %[inreQ7], 0 \n\t"
+ "addiu %[inim], %[inimQ7], 0 \n\t"
+ "addiu %[outre1], %[outre1Q16], 0 \n\t"
+ "addiu %[outre2], %[outre2Q16], 0 \n\t"
+ "addiu %[r4], $zero, 273 \n\t"
+ "addiu %[r5], $zero, 31727 \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "addiu %[max], %[max], 16 \n\t"
+ "replv.ph %[r4], %[r4] \n\t"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ "bltz %[max], 2f \n\t"
+ " subu %[max1], $zero, %[max] \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "addiu %[max], %[max], 1 \n\t"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ "1: \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "lwl %[r0], 0(%[inre]) \n\t"
+ "lwl %[r1], 0(%[inim]) \n\t"
+ "lh %[r2], 0(%[cosptr]) \n\t"
+ "lwr %[r0], 0(%[inre]) \n\t"
+ "lwr %[r1], 0(%[inim]) \n\t"
+ "lh %[r3], 0(%[sinptr]) \n\t"
+ "muleq_s.w.phr %[r6], %[r0], %[r4] \n\t"
+ "muleq_s.w.phr %[r7], %[r1], %[r4] \n\t"
+ "muleq_s.w.phl %[r0], %[r0], %[r4] \n\t"
+ "muleq_s.w.phl %[r1], %[r1], %[r4] \n\t"
+ "addiu %[k], %[k], -2 \n\t"
+ "addiu %[inre], %[inre], 4 \n\t"
+ "addiu %[inim], %[inim], 4 \n\t"
+ "shrav_r.w %[r6], %[r6], %[max] \n\t"
+ "shrav_r.w %[r7], %[r7], %[max] \n\t"
+ "mult $ac0, %[r2], %[r6] \n\t"
+ "mult $ac1, %[r3], %[r7] \n\t"
+ "mult $ac2, %[r2], %[r7] \n\t"
+ "mult $ac3, %[r3], %[r6] \n\t"
+ "lh %[r2], 2(%[cosptr]) \n\t"
+ "lh %[r3], 2(%[sinptr]) \n\t"
+ "extr_r.w %[r6], $ac0, 14 \n\t"
+ "extr_r.w %[r7], $ac1, 14 \n\t"
+ "extr_r.w %[r8], $ac2, 14 \n\t"
+ "extr_r.w %[r9], $ac3, 14 \n\t"
+ "shrav_r.w %[r0], %[r0], %[max] \n\t"
+ "shrav_r.w %[r1], %[r1], %[max] \n\t"
+ "mult $ac0, %[r2], %[r0] \n\t"
+ "mult $ac1, %[r3], %[r1] \n\t"
+ "mult $ac2, %[r2], %[r1] \n\t"
+ "mult $ac3, %[r3], %[r0] \n\t"
+ "addiu %[cosptr], %[cosptr], 4 \n\t"
+ "extr_r.w %[r0], $ac0, 14 \n\t"
+ "extr_r.w %[r1], $ac1, 14 \n\t"
+ "extr_r.w %[r2], $ac2, 14 \n\t"
+ "extr_r.w %[r3], $ac3, 14 \n\t"
+ "subu %[r6], %[r6], %[r7] \n\t"
+ "addu %[r8], %[r8], %[r9] \n\t"
+ "mult $ac0, %[r5], %[r6] \n\t"
+ "mult $ac1, %[r5], %[r8] \n\t"
+ "addiu %[sinptr], %[sinptr], 4 \n\t"
+ "subu %[r0], %[r0], %[r1] \n\t"
+ "addu %[r2], %[r2], %[r3] \n\t"
+ "extr_r.w %[r1], $ac0, 11 \n\t"
+ "extr_r.w %[r3], $ac1, 11 \n\t"
+ "mult $ac2, %[r5], %[r0] \n\t"
+ "mult $ac3, %[r5], %[r2] \n\t"
+ "sw %[r1], 0(%[outre1]) \n\t"
+ "sw %[r3], 0(%[outre2]) \n\t"
+ "addiu %[outre1], %[outre1], 8 \n\t"
+ "extr_r.w %[r0], $ac2, 11 \n\t"
+ "extr_r.w %[r2], $ac3, 11 \n\t"
+ "sw %[r0], -4(%[outre1]) \n\t"
+ "sw %[r2], 4(%[outre2]) \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[outre2], %[outre2], 8 \n\t"
+ "b 3f \n\t"
+#else // #if defined(MIPS_DSP_R2_LE)
+ "lh %[r0], 0(%[inre]) \n\t"
+ "lh %[r1], 0(%[inim]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "srav %[r0], %[r0], %[max] \n\t"
+ "srav %[r1], %[r1], %[max] \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "sra %[r0], %[r0], 1 \n\t"
+ "sra %[r3], %[r1], 16 \n\t"
+ "andi %[r1], %[r1], 0xFFFF \n\t"
+ "sra %[r1], %[r1], 1 \n\t"
+ "mul %[r2], %[r2], %[r4] \n\t"
+ "mul %[r0], %[r0], %[r4] \n\t"
+ "mul %[r3], %[r3], %[r4] \n\t"
+ "mul %[r1], %[r1], %[r4] \n\t"
+ "addiu %[inre], %[inre], 2 \n\t"
+ "addiu %[inim], %[inim], 2 \n\t"
+ "lh %[r6], 0(%[cosptr]) \n\t"
+ "lh %[r7], 0(%[sinptr]) \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r0], %[r0], 15 \n\t"
+ "shra_r.w %[r1], %[r1], 15 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r0], %[r0], 0x4000 \n\t"
+ "addiu %[r1], %[r1], 0x4000 \n\t"
+ "sra %[r0], %[r0], 15 \n\t"
+ "sra %[r1], %[r1], 15 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r2], %[r0] \n\t"
+ "addu %[r1], %[r3], %[r1] \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "mul %[r9], %[r2], %[r6] \n\t"
+ "mul %[r2], %[r2], %[r7] \n\t"
+ "mul %[r8], %[r0], %[r6] \n\t"
+ "mul %[r0], %[r0], %[r7] \n\t"
+ "sra %[r3], %[r3], 16 \n\t"
+ "andi %[r1], %[r1], 0xFFFF \n\t"
+ "sll %[r9], %[r9], 2 \n\t"
+ "sll %[r2], %[r2], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r8], %[r8], 14 \n\t"
+ "shra_r.w %[r0], %[r0], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r8], %[r8], 0x2000 \n\t"
+ "addiu %[r0], %[r0], 0x2000 \n\t"
+ "sra %[r8], %[r8], 14 \n\t"
+ "sra %[r0], %[r0], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r9], %[r9], %[r8] \n\t"
+ "addu %[r2], %[r2], %[r0] \n\t"
+ "mul %[r0], %[r3], %[r6] \n\t"
+ "mul %[r3], %[r3], %[r7] \n\t"
+ "mul %[r8], %[r1], %[r6] \n\t"
+ "mul %[r1], %[r1], %[r8] \n\t"
+ "addiu %[cosptr], %[cosptr], 2 \n\t"
+ "addiu %[sinptr], %[sinptr], 2 \n\t"
+ "sll %[r0], %[r0], 2 \n\t"
+ "sll %[r3], %[r3], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r8], %[r8], 14 \n\t"
+ "shra_r.w %[r1], %[r1], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r8], %[r8], 0x2000 \n\t"
+ "addiu %[r1], %[r1], 0x2000 \n\t"
+ "sra %[r8], %[r8], 14 \n\t"
+ "sra %[r1], %[r1], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r8] \n\t"
+ "addu %[r3], %[r3], %[r1] \n\t"
+ "subu %[r9], %[r9], %[r3] \n\t"
+ "addu %[r0], %[r0], %[r2] \n\t"
+ "sra %[r1], %[r9], 16 \n\t"
+ "andi %[r9], %[r9], 0xFFFF \n\t"
+ "mul %[r1], %[r1], %[r5] \n\t"
+ "mul %[r9], %[r9], %[r5] \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "mul %[r2], %[r2], %[r5] \n\t"
+ "mul %[r0], %[r0], %[r5] \n\t"
+ "sll %[r1], %[r1], 5 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r9], %[r9], 11 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r9], %[r9], 0x400 \n\t"
+ "sra %[r9], %[r9], 11 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r1], %[r1], %[r9] \n\t"
+ "sll %[r2], %[r2], 5 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r0], %[r0], 11 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r0], %[r0], 0x400 \n\t"
+ "sra %[r0], %[r0], 11 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r2] \n\t"
+ "sw %[r1], 0(%[outre1]) \n\t"
+ "addiu %[outre1], %[outre1], 4 \n\t"
+ "sw %[r0], 0(%[outre2]) \n\t"
+ "bgtz %[k], 1b \n\t"
+ " addiu %[outre2], %[outre2], 4 \n\t"
+ "b 3f \n\t"
+ " nop \n\t"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ "2: \n\t"
+#if defined(MIPS_DSP_R2_LE)
+ "addiu %[max1], %[max1], -1 \n\t"
+ "21: \n\t"
+ "lwl %[r0], 0(%[inre]) \n\t"
+ "lwl %[r1], 0(%[inim]) \n\t"
+ "lh %[r2], 0(%[cosptr]) \n\t"
+ "lwr %[r0], 0(%[inre]) \n\t"
+ "lwr %[r1], 0(%[inim]) \n\t"
+ "lh %[r3], 0(%[sinptr]) \n\t"
+ "muleq_s.w.phr %[r6], %[r0], %[r4] \n\t"
+ "muleq_s.w.phr %[r7], %[r1], %[r4] \n\t"
+ "muleq_s.w.phl %[r0], %[r0], %[r4] \n\t"
+ "muleq_s.w.phl %[r1], %[r1], %[r4] \n\t"
+ "addiu %[k], %[k], -2 \n\t"
+ "addiu %[inre], %[inre], 4 \n\t"
+ "addiu %[inim], %[inim], 4 \n\t"
+ "sllv %[r6], %[r6], %[max1] \n\t"
+ "sllv %[r7], %[r7], %[max1] \n\t"
+ "mult $ac0, %[r2], %[r6] \n\t"
+ "mult $ac1, %[r3], %[r7] \n\t"
+ "mult $ac2, %[r2], %[r7] \n\t"
+ "mult $ac3, %[r3], %[r6] \n\t"
+ "lh %[r2], 2(%[cosptr]) \n\t"
+ "lh %[r3], 2(%[sinptr]) \n\t"
+ "extr_r.w %[r6], $ac0, 14 \n\t"
+ "extr_r.w %[r7], $ac1, 14 \n\t"
+ "extr_r.w %[r8], $ac2, 14 \n\t"
+ "extr_r.w %[r9], $ac3, 14 \n\t"
+ "sllv %[r0], %[r0], %[max1] \n\t"
+ "sllv %[r1], %[r1], %[max1] \n\t"
+ "mult $ac0, %[r2], %[r0] \n\t"
+ "mult $ac1, %[r3], %[r1] \n\t"
+ "mult $ac2, %[r2], %[r1] \n\t"
+ "mult $ac3, %[r3], %[r0] \n\t"
+ "addiu %[cosptr], %[cosptr], 4 \n\t"
+ "extr_r.w %[r0], $ac0, 14 \n\t"
+ "extr_r.w %[r1], $ac1, 14 \n\t"
+ "extr_r.w %[r2], $ac2, 14 \n\t"
+ "extr_r.w %[r3], $ac3, 14 \n\t"
+ "subu %[r6], %[r6], %[r7] \n\t"
+ "addu %[r8], %[r8], %[r9] \n\t"
+ "mult $ac0, %[r5], %[r6] \n\t"
+ "mult $ac1, %[r5], %[r8] \n\t"
+ "addiu %[sinptr], %[sinptr], 4 \n\t"
+ "subu %[r0], %[r0], %[r1] \n\t"
+ "addu %[r2], %[r2], %[r3] \n\t"
+ "extr_r.w %[r1], $ac0, 11 \n\t"
+ "extr_r.w %[r3], $ac1, 11 \n\t"
+ "mult $ac2, %[r5], %[r0] \n\t"
+ "mult $ac3, %[r5], %[r2] \n\t"
+ "sw %[r1], 0(%[outre1]) \n\t"
+ "sw %[r3], 0(%[outre2]) \n\t"
+ "addiu %[outre1], %[outre1], 8 \n\t"
+ "extr_r.w %[r0], $ac2, 11 \n\t"
+ "extr_r.w %[r2], $ac3, 11 \n\t"
+ "sw %[r0], -4(%[outre1]) \n\t"
+ "sw %[r2], 4(%[outre2]) \n\t"
+ "bgtz %[k], 21b \n\t"
+ " addiu %[outre2], %[outre2], 8 \n\t"
+ "b 3f \n\t"
+ " nop \n\t"
+#else // #if defined(MIPS_DSP_R2_LE)
+ "lh %[r0], 0(%[inre]) \n\t"
+ "lh %[r1], 0(%[inim]) \n\t"
+ "addiu %[k], %[k], -1 \n\t"
+ "sllv %[r0], %[r0], %[max1] \n\t"
+ "sllv %[r1], %[r1], %[max1] \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "sra %[r0], %[r0], 1 \n\t"
+ "sra %[r3], %[r1], 16 \n\t"
+ "andi %[r1], %[r1], 0xFFFF \n\t"
+ "sra %[r1], %[r1], 1 \n\t"
+ "mul %[r2], %[r2], %[r4] \n\t"
+ "mul %[r0], %[r0], %[r4] \n\t"
+ "mul %[r3], %[r3], %[r4] \n\t"
+ "mul %[r1], %[r1], %[r4] \n\t"
+ "addiu %[inre], %[inre], 2 \n\t"
+ "addiu %[inim], %[inim], 2 \n\t"
+ "lh %[r6], 0(%[cosptr]) \n\t"
+ "lh %[r7], 0(%[sinptr]) \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r0], %[r0], 15 \n\t"
+ "shra_r.w %[r1], %[r1], 15 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r0], %[r0], 0x4000 \n\t"
+ "addiu %[r1], %[r1], 0x4000 \n\t"
+ "sra %[r0], %[r0], 15 \n\t"
+ "sra %[r1], %[r1], 15 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r2], %[r0] \n\t"
+ "addu %[r1], %[r3], %[r1] \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "mul %[r9], %[r2], %[r6] \n\t"
+ "mul %[r2], %[r2], %[r7] \n\t"
+ "mul %[r8], %[r0], %[r6] \n\t"
+ "mul %[r0], %[r0], %[r7] \n\t"
+ "sra %[r3], %[r1], 16 \n\t"
+ "andi %[r1], %[r1], 0xFFFF \n\t"
+ "sll %[r9], %[r9], 2 \n\t"
+ "sll %[r2], %[r2], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r8], %[r8], 14 \n\t"
+ "shra_r.w %[r0], %[r0], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r8], %[r8], 0x2000 \n\t"
+ "addiu %[r0], %[r0], 0x2000 \n\t"
+ "sra %[r8], %[r8], 14 \n\t"
+ "sra %[r0], %[r0], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r9], %[r9], %[r8] \n\t"
+ "addu %[r2], %[r2], %[r0] \n\t"
+ "mul %[r0], %[r3], %[r6] \n\t"
+ "mul %[r3], %[r3], %[r7] \n\t"
+ "mul %[r8], %[r1], %[r6] \n\t"
+ "mul %[r1], %[r1], %[r7] \n\t"
+ "addiu %[cosptr], %[cosptr], 2 \n\t"
+ "addiu %[sinptr], %[sinptr], 2 \n\t"
+ "sll %[r0], %[r0], 2 \n\t"
+ "sll %[r3], %[r3], 2 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r8], %[r8], 14 \n\t"
+ "shra_r.w %[r1], %[r1], 14 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r8], %[r8], 0x2000 \n\t"
+ "addiu %[r1], %[r1], 0x2000 \n\t"
+ "sra %[r8], %[r8], 14 \n\t"
+ "sra %[r1], %[r1], 14 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r8] \n\t"
+ "addu %[r3], %[r3], %[r1] \n\t"
+ "subu %[r9], %[r9], %[r3] \n\t"
+ "addu %[r0], %[r0], %[r2] \n\t"
+ "sra %[r1], %[r9], 16 \n\t"
+ "andi %[r9], %[r9], 0xFFFF \n\t"
+ "mul %[r1], %[r1], %[r5] \n\t"
+ "mul %[r9], %[r9], %[r5] \n\t"
+ "sra %[r2], %[r0], 16 \n\t"
+ "andi %[r0], %[r0], 0xFFFF \n\t"
+ "mul %[r2], %[r2], %[r5] \n\t"
+ "mul %[r0], %[r0], %[r5] \n\t"
+ "sll %[r1], %[r1], 5 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r9], %[r9], 11 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r9], %[r9], 0x400 \n\t"
+ "sra %[r9], %[r9], 11 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r1], %[r1], %[r9] \n\t"
+ "sll %[r2], %[r2], 5 \n\t"
+#if defined(MIPS_DSP_R1_LE)
+ "shra_r.w %[r0], %[r0], 11 \n\t"
+#else // #if defined(MIPS_DSP_R1_LE)
+ "addiu %[r0], %[r0], 0x400 \n\t"
+ "sra %[r0], %[r0], 11 \n\t"
+#endif // #if defined(MIPS_DSP_R1_LE)
+ "addu %[r0], %[r0], %[r2] \n\t"
+ "sw %[r1], 0(%[outre1]) \n\t"
+ "addiu %[outre1], %[outre1], 4 \n\t"
+ "sw %[r0], 0(%[outre2]) \n\t"
+ "bgtz %[k], 2b \n\t"
+ " addiu %[outre2], %[outre2], 4 \n\t"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ "3: \n\t"
+ ".set pop \n\t"
+ : [k] "+r" (k), [r0] "=&r" (r0), [r1] "=&r" (r1),
+ [r2] "=&r" (r2), [r3] "=&r" (r3), [r4] "=&r" (r4),
+ [r5] "=&r" (r5), [r6] "=&r" (r6), [r7] "=&r" (r7),
+ [r8] "=&r" (r8), [r9] "=&r" (r9), [max1] "=&r" (max1),
+ [inre] "=&r" (inre), [inim] "=&r" (inim),
+ [outre1] "=&r" (outre1), [outre2] "=&r" (outre2)
+ : [max] "r" (max), [inreQ7] "r" (inreQ7),
+ [inimQ7] "r" (inimQ7), [cosptr] "r" (cosptr),
+ [sinptr] "r" (sinptr), [outre1Q16] "r" (outre1Q16),
+ [outre2Q16] "r" (outre2Q16)
+ : "hi", "lo", "memory"
+#if defined(MIPS_DSP_R2_LE)
+ , "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
+#endif // #if defined(MIPS_DSP_R2_LE)
+ );
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c
new file mode 100644
index 0000000000..79dadc4600
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <arm_neon.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+// Tables are defined in transform_tables.c file.
+// Cosine table 1 in Q14.
+extern const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2];
+// Sine table 1 in Q14.
+extern const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2];
+// Sine table 2 in Q14.
+extern const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4];
+
+static inline int32_t ComplexMulAndFindMaxNeon(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int32_t* outreQ16,
+ int32_t* outimQ16) {
+ int k;
+ const int16_t* kCosTab = &WebRtcIsacfix_kCosTab1[0];
+ const int16_t* kSinTab = &WebRtcIsacfix_kSinTab1[0];
+ // 0.5 / sqrt(240) in Q19 is round((.5 / sqrt(240)) * (2^19)) = 16921.
+ // Use "16921 << 5" and vqdmulh, instead of ">> 26" as in the C code.
+ int32_t fact = 16921 << 5;
+ int32x4_t factq = vdupq_n_s32(fact);
+ uint32x4_t max_r = vdupq_n_u32(0);
+ uint32x4_t max_i = vdupq_n_u32(0);
+
+ for (k = 0; k < FRAMESAMPLES/2; k += 8) {
+ int16x8_t tmpr = vld1q_s16(kCosTab);
+ int16x8_t tmpi = vld1q_s16(kSinTab);
+ int16x8_t inre1 = vld1q_s16(inre1Q9);
+ int16x8_t inre2 = vld1q_s16(inre2Q9);
+ kCosTab += 8;
+ kSinTab += 8;
+ inre1Q9 += 8;
+ inre2Q9 += 8;
+
+ // Use ">> 26", instead of ">> 7", ">> 16" and then ">> 3" as in the C code.
+ int32x4_t tmp0 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre1));
+ int32x4_t tmp1 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre2));
+ tmp0 = vmlal_s16(tmp0, vget_low_s16(tmpi), vget_low_s16(inre2));
+ tmp1 = vmlsl_s16(tmp1, vget_low_s16(tmpi), vget_low_s16(inre1));
+#if defined(WEBRTC_ARCH_ARM64)
+ int32x4_t tmp2 = vmull_high_s16(tmpr, inre1);
+ int32x4_t tmp3 = vmull_high_s16(tmpr, inre2);
+ tmp2 = vmlal_high_s16(tmp2, tmpi, inre2);
+ tmp3 = vmlsl_high_s16(tmp3, tmpi, inre1);
+#else
+ int32x4_t tmp2 = vmull_s16(vget_high_s16(tmpr), vget_high_s16(inre1));
+ int32x4_t tmp3 = vmull_s16(vget_high_s16(tmpr), vget_high_s16(inre2));
+ tmp2 = vmlal_s16(tmp2, vget_high_s16(tmpi), vget_high_s16(inre2));
+ tmp3 = vmlsl_s16(tmp3, vget_high_s16(tmpi), vget_high_s16(inre1));
+#endif
+
+ int32x4_t outr_0 = vqdmulhq_s32(tmp0, factq);
+ int32x4_t outr_1 = vqdmulhq_s32(tmp2, factq);
+ int32x4_t outi_0 = vqdmulhq_s32(tmp1, factq);
+ int32x4_t outi_1 = vqdmulhq_s32(tmp3, factq);
+ vst1q_s32(outreQ16, outr_0);
+ outreQ16 += 4;
+ vst1q_s32(outreQ16, outr_1);
+ outreQ16 += 4;
+ vst1q_s32(outimQ16, outi_0);
+ outimQ16 += 4;
+ vst1q_s32(outimQ16, outi_1);
+ outimQ16 += 4;
+
+ // Find the absolute maximum in the vectors.
+ tmp0 = vabsq_s32(outr_0);
+ tmp1 = vabsq_s32(outr_1);
+ tmp2 = vabsq_s32(outi_0);
+ tmp3 = vabsq_s32(outi_1);
+ // vabs doesn't change the value of 0x80000000.
+ // Use u32 so we don't lose the value 0x80000000.
+ max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp0));
+ max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp2));
+ max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp1));
+ max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp3));
+ }
+
+ max_r = vmaxq_u32(max_r, max_i);
+#if defined(WEBRTC_ARCH_ARM64)
+ uint32_t maximum = vmaxvq_u32(max_r);
+#else
+ uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
+ max32x2_r = vpmax_u32(max32x2_r, max32x2_r);
+ uint32_t maximum = vget_lane_u32(max32x2_r, 0);
+#endif
+
+ return (int32_t)maximum;
+}
+
+static inline void PreShiftW32toW16Neon(int32_t* inre,
+ int32_t* inim,
+ int16_t* outre,
+ int16_t* outim,
+ int32_t sh) {
+ int k;
+ int32x4_t sh32x4 = vdupq_n_s32(sh);
+ for (k = 0; k < FRAMESAMPLES/2; k += 16) {
+ int32x4x4_t inre32x4x4 = vld4q_s32(inre);
+ int32x4x4_t inim32x4x4 = vld4q_s32(inim);
+ inre += 16;
+ inim += 16;
+ inre32x4x4.val[0] = vrshlq_s32(inre32x4x4.val[0], sh32x4);
+ inre32x4x4.val[1] = vrshlq_s32(inre32x4x4.val[1], sh32x4);
+ inre32x4x4.val[2] = vrshlq_s32(inre32x4x4.val[2], sh32x4);
+ inre32x4x4.val[3] = vrshlq_s32(inre32x4x4.val[3], sh32x4);
+ inim32x4x4.val[0] = vrshlq_s32(inim32x4x4.val[0], sh32x4);
+ inim32x4x4.val[1] = vrshlq_s32(inim32x4x4.val[1], sh32x4);
+ inim32x4x4.val[2] = vrshlq_s32(inim32x4x4.val[2], sh32x4);
+ inim32x4x4.val[3] = vrshlq_s32(inim32x4x4.val[3], sh32x4);
+ int16x4x4_t outre16x4x4;
+ int16x4x4_t outim16x4x4;
+ outre16x4x4.val[0] = vmovn_s32(inre32x4x4.val[0]);
+ outre16x4x4.val[1] = vmovn_s32(inre32x4x4.val[1]);
+ outre16x4x4.val[2] = vmovn_s32(inre32x4x4.val[2]);
+ outre16x4x4.val[3] = vmovn_s32(inre32x4x4.val[3]);
+ outim16x4x4.val[0] = vmovn_s32(inim32x4x4.val[0]);
+ outim16x4x4.val[1] = vmovn_s32(inim32x4x4.val[1]);
+ outim16x4x4.val[2] = vmovn_s32(inim32x4x4.val[2]);
+ outim16x4x4.val[3] = vmovn_s32(inim32x4x4.val[3]);
+ vst4_s16(outre, outre16x4x4);
+ vst4_s16(outim, outim16x4x4);
+ outre += 16;
+ outim += 16;
+ }
+}
+
+static inline void PostShiftAndSeparateNeon(int16_t* inre,
+ int16_t* inim,
+ int16_t* outre,
+ int16_t* outim,
+ int32_t sh) {
+ int k;
+ int16_t* inre1 = inre;
+ int16_t* inre2 = &inre[FRAMESAMPLES/2 - 4];
+ int16_t* inim1 = inim;
+ int16_t* inim2 = &inim[FRAMESAMPLES/2 - 4];
+ int16_t* outre1 = outre;
+ int16_t* outre2 = &outre[FRAMESAMPLES/2 - 4];
+ int16_t* outim1 = outim;
+ int16_t* outim2 = &outim[FRAMESAMPLES/2 - 4];
+ const int16_t* kSinTab1 = &WebRtcIsacfix_kSinTab2[0];
+ const int16_t* kSinTab2 = &WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 -4];
+ // By vshl, we effectively did "<< (-sh - 23)", instead of "<< (-sh)",
+ // ">> 14" and then ">> 9" as in the C code.
+ int32x4_t shift = vdupq_n_s32(-sh - 23);
+
+ for (k = 0; k < FRAMESAMPLES/4; k += 4) {
+ int16x4_t tmpi = vld1_s16(kSinTab1);
+ kSinTab1 += 4;
+ int16x4_t tmpr = vld1_s16(kSinTab2);
+ kSinTab2 -= 4;
+ int16x4_t inre_0 = vld1_s16(inre1);
+ inre1 += 4;
+ int16x4_t inre_1 = vld1_s16(inre2);
+ inre2 -= 4;
+ int16x4_t inim_0 = vld1_s16(inim1);
+ inim1 += 4;
+ int16x4_t inim_1 = vld1_s16(inim2);
+ inim2 -= 4;
+ tmpr = vneg_s16(tmpr);
+ inre_1 = vrev64_s16(inre_1);
+ inim_1 = vrev64_s16(inim_1);
+ tmpr = vrev64_s16(tmpr);
+
+ int16x4_t xr = vqadd_s16(inre_0, inre_1);
+ int16x4_t xi = vqsub_s16(inim_0, inim_1);
+ int16x4_t yr = vqadd_s16(inim_0, inim_1);
+ int16x4_t yi = vqsub_s16(inre_1, inre_0);
+
+ int32x4_t outr0 = vmull_s16(tmpr, xr);
+ int32x4_t outi0 = vmull_s16(tmpi, xr);
+ int32x4_t outr1 = vmull_s16(tmpi, yr);
+ int32x4_t outi1 = vmull_s16(tmpi, yi);
+ outr0 = vmlsl_s16(outr0, tmpi, xi);
+ outi0 = vmlal_s16(outi0, tmpr, xi);
+ outr1 = vmlal_s16(outr1, tmpr, yi);
+ outi1 = vmlsl_s16(outi1, tmpr, yr);
+
+ outr0 = vshlq_s32(outr0, shift);
+ outi0 = vshlq_s32(outi0, shift);
+ outr1 = vshlq_s32(outr1, shift);
+ outi1 = vshlq_s32(outi1, shift);
+ outr1 = vnegq_s32(outr1);
+
+ int16x4_t outre_0 = vmovn_s32(outr0);
+ int16x4_t outim_0 = vmovn_s32(outi0);
+ int16x4_t outre_1 = vmovn_s32(outr1);
+ int16x4_t outim_1 = vmovn_s32(outi1);
+ outre_1 = vrev64_s16(outre_1);
+ outim_1 = vrev64_s16(outim_1);
+
+ vst1_s16(outre1, outre_0);
+ outre1 += 4;
+ vst1_s16(outim1, outim_0);
+ outim1 += 4;
+ vst1_s16(outre2, outre_1);
+ outre2 -= 4;
+ vst1_s16(outim2, outim_1);
+ outim2 -= 4;
+ }
+}
+
+void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
+ int16_t* inre2Q9,
+ int16_t* outreQ7,
+ int16_t* outimQ7) {
+ int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
+ int32_t max;
+ int32_t sh;
+
+ // Multiply with complex exponentials and combine into one complex vector.
+ // And find the maximum.
+ max = ComplexMulAndFindMaxNeon(inre1Q9, inre2Q9, tmpreQ16, tmpimQ16);
+
+ sh = (int32_t)WebRtcSpl_NormW32(max);
+ sh = sh - 24;
+
+ // If sh becomes >= 0, then we should shift sh steps to the left,
+ // and the domain will become Q(16 + sh).
+ // If sh becomes < 0, then we should shift -sh steps to the right,
+ // and the domain will become Q(16 + sh).
+ PreShiftW32toW16Neon(tmpreQ16, tmpimQ16, inre1Q9, inre2Q9, sh);
+
+ // Get DFT.
+ WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1);
+
+ // If sh >= 0, shift sh steps to the right,
+ // If sh < 0, shift -sh steps to the left.
+ // Use symmetry to separate into two complex vectors
+ // and center frames in time around zero.
+ PostShiftAndSeparateNeon(inre1Q9, inre2Q9, outreQ7, outimQ7, sh);
+}
+
+static inline int32_t TransformAndFindMaxNeon(int16_t* inre,
+ int16_t* inim,
+ int32_t* outre,
+ int32_t* outim) {
+ int k;
+ int16_t* inre1 = inre;
+ int16_t* inre2 = &inre[FRAMESAMPLES/2 - 4];
+ int16_t* inim1 = inim;
+ int16_t* inim2 = &inim[FRAMESAMPLES/2 - 4];
+ int32_t* outre1 = outre;
+ int32_t* outre2 = &outre[FRAMESAMPLES/2 - 4];
+ int32_t* outim1 = outim;
+ int32_t* outim2 = &outim[FRAMESAMPLES/2 - 4];
+ const int16_t* kSinTab1 = &WebRtcIsacfix_kSinTab2[0];
+ const int16_t* kSinTab2 = &WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 4];
+ uint32x4_t max_r = vdupq_n_u32(0);
+ uint32x4_t max_i = vdupq_n_u32(0);
+
+ // Use ">> 5", instead of "<< 9" and then ">> 14" as in the C code.
+ for (k = 0; k < FRAMESAMPLES/4; k += 4) {
+ int16x4_t tmpi = vld1_s16(kSinTab1);
+ kSinTab1 += 4;
+ int16x4_t tmpr = vld1_s16(kSinTab2);
+ kSinTab2 -= 4;
+ int16x4_t inre_0 = vld1_s16(inre1);
+ inre1 += 4;
+ int16x4_t inre_1 = vld1_s16(inre2);
+ inre2 -= 4;
+ int16x4_t inim_0 = vld1_s16(inim1);
+ inim1 += 4;
+ int16x4_t inim_1 = vld1_s16(inim2);
+ inim2 -= 4;
+ tmpr = vneg_s16(tmpr);
+ inre_1 = vrev64_s16(inre_1);
+ inim_1 = vrev64_s16(inim_1);
+ tmpr = vrev64_s16(tmpr);
+
+ int32x4_t xr = vmull_s16(tmpr, inre_0);
+ int32x4_t xi = vmull_s16(tmpr, inim_0);
+ int32x4_t yr = vmull_s16(tmpr, inim_1);
+ int32x4_t yi = vmull_s16(tmpi, inim_1);
+ xr = vmlal_s16(xr, tmpi, inim_0);
+ xi = vmlsl_s16(xi, tmpi, inre_0);
+ yr = vmlal_s16(yr, tmpi, inre_1);
+ yi = vmlsl_s16(yi, tmpr, inre_1);
+ yr = vnegq_s32(yr);
+
+ xr = vshrq_n_s32(xr, 5);
+ xi = vshrq_n_s32(xi, 5);
+ yr = vshrq_n_s32(yr, 5);
+ yi = vshrq_n_s32(yi, 5);
+
+ int32x4_t outr0 = vsubq_s32(xr, yi);
+ int32x4_t outr1 = vaddq_s32(xr, yi);
+ int32x4_t outi0 = vaddq_s32(xi, yr);
+ int32x4_t outi1 = vsubq_s32(yr, xi);
+
+ // Find the absolute maximum in the vectors.
+ int32x4_t tmp0 = vabsq_s32(outr0);
+ int32x4_t tmp1 = vabsq_s32(outr1);
+ int32x4_t tmp2 = vabsq_s32(outi0);
+ int32x4_t tmp3 = vabsq_s32(outi1);
+ // vabs doesn't change the value of 0x80000000.
+ // Use u32 so we don't lose the value 0x80000000.
+ max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp0));
+ max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp2));
+ max_r = vmaxq_u32(max_r, vreinterpretq_u32_s32(tmp1));
+ max_i = vmaxq_u32(max_i, vreinterpretq_u32_s32(tmp3));
+
+ // Store the vectors.
+ outr1 = vrev64q_s32(outr1);
+ outi1 = vrev64q_s32(outi1);
+ int32x4_t outr_1 = vcombine_s32(vget_high_s32(outr1), vget_low_s32(outr1));
+ int32x4_t outi_1 = vcombine_s32(vget_high_s32(outi1), vget_low_s32(outi1));
+
+ vst1q_s32(outre1, outr0);
+ outre1 += 4;
+ vst1q_s32(outim1, outi0);
+ outim1 += 4;
+ vst1q_s32(outre2, outr_1);
+ outre2 -= 4;
+ vst1q_s32(outim2, outi_1);
+ outim2 -= 4;
+ }
+
+ max_r = vmaxq_u32(max_r, max_i);
+#if defined(WEBRTC_ARCH_ARM64)
+ uint32_t maximum = vmaxvq_u32(max_r);
+#else
+ uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
+ max32x2_r = vpmax_u32(max32x2_r, max32x2_r);
+ uint32_t maximum = vget_lane_u32(max32x2_r, 0);
+#endif
+
+ return (int32_t)maximum;
+}
+
+static inline void PostShiftAndDivideAndDemodulateNeon(int16_t* inre,
+ int16_t* inim,
+ int32_t* outre1,
+ int32_t* outre2,
+ int32_t sh) {
+ int k;
+ int16_t* p_inre = inre;
+ int16_t* p_inim = inim;
+ int32_t* p_outre1 = outre1;
+ int32_t* p_outre2 = outre2;
+ const int16_t* kCosTab = &WebRtcIsacfix_kCosTab1[0];
+ const int16_t* kSinTab = &WebRtcIsacfix_kSinTab1[0];
+ int32x4_t shift = vdupq_n_s32(-sh - 16);
+ // Divide through by the normalizing constant:
+ // scale all values with 1/240, i.e. with 273 in Q16.
+ // 273/65536 ~= 0.0041656
+ // 1/240 ~= 0.0041666
+ int16x8_t scale = vdupq_n_s16(273);
+ // Sqrt(240) in Q11 is round(15.49193338482967 * 2048) = 31727.
+ int factQ19 = 31727 << 16;
+ int32x4_t fact = vdupq_n_s32(factQ19);
+
+ for (k = 0; k < FRAMESAMPLES/2; k += 8) {
+ int16x8_t inre16x8 = vld1q_s16(p_inre);
+ int16x8_t inim16x8 = vld1q_s16(p_inim);
+ p_inre += 8;
+ p_inim += 8;
+ int16x8_t tmpr = vld1q_s16(kCosTab);
+ int16x8_t tmpi = vld1q_s16(kSinTab);
+ kCosTab += 8;
+ kSinTab += 8;
+ // By vshl and vmull, we effectively did "<< (-sh - 16)",
+ // instead of "<< (-sh)" and ">> 16" as in the C code.
+ int32x4_t outre1_0 = vmull_s16(vget_low_s16(inre16x8), vget_low_s16(scale));
+ int32x4_t outre2_0 = vmull_s16(vget_low_s16(inim16x8), vget_low_s16(scale));
+#if defined(WEBRTC_ARCH_ARM64)
+ int32x4_t outre1_1 = vmull_high_s16(inre16x8, scale);
+ int32x4_t outre2_1 = vmull_high_s16(inim16x8, scale);
+#else
+ int32x4_t outre1_1 = vmull_s16(vget_high_s16(inre16x8),
+ vget_high_s16(scale));
+ int32x4_t outre2_1 = vmull_s16(vget_high_s16(inim16x8),
+ vget_high_s16(scale));
+#endif
+
+ outre1_0 = vshlq_s32(outre1_0, shift);
+ outre1_1 = vshlq_s32(outre1_1, shift);
+ outre2_0 = vshlq_s32(outre2_0, shift);
+ outre2_1 = vshlq_s32(outre2_1, shift);
+
+ // Demodulate and separate.
+ int32x4_t tmpr_0 = vmovl_s16(vget_low_s16(tmpr));
+ int32x4_t tmpi_0 = vmovl_s16(vget_low_s16(tmpi));
+#if defined(WEBRTC_ARCH_ARM64)
+ int32x4_t tmpr_1 = vmovl_high_s16(tmpr);
+ int32x4_t tmpi_1 = vmovl_high_s16(tmpi);
+#else
+ int32x4_t tmpr_1 = vmovl_s16(vget_high_s16(tmpr));
+ int32x4_t tmpi_1 = vmovl_s16(vget_high_s16(tmpi));
+#endif
+
+ int64x2_t xr0 = vmull_s32(vget_low_s32(tmpr_0), vget_low_s32(outre1_0));
+ int64x2_t xi0 = vmull_s32(vget_low_s32(tmpr_0), vget_low_s32(outre2_0));
+ int64x2_t xr2 = vmull_s32(vget_low_s32(tmpr_1), vget_low_s32(outre1_1));
+ int64x2_t xi2 = vmull_s32(vget_low_s32(tmpr_1), vget_low_s32(outre2_1));
+ xr0 = vmlsl_s32(xr0, vget_low_s32(tmpi_0), vget_low_s32(outre2_0));
+ xi0 = vmlal_s32(xi0, vget_low_s32(tmpi_0), vget_low_s32(outre1_0));
+ xr2 = vmlsl_s32(xr2, vget_low_s32(tmpi_1), vget_low_s32(outre2_1));
+ xi2 = vmlal_s32(xi2, vget_low_s32(tmpi_1), vget_low_s32(outre1_1));
+
+#if defined(WEBRTC_ARCH_ARM64)
+ int64x2_t xr1 = vmull_high_s32(tmpr_0, outre1_0);
+ int64x2_t xi1 = vmull_high_s32(tmpr_0, outre2_0);
+ int64x2_t xr3 = vmull_high_s32(tmpr_1, outre1_1);
+ int64x2_t xi3 = vmull_high_s32(tmpr_1, outre2_1);
+ xr1 = vmlsl_high_s32(xr1, tmpi_0, outre2_0);
+ xi1 = vmlal_high_s32(xi1, tmpi_0, outre1_0);
+ xr3 = vmlsl_high_s32(xr3, tmpi_1, outre2_1);
+ xi3 = vmlal_high_s32(xi3, tmpi_1, outre1_1);
+#else
+ int64x2_t xr1 = vmull_s32(vget_high_s32(tmpr_0), vget_high_s32(outre1_0));
+ int64x2_t xi1 = vmull_s32(vget_high_s32(tmpr_0), vget_high_s32(outre2_0));
+ int64x2_t xr3 = vmull_s32(vget_high_s32(tmpr_1), vget_high_s32(outre1_1));
+ int64x2_t xi3 = vmull_s32(vget_high_s32(tmpr_1), vget_high_s32(outre2_1));
+ xr1 = vmlsl_s32(xr1, vget_high_s32(tmpi_0), vget_high_s32(outre2_0));
+ xi1 = vmlal_s32(xi1, vget_high_s32(tmpi_0), vget_high_s32(outre1_0));
+ xr3 = vmlsl_s32(xr3, vget_high_s32(tmpi_1), vget_high_s32(outre2_1));
+ xi3 = vmlal_s32(xi3, vget_high_s32(tmpi_1), vget_high_s32(outre1_1));
+#endif
+
+ outre1_0 = vcombine_s32(vrshrn_n_s64(xr0, 10), vrshrn_n_s64(xr1, 10));
+ outre2_0 = vcombine_s32(vrshrn_n_s64(xi0, 10), vrshrn_n_s64(xi1, 10));
+ outre1_1 = vcombine_s32(vrshrn_n_s64(xr2, 10), vrshrn_n_s64(xr3, 10));
+ outre2_1 = vcombine_s32(vrshrn_n_s64(xi2, 10), vrshrn_n_s64(xi3, 10));
+ outre1_0 = vqdmulhq_s32(outre1_0, fact);
+ outre2_0 = vqdmulhq_s32(outre2_0, fact);
+ outre1_1 = vqdmulhq_s32(outre1_1, fact);
+ outre2_1 = vqdmulhq_s32(outre2_1, fact);
+
+ vst1q_s32(p_outre1, outre1_0);
+ p_outre1 += 4;
+ vst1q_s32(p_outre1, outre1_1);
+ p_outre1 += 4;
+ vst1q_s32(p_outre2, outre2_0);
+ p_outre2 += 4;
+ vst1q_s32(p_outre2, outre2_1);
+ p_outre2 += 4;
+ }
+}
+
+void WebRtcIsacfix_Spec2TimeNeon(int16_t* inreQ7,
+ int16_t* inimQ7,
+ int32_t* outre1Q16,
+ int32_t* outre2Q16) {
+ int32_t max;
+ int32_t sh;
+
+ max = TransformAndFindMaxNeon(inreQ7, inimQ7, outre1Q16, outre2Q16);
+
+
+ sh = (int32_t)WebRtcSpl_NormW32(max);
+ sh = sh - 24;
+ // If sh becomes >= 0, then we should shift sh steps to the left,
+ // and the domain will become Q(16 + sh).
+ // If sh becomes < 0, then we should shift -sh steps to the right,
+ // and the domain will become Q(16 + sh).
+
+ // "Fastest" vectors.
+ PreShiftW32toW16Neon(outre1Q16, outre2Q16, inreQ7, inimQ7, sh);
+
+ // Get IDFT.
+ WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1);
+
+ PostShiftAndDivideAndDemodulateNeon(inreQ7, inimQ7, outre1Q16, outre2Q16, sh);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
new file mode 100644
index 0000000000..e661effdde
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * This file contains trigonometric functions look-up tables used in
+ * transform functions WebRtcIsacfix_Time2Spec and WebRtcIsacfix_Spec2Time.
+ */
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+
+/* Cosine table 1 in Q14. */
+const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2] = {
+ 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315, 16294, 16270,
+ 16244, 16214, 16182, 16147, 16110, 16069, 16026, 15980, 15931, 15880,
+ 15826, 15769, 15709, 15647, 15582, 15515, 15444, 15371, 15296, 15218,
+ 15137, 15053, 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295,
+ 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380, 13255, 13128,
+ 12998, 12867, 12733, 12597, 12458, 12318, 12176, 12031, 11885, 11736,
+ 11585, 11433, 11278, 11121, 10963, 10803, 10641, 10477, 10311, 10143,
+ 9974, 9803, 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377,
+ 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859, 6664, 6467,
+ 6270, 6071, 5872, 5671, 5469, 5266, 5063, 4859, 4653, 4447,
+ 4240, 4033, 3825, 3616, 3406, 3196, 2986, 2775, 2563, 2351,
+ 2139, 1926, 1713, 1499, 1285, 1072, 857, 643, 429, 214,
+ 0, -214, -429, -643, -857, -1072, -1285, -1499, -1713, -1926,
+ -2139, -2351, -2563, -2775, -2986, -3196, -3406, -3616, -3825, -4033,
+ -4240, -4447, -4653, -4859, -5063, -5266, -5469, -5671, -5872, -6071,
+ -6270, -6467, -6664, -6859, -7053, -7246, -7438, -7629, -7818, -8006,
+ -8192, -8377, -8561, -8743, -8923, -9102, -9280, -9456, -9630, -9803,
+ -9974, -10143, -10311, -10477, -10641, -10803, -10963, -11121, -11278, -11433,
+ -11585, -11736, -11885, -12031, -12176, -12318, -12458, -12597, -12733,
+ -12867, -12998, -13128, -13255, -13380, -13502, -13623, -13741, -13856,
+ -13970, -14081, -14189, -14295, -14399, -14500, -14598, -14694, -14788,
+ -14879, -14968, -15053, -15137, -15218, -15296, -15371, -15444, -15515,
+ -15582, -15647, -15709, -15769, -15826, -15880, -15931, -15980, -16026,
+ -16069, -16110, -16147, -16182, -16214, -16244, -16270, -16294, -16315,
+ -16333, -16349, -16362, -16371, -16378, -16383
+};
+
+/* Sine table 1 in Q14. */
+const int16_t WebRtcIsacfix_kSinTab1[FRAMESAMPLES/2] = {
+ 0, 214, 429, 643, 857, 1072, 1285, 1499, 1713, 1926,
+ 2139, 2351, 2563, 2775, 2986, 3196, 3406, 3616, 3825, 4033,
+ 4240, 4447, 4653, 4859, 5063, 5266, 5469, 5671, 5872, 6071,
+ 6270, 6467, 6664, 6859, 7053, 7246, 7438, 7629, 7818, 8006,
+ 8192, 8377, 8561, 8743, 8923, 9102, 9280, 9456, 9630, 9803,
+ 9974, 10143, 10311, 10477, 10641, 10803, 10963, 11121, 11278, 11433,
+ 11585, 11736, 11885, 12031, 12176, 12318, 12458, 12597, 12733, 12867,
+ 12998, 13128, 13255, 13380, 13502, 13623, 13741, 13856, 13970, 14081,
+ 14189, 14295, 14399, 14500, 14598, 14694, 14788, 14879, 14968, 15053,
+ 15137, 15218, 15296, 15371, 15444, 15515, 15582, 15647, 15709, 15769,
+ 15826, 15880, 15931, 15980, 16026, 16069, 16110, 16147, 16182, 16214,
+ 16244, 16270, 16294, 16315, 16333, 16349, 16362, 16371, 16378, 16383,
+ 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315, 16294, 16270,
+ 16244, 16214, 16182, 16147, 16110, 16069, 16026, 15980, 15931, 15880,
+ 15826, 15769, 15709, 15647, 15582, 15515, 15444, 15371, 15296, 15218,
+ 15137, 15053, 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295,
+ 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380, 13255, 13128,
+ 12998, 12867, 12733, 12597, 12458, 12318, 12176, 12031, 11885, 11736,
+ 11585, 11433, 11278, 11121, 10963, 10803, 10641, 10477, 10311, 10143,
+ 9974, 9803, 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377,
+ 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859, 6664, 6467,
+ 6270, 6071, 5872, 5671, 5469, 5266, 5063, 4859, 4653, 4447,
+ 4240, 4033, 3825, 3616, 3406, 3196, 2986, 2775, 2563, 2351,
+ 2139, 1926, 1713, 1499, 1285, 1072, 857, 643, 429, 214
+};
+
+
+/* Sine table 2 in Q14. */
+const int16_t WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4] = {
+ 16384, -16381, 16375, -16367, 16356, -16342, 16325, -16305, 16283, -16257,
+ 16229, -16199, 16165, -16129, 16090, -16048, 16003, -15956, 15906, -15853,
+ 15798, -15739, 15679, -15615, 15549, -15480, 15408, -15334, 15257, -15178,
+ 15095, -15011, 14924, -14834, 14741, -14647, 14549, -14449, 14347, -14242,
+ 14135, -14025, 13913, -13799, 13682, -13563, 13441, -13318, 13192, -13063,
+ 12933, -12800, 12665, -12528, 12389, -12247, 12104, -11958, 11810, -11661,
+ 11509, -11356, 11200, -11042, 10883, -10722, 10559, -10394, 10227, -10059,
+ 9889, -9717, 9543, -9368, 9191, -9013, 8833, -8652, 8469, -8285,
+ 8099, -7912, 7723, -7534, 7342, -7150, 6957, -6762, 6566, -6369,
+ 6171, -5971, 5771, -5570, 5368, -5165, 4961, -4756, 4550, -4344,
+ 4137, -3929, 3720, -3511, 3301, -3091, 2880, -2669, 2457, -2245,
+ 2032, -1819, 1606, -1392, 1179, -965, 750, -536, 322, -107
+};
+
+#if defined(MIPS32_LE)
+/* Cosine table 2 in Q14. Used only on MIPS platforms. */
+const int16_t WebRtcIsacfix_kCosTab2[FRAMESAMPLES/4] = {
+ 107, -322, 536, -750, 965, -1179, 1392, -1606, 1819, -2032,
+ 2245, -2457, 2669, -2880, 3091, -3301, 3511, -3720, 3929, -4137,
+ 4344, -4550, 4756, -4961, 5165, -5368, 5570, -5771, 5971, -6171,
+ 6369, -6566, 6762, -6957, 7150, -7342, 7534, -7723, 7912, -8099,
+ 8285, -8469, 8652, -8833, 9013, -9191, 9368, -9543, 9717, -9889,
+ 10059, -10227, 10394, -10559, 10722, -10883, 11042, -11200, 11356, -11509,
+ 11661, -11810, 11958, -12104, 12247, -12389, 12528, -12665, 12800, -12933,
+ 13063, -13192, 13318, -13441, 13563, -13682, 13799, -13913, 14025, -14135,
+ 14242, -14347, 14449, -14549, 14647, -14741, 14834, -14924, 15011, -15095,
+ 15178, -15257, 15334, -15408, 15480, -15549, 15615, -15679, 15739, -15798,
+ 15853, -15906, 15956, -16003, 16048, -16090, 16129, -16165, 16199, -16229,
+ 16257, -16283, 16305, -16325, 16342, -16356, 16367, -16375, 16381, -16384
+};
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc
new file mode 100644
index 0000000000..433ec534fe
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/source/transform_unittest.cc
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+#include "test/gtest.h"
+
+static const int kSamples = FRAMESAMPLES / 2;
+static const int32_t spec2time_out_expected_1[kSamples] = {
+ -3366470, -2285227, -3415765, -2310215, -3118030, -2222470, -3030254,
+ -2192091, -3423170, -2216041, -3305541, -2171936, -3195767, -2095779,
+ -3153304, -2157560, -3071167, -2032108, -3101190, -1972016, -3103824,
+ -2089118, -3139811, -1898337, -3102801, -2055082, -3029665, -1854140,
+ -2962586, -1966454, -3071167, -1894588, -2851743, -1917315, -2848087,
+ -1594932, -2799242, -1462184, -2845887, -1437599, -2691776, -1329637,
+ -2770659, -1268491, -2625161, -1578991, -2460299, -1186385, -2365613,
+ -1039354, -2322608, -958518, -2271749, -789860, -2254538, -850308,
+ -2384436, -850959, -2133734, -587678, -2093316, -495115, -1973364,
+ -475177, -1801282, -173507, -1848516, -158015, -1792018, -62648,
+ -1643313, 214746, -1500758, 267077, -1450193, 560521, -1521579,
+ 675283, -1345408, 857559, -1300822, 1116332, -1294533, 1241117,
+ -1070027, 1263503, -983816, 1529821, -1019586, 1910421, -955420,
+ 2073688, -836459, 2401105, -653905, 2690474, -731425, 2930131,
+ -935234, 3299500, -875978, 3523432, -878906, 3924822, -1081630,
+ 4561267, -1203023, 5105274, -1510983, 6052762, -2294646, 7021597,
+ -3108053, 8826736, -4935222, 11678789, -8442713, 18725700, -21526692,
+ 25420577, 19589811, -28108666, 12634054, -14483066, 6263217, -9979706,
+ 3665661, -7909736, 2531530, -6434896, 1700772, -5525393, 1479473,
+ -4894262, 1231760, -4353044, 1032940, -3786590, 941152, -3331614,
+ 665090, -2851619, 830696, -2762201, 958007, -2483118, 788233,
+ -2184965, 804825, -1967306, 1007255, -1862474, 920889, -1457506,
+ 755406, -1405841, 890230, -1302124, 1161599, -701867, 1154163,
+ -1083366, 1204743, -513581, 1547264, -650636, 1493384, -285543,
+ 1771863, -277906, 1841343, -9078, 1751863, 230222, 1819578,
+ 207170, 1978972, 398137, 2106468, 552155, 1997624, 685213,
+ 2129520, 601078, 2238736, 944591, 2441879, 1194178, 2355280,
+ 986124, 2393328, 1049005, 2417944, 1208368, 2489516, 1352023,
+ 2572118, 1445283, 2856081, 1532997, 2742279, 1615877, 2915274,
+ 1808036, 2856871, 1806936, 3241747, 1622461, 2978558, 1841297,
+ 3010378, 1923666, 3271367, 2126700, 3070935, 1956958, 3107588,
+ 2128405, 3288872, 2114911, 3315952, 2406651, 3344038, 2370199,
+ 3368980, 2144361, 3305030, 2183803, 3401450, 2523102, 3405463,
+ 2452475, 3463355, 2421678, 3551968, 2431949, 3477251, 2148125,
+ 3244489, 2174090};
+static const int32_t spec2time_out_expected_2[kSamples] = {
+ 1691694, -2499988, -2035547, 1060469, 988634, -2044502, -306271,
+ 2041000, 201454, -2289456, 93694, 2129427, -369152, -1887834,
+ 860796, 2089102, -929424, -1673956, 1395291, 1785651, -1619673,
+ -1380109, 1963449, 1093311, -2111007, -840456, 2372786, 578119,
+ -2242702, 89774, 2463304, -132717, -2121480, 643634, 2277636,
+ -1125999, -1995858, 1543748, 2227861, -1483779, -1495491, 2102642,
+ 1833876, -1920568, -958378, 2485101, 772261, -2454257, -24942,
+ 2918714, 136838, -2500453, 816118, 3039735, -746560, -2365815,
+ 1586396, 2714951, -1511696, -1942334, 2571792, 2182827, -2325335,
+ -1311543, 3055970, 1367220, -2737182, -110626, 3889222, 631008,
+ -3280879, 853066, 4122279, -706638, -3334449, 2148311, 3993512,
+ -1846301, -3004894, 3426779, 3329522, -3165264, -2242423, 4756866,
+ 2557711, -4131280, -805259, 5702711, 1120592, -4852821, 743664,
+ 6476444, -621186, -5465828, 2815787, 6768835, -3017442, -5338409,
+ 5658126, 6838454, -5492288, -4682382, 8874947, 6153814, -8832561,
+ -2649251, 12817398, 4237692, -13000247, 1190661, 18986363, -115738,
+ -19693978, 9908367, 30660381, -10632635, -37962068, 47022884, 89744622,
+ -42087632, 40279224, -88869341, -47542383, 38572364, 10441576, -30339718,
+ -9926740, 19896578, 28009, -18886612, -1124047, 13232498, -4150304,
+ -12770551, 2637074, 9051831, -6162211, -8713972, 4557937, 5489716,
+ -6862312, -5532349, 5415449, 2791310, -6999367, -2790102, 5375806,
+ 546222, -6486452, -821261, 4994973, -1278840, -5645501, 1060484,
+ 3996285, -2503954, -4653629, 2220549, 3036977, -3282133, -3318585,
+ 2780636, 1789880, -4004589, -2041031, 3105373, 574819, -3992722,
+ -971004, 3001703, -676739, -3841508, 417284, 2897970, -1427018,
+ -3058480, 1189948, 2210960, -2268992, -2603272, 1949785, 1576172,
+ -2720404, -1891738, 2309456, 769178, -2975646, -707150, 2424652,
+ -88039, -2966660, -65452, 2320780, -957557, -2798978, 744640,
+ 1879794, -1672081, -2365319, 1253309, 1366383, -2204082, -1544367,
+ 1801452, 613828, -2531994, -983847, 2064842, 118326, -2613790,
+ -203220, 2219635, -730341, -2641861, 563557, 1765434, -1329916,
+ -2272927, 1037138, 1266725, -1939220, -1588643, 1754528, 816552,
+ -2376303, -1099167, 1864999, 122477, -2422762, -400027, 1889228,
+ -579916, -2490353, 287139, 2011318, -1176657, -2502978, 812896,
+ 1116502, -1940211};
+static const int16_t time2spec_out_expected_1[kSamples] = {
+ 20342, 23889, -10063, -9419, 3242, 7280, -2012, -5029, 332, 4478,
+ -97, -3244, -891, 3117, 773, -2204, -1335, 2009, 1236, -1469,
+ -1562, 1277, 1366, -815, -1619, 599, 1449, -177, -1507, 116,
+ 1294, 263, -1338, -244, 1059, 553, -1045, -549, 829, 826,
+ -731, -755, 516, 909, -427, -853, 189, 1004, -184, -828,
+ -108, 888, 72, -700, -280, 717, 342, -611, -534, 601,
+ 534, -374, -646, 399, 567, -171, -720, 234, 645, -11,
+ -712, -26, 593, 215, -643, -172, 536, 361, -527, -403,
+ 388, 550, -361, -480, 208, 623, -206, -585, 41, 578,
+ 12, -504, -182, 583, 218, -437, -339, 499, 263, -354,
+ -450, 347, 456, -193, -524, 212, 475, -74, -566, 94,
+ 511, 112, -577, -201, 408, 217, -546, -295, 338, 387,
+ -13, 4, -46, 2, -76, 103, -83, 108, -55, 100,
+ -150, 131, -156, 141, -171, 179, -190, 128, -227, 172,
+ -214, 215, -189, 265, -244, 322, -335, 337, -352, 358,
+ -368, 362, -355, 366, -381, 403, -395, 411, -392, 446,
+ -458, 504, -449, 507, -464, 452, -491, 481, -534, 486,
+ -516, 560, -535, 525, -537, 559, -554, 570, -616, 591,
+ -585, 627, -509, 588, -584, 547, -610, 580, -614, 635,
+ -620, 655, -554, 546, -591, 642, -590, 660, -656, 629,
+ -604, 620, -580, 617, -645, 648, -573, 612, -604, 584,
+ -571, 597, -562, 627, -550, 560, -606, 529, -584, 568,
+ -503, 532, -463, 512, -440, 399, -457, 437, -349, 278,
+ -317, 257, -220, 163, -8, -61, 18, -161, 367, -1306};
+static const int16_t time2spec_out_expected_2[kSamples] = {
+ 14283, -11552, -15335, 6626, 7554, -2150, -6309, 1307, 4523, -4,
+ -3908, -314, 3001, 914, -2715, -1042, 2094, 1272, -1715, -1399,
+ 1263, 1508, -1021, -1534, 735, 1595, -439, -1447, 155, 1433,
+ 22, -1325, -268, 1205, 424, -1030, -608, 950, 643, -733,
+ -787, 661, 861, -502, -888, 331, 852, -144, -849, 19,
+ 833, 99, -826, -154, 771, 368, -735, -459, 645, 513,
+ -491, -604, 431, 630, -314, -598, 183, 622, -78, -612,
+ -48, 641, 154, -645, -257, 610, 281, -529, -444, 450,
+ 441, -327, -506, 274, 476, -232, -570, 117, 554, -86,
+ -531, -21, 572, 151, -606, -221, 496, 322, -407, -388,
+ 407, 394, -268, -428, 280, 505, -115, -588, 19, 513,
+ -29, -539, -109, 468, 173, -501, -242, 442, 278, -478,
+ -680, 656, -659, 656, -669, 602, -688, 612, -667, 612,
+ -642, 627, -648, 653, -676, 596, -680, 655, -649, 678,
+ -672, 587, -608, 637, -645, 637, -620, 556, -580, 553,
+ -635, 518, -599, 583, -501, 536, -544, 473, -552, 583,
+ -511, 541, -532, 563, -486, 461, -453, 486, -388, 424,
+ -416, 432, -374, 399, -462, 364, -346, 293, -329, 331,
+ -313, 281, -247, 309, -337, 241, -190, 207, -194, 179,
+ -163, 155, -156, 117, -135, 107, -126, 29, -22, 81,
+ -8, 17, -61, -10, 8, -37, 80, -44, 72, -88,
+ 65, -89, 130, -114, 181, -215, 189, -245, 260, -288,
+ 294, -339, 344, -396, 407, -429, 438, -439, 485, -556,
+ 629, -612, 637, -645, 661, -737, 829, -830, 831, -1041};
+
+class TransformTest : public ::testing::Test {
+ protected:
+ // Pass a function pointer to the Tester function.
+ void Time2SpecTester(Time2Spec Time2SpecFunction) {
+ // WebRtcIsacfix_Time2Spec functions hard coded the buffer lengths. It's a
+ // large buffer but we have to test it here.
+ int16_t data_in_1[kSamples] = {0};
+ int16_t data_in_2[kSamples] = {0};
+ int16_t data_out_1[kSamples] = {0};
+ int16_t data_out_2[kSamples] = {0};
+
+ for (int i = 0; i < kSamples; i++) {
+ data_in_1[i] = i * i + 1777;
+ data_in_2[i] = WEBRTC_SPL_WORD16_MAX / (i + 1) + 17;
+ }
+
+ Time2SpecFunction(data_in_1, data_in_2, data_out_1, data_out_2);
+
+ for (int i = 0; i < kSamples; i++) {
+ // We don't require bit-exact for ARM assembly code.
+ EXPECT_LE(abs(time2spec_out_expected_1[i] - data_out_1[i]), 1);
+ EXPECT_LE(abs(time2spec_out_expected_2[i] - data_out_2[i]), 1);
+ }
+ }
+
+ // Pass a function pointer to the Tester function.
+ void Spec2TimeTester(Spec2Time Spec2TimeFunction) {
+ // WebRtcIsacfix_Spec2Time functions hard coded the buffer lengths. It's a
+ // large buffer but we have to test it here.
+ int16_t data_in_1[kSamples] = {0};
+ int16_t data_in_2[kSamples] = {0};
+ int32_t data_out_1[kSamples] = {0};
+ int32_t data_out_2[kSamples] = {0};
+ for (int i = 0; i < kSamples; i++) {
+ data_in_1[i] = i * i + 1777;
+ data_in_2[i] = WEBRTC_SPL_WORD16_MAX / (i + 1) + 17;
+ }
+
+ Spec2TimeFunction(data_in_1, data_in_2, data_out_1, data_out_2);
+
+ for (int i = 0; i < kSamples; i++) {
+ // We don't require bit-exact for ARM assembly code.
+ EXPECT_LE(abs(spec2time_out_expected_1[i] - data_out_1[i]), 16);
+ EXPECT_LE(abs(spec2time_out_expected_2[i] - data_out_2[i]), 16);
+ }
+ }
+};
+
+TEST_F(TransformTest, Time2SpecTest) {
+ Time2SpecTester(WebRtcIsacfix_Time2SpecC);
+#if defined(WEBRTC_HAS_NEON)
+ Time2SpecTester(WebRtcIsacfix_Time2SpecNeon);
+#endif
+}
+
+TEST_F(TransformTest, Spec2TimeTest) {
+ Spec2TimeTester(WebRtcIsacfix_Spec2TimeC);
+#if defined(WEBRTC_HAS_NEON)
+ Spec2TimeTester(WebRtcIsacfix_Spec2TimeNeon);
+#endif
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc
new file mode 100644
index 0000000000..903ac64aff
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
+#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
+#include "rtc_base/checks.h"
+
+using std::string;
+
+namespace webrtc {
+
+static const int kIsacBlockDurationMs = 30;
+static const int kIsacInputSamplingKhz = 16;
+static const int kIsacOutputSamplingKhz = 16;
+
+class IsacSpeedTest : public AudioCodecSpeedTest {
+ protected:
+ IsacSpeedTest();
+ void SetUp() override;
+ void TearDown() override;
+ float EncodeABlock(int16_t* in_data,
+ uint8_t* bit_stream,
+ size_t max_bytes,
+ size_t* encoded_bytes) override;
+ float DecodeABlock(const uint8_t* bit_stream,
+ size_t encoded_bytes,
+ int16_t* out_data) override;
+ ISACFIX_MainStruct* ISACFIX_main_inst_;
+};
+
+IsacSpeedTest::IsacSpeedTest()
+ : AudioCodecSpeedTest(kIsacBlockDurationMs,
+ kIsacInputSamplingKhz,
+ kIsacOutputSamplingKhz),
+ ISACFIX_main_inst_(NULL) {}
+
+void IsacSpeedTest::SetUp() {
+ AudioCodecSpeedTest::SetUp();
+
+ // Check whether the allocated buffer for the bit stream is large enough.
+ EXPECT_GE(max_bytes_, static_cast<size_t>(STREAM_MAXW16_60MS));
+
+ // Create encoder memory.
+ EXPECT_EQ(0, WebRtcIsacfix_Create(&ISACFIX_main_inst_));
+ EXPECT_EQ(0, WebRtcIsacfix_EncoderInit(ISACFIX_main_inst_, 1));
+ WebRtcIsacfix_DecoderInit(ISACFIX_main_inst_);
+ // Set bitrate and block length.
+ EXPECT_EQ(0, WebRtcIsacfix_Control(ISACFIX_main_inst_, bit_rate_,
+ block_duration_ms_));
+}
+
+void IsacSpeedTest::TearDown() {
+ AudioCodecSpeedTest::TearDown();
+ // Free memory.
+ EXPECT_EQ(0, WebRtcIsacfix_Free(ISACFIX_main_inst_));
+}
+
+float IsacSpeedTest::EncodeABlock(int16_t* in_data,
+ uint8_t* bit_stream,
+ size_t max_bytes,
+ size_t* encoded_bytes) {
+ // ISAC takes 10 ms everycall
+ const int subblocks = block_duration_ms_ / 10;
+ const int subblock_length = 10 * input_sampling_khz_;
+ int value = 0;
+
+ clock_t clocks = clock();
+ size_t pointer = 0;
+ for (int idx = 0; idx < subblocks; idx++, pointer += subblock_length) {
+ value =
+ WebRtcIsacfix_Encode(ISACFIX_main_inst_, &in_data[pointer], bit_stream);
+ if (idx == subblocks - 1)
+ EXPECT_GT(value, 0);
+ else
+ EXPECT_EQ(0, value);
+ }
+ clocks = clock() - clocks;
+ *encoded_bytes = static_cast<size_t>(value);
+ RTC_DCHECK_LE(*encoded_bytes, max_bytes);
+ return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+float IsacSpeedTest::DecodeABlock(const uint8_t* bit_stream,
+ size_t encoded_bytes,
+ int16_t* out_data) {
+ int value;
+ int16_t audio_type;
+ clock_t clocks = clock();
+ value = WebRtcIsacfix_Decode(ISACFIX_main_inst_, bit_stream, encoded_bytes,
+ out_data, &audio_type);
+ clocks = clock() - clocks;
+ EXPECT_EQ(output_length_sample_, static_cast<size_t>(value));
+ return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+TEST_P(IsacSpeedTest, IsacEncodeDecodeTest) {
+ size_t kDurationSec = 400; // Test audio length in second.
+ EncodeDecode(kDurationSec);
+}
+
+const coding_param param_set[] = {
+ std::make_tuple(1,
+ 32000,
+ string("audio_coding/speech_mono_16kHz"),
+ string("pcm"),
+ true)};
+
+INSTANTIATE_TEST_SUITE_P(AllTest,
+ IsacSpeedTest,
+ ::testing::ValuesIn(param_set));
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc
new file mode 100644
index 0000000000..cafca75e46
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <array>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/audio_codecs/isac/audio_decoder_isac_fix.h"
+#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_fix.h"
+#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
+#include "modules/audio_coding/test/PCMFile.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/strings/string_builder.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+namespace {
+
+constexpr int kPayloadType = 42;
+
+enum class IsacImpl { kFixed, kFloat };
+
+absl::string_view IsacImplToString(IsacImpl impl) {
+ switch (impl) {
+ case IsacImpl::kFixed:
+ return "fixed";
+ case IsacImpl::kFloat:
+ return "float";
+ }
+}
+
+std::unique_ptr<PCMFile> GetPcmTestFileReader(int sample_rate_hz) {
+ std::string filename;
+ switch (sample_rate_hz) {
+ case 16000:
+ filename = test::ResourcePath("audio_coding/testfile16kHz", "pcm");
+ break;
+ case 32000:
+ filename = test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+ break;
+ default:
+ RTC_DCHECK_NOTREACHED()
+ << "No test file available for " << sample_rate_hz << " Hz.";
+ }
+ auto pcm_file = std::make_unique<PCMFile>();
+ pcm_file->ReadStereo(false);
+ pcm_file->Open(filename, sample_rate_hz, "rb", /*auto_rewind=*/true);
+ pcm_file->FastForward(/*num_10ms_blocks=*/100); // Skip initial silence.
+ RTC_CHECK(!pcm_file->EndOfFile());
+ return pcm_file;
+}
+
+// Returns a view to the interleaved samples of an AudioFrame object.
+rtc::ArrayView<const int16_t> AudioFrameToView(const AudioFrame& audio_frame) {
+ return {audio_frame.data(),
+ audio_frame.samples_per_channel() * audio_frame.num_channels()};
+}
+
+std::unique_ptr<AudioEncoder> CreateEncoder(IsacImpl impl,
+ int sample_rate_hz,
+ int frame_size_ms,
+ int bitrate_bps) {
+ RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000);
+ RTC_CHECK(frame_size_ms == 30 || frame_size_ms == 60);
+ RTC_CHECK_GT(bitrate_bps, 0);
+ switch (impl) {
+ case IsacImpl::kFixed: {
+ AudioEncoderIsacFix::Config config;
+ config.bit_rate = bitrate_bps;
+ config.frame_size_ms = frame_size_ms;
+ RTC_CHECK_EQ(16000, sample_rate_hz);
+ return AudioEncoderIsacFix::MakeAudioEncoder(config, kPayloadType);
+ }
+ case IsacImpl::kFloat: {
+ AudioEncoderIsacFloat::Config config;
+ config.bit_rate = bitrate_bps;
+ config.frame_size_ms = frame_size_ms;
+ config.sample_rate_hz = sample_rate_hz;
+ return AudioEncoderIsacFloat::MakeAudioEncoder(config, kPayloadType);
+ }
+ }
+}
+
+std::unique_ptr<AudioDecoder> CreateDecoder(IsacImpl impl, int sample_rate_hz) {
+ RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000);
+ switch (impl) {
+ case IsacImpl::kFixed: {
+ webrtc::AudioDecoderIsacFix::Config config;
+ RTC_CHECK_EQ(16000, sample_rate_hz);
+ return webrtc::AudioDecoderIsacFix::MakeAudioDecoder(config);
+ }
+ case IsacImpl::kFloat: {
+ webrtc::AudioDecoderIsacFloat::Config config;
+ config.sample_rate_hz = sample_rate_hz;
+ return webrtc::AudioDecoderIsacFloat::MakeAudioDecoder(config);
+ }
+ }
+}
+
+struct EncoderTestParams {
+ IsacImpl impl;
+ int sample_rate_hz;
+ int frame_size_ms;
+};
+
+class EncoderTest : public testing::TestWithParam<EncoderTestParams> {
+ protected:
+ EncoderTest() = default;
+ IsacImpl GetIsacImpl() const { return GetParam().impl; }
+ int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
+ int GetFrameSizeMs() const { return GetParam().frame_size_ms; }
+};
+
+TEST_P(EncoderTest, TestConfig) {
+ for (int bitrate_bps : {10000, 21000, 32000}) {
+ SCOPED_TRACE(bitrate_bps);
+ auto encoder = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+ GetFrameSizeMs(), bitrate_bps);
+ EXPECT_EQ(GetSampleRateHz(), encoder->SampleRateHz());
+ EXPECT_EQ(size_t{1}, encoder->NumChannels());
+ EXPECT_EQ(bitrate_bps, encoder->GetTargetBitrate());
+ }
+}
+
+// Encodes an input audio sequence with a low and a high target bitrate and
+// checks that the number of produces bytes in the first case is less than that
+// of the second case.
+TEST_P(EncoderTest, TestDifferentBitrates) {
+ auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+ constexpr int kLowBps = 20000;
+ constexpr int kHighBps = 25000;
+ auto encoder_low = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+ GetFrameSizeMs(), kLowBps);
+ auto encoder_high = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+ GetFrameSizeMs(), kHighBps);
+ int num_bytes_low = 0;
+ int num_bytes_high = 0;
+ constexpr int kNumFrames = 12;
+ for (int i = 0; i < kNumFrames; ++i) {
+ AudioFrame in;
+ pcm_file->Read10MsData(in);
+ rtc::Buffer low, high;
+ encoder_low->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &low);
+ encoder_high->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &high);
+ num_bytes_low += low.size();
+ num_bytes_high += high.size();
+ }
+ EXPECT_LT(num_bytes_low, num_bytes_high);
+}
+
+// Encodes an input audio sequence first with a low, then with a high target
+// bitrate *using the same encoder* and checks that the number of emitted bytes
+// in the first case is less than in the second case.
+TEST_P(EncoderTest, TestDynamicBitrateChange) {
+ constexpr int kLowBps = 20000;
+ constexpr int kHighBps = 25000;
+ constexpr int kStartBps = 30000;
+ auto encoder = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
+ GetFrameSizeMs(), kStartBps);
+ std::map<int, int> num_bytes;
+ constexpr int kNumFrames = 200; // 2 seconds.
+ for (int bitrate_bps : {kLowBps, kHighBps}) {
+ auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+ encoder->OnReceivedTargetAudioBitrate(bitrate_bps);
+ for (int i = 0; i < kNumFrames; ++i) {
+ AudioFrame in;
+ pcm_file->Read10MsData(in);
+ rtc::Buffer buf;
+ encoder->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &buf);
+ num_bytes[bitrate_bps] += buf.size();
+ }
+ }
+ // kHighBps / kLowBps == 1.25, so require the high-bitrate run to produce at
+ // least 1.195 times the number of bytes.
+ EXPECT_LT(1.195 * num_bytes[kLowBps], num_bytes[kHighBps]);
+}
+
+// Checks that, given a target bitrate, the encoder does not overshoot too much.
+TEST_P(EncoderTest, DoNotOvershootTargetBitrate) {
+ for (int bitrate_bps : {10000, 15000, 20000, 26000, 32000}) {
+ SCOPED_TRACE(bitrate_bps);
+ auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+ auto e = CreateEncoder(GetIsacImpl(), GetSampleRateHz(), GetFrameSizeMs(),
+ bitrate_bps);
+ int num_bytes = 0;
+ constexpr int kNumFrames = 200; // 2 seconds.
+ for (int i = 0; i < kNumFrames; ++i) {
+ AudioFrame in;
+ pcm_file->Read10MsData(in);
+ rtc::Buffer encoded;
+ e->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &encoded);
+ num_bytes += encoded.size();
+ }
+ // Inverse of the duration of `kNumFrames` 10 ms frames (unit: seconds^-1).
+ constexpr float kAudioDurationInv = 100.f / kNumFrames;
+ const int measured_bitrate_bps = 8 * num_bytes * kAudioDurationInv;
+ EXPECT_LT(measured_bitrate_bps, bitrate_bps + 2250); // Max 2250 bps extra.
+ }
+}
+
+// Creates tests for different encoder configurations and implementations.
+INSTANTIATE_TEST_SUITE_P(
+ IsacApiTest,
+ EncoderTest,
+ ::testing::ValuesIn([] {
+ std::vector<EncoderTestParams> cases;
+ for (IsacImpl impl : {IsacImpl::kFloat, IsacImpl::kFixed}) {
+ for (int frame_size_ms : {30, 60}) {
+ cases.push_back({impl, 16000, frame_size_ms});
+ }
+ }
+ cases.push_back({IsacImpl::kFloat, 32000, 30});
+ return cases;
+ }()),
+ [](const ::testing::TestParamInfo<EncoderTestParams>& info) {
+ rtc::StringBuilder b;
+ const auto& p = info.param;
+ b << IsacImplToString(p.impl) << "_" << p.sample_rate_hz << "_"
+ << p.frame_size_ms;
+ return b.Release();
+ });
+
+struct DecoderTestParams {
+ IsacImpl impl;
+ int sample_rate_hz;
+};
+
+class DecoderTest : public testing::TestWithParam<DecoderTestParams> {
+ protected:
+ DecoderTest() = default;
+ IsacImpl GetIsacImpl() const { return GetParam().impl; }
+ int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
+};
+
+TEST_P(DecoderTest, TestConfig) {
+ auto decoder = CreateDecoder(GetIsacImpl(), GetSampleRateHz());
+ EXPECT_EQ(GetSampleRateHz(), decoder->SampleRateHz());
+ EXPECT_EQ(size_t{1}, decoder->Channels());
+}
+
+// Creates tests for different decoder configurations and implementations.
+INSTANTIATE_TEST_SUITE_P(
+ IsacApiTest,
+ DecoderTest,
+ ::testing::ValuesIn({DecoderTestParams{IsacImpl::kFixed, 16000},
+ DecoderTestParams{IsacImpl::kFloat, 16000},
+ DecoderTestParams{IsacImpl::kFloat, 32000}}),
+ [](const ::testing::TestParamInfo<DecoderTestParams>& info) {
+ const auto& p = info.param;
+ return (rtc::StringBuilder()
+ << IsacImplToString(p.impl) << "_" << p.sample_rate_hz)
+ .Release();
+ });
+
+struct EncoderDecoderPairTestParams {
+ int sample_rate_hz;
+ int frame_size_ms;
+ IsacImpl encoder_impl;
+ IsacImpl decoder_impl;
+};
+
+class EncoderDecoderPairTest
+ : public testing::TestWithParam<EncoderDecoderPairTestParams> {
+ protected:
+ EncoderDecoderPairTest() = default;
+ int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
+ int GetEncoderFrameSizeMs() const { return GetParam().frame_size_ms; }
+ IsacImpl GetEncoderIsacImpl() const { return GetParam().encoder_impl; }
+ IsacImpl GetDecoderIsacImpl() const { return GetParam().decoder_impl; }
+ int GetEncoderFrameSize() const {
+ return GetEncoderFrameSizeMs() * GetSampleRateHz() / 1000;
+ }
+};
+
+// Checks that the number of encoded and decoded samples match.
+TEST_P(EncoderDecoderPairTest, EncodeDecode) {
+ auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
+ auto encoder = CreateEncoder(GetEncoderIsacImpl(), GetSampleRateHz(),
+ GetEncoderFrameSizeMs(), /*bitrate_bps=*/20000);
+ auto decoder = CreateDecoder(GetDecoderIsacImpl(), GetSampleRateHz());
+ const int encoder_frame_size = GetEncoderFrameSize();
+ std::vector<int16_t> out(encoder_frame_size);
+ size_t num_encoded_samples = 0;
+ size_t num_decoded_samples = 0;
+ constexpr int kNumFrames = 12;
+ for (int i = 0; i < kNumFrames; ++i) {
+ AudioFrame in;
+ pcm_file->Read10MsData(in);
+ rtc::Buffer encoded;
+ encoder->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &encoded);
+ num_encoded_samples += in.samples_per_channel();
+ if (encoded.empty()) {
+ continue;
+ }
+ // Decode.
+ const std::vector<AudioDecoder::ParseResult> parse_result =
+ decoder->ParsePayload(std::move(encoded), /*timestamp=*/0);
+ EXPECT_EQ(parse_result.size(), size_t{1});
+ auto decode_result = parse_result[0].frame->Decode(out);
+ EXPECT_TRUE(decode_result.has_value());
+ EXPECT_EQ(out.size(), decode_result->num_decoded_samples);
+ num_decoded_samples += decode_result->num_decoded_samples;
+ }
+ EXPECT_EQ(num_encoded_samples, num_decoded_samples);
+}
+
+// Creates tests for different encoder frame sizes and different
+// encoder/decoder implementations.
+INSTANTIATE_TEST_SUITE_P(
+ IsacApiTest,
+ EncoderDecoderPairTest,
+ ::testing::ValuesIn([] {
+ std::vector<EncoderDecoderPairTestParams> cases;
+ for (int frame_size_ms : {30, 60}) {
+ for (IsacImpl enc : {IsacImpl::kFloat, IsacImpl::kFixed}) {
+ for (IsacImpl dec : {IsacImpl::kFloat, IsacImpl::kFixed}) {
+ cases.push_back({16000, frame_size_ms, enc, dec});
+ }
+ }
+ }
+ cases.push_back({32000, 30, IsacImpl::kFloat, IsacImpl::kFloat});
+ return cases;
+ }()),
+ [](const ::testing::TestParamInfo<EncoderDecoderPairTestParams>& info) {
+ rtc::StringBuilder b;
+ const auto& p = info.param;
+ b << p.sample_rate_hz << "_" << p.frame_size_ms << "_"
+ << IsacImplToString(p.encoder_impl) << "_"
+ << IsacImplToString(p.decoder_impl);
+ return b.Release();
+ });
+
+} // namespace
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h
new file mode 100644
index 0000000000..fae2f3d4a7
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_DECODER_ISAC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_DECODER_ISAC_H_
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_float_type.h"
+
+namespace webrtc {
+
+using AudioDecoderIsacFloatImpl = AudioDecoderIsacT<IsacFloat>;
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h
new file mode 100644
index 0000000000..dc32bcdde6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_float_type.h"
+
+namespace webrtc {
+
+using AudioEncoderIsacFloatImpl = AudioEncoderIsacT<IsacFloat>;
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_AUDIO_ENCODER_ISAC_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/isac.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/isac.h
new file mode 100644
index 0000000000..3b05a8bcda
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/include/isac.h
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_ISAC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_ISAC_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+
+typedef struct WebRtcISACStruct ISACStruct;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/******************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsac_Create(ISACStruct** ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : an ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsac_Free(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_EncoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - CodingMode : 0 -> Bit rate and frame length are
+ * automatically adjusted to available bandwidth
+ * on transmission channel, just valid if codec
+ * is created to work in wideband mode.
+ * 1 -> User sets a frame length and a target bit
+ * rate which is taken as the maximum
+ * short-term average bit rate.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsac_EncoderInit(ISACStruct* ISAC_main_inst, int16_t CodingMode);
+
+/******************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms audio blocks and inserts it into a package.
+ * Input speech length has 160 samples if operating at 16 kHz sampling
+ * rate, or 320 if operating at 32 kHz sampling rate. The encoder buffers the
+ * input audio until the whole frame is buffered then proceeds with encoding.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - speechIn : input speech vector.
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : 0 - The buffer didn't reach the chosen
+ * frame-size so it keeps buffering speech
+ * samples.
+ * : -1 - Error
+ */
+
+int WebRtcIsac_Encode(ISACStruct* ISAC_main_inst,
+ const int16_t* speechIn,
+ uint8_t* encoded);
+
+/******************************************************************************
+ * WebRtcIsac_DecoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ */
+
+void WebRtcIsac_DecoderInit(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - send_ts : the RTP send timestamp, given in samples
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsac_UpdateBwEstimate(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts);
+
+/******************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes an ISAC frame. At 16 kHz sampling rate, the length
+ * of the output audio could be either 480 or 960 samples, equivalent to
+ * 30 or 60 ms respectively. At 32 kHz sampling rate, the length of the
+ * output audio is 960 samples, which is 30 ms.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - len : bytes in encoded vector.
+ *
+ * Output:
+ * - decoded : The decoded vector.
+ *
+ * Return value : >0 - number of samples in decoded vector.
+ * -1 - Error.
+ */
+
+int WebRtcIsac_Decode(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/******************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of frames, i.e. multiples of 30 ms audio. Therefore,
+ * the output is multiple of 480 samples if operating at 16 kHz and multiple
+ * of 960 if operating at 32 kHz.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames to produce.
+ *
+ * Output:
+ * - decoded : The decoded vector.
+ *
+ * Return value : Number of samples in decoded PLC vector
+ */
+
+size_t WebRtcIsac_DecodePlc(ISACStruct* ISAC_main_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames);
+
+/******************************************************************************
+ * WebRtcIsac_Control(...)
+ *
+ * This function sets the limit on the short-term average bit-rate and the
+ * frame length. Should be used only in Instantaneous mode. At 16 kHz sampling
+ * rate, an average bit-rate between 10000 to 32000 bps is valid and a
+ * frame-size of 30 or 60 ms is acceptable. At 32 kHz, an average bit-rate
+ * between 10000 to 56000 is acceptable, and the valid frame-size is 30 ms.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second.
+ * - framesize : frame-size in millisecond.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsac_Control(ISACStruct* ISAC_main_inst,
+ int32_t rate,
+ int framesize);
+
+void WebRtcIsac_SetInitialBweBottleneck(ISACStruct* ISAC_main_inst,
+ int bottleneck_bits_per_second);
+
+/******************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Therefore, this API is not
+ * applicable if the codec is created to operate in super-wideband mode.
+ *
+ * Through this API, users can enforce a frame-size for all values of
+ * bottleneck. Then iSAC will not automatically change the frame-size.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rateBPS : initial value of bottleneck in bits/second
+ * 10000 <= rateBPS <= 56000 is accepted
+ * For default bottleneck set rateBPS = 0
+ * - frameSizeMs : number of milliseconds per frame (30 or 60)
+ * - enforceFrameSize : 1 to enforce the given frame-size through
+ * out the adaptation process, 0 to let iSAC
+ * change the frame-size if required.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+int16_t WebRtcIsac_ControlBwe(ISACStruct* ISAC_main_inst,
+ int32_t rateBPS,
+ int frameSizeMs,
+ int16_t enforceFrameSize);
+
+/******************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ * - encoded : Encoded bit-stream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+
+int16_t WebRtcIsac_ReadFrameLen(const ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ int16_t* frameLength);
+
+/******************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+void WebRtcIsac_version(char* version);
+
+/******************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occurred in the
+ * specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+
+int16_t WebRtcIsac_GetErrorCode(ISACStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through in-band
+ * signalling retreived by bandwidth estimator.
+ * In channel-independent, also called instantaneous mode, the target
+ * bottleneck is provided to the encoder by calling xxx_control(...). If
+ * xxx_control is never called the default values is returned. The default
+ * value for bottleneck at 16 kHz encoder sampling rate is 32000 bits/sec,
+ * and it is 56000 bits/sec for 32 kHz sampling rate.
+ * Note that the output is the iSAC internal operating bottleneck which might
+ * differ slightly from the one provided through xxx_control().
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Output:
+ * - *bottleneck : bottleneck in bits/sec
+ *
+ * Return value : -1 if error happens
+ * 0 bit-rates computed correctly.
+ */
+
+int16_t WebRtcIsac_GetUplinkBw(ISACStruct* ISAC_main_inst, int32_t* bottleneck);
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 ms packets. If the encoder sampling rate
+ * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
+ * encoder sampling rate is 32 kHz the maximum payload size is between 120
+ * and 600 bytes.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, i.e. min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 120 and 400 bytes
+ * if encoder sampling rate is 16 kHz. For
+ * 32 kHz encoder sampling rate valid values
+ * are between 120 and 600 bytes.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+
+int16_t WebRtcIsac_SetMaxPayloadSize(ISACStruct* ISAC_main_inst,
+ int16_t maxPayloadBytes);
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for
+ * any signal packet. The maximum rate is defined and payload-size per
+ * frame-size in bits per second.
+ *
+ * The codec has a maximum rate of 53400 bits per second (200 bytes per 30
+ * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
+ * if the encoder sampling rate is 32 kHz.
+ *
+ * It is possible to set a maximum rate between 32000 and 53400 bits/sec
+ * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRate : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits/sec in
+ * wideband mode, and 32000 to 160000 bits/sec in
+ * super-wideband mode.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+
+int16_t WebRtcIsac_SetMaxRate(ISACStruct* ISAC_main_inst, int32_t maxRate);
+
+/******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : sampling frequency in Hertz.
+ *
+ */
+
+uint16_t WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : sampling rate in Hertz.
+ *
+ */
+
+uint16_t WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst);
+
+/******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * Set the sampling rate of the decoder. Initialization of the decoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : sampling rate in Hertz.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+
+int16_t WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst,
+ uint16_t samp_rate_hz);
+
+/******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * Set the sampling rate of the encoder. Initialization of the encoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created. The encoding-mode and the
+ * bottleneck remain unchanged by this call, however, the maximum rate and
+ * maximum payload-size will reset to their default value.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : sampling rate in Hertz.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+
+int16_t WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst,
+ uint16_t sample_rate_hz);
+
+/******************************************************************************
+ * WebRtcIsac_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. If the rate is set to a value less than bottleneck of codec
+ * the new bistream will be re-encoded with the given target rate.
+ * It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames.
+ *
+ * NOTE 1! This function does not write in the ISACStruct, it is not allowed.
+ * NOTE 2! Currently not implemented for SWB mode.
+ * NOTE 3! Rates larger than the bottleneck of the codec will be limited
+ * to the current bottleneck.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : Index of bandwidth estimate to put in new
+ * bitstream
+ * - rate : target rate of the transcoder is bits/sec.
+ * Valid values are the accepted rate in iSAC,
+ * i.e. 10000 to 56000.
+ * - isRCU : if the new bit-stream is an RCU
+ * stream. Note that the rate parameter always indicates the target rate of the
+ * main payload, regardless of 'isRCU' value.
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error or called in SWB mode
+ * NOTE! No error code is written to
+ * the struct since it is only allowed to read
+ * the struct.
+ */
+int16_t WebRtcIsac_GetNewBitStream(ISACStruct* ISAC_main_inst,
+ int16_t bweIndex,
+ int16_t jitterInfo,
+ int32_t rate,
+ uint8_t* encoded,
+ int16_t isRCU);
+
+/****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - bweIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+int16_t WebRtcIsac_GetDownLinkBwIndex(ISACStruct* ISAC_main_inst,
+ int16_t* bweIndex,
+ int16_t* jitterInfo);
+
+/****************************************************************************
+ * WebRtcIsac_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ * - bweIndex : Bandwidth estimate from other side.
+ *
+ */
+
+int16_t WebRtcIsac_UpdateUplinkBw(ISACStruct* ISAC_main_inst, int16_t bweIndex);
+
+/****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ * - bweIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+int16_t WebRtcIsac_ReadBwIndex(const uint8_t* encoded, int16_t* bweIndex);
+
+/*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * returns the frame lenght (in samples) of the next packet. In the case of
+ * channel-adaptive mode, iSAC decides on its frame lenght based on the
+ * estimated bottleneck this allows a user to prepare for the next packet (at
+ * the encoder)
+ *
+ * The primary usage is in CE to make the iSAC works in channel-adaptive mode
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Return Value : frame lenght in samples
+ *
+ */
+
+int16_t WebRtcIsac_GetNewFrameLen(ISACStruct* ISAC_main_inst);
+
+/****************************************************************************
+ * WebRtcIsac_GetRedPayload(...)
+ *
+ * Populates "encoded" with the redundant payload of the recently encoded
+ * frame. This function has to be called once that WebRtcIsac_Encode(...)
+ * returns a positive value. Regardless of the frame-size this function will
+ * be called only once after encoding is completed.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : -1 - Error
+ *
+ *
+ */
+int16_t WebRtcIsac_GetRedPayload(ISACStruct* ISAC_main_inst, uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload i case of packet loss. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC RCU frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+int WebRtcIsac_DecodeRcu(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speechType);
+
+/* If `inst` is a decoder but not an encoder: tell it what sample rate the
+ encoder is using, for bandwidth estimation purposes. */
+void WebRtcIsac_SetEncSampRateInDecoder(ISACStruct* inst, int sample_rate_hz);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INCLUDE_ISAC_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.c
new file mode 100644
index 0000000000..9d5c6930b1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+
+/*
+ * terminate and return byte stream;
+ * returns the number of bytes in the stream
+ */
+int WebRtcIsac_EncTerminate(Bitstr *streamdata) /* in-/output struct containing bitstream */
+{
+ uint8_t *stream_ptr;
+
+
+ /* point to the right place in the stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+
+ /* find minimum length (determined by current interval width) */
+ if ( streamdata->W_upper > 0x01FFFFFF )
+ {
+ streamdata->streamval += 0x01000000;
+ /* add carry to buffer */
+ if (streamdata->streamval < 0x01000000)
+ {
+ /* propagate carry */
+ while ( !(++(*--stream_ptr)) );
+ /* put pointer back to the old value */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ }
+ /* write remaining data to bitstream */
+ *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+ }
+ else
+ {
+ streamdata->streamval += 0x00010000;
+ /* add carry to buffer */
+ if (streamdata->streamval < 0x00010000)
+ {
+ /* propagate carry */
+ while ( !(++(*--stream_ptr)) );
+ /* put pointer back to the old value */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ }
+ /* write remaining data to bitstream */
+ *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+ *stream_ptr++ = (uint8_t) ((streamdata->streamval >> 16) & 0x00FF);
+ }
+
+ /* calculate stream length */
+ return (int)(stream_ptr - streamdata->stream);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.h
new file mode 100644
index 0000000000..3f9f6de7bb
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+int WebRtcIsac_EncLogisticMulti2(
+ Bitstr* streamdata, /* in-/output struct containing bitstream */
+ int16_t* dataQ7, /* input: data vector */
+ const uint16_t*
+ env, /* input: side info vector defining the width of the pdf */
+ int N, /* input: data vector length */
+ int16_t isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+/* returns the number of bytes in the stream */
+int WebRtcIsac_EncTerminate(
+ Bitstr* streamdata); /* in-/output struct containing bitstream */
+
+/* returns the number of bytes in the stream so far */
+int WebRtcIsac_DecLogisticMulti2(
+ int16_t* data, /* output: data vector */
+ Bitstr* streamdata, /* in-/output struct containing bitstream */
+ const uint16_t*
+ env, /* input: side info vector defining the width of the pdf */
+ const int16_t* dither, /* input: dither vector */
+ int N, /* input: data vector length */
+ int16_t isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+void WebRtcIsac_EncHistMulti(
+ Bitstr* streamdata, /* in-/output struct containing bitstream */
+ const int* data, /* input: data vector */
+ const uint16_t* const* cdf, /* input: array of cdf arrays */
+ int N); /* input: data vector length */
+
+int WebRtcIsac_DecHistBisectMulti(
+ int* data, /* output: data vector */
+ Bitstr* streamdata, /* in-/output struct containing bitstream */
+ const uint16_t* const* cdf, /* input: array of cdf arrays */
+ const uint16_t*
+ cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+ int N); /* input: data vector length */
+
+int WebRtcIsac_DecHistOneStepMulti(
+ int* data, /* output: data vector */
+ Bitstr* streamdata, /* in-/output struct containing bitstream */
+ const uint16_t* const* cdf, /* input: array of cdf arrays */
+ const uint16_t*
+ init_index, /* input: vector of initial cdf table search entries */
+ int N); /* input: data vector length */
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c
new file mode 100644
index 0000000000..e948979fd7
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+
+
+/*
+ * code symbols into arithmetic bytestream
+ */
+void WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const int *data, /* input: data vector */
+ const uint16_t *const *cdf, /* input: array of cdf arrays */
+ const int N) /* input: data vector length */
+{
+ uint32_t W_lower, W_upper;
+ uint32_t W_upper_LSB, W_upper_MSB;
+ uint8_t *stream_ptr;
+ uint8_t *stream_ptr_carry;
+ uint32_t cdf_lo, cdf_hi;
+ int k;
+
+
+ /* point to beginning of stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+
+ for (k=N; k>0; k--)
+ {
+ /* fetch cdf_lower and cdf_upper from cdf tables */
+ cdf_lo = (uint32_t) *(*cdf + *data);
+ cdf_hi = (uint32_t) *(*cdf++ + *data++ + 1);
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = W_upper_MSB * cdf_lo;
+ W_lower += (W_upper_LSB * cdf_lo) >> 16;
+ W_upper = W_upper_MSB * cdf_hi;
+ W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamdata->streamval += W_lower;
+
+ /* handle carry */
+ if (streamdata->streamval < W_lower)
+ {
+ /* propagate carry */
+ stream_ptr_carry = stream_ptr;
+ while (!(++(*--stream_ptr_carry)));
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ W_upper <<= 8;
+ *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+ streamdata->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+
+ return;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, using method of bisection
+ * cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2)
+ */
+int WebRtcIsac_DecHistBisectMulti(int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const uint16_t *const *cdf, /* input: array of cdf arrays */
+ const uint16_t *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+ const int N) /* input: data vector length */
+{
+ uint32_t W_lower, W_upper;
+ uint32_t W_tmp;
+ uint32_t W_upper_LSB, W_upper_MSB;
+ uint32_t streamval;
+ const uint8_t *stream_ptr;
+ const uint16_t *cdf_ptr;
+ int size_tmp;
+ int k;
+
+ W_lower = 0; //to remove warning -DH
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+ for (k=N; k>0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start halfway the cdf range */
+ size_tmp = *cdf_size++ >> 1;
+ cdf_ptr = *cdf + (size_tmp - 1);
+
+ /* method of bisection */
+ for ( ;; )
+ {
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ size_tmp >>= 1;
+ if (size_tmp == 0) break;
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ cdf_ptr += size_tmp;
+ } else {
+ W_upper = W_tmp;
+ cdf_ptr -= size_tmp;
+ }
+ }
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++);
+ } else {
+ W_upper = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++ - 1);
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, taking single step up or
+ * down at a time
+ * cdf tables can be of arbitrary size, but large tables may take a lot of iterations
+ */
+int WebRtcIsac_DecHistOneStepMulti(int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const uint16_t *const *cdf, /* input: array of cdf arrays */
+ const uint16_t *init_index, /* input: vector of initial cdf table search entries */
+ const int N) /* input: data vector length */
+{
+ uint32_t W_lower, W_upper;
+ uint32_t W_tmp;
+ uint32_t W_upper_LSB, W_upper_MSB;
+ uint32_t streamval;
+ const uint8_t *stream_ptr;
+ const uint16_t *cdf_ptr;
+ int k;
+
+
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = (uint32_t)(*stream_ptr) << 24;
+ streamval |= (uint32_t)(*++stream_ptr) << 16;
+ streamval |= (uint32_t)(*++stream_ptr) << 8;
+ streamval |= (uint32_t)(*++stream_ptr);
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+
+ for (k=N; k>0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start at the specified table entry */
+ cdf_ptr = *cdf + (*init_index++);
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval > W_tmp)
+ {
+ for ( ;; )
+ {
+ W_lower = W_tmp;
+ if (cdf_ptr[0]==65535)
+ /* range check */
+ return -3;
+ W_tmp = W_upper_MSB * *++cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval <= W_tmp) break;
+ }
+ W_upper = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++ - 1);
+ } else {
+ for ( ;; )
+ {
+ W_upper = W_tmp;
+ --cdf_ptr;
+ if (cdf_ptr<*cdf) {
+ /* range check */
+ return -3;
+ }
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval > W_tmp) break;
+ }
+ W_lower = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++);
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c
new file mode 100644
index 0000000000..777780f54f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * This file contains functions for arithmatically encoding and
+ * decoding DFT coefficients.
+ *
+ */
+
+
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+
+
+
+static const int32_t kHistEdgesQ15[51] = {
+ -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
+ -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644,
+ -65536, -52429, -39322, -26215, -13108, 0, 13107, 26214, 39321, 52428,
+ 65536, 78643, 91750, 104857, 117964, 131072, 144179, 157286, 170393, 183500,
+ 196608, 209715, 222822, 235929, 249036, 262144, 275251, 288358, 301465, 314572,
+ 327680};
+
+
+static const int kCdfSlopeQ0[51] = { /* Q0 */
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 13, 23, 47, 87, 154, 315, 700, 1088,
+ 2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
+ 1095, 660, 316, 145, 86, 41, 32, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 0};
+
+
+static const int kCdfQ16[51] = { /* Q16 */
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 22, 24, 29, 38, 57, 92, 153, 279, 559,
+ 994, 1983, 4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
+ 64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
+ 65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
+ 65535};
+
+
+
+/* function to be converted to fixed point */
+static __inline uint32_t piecewise(int32_t xinQ15) {
+
+ int32_t ind, qtmp1, qtmp2, qtmp3;
+ uint32_t tmpUW32;
+
+
+ qtmp2 = xinQ15;
+
+ if (qtmp2 < kHistEdgesQ15[0]) {
+ qtmp2 = kHistEdgesQ15[0];
+ }
+ if (qtmp2 > kHistEdgesQ15[50]) {
+ qtmp2 = kHistEdgesQ15[50];
+ }
+
+ qtmp1 = qtmp2 - kHistEdgesQ15[0]; /* Q15 - Q15 = Q15 */
+ ind = (qtmp1 * 5) >> 16; /* 2^16 / 5 = 0.4 in Q15 */
+ /* Q15 -> Q0 */
+ qtmp1 = qtmp2 - kHistEdgesQ15[ind]; /* Q15 - Q15 = Q15 */
+ qtmp2 = kCdfSlopeQ0[ind] * qtmp1; /* Q0 * Q15 = Q15 */
+ qtmp3 = qtmp2>>15; /* Q15 -> Q0 */
+
+ tmpUW32 = kCdfQ16[ind] + qtmp3; /* Q0 + Q0 = Q0 */
+ return tmpUW32;
+}
+
+
+
+int WebRtcIsac_EncLogisticMulti2(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ int16_t *dataQ7, /* input: data vector */
+ const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */
+ const int N, /* input: data vector length / 2 */
+ const int16_t isSWB12kHz)
+{
+ uint32_t W_lower, W_upper;
+ uint32_t W_upper_LSB, W_upper_MSB;
+ uint8_t *stream_ptr;
+ uint8_t *maxStreamPtr;
+ uint8_t *stream_ptr_carry;
+ uint32_t cdf_lo, cdf_hi;
+ int k;
+
+ /* point to beginning of stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+
+ maxStreamPtr = streamdata->stream + STREAM_SIZE_MAX_60 - 1;
+ for (k = 0; k < N; k++)
+ {
+ /* compute cdf_lower and cdf_upper by evaluating the piecewise linear cdf */
+ cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+ cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+
+ /* test and clip if probability gets too small */
+ while (cdf_lo+1 >= cdf_hi) {
+ /* clip */
+ if (*dataQ7 > 0) {
+ *dataQ7 -= 128;
+ cdf_hi = cdf_lo;
+ cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+ } else {
+ *dataQ7 += 128;
+ cdf_lo = cdf_hi;
+ cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+ }
+ }
+
+ dataQ7++;
+ // increment only once per 4 iterations for SWB-16kHz or WB
+ // increment only once per 2 iterations for SWB-12kHz
+ envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = W_upper_MSB * cdf_lo;
+ W_lower += (W_upper_LSB * cdf_lo) >> 16;
+ W_upper = W_upper_MSB * cdf_hi;
+ W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamdata->streamval += W_lower;
+
+ /* handle carry */
+ if (streamdata->streamval < W_lower)
+ {
+ /* propagate carry */
+ stream_ptr_carry = stream_ptr;
+ while (!(++(*--stream_ptr_carry)));
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ W_upper <<= 8;
+ *stream_ptr++ = (uint8_t) (streamdata->streamval >> 24);
+
+ if(stream_ptr > maxStreamPtr)
+ {
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+ }
+ streamdata->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+
+ return 0;
+}
+
+
+
+int WebRtcIsac_DecLogisticMulti2(
+ int16_t *dataQ7, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const uint16_t *envQ8, /* input: side info vector defining the width of the pdf */
+ const int16_t *ditherQ7,/* input: dither vector */
+ const int N, /* input: data vector length */
+ const int16_t isSWB12kHz)
+{
+ uint32_t W_lower, W_upper;
+ uint32_t W_tmp;
+ uint32_t W_upper_LSB, W_upper_MSB;
+ uint32_t streamval;
+ const uint8_t *stream_ptr;
+ uint32_t cdf_tmp;
+ int16_t candQ7;
+ int k;
+
+ // Position just past the end of the stream. STREAM_SIZE_MAX_60 instead of
+ // STREAM_SIZE_MAX (which is the size of the allocated buffer) because that's
+ // the limit to how much data is filled in.
+ const uint8_t* const stream_end = streamdata->stream + STREAM_SIZE_MAX_60;
+
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ if (stream_ptr + 3 >= stream_end)
+ return -1; // Would read out of bounds. Malformed input?
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+
+ for (k = 0; k < N; k++)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* find first candidate by inverting the logistic cdf */
+ candQ7 = - *ditherQ7 + 64;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ while (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+ /* error check */
+ if (W_lower == W_tmp) return -1;
+ }
+ W_upper = W_tmp;
+
+ /* another sample decoded */
+ *dataQ7 = candQ7 - 64;
+ }
+ else
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ while ( !(streamval > W_tmp) )
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+ /* error check */
+ if (W_upper == W_tmp) return -1;
+ }
+ W_lower = W_tmp;
+
+ /* another sample decoded */
+ *dataQ7 = candQ7 + 64;
+ }
+ ditherQ7++;
+ dataQ7++;
+ // increment only once per 4 iterations for SWB-16kHz or WB
+ // increment only once per 2 iterations for SWB-12kHz
+ envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ if (stream_ptr + 1 >= stream_end)
+ return -1; // Would read out of bounds. Malformed input?
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc
new file mode 100644
index 0000000000..b671002e1e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_decoder_isac.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
+
+#include "modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioDecoderIsacT<IsacFloat>;
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
new file mode 100644
index 0000000000..b7f2c0b1af
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+
+#include "modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
+
+namespace webrtc {
+
+// Explicit instantiation:
+template class AudioEncoderIsacT<IsacFloat>;
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc
new file mode 100644
index 0000000000..07bab055e1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+
+#include <limits>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+void TestBadConfig(const AudioEncoderIsacFloatImpl::Config& config) {
+ EXPECT_FALSE(config.IsOk());
+}
+
+void TestGoodConfig(const AudioEncoderIsacFloatImpl::Config& config) {
+ EXPECT_TRUE(config.IsOk());
+ AudioEncoderIsacFloatImpl aei(config);
+}
+
+// Wrap subroutine calls that test things in this, so that the error messages
+// will be accompanied by stack traces that make it possible to tell which
+// subroutine invocation caused the failure.
+#define S(x) \
+ do { \
+ SCOPED_TRACE(#x); \
+ x; \
+ } while (0)
+
+} // namespace
+
+TEST(AudioEncoderIsacTest, TestConfigBitrate) {
+ AudioEncoderIsacFloatImpl::Config config;
+
+ // The default value is some real, positive value.
+ EXPECT_GT(config.bit_rate, 1);
+ S(TestGoodConfig(config));
+
+ // 0 is another way to ask for the default value.
+ config.bit_rate = 0;
+ S(TestGoodConfig(config));
+
+ // Try some unreasonable values and watch them fail.
+ config.bit_rate = -1;
+ S(TestBadConfig(config));
+ config.bit_rate = 1;
+ S(TestBadConfig(config));
+ config.bit_rate = std::numeric_limits<int>::max();
+ S(TestBadConfig(config));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c
new file mode 100644
index 0000000000..486cd95914
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c
@@ -0,0 +1,1013 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * BwEstimator.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "rtc_base/checks.h"
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const float kQRateTableWb[12] =
+{
+ 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+ 18859.8f, 20963.3f, 23301.4f, 25900.3f, 28789.0f, 32000.0f};
+
+
+static const float kQRateTableSwb[24] =
+{
+ 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+ 18859.8f, 20963.3f, 23153.1f, 25342.9f, 27532.7f, 29722.5f,
+ 31912.3f, 34102.1f, 36291.9f, 38481.7f, 40671.4f, 42861.2f,
+ 45051.0f, 47240.8f, 49430.6f, 51620.4f, 53810.2f, 56000.0f,
+};
+
+
+
+
+int32_t WebRtcIsac_InitBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate)
+{
+ switch(encoderSampRate)
+ {
+ case kIsacWideband:
+ {
+ bwest_str->send_bw_avg = INIT_BN_EST_WB;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ bwest_str->send_bw_avg = INIT_BN_EST_SWB;
+ break;
+ }
+ }
+
+ switch(decoderSampRate)
+ {
+ case kIsacWideband:
+ {
+ bwest_str->prev_frame_length = INIT_FRAME_LEN_WB;
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+ bwest_str->rec_bw = (int32_t)INIT_BN_EST_WB;
+ bwest_str->rec_bw_avg_Q = INIT_BN_EST_WB;
+ bwest_str->rec_bw_avg = INIT_BN_EST_WB + INIT_HDR_RATE_WB;
+ bwest_str->rec_header_rate = INIT_HDR_RATE_WB;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ bwest_str->prev_frame_length = INIT_FRAME_LEN_SWB;
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_SWB + INIT_HDR_RATE_SWB);
+ bwest_str->rec_bw = (int32_t)INIT_BN_EST_SWB;
+ bwest_str->rec_bw_avg_Q = INIT_BN_EST_SWB;
+ bwest_str->rec_bw_avg = INIT_BN_EST_SWB + INIT_HDR_RATE_SWB;
+ bwest_str->rec_header_rate = INIT_HDR_RATE_SWB;
+ break;
+ }
+ }
+
+ bwest_str->prev_rec_rtp_number = 0;
+ bwest_str->prev_rec_arr_ts = 0;
+ bwest_str->prev_rec_send_ts = 0;
+ bwest_str->prev_rec_rtp_rate = 1.0f;
+ bwest_str->last_update_ts = 0;
+ bwest_str->last_reduction_ts = 0;
+ bwest_str->count_tot_updates_rec = -9;
+ bwest_str->rec_jitter = 10.0f;
+ bwest_str->rec_jitter_short_term = 0.0f;
+ bwest_str->rec_jitter_short_term_abs = 5.0f;
+ bwest_str->rec_max_delay = 10.0f;
+ bwest_str->rec_max_delay_avg_Q = 10.0f;
+ bwest_str->num_pkts_rec = 0;
+
+ bwest_str->send_max_delay_avg = 10.0f;
+
+ bwest_str->hsn_detect_rec = 0;
+
+ bwest_str->num_consec_rec_pkts_over_30k = 0;
+
+ bwest_str->hsn_detect_snd = 0;
+
+ bwest_str->num_consec_snt_pkts_over_30k = 0;
+
+ bwest_str->in_wait_period = 0;
+
+ bwest_str->change_to_WB = 0;
+
+ bwest_str->numConsecLatePkts = 0;
+ bwest_str->consecLatency = 0;
+ bwest_str->inWaitLatePkts = 0;
+ bwest_str->senderTimestamp = 0;
+ bwest_str->receiverTimestamp = 0;
+
+ bwest_str->external_bw_info.in_use = 0;
+
+ return 0;
+}
+
+/* This function updates both bottle neck rates */
+/* Parameters: */
+/* rtp_number - value from RTP packet, from NetEq */
+/* frame length - length of signal frame in ms, from iSAC decoder */
+/* send_ts - value in RTP header giving send time in samples */
+/* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
+/* pksize - size of packet in bytes, from NetEq */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+int16_t WebRtcIsac_UpdateBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ const uint16_t rtp_number,
+ const int32_t frame_length,
+ const uint32_t send_ts,
+ const uint32_t arr_ts,
+ const size_t pksize
+ /*, const uint16_t Index*/)
+{
+ float weight = 0.0f;
+ float curr_bw_inv = 0.0f;
+ float rec_rtp_rate;
+ float t_diff_proj;
+ float arr_ts_diff;
+ float send_ts_diff;
+ float arr_time_noise;
+ float arr_time_noise_abs;
+
+ float delay_correction_factor = 1;
+ float late_diff = 0.0f;
+ int immediate_set = 0;
+ int num_pkts_expected;
+
+ RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+ // We have to adjust the header-rate if the first packet has a
+ // frame-size different than the initialized value.
+ if ( frame_length != bwest_str->prev_frame_length )
+ {
+ bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+ 1000.0f / (float)frame_length; /* bits/s */
+ }
+
+ /* UPDATE ESTIMATES ON THIS SIDE */
+ /* compute far-side transmission rate */
+ rec_rtp_rate = ((float)pksize * 8.0f * 1000.0f / (float)frame_length) +
+ bwest_str->rec_header_rate;
+ // rec_rtp_rate packet bits/s + header bits/s
+
+ /* check for timer wrap-around */
+ if (arr_ts < bwest_str->prev_rec_arr_ts)
+ {
+ bwest_str->prev_rec_arr_ts = arr_ts;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->num_pkts_rec = 0;
+
+ /* store frame length */
+ bwest_str->prev_frame_length = frame_length;
+
+ /* store far-side transmission rate */
+ bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+ /* store far-side RTP time stamp */
+ bwest_str->prev_rec_rtp_number = rtp_number;
+
+ return 0;
+ }
+
+ bwest_str->num_pkts_rec++;
+
+ /* check that it's not one of the first 9 packets */
+ if ( bwest_str->count_tot_updates_rec > 0 )
+ {
+ if(bwest_str->in_wait_period > 0 )
+ {
+ bwest_str->in_wait_period--;
+ }
+
+ bwest_str->inWaitLatePkts -= ((bwest_str->inWaitLatePkts > 0)? 1:0);
+ send_ts_diff = (float)(send_ts - bwest_str->prev_rec_send_ts);
+
+ if (send_ts_diff <= (16 * frame_length)*2)
+ //doesn't allow for a dropped packet, not sure necessary to be
+ // that strict -DH
+ {
+ /* if not been updated for a long time, reduce the BN estimate */
+ if((uint32_t)(arr_ts - bwest_str->last_update_ts) *
+ 1000.0f / FS > 3000)
+ {
+ //how many frames should have been received since the last
+ // update if too many have been dropped or there have been
+ // big delays won't allow this reduction may no longer need
+ // the send_ts_diff here
+ num_pkts_expected = (int)(((float)(arr_ts -
+ bwest_str->last_update_ts) * 1000.0f /(float) FS) /
+ (float)frame_length);
+
+ if(((float)bwest_str->num_pkts_rec/(float)num_pkts_expected) >
+ 0.9)
+ {
+ float inv_bitrate = (float) pow( 0.99995,
+ (double)((uint32_t)(arr_ts -
+ bwest_str->last_reduction_ts)*1000.0f/FS) );
+
+ if ( inv_bitrate )
+ {
+ bwest_str->rec_bw_inv /= inv_bitrate;
+
+ //precautionary, likely never necessary
+ if (bwest_str->hsn_detect_snd &&
+ bwest_str->hsn_detect_rec)
+ {
+ if (bwest_str->rec_bw_inv > 0.000066f)
+ {
+ bwest_str->rec_bw_inv = 0.000066f;
+ }
+ }
+ }
+ else
+ {
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+ }
+ /* reset time-since-update counter */
+ bwest_str->last_reduction_ts = arr_ts;
+ }
+ else
+ //reset here?
+ {
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->num_pkts_rec = 0;
+ }
+ }
+ }
+ else
+ {
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->num_pkts_rec = 0;
+ }
+
+
+ /* temporarily speed up adaptation if frame length has changed */
+ if ( frame_length != bwest_str->prev_frame_length )
+ {
+ bwest_str->count_tot_updates_rec = 10;
+ bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+ 1000.0f / (float)frame_length; /* bits/s */
+
+ bwest_str->rec_bw_inv = 1.0f /((float)bwest_str->rec_bw +
+ bwest_str->rec_header_rate);
+ }
+
+ ////////////////////////
+ arr_ts_diff = (float)(arr_ts - bwest_str->prev_rec_arr_ts);
+
+ if (send_ts_diff > 0 )
+ {
+ late_diff = arr_ts_diff - send_ts_diff;
+ }
+ else
+ {
+ late_diff = arr_ts_diff - (float)(16 * frame_length);
+ }
+
+ if((late_diff > 0) && !bwest_str->inWaitLatePkts)
+ {
+ bwest_str->numConsecLatePkts++;
+ bwest_str->consecLatency += late_diff;
+ }
+ else
+ {
+ bwest_str->numConsecLatePkts = 0;
+ bwest_str->consecLatency = 0;
+ }
+ if(bwest_str->numConsecLatePkts > 50)
+ {
+ float latencyMs = bwest_str->consecLatency/(FS/1000);
+ float averageLatencyMs = latencyMs / bwest_str->numConsecLatePkts;
+ delay_correction_factor = frame_length / (frame_length + averageLatencyMs);
+ immediate_set = 1;
+ bwest_str->inWaitLatePkts = (int16_t)((bwest_str->consecLatency/(FS/1000)) / 30);// + 150;
+ bwest_str->start_wait_period = arr_ts;
+ }
+ ///////////////////////////////////////////////
+
+
+
+ /* update only if previous packet was not lost */
+ if ( rtp_number == bwest_str->prev_rec_rtp_number + 1 )
+ {
+
+
+ if (!(bwest_str->hsn_detect_snd && bwest_str->hsn_detect_rec))
+ {
+ if ((arr_ts_diff > (float)(16 * frame_length)))
+ {
+ //1/2 second
+ if ((late_diff > 8000.0f) && !bwest_str->in_wait_period)
+ {
+ delay_correction_factor = 0.7f;
+ bwest_str->in_wait_period = 55;
+ bwest_str->start_wait_period = arr_ts;
+ immediate_set = 1;
+ }
+ //320 ms
+ else if (late_diff > 5120.0f && !bwest_str->in_wait_period)
+ {
+ delay_correction_factor = 0.8f;
+ immediate_set = 1;
+ bwest_str->in_wait_period = 44;
+ bwest_str->start_wait_period = arr_ts;
+ }
+ }
+ }
+
+
+ if ((bwest_str->prev_rec_rtp_rate > bwest_str->rec_bw_avg) &&
+ (rec_rtp_rate > bwest_str->rec_bw_avg) &&
+ !bwest_str->in_wait_period)
+ {
+ /* test if still in initiation period and increment counter */
+ if (bwest_str->count_tot_updates_rec++ > 99)
+ {
+ /* constant weight after initiation part */
+ weight = 0.01f;
+ }
+ else
+ {
+ /* weight decreases with number of updates */
+ weight = 1.0f / (float) bwest_str->count_tot_updates_rec;
+ }
+ /* Bottle Neck Estimation */
+
+ /* limit outliers */
+ /* if more than 25 ms too much */
+ if (arr_ts_diff > frame_length * FS/1000 + 400.0f)
+ {
+ // in samples, why 25ms??
+ arr_ts_diff = frame_length * FS/1000 + 400.0f;
+ }
+ if(arr_ts_diff < (frame_length * FS/1000) - 160.0f)
+ {
+ /* don't allow it to be less than frame rate - 10 ms */
+ arr_ts_diff = (float)frame_length * FS/1000 - 160.0f;
+ }
+
+ /* compute inverse receiving rate for last packet */
+ curr_bw_inv = arr_ts_diff / ((float)(pksize + HEADER_SIZE) *
+ 8.0f * FS); // (180+35)*8*16000 = 27.5 Mbit....
+
+
+ if(curr_bw_inv <
+ (1.0f / (MAX_ISAC_BW + bwest_str->rec_header_rate)))
+ {
+ // don't allow inv rate to be larger than MAX
+ curr_bw_inv = (1.0f /
+ (MAX_ISAC_BW + bwest_str->rec_header_rate));
+ }
+
+ /* update bottle neck rate estimate */
+ bwest_str->rec_bw_inv = weight * curr_bw_inv +
+ (1.0f - weight) * bwest_str->rec_bw_inv;
+
+ /* reset time-since-update counter */
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3 * FS;
+ bwest_str->num_pkts_rec = 0;
+
+ /* Jitter Estimation */
+ /* projected difference between arrival times */
+ t_diff_proj = ((float)(pksize + HEADER_SIZE) * 8.0f *
+ 1000.0f) / bwest_str->rec_bw_avg;
+
+
+ // difference between projected and actual
+ // arrival time differences
+ arr_time_noise = (float)(arr_ts_diff*1000.0f/FS) -
+ t_diff_proj;
+ arr_time_noise_abs = (float) fabs( arr_time_noise );
+
+ /* long term averaged absolute jitter */
+ bwest_str->rec_jitter = weight * arr_time_noise_abs +
+ (1.0f - weight) * bwest_str->rec_jitter;
+ if (bwest_str->rec_jitter > 10.0f)
+ {
+ bwest_str->rec_jitter = 10.0f;
+ }
+ /* short term averaged absolute jitter */
+ bwest_str->rec_jitter_short_term_abs = 0.05f *
+ arr_time_noise_abs + 0.95f *
+ bwest_str->rec_jitter_short_term_abs;
+
+ /* short term averaged jitter */
+ bwest_str->rec_jitter_short_term = 0.05f * arr_time_noise +
+ 0.95f * bwest_str->rec_jitter_short_term;
+ }
+ }
+ }
+ else
+ {
+ // reset time-since-update counter when
+ // receiving the first 9 packets
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->num_pkts_rec = 0;
+
+ bwest_str->count_tot_updates_rec++;
+ }
+
+ /* limit minimum bottle neck rate */
+ if (bwest_str->rec_bw_inv > 1.0f / ((float)MIN_ISAC_BW +
+ bwest_str->rec_header_rate))
+ {
+ bwest_str->rec_bw_inv = 1.0f / ((float)MIN_ISAC_BW +
+ bwest_str->rec_header_rate);
+ }
+
+ // limit maximum bitrate
+ if (bwest_str->rec_bw_inv < 1.0f / ((float)MAX_ISAC_BW +
+ bwest_str->rec_header_rate))
+ {
+ bwest_str->rec_bw_inv = 1.0f / ((float)MAX_ISAC_BW +
+ bwest_str->rec_header_rate);
+ }
+
+ /* store frame length */
+ bwest_str->prev_frame_length = frame_length;
+
+ /* store far-side transmission rate */
+ bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+ /* store far-side RTP time stamp */
+ bwest_str->prev_rec_rtp_number = rtp_number;
+
+ // Replace bwest_str->rec_max_delay by the new
+ // value (atomic operation)
+ bwest_str->rec_max_delay = 3.0f * bwest_str->rec_jitter;
+
+ /* store send and arrival time stamp */
+ bwest_str->prev_rec_arr_ts = arr_ts ;
+ bwest_str->prev_rec_send_ts = send_ts;
+
+ /* Replace bwest_str->rec_bw by the new value (atomic operation) */
+ bwest_str->rec_bw = (int32_t)(1.0f / bwest_str->rec_bw_inv -
+ bwest_str->rec_header_rate);
+
+ if (immediate_set)
+ {
+ bwest_str->rec_bw = (int32_t) (delay_correction_factor *
+ (float) bwest_str->rec_bw);
+
+ if (bwest_str->rec_bw < (int32_t) MIN_ISAC_BW)
+ {
+ bwest_str->rec_bw = (int32_t) MIN_ISAC_BW;
+ }
+
+ bwest_str->rec_bw_avg = bwest_str->rec_bw +
+ bwest_str->rec_header_rate;
+
+ bwest_str->rec_bw_avg_Q = (float) bwest_str->rec_bw;
+
+ bwest_str->rec_jitter_short_term = 0.0f;
+
+ bwest_str->rec_bw_inv = 1.0f / (bwest_str->rec_bw +
+ bwest_str->rec_header_rate);
+
+ bwest_str->count_tot_updates_rec = 1;
+
+ immediate_set = 0;
+ bwest_str->consecLatency = 0;
+ bwest_str->numConsecLatePkts = 0;
+ }
+
+ return 0;
+}
+
+
+/* This function updates the send bottle neck rate */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+int16_t WebRtcIsac_UpdateUplinkBwImpl(
+ BwEstimatorstr* bwest_str,
+ int16_t index,
+ enum IsacSamplingRate encoderSamplingFreq)
+{
+ RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+ if((index < 0) || (index > 23))
+ {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+ if(encoderSamplingFreq == kIsacWideband)
+ {
+ if(index > 11)
+ {
+ index -= 12;
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MAX_ISAC_MD;
+ }
+ else
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MIN_ISAC_MD;
+ }
+
+ /* compute the BN estimate as decoded on the other side */
+ bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+ 0.1f * kQRateTableWb[index];
+ }
+ else
+ {
+ /* compute the BN estimate as decoded on the other side */
+ bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+ 0.1f * kQRateTableSwb[index];
+ }
+
+ if (bwest_str->send_bw_avg > (float) 28000 && !bwest_str->hsn_detect_snd)
+ {
+ bwest_str->num_consec_snt_pkts_over_30k++;
+
+ if (bwest_str->num_consec_snt_pkts_over_30k >= 66)
+ {
+ //approx 2 seconds with 30ms frames
+ bwest_str->hsn_detect_snd = 1;
+ }
+ }
+ else if (!bwest_str->hsn_detect_snd)
+ {
+ bwest_str->num_consec_snt_pkts_over_30k = 0;
+ }
+ return 0;
+}
+
+// called when there is upper-band bit-stream to update jitter
+// statistics.
+int16_t WebRtcIsac_UpdateUplinkJitter(
+ BwEstimatorstr* bwest_str,
+ int32_t index)
+{
+ RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+ if((index < 0) || (index > 23))
+ {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ if(index > 0)
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MAX_ISAC_MD;
+ }
+ else
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MIN_ISAC_MD;
+ }
+
+ return 0;
+}
+
+
+
+// Returns the bandwidth/jitter estimation code (integer 0...23)
+// to put in the sending iSAC payload
+void
+WebRtcIsac_GetDownlinkBwJitIndexImpl(
+ BwEstimatorstr* bwest_str,
+ int16_t* bottleneckIndex,
+ int16_t* jitterInfo,
+ enum IsacSamplingRate decoderSamplingFreq)
+{
+ float MaxDelay;
+ //uint16_t MaxDelayBit;
+
+ float rate;
+ float r;
+ float e1, e2;
+ const float weight = 0.1f;
+ const float* ptrQuantizationTable;
+ int16_t addJitterInfo;
+ int16_t minInd;
+ int16_t maxInd;
+ int16_t midInd;
+
+ if (bwest_str->external_bw_info.in_use) {
+ *bottleneckIndex = bwest_str->external_bw_info.bottleneck_idx;
+ *jitterInfo = bwest_str->external_bw_info.jitter_info;
+ return;
+ }
+
+ /* Get Max Delay Bit */
+ /* get unquantized max delay */
+ MaxDelay = (float)WebRtcIsac_GetDownlinkMaxDelay(bwest_str);
+
+ if ( ((1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ MAX_ISAC_MD - MaxDelay) > (MaxDelay - (1.f-weight) *
+ bwest_str->rec_max_delay_avg_Q - weight * MIN_ISAC_MD) )
+ {
+ jitterInfo[0] = 0;
+ /* update quantized average */
+ bwest_str->rec_max_delay_avg_Q =
+ (1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ (float)MIN_ISAC_MD;
+ }
+ else
+ {
+ jitterInfo[0] = 1;
+ /* update quantized average */
+ bwest_str->rec_max_delay_avg_Q =
+ (1.f-weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ (float)MAX_ISAC_MD;
+ }
+
+ // Get unquantized rate.
+ rate = (float)WebRtcIsac_GetDownlinkBandwidth(bwest_str);
+
+ /* Get Rate Index */
+ if(decoderSamplingFreq == kIsacWideband)
+ {
+ ptrQuantizationTable = kQRateTableWb;
+ addJitterInfo = 1;
+ maxInd = 11;
+ }
+ else
+ {
+ ptrQuantizationTable = kQRateTableSwb;
+ addJitterInfo = 0;
+ maxInd = 23;
+ }
+
+ minInd = 0;
+ while(maxInd > minInd + 1)
+ {
+ midInd = (maxInd + minInd) >> 1;
+ if(rate > ptrQuantizationTable[midInd])
+ {
+ minInd = midInd;
+ }
+ else
+ {
+ maxInd = midInd;
+ }
+ }
+ // Chose the index which gives results an average which is closest
+ // to rate
+ r = (1 - weight) * bwest_str->rec_bw_avg_Q - rate;
+ e1 = weight * ptrQuantizationTable[minInd] + r;
+ e2 = weight * ptrQuantizationTable[maxInd] + r;
+ e1 = (e1 > 0)? e1:-e1;
+ e2 = (e2 > 0)? e2:-e2;
+ if(e1 < e2)
+ {
+ bottleneckIndex[0] = minInd;
+ }
+ else
+ {
+ bottleneckIndex[0] = maxInd;
+ }
+
+ bwest_str->rec_bw_avg_Q = (1 - weight) * bwest_str->rec_bw_avg_Q +
+ weight * ptrQuantizationTable[bottleneckIndex[0]];
+ bottleneckIndex[0] += jitterInfo[0] * 12 * addJitterInfo;
+
+ bwest_str->rec_bw_avg = (1 - weight) * bwest_str->rec_bw_avg + weight *
+ (rate + bwest_str->rec_header_rate);
+}
+
+
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+int32_t WebRtcIsac_GetDownlinkBandwidth( const BwEstimatorstr *bwest_str)
+{
+ int32_t rec_bw;
+ float jitter_sign;
+ float bw_adjust;
+
+ RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+ /* create a value between -1.0 and 1.0 indicating "average sign" of jitter */
+ jitter_sign = bwest_str->rec_jitter_short_term /
+ bwest_str->rec_jitter_short_term_abs;
+
+ /* adjust bw proportionally to negative average jitter sign */
+ bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+
+ /* adjust Rate if jitter sign is mostly constant */
+ rec_bw = (int32_t)(bwest_str->rec_bw * bw_adjust);
+
+ /* limit range of bottle neck rate */
+ if (rec_bw < MIN_ISAC_BW)
+ {
+ rec_bw = MIN_ISAC_BW;
+ }
+ else if (rec_bw > MAX_ISAC_BW)
+ {
+ rec_bw = MAX_ISAC_BW;
+ }
+ return rec_bw;
+}
+
+/* Returns the max delay (in ms) */
+int32_t
+WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str)
+{
+ int32_t rec_max_delay;
+
+ RTC_DCHECK(!bwest_str->external_bw_info.in_use);
+
+ rec_max_delay = (int32_t)(bwest_str->rec_max_delay);
+
+ /* limit range of jitter estimate */
+ if (rec_max_delay < MIN_ISAC_MD)
+ {
+ rec_max_delay = MIN_ISAC_MD;
+ }
+ else if (rec_max_delay > MAX_ISAC_MD)
+ {
+ rec_max_delay = MAX_ISAC_MD;
+ }
+ return rec_max_delay;
+}
+
+/* Clamp val to the closed interval [min,max]. */
+static int32_t clamp(int32_t val, int32_t min, int32_t max) {
+ RTC_DCHECK_LE(min, max);
+ return val < min ? min : (val > max ? max : val);
+}
+
+int32_t WebRtcIsac_GetUplinkBandwidth(const BwEstimatorstr* bwest_str) {
+ return bwest_str->external_bw_info.in_use
+ ? bwest_str->external_bw_info.send_bw_avg
+ : clamp(bwest_str->send_bw_avg, MIN_ISAC_BW, MAX_ISAC_BW);
+}
+
+int32_t WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str) {
+ return bwest_str->external_bw_info.in_use
+ ? bwest_str->external_bw_info.send_max_delay_avg
+ : clamp(bwest_str->send_max_delay_avg, MIN_ISAC_MD, MAX_ISAC_MD);
+}
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ * returns minimum payload size (bytes)
+ */
+int WebRtcIsac_GetMinBytes(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+ enum ISACBandwidth bandwidth
+ /*,int16_t frequentLargePackets*/)
+{
+ double MinRate = 0.0;
+ int MinBytes;
+ double TransmissionTime;
+ int burstInterval = BURST_INTERVAL;
+
+ // first 10 packets @ low rate, then INIT_BURST_LEN packets @
+ // fixed rate of INIT_RATE bps
+ if (State->InitCounter > 0)
+ {
+ if (State->InitCounter-- <= INIT_BURST_LEN)
+ {
+ if(bandwidth == isac8kHz)
+ {
+ MinRate = INIT_RATE_WB;
+ }
+ else
+ {
+ MinRate = INIT_RATE_SWB;
+ }
+ }
+ else
+ {
+ MinRate = 0;
+ }
+ }
+ else
+ {
+ /* handle burst */
+ if (State->BurstCounter)
+ {
+ if (State->StillBuffered < (1.0 - 1.0/BURST_LEN) * DelayBuildUp)
+ {
+ /* max bps derived from BottleNeck and DelayBuildUp values */
+ MinRate = (1.0 + (FS/1000) * DelayBuildUp /
+ (double)(BURST_LEN * FrameSamples)) * BottleNeck;
+ }
+ else
+ {
+ // max bps derived from StillBuffered and DelayBuildUp
+ // values
+ MinRate = (1.0 + (FS/1000) * (DelayBuildUp -
+ State->StillBuffered) / (double)FrameSamples) * BottleNeck;
+ if (MinRate < 1.04 * BottleNeck)
+ {
+ MinRate = 1.04 * BottleNeck;
+ }
+ }
+ State->BurstCounter--;
+ }
+ }
+
+
+ /* convert rate from bits/second to bytes/packet */
+ MinBytes = (int) (MinRate * FrameSamples / (8.0 * FS));
+
+ /* StreamSize will be adjusted if less than MinBytes */
+ if (StreamSize < MinBytes)
+ {
+ StreamSize = MinBytes;
+ }
+
+ /* keep track of when bottle neck was last exceeded by at least 1% */
+ if (StreamSize * 8.0 * FS / FrameSamples > 1.01 * BottleNeck) {
+ if (State->PrevExceed) {
+ /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+ State->ExceedAgo -= /*BURST_INTERVAL*/ burstInterval / (BURST_LEN - 1);
+ if (State->ExceedAgo < 0)
+ State->ExceedAgo = 0;
+ }
+ else
+ {
+ State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+ State->PrevExceed = 1;
+ }
+ }
+ else
+ {
+ State->PrevExceed = 0;
+ State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+ }
+
+ /* set burst flag if bottle neck not exceeded for long time */
+ if ((State->ExceedAgo > burstInterval) &&
+ (State->BurstCounter == 0))
+ {
+ if (State->PrevExceed)
+ {
+ State->BurstCounter = BURST_LEN - 1;
+ }
+ else
+ {
+ State->BurstCounter = BURST_LEN;
+ }
+ }
+
+
+ /* Update buffer delay */
+ TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (FrameSamples * 1000) / FS; /* ms */
+ if (State->StillBuffered < 0.0)
+ {
+ State->StillBuffered = 0.0;
+ }
+
+ return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsac_UpdateRateModel(
+ RateModel *State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck) /* bottle neck rate; excl headers (bps) */
+{
+ double TransmissionTime;
+
+ /* avoid the initial "high-rate" burst */
+ State->InitCounter = 0;
+
+ /* Update buffer delay */
+ TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (FrameSamples * 1000) / FS; /* ms */
+ if (State->StillBuffered < 0.0)
+ State->StillBuffered = 0.0;
+
+}
+
+
+void WebRtcIsac_InitRateModel(
+ RateModel *State)
+{
+ State->PrevExceed = 0; /* boolean */
+ State->ExceedAgo = 0; /* ms */
+ State->BurstCounter = 0; /* packets */
+ State->InitCounter = INIT_BURST_LEN + 10; /* packets */
+ State->StillBuffered = 1.0; /* ms */
+}
+
+int WebRtcIsac_GetNewFrameLength(
+ double bottle_neck,
+ int current_framesamples)
+{
+ int new_framesamples;
+
+ const int Thld_20_30 = 20000;
+
+ //const int Thld_30_20 = 30000;
+ const int Thld_30_20 = 1000000; // disable 20 ms frames
+
+ const int Thld_30_60 = 18000;
+ //const int Thld_30_60 = 0; // disable 60 ms frames
+
+ const int Thld_60_30 = 27000;
+
+
+ new_framesamples = current_framesamples;
+
+ /* find new framelength */
+ switch(current_framesamples) {
+ case 320:
+ if (bottle_neck < Thld_20_30)
+ new_framesamples = 480;
+ break;
+ case 480:
+ if (bottle_neck < Thld_30_60)
+ new_framesamples = 960;
+ else if (bottle_neck > Thld_30_20)
+ new_framesamples = 320;
+ break;
+ case 960:
+ if (bottle_neck >= Thld_60_30)
+ new_framesamples = 480;
+ break;
+ }
+
+ return new_framesamples;
+}
+
+double WebRtcIsac_GetSnr(
+ double bottle_neck,
+ int framesamples)
+{
+ double s2nr;
+
+ const double a_20 = -30.0;
+ const double b_20 = 0.8;
+ const double c_20 = 0.0;
+
+ const double a_30 = -23.0;
+ const double b_30 = 0.48;
+ const double c_30 = 0.0;
+
+ const double a_60 = -23.0;
+ const double b_60 = 0.53;
+ const double c_60 = 0.0;
+
+
+ /* find new SNR value */
+ switch(framesamples) {
+ case 320:
+ s2nr = a_20 + b_20 * bottle_neck * 0.001 + c_20 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ case 480:
+ s2nr = a_30 + b_30 * bottle_neck * 0.001 + c_30 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ case 960:
+ s2nr = a_60 + b_60 * bottle_neck * 0.001 + c_60 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ default:
+ s2nr = 0;
+ }
+
+ return s2nr;
+
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h
new file mode 100644
index 0000000000..5f4550a3a5
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.h
+ *
+ * This header file contains the API for the Bandwidth Estimator
+ * designed for iSAC.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+#define MIN_ISAC_BW 10000
+#define MIN_ISAC_BW_LB 10000
+#define MIN_ISAC_BW_UB 25000
+
+#define MAX_ISAC_BW 56000
+#define MAX_ISAC_BW_UB 32000
+#define MAX_ISAC_BW_LB 32000
+
+#define MIN_ISAC_MD 5
+#define MAX_ISAC_MD 25
+
+// assumed header size, in bytes; we don't know the exact number
+// (header compression may be used)
+#define HEADER_SIZE 35
+
+// Initial Frame-Size, in ms, for Wideband & Super-Wideband Mode
+#define INIT_FRAME_LEN_WB 60
+#define INIT_FRAME_LEN_SWB 30
+
+// Initial Bottleneck Estimate, in bits/sec, for
+// Wideband & Super-wideband mode
+#define INIT_BN_EST_WB 20e3f
+#define INIT_BN_EST_SWB 56e3f
+
+// Initial Header rate (header rate depends on frame-size),
+// in bits/sec, for Wideband & Super-Wideband mode.
+#define INIT_HDR_RATE_WB \
+ ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_WB)
+#define INIT_HDR_RATE_SWB \
+ ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_SWB)
+
+// number of packets in a row for a high rate burst
+#define BURST_LEN 3
+
+// ms, max time between two full bursts
+#define BURST_INTERVAL 500
+
+// number of packets in a row for initial high rate burst
+#define INIT_BURST_LEN 5
+
+// bits/s, rate for the first BURST_LEN packets
+#define INIT_RATE_WB INIT_BN_EST_WB
+#define INIT_RATE_SWB INIT_BN_EST_SWB
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* This function initializes the struct */
+/* to be called before using the struct for anything else */
+/* returns 0 if everything went fine, -1 otherwise */
+int32_t WebRtcIsac_InitBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate);
+
+/* This function updates the receiving estimate */
+/* Parameters: */
+/* rtp_number - value from RTP packet, from NetEq */
+/* frame length - length of signal frame in ms, from iSAC decoder */
+/* send_ts - value in RTP header giving send time in samples */
+/* arr_ts - value given by timeGetTime() time of arrival in samples of
+ * packet from NetEq */
+/* pksize - size of packet in bytes, from NetEq */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as
+ * estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+int16_t WebRtcIsac_UpdateBandwidthEstimator(BwEstimatorstr* bwest_str,
+ uint16_t rtp_number,
+ int32_t frame_length,
+ uint32_t send_ts,
+ uint32_t arr_ts,
+ size_t pksize);
+
+/* Update receiving estimates. Used when we only receive BWE index, no iSAC data
+ * packet. */
+int16_t WebRtcIsac_UpdateUplinkBwImpl(
+ BwEstimatorstr* bwest_str,
+ int16_t Index,
+ enum IsacSamplingRate encoderSamplingFreq);
+
+/* Returns the bandwidth/jitter estimation code (integer 0...23) to put in the
+ * sending iSAC payload */
+void WebRtcIsac_GetDownlinkBwJitIndexImpl(
+ BwEstimatorstr* bwest_str,
+ int16_t* bottleneckIndex,
+ int16_t* jitterInfo,
+ enum IsacSamplingRate decoderSamplingFreq);
+
+/* Returns the bandwidth estimation (in bps) */
+int32_t WebRtcIsac_GetDownlinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay (in ms) */
+int32_t WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/* Returns the bandwidth that iSAC should send with in bps */
+int32_t WebRtcIsac_GetUplinkBandwidth(const BwEstimatorstr* bwest_str);
+
+/* Returns the max delay value from the other side in ms */
+int32_t WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr* bwest_str);
+
+/*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+int WebRtcIsac_GetMinBytes(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ int FrameLen, /* ms per frame */
+ double BottleNeck, /* bottle neck rate; excl headers (bps) */
+ double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+ enum ISACBandwidth bandwidth
+ /*,int16_t frequentLargePackets*/);
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsac_UpdateRateModel(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ int FrameSamples, /* samples per frame */
+ double BottleNeck); /* bottle neck rate; excl headers (bps) */
+
+void WebRtcIsac_InitRateModel(RateModel* State);
+
+/* Returns the new framelength value (input argument: bottle_neck) */
+int WebRtcIsac_GetNewFrameLength(double bottle_neck, int current_framelength);
+
+/* Returns the new SNR value (input argument: bottle_neck) */
+double WebRtcIsac_GetSnr(double bottle_neck, int new_framelength);
+
+int16_t WebRtcIsac_UpdateUplinkJitter(BwEstimatorstr* bwest_str, int32_t index);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_ \
+ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/codec.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/codec.h
new file mode 100644
index 0000000000..a7c7ddc14a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/codec.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * codec.h
+ *
+ * This header file contains the calls to the internal encoder
+ * and decoder functions.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/third_party/fft/fft.h"
+
+void WebRtcIsac_ResetBitstream(Bitstr* bit_stream);
+
+int WebRtcIsac_EstimateBandwidth(BwEstimatorstr* bwest_str,
+ Bitstr* streamdata,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate);
+
+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(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,
+ float scale);
+
+int WebRtcIsac_EncodeStoredDataUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ int32_t jitterInfo,
+ float scale,
+ enum ISACBandwidth bandwidth);
+
+int16_t WebRtcIsac_GetRedPayloadUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+ Bitstr* bitStreamObj,
+ enum ISACBandwidth bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ * - inRateBitPerSec : a total bit-rate in bits/sec.
+ *
+ * Output:
+ * - rateLBBitPerSec : a bit-rate allocated to the lower-band
+ * in bits/sec.
+ * - rateUBBitPerSec : a bit-rate allocated to the upper-band
+ * in bits/sec.
+ *
+ * Return value : 0 if rate allocation has been successful.
+ * -1 if failed to allocate rates.
+ */
+
+int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
+ double* rateLBBitPerSec,
+ double* rateUBBitPerSec,
+ enum ISACBandwidth* bandwidthKHz);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb16()
+ *
+ * Decode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band decoder object. The
+ * bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ * -signal_out : decoded audio, 480 samples 30 ms.
+ *
+ * Return value : >0 number of decoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables,
+ float* signal_out,
+ ISACUBDecStruct* ISACdec_obj,
+ int16_t isRCUPayload);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb12()
+ *
+ * Decode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band decoder object. The
+ * bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ * -signal_out : decoded audio, 480 samples 30 ms.
+ *
+ * Return value : >0 number of decoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables,
+ float* signal_out,
+ ISACUBDecStruct* ISACdec_obj,
+ int16_t isRCUPayload);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb16()
+ *
+ * Encode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input:
+ * -in : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band encoder object. The
+ * bit-stream is stored inside the encoder object.
+ *
+ * Return value : >0 number of encoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables,
+ float* in,
+ ISACUBEncStruct* ISACenc_obj,
+ int32_t jitterInfo);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb12()
+ *
+ * Encode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input:
+ * -in : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band encoder object. The
+ * bit-stream is stored inside the encoder object.
+ *
+ * Return value : >0 number of encoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables,
+ float* in,
+ ISACUBEncStruct* ISACenc_obj,
+ int32_t jitterInfo);
+
+/************************** initialization functions *************************/
+
+void WebRtcIsac_InitMasking(MaskFiltstr* maskdata);
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr* postfiltdata);
+
+/**************************** transform functions ****************************/
+
+void WebRtcIsac_InitTransform(TransformTables* tables);
+
+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);
+
+/***************************** filterbank functions **************************/
+
+void WebRtcIsac_FilterAndCombineFloat(float* InLP,
+ float* InHP,
+ float* Out,
+ PostFiltBankstr* postfiltdata);
+
+/************************* normalized lattice filters ************************/
+
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+ float* stateF,
+ float* stateG,
+ float* lat_in,
+ double* filtcoeflo,
+ double* lat_out);
+
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
+ float* stateF,
+ float* stateG,
+ double* lat_in,
+ double* lo_filt_coef,
+ float* lat_out);
+
+void WebRtcIsac_Dir2Lat(double* a, int orderCoef, float* sth, float* cth);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.c
new file mode 100644
index 0000000000..1bb0827031
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/crc.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+
+#define POLYNOMIAL 0x04c11db7L
+
+
+static const uint32_t kCrcTable[256] = {
+ 0, 0x4c11db7, 0x9823b6e, 0xd4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13, 0x54bf6a4,
+ 0x808d07d, 0xcc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+ 0x3f9b762c, 0x3b5a6b9b, 0x315d626, 0x7d4cb91, 0xa97ed48, 0xe56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+ 0x18197087, 0x1cd86d30, 0x29f3d35, 0x65e2082, 0xb1d065b, 0xfdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ * - bitstream : payload bitstream
+ * - len_bitstream_in_bytes : number of 8-bit words in the bit stream
+ *
+ * Output:
+ * - crc : checksum
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int WebRtcIsac_GetCrc(const int16_t* bitstream,
+ int len_bitstream_in_bytes,
+ uint32_t* crc)
+{
+ uint8_t* bitstream_ptr_uw8;
+ uint32_t crc_state;
+ int byte_cntr;
+ int crc_tbl_indx;
+
+ /* Sanity Check. */
+ if (bitstream == NULL) {
+ return -1;
+ }
+ /* cast to UWord8 pointer */
+ bitstream_ptr_uw8 = (uint8_t *)bitstream;
+
+ /* initialize */
+ crc_state = 0xFFFFFFFF;
+
+ for (byte_cntr = 0; byte_cntr < len_bitstream_in_bytes; byte_cntr++) {
+ crc_tbl_indx = (WEBRTC_SPL_RSHIFT_U32(crc_state, 24) ^
+ bitstream_ptr_uw8[byte_cntr]) & 0xFF;
+ crc_state = (crc_state << 8) ^ kCrcTable[crc_tbl_indx];
+ }
+
+ *crc = ~crc_state;
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.h
new file mode 100644
index 0000000000..f031019ed3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/crc.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * crc.h
+ *
+ * Checksum functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+
+#include <stdint.h>
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ * - encoded : payload bit stream
+ * - no_of_word8s : number of 8-bit words in the bit stream
+ *
+ * Output:
+ * - crc : checksum
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int WebRtcIsac_GetCrc(const int16_t* encoded, int no_of_word8s, uint32_t* crc);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode.c
new file mode 100644
index 0000000000..6e114e4a2b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_B.c
+ *
+ * This file contains definition of funtions for decoding.
+ * Decoding of lower-band, including normal-decoding and RCU decoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_filter.h"
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+int WebRtcIsac_DecodeLb(const TransformTables* transform_tables,
+ float* signal_out, ISACLBDecStruct* ISACdecLB_obj,
+ int16_t* current_framesamples,
+ int16_t isRCUPayload) {
+ int k;
+ int len, err;
+ int16_t bandwidthInd;
+
+ float LP_dec_float[FRAMESAMPLES_HALF];
+ float HP_dec_float[FRAMESAMPLES_HALF];
+
+ double LPw[FRAMESAMPLES_HALF];
+ double HPw[FRAMESAMPLES_HALF];
+ double LPw_pf[FRAMESAMPLES_HALF];
+
+ double lo_filt_coef[(ORDERLO + 1)*SUBFRAMES];
+ double hi_filt_coef[(ORDERHI + 1)*SUBFRAMES];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+
+ double PitchLags[4];
+ double PitchGains[4];
+ double AvgPitchGain;
+ int16_t PitchGains_Q12[4];
+ int16_t AvgPitchGain_Q12;
+
+ float gain;
+
+ int frame_nb; /* counter */
+ int frame_mode; /* 0 30ms, 1 for 60ms */
+ /* Processed_samples: 480 (30, 60 ms). Cannot take other values. */
+
+ WebRtcIsac_ResetBitstream(&(ISACdecLB_obj->bitstr_obj));
+
+ len = 0;
+
+ /* Decode framelength and BW estimation - not used,
+ only for stream pointer*/
+ err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj,
+ current_framesamples);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Frame_mode:
+ * 0: indicates 30 ms frame (480 samples)
+ * 1: indicates 60 ms frame (960 samples) */
+ frame_mode = *current_framesamples / MAX_FRAMESAMPLES;
+
+ err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
+ if (err < 0) {
+ return err;
+ }
+
+ /* One loop if it's one frame (20 or 30ms), 2 loops if 2 frames
+ bundled together (60ms). */
+ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+ /* Decode & de-quantize pitch parameters */
+ err = WebRtcIsac_DecodePitchGain(&ISACdecLB_obj->bitstr_obj,
+ PitchGains_Q12);
+ if (err < 0) {
+ return err;
+ }
+
+ err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj, PitchGains_Q12,
+ PitchLags);
+ if (err < 0) {
+ return err;
+ }
+
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+ /* Decode & de-quantize filter coefficients. */
+ err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj, lo_filt_coef,
+ hi_filt_coef);
+ if (err < 0) {
+ return err;
+ }
+ /* Decode & de-quantize spectrum. */
+ len = WebRtcIsac_DecodeSpec(&ISACdecLB_obj->bitstr_obj, AvgPitchGain_Q12,
+ kIsacLowerBand, real_f, imag_f);
+ if (len < 0) {
+ return len;
+ }
+
+ /* Inverse transform. */
+ WebRtcIsac_Spec2time(transform_tables, real_f, imag_f, LPw, HPw,
+ &ISACdecLB_obj->fftstr_obj);
+
+ /* Convert PitchGains back to float for pitchfilter_post */
+ for (k = 0; k < 4; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+ }
+ if (isRCUPayload) {
+ for (k = 0; k < 240; k++) {
+ LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+ HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+ }
+ }
+
+ /* Inverse pitch filter. */
+ WebRtcIsac_PitchfilterPost(LPw, LPw_pf, &ISACdecLB_obj->pitchfiltstr_obj,
+ PitchLags, PitchGains);
+ /* Convert AvgPitchGain back to float for computation of gain. */
+ AvgPitchGain = ((float)AvgPitchGain_Q12) / 4096;
+ gain = 1.0f - 0.45f * (float)AvgPitchGain;
+
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ /* Reduce gain to compensate for pitch enhancer. */
+ LPw_pf[k] *= gain;
+ }
+
+ if (isRCUPayload) {
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ /* Compensation for transcoding gain changes. */
+ LPw_pf[k] *= RCU_TRANSCODING_SCALE;
+ HPw[k] *= RCU_TRANSCODING_SCALE;
+ }
+ }
+ /* Perceptual post-filtering (using normalized lattice filter). */
+ WebRtcIsac_NormLatticeFilterAr(
+ ORDERLO, ISACdecLB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecLB_obj->maskfiltstr_obj).PostStateLoG, LPw_pf, lo_filt_coef,
+ LP_dec_float);
+ WebRtcIsac_NormLatticeFilterAr(
+ ORDERHI, ISACdecLB_obj->maskfiltstr_obj.PostStateHiF,
+ (ISACdecLB_obj->maskfiltstr_obj).PostStateHiG, HPw, hi_filt_coef,
+ HP_dec_float);
+
+ /* Recombine the 2 bands. */
+ WebRtcIsac_FilterAndCombineFloat(LP_dec_float, HP_dec_float,
+ signal_out + frame_nb * FRAMESAMPLES,
+ &ISACdecLB_obj->postfiltbankstr_obj);
+ }
+ return len;
+}
+
+
+/*
+ * This decode function is called when the codec is operating in 16 kHz
+ * bandwidth to decode the upperband, i.e. 8-16 kHz.
+ *
+ * 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(const TransformTables* transform_tables,
+ float* signal_out, ISACUBDecStruct* ISACdecUB_obj,
+ int16_t isRCUPayload) {
+ int len, err;
+
+ double halfFrameFirst[FRAMESAMPLES_HALF];
+ double halfFrameSecond[FRAMESAMPLES_HALF];
+
+ double percepFilterParam[(UB_LPC_ORDER + 1) * (SUBFRAMES << 1) +
+ (UB_LPC_ORDER + 1)];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+ const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
+ len = 0;
+
+ /* Decode & de-quantize filter coefficients. */
+ memset(percepFilterParam, 0, sizeof(percepFilterParam));
+ err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+ percepFilterParam, isac16kHz);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Decode & de-quantize spectrum. */
+ len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
+ kIsacUpperBand16, real_f, imag_f);
+ if (len < 0) {
+ return len;
+ }
+ if (isRCUPayload) {
+ int n;
+ for (n = 0; n < 240; n++) {
+ real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ }
+ }
+ /* Inverse transform. */
+ WebRtcIsac_Spec2time(transform_tables,
+ real_f, imag_f, halfFrameFirst, halfFrameSecond,
+ &ISACdecUB_obj->fftstr_obj);
+
+ /* Perceptual post-filtering (using normalized lattice filter). */
+ WebRtcIsac_NormLatticeFilterAr(
+ UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst,
+ &percepFilterParam[(UB_LPC_ORDER + 1)], signal_out);
+
+ WebRtcIsac_NormLatticeFilterAr(
+ UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond,
+ &percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER + 1)],
+ &signal_out[FRAMESAMPLES_HALF]);
+
+ return len;
+}
+
+/*
+ * This decode function is called when the codec operates at 0-12 kHz
+ * bandwidth to decode the upperband, i.e. 8-12 kHz.
+ *
+ * At the encoder the upper-band is split into two band, 8-12 kHz & 12-16
+ * kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is
+ * reconstructed and 12-16 kHz replaced with zeros. Then two bands
+ * are combined, to reconstruct the upperband 8-16 kHz.
+ */
+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];
+ float HP_dec_float[FRAMESAMPLES_HALF];
+
+ double LPw[FRAMESAMPLES_HALF];
+ double HPw[FRAMESAMPLES_HALF];
+
+ double percepFilterParam[(UB_LPC_ORDER + 1)*SUBFRAMES];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+ const int16_t kAveragePitchGain = 0; /* No pitch-gain for upper-band. */
+ len = 0;
+
+ /* Decode & dequantize filter coefficients. */
+ err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+ percepFilterParam, isac12kHz);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Decode & de-quantize spectrum. */
+ len = WebRtcIsac_DecodeSpec(&ISACdecUB_obj->bitstr_obj, kAveragePitchGain,
+ kIsacUpperBand12, real_f, imag_f);
+ if (len < 0) {
+ return len;
+ }
+
+ if (isRCUPayload) {
+ int n;
+ for (n = 0; n < 240; n++) {
+ real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ }
+ }
+ /* Inverse transform. */
+ 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,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG,
+ LPw, percepFilterParam, LP_dec_float);
+ /* Zero for 12-16 kHz. */
+ memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF));
+ /* Recombine the 2 bands. */
+ WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out,
+ &ISACdecUB_obj->postfiltbankstr_obj);
+ return len;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode_bwe.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode_bwe.c
new file mode 100644
index 0000000000..89d970fc75
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/decode_bwe.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+
+
+int
+WebRtcIsac_EstimateBandwidth(
+ BwEstimatorstr* bwest_str,
+ Bitstr* streamdata,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate)
+{
+ int16_t index;
+ int16_t frame_samples;
+ uint32_t sendTimestampIn16kHz;
+ uint32_t arrivalTimestampIn16kHz;
+ uint32_t diffSendTime;
+ uint32_t diffArrivalTime;
+ int err;
+
+ /* decode framelength and BW estimation */
+ err = WebRtcIsac_DecodeFrameLen(streamdata, &frame_samples);
+ if(err < 0) // error check
+ {
+ return err;
+ }
+ err = WebRtcIsac_DecodeSendBW(streamdata, &index);
+ if(err < 0) // error check
+ {
+ return err;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+ err = WebRtcIsac_UpdateUplinkBwImpl(bwest_str, index, encoderSampRate);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ // We like BWE to work at 16 kHz sampling rate,
+ // therefore, we have to change the timestamps accordingly.
+ // translate the send timestamp if required
+ diffSendTime = (uint32_t)((uint32_t)send_ts -
+ (uint32_t)bwest_str->senderTimestamp);
+ bwest_str->senderTimestamp = send_ts;
+
+ diffArrivalTime = (uint32_t)((uint32_t)arr_ts -
+ (uint32_t)bwest_str->receiverTimestamp);
+ bwest_str->receiverTimestamp = arr_ts;
+
+ if(decoderSampRate == kIsacSuperWideband)
+ {
+ diffArrivalTime = (uint32_t)diffArrivalTime >> 1;
+ diffSendTime = (uint32_t)diffSendTime >> 1;
+ }
+
+ // arrival timestamp in 16 kHz
+ arrivalTimestampIn16kHz = (uint32_t)((uint32_t)
+ bwest_str->prev_rec_arr_ts + (uint32_t)diffArrivalTime);
+ // send timestamp in 16 kHz
+ sendTimestampIn16kHz = (uint32_t)((uint32_t)
+ bwest_str->prev_rec_send_ts + (uint32_t)diffSendTime);
+
+ err = WebRtcIsac_UpdateBandwidthEstimator(bwest_str, rtp_seq_number,
+ (frame_samples * 1000) / FS, sendTimestampIn16kHz,
+ arrivalTimestampIn16kHz, packet_size);
+ // error check
+ if(err < 0)
+ {
+ return err;
+ }
+
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode.c
new file mode 100644
index 0000000000..bf92d02c53
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode.c
@@ -0,0 +1,1260 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode.c
+ *
+ * This file contains definition of funtions for encoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_analysis.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_filter.h"
+
+
+#define UB_LOOKAHEAD 24
+
+
+/*
+ Rate allocation tables of lower and upper-band bottleneck for
+ 12kHz & 16kHz bandwidth.
+
+ 12 kHz bandwidth
+ -----------------
+ The overall bottleneck of the coder is between 38 kbps and 45 kbps. We have
+ considered 7 enteries, uniformly distributed in this interval, i.e. 38,
+ 39.17, 40.33, 41.5, 42.67, 43.83 and 45. For every entery, the lower-band
+ and the upper-band bottlenecks are specified in
+ 'kLowerBandBitRate12' and 'kUpperBandBitRate12'
+ tables, respectively. E.g. the overall rate of 41.5 kbps corresponts to a
+ bottleneck of 31 kbps for lower-band and 27 kbps for upper-band. Given an
+ overall bottleneck of the codec, we use linear interpolation to get
+ lower-band and upper-band bottlenecks.
+
+ 16 kHz bandwidth
+ -----------------
+ The overall bottleneck of the coder is between 50 kbps and 56 kbps. We have
+ considered 7 enteries, uniformly distributed in this interval, i.e. 50, 51.2,
+ 52.4, 53.6, 54.8 and 56. For every entery, the lower-band and the upper-band
+ bottlenecks are specified in 'kLowerBandBitRate16' and
+ 'kUpperBandBitRate16' tables, respectively. E.g. the overall rate
+ of 53.6 kbps corresponts to a bottleneck of 32 kbps for lower-band and 30
+ kbps for upper-band. Given an overall bottleneck of the codec, we use linear
+ interpolation to get lower-band and upper-band bottlenecks.
+
+ */
+
+/* 38 39.17 40.33 41.5 42.67 43.83 45 */
+static const int16_t kLowerBandBitRate12[7] = {
+ 29000, 30000, 30000, 31000, 31000, 32000, 32000 };
+static const int16_t kUpperBandBitRate12[7] = {
+ 25000, 25000, 27000, 27000, 29000, 29000, 32000 };
+
+/* 50 51.2 52.4 53.6 54.8 56 */
+static const int16_t kLowerBandBitRate16[6] = {
+ 31000, 31000, 32000, 32000, 32000, 32000 };
+static const int16_t kUpperBandBitRate16[6] = {
+ 28000, 29000, 29000, 30000, 31000, 32000 };
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ * - inRateBitPerSec : a total bottleneck in bits/sec.
+ *
+ * Output:
+ * - rateLBBitPerSec : a bottleneck allocated to the lower-band
+ * in bits/sec.
+ * - rateUBBitPerSec : a bottleneck allocated to the upper-band
+ * in bits/sec.
+ *
+ * Return value : 0 if rate allocation has been successful.
+ * -1 if failed to allocate rates.
+ */
+
+int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
+ double* rateLBBitPerSec,
+ double* rateUBBitPerSec,
+ enum ISACBandwidth* bandwidthKHz) {
+ int16_t idx;
+ double idxD;
+ double idxErr;
+ if (inRateBitPerSec < 38000) {
+ /* If the given overall bottleneck is less than 38000 then
+ * then codec has to operate in wideband mode, i.e. 8 kHz
+ * bandwidth. */
+ *rateLBBitPerSec = (int16_t)((inRateBitPerSec > 32000) ?
+ 32000 : inRateBitPerSec);
+ *rateUBBitPerSec = 0;
+ *bandwidthKHz = isac8kHz;
+ } else if ((inRateBitPerSec >= 38000) && (inRateBitPerSec < 50000)) {
+ /* At a bottleneck between 38 and 50 kbps the codec is operating
+ * at 12 kHz bandwidth. Using xxxBandBitRate12[] to calculates
+ * upper/lower bottleneck */
+
+ /* Find the bottlenecks by linear interpolation,
+ * step is (45000 - 38000)/6.0 we use the inverse of it. */
+ const double stepSizeInv = 8.5714286e-4;
+ idxD = (inRateBitPerSec - 38000) * stepSizeInv;
+ idx = (idxD >= 6) ? 6 : ((int16_t)idxD);
+ idxErr = idxD - idx;
+ *rateLBBitPerSec = kLowerBandBitRate12[idx];
+ *rateUBBitPerSec = kUpperBandBitRate12[idx];
+
+ if (idx < 6) {
+ *rateLBBitPerSec += (int16_t)(
+ idxErr * (kLowerBandBitRate12[idx + 1] - kLowerBandBitRate12[idx]));
+ *rateUBBitPerSec += (int16_t)(
+ idxErr * (kUpperBandBitRate12[idx + 1] - kUpperBandBitRate12[idx]));
+ }
+ *bandwidthKHz = isac12kHz;
+ } else if ((inRateBitPerSec >= 50000) && (inRateBitPerSec <= 56000)) {
+ /* A bottleneck between 50 and 56 kbps corresponds to bandwidth
+ * of 16 kHz. Using xxxBandBitRate16[] to calculates
+ * upper/lower bottleneck. */
+
+ /* Find the bottlenecks by linear interpolation
+ * step is (56000 - 50000)/5 we use the inverse of it. */
+ const double stepSizeInv = 8.3333333e-4;
+ idxD = (inRateBitPerSec - 50000) * stepSizeInv;
+ idx = (idxD >= 5) ? 5 : ((int16_t)idxD);
+ idxErr = idxD - idx;
+ *rateLBBitPerSec = kLowerBandBitRate16[idx];
+ *rateUBBitPerSec = kUpperBandBitRate16[idx];
+
+ if (idx < 5) {
+ *rateLBBitPerSec += (int16_t)(idxErr *
+ (kLowerBandBitRate16[idx + 1] -
+ kLowerBandBitRate16[idx]));
+
+ *rateUBBitPerSec += (int16_t)(idxErr *
+ (kUpperBandBitRate16[idx + 1] -
+ kUpperBandBitRate16[idx]));
+ }
+ *bandwidthKHz = isac16kHz;
+ } else {
+ /* Out-of-range botlteneck value. */
+ return -1;
+ }
+
+ /* limit the values. */
+ *rateLBBitPerSec = (*rateLBBitPerSec > 32000) ? 32000 : *rateLBBitPerSec;
+ *rateUBBitPerSec = (*rateUBBitPerSec > 32000) ? 32000 : *rateUBBitPerSec;
+ return 0;
+}
+
+
+void WebRtcIsac_ResetBitstream(Bitstr* bit_stream) {
+ bit_stream->W_upper = 0xFFFFFFFF;
+ bit_stream->stream_index = 0;
+ bit_stream->streamval = 0;
+}
+
+int WebRtcIsac_EncodeLb(const TransformTables* transform_tables,
+ float* in, ISACLBEncStruct* ISACencLB_obj,
+ int16_t codingMode,
+ int16_t bottleneckIndex) {
+ int stream_length = 0;
+ int err;
+ int k;
+ int iterCntr;
+
+ double lofilt_coef[(ORDERLO + 1)*SUBFRAMES];
+ double hifilt_coef[(ORDERHI + 1)*SUBFRAMES];
+ float LP[FRAMESAMPLES_HALF];
+ float HP[FRAMESAMPLES_HALF];
+
+ double LP_lookahead[FRAMESAMPLES_HALF];
+ double HP_lookahead[FRAMESAMPLES_HALF];
+ double LP_lookahead_pf[FRAMESAMPLES_HALF + QLOOKAHEAD];
+ double LPw[FRAMESAMPLES_HALF];
+
+ double HPw[FRAMESAMPLES_HALF];
+ double LPw_pf[FRAMESAMPLES_HALF];
+ int16_t fre[FRAMESAMPLES_HALF]; /* Q7 */
+ int16_t fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ double PitchLags[4];
+ double PitchGains[4];
+ int16_t PitchGains_Q12[4];
+ int16_t AvgPitchGain_Q12;
+
+ int frame_mode; /* 0 for 30ms, 1 for 60ms */
+ int status = 0;
+ int my_index;
+ transcode_obj transcodingParam;
+ double bytesLeftSpecCoding;
+ uint16_t payloadLimitBytes;
+
+ /* Copy new frame-length and bottleneck rate only for the first 10 ms data */
+ if (ISACencLB_obj->buffer_index == 0) {
+ /* Set the framelength for the next packet. */
+ ISACencLB_obj->current_framesamples = ISACencLB_obj->new_framelength;
+ }
+ /* 'frame_mode' is 0 (30 ms) or 1 (60 ms). */
+ frame_mode = ISACencLB_obj->current_framesamples / MAX_FRAMESAMPLES;
+
+ /* buffer speech samples (by 10ms packet) until the frame-length */
+ /* is reached (30 or 60 ms). */
+ /*****************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ ISACencLB_obj->data_buffer_float[k + ISACencLB_obj->buffer_index] = in[k];
+ }
+
+ /* If buffersize is not equal to current framesize then increase index
+ * and return. We do no encoding untill we have enough audio. */
+ if (ISACencLB_obj->buffer_index + FRAMESAMPLES_10ms != FRAMESAMPLES) {
+ ISACencLB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* If buffer reached the right size, reset index and continue with
+ * encoding the frame. */
+ ISACencLB_obj->buffer_index = 0;
+
+ /* End of buffer function. */
+ /**************************/
+
+ /* Encoding */
+ /************/
+
+ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
+ /* This is to avoid Linux warnings until we change 'int' to 'Word32'
+ * at all places. */
+ int intVar;
+ /* reset bitstream */
+ WebRtcIsac_ResetBitstream(&(ISACencLB_obj->bitstr_obj));
+
+ if ((codingMode == 0) && (frame_mode == 0) &&
+ (ISACencLB_obj->enforceFrameSize == 0)) {
+ ISACencLB_obj->new_framelength = WebRtcIsac_GetNewFrameLength(
+ ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+ }
+
+ ISACencLB_obj->s2nr = WebRtcIsac_GetSnr(
+ ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+
+ /* Encode frame length. */
+ status = WebRtcIsac_EncodeFrameLen(
+ ISACencLB_obj->current_framesamples, &ISACencLB_obj->bitstr_obj);
+ if (status < 0) {
+ /* Wrong frame size. */
+ return status;
+ }
+ /* Save framelength for multiple packets memory. */
+ ISACencLB_obj->SaveEnc_obj.framelength =
+ ISACencLB_obj->current_framesamples;
+
+ /* To be used for Redundant Coding. */
+ ISACencLB_obj->lastBWIdx = bottleneckIndex;
+ intVar = (int)bottleneckIndex;
+ WebRtcIsac_EncodeReceiveBw(&intVar, &ISACencLB_obj->bitstr_obj);
+ }
+
+ /* Split signal in two bands. */
+ WebRtcIsac_SplitAndFilterFloat(ISACencLB_obj->data_buffer_float, LP, HP,
+ LP_lookahead, HP_lookahead,
+ &ISACencLB_obj->prefiltbankstr_obj);
+
+ /* estimate pitch parameters and pitch-filter lookahead signal */
+ WebRtcIsac_PitchAnalysis(LP_lookahead, LP_lookahead_pf,
+ &ISACencLB_obj->pitchanalysisstr_obj, PitchLags,
+ PitchGains);
+
+ /* Encode in FIX Q12. */
+
+ /* Convert PitchGain to Fixed point. */
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchGains_Q12[k] = (int16_t)(PitchGains[k] * 4096.0);
+ }
+
+ /* Set where to store data in multiple packets memory. */
+ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
+ ISACencLB_obj->SaveEnc_obj.startIdx = 0;
+ } else {
+ ISACencLB_obj->SaveEnc_obj.startIdx = 1;
+ }
+
+ /* Quantize & encode pitch parameters. */
+ WebRtcIsac_EncodePitchGain(PitchGains_Q12, &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+ WebRtcIsac_EncodePitchLag(PitchLags, PitchGains_Q12,
+ &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
+
+ /* Find coefficients for perceptual pre-filters. */
+ WebRtcIsac_GetLpcCoefLb(LP_lookahead_pf, HP_lookahead,
+ &ISACencLB_obj->maskfiltstr_obj, ISACencLB_obj->s2nr,
+ PitchGains_Q12, lofilt_coef, hifilt_coef);
+
+ /* Code LPC model and shape - gains not quantized yet. */
+ WebRtcIsac_EncodeLpcLb(lofilt_coef, hifilt_coef, &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ /* Convert PitchGains back to FLOAT for pitchfilter_pre. */
+ for (k = 0; k < 4; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+ }
+
+ /* Store the state of arithmetic coder before coding LPC gains. */
+ transcodingParam.W_upper = ISACencLB_obj->bitstr_obj.W_upper;
+ transcodingParam.stream_index = ISACencLB_obj->bitstr_obj.stream_index;
+ transcodingParam.streamval = ISACencLB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] =
+ ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
+ 2];
+ transcodingParam.stream[1] =
+ ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
+ 1];
+ transcodingParam.stream[2] =
+ ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
+ transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
+ }
+
+ /* Code gains */
+ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
+ &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ /* Get the correct value for the payload limit and calculate the
+ * number of bytes left for coding the spectrum. */
+ if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+ /* It is a 60ms and we are in the first 30ms then the limit at
+ * this point should be half of the assigned value. */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 >> 1;
+ } else if (frame_mode == 0) {
+ /* It is a 30ms frame */
+ /* Subract 3 because termination process may add 3 bytes. */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes30 - 3;
+ } else {
+ /* This is the second half of a 60ms frame. */
+ /* Subract 3 because termination process may add 3 bytes. */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 - 3;
+ }
+ bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+ /* Perceptual pre-filtering (using normalized lattice filter). */
+ /* Low-band filtering. */
+ WebRtcIsac_NormLatticeFilterMa(ORDERLO,
+ ISACencLB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencLB_obj->maskfiltstr_obj.PreStateLoG,
+ LP, lofilt_coef, LPw);
+ /* High-band filtering. */
+ WebRtcIsac_NormLatticeFilterMa(ORDERHI,
+ ISACencLB_obj->maskfiltstr_obj.PreStateHiF,
+ ISACencLB_obj->maskfiltstr_obj.PreStateHiG,
+ HP, hifilt_coef, HPw);
+ /* Pitch filter. */
+ WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj,
+ PitchLags, PitchGains);
+ /* Transform */
+ 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;
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
+
+ ISACencLB_obj->SaveEnc_obj.AvgPitchGain[ISACencLB_obj->SaveEnc_obj.startIdx] =
+ AvgPitchGain_Q12;
+
+ /* Quantization and loss-less coding. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
+ &ISACencLB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload). */
+ if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+ /* If this is the second 30ms of a 60ms frame reset
+ this such that in the next call encoder starts fresh. */
+ ISACencLB_obj->frame_nb = 0;
+ }
+ return err;
+ }
+ iterCntr = 0;
+ while ((ISACencLB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+
+ if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size */
+ if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+ /* This was the first 30ms of a 60ms frame. Although
+ the payload is larger than it should be but we let
+ the second 30ms be encoded. Maybe together we
+ won't exceed the limit. */
+ ISACencLB_obj->frame_nb = 1;
+ return 0;
+ } else if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 1)) {
+ ISACencLB_obj->frame_nb = 0;
+ }
+
+ if (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ } else {
+ return status;
+ }
+ }
+
+ if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ /* Being conservative */
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencLB_obj->bitstr_obj.stream_index -
+ transcodingParam.stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on
+ the number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ lofilt_coef[(LPC_LOBAND_ORDER + 1) * k] =
+ transcodingParam.loFiltGain[k] * transcodeScale;
+ hifilt_coef[(LPC_HIBAND_ORDER + 1) * k] =
+ transcodingParam.hiFiltGain[k] * transcodeScale;
+ transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
+ transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
+ }
+
+ /* Scale DFT coefficients. */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (int16_t)(fre[k] * transcodeScale);
+ fim[k] = (int16_t)(fim[k] * transcodeScale);
+ }
+
+ /* Save data for multiple packets memory. */
+ my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
+ memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
+
+ /* Re-store the state of arithmetic coder before coding LPC gains. */
+ ISACencLB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+ ISACencLB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+ ISACencLB_obj->bitstr_obj.streamval = transcodingParam.streamval;
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
+ transcodingParam.stream[0];
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
+ transcodingParam.stream[1];
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
+ transcodingParam.stream[2];
+
+ /* Code gains. */
+ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
+ &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+
+ /* Update the number of bytes left for encoding the spectrum. */
+ bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+ /* Encode the spectrum. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
+ &ISACencLB_obj->bitstr_obj);
+
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large
+ payload (we can cure too large payload). */
+ if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+ /* If this is the second 30 ms of a 60 ms frame reset
+ this such that in the next call encoder starts fresh. */
+ ISACencLB_obj->frame_nb = 0;
+ }
+ return err;
+ }
+ iterCntr++;
+ }
+
+ /* If 60 ms frame-size and just processed the first 30 ms, */
+ /* go back to main function to buffer the other 30 ms speech frame. */
+ if (frame_mode == 1) {
+ if (ISACencLB_obj->frame_nb == 0) {
+ ISACencLB_obj->frame_nb = 1;
+ return 0;
+ } else if (ISACencLB_obj->frame_nb == 1) {
+ ISACencLB_obj->frame_nb = 0;
+ /* Also update the frame-length for next packet,
+ in Adaptive mode only. */
+ if (codingMode == 0 && (ISACencLB_obj->enforceFrameSize == 0)) {
+ ISACencLB_obj->new_framelength =
+ WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
+ ISACencLB_obj->current_framesamples);
+ }
+ }
+ } else {
+ ISACencLB_obj->frame_nb = 0;
+ }
+
+ /* Complete arithmetic coding. */
+ stream_length = WebRtcIsac_EncTerminate(&ISACencLB_obj->bitstr_obj);
+ return stream_length;
+}
+
+
+
+static int LimitPayloadUb(ISACUBEncStruct* ISACencUB_obj,
+ uint16_t payloadLimitBytes,
+ double bytesLeftSpecCoding,
+ transcode_obj* transcodingParam,
+ int16_t* fre, int16_t* fim,
+ double* lpcGains, enum ISACBand band, int status) {
+
+ int iterCntr = 0;
+ int k;
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+ const int16_t kAveragePitchGain = 0.0;
+
+ do {
+ if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size. */
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ }
+
+ if (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ /* Being conservative. */
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
+ transcodingParam->stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on the
+ number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains. */
+ if (band == kIsacUpperBand16) {
+ /* Two sets of coefficients if 16 kHz. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam->loFiltGain[k] *= transcodeScale;
+ transcodingParam->hiFiltGain[k] *= transcodeScale;
+ }
+ } else {
+ /* One sets of coefficients if 12 kHz. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam->loFiltGain[k] *= transcodeScale;
+ }
+ }
+
+ /* Scale DFT coefficients. */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (int16_t)(fre[k] * transcodeScale + 0.5);
+ fim[k] = (int16_t)(fim[k] * transcodeScale + 0.5);
+ }
+ /* Store FFT coefficients for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
+ memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ ISACencUB_obj->bitstr_obj.W_upper = transcodingParam->W_upper;
+ ISACencUB_obj->bitstr_obj.stream_index = transcodingParam->stream_index;
+ ISACencUB_obj->bitstr_obj.streamval = transcodingParam->streamval;
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 2] =
+ transcodingParam->stream[0];
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 1] =
+ transcodingParam->stream[1];
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index] =
+ transcodingParam->stream[2];
+
+ /* Store the gains for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+ SUBFRAMES * sizeof(double));
+ /* Entropy Code lpc-gains, indices are stored for a later use.*/
+ WebRtcIsac_EncodeLpcGainUb(transcodingParam->loFiltGain,
+ &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+ /* If 16kHz should do one more set. */
+ if (band == kIsacUpperBand16) {
+ /* Store the gains for multiple encoding. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.lpcGain[SUBFRAMES],
+ &lpcGains[SUBFRAMES], SUBFRAMES * sizeof(double));
+ /* Entropy Code lpc-gains, indices are stored for a later use.*/
+ WebRtcIsac_EncodeLpcGainUb(
+ transcodingParam->hiFiltGain, &ISACencUB_obj->bitstr_obj,
+ &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+ }
+
+ /* Update the number of bytes left for encoding the spectrum. */
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ /* Save the bit-stream object at this point for FEC. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* Encode the spectrum. */
+ status = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain,
+ band, &ISACencUB_obj->bitstr_obj);
+ if ((status < 0) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload). */
+ return status;
+ }
+ iterCntr++;
+ } while ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH));
+ return 0;
+}
+
+int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables,
+ float* in, ISACUBEncStruct* ISACencUB_obj,
+ int32_t jitterInfo) {
+ int err;
+ int k;
+
+ double lpcVecs[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ double percepFilterParams[(1 + UB_LPC_ORDER) * (SUBFRAMES << 1) +
+ (1 + UB_LPC_ORDER)];
+
+ double LP_lookahead[FRAMESAMPLES];
+ int16_t fre[FRAMESAMPLES_HALF]; /* Q7 */
+ int16_t fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ int status = 0;
+
+ double varscale[2];
+ double corr[SUBFRAMES << 1][UB_LPC_ORDER + 1];
+ double lpcGains[SUBFRAMES << 1];
+ transcode_obj transcodingParam;
+ uint16_t payloadLimitBytes;
+ double s2nr;
+ const int16_t kAveragePitchGain = 0.0;
+ int bytesLeftSpecCoding;
+
+ /* Buffer speech samples (by 10ms packet) until the frame-length is */
+ /* reached (30 ms). */
+ /*********************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
+ FRAMESAMPLES_10ms * sizeof(float));
+
+ /* If buffer size is not equal to current frame-size, and end of file is
+ * not reached yet, we don't do encoding unless we have the whole frame. */
+ if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+ ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+
+ /* End of buffer function. */
+ /**************************/
+
+ /* Encoding */
+ /************/
+
+ /* Reset bit-stream */
+ WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
+
+ /* Encoding of bandwidth information. */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+
+ status = WebRtcIsac_EncodeBandwidth(isac16kHz, &ISACencUB_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
+
+ memcpy(lpcVecs, ISACencUB_obj->lastLPCVec, UB_LPC_ORDER * sizeof(double));
+
+ for (k = 0; k < FRAMESAMPLES; k++) {
+ LP_lookahead[k] = ISACencUB_obj->data_buffer_float[UB_LOOKAHEAD + k];
+ }
+
+ /* Find coefficients for perceptual pre-filters. */
+ WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+ &lpcVecs[UB_LPC_ORDER], corr, varscale, isac16kHz);
+
+ memcpy(ISACencUB_obj->lastLPCVec,
+ &lpcVecs[(UB16_LPC_VEC_PER_FRAME - 1) * (UB_LPC_ORDER)],
+ sizeof(double) * UB_LPC_ORDER);
+
+ /* Code LPC model and shape - gains not quantized yet. */
+ WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+ percepFilterParams, isac16kHz,
+ &ISACencUB_obj->SaveEnc_obj);
+
+ /* the first set of lpc parameters are from the last sub-frame of
+ * the previous frame. so we don't care about them. */
+ WebRtcIsac_GetLpcGain(s2nr, &percepFilterParams[UB_LPC_ORDER + 1],
+ (SUBFRAMES << 1), lpcGains, corr, varscale);
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+ transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+ transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 2];
+ transcodingParam.stream[1] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 1];
+ transcodingParam.stream[2] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lpcGains[k];
+ transcodingParam.hiFiltGain[k] = lpcGains[SUBFRAMES + k];
+ }
+
+ /* Store the gains for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+ (SUBFRAMES << 1) * sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+ WebRtcIsac_EncodeLpcGainUb(
+ &lpcGains[SUBFRAMES], &ISACencUB_obj->bitstr_obj,
+ &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+
+ /* Get the correct value for the payload limit and calculate the number of
+ bytes left for coding the spectrum. It is a 30ms frame
+ Subract 3 because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+ ISACencUB_obj->numBytesUsed - 3;
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ for (k = 0; k < (SUBFRAMES << 1); k++) {
+ percepFilterParams[k * (UB_LPC_ORDER + 1) + (UB_LPC_ORDER + 1)] =
+ lpcGains[k];
+ }
+
+ /* LPC filtering (using normalized lattice filter), */
+ /* first half-frame. */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+ &ISACencUB_obj->data_buffer_float[0],
+ &percepFilterParams[UB_LPC_ORDER + 1],
+ &LP_lookahead[0]);
+
+ /* Second half-frame filtering. */
+ WebRtcIsac_NormLatticeFilterMa(
+ UB_LPC_ORDER, ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+ &ISACencUB_obj->data_buffer_float[FRAMESAMPLES_HALF],
+ &percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES * (UB_LPC_ORDER + 1)],
+ &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. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre, sizeof(fre));
+ memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim, sizeof(fim));
+
+ /* Prepare the audio buffer for the next packet
+ * move the last 3 ms to the beginning of the buffer. */
+ memcpy(ISACencUB_obj->data_buffer_float,
+ &ISACencUB_obj->data_buffer_float[FRAMESAMPLES],
+ LB_TOTAL_DELAY_SAMPLES * sizeof(float));
+ /* start writing with 3 ms delay to compensate for the delay
+ * of the lower-band. */
+ ISACencUB_obj->buffer_index = LB_TOTAL_DELAY_SAMPLES;
+
+ /* Save the bit-stream object at this point for FEC. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj, &ISACencUB_obj->bitstr_obj,
+ sizeof(Bitstr));
+
+ /* Qantization and lossless coding */
+ /* Note that there is no pitch-gain for this band so kAveragePitchGain = 0
+ * is passed to the function. In fact, the function ignores the 3rd parameter
+ * for this band. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand16,
+ &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ return err;
+ }
+
+ if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
+ &transcodingParam, fre, fim, lpcGains,
+ kIsacUpperBand16, err);
+ }
+ if (err < 0) {
+ return err;
+ }
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables,
+ float* in, ISACUBEncStruct* ISACencUB_obj,
+ int32_t jitterInfo) {
+ int err;
+ int k;
+
+ double lpcVecs[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+ double percepFilterParams[(1 + UB_LPC_ORDER) * SUBFRAMES];
+ float LP[FRAMESAMPLES_HALF];
+ float HP[FRAMESAMPLES_HALF];
+
+ double LP_lookahead[FRAMESAMPLES_HALF];
+ double HP_lookahead[FRAMESAMPLES_HALF];
+ double LPw[FRAMESAMPLES_HALF];
+
+ double HPw[FRAMESAMPLES_HALF];
+ int16_t fre[FRAMESAMPLES_HALF]; /* Q7 */
+ int16_t fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ int status = 0;
+
+ double varscale[1];
+
+ double corr[UB_LPC_GAIN_DIM][UB_LPC_ORDER + 1];
+ double lpcGains[SUBFRAMES];
+ transcode_obj transcodingParam;
+ uint16_t payloadLimitBytes;
+ double s2nr;
+ const int16_t kAveragePitchGain = 0.0;
+ double bytesLeftSpecCoding;
+
+ /* Buffer speech samples (by 10ms packet) until the framelength is */
+ /* reached (30 ms). */
+ /********************************************************************/
+
+ /* Fill the buffer with 10ms input data. */
+ memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
+ FRAMESAMPLES_10ms * sizeof(float));
+
+ /* if buffer-size is not equal to current frame-size then increase the
+ index and return. We do the encoding when we have enough audio. */
+ if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+ ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* If buffer reached the right size, reset index and continue
+ with encoding the frame */
+ ISACencUB_obj->buffer_index = 0;
+
+ /* End of buffer function */
+ /**************************/
+
+ /* Encoding */
+ /************/
+
+ /* Reset bit-stream. */
+ WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
+
+ /* Encoding bandwidth information. */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+ status = WebRtcIsac_EncodeBandwidth(isac12kHz, &ISACencUB_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
+
+ /* Split signal in two bands. */
+ WebRtcIsac_SplitAndFilterFloat(ISACencUB_obj->data_buffer_float, HP, LP,
+ HP_lookahead, LP_lookahead,
+ &ISACencUB_obj->prefiltbankstr_obj);
+
+ /* Find coefficients for perceptual pre-filters. */
+ WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+ lpcVecs, corr, varscale, isac12kHz);
+
+ /* Code LPC model and shape - gains not quantized yet. */
+ WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+ percepFilterParams, isac12kHz,
+ &ISACencUB_obj->SaveEnc_obj);
+
+ WebRtcIsac_GetLpcGain(s2nr, percepFilterParams, SUBFRAMES, lpcGains, corr,
+ varscale);
+
+ /* Store the state of arithmetic coder before coding LPC gains. */
+ transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+ transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+ transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 2];
+ transcodingParam.stream[1] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
+ 1];
+ transcodingParam.stream[2] =
+ ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them. */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lpcGains[k];
+ }
+
+ /* Store the gains for multiple encoding. */
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
+ sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+ for (k = 0; k < SUBFRAMES; k++) {
+ percepFilterParams[k * (UB_LPC_ORDER + 1)] = lpcGains[k];
+ }
+
+ /* perceptual pre-filtering (using normalized lattice filter) */
+ /* low-band filtering */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG, LP,
+ percepFilterParams, LPw);
+
+ /* Get the correct value for the payload limit and calculate the number
+ of bytes left for coding the spectrum. It is a 30ms frame Subract 3
+ because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+ ISACencUB_obj->numBytesUsed - 3;
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ memset(HPw, 0, sizeof(HPw));
+
+ /* Transform */
+ 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,
+ sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
+ memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
+
+ /* Save the bit-stream object at this point for FEC. */
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* Quantization and loss-less coding */
+ /* The 4th parameter to this function is pitch-gain, which is only used
+ * when encoding 0-8 kHz band, and irrelevant in this function, therefore,
+ * we insert zero here. */
+ err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand12,
+ &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large
+ payload (we can cure too large payload) */
+ return err;
+ }
+
+ if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
+ &transcodingParam, fre, fim, lpcGains,
+ kIsacUpperBand12, err);
+ }
+ if (err < 0) {
+ return err;
+ }
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+
+
+
+
+/* This function is used to create a new bit-stream with new BWE.
+ The same data as previously encoded with the function WebRtcIsac_Encoder().
+ The data needed is taken from the structure, where it was stored
+ when calling the encoder. */
+
+int WebRtcIsac_EncodeStoredDataLb(const IsacSaveEncoderData* ISACSavedEnc_obj,
+ Bitstr* ISACBitStr_obj, int BWnumber,
+ float scale) {
+ int ii;
+ int status;
+ int BWno = BWnumber;
+
+ const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
+ const uint16_t** cdf;
+
+ double tmpLPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * 2];
+ double tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * 2];
+ int tmpLPCindex_g[12 * 2];
+ int16_t tmp_fre[FRAMESAMPLES], tmp_fim[FRAMESAMPLES];
+ const int kModel = 0;
+
+ /* Sanity Check - possible values for BWnumber is 0 - 23. */
+ if ((BWnumber < 0) || (BWnumber > 23)) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* Reset bit-stream. */
+ WebRtcIsac_ResetBitstream(ISACBitStr_obj);
+
+ /* Encode frame length */
+ status = WebRtcIsac_EncodeFrameLen(ISACSavedEnc_obj->framelength,
+ ISACBitStr_obj);
+ if (status < 0) {
+ /* Wrong frame size. */
+ return status;
+ }
+
+ /* Transcoding */
+ if ((scale > 0.0) && (scale < 1.0)) {
+ /* Compensate LPC gain. */
+ for (ii = 0;
+ ii < ((ORDERLO + 1)* SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCcoeffs_lo[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_lo[ii];
+ }
+ for (ii = 0;
+ ii < ((ORDERHI + 1) * SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCcoeffs_hi[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_hi[ii];
+ }
+ /* Scale DFT. */
+ for (ii = 0;
+ ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmp_fre[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fre[ii]);
+ tmp_fim[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fim[ii]);
+ }
+ } else {
+ for (ii = 0;
+ ii < (KLT_ORDER_GAIN * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCindex_g[ii] = ISACSavedEnc_obj->LPCindex_g[ii];
+ }
+ for (ii = 0;
+ ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmp_fre[ii] = ISACSavedEnc_obj->fre[ii];
+ tmp_fim[ii] = ISACSavedEnc_obj->fim[ii];
+ }
+ }
+
+ /* Encode bandwidth estimate. */
+ WebRtcIsac_EncodeReceiveBw(&BWno, ISACBitStr_obj);
+
+ /* Loop over number of 30 msec */
+ for (ii = 0; ii <= ISACSavedEnc_obj->startIdx; ii++) {
+ /* Encode pitch gains. */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->pitchGain_index[ii],
+ WebRtcIsac_kQPitchGainCdf_ptr, 1);
+
+ /* Entropy coding of quantization pitch lags */
+ /* Voicing classification. */
+ if (ISACSavedEnc_obj->meanGain[ii] < 0.2) {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ } else if (ISACSavedEnc_obj->meanGain[ii] < 0.4) {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ } else {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ }
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->pitchIndex[PITCH_SUBFRAMES * ii],
+ cdf, PITCH_SUBFRAMES);
+
+ /* LPC */
+ /* Only one model exists. The entropy coding is done only for backward
+ * compatibility. */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj, &kModel,
+ WebRtcIsac_kQKltModelCdfPtr, 1);
+ /* Entropy coding of quantization indices - LPC shape only. */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->LPCindex_s[KLT_ORDER_SHAPE * ii],
+ WebRtcIsac_kQKltCdfPtrShape,
+ KLT_ORDER_SHAPE);
+
+ /* If transcoding, get new LPC gain indices */
+ if (scale < 1.0) {
+ WebRtcIsac_TranscodeLPCCoef(
+ &tmpLPCcoeffs_lo[(ORDERLO + 1) * SUBFRAMES * ii],
+ &tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * ii],
+ &tmpLPCindex_g[KLT_ORDER_GAIN * ii]);
+ }
+
+ /* Entropy coding of quantization indices - LPC gain. */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN * ii],
+ WebRtcIsac_kQKltCdfPtrGain, KLT_ORDER_GAIN);
+
+ /* Quantization and loss-less coding. */
+ status = WebRtcIsac_EncodeSpec(&tmp_fre[ii * FRAMESAMPLES_HALF],
+ &tmp_fim[ii * FRAMESAMPLES_HALF],
+ ISACSavedEnc_obj->AvgPitchGain[ii],
+ kIsacLowerBand, ISACBitStr_obj);
+ if (status < 0) {
+ return status;
+ }
+ }
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(ISACBitStr_obj);
+}
+
+
+int WebRtcIsac_EncodeStoredDataUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ int32_t jitterInfo,
+ float scale,
+ enum ISACBandwidth bandwidth) {
+ int n;
+ int err;
+ double lpcGain[SUBFRAMES];
+ int16_t realFFT[FRAMESAMPLES_HALF];
+ int16_t imagFFT[FRAMESAMPLES_HALF];
+ const uint16_t** shape_cdf;
+ int shape_len;
+ const int16_t kAveragePitchGain = 0.0;
+ enum ISACBand band;
+ /* Reset bitstream. */
+ WebRtcIsac_ResetBitstream(bitStream);
+
+ /* Encode jitter index. */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
+
+ err = WebRtcIsac_EncodeBandwidth(bandwidth, bitStream);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Encode LPC-shape. */
+ if (bandwidth == isac12kHz) {
+ shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb12;
+ shape_len = UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME;
+ band = kIsacUpperBand12;
+ } else {
+ shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb16;
+ shape_len = UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME;
+ band = kIsacUpperBand16;
+ }
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
+ shape_cdf, shape_len);
+
+ if ((scale <= 0.0) || (scale >= 1.0)) {
+ /* We only consider scales between zero and one. */
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ if (bandwidth == isac16kHz) {
+ /* Store gain indices of the second half. */
+ WebRtcIsac_EncHistMulti(bitStream,
+ &ISACSavedEnc_obj->lpcGainIndex[SUBFRAMES],
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ }
+ /* Store FFT coefficients. */
+ err = WebRtcIsac_EncodeSpec(ISACSavedEnc_obj->realFFT,
+ ISACSavedEnc_obj->imagFFT, kAveragePitchGain,
+ band, bitStream);
+ } else {
+ /* Scale LPC gain and FFT coefficients. */
+ for (n = 0; n < SUBFRAMES; n++) {
+ lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
+ }
+ /* Store LPC gains. */
+ WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+
+ if (bandwidth == isac16kHz) {
+ /* Scale and code the gains of the second half of the frame, if 16kHz. */
+ for (n = 0; n < SUBFRAMES; n++) {
+ lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n + SUBFRAMES];
+ }
+ WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+ }
+
+ for (n = 0; n < FRAMESAMPLES_HALF; n++) {
+ realFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->realFFT[n] +
+ 0.5f);
+ imagFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->imagFFT[n] +
+ 0.5f);
+ }
+ /* Store FFT coefficients. */
+ err = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain,
+ band, bitStream);
+ }
+ if (err < 0) {
+ /* Error happened while encoding FFT coefficients. */
+ return err;
+ }
+
+ /* Complete arithmetic coding. */
+ return WebRtcIsac_EncTerminate(bitStream);
+}
+
+int16_t WebRtcIsac_GetRedPayloadUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+ Bitstr* bitStreamObj,
+ enum ISACBandwidth bandwidth) {
+ int n;
+ int16_t status;
+ int16_t realFFT[FRAMESAMPLES_HALF];
+ int16_t imagFFT[FRAMESAMPLES_HALF];
+ enum ISACBand band;
+ const int16_t kAveragePitchGain = 0.0;
+ /* Store bit-stream object. */
+ memcpy(bitStreamObj, &ISACSavedEncObj->bitStreamObj, sizeof(Bitstr));
+
+ /* Scale FFT coefficients. */
+ for (n = 0; n < FRAMESAMPLES_HALF; n++) {
+ realFFT[n] = (int16_t)((float)ISACSavedEncObj->realFFT[n] *
+ RCU_TRANSCODING_SCALE_UB + 0.5);
+ imagFFT[n] = (int16_t)((float)ISACSavedEncObj->imagFFT[n] *
+ RCU_TRANSCODING_SCALE_UB + 0.5);
+ }
+
+ band = (bandwidth == isac12kHz) ? kIsacUpperBand12 : kIsacUpperBand16;
+ status = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain, band,
+ bitStreamObj);
+ if (status < 0) {
+ return status;
+ } else {
+ /* Terminate entropy coding */
+ return WebRtcIsac_EncTerminate(bitStreamObj);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
new file mode 100644
index 0000000000..7b02e64a01
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * code_LPC_UB.c
+ *
+ * This file contains definition of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ * -lar : pointer to lar vectors. LAR vectors are
+ * concatenated.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -lar : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+int16_t
+WebRtcIsac_RemoveLarMean(
+ double* lar,
+ int16_t bandwidth)
+{
+ int16_t coeffCntr;
+ int16_t vecCntr;
+ int16_t numVec;
+ const double* meanLAR;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb12;
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ // REMOVE MEAN
+ *lar++ -= meanLAR[coeffCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ * -inLar : pointer to mean-removed LAR vecrtors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+int16_t
+WebRtcIsac_DecorrelateIntraVec(
+ const double* data,
+ double* out,
+ int16_t bandwidth)
+{
+ const double* ptrData;
+ const double* ptrRow;
+ int16_t rowCntr;
+ int16_t colCntr;
+ int16_t larVecCntr;
+ int16_t numVec;
+ const double* decorrMat;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+ numVec = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // decorrMat * data
+ //
+ // data is assumed to contain 'numVec' of LAR
+ // vectors (mean removed) each of dimension 'UB_LPC_ORDER'
+ // concatenated one after the other.
+ //
+
+ ptrData = data;
+ for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++)
+ {
+ for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+ {
+ ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER];
+ *out = 0;
+ for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+ {
+ *out += ptrData[colCntr] * ptrRow[colCntr];
+ }
+ out++;
+ }
+ ptrData += UB_LPC_ORDER;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ * -data : pointer to matrix of LAR vectors. The matrix
+ * is stored column-wise.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+int16_t
+WebRtcIsac_DecorrelateInterVec(
+ const double* data,
+ double* out,
+ int16_t bandwidth)
+{
+ int16_t coeffCntr;
+ int16_t rowCntr;
+ int16_t colCntr;
+ const double* decorrMat;
+ int16_t interVecDim;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // data * decorrMat
+ //
+ // data is of size 'interVecDim' * 'UB_LPC_ORDER'
+ // That is 'interVecDim' of LAR vectors (mean removed)
+ // in columns each of dimension 'UB_LPC_ORDER'.
+ // matrix is stored column-wise.
+ //
+
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ for(colCntr = 0; colCntr < interVecDim; colCntr++)
+ {
+ out[coeffCntr + colCntr * UB_LPC_ORDER] = 0;
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ out[coeffCntr + colCntr * UB_LPC_ORDER] +=
+ data[coeffCntr + rowCntr * UB_LPC_ORDER] *
+ decorrMat[rowCntr * interVecDim + colCntr];
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ * -data : uncorrelated LAR vectors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : quantized version of the input.
+ * -idx : pointer to quantization indices.
+ */
+double
+WebRtcIsac_QuantizeUncorrLar(
+ double* data,
+ int* recIdx,
+ int16_t bandwidth)
+{
+ int16_t cntr;
+ int32_t idx;
+ int16_t interVecDim;
+ const double* leftRecPoint;
+ double quantizationStepSize;
+ const int16_t* numQuantCell;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+ numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb12;
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+ numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb16;
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // Quantize the parametrs.
+ //
+ for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+ {
+ idx = (int32_t)floor((*data - leftRecPoint[cntr]) /
+ quantizationStepSize + 0.5);
+ if(idx < 0)
+ {
+ idx = 0;
+ }
+ else if(idx >= numQuantCell[cntr])
+ {
+ idx = numQuantCell[cntr] - 1;
+ }
+
+ *data++ = leftRecPoint[cntr] + idx * quantizationStepSize;
+ *recIdx++ = idx;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantiztion indices.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : pointer to quantized values.
+ */
+int16_t
+WebRtcIsac_DequantizeLpcParam(
+ const int* idx,
+ double* out,
+ int16_t bandwidth)
+{
+ int16_t cntr;
+ int16_t interVecDim;
+ const double* leftRecPoint;
+ double quantizationStepSize;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // Dequantize given the quantization indices
+ //
+
+ for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+ {
+ *out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ * -data : uncorrelated parameters.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+int16_t
+WebRtcIsac_CorrelateIntraVec(
+ const double* data,
+ double* out,
+ int16_t bandwidth)
+{
+ int16_t vecCntr;
+ int16_t rowCntr;
+ int16_t colCntr;
+ int16_t numVec;
+ const double* ptrData;
+ const double* intraVecDecorrMat;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+ break;
+ }
+ default:
+ return -1;
+ }
+
+
+ ptrData = data;
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+ {
+ *out = 0;
+ for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+ {
+ *out += ptrData[rowCntr] *
+ intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr];
+ }
+ out++;
+ }
+ ptrData += UB_LPC_ORDER;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ * -data
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+int16_t
+WebRtcIsac_CorrelateInterVec(
+ const double* data,
+ double* out,
+ int16_t bandwidth)
+{
+ int16_t coeffCntr;
+ int16_t rowCntr;
+ int16_t colCntr;
+ int16_t interVecDim;
+ double myVec[UB16_LPC_VEC_PER_FRAME] = {0.0};
+ const double* interVecDecorrMat;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+ break;
+ }
+ case isac16kHz:
+ {
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ myVec[rowCntr] = 0;
+ for(colCntr = 0; colCntr < interVecDim; colCntr++)
+ {
+ myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData *
+ interVecDecorrMat[rowCntr * interVecDim + colCntr];
+ //ptrData += UB_LPC_ORDER;
+ }
+ }
+
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ * -data : pointer to mean-removed LAR:s.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : pointer to LARs.
+ */
+int16_t
+WebRtcIsac_AddLarMean(
+ double* data,
+ int16_t bandwidth)
+{
+ int16_t coeffCntr;
+ int16_t vecCntr;
+ int16_t numVec;
+ const double* meanLAR;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb12;
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ *data++ += meanLAR[coeffCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ * -lpcGain : mean-removed in log domain.
+ */
+int16_t
+WebRtcIsac_ToLogDomainRemoveMean(
+ double* data)
+{
+ int16_t coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ * -data : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ * -out : decorrelated parameters.
+ */
+int16_t WebRtcIsac_DecorrelateLPGain(
+ const double* data,
+ double* out)
+{
+ int16_t rowCntr;
+ int16_t colCntr;
+
+ for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+ {
+ *out = 0;
+ for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+ {
+ *out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr];
+ }
+ out++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ * -lpcGain : uncorrelated LPC gains.
+ *
+ * Output:
+ * -idx : quantization indices
+ * -lpcGain : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(
+ double* data,
+ int* idx)
+{
+ int16_t coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ *idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) /
+ WebRtcIsac_kQSizeLpcGain + 0.5);
+
+ if(*idx < 0)
+ {
+ *idx = 0;
+ }
+ else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr])
+ {
+ *idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1;
+ }
+ *data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+ WebRtcIsac_kQSizeLpcGain;
+
+ data++;
+ idx++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantization indices.
+ *
+ * Output:
+ * -lpcGains : quantized values of the given parametes.
+ */
+int16_t WebRtcIsac_DequantizeLpcGain(
+ const int* idx,
+ double* out)
+{
+ int16_t coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ *out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+ WebRtcIsac_kQSizeLpcGain;
+ out++;
+ idx++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ * -data : decorrelated parameters.
+ *
+ * Output:
+ * -out : correlated parameters.
+ */
+int16_t WebRtcIsac_CorrelateLpcGain(
+ const double* data,
+ double* out)
+{
+ int16_t rowCntr;
+ int16_t colCntr;
+
+ for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+ {
+ *out = 0;
+ for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+ {
+ *out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr];
+ }
+ out++;
+ }
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ * -lpcGain : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ * -lpcGain : LPC gain in normal domain.
+ */
+int16_t WebRtcIsac_AddMeanToLinearDomain(
+ double* lpcGains)
+{
+ int16_t coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain);
+ }
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
new file mode 100644
index 0000000000..8bc3d752c3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode_lpc_swb.h
+ *
+ * This file contains declaration of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ * -lar : pointer to lar vectors. LAR vectors are
+ * concatenated.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -lar : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+int16_t WebRtcIsac_RemoveLarMean(double* lar, int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ * -inLar : pointer to mean-removed LAR vecrtors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+int16_t WebRtcIsac_DecorrelateIntraVec(const double* inLAR,
+ double* out,
+ int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ * -data : pointer to matrix of LAR vectors. The matrix
+ * is stored column-wise.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+int16_t WebRtcIsac_DecorrelateInterVec(const double* data,
+ double* out,
+ int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ * -data : uncorrelated LAR vectors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : quantized version of the input.
+ * -idx : pointer to quantization indices.
+ */
+double WebRtcIsac_QuantizeUncorrLar(double* data, int* idx, int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ * -data : uncorrelated parameters.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+int16_t WebRtcIsac_CorrelateIntraVec(const double* data,
+ double* out,
+ int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ * -data
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+int16_t WebRtcIsac_CorrelateInterVec(const double* data,
+ double* out,
+ int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ * -data : pointer to mean-removed LAR:s.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : pointer to LARs.
+ */
+int16_t WebRtcIsac_AddLarMean(double* data, int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantiztion indices.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : pointer to quantized values.
+ */
+int16_t WebRtcIsac_DequantizeLpcParam(const int* idx,
+ double* out,
+ int16_t bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ * -lpcGain : mean-removed in log domain.
+ */
+int16_t WebRtcIsac_ToLogDomainRemoveMean(double* lpGains);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ * -data : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ * -out : decorrelated parameters.
+ */
+int16_t WebRtcIsac_DecorrelateLPGain(const double* data, double* out);
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ * -lpcGain : uncorrelated LPC gains.
+ *
+ * Output:
+ * -idx : quantization indices
+ * -lpcGain : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(double* lpGains, int* idx);
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantization indices.
+ *
+ * Output:
+ * -lpcGains : quantized values of the given parametes.
+ */
+int16_t WebRtcIsac_DequantizeLpcGain(const int* idx, double* lpGains);
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ * -data : decorrelated parameters.
+ *
+ * Output:
+ * -out : correlated parameters.
+ */
+int16_t WebRtcIsac_CorrelateLpcGain(const double* data, double* out);
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ * -lpcGain : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ * -lpcGain : LPC gain in normal domain.
+ */
+int16_t WebRtcIsac_AddMeanToLinearDomain(double* lpcGains);
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.c
new file mode 100644
index 0000000000..188c8f6b86
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.c
@@ -0,0 +1,2066 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This header file defines all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/arith_routines.h"
+#include "modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+
+#include <math.h>
+#include <string.h>
+
+static const uint16_t kLpcVecPerSegmentUb12 = 5;
+static const uint16_t kLpcVecPerSegmentUb16 = 4;
+
+/* CDF array for encoder bandwidth (12 vs 16 kHz) indicator. */
+static const uint16_t kOneBitEqualProbCdf[3] = {
+ 0, 32768, 65535 };
+
+/* Pointer to cdf array for encoder bandwidth (12 vs 16 kHz) indicator. */
+static const uint16_t* const kOneBitEqualProbCdf_ptr[1] = {
+ kOneBitEqualProbCdf };
+
+/*
+ * Initial cdf index for decoder of encoded bandwidth
+ * (12 vs 16 kHz) indicator.
+ */
+static const uint16_t kOneBitEqualProbInitIndex[1] = { 1 };
+
+
+static const int kIsSWB12 = 1;
+
+/* compute correlation from power spectrum */
+static void FindCorrelation(int32_t* PSpecQ12, int32_t* CorrQ7) {
+ int32_t summ[FRAMESAMPLES / 8];
+ int32_t diff[FRAMESAMPLES / 8];
+ const int16_t* CS_ptrQ9;
+ int32_t sum;
+ int k, n;
+
+ for (k = 0; k < FRAMESAMPLES / 8; k++) {
+ summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
+ diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
+ }
+
+ sum = 2;
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ sum += summ[n];
+ }
+ CorrQ7[0] = sum;
+
+ for (k = 0; k < AR_ORDER; k += 2) {
+ sum = 0;
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES / 8; n++)
+ sum += (CS_ptrQ9[n] * diff[n] + 256) >> 9;
+ CorrQ7[k + 1] = sum;
+ }
+
+ for (k = 1; k < AR_ORDER; k += 2) {
+ sum = 0;
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES / 8; n++)
+ sum += (CS_ptrQ9[n] * summ[n] + 256) >> 9;
+ CorrQ7[k + 1] = sum;
+ }
+}
+
+/* compute inverse AR power spectrum */
+/* Changed to the function used in iSAC FIX for compatibility reasons */
+static void FindInvArSpec(const int16_t* ARCoefQ12,
+ const int32_t gainQ10,
+ int32_t* CurveQ16) {
+ int32_t CorrQ11[AR_ORDER + 1];
+ int64_t sum, tmpGain;
+ int32_t diffQ16[FRAMESAMPLES / 8];
+ const int16_t* CS_ptrQ9;
+ int k, n;
+ int16_t round, shftVal = 0, sh;
+
+ sum = 0;
+ for (n = 0; n < AR_ORDER + 1; n++) {
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]); /* Q24 */
+ }
+ sum = ((sum >> 6) * 65 + 32768) >> 16; /* Q8 */
+ CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
+
+ /* To avoid overflow, we shift down gainQ10 if it is large.
+ * We will not lose any precision */
+ if (gainQ10 > 400000) {
+ tmpGain = gainQ10 >> 3;
+ round = 32;
+ shftVal = 6;
+ } else {
+ tmpGain = gainQ10;
+ round = 256;
+ shftVal = 9;
+ }
+
+ for (k = 1; k < AR_ORDER + 1; k++) {
+ sum = 16384;
+ for (n = k; n < AR_ORDER + 1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n - k], ARCoefQ12[n]); /* Q24 */
+ sum >>= 15;
+ CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
+ }
+ sum = CorrQ11[0] << 7;
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ CurveQ16[n] = sum;
+ }
+ for (k = 1; k < AR_ORDER; k += 2) {
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ CurveQ16[n] += (WebRtcIsac_kCos[k][n] * CorrQ11[k + 1] + 2) >> 2;
+ }
+ }
+
+ CS_ptrQ9 = WebRtcIsac_kCos[0];
+
+ /* If CorrQ11[1] too large we avoid getting overflow in the
+ * calculation by shifting */
+ sh = WebRtcSpl_NormW32(CorrQ11[1]);
+ if (CorrQ11[1] == 0) { /* Use next correlation */
+ sh = WebRtcSpl_NormW32(CorrQ11[2]);
+ }
+ if (sh < 9) {
+ shftVal = 9 - sh;
+ } else {
+ shftVal = 0;
+ }
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
+ }
+ for (k = 2; k < AR_ORDER; k += 2) {
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES / 8; n++) {
+ diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
+ }
+ }
+
+ for (k = 0; k < FRAMESAMPLES / 8; k++) {
+ int32_t diff_q16_shifted = (int32_t)((uint32_t)(diffQ16[k]) << shftVal);
+ CurveQ16[FRAMESAMPLES_QUARTER - 1 - k] = CurveQ16[k] - diff_q16_shifted;
+ CurveQ16[k] += diff_q16_shifted;
+ }
+}
+
+/* Generate array of dither samples in Q7. */
+static void GenerateDitherQ7Lb(int16_t* bufQ7, uint32_t seed,
+ int length, int16_t AvgPitchGain_Q12) {
+ int k, shft;
+ int16_t dither1_Q7, dither2_Q7, dither_gain_Q14;
+
+ /* This threshold should be equal to that in decode_spec(). */
+ if (AvgPitchGain_Q12 < 614) {
+ for (k = 0; k < length - 2; k += 3) {
+ /* New random unsigned int. */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64 (Q7). */
+ /* dither = seed * 128 / 4294967295 */
+ dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ /* New random unsigned int. */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64. */
+ dither2_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ shft = (seed >> 25) & 15;
+ if (shft < 5) {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k + 1] = dither2_Q7;
+ bufQ7[k + 2] = 0;
+ } else if (shft < 10) {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k + 1] = 0;
+ bufQ7[k + 2] = dither2_Q7;
+ } else {
+ bufQ7[k] = 0;
+ bufQ7[k + 1] = dither1_Q7;
+ bufQ7[k + 2] = dither2_Q7;
+ }
+ }
+ } else {
+ dither_gain_Q14 = (int16_t)(22528 - 10 * AvgPitchGain_Q12);
+
+ /* Dither on half of the coefficients. */
+ for (k = 0; k < length - 1; k += 2) {
+ /* New random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64. */
+ dither1_Q7 = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ /* Dither sample is placed in either even or odd index. */
+ shft = (seed >> 25) & 1; /* Either 0 or 1 */
+
+ bufQ7[k + shft] = (((dither_gain_Q14 * dither1_Q7) + 8192) >> 14);
+ bufQ7[k + 1 - shft] = 0;
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * GenerateDitherQ7LbUB()
+ *
+ * generate array of dither samples in Q7 There are less zeros in dither
+ * vector compared to GenerateDitherQ7Lb.
+ *
+ * A uniform random number generator with the range of [-64 64] is employed
+ * but the generated dithers are scaled by 0.35, a heuristic scaling.
+ *
+ * Input:
+ * -seed : the initial seed for the random number generator.
+ * -length : the number of dither values to be generated.
+ *
+ * Output:
+ * -bufQ7 : pointer to a buffer where dithers are written to.
+ */
+static void GenerateDitherQ7LbUB(
+ int16_t* bufQ7,
+ uint32_t seed,
+ int length) {
+ int k;
+ for (k = 0; k < length; k++) {
+ /* new random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* Fixed-point dither sample between -64 and 64 (Q7). */
+ /* bufQ7 = seed * 128 / 4294967295 */
+ bufQ7[k] = (int16_t)(((int32_t)(seed + 16777216)) >> 25);
+
+ /* Scale by 0.35. */
+ bufQ7[k] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(bufQ7[k], 2048, 13);
+ }
+}
+
+/*
+ * Function to decode the complex spectrum from the bit stream
+ * returns the total number of bytes in the stream.
+ */
+int WebRtcIsac_DecodeSpec(Bitstr* streamdata, int16_t AvgPitchGain_Q12,
+ enum ISACBand band, double* fr, double* fi) {
+ int16_t DitherQ7[FRAMESAMPLES];
+ int16_t data[FRAMESAMPLES];
+ int32_t invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ uint16_t invARSpecQ8[FRAMESAMPLES_QUARTER];
+ int16_t ARCoefQ12[AR_ORDER + 1];
+ int16_t RCQ15[AR_ORDER];
+ int16_t gainQ10;
+ int32_t gain2_Q10, res;
+ int32_t in_sqrt;
+ int32_t newRes;
+ int k, len, i;
+ int is_12khz = !kIsSWB12;
+ int num_dft_coeff = FRAMESAMPLES;
+ /* Create dither signal. */
+ if (band == kIsacLowerBand) {
+ GenerateDitherQ7Lb(DitherQ7, streamdata->W_upper, FRAMESAMPLES,
+ AvgPitchGain_Q12);
+ } else {
+ GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES);
+ if (band == kIsacUpperBand12) {
+ is_12khz = kIsSWB12;
+ num_dft_coeff = FRAMESAMPLES_HALF;
+ }
+ }
+
+ /* Decode model parameters. */
+ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* Compute inverse AR power spectrum. */
+ FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* Convert to magnitude spectrum,
+ * by doing square-roots (modified from SPLIB). */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt < 0)
+ in_sqrt = -in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (int16_t)newRes;
+ }
+
+ len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7,
+ num_dft_coeff, is_12khz);
+ /* Arithmetic decoding of spectrum. */
+ if (len < 1) {
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+ }
+
+ switch (band) {
+ case kIsacLowerBand: {
+ /* Scale down spectral samples with low SNR. */
+ int32_t p1;
+ int32_t p2;
+ if (AvgPitchGain_Q12 <= 614) {
+ p1 = 30 << 10;
+ p2 = 32768 + (33 << 16);
+ } else {
+ p1 = 36 << 10;
+ p2 = 32768 + (40 << 16);
+ }
+ for (k = 0; k < FRAMESAMPLES; k += 4) {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(p1, (int16_t)(
+ (invARSpec2_Q16[k >> 2] + p2) >> 16));
+ *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k + 1] * gainQ10 + 512) >> 10) / 128.0;
+ *fr++ = (double)((data[k + 2] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k + 3] * gainQ10 + 512) >> 10) / 128.0;
+ }
+ break;
+ }
+ case kIsacUpperBand12: {
+ for (k = 0, i = 0; k < FRAMESAMPLES_HALF; k += 4) {
+ fr[i] = (double)data[ k ] / 128.0;
+ fi[i] = (double)data[k + 1] / 128.0;
+ i++;
+ fr[i] = (double)data[k + 2] / 128.0;
+ fi[i] = (double)data[k + 3] / 128.0;
+ i++;
+ }
+ /* The second half of real and imaginary coefficients is zero. This is
+ * due to using the old FFT module which requires two signals as input
+ * while in 0-12 kHz mode we only have 8-12 kHz band, and the second
+ * signal is set to zero. */
+ memset(&fr[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
+ sizeof(double));
+ memset(&fi[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
+ sizeof(double));
+ break;
+ }
+ case kIsacUpperBand16: {
+ for (i = 0, k = 0; k < FRAMESAMPLES; k += 4, i++) {
+ fr[i] = (double)data[ k ] / 128.0;
+ fi[i] = (double)data[k + 1] / 128.0;
+ fr[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 2] / 128.0;
+ fi[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 3] / 128.0;
+ }
+ break;
+ }
+ }
+ return len;
+}
+
+
+int WebRtcIsac_EncodeSpec(const int16_t* fr, const int16_t* fi,
+ int16_t AvgPitchGain_Q12, enum ISACBand band,
+ Bitstr* streamdata) {
+ int16_t ditherQ7[FRAMESAMPLES];
+ int16_t dataQ7[FRAMESAMPLES];
+ int32_t PSpec[FRAMESAMPLES_QUARTER];
+ int32_t invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ uint16_t invARSpecQ8[FRAMESAMPLES_QUARTER];
+ int32_t CorrQ7[AR_ORDER + 1];
+ int32_t CorrQ7_norm[AR_ORDER + 1];
+ int16_t RCQ15[AR_ORDER];
+ int16_t ARCoefQ12[AR_ORDER + 1];
+ int32_t gain2_Q10;
+ int16_t val;
+ int32_t nrg, res;
+ uint32_t sum;
+ int32_t in_sqrt;
+ int32_t newRes;
+ int16_t err;
+ uint32_t nrg_u32;
+ int shift_var;
+ int k, n, j, i;
+ int is_12khz = !kIsSWB12;
+ int num_dft_coeff = FRAMESAMPLES;
+
+ /* Create dither signal. */
+ if (band == kIsacLowerBand) {
+ GenerateDitherQ7Lb(ditherQ7, streamdata->W_upper, FRAMESAMPLES,
+ AvgPitchGain_Q12);
+ } else {
+ GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES);
+ if (band == kIsacUpperBand12) {
+ is_12khz = kIsSWB12;
+ num_dft_coeff = FRAMESAMPLES_HALF;
+ }
+ }
+
+ /* add dither and quantize, and compute power spectrum */
+ switch (band) {
+ case kIsacLowerBand: {
+ for (k = 0; k < FRAMESAMPLES; k += 4) {
+ val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+ dataQ7[k + 1] = val;
+ sum += val * val;
+
+ val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
+ dataQ7[k + 2] = val;
+ sum += val * val;
+
+ val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
+ dataQ7[k + 3] = val;
+ sum += val * val;
+
+ PSpec[k >> 2] = sum >> 2;
+ }
+ break;
+ }
+ case kIsacUpperBand12: {
+ for (k = 0, j = 0; k < FRAMESAMPLES_HALF; k += 4) {
+ val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+ dataQ7[k + 1] = val;
+ sum += val * val;
+
+ PSpec[j++] = sum >> 1;
+
+ val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
+ dataQ7[k + 2] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
+ dataQ7[k + 3] = val;
+ sum += val * val;
+
+ PSpec[j++] = sum >> 1;
+ }
+ break;
+ }
+ case kIsacUpperBand16: {
+ for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++) {
+ val = ((fr[j] + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((fi[j] + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
+ dataQ7[k + 1] = val;
+ sum += val * val;
+
+ val = ((fr[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 2] + 64) &
+ 0xFF80) - ditherQ7[k + 2];
+ dataQ7[k + 2] = val;
+ sum += val * val;
+
+ val = ((fi[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 3] + 64) &
+ 0xFF80) - ditherQ7[k + 3];
+ dataQ7[k + 3] = val;
+ sum += val * val;
+
+ PSpec[k >> 2] = sum >> 2;
+ }
+ break;
+ }
+ }
+
+ /* compute correlation from power spectrum */
+ FindCorrelation(PSpec, CorrQ7);
+
+ /* Find AR coefficients */
+ /* Aumber of bit shifts to 14-bit normalize CorrQ7[0]
+ * (leaving room for sign) */
+ shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (shift_var > 0) {
+ for (k = 0; k < AR_ORDER + 1; k++) {
+ CorrQ7_norm[k] = CorrQ7[k] << shift_var;
+ }
+ } else {
+ for (k = 0; k < AR_ORDER + 1; k++) {
+ CorrQ7_norm[k] = CorrQ7[k] >> (-shift_var);
+ }
+ }
+
+ /* Find RC coefficients. */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* Quantize & code RC Coefficient. */
+ WebRtcIsac_EncodeRc(RCQ15, streamdata);
+
+ /* RC -> AR coefficients */
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ /* Compute ARCoef' * Corr * ARCoef in Q19. */
+ nrg = 0;
+ for (j = 0; j <= AR_ORDER; j++) {
+ for (n = 0; n <= j; n++) {
+ nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
+ 4) >> 3;
+ }
+ for (n = j + 1; n <= AR_ORDER; n++) {
+ nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
+ 4) >> 3;
+ }
+ }
+
+ nrg_u32 = (uint32_t)nrg;
+ if (shift_var > 0) {
+ nrg_u32 = nrg_u32 >> shift_var;
+ } else {
+ nrg_u32 = nrg_u32 << (-shift_var);
+ }
+ if (nrg_u32 > 0x7FFFFFFF) {
+ nrg = 0x7FFFFFFF;
+ } else {
+ nrg = (int32_t)nrg_u32;
+ }
+ /* Also shifts 31 bits to the left! */
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg);
+
+ /* Quantize & code gain2_Q10. */
+ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
+ return -1;
+ }
+
+ /* Compute inverse AR power spectrum. */
+ FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+ /* Convert to magnitude spectrum, by doing square-roots
+ * (modified from SPLIB). */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt < 0) {
+ in_sqrt = -in_sqrt;
+ }
+ newRes = (in_sqrt / res + res) >> 1;
+ do {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (int16_t)newRes;
+ }
+ /* arithmetic coding of spectrum */
+ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
+ num_dft_coeff, is_12khz);
+ if (err < 0) {
+ return (err);
+ }
+ return 0;
+}
+
+
+/* step-up */
+void WebRtcIsac_Rc2Poly(double* RC, int N, double* a) {
+ int m, k;
+ double tmp[MAX_AR_MODEL_ORDER];
+
+ a[0] = 1.0;
+ tmp[0] = 1.0;
+ for (m = 1; m <= N; m++) {
+ /* copy */
+ memcpy(&tmp[1], &a[1], (m - 1) * sizeof(double));
+ a[m] = RC[m - 1];
+ for (k = 1; k < m; k++) {
+ a[k] += RC[m - 1] * tmp[m - k];
+ }
+ }
+ return;
+}
+
+/* step-down */
+void WebRtcIsac_Poly2Rc(double* a, int N, double* RC) {
+ int m, k;
+ double tmp[MAX_AR_MODEL_ORDER];
+ double tmp_inv;
+
+ RC[N - 1] = a[N];
+ for (m = N - 1; m > 0; m--) {
+ tmp_inv = 1.0 / (1.0 - RC[m] * RC[m]);
+ for (k = 1; k <= m; k++) {
+ tmp[k] = (a[k] - RC[m] * a[m - k + 1]) * tmp_inv;
+ }
+
+ memcpy(&a[1], &tmp[1], (m - 1) * sizeof(double));
+ RC[m - 1] = tmp[m];
+ }
+ return;
+}
+
+
+#define MAX_ORDER 100
+
+/* Matlab's LAR definition */
+void WebRtcIsac_Rc2Lar(const double* refc, double* lar, int order) {
+ int k;
+ for (k = 0; k < order; k++) {
+ lar[k] = log((1 + refc[k]) / (1 - refc[k]));
+ }
+}
+
+
+void WebRtcIsac_Lar2Rc(const double* lar, double* refc, int order) {
+ int k;
+ double tmp;
+
+ for (k = 0; k < order; k++) {
+ tmp = exp(lar[k]);
+ refc[k] = (tmp - 1) / (tmp + 1);
+ }
+}
+
+void WebRtcIsac_Poly2Lar(double* lowband, int orderLo, double* hiband,
+ int orderHi, int Nsub, double* lars) {
+ int k;
+ double rc[MAX_ORDER], *inpl, *inph, *outp;
+
+ inpl = lowband;
+ inph = hiband;
+ outp = lars;
+ for (k = 0; k < Nsub; k++) {
+ /* gains */
+ outp[0] = inpl[0];
+ outp[1] = inph[0];
+ outp += 2;
+
+ /* Low band */
+ inpl[0] = 1.0;
+ WebRtcIsac_Poly2Rc(inpl, orderLo, rc);
+ WebRtcIsac_Rc2Lar(rc, outp, orderLo);
+ outp += orderLo;
+
+ /* High band */
+ inph[0] = 1.0;
+ WebRtcIsac_Poly2Rc(inph, orderHi, rc);
+ WebRtcIsac_Rc2Lar(rc, outp, orderHi);
+ outp += orderHi;
+
+ inpl += orderLo + 1;
+ inph += orderHi + 1;
+ }
+}
+
+
+int16_t WebRtcIsac_Poly2LarUB(double* lpcVecs, int16_t bandwidth) {
+ double poly[MAX_ORDER];
+ double rc[MAX_ORDER];
+ double* ptrIO;
+ int16_t vecCntr;
+ int16_t vecSize;
+ int16_t numVec;
+
+ vecSize = UB_LPC_ORDER;
+ switch (bandwidth) {
+ case isac12kHz: {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz: {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ ptrIO = lpcVecs;
+ poly[0] = 1.0;
+ for (vecCntr = 0; vecCntr < numVec; vecCntr++) {
+ memcpy(&poly[1], ptrIO, sizeof(double) * vecSize);
+ WebRtcIsac_Poly2Rc(poly, vecSize, rc);
+ WebRtcIsac_Rc2Lar(rc, ptrIO, vecSize);
+ ptrIO += vecSize;
+ }
+ return 0;
+}
+
+
+void WebRtcIsac_Lar2Poly(double* lars, double* lowband, int orderLo,
+ double* hiband, int orderHi, int Nsub) {
+ int k, orderTot;
+ double rc[MAX_ORDER], *outpl, *outph, *inp;
+
+ orderTot = (orderLo + orderHi + 2);
+ outpl = lowband;
+ outph = hiband;
+ /* First two elements of 'inp' store gains*/
+ inp = lars;
+ for (k = 0; k < Nsub; k++) {
+ /* Low band */
+ WebRtcIsac_Lar2Rc(&inp[2], rc, orderLo);
+ WebRtcIsac_Rc2Poly(rc, orderLo, outpl);
+
+ /* High band */
+ WebRtcIsac_Lar2Rc(&inp[orderLo + 2], rc, orderHi);
+ WebRtcIsac_Rc2Poly(rc, orderHi, outph);
+
+ /* gains */
+ outpl[0] = inp[0];
+ outph[0] = inp[1];
+
+ outpl += orderLo + 1;
+ outph += orderHi + 1;
+ inp += orderTot;
+ }
+}
+
+/*
+ * assumes 2 LAR vectors interpolates to 'numPolyVec' A-polynomials
+ * Note: 'numPolyVecs' includes the first and the last point of the interval
+ */
+void WebRtcIsac_Lar2PolyInterpolUB(double* larVecs, double* percepFilterParams,
+ int numPolyVecs) {
+ int polyCntr, coeffCntr;
+ double larInterpol[UB_LPC_ORDER];
+ double rc[UB_LPC_ORDER];
+ double delta[UB_LPC_ORDER];
+
+ /* calculate the step-size for linear interpolation coefficients */
+ for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
+ delta[coeffCntr] = (larVecs[UB_LPC_ORDER + coeffCntr] -
+ larVecs[coeffCntr]) / (numPolyVecs - 1);
+ }
+
+ for (polyCntr = 0; polyCntr < numPolyVecs; polyCntr++) {
+ for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
+ larInterpol[coeffCntr] = larVecs[coeffCntr] +
+ delta[coeffCntr] * polyCntr;
+ }
+ WebRtcIsac_Lar2Rc(larInterpol, rc, UB_LPC_ORDER);
+
+ /* convert to A-polynomial, the following function returns A[0] = 1;
+ * which is written where gains had to be written. Then we write the
+ * gain (outside this function). This way we say a memcpy. */
+ WebRtcIsac_Rc2Poly(rc, UB_LPC_ORDER, percepFilterParams);
+ percepFilterParams += (UB_LPC_ORDER + 1);
+ }
+}
+
+int WebRtcIsac_DecodeLpc(Bitstr* streamdata, double* LPCCoef_lo,
+ double* LPCCoef_hi) {
+ double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
+ int err;
+
+ err = WebRtcIsac_DecodeLpcCoef(streamdata, lars);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_LPC;
+ }
+ WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
+ SUBFRAMES);
+ return 0;
+}
+
+int16_t WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
+ double* percepFilterParams,
+ int16_t bandwidth) {
+ double lpcCoeff[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int err;
+ int interpolCntr;
+ int subframeCntr;
+ int16_t numSegments;
+ int16_t numVecPerSegment;
+ int16_t numGains;
+
+ double percepFilterGains[SUBFRAMES << 1];
+ double* ptrOutParam = percepFilterParams;
+
+ err = WebRtcIsac_DecodeLpcCoefUB(streamdata, lpcCoeff, percepFilterGains,
+ bandwidth);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_LPC;
+ }
+
+ switch (bandwidth) {
+ case isac12kHz: {
+ numGains = SUBFRAMES;
+ numSegments = UB_LPC_VEC_PER_FRAME - 1;
+ numVecPerSegment = kLpcVecPerSegmentUb12;
+ break;
+ }
+ case isac16kHz: {
+ numGains = SUBFRAMES << 1;
+ numSegments = UB16_LPC_VEC_PER_FRAME - 1;
+ numVecPerSegment = kLpcVecPerSegmentUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for (interpolCntr = 0; interpolCntr < numSegments; interpolCntr++) {
+ WebRtcIsac_Lar2PolyInterpolUB(&lpcCoeff[interpolCntr * UB_LPC_ORDER],
+ ptrOutParam, numVecPerSegment + 1);
+ ptrOutParam += (numVecPerSegment * (UB_LPC_ORDER + 1));
+ }
+
+ ptrOutParam = percepFilterParams;
+
+ if (bandwidth == isac16kHz) {
+ ptrOutParam += (1 + UB_LPC_ORDER);
+ }
+
+ for (subframeCntr = 0; subframeCntr < numGains; subframeCntr++) {
+ *ptrOutParam = percepFilterGains[subframeCntr];
+ ptrOutParam += (1 + UB_LPC_ORDER);
+ }
+ return 0;
+}
+
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef) {
+ int j, k, n, pos, pos2, posg, poss, offsg, offss, offs2;
+ int index_g[KLT_ORDER_GAIN], index_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs_g[KLT_ORDER_GAIN], tmpcoeffs_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN], tmpcoeffs2_s[KLT_ORDER_SHAPE];
+ double sum;
+ int err;
+ int model = 1;
+
+ /* entropy decoding of model number */
+ /* We are keeping this for backward compatibility of bit-streams. */
+ err = WebRtcIsac_DecHistOneStepMulti(&model, streamdata,
+ WebRtcIsac_kQKltModelCdfPtr,
+ WebRtcIsac_kQKltModelInitIndex, 1);
+ if (err < 0) {
+ return err;
+ }
+ /* Only accepted value of model is 0. It is kept in bit-stream for backward
+ * compatibility. */
+ if (model != 0) {
+ return -ISAC_DISALLOWED_LPC_MODEL;
+ }
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_s, streamdata, WebRtcIsac_kQKltCdfPtrShape,
+ WebRtcIsac_kQKltInitIndexShape, KLT_ORDER_SHAPE);
+ if (err < 0) {
+ return err;
+ }
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_g, streamdata, WebRtcIsac_kQKltCdfPtrGain,
+ WebRtcIsac_kQKltInitIndexGain, KLT_ORDER_GAIN);
+ if (err < 0) {
+ return err;
+ }
+
+ /* find quantization levels for coefficients */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_s[k] =
+ WebRtcIsac_kQKltLevelsShape[WebRtcIsac_kQKltOffsetShape[k] +
+ index_s[k]];
+ }
+ for (k = 0; k < KLT_ORDER_GAIN; k++) {
+ tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOffsetGain[k] +
+ index_g[k]];
+ }
+
+ /* Inverse KLT */
+
+ /* Left transform, transpose matrix! */
+ offsg = 0;
+ offss = 0;
+ posg = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = offs2;
+ for (n = 0; n < LPC_GAIN_ORDER; n++) {
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
+ }
+ tmpcoeffs2_g[posg++] = sum;
+ offs2 += LPC_GAIN_ORDER;
+ }
+ offs2 = 0;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = offss;
+ pos2 = offs2;
+ for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+ sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
+ }
+ tmpcoeffs2_s[poss++] = sum;
+ offs2 += LPC_SHAPE_ORDER;
+ }
+ offsg += LPC_GAIN_ORDER;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Right transform, transpose matrix */
+ offsg = 0;
+ offss = 0;
+ posg = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
+ pos += LPC_GAIN_ORDER;
+ pos2 += SUBFRAMES;
+
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
+ pos += LPC_SHAPE_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_s[poss++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* scaling, mean addition, and gain restoration */
+ posg = 0;
+ poss = 0;
+ pos = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ /* log gains */
+ LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef[pos] = exp(LPCCoef[pos]);
+ pos++;
+ posg++;
+ LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef[pos] = exp(LPCCoef[pos]);
+ pos++;
+ posg++;
+
+ /* Low-band LAR coefficients. */
+ for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+
+ /* High-band LAR coefficients. */
+ for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+ }
+ return 0;
+}
+
+/* Encode LPC in LAR domain. */
+void WebRtcIsac_EncodeLar(double* LPCCoef, Bitstr* streamdata,
+ IsacSaveEncoderData* encData) {
+ int j, k, n, pos, pos2, poss, offss, offs2;
+ int index_s[KLT_ORDER_SHAPE];
+ int index_ovr_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs_s[KLT_ORDER_SHAPE];
+ double tmpcoeffs2_s[KLT_ORDER_SHAPE];
+ double sum;
+ const int kModel = 0;
+
+ /* Mean removal and scaling. */
+ poss = 0;
+ pos = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ /* First two element are gains, move over them. */
+ pos += 2;
+
+ /* Low-band LAR coefficients. */
+ for (n = 0; n < LPC_LOBAND_ORDER; n++, poss++, pos++) {
+ tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
+ tmpcoeffs_s[poss] *= LPC_LOBAND_SCALE;
+ }
+
+ /* High-band LAR coefficients. */
+ for (n = 0; n < LPC_HIBAND_ORDER; n++, poss++, pos++) {
+ tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
+ tmpcoeffs_s[poss] *= LPC_HIBAND_SCALE;
+ }
+ }
+
+ /* KLT */
+
+ /* Left transform. */
+ offss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = offss;
+ pos2 = k;
+ for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+ sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2];
+ pos2 += LPC_SHAPE_ORDER;
+ }
+ tmpcoeffs2_s[poss++] = sum;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Right transform. */
+ offss = 0;
+ offs2 = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2++];
+ pos += LPC_SHAPE_ORDER;
+ }
+ tmpcoeffs_s[poss++] = sum;
+ }
+ offs2 += SUBFRAMES;
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Quantize coefficients. */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ index_s[k] = (WebRtcIsac_lrint(tmpcoeffs_s[k] / KLT_STEPSIZE)) +
+ WebRtcIsac_kQKltQuantMinShape[k];
+ if (index_s[k] < 0) {
+ index_s[k] = 0;
+ } else if (index_s[k] > WebRtcIsac_kQKltMaxIndShape[k]) {
+ index_s[k] = WebRtcIsac_kQKltMaxIndShape[k];
+ }
+ index_ovr_s[k] = WebRtcIsac_kQKltOffsetShape[k] + index_s[k];
+ }
+
+
+ /* Only one model remains in this version of the code, kModel = 0. We
+ * are keeping for bit-streams to be backward compatible. */
+ /* entropy coding of model number */
+ WebRtcIsac_EncHistMulti(streamdata, &kModel, WebRtcIsac_kQKltModelCdfPtr, 1);
+
+ /* Save data for creation of multiple bit streams */
+ /* Entropy coding of quantization indices - shape only. */
+ WebRtcIsac_EncHistMulti(streamdata, index_s, WebRtcIsac_kQKltCdfPtrShape,
+ KLT_ORDER_SHAPE);
+
+ /* Save data for creation of multiple bit streams. */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ encData->LPCindex_s[KLT_ORDER_SHAPE * encData->startIdx + k] = index_s[k];
+ }
+
+ /* Find quantization levels for shape coefficients. */
+ for (k = 0; k < KLT_ORDER_SHAPE; k++) {
+ tmpcoeffs_s[k] = WebRtcIsac_kQKltLevelsShape[index_ovr_s[k]];
+ }
+ /* Inverse KLT. */
+ /* Left transform, transpose matrix.! */
+ offss = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = offss;
+ pos2 = offs2;
+ for (n = 0; n < LPC_SHAPE_ORDER; n++) {
+ sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
+ }
+ tmpcoeffs2_s[poss++] = sum;
+ offs2 += LPC_SHAPE_ORDER;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Right transform, Transpose matrix */
+ offss = 0;
+ poss = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ poss = offss;
+ for (k = 0; k < LPC_SHAPE_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
+ pos += LPC_SHAPE_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_s[poss++] = sum;
+ }
+ offss += LPC_SHAPE_ORDER;
+ }
+
+ /* Scaling, mean addition, and gain restoration. */
+ poss = 0;
+ pos = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ /* Ignore gains. */
+ pos += 2;
+
+ /* Low band LAR coefficients. */
+ for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+
+ /* High band LAR coefficients. */
+ for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
+ LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
+ LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
+ }
+ }
+}
+
+
+void WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo, double* LPCCoef_hi,
+ Bitstr* streamdata, IsacSaveEncoderData* encData) {
+ double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
+ int k;
+
+ WebRtcIsac_Poly2Lar(LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI, SUBFRAMES,
+ lars);
+ WebRtcIsac_EncodeLar(lars, streamdata, encData);
+ WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
+ SUBFRAMES);
+ /* Save data for creation of multiple bit streams (and transcoding). */
+ for (k = 0; k < (ORDERLO + 1)*SUBFRAMES; k++) {
+ encData->LPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * encData->startIdx + k] =
+ LPCCoef_lo[k];
+ }
+ for (k = 0; k < (ORDERHI + 1)*SUBFRAMES; k++) {
+ encData->LPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * encData->startIdx + k] =
+ LPCCoef_hi[k];
+ }
+}
+
+
+int16_t WebRtcIsac_EncodeLpcUB(double* lpcVecs, Bitstr* streamdata,
+ double* interpolLPCCoeff,
+ int16_t bandwidth,
+ ISACUBSaveEncDataStruct* encData) {
+ double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int idx[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int interpolCntr;
+
+ WebRtcIsac_Poly2LarUB(lpcVecs, bandwidth);
+ WebRtcIsac_RemoveLarMean(lpcVecs, bandwidth);
+ WebRtcIsac_DecorrelateIntraVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_DecorrelateInterVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_QuantizeUncorrLar(lpcVecs, idx, bandwidth);
+
+ WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+
+ switch (bandwidth) {
+ case isac12kHz: {
+ /* Store the indices to be used for multiple encoding. */
+ memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
+ UB_LPC_VEC_PER_FRAME * sizeof(int));
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb12,
+ UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
+ for (interpolCntr = 0; interpolCntr < UB_INTERPOL_SEGMENTS;
+ interpolCntr++) {
+ WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
+ kLpcVecPerSegmentUb12 + 1);
+ lpcVecs += UB_LPC_ORDER;
+ interpolLPCCoeff += (kLpcVecPerSegmentUb12 * (UB_LPC_ORDER + 1));
+ }
+ break;
+ }
+ case isac16kHz: {
+ /* Store the indices to be used for multiple encoding. */
+ memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
+ UB16_LPC_VEC_PER_FRAME * sizeof(int));
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb16,
+ UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
+ for (interpolCntr = 0; interpolCntr < UB16_INTERPOL_SEGMENTS;
+ interpolCntr++) {
+ WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
+ kLpcVecPerSegmentUb16 + 1);
+ lpcVecs += UB_LPC_ORDER;
+ interpolLPCCoeff += (kLpcVecPerSegmentUb16 * (UB_LPC_ORDER + 1));
+ }
+ break;
+ }
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+void WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo, double* LPCCoef_hi,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData) {
+ int j, k, n, pos, pos2, posg, offsg, offs2;
+ int index_g[KLT_ORDER_GAIN];
+ int index_ovr_g[KLT_ORDER_GAIN];
+ double tmpcoeffs_g[KLT_ORDER_GAIN];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN];
+ double sum;
+ /* log gains, mean removal and scaling */
+ posg = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ }
+
+ /* KLT */
+
+ /* Left transform. */
+ offsg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n = 0; n < LPC_GAIN_ORDER; n++) {
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
+ pos2 += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs2_g[posg++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Right transform. */
+ offsg = 0;
+ offs2 = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
+ pos += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ offs2 += SUBFRAMES;
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Quantize coefficients. */
+ for (k = 0; k < KLT_ORDER_GAIN; k++) {
+ /* Get index. */
+ pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
+ index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
+ if (index_g[k] < 0) {
+ index_g[k] = 0;
+ } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ }
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
+
+ /* Find quantization levels for coefficients. */
+ tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
+
+ /* Save data for creation of multiple bit streams. */
+ encData->LPCindex_g[KLT_ORDER_GAIN * encData->startIdx + k] = index_g[k];
+ }
+
+ /* Entropy coding of quantization indices - gain. */
+ WebRtcIsac_EncHistMulti(streamdata, index_g, WebRtcIsac_kQKltCdfPtrGain,
+ KLT_ORDER_GAIN);
+
+ /* Find quantization levels for coefficients. */
+ /* Left transform. */
+ offsg = 0;
+ posg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ offs2 = 0;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = offs2;
+ for (n = 0; n < LPC_GAIN_ORDER; n++)
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
+ tmpcoeffs2_g[posg++] = sum;
+ offs2 += LPC_GAIN_ORDER;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Right transform, transpose matrix. */
+ offsg = 0;
+ posg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = j;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
+ pos += LPC_GAIN_ORDER;
+ pos2 += SUBFRAMES;
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+
+ /* Scaling, mean addition, and gain restoration. */
+ posg = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ sum += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef_lo[k * (LPC_LOBAND_ORDER + 1)] = exp(sum);
+ pos++;
+ posg++;
+ sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
+ sum += WebRtcIsac_kLpcMeansGain[posg];
+ LPCCoef_hi[k * (LPC_HIBAND_ORDER + 1)] = exp(sum);
+ pos++;
+ posg++;
+ }
+
+}
+
+void WebRtcIsac_EncodeLpcGainUb(double* lpGains, Bitstr* streamdata,
+ int* lpcGainIndex) {
+ double U[UB_LPC_GAIN_DIM];
+ int idx[UB_LPC_GAIN_DIM];
+ WebRtcIsac_ToLogDomainRemoveMean(lpGains);
+ WebRtcIsac_DecorrelateLPGain(lpGains, U);
+ WebRtcIsac_QuantizeLpcGain(U, idx);
+ /* Store the index for re-encoding for FEC. */
+ memcpy(lpcGainIndex, idx, UB_LPC_GAIN_DIM * sizeof(int));
+ WebRtcIsac_CorrelateLpcGain(U, lpGains);
+ WebRtcIsac_AddMeanToLinearDomain(lpGains);
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
+ UB_LPC_GAIN_DIM);
+}
+
+
+void WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata) {
+ double U[UB_LPC_GAIN_DIM];
+ int idx[UB_LPC_GAIN_DIM];
+ WebRtcIsac_ToLogDomainRemoveMean(lpGains);
+ WebRtcIsac_DecorrelateLPGain(lpGains, U);
+ WebRtcIsac_QuantizeLpcGain(U, idx);
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
+ UB_LPC_GAIN_DIM);
+}
+
+
+
+int16_t WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata) {
+ double U[UB_LPC_GAIN_DIM];
+ int idx[UB_LPC_GAIN_DIM];
+ int err;
+ err = WebRtcIsac_DecHistOneStepMulti(idx, streamdata,
+ WebRtcIsac_kLpcGainCdfMat,
+ WebRtcIsac_kLpcGainEntropySearch,
+ UB_LPC_GAIN_DIM);
+ if (err < 0) {
+ return -1;
+ }
+ WebRtcIsac_DequantizeLpcGain(idx, U);
+ WebRtcIsac_CorrelateLpcGain(U, lpGains);
+ WebRtcIsac_AddMeanToLinearDomain(lpGains);
+ return 0;
+}
+
+
+
+/* decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr* streamdata, int16_t* RCQ15) {
+ int k, err;
+ int index[AR_ORDER];
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsac_DecHistOneStepMulti(index, streamdata,
+ WebRtcIsac_kQArRcCdfPtr,
+ WebRtcIsac_kQArRcInitIndex, AR_ORDER);
+ if (err < 0)
+ return err;
+
+ /* find quantization levels for reflection coefficients */
+ for (k = 0; k < AR_ORDER; k++) {
+ RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+ }
+ return 0;
+}
+
+
+/* quantize & code RC */
+void WebRtcIsac_EncodeRc(int16_t* RCQ15, Bitstr* streamdata) {
+ int k;
+ int index[AR_ORDER];
+
+ /* quantize reflection coefficients (add noise feedback?) */
+ for (k = 0; k < AR_ORDER; k++) {
+ index[k] = WebRtcIsac_kQArRcInitIndex[k];
+ // The safe-guards in following while conditions are to suppress gcc 4.8.3
+ // warnings, Issue 2888. Otherwise, first and last elements of
+ // `WebRtcIsac_kQArBoundaryLevels` are such that the following search
+ // *never* cause an out-of-boundary read.
+ if (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k]]) {
+ while (index[k] + 1 < NUM_AR_RC_QUANT_BAUNDARY &&
+ RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k] + 1]) {
+ index[k]++;
+ }
+ } else {
+ while (index[k] > 0 &&
+ RCQ15[k] < WebRtcIsac_kQArBoundaryLevels[--index[k]]) ;
+ }
+ RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+ }
+
+ /* entropy coding of quantization indices */
+ WebRtcIsac_EncHistMulti(streamdata, index, WebRtcIsac_kQArRcCdfPtr, AR_ORDER);
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr* streamdata, int32_t* gainQ10) {
+ int index, err;
+
+ /* entropy decoding of quantization index */
+ err = WebRtcIsac_DecHistOneStepMulti(&index, streamdata,
+ WebRtcIsac_kQGainCdf_ptr,
+ WebRtcIsac_kQGainInitIndex, 1);
+ if (err < 0) {
+ return err;
+ }
+ /* find quantization level */
+ *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+ return 0;
+}
+
+
+/* quantize & code squared Gain */
+int WebRtcIsac_EncodeGain2(int32_t* gainQ10, Bitstr* streamdata) {
+ int index;
+
+ /* find quantization index */
+ index = WebRtcIsac_kQGainInitIndex[0];
+ if (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index]) {
+ while (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index + 1]) {
+ index++;
+ }
+ } else {
+ while (*gainQ10 < WebRtcIsac_kQGain2BoundaryLevels[--index]) ;
+ }
+ /* De-quantize */
+ *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+
+ /* entropy coding of quantization index */
+ WebRtcIsac_EncHistMulti(streamdata, &index, WebRtcIsac_kQGainCdf_ptr, 1);
+ return 0;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsac_DecodePitchGain(Bitstr* streamdata,
+ int16_t* PitchGains_Q12) {
+ int index_comb, err;
+ const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
+
+ /* Entropy decoding of quantization indices */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ err = WebRtcIsac_DecHistBisectMulti(&index_comb, streamdata,
+ WebRtcIsac_kQPitchGainCdf_ptr,
+ WebRtcIsac_kQCdfTableSizeGain, 1);
+ /* Error check, Q_mean_Gain.. tables are of size 144 */
+ if ((err < 0) || (index_comb < 0) || (index_comb >= 144)) {
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
+ }
+ /* De-quantize back to pitch gains by table look-up. */
+ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+ PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+ PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+ PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+ return 0;
+}
+
+
+/* Quantize & code Pitch Gains. */
+void WebRtcIsac_EncodePitchGain(int16_t* PitchGains_Q12,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData) {
+ int k, j;
+ double C;
+ double S[PITCH_SUBFRAMES];
+ int index[3];
+ int index_comb;
+ const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
+ double PitchGains[PITCH_SUBFRAMES] = {0, 0, 0, 0};
+
+ /* Take the asin. */
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
+ S[k] = asin(PitchGains[k]);
+ }
+
+ /* Find quantization index; only for the first three
+ * transform coefficients. */
+ for (k = 0; k < 3; k++) {
+ /* transform */
+ C = 0.0;
+ for (j = 0; j < PITCH_SUBFRAMES; j++) {
+ C += WebRtcIsac_kTransform[k][j] * S[j];
+ }
+ /* Quantize */
+ index[k] = WebRtcIsac_lrint(C / PITCH_GAIN_STEPSIZE);
+
+ /* Check that the index is not outside the boundaries of the table. */
+ if (index[k] < WebRtcIsac_kIndexLowerLimitGain[k]) {
+ index[k] = WebRtcIsac_kIndexLowerLimitGain[k];
+ } else if (index[k] > WebRtcIsac_kIndexUpperLimitGain[k]) {
+ index[k] = WebRtcIsac_kIndexUpperLimitGain[k];
+ }
+ index[k] -= WebRtcIsac_kIndexLowerLimitGain[k];
+ }
+
+ /* Calculate unique overall index. */
+ index_comb = WebRtcIsac_kIndexMultsGain[0] * index[0] +
+ WebRtcIsac_kIndexMultsGain[1] * index[1] + index[2];
+
+ /* unquantize back to pitch gains by table look-up */
+ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+ PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+ PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+ PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+
+ /* entropy coding of quantization pitch gains */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ WebRtcIsac_EncHistMulti(streamdata, &index_comb,
+ WebRtcIsac_kQPitchGainCdf_ptr, 1);
+ encData->pitchGain_index[encData->startIdx] = index_comb;
+}
+
+
+
+/* Pitch LAG */
+/* Decode & de-quantize Pitch Lags. */
+int WebRtcIsac_DecodePitchLag(Bitstr* streamdata, int16_t* PitchGain_Q12,
+ double* PitchLags) {
+ int k, err;
+ double StepSize;
+ double C;
+ int index[PITCH_SUBFRAMES];
+ double mean_gain;
+ const double* mean_val2, *mean_val3, *mean_val4;
+ const int16_t* lower_limit;
+ const uint16_t* init_index;
+ const uint16_t* cdf_size;
+ const uint16_t** cdf;
+ double PitchGain[4] = {0, 0, 0, 0};
+
+ /* compute mean pitch gain */
+ mean_gain = 0.0;
+ for (k = 0; k < 4; k++) {
+ PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
+ mean_gain += PitchGain[k];
+ }
+ mean_gain /= 4.0;
+
+ /* voicing classification. */
+ if (mean_gain < 0.2) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeLo;
+ mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+ mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+ mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+ init_index = WebRtcIsac_kQInitIndexLagLo;
+ } else if (mean_gain < 0.4) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeMid;
+ mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+ mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+ mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+ init_index = WebRtcIsac_kQInitIndexLagMid;
+ } else {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeHi;
+ mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+ mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+ mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+ lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+ init_index = WebRtcIsac_kQInitIndexLagHi;
+ }
+
+ /* Entropy decoding of quantization indices. */
+ err = WebRtcIsac_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+ if ((err < 0) || (index[0] < 0)) {
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+ }
+ err = WebRtcIsac_DecHistOneStepMulti(index + 1, streamdata, cdf + 1,
+ init_index, 3);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+ }
+
+ /* Unquantize back to transform coefficients and do the inverse transform:
+ * S = T'*C. */
+ C = (index[0] + lower_limit[0]) * StepSize;
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
+ }
+ C = mean_val2[index[1]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
+ }
+ C = mean_val3[index[2]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
+ }
+ C = mean_val4[index[3]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
+ }
+ return 0;
+}
+
+
+
+/* Quantize & code pitch lags. */
+void WebRtcIsac_EncodePitchLag(double* PitchLags, int16_t* PitchGain_Q12,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData) {
+ int k, j;
+ double StepSize;
+ double C;
+ int index[PITCH_SUBFRAMES];
+ double mean_gain;
+ const double* mean_val2, *mean_val3, *mean_val4;
+ const int16_t* lower_limit, *upper_limit;
+ const uint16_t** cdf;
+ double PitchGain[4] = {0, 0, 0, 0};
+
+ /* compute mean pitch gain */
+ mean_gain = 0.0;
+ for (k = 0; k < 4; k++) {
+ PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
+ mean_gain += PitchGain[k];
+ }
+ mean_gain /= 4.0;
+
+ /* Save data for creation of multiple bit streams */
+ encData->meanGain[encData->startIdx] = mean_gain;
+
+ /* Voicing classification. */
+ if (mean_gain < 0.2) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+ mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+ mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+ upper_limit = WebRtcIsac_kQIndexUpperLimitLagLo;
+ } else if (mean_gain < 0.4) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+ mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+ mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+ upper_limit = WebRtcIsac_kQIndexUpperLimitLagMid;
+ } else {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+ mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+ mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+ lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+ upper_limit = WebRtcIsac_kQindexUpperLimitLagHi;
+ }
+
+ /* find quantization index */
+ for (k = 0; k < 4; k++) {
+ /* transform */
+ C = 0.0;
+ for (j = 0; j < PITCH_SUBFRAMES; j++) {
+ C += WebRtcIsac_kTransform[k][j] * PitchLags[j];
+ }
+ /* quantize */
+ index[k] = WebRtcIsac_lrint(C / StepSize);
+
+ /* check that the index is not outside the boundaries of the table */
+ if (index[k] < lower_limit[k]) {
+ index[k] = lower_limit[k];
+ } else if (index[k] > upper_limit[k]) index[k] = upper_limit[k]; {
+ index[k] -= lower_limit[k];
+ }
+ /* Save data for creation of multiple bit streams */
+ encData->pitchIndex[PITCH_SUBFRAMES * encData->startIdx + k] = index[k];
+ }
+
+ /* Un-quantize back to transform coefficients and do the inverse transform:
+ * S = T'*C */
+ C = (index[0] + lower_limit[0]) * StepSize;
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
+ }
+ C = mean_val2[index[1]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
+ }
+ C = mean_val3[index[2]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
+ }
+ C = mean_val4[index[3]];
+ for (k = 0; k < PITCH_SUBFRAMES; k++) {
+ PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
+ }
+ /* entropy coding of quantization pitch lags */
+ WebRtcIsac_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
+}
+
+
+
+/* Routines for in-band signaling of bandwidth estimation */
+/* Histograms based on uniform distribution of indices */
+/* Move global variables later! */
+
+
+/* cdf array for frame length indicator */
+const uint16_t WebRtcIsac_kFrameLengthCdf[4] = {
+ 0, 21845, 43690, 65535 };
+
+/* pointer to cdf array for frame length indicator */
+const uint16_t* WebRtcIsac_kFrameLengthCdf_ptr[1] = {
+ WebRtcIsac_kFrameLengthCdf };
+
+/* initial cdf index for decoder of frame length indicator */
+const uint16_t WebRtcIsac_kFrameLengthInitIndex[1] = { 1 };
+
+
+int WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, int16_t* framesamples) {
+ int frame_mode, err;
+ err = 0;
+ /* entropy decoding of frame length [1:30ms,2:60ms] */
+ err = WebRtcIsac_DecHistOneStepMulti(&frame_mode, streamdata,
+ WebRtcIsac_kFrameLengthCdf_ptr,
+ WebRtcIsac_kFrameLengthInitIndex, 1);
+ if (err < 0)
+ return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
+
+ switch (frame_mode) {
+ case 1:
+ *framesamples = 480; /* 30ms */
+ break;
+ case 2:
+ *framesamples = 960; /* 60ms */
+ break;
+ default:
+ err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
+ }
+ return err;
+}
+
+int WebRtcIsac_EncodeFrameLen(int16_t framesamples, Bitstr* streamdata) {
+ int frame_mode, status;
+
+ status = 0;
+ frame_mode = 0;
+ /* entropy coding of frame length [1:480 samples,2:960 samples] */
+ switch (framesamples) {
+ case 480:
+ frame_mode = 1;
+ break;
+ case 960:
+ frame_mode = 2;
+ break;
+ default:
+ status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
+ }
+
+ if (status < 0)
+ return status;
+
+ WebRtcIsac_EncHistMulti(streamdata, &frame_mode,
+ WebRtcIsac_kFrameLengthCdf_ptr, 1);
+ return status;
+}
+
+/* cdf array for estimated bandwidth */
+static const uint16_t kBwCdf[25] = {
+ 0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
+ 32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
+ 62804, 65535 };
+
+/* pointer to cdf array for estimated bandwidth */
+static const uint16_t* const kBwCdfPtr[1] = { kBwCdf };
+
+/* initial cdf index for decoder of estimated bandwidth*/
+static const uint16_t kBwInitIndex[1] = { 7 };
+
+
+int WebRtcIsac_DecodeSendBW(Bitstr* streamdata, int16_t* BWno) {
+ int BWno32, err;
+
+ /* entropy decoding of sender's BW estimation [0..23] */
+ err = WebRtcIsac_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr,
+ kBwInitIndex, 1);
+ if (err < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
+ }
+ *BWno = (int16_t)BWno32;
+ return err;
+}
+
+void WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata) {
+ /* entropy encoding of receiver's BW estimation [0..23] */
+ WebRtcIsac_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
+}
+
+
+/* estimate code length of LPC Coef */
+void WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo, double* LPCCoef_hi,
+ int* index_g) {
+ int j, k, n, pos, pos2, posg, offsg, offs2;
+ int index_ovr_g[KLT_ORDER_GAIN];
+ double tmpcoeffs_g[KLT_ORDER_GAIN];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN];
+ double sum;
+
+ /* log gains, mean removal and scaling */
+ posg = 0;
+ for (k = 0; k < SUBFRAMES; k++) {
+ tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
+ tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
+ tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
+ posg++;
+ }
+
+ /* KLT */
+
+ /* Left transform. */
+ offsg = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = offsg;
+ pos2 = k;
+ for (n = 0; n < LPC_GAIN_ORDER; n++) {
+ sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
+ pos2 += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs2_g[posg++] = sum;
+ }
+ offsg += LPC_GAIN_ORDER;
+ }
+
+ /* Right transform. */
+ offsg = 0;
+ offs2 = 0;
+ for (j = 0; j < SUBFRAMES; j++) {
+ posg = offsg;
+ for (k = 0; k < LPC_GAIN_ORDER; k++) {
+ sum = 0;
+ pos = k;
+ pos2 = offs2;
+ for (n = 0; n < SUBFRAMES; n++) {
+ sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
+ pos += LPC_GAIN_ORDER;
+ }
+ tmpcoeffs_g[posg++] = sum;
+ }
+ offs2 += SUBFRAMES;
+ offsg += LPC_GAIN_ORDER;
+ }
+
+
+ /* quantize coefficients */
+ for (k = 0; k < KLT_ORDER_GAIN; k++) {
+ /* Get index. */
+ pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
+ index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
+ if (index_g[k] < 0) {
+ index_g[k] = 0;
+ } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ }
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
+
+ /* find quantization levels for coefficients */
+ tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
+ }
+}
+
+
+/* Decode & de-quantize LPC Coefficients. */
+int WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata, double* lpcVecs,
+ double* percepFilterGains,
+ int16_t bandwidth) {
+ int index_s[KLT_ORDER_SHAPE];
+
+ double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int err;
+
+ /* Entropy decoding of quantization indices. */
+ switch (bandwidth) {
+ case isac12kHz: {
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb12,
+ WebRtcIsac_kLpcShapeEntropySearchUb12, UB_LPC_ORDER *
+ UB_LPC_VEC_PER_FRAME);
+ break;
+ }
+ case isac16kHz: {
+ err = WebRtcIsac_DecHistOneStepMulti(
+ index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb16,
+ WebRtcIsac_kLpcShapeEntropySearchUb16, UB_LPC_ORDER *
+ UB16_LPC_VEC_PER_FRAME);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if (err < 0) {
+ return err;
+ }
+
+ WebRtcIsac_DequantizeLpcParam(index_s, lpcVecs, bandwidth);
+ WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+ WebRtcIsac_DecodeLpcGainUb(percepFilterGains, streamdata);
+
+ if (bandwidth == isac16kHz) {
+ /* Decode another set of Gains. */
+ WebRtcIsac_DecodeLpcGainUb(&percepFilterGains[SUBFRAMES], streamdata);
+ }
+ return 0;
+}
+
+int16_t WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
+ Bitstr* streamData) {
+ int bandwidthMode;
+ switch (bandwidth) {
+ case isac12kHz: {
+ bandwidthMode = 0;
+ break;
+ }
+ case isac16kHz: {
+ bandwidthMode = 1;
+ break;
+ }
+ default:
+ return -ISAC_DISALLOWED_ENCODER_BANDWIDTH;
+ }
+ WebRtcIsac_EncHistMulti(streamData, &bandwidthMode, kOneBitEqualProbCdf_ptr,
+ 1);
+ return 0;
+}
+
+int16_t WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
+ enum ISACBandwidth* bandwidth) {
+ int bandwidthMode;
+ if (WebRtcIsac_DecHistOneStepMulti(&bandwidthMode, streamData,
+ kOneBitEqualProbCdf_ptr,
+ kOneBitEqualProbInitIndex, 1) < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+ }
+ switch (bandwidthMode) {
+ case 0: {
+ *bandwidth = isac12kHz;
+ break;
+ }
+ case 1: {
+ *bandwidth = isac16kHz;
+ break;
+ }
+ default:
+ return -ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER;
+ }
+ return 0;
+}
+
+int16_t WebRtcIsac_EncodeJitterInfo(int32_t jitterIndex,
+ Bitstr* streamData) {
+ /* This is to avoid LINUX warning until we change 'int' to 'Word32'. */
+ int intVar;
+
+ if ((jitterIndex < 0) || (jitterIndex > 1)) {
+ return -1;
+ }
+ intVar = (int)(jitterIndex);
+ /* Use the same CDF table as for bandwidth
+ * both take two values with equal probability.*/
+ WebRtcIsac_EncHistMulti(streamData, &intVar, kOneBitEqualProbCdf_ptr, 1);
+ return 0;
+}
+
+int16_t WebRtcIsac_DecodeJitterInfo(Bitstr* streamData,
+ int32_t* jitterInfo) {
+ int intVar;
+ /* Use the same CDF table as for bandwidth
+ * both take two values with equal probability. */
+ if (WebRtcIsac_DecHistOneStepMulti(&intVar, streamData,
+ kOneBitEqualProbCdf_ptr,
+ kOneBitEqualProbInitIndex, 1) < 0) {
+ return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+ }
+ *jitterInfo = (int16_t)(intVar);
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.h
new file mode 100644
index 0000000000..6c2b8d3cc1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/entropy_coding.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file declares all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpec()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ * - AvgPitchGain_Q12 : average pitch-gain of the frame. This is only
+ * relevant for 0-4 kHz band, and the input value is
+ * not used in other bands.
+ * - band : specifies which band's DFT should be decoded.
+ *
+ * Output:
+ * - *fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * - *fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpec(Bitstr* streamdata,
+ int16_t AvgPitchGain_Q12,
+ enum ISACBand band,
+ double* fr,
+ double* fi);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeSpec()
+ * Encode real and imaginary part of the DFT coefficients into the given
+ * bit-stream.
+ *
+ * Input:
+ * - *fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * - *fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ * - AvgPitchGain_Q12 : average pitch-gain of the frame. This is only
+ * relevant for 0-4 kHz band, and the input value is
+ * not used in other bands.
+ * - band : specifies which band's DFT should be decoded.
+ *
+ * Output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_EncodeSpec(const int16_t* fr,
+ const int16_t* fi,
+ int16_t AvgPitchGain_Q12,
+ enum ISACBand band,
+ Bitstr* streamdata);
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef);
+int WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata,
+ double* lpcVecs,
+ double* percepFilterGains,
+ int16_t bandwidth);
+
+int WebRtcIsac_DecodeLpc(Bitstr* streamdata,
+ double* LPCCoef_lo,
+ double* LPCCoef_hi);
+
+/* quantize & code LPC Coef */
+void WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo,
+ double* LPCCoef_hi,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData);
+
+void WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo,
+ double* LPCCoef_hi,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcUB()
+ * Encode LPC parameters, given as A-polynomial, of upper-band. The encoding
+ * is performed in LAR domain.
+ * For the upper-band, we compute and encode LPC of some sub-frames, LPC of
+ * other sub-frames are computed by linear interpolation, in LAR domain. This
+ * function performs the interpolation and returns the LPC of all sub-frames.
+ *
+ * Inputs:
+ * - lpcCoef : a buffer containing A-polynomials of sub-frames
+ * (excluding first coefficient that is 1).
+ * - bandwidth : specifies if the codec is operating at 0-12 kHz
+ * or 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a structure containing the encoded
+ * data and the parameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - interpolLPCCoeff : Decoded and interpolated LPC (A-polynomial)
+ * of all sub-frames.
+ * If LP analysis is of order K, and there are N
+ * sub-frames then this is a buffer of size
+ * (k + 1) * N, each vector starts with the LPC gain
+ * of the corresponding sub-frame. The LPC gains
+ * are encoded and inserted after this function is
+ * called. The first A-coefficient which is 1 is not
+ * included.
+ *
+ * Return value : 0 if encoding is successful,
+ * <0 if failed to encode.
+ */
+int16_t WebRtcIsac_EncodeLpcUB(double* lpcCoeff,
+ Bitstr* streamdata,
+ double* interpolLPCCoeff,
+ int16_t bandwidth,
+ ISACUBSaveEncDataStruct* encData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeInterpolLpcUb()
+ * Decode LPC coefficients and interpolate to get the coefficients fo all
+ * sub-frmaes.
+ *
+ * Inputs:
+ * - bandwidth : spepecifies if the codec is in 0-12 kHz or
+ * 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - percepFilterParam : Decoded and interpolated LPC (A-polynomial) of
+ * all sub-frames.
+ * If LP analysis is of order K, and there are N
+ * sub-frames then this is a buffer of size
+ * (k + 1) * N, each vector starts with the LPC gain
+ * of the corresponding sub-frame. The LPC gains
+ * are encoded and inserted after this function is
+ * called. The first A-coefficient which is 1 is not
+ * included.
+ *
+ * Return value : 0 if encoding is successful,
+ * <0 if failed to encode.
+ */
+int16_t WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
+ double* percepFilterParam,
+ int16_t bandwidth);
+
+/* Decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr* streamdata, int16_t* RCQ15);
+
+/* Quantize & code RC */
+void WebRtcIsac_EncodeRc(int16_t* RCQ15, Bitstr* streamdata);
+
+/* Decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr* streamdata, int32_t* Gain2);
+
+/* Quantize & code squared Gain (input is squared gain) */
+int WebRtcIsac_EncodeGain2(int32_t* gain2, Bitstr* streamdata);
+
+void WebRtcIsac_EncodePitchGain(int16_t* PitchGains_Q12,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData);
+
+void WebRtcIsac_EncodePitchLag(double* PitchLags,
+ int16_t* PitchGain_Q12,
+ Bitstr* streamdata,
+ IsacSaveEncoderData* encData);
+
+int WebRtcIsac_DecodePitchGain(Bitstr* streamdata, int16_t* PitchGain_Q12);
+int WebRtcIsac_DecodePitchLag(Bitstr* streamdata,
+ int16_t* PitchGain_Q12,
+ double* PitchLag);
+
+int WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, int16_t* framelength);
+int WebRtcIsac_EncodeFrameLen(int16_t framelength, Bitstr* streamdata);
+int WebRtcIsac_DecodeSendBW(Bitstr* streamdata, int16_t* BWno);
+void WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata);
+
+/* Step-down */
+void WebRtcIsac_Poly2Rc(double* a, int N, double* RC);
+
+/* Step-up */
+void WebRtcIsac_Rc2Poly(double* RC, int N, double* a);
+
+void WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo,
+ double* LPCCoef_hi,
+ int* index_g);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Encode LPC gains of sub-Frames.
+ *
+ * Input/outputs:
+ * - lpGains : a buffer which contains 'SUBFRAME' number of
+ * LP gains to be encoded. The input values are
+ * overwritten by the quantized values.
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - lpcGainIndex : quantization indices for lpc gains, these will
+ * be stored to be used for FEC.
+ */
+void WebRtcIsac_EncodeLpcGainUb(double* lpGains,
+ Bitstr* streamdata,
+ int* lpcGainIndex);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Store LPC gains of sub-Frames in 'streamdata'.
+ *
+ * Input:
+ * - lpGains : a buffer which contains 'SUBFRAME' number of
+ * LP gains to be encoded.
+ * Input/outputs:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ */
+void WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeLpcGainUb()
+ * Decode the LPC gain of sub-frames.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - lpGains : a buffer where decoded LPC gians will be stored.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+int16_t WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeBandwidth()
+ * Encode if the bandwidth of encoded audio is 0-12 kHz or 0-16 kHz.
+ *
+ * Input:
+ * - bandwidth : an enumerator specifying if the codec in is
+ * 0-12 kHz or 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+int16_t WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
+ Bitstr* streamData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeBandwidth()
+ * Decode the bandwidth of the encoded audio, i.e. if the bandwidth is 0-12 kHz
+ * or 0-16 kHz.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - bandwidth : an enumerator specifying if the codec is in
+ * 0-12 kHz or 0-16 kHz mode.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+int16_t WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
+ enum ISACBandwidth* bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Input:
+ * - jitterInfo : one bit of info specifying if the channel is
+ * in high/low jitter. Zero indicates low jitter
+ * and one indicates high jitter.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+int16_t WebRtcIsac_EncodeJitterInfo(int32_t jitterIndex, Bitstr* streamData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - jitterInfo : one bit of info specifying if the channel is
+ * in high/low jitter. Zero indicates low jitter
+ * and one indicates high jitter.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+int16_t WebRtcIsac_DecodeJitterInfo(Bitstr* streamData, int32_t* jitterInfo);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.c
new file mode 100644
index 0000000000..a4f297c5a1
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory.h>
+#include <string.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+
+static void WebRtcIsac_AllPoleFilter(double* InOut,
+ double* Coef,
+ size_t lengthInOut,
+ int orderCoef) {
+ /* the state of filter is assumed to be in InOut[-1] to InOut[-orderCoef] */
+ double scal;
+ double sum;
+ size_t n;
+ int k;
+
+ //if (fabs(Coef[0]-1.0)<0.001) {
+ if ( (Coef[0] > 0.9999) && (Coef[0] < 1.0001) )
+ {
+ for(n = 0; n < lengthInOut; n++)
+ {
+ sum = Coef[1] * InOut[-1];
+ for(k = 2; k <= orderCoef; k++){
+ sum += Coef[k] * InOut[-k];
+ }
+ *InOut++ -= sum;
+ }
+ }
+ else
+ {
+ scal = 1.0 / Coef[0];
+ for(n=0;n<lengthInOut;n++)
+ {
+ *InOut *= scal;
+ for(k=1;k<=orderCoef;k++){
+ *InOut -= scal*Coef[k]*InOut[-k];
+ }
+ InOut++;
+ }
+ }
+}
+
+static void WebRtcIsac_AllZeroFilter(double* In,
+ double* Coef,
+ size_t lengthInOut,
+ int orderCoef,
+ double* Out) {
+ /* the state of filter is assumed to be in In[-1] to In[-orderCoef] */
+
+ size_t n;
+ int k;
+ double tmp;
+
+ for(n = 0; n < lengthInOut; n++)
+ {
+ tmp = In[0] * Coef[0];
+
+ for(k = 1; k <= orderCoef; k++){
+ tmp += Coef[k] * In[-k];
+ }
+
+ *Out++ = tmp;
+ In++;
+ }
+}
+
+static void WebRtcIsac_ZeroPoleFilter(double* In,
+ double* ZeroCoef,
+ double* PoleCoef,
+ size_t lengthInOut,
+ int orderCoef,
+ double* Out) {
+ /* the state of the zero section is assumed to be in In[-1] to In[-orderCoef] */
+ /* the state of the pole section is assumed to be in Out[-1] to Out[-orderCoef] */
+
+ WebRtcIsac_AllZeroFilter(In,ZeroCoef,lengthInOut,orderCoef,Out);
+ WebRtcIsac_AllPoleFilter(Out,PoleCoef,lengthInOut,orderCoef);
+}
+
+
+void WebRtcIsac_AutoCorr(double* r, const double* x, size_t N, size_t order) {
+ size_t lag, n;
+ double sum, prod;
+ const double *x_lag;
+
+ for (lag = 0; lag <= order; lag++)
+ {
+ sum = 0.0f;
+ x_lag = &x[lag];
+ prod = x[0] * x_lag[0];
+ for (n = 1; n < N - lag; n++) {
+ sum += prod;
+ prod = x[n] * x_lag[n];
+ }
+ sum += prod;
+ r[lag] = sum;
+ }
+
+}
+
+static void WebRtcIsac_BwExpand(double* out,
+ double* in,
+ double coef,
+ size_t length) {
+ size_t i;
+ double chirp;
+
+ chirp = coef;
+
+ out[0] = in[0];
+ for (i = 1; i < length; i++) {
+ out[i] = chirp * in[i];
+ chirp *= coef;
+ }
+}
+
+void WebRtcIsac_WeightingFilter(const double* in,
+ double* weiout,
+ double* whiout,
+ WeightFiltstr* wfdata) {
+ double tmpbuffer[PITCH_FRAME_LEN + PITCH_WLPCBUFLEN];
+ double corr[PITCH_WLPCORDER+1], rc[PITCH_WLPCORDER+1];
+ double apol[PITCH_WLPCORDER+1], apolr[PITCH_WLPCORDER+1];
+ double rho=0.9, *inp, *dp, *dp2;
+ double whoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER];
+ double weoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER];
+ double *weo, *who, opol[PITCH_WLPCORDER+1], ext[PITCH_WLPCWINLEN];
+ int k, n, endpos, start;
+
+ /* Set up buffer and states */
+ memcpy(tmpbuffer, wfdata->buffer, sizeof(double) * PITCH_WLPCBUFLEN);
+ memcpy(tmpbuffer+PITCH_WLPCBUFLEN, in, sizeof(double) * PITCH_FRAME_LEN);
+ memcpy(wfdata->buffer, tmpbuffer+PITCH_FRAME_LEN, sizeof(double) * PITCH_WLPCBUFLEN);
+
+ dp=weoutbuf;
+ dp2=whoutbuf;
+ for (k=0;k<PITCH_WLPCORDER;k++) {
+ *dp++ = wfdata->weostate[k];
+ *dp2++ = wfdata->whostate[k];
+ opol[k]=0.0;
+ }
+ opol[0]=1.0;
+ opol[PITCH_WLPCORDER]=0.0;
+ weo=dp;
+ who=dp2;
+
+ endpos=PITCH_WLPCBUFLEN + PITCH_SUBFRAME_LEN;
+ inp=tmpbuffer + PITCH_WLPCBUFLEN;
+
+ for (n=0; n<PITCH_SUBFRAMES; n++) {
+ /* Windowing */
+ start=endpos-PITCH_WLPCWINLEN;
+ for (k=0; k<PITCH_WLPCWINLEN; k++) {
+ ext[k]=wfdata->window[k]*tmpbuffer[start+k];
+ }
+
+ /* Get LPC polynomial */
+ WebRtcIsac_AutoCorr(corr, ext, PITCH_WLPCWINLEN, PITCH_WLPCORDER);
+ corr[0]=1.01*corr[0]+1.0; /* White noise correction */
+ WebRtcIsac_LevDurb(apol, rc, corr, PITCH_WLPCORDER);
+ WebRtcIsac_BwExpand(apolr, apol, rho, PITCH_WLPCORDER+1);
+
+ /* Filtering */
+ WebRtcIsac_ZeroPoleFilter(inp, apol, apolr, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, weo);
+ WebRtcIsac_ZeroPoleFilter(inp, apolr, opol, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, who);
+
+ inp+=PITCH_SUBFRAME_LEN;
+ endpos+=PITCH_SUBFRAME_LEN;
+ weo+=PITCH_SUBFRAME_LEN;
+ who+=PITCH_SUBFRAME_LEN;
+ }
+
+ /* Export filter states */
+ for (k=0;k<PITCH_WLPCORDER;k++) {
+ wfdata->weostate[k]=weoutbuf[PITCH_FRAME_LEN+k];
+ wfdata->whostate[k]=whoutbuf[PITCH_FRAME_LEN+k];
+ }
+
+ /* Export output data */
+ memcpy(weiout, weoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN);
+ memcpy(whiout, whoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.h
new file mode 100644
index 0000000000..48a9b7426b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filter_functions.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTER_FUNCTIONS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTER_FUNCTIONS_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+void WebRtcIsac_AutoCorr(double* r, const double* x, size_t N, size_t order);
+
+void WebRtcIsac_WeightingFilter(const double* in,
+ double* weiout,
+ double* whiout,
+ WeightFiltstr* wfdata);
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTER_FUNCTIONS_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filterbanks.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filterbanks.c
new file mode 100644
index 0000000000..d57b55022d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/filterbanks.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function WebRtcIsac_AllPassFilter2Float,
+ * WebRtcIsac_SplitAndFilter, and WebRtcIsac_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+
+/* Combining */
+
+/* HPstcoeff_out_1 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefOut1Float[4] =
+{-1.99701049409000f, 0.99714204490000f, 0.01701049409000f, -0.01704204490000f};
+
+/* HPstcoeff_out_2 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+static const float kHpStCoefOut2Float[4] =
+{-1.98645294509837f, 0.98672435560000f, 0.00645294509837f, -0.00662435560000f};
+
+
+/* Function WebRtcIsac_FilterAndCombine */
+/* This is a decoder function that takes the decimated
+ length FRAMESAMPLES_HALF input low-pass and
+ high-pass signals and creates a reconstructed fullband
+ output signal of length FRAMESAMPLES. WebRtcIsac_FilterAndCombine
+ is the sibling function of WebRtcIsac_SplitAndFilter */
+/* INPUTS:
+ inLP: a length FRAMESAMPLES_HALF array of input low-pass
+ samples.
+ inHP: a length FRAMESAMPLES_HALF array of input high-pass
+ samples.
+ postfiltdata: input data structure containing the filterbank
+ states from the previous decoding iteration.
+ OUTPUTS:
+ Out: a length FRAMESAMPLES array of output reconstructed
+ samples (fullband) based on the input low-pass and
+ high-pass signals.
+ postfiltdata: the input data structure containing the filterbank
+ states is updated for the next decoding iteration */
+void WebRtcIsac_FilterAndCombineFloat(float *InLP,
+ float *InHP,
+ float *Out,
+ PostFiltBankstr *postfiltdata)
+{
+ int k;
+ float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float ftmp, ftmp2;
+
+ /* Form the polyphase signals*/
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ tempin_ch1[k]=InLP[k]+InHP[k]; /* Construct a new upper channel signal*/
+ tempin_ch2[k]=InLP[k]-InHP[k]; /* Construct a new lower channel signal*/
+ }
+
+
+ /* all-pass filter the new upper channel signal. HOWEVER, use the all-pass filter factors
+ that were used as a lower channel at the encoding side. So at the decoder, the
+ corresponding all-pass filter factors for each channel are swapped.*/
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_float);
+
+ /* Now, all-pass filter the new lower channel signal. But since all-pass filter factors
+ at the decoder are swapped from the ones at the encoder, the 'upper' channel
+ all-pass filter factors (WebRtcIsac_kUpperApFactorsFloat) are used to filter this new
+ lower channel signal */
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float);
+
+
+ /* Merge outputs to form the full length output signal.*/
+ for (k=0;k<FRAMESAMPLES_HALF;k++) {
+ Out[2*k]=tempin_ch2[k];
+ Out[2*k+1]=tempin_ch1[k];
+ }
+
+
+ /* High pass filter */
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ ftmp2 = Out[k] + kHpStCoefOut1Float[2] * postfiltdata->HPstates1_float[0] +
+ kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1];
+ ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] -
+ kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1];
+ postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0];
+ postfiltdata->HPstates1_float[0] = ftmp;
+ Out[k] = ftmp2;
+ }
+
+ for (k=0;k<FRAMESAMPLES;k++) {
+ ftmp2 = Out[k] + kHpStCoefOut2Float[2] * postfiltdata->HPstates2_float[0] +
+ kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1];
+ ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] -
+ kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1];
+ postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0];
+ postfiltdata->HPstates2_float[0] = ftmp;
+ Out[k] = ftmp2;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/intialize.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/intialize.c
new file mode 100644
index 0000000000..5c951f6e9d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/intialize.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* encode.c - Encoding function for the iSAC coder */
+
+#include <math.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+
+void WebRtcIsac_InitMasking(MaskFiltstr *maskdata) {
+
+ int k;
+
+ for (k = 0; k < WINLEN; k++) {
+ maskdata->DataBufferLo[k] = 0.0;
+ maskdata->DataBufferHi[k] = 0.0;
+ }
+ for (k = 0; k < ORDERLO+1; k++) {
+ maskdata->CorrBufLo[k] = 0.0;
+ maskdata->PreStateLoF[k] = 0.0;
+ maskdata->PreStateLoG[k] = 0.0;
+ maskdata->PostStateLoF[k] = 0.0;
+ maskdata->PostStateLoG[k] = 0.0;
+ }
+ for (k = 0; k < ORDERHI+1; k++) {
+ maskdata->CorrBufHi[k] = 0.0;
+ maskdata->PreStateHiF[k] = 0.0;
+ maskdata->PreStateHiG[k] = 0.0;
+ maskdata->PostStateHiF[k] = 0.0;
+ maskdata->PostStateHiG[k] = 0.0;
+ }
+
+ maskdata->OldEnergy = 10.0;
+ return;
+}
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+ int k;
+
+ for (k = 0; k < 2*POSTQORDER; k++) {
+ postfiltdata->STATE_0_LOWER[k] = 0;
+ postfiltdata->STATE_0_UPPER[k] = 0;
+
+ postfiltdata->STATE_0_LOWER_float[k] = 0;
+ postfiltdata->STATE_0_UPPER_float[k] = 0;
+ }
+
+ /* High pass filter states */
+ postfiltdata->HPstates1[0] = 0.0;
+ postfiltdata->HPstates1[1] = 0.0;
+
+ postfiltdata->HPstates2[0] = 0.0;
+ postfiltdata->HPstates2[1] = 0.0;
+
+ postfiltdata->HPstates1_float[0] = 0.0f;
+ postfiltdata->HPstates1_float[1] = 0.0f;
+
+ postfiltdata->HPstates2_float[0] = 0.0f;
+ postfiltdata->HPstates2_float[1] = 0.0f;
+
+ return;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac.c
new file mode 100644
index 0000000000..456f447d9a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac.c
@@ -0,0 +1,2307 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * isac.c
+ *
+ * This C file contains the functions for the ISAC API
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rtc_base/checks.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/crc.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+#include "rtc_base/system/arch.h"
+
+#define BIT_MASK_DEC_INIT 0x0001
+#define BIT_MASK_ENC_INIT 0x0002
+
+#define LEN_CHECK_SUM_WORD8 4
+#define MAX_NUM_LAYERS 10
+
+
+/****************************************************************************
+ * UpdatePayloadSizeLimit(...)
+ *
+ * Call this function to update the limit on the payload size. The limit on
+ * payload size might change i) if a user ''directly changes the limit by
+ * calling xxx_setMaxPayloadSize() or xxx_setMaxRate(), or ii) indirectly
+ * when bandwidth is changing. The latter might be the result of bandwidth
+ * adaptation, or direct change of the bottleneck in instantaneous mode.
+ *
+ * This function takes the current overall limit on payload, and translates it
+ * to the limits on lower and upper-band. If the codec is in wideband mode,
+ * then the overall limit and the limit on the lower-band is the same.
+ * Otherwise, a fraction of the limit should be allocated to lower-band
+ * leaving some room for the upper-band bit-stream. That is why an update
+ * of limit is required every time that the bandwidth is changing.
+ *
+ */
+static void UpdatePayloadSizeLimit(ISACMainStruct* instISAC) {
+ int16_t lim30MsPayloadBytes = WEBRTC_SPL_MIN(
+ (instISAC->maxPayloadSizeBytes),
+ (instISAC->maxRateBytesPer30Ms));
+ int16_t lim60MsPayloadBytes = WEBRTC_SPL_MIN(
+ (instISAC->maxPayloadSizeBytes),
+ (instISAC->maxRateBytesPer30Ms << 1));
+
+ /* The only time that iSAC will have 60 ms
+ * frame-size is when operating in wideband, so
+ * there is no upper-band bit-stream. */
+
+ if (instISAC->bandwidthKHz == isac8kHz) {
+ /* At 8 kHz there is no upper-band bit-stream,
+ * therefore, the lower-band limit is the overall limit. */
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes60 =
+ lim60MsPayloadBytes;
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ lim30MsPayloadBytes;
+ } else {
+ /* When in super-wideband, we only have 30 ms frames.
+ * Do a rate allocation for the given limit. */
+ if (lim30MsPayloadBytes > 250) {
+ /* 4/5 to lower-band the rest for upper-band. */
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ (lim30MsPayloadBytes << 2) / 5;
+ } else if (lim30MsPayloadBytes > 200) {
+ /* For the interval of 200 to 250 the share of
+ * upper-band linearly grows from 20 to 50. */
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ (lim30MsPayloadBytes << 1) / 5 + 100;
+ } else {
+ /* Allocate only 20 for upper-band. */
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ lim30MsPayloadBytes - 20;
+ }
+ instISAC->instUB.ISACencUB_obj.maxPayloadSizeBytes =
+ lim30MsPayloadBytes;
+ }
+}
+
+
+/****************************************************************************
+ * UpdateBottleneck(...)
+ *
+ * This function updates the bottleneck only if the codec is operating in
+ * channel-adaptive mode. Furthermore, as the update of bottleneck might
+ * result in an update of bandwidth, therefore, the bottlenech should be
+ * updated just right before the first 10ms of a frame is pushed into encoder.
+ *
+ */
+static void UpdateBottleneck(ISACMainStruct* instISAC) {
+ /* Read the bottleneck from bandwidth estimator for the
+ * first 10 ms audio. This way, if there is a change
+ * in bandwidth, upper and lower-band will be in sync. */
+ if ((instISAC->codingMode == 0) &&
+ (instISAC->instLB.ISACencLB_obj.buffer_index == 0) &&
+ (instISAC->instLB.ISACencLB_obj.frame_nb == 0)) {
+ int32_t bottleneck =
+ WebRtcIsac_GetUplinkBandwidth(&instISAC->bwestimator_obj);
+
+ /* Adding hysteresis when increasing signal bandwidth. */
+ if ((instISAC->bandwidthKHz == isac8kHz)
+ && (bottleneck > 37000)
+ && (bottleneck < 41000)) {
+ bottleneck = 37000;
+ }
+
+ /* Switching from 12 kHz to 16 kHz is not allowed at this revision.
+ * If we let this happen, we have to take care of buffer_index and
+ * the last LPC vector. */
+ if ((instISAC->bandwidthKHz != isac16kHz) &&
+ (bottleneck > 46000)) {
+ bottleneck = 46000;
+ }
+
+ /* We might need a rate allocation. */
+ if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+ /* Wideband is the only choice we have here. */
+ instISAC->instLB.ISACencLB_obj.bottleneck =
+ (bottleneck > 32000) ? 32000 : bottleneck;
+ instISAC->bandwidthKHz = isac8kHz;
+ } else {
+ /* Do the rate-allocation and get the new bandwidth. */
+ enum ISACBandwidth bandwidth;
+ WebRtcIsac_RateAllocation(bottleneck,
+ &(instISAC->instLB.ISACencLB_obj.bottleneck),
+ &(instISAC->instUB.ISACencUB_obj.bottleneck),
+ &bandwidth);
+ if (bandwidth != isac8kHz) {
+ instISAC->instLB.ISACencLB_obj.new_framelength = 480;
+ }
+ if (bandwidth != instISAC->bandwidthKHz) {
+ /* Bandwidth is changing. */
+ instISAC->bandwidthKHz = bandwidth;
+ UpdatePayloadSizeLimit(instISAC);
+ if (bandwidth == isac12kHz) {
+ instISAC->instLB.ISACencLB_obj.buffer_index = 0;
+ }
+ /* Currently we don't let the bandwidth to switch to 16 kHz
+ * if in adaptive mode. If we let this happen, we have to take
+ * care of buffer_index and the last LPC vector. */
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ * GetSendBandwidthInfo(...)
+ *
+ * This is called to get the bandwidth info. This info is the bandwidth and
+ * the jitter of 'there-to-here' channel, estimated 'here.' These info
+ * is signaled in an in-band fashion to the other side.
+ *
+ * The call to the bandwidth estimator triggers a recursive averaging which
+ * has to be synchronized between encoder & decoder, therefore, the call to
+ * BWE should be once per packet. As the BWE info is inserted into bit-stream
+ * We need a valid info right before the encodeLB function is going to
+ * generate a bit-stream. That is when lower-band buffer has already 20ms
+ * of audio, and the 3rd block of 10ms is going to be injected into encoder.
+ *
+ * Inputs:
+ * - instISAC : iSAC instance.
+ *
+ * Outputs:
+ * - bandwidthIndex : an index which has to be encoded in
+ * lower-band bit-stream, indicating the
+ * bandwidth of there-to-here channel.
+ * - jitterInfo : this indicates if the jitter is high
+ * or low and it is encoded in upper-band
+ * bit-stream.
+ *
+ */
+static void GetSendBandwidthInfo(ISACMainStruct* instISAC,
+ int16_t* bandwidthIndex,
+ int16_t* jitterInfo) {
+ if ((instISAC->instLB.ISACencLB_obj.buffer_index ==
+ (FRAMESAMPLES_10ms << 1)) &&
+ (instISAC->instLB.ISACencLB_obj.frame_nb == 0)) {
+ /* Bandwidth estimation and coding. */
+ WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj),
+ bandwidthIndex, jitterInfo,
+ instISAC->decoderSamplingRateKHz);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - ISAC_main_inst : address of the pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int16_t WebRtcIsac_Create(ISACStruct** ISAC_main_inst) {
+ ISACMainStruct* instISAC;
+
+ if (ISAC_main_inst != NULL) {
+ instISAC = (ISACMainStruct*)malloc(sizeof(ISACMainStruct));
+ *ISAC_main_inst = (ISACStruct*)instISAC;
+ if (*ISAC_main_inst != NULL) {
+ instISAC->errorCode = 0;
+ instISAC->initFlag = 0;
+ /* Default is wideband. */
+ instISAC->bandwidthKHz = isac8kHz;
+ instISAC->encoderSamplingRateKHz = kIsacWideband;
+ instISAC->decoderSamplingRateKHz = kIsacWideband;
+ instISAC->in_sample_rate_hz = 16000;
+
+ WebRtcIsac_InitTransform(&instISAC->transform_tables);
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : a ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int16_t WebRtcIsac_Free(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ free(instISAC);
+ return 0;
+}
+
+
+/****************************************************************************
+ * EncoderInitLb(...) - internal function for initialization of
+ * Lower Band
+ * EncoderInitUb(...) - internal function for initialization of
+ * Upper Band
+ * WebRtcIsac_EncoderInit(...) - API function
+ *
+ * This function initializes a ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - CodingMode : 0 -> Bit rate and frame length are automatically
+ * adjusted to available bandwidth on
+ * transmission channel, applicable just to
+ * wideband mode.
+ * 1 -> User sets a frame length and a target bit
+ * rate which is taken as the maximum
+ * short-term average bit rate.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+static int16_t EncoderInitLb(ISACLBStruct* instLB,
+ int16_t codingMode,
+ enum IsacSamplingRate sampRate) {
+ int16_t statusInit = 0;
+ int k;
+
+ /* Init stream vector to zero */
+ for (k = 0; k < STREAM_SIZE_MAX_60; k++) {
+ instLB->ISACencLB_obj.bitstr_obj.stream[k] = 0;
+ }
+
+ if ((codingMode == 1) || (sampRate == kIsacSuperWideband)) {
+ /* 30 ms frame-size if either in super-wideband or
+ * instantaneous mode (I-mode). */
+ instLB->ISACencLB_obj.new_framelength = 480;
+ } else {
+ instLB->ISACencLB_obj.new_framelength = INITIAL_FRAMESAMPLES;
+ }
+
+ WebRtcIsac_InitMasking(&instLB->ISACencLB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPreFilterbank(&instLB->ISACencLB_obj.prefiltbankstr_obj);
+ WebRtcIsac_InitPitchFilter(&instLB->ISACencLB_obj.pitchfiltstr_obj);
+ WebRtcIsac_InitPitchAnalysis(
+ &instLB->ISACencLB_obj.pitchanalysisstr_obj);
+
+ instLB->ISACencLB_obj.buffer_index = 0;
+ instLB->ISACencLB_obj.frame_nb = 0;
+ /* Default for I-mode. */
+ instLB->ISACencLB_obj.bottleneck = 32000;
+ instLB->ISACencLB_obj.current_framesamples = 0;
+ instLB->ISACencLB_obj.s2nr = 0;
+ instLB->ISACencLB_obj.payloadLimitBytes30 = STREAM_SIZE_MAX_30;
+ instLB->ISACencLB_obj.payloadLimitBytes60 = STREAM_SIZE_MAX_60;
+ instLB->ISACencLB_obj.maxPayloadBytes = STREAM_SIZE_MAX_60;
+ instLB->ISACencLB_obj.maxRateInBytes = STREAM_SIZE_MAX_30;
+ instLB->ISACencLB_obj.enforceFrameSize = 0;
+ /* Invalid value prevents getRedPayload to
+ run before encoder is called. */
+ instLB->ISACencLB_obj.lastBWIdx = -1;
+ return statusInit;
+}
+
+static int16_t EncoderInitUb(ISACUBStruct* instUB,
+ int16_t bandwidth) {
+ int16_t statusInit = 0;
+ int k;
+
+ /* Init stream vector to zero. */
+ for (k = 0; k < STREAM_SIZE_MAX_60; k++) {
+ instUB->ISACencUB_obj.bitstr_obj.stream[k] = 0;
+ }
+
+ WebRtcIsac_InitMasking(&instUB->ISACencUB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPreFilterbank(&instUB->ISACencUB_obj.prefiltbankstr_obj);
+
+ if (bandwidth == isac16kHz) {
+ instUB->ISACencUB_obj.buffer_index = LB_TOTAL_DELAY_SAMPLES;
+ } else {
+ instUB->ISACencUB_obj.buffer_index = 0;
+ }
+ /* Default for I-mode. */
+ instUB->ISACencUB_obj.bottleneck = 32000;
+ /* These store the limits for the wideband + super-wideband bit-stream. */
+ instUB->ISACencUB_obj.maxPayloadSizeBytes = STREAM_SIZE_MAX_30 << 1;
+ /* This has to be updated after each lower-band encoding to guarantee
+ * a correct payload-limitation. */
+ instUB->ISACencUB_obj.numBytesUsed = 0;
+ memset(instUB->ISACencUB_obj.data_buffer_float, 0,
+ (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES) * sizeof(float));
+
+ memcpy(&(instUB->ISACencUB_obj.lastLPCVec),
+ WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER);
+
+ return statusInit;
+}
+
+
+int16_t WebRtcIsac_EncoderInit(ISACStruct* ISAC_main_inst,
+ int16_t codingMode) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ int16_t status;
+
+ if ((codingMode != 0) && (codingMode != 1)) {
+ instISAC->errorCode = ISAC_DISALLOWED_CODING_MODE;
+ return -1;
+ }
+ /* Default bottleneck. */
+ instISAC->bottleneck = MAX_ISAC_BW;
+
+ if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+ instISAC->bandwidthKHz = isac8kHz;
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30;
+ } else {
+ instISAC->bandwidthKHz = isac16kHz;
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX;
+ }
+
+ /* Channel-adaptive = 0; Instantaneous (Channel-independent) = 1. */
+ instISAC->codingMode = codingMode;
+
+ WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj,
+ instISAC->encoderSamplingRateKHz,
+ instISAC->decoderSamplingRateKHz);
+
+ WebRtcIsac_InitRateModel(&instISAC->rate_data_obj);
+ /* Default for I-mode. */
+ instISAC->MaxDelay = 10.0;
+
+ status = EncoderInitLb(&instISAC->instLB, codingMode,
+ instISAC->encoderSamplingRateKHz);
+ if (status < 0) {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+
+ if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+ /* Initialize encoder filter-bank. */
+ memset(instISAC->analysisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+ memset(instISAC->analysisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+
+ status = EncoderInitUb(&(instISAC->instUB),
+ instISAC->bandwidthKHz);
+ if (status < 0) {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+ }
+ /* Initialization is successful, set the flag. */
+ instISAC->initFlag |= BIT_MASK_ENC_INIT;
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - speechIn : input speech vector.
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : 0 - The buffer didn't reach the chosen
+ * frameSize so it keeps buffering speech
+ * samples.
+ * : -1 - Error
+ */
+int WebRtcIsac_Encode(ISACStruct* ISAC_main_inst,
+ const int16_t* speechIn,
+ uint8_t* encoded) {
+ float inFrame[FRAMESAMPLES_10ms];
+ int16_t speechInLB[FRAMESAMPLES_10ms];
+ int16_t speechInUB[FRAMESAMPLES_10ms];
+ int streamLenLB = 0;
+ int streamLenUB = 0;
+ int streamLen = 0;
+ size_t k = 0;
+ uint8_t garbageLen = 0;
+ int32_t bottleneck = 0;
+ int16_t bottleneckIdx = 0;
+ int16_t jitterInfo = 0;
+
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ ISACLBStruct* instLB = &(instISAC->instLB);
+ ISACUBStruct* instUB = &(instISAC->instUB);
+
+ /* Check if encoder initiated. */
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+ WebRtcSpl_AnalysisQMF(speechIn, SWBFRAMESAMPLES_10ms, speechInLB,
+ speechInUB, instISAC->analysisFBState1,
+ instISAC->analysisFBState2);
+
+ /* Convert from fixed to floating point. */
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ inFrame[k] = (float)speechInLB[k];
+ }
+ } else {
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ inFrame[k] = (float) speechIn[k];
+ }
+ }
+
+ /* Add some noise to avoid denormal numbers. */
+ inFrame[0] += (float)1.23455334e-3;
+ inFrame[1] -= (float)2.04324239e-3;
+ inFrame[2] += (float)1.90854954e-3;
+ inFrame[9] += (float)1.84854878e-3;
+
+ /* This function will update the bottleneck if required. */
+ UpdateBottleneck(instISAC);
+
+ /* Get the bandwith information which has to be sent to the other side. */
+ GetSendBandwidthInfo(instISAC, &bottleneckIdx, &jitterInfo);
+
+ /* Encode lower-band. */
+ streamLenLB = WebRtcIsac_EncodeLb(&instISAC->transform_tables,
+ inFrame, &instLB->ISACencLB_obj,
+ instISAC->codingMode, bottleneckIdx);
+ if (streamLenLB < 0) {
+ return -1;
+ }
+
+ if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+ instUB = &(instISAC->instUB);
+
+ /* Convert to float. */
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ inFrame[k] = (float) speechInUB[k];
+ }
+
+ /* Add some noise to avoid denormal numbers. */
+ inFrame[0] += (float)1.23455334e-3;
+ inFrame[1] -= (float)2.04324239e-3;
+ inFrame[2] += (float)1.90854954e-3;
+ inFrame[9] += (float)1.84854878e-3;
+
+ /* Tell to upper-band the number of bytes used so far.
+ * This is for payload limitation. */
+ instUB->ISACencUB_obj.numBytesUsed =
+ (int16_t)(streamLenLB + 1 + LEN_CHECK_SUM_WORD8);
+ /* Encode upper-band. */
+ switch (instISAC->bandwidthKHz) {
+ case isac12kHz: {
+ streamLenUB = WebRtcIsac_EncodeUb12(&instISAC->transform_tables,
+ inFrame, &instUB->ISACencUB_obj,
+ jitterInfo);
+ break;
+ }
+ case isac16kHz: {
+ streamLenUB = WebRtcIsac_EncodeUb16(&instISAC->transform_tables,
+ inFrame, &instUB->ISACencUB_obj,
+ jitterInfo);
+ break;
+ }
+ case isac8kHz: {
+ streamLenUB = 0;
+ break;
+ }
+ }
+
+ if ((streamLenUB < 0) && (streamLenUB != -ISAC_PAYLOAD_LARGER_THAN_LIMIT)) {
+ /* An error has happened but this is not the error due to a
+ * bit-stream larger than the limit. */
+ return -1;
+ }
+
+ if (streamLenLB == 0) {
+ return 0;
+ }
+
+ /* One byte is allocated for the length. According to older decoders
+ so the length bit-stream plus one byte for size and
+ LEN_CHECK_SUM_WORD8 for the checksum should be less than or equal
+ to 255. */
+ if ((streamLenUB > (255 - (LEN_CHECK_SUM_WORD8 + 1))) ||
+ (streamLenUB == -ISAC_PAYLOAD_LARGER_THAN_LIMIT)) {
+ /* We have got a too long bit-stream we skip the upper-band
+ * bit-stream for this frame. */
+ streamLenUB = 0;
+ }
+
+ memcpy(encoded, instLB->ISACencLB_obj.bitstr_obj.stream, streamLenLB);
+ streamLen = streamLenLB;
+ if (streamLenUB > 0) {
+ encoded[streamLenLB] = (uint8_t)(streamLenUB + 1 + LEN_CHECK_SUM_WORD8);
+ memcpy(&encoded[streamLenLB + 1],
+ instUB->ISACencUB_obj.bitstr_obj.stream,
+ streamLenUB);
+ streamLen += encoded[streamLenLB];
+ } else {
+ encoded[streamLenLB] = 0;
+ }
+ } else {
+ if (streamLenLB == 0) {
+ return 0;
+ }
+ memcpy(encoded, instLB->ISACencLB_obj.bitstr_obj.stream, streamLenLB);
+ streamLenUB = 0;
+ streamLen = streamLenLB;
+ }
+
+ /* Add Garbage if required. */
+ bottleneck = WebRtcIsac_GetUplinkBandwidth(&instISAC->bwestimator_obj);
+ if (instISAC->codingMode == 0) {
+ int minBytes;
+ int limit;
+ uint8_t* ptrGarbage;
+
+ instISAC->MaxDelay = (double)WebRtcIsac_GetUplinkMaxDelay(
+ &instISAC->bwestimator_obj);
+
+ /* Update rate model and get minimum number of bytes in this packet. */
+ minBytes = WebRtcIsac_GetMinBytes(
+ &(instISAC->rate_data_obj), streamLen,
+ instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck,
+ instISAC->MaxDelay, instISAC->bandwidthKHz);
+
+ /* Make sure MinBytes does not exceed packet size limit. */
+ if (instISAC->bandwidthKHz == isac8kHz) {
+ if (instLB->ISACencLB_obj.current_framesamples == FRAMESAMPLES) {
+ limit = instLB->ISACencLB_obj.payloadLimitBytes30;
+ } else {
+ limit = instLB->ISACencLB_obj.payloadLimitBytes60;
+ }
+ } else {
+ limit = instUB->ISACencUB_obj.maxPayloadSizeBytes;
+ }
+ minBytes = (minBytes > limit) ? limit : minBytes;
+
+ /* Make sure we don't allow more than 255 bytes of garbage data.
+ * We store the length of the garbage data in 8 bits in the bitstream,
+ * 255 is the max garbage length we can signal using 8 bits. */
+ if ((instISAC->bandwidthKHz == isac8kHz) ||
+ (streamLenUB == 0)) {
+ ptrGarbage = &encoded[streamLenLB];
+ limit = streamLen + 255;
+ } else {
+ ptrGarbage = &encoded[streamLenLB + 1 + streamLenUB];
+ limit = streamLen + (255 - encoded[streamLenLB]);
+ }
+ minBytes = (minBytes > limit) ? limit : minBytes;
+
+ garbageLen = (minBytes > streamLen) ? (uint8_t)(minBytes - streamLen) : 0;
+
+ /* Save data for creation of multiple bit-streams. */
+ /* If bit-stream too short then add garbage at the end. */
+ if (garbageLen > 0) {
+ /* Overwrite the garbage area to avoid leaking possibly sensitive data
+ over the network. This also makes the output deterministic. */
+ memset(ptrGarbage, 0, garbageLen);
+
+ /* For a correct length of the upper-band bit-stream together
+ * with the garbage. Garbage is embeded in upper-band bit-stream.
+ * That is the only way to preserve backward compatibility. */
+ if ((instISAC->bandwidthKHz == isac8kHz) ||
+ (streamLenUB == 0)) {
+ encoded[streamLenLB] = garbageLen;
+ } else {
+ encoded[streamLenLB] += garbageLen;
+ /* Write the length of the garbage at the end of the upper-band
+ * bit-stream, if exists. This helps for sanity check. */
+ encoded[streamLenLB + 1 + streamLenUB] = garbageLen;
+
+ }
+ streamLen += garbageLen;
+ }
+ } else {
+ /* update rate model */
+ WebRtcIsac_UpdateRateModel(
+ &instISAC->rate_data_obj, streamLen,
+ instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck);
+ garbageLen = 0;
+ }
+
+ /* Generate CRC if required. */
+ if ((instISAC->bandwidthKHz != isac8kHz) && (streamLenUB > 0)) {
+ uint32_t crc;
+
+ WebRtcIsac_GetCrc((int16_t*)(&(encoded[streamLenLB + 1])),
+ streamLenUB + garbageLen, &crc);
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+ encoded[streamLen - LEN_CHECK_SUM_WORD8 + k] =
+ (uint8_t)(crc >> (24 - k * 8));
+ }
+#else
+ memcpy(&encoded[streamLenLB + streamLenUB + 1], &crc, LEN_CHECK_SUM_WORD8);
+#endif
+ }
+ return streamLen;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the received bwe-index in the
+ * stream. If the rate is set to a value less than bottleneck of codec
+ * the new bistream will be re-encoded with the given target rate.
+ * It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames.
+ *
+ * NOTE 1! This function does not write in the ISACStruct, it is not allowed.
+ * NOTE 2! Rates larger than the bottleneck of the codec will be limited
+ * to the current bottleneck.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : Index of bandwidth estimate to put in new
+ * bitstream
+ * - rate : target rate of the transcoder is bits/sec.
+ * Valid values are the accepted rate in iSAC,
+ * i.e. 10000 to 56000.
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error or called in SWB mode
+ * NOTE! No error code is written to
+ * the struct since it is only allowed to read
+ * the struct.
+ */
+int16_t WebRtcIsac_GetNewBitStream(ISACStruct* ISAC_main_inst,
+ int16_t bweIndex,
+ int16_t jitterInfo,
+ int32_t rate,
+ uint8_t* encoded,
+ int16_t isRCU) {
+ Bitstr iSACBitStreamInst; /* Local struct for bitstream handling */
+ int16_t streamLenLB;
+ int16_t streamLenUB;
+ int16_t totalStreamLen;
+ double gain2;
+ double gain1;
+ float scale;
+ enum ISACBandwidth bandwidthKHz;
+ double rateLB;
+ double rateUB;
+ int32_t currentBN;
+ uint32_t crc;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ int16_t k;
+#endif
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ return -1;
+ }
+
+ /* Get the bottleneck of this iSAC and limit the
+ * given rate to the current bottleneck. */
+ WebRtcIsac_GetUplinkBw(ISAC_main_inst, &currentBN);
+ if (rate > currentBN) {
+ rate = currentBN;
+ }
+
+ if (WebRtcIsac_RateAllocation(rate, &rateLB, &rateUB, &bandwidthKHz) < 0) {
+ return -1;
+ }
+
+ /* Cannot transcode from 16 kHz to 12 kHz. */
+ if ((bandwidthKHz == isac12kHz) &&
+ (instISAC->bandwidthKHz == isac16kHz)) {
+ return -1;
+ }
+
+ /* A gain [dB] for the given rate. */
+ gain1 = WebRtcIsac_GetSnr(
+ rateLB, instISAC->instLB.ISACencLB_obj.current_framesamples);
+ /* The gain [dB] of this iSAC. */
+ gain2 = WebRtcIsac_GetSnr(
+ instISAC->instLB.ISACencLB_obj.bottleneck,
+ instISAC->instLB.ISACencLB_obj.current_framesamples);
+
+ /* Scale is the ratio of two gains in normal domain. */
+ scale = (float)pow(10, (gain1 - gain2) / 20.0);
+ /* Change the scale if this is a RCU bit-stream. */
+ scale = (isRCU) ? (scale * RCU_TRANSCODING_SCALE) : scale;
+
+ streamLenLB = WebRtcIsac_EncodeStoredDataLb(
+ &instISAC->instLB.ISACencLB_obj.SaveEnc_obj,
+ &iSACBitStreamInst, bweIndex, scale);
+
+ if (streamLenLB < 0) {
+ return -1;
+ }
+
+ /* Convert from bytes to int16_t. */
+ memcpy(encoded, iSACBitStreamInst.stream, streamLenLB);
+
+ if (bandwidthKHz == isac8kHz) {
+ return streamLenLB;
+ }
+
+ totalStreamLen = streamLenLB;
+ /* super-wideband is always at 30ms.
+ * These gains are in dB.
+ * Gain for the given rate. */
+ gain1 = WebRtcIsac_GetSnr(rateUB, FRAMESAMPLES);
+ /* Gain of this iSAC */
+ gain2 = WebRtcIsac_GetSnr(instISAC->instUB.ISACencUB_obj.bottleneck,
+ FRAMESAMPLES);
+
+ /* Scale is the ratio of two gains in normal domain. */
+ scale = (float)pow(10, (gain1 - gain2) / 20.0);
+
+ /* Change the scale if this is a RCU bit-stream. */
+ scale = (isRCU)? (scale * RCU_TRANSCODING_SCALE_UB) : scale;
+
+ streamLenUB = WebRtcIsac_EncodeStoredDataUb(
+ &(instISAC->instUB.ISACencUB_obj.SaveEnc_obj),
+ &iSACBitStreamInst, jitterInfo, scale,
+ instISAC->bandwidthKHz);
+
+ if (streamLenUB < 0) {
+ return -1;
+ }
+
+ if (streamLenUB + 1 + LEN_CHECK_SUM_WORD8 > 255) {
+ return streamLenLB;
+ }
+
+ totalStreamLen = streamLenLB + streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+ encoded[streamLenLB] = streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+
+ memcpy(&encoded[streamLenLB + 1], iSACBitStreamInst.stream,
+ streamLenUB);
+
+ WebRtcIsac_GetCrc((int16_t*)(&(encoded[streamLenLB + 1])),
+ streamLenUB, &crc);
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+ encoded[totalStreamLen - LEN_CHECK_SUM_WORD8 + k] =
+ (uint8_t)((crc >> (24 - k * 8)) & 0xFF);
+ }
+#else
+ memcpy(&encoded[streamLenLB + streamLenUB + 1], &crc,
+ LEN_CHECK_SUM_WORD8);
+#endif
+ return totalStreamLen;
+}
+
+
+/****************************************************************************
+ * DecoderInitLb(...) - internal function for initialization of
+ * Lower Band
+ * DecoderInitUb(...) - internal function for initialization of
+ * Upper Band
+ * WebRtcIsac_DecoderInit(...) - API function
+ *
+ * This function initializes a ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ */
+static void DecoderInitLb(ISACLBStruct* instISAC) {
+ int i;
+ /* Initialize stream vector to zero. */
+ for (i = 0; i < STREAM_SIZE_MAX_60; i++) {
+ instISAC->ISACdecLB_obj.bitstr_obj.stream[i] = 0;
+ }
+
+ WebRtcIsac_InitMasking(&instISAC->ISACdecLB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPostFilterbank(
+ &instISAC->ISACdecLB_obj.postfiltbankstr_obj);
+ WebRtcIsac_InitPitchFilter(&instISAC->ISACdecLB_obj.pitchfiltstr_obj);
+}
+
+static void DecoderInitUb(ISACUBStruct* instISAC) {
+ int i;
+ /* Init stream vector to zero */
+ for (i = 0; i < STREAM_SIZE_MAX_60; i++) {
+ instISAC->ISACdecUB_obj.bitstr_obj.stream[i] = 0;
+ }
+
+ WebRtcIsac_InitMasking(&instISAC->ISACdecUB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPostFilterbank(
+ &instISAC->ISACdecUB_obj.postfiltbankstr_obj);
+}
+
+void WebRtcIsac_DecoderInit(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ DecoderInitLb(&instISAC->instLB);
+ if (instISAC->decoderSamplingRateKHz == kIsacSuperWideband) {
+ memset(instISAC->synthesisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+ memset(instISAC->synthesisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+ DecoderInitUb(&(instISAC->instUB));
+ }
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != BIT_MASK_ENC_INIT) {
+ WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj,
+ instISAC->encoderSamplingRateKHz,
+ instISAC->decoderSamplingRateKHz);
+ }
+ instISAC->initFlag |= BIT_MASK_DEC_INIT;
+ instISAC->resetFlag_8kHz = 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * NOTE:
+ * The estimates of bandwidth is not valid if the sample rate of the far-end
+ * encoder is set to 48 kHz and send timestamps are increamented according to
+ * 48 kHz sampling rate.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int16_t WebRtcIsac_UpdateBwEstimate(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ Bitstr streamdata;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ int k;
+#endif
+ int16_t err;
+
+ /* Check if decoder initiated. */
+ if ((instISAC->initFlag & BIT_MASK_DEC_INIT) != BIT_MASK_DEC_INIT) {
+ instISAC->errorCode = ISAC_DECODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Check that the size of the packet is valid, and if not return without
+ * updating the bandwidth estimate. A valid size is at least 10 bytes. */
+ if (packet_size < 10) {
+ /* Return error code if the packet length is null. */
+ instISAC->errorCode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ WebRtcIsac_ResetBitstream(&(streamdata));
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ for (k = 0; k < 10; k++) {
+ uint16_t ek = ((const uint16_t*)encoded)[k >> 1];
+ streamdata.stream[k] = (uint8_t)((ek >> ((k & 1) << 3)) & 0xff);
+ }
+#else
+ memcpy(streamdata.stream, encoded, 10);
+#endif
+
+ err = WebRtcIsac_EstimateBandwidth(&instISAC->bwestimator_obj, &streamdata,
+ packet_size, rtp_seq_number, send_ts,
+ arr_ts, instISAC->encoderSamplingRateKHz,
+ instISAC->decoderSamplingRateKHz);
+ if (err < 0) {
+ /* Return error code if something went wrong. */
+ instISAC->errorCode = -err;
+ return -1;
+ }
+ return 0;
+}
+
+static int Decode(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t lenEncodedBytes,
+ int16_t* decoded,
+ int16_t* speechType,
+ int16_t isRCUPayload) {
+ /* Number of samples (480 or 960), output from decoder
+ that were actually used in the encoder/decoder
+ (determined on the fly). */
+ int16_t numSamplesLB;
+ int16_t numSamplesUB;
+ int16_t speechIdx;
+ float outFrame[MAX_FRAMESAMPLES];
+ int16_t outFrameLB[MAX_FRAMESAMPLES];
+ int16_t outFrameUB[MAX_FRAMESAMPLES];
+ int numDecodedBytesLBint;
+ size_t numDecodedBytesLB;
+ int numDecodedBytesUB;
+ size_t lenEncodedLBBytes;
+ int16_t validChecksum = 1;
+ int16_t k;
+ uint16_t numLayer;
+ size_t totSizeBytes;
+ int16_t err;
+
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ ISACUBDecStruct* decInstUB = &(instISAC->instUB.ISACdecUB_obj);
+ ISACLBDecStruct* decInstLB = &(instISAC->instLB.ISACdecLB_obj);
+
+ /* Check if decoder initiated. */
+ if ((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+ BIT_MASK_DEC_INIT) {
+ instISAC->errorCode = ISAC_DECODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if (lenEncodedBytes == 0) {
+ /* return error code if the packet length is null. */
+ instISAC->errorCode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ /* The size of the encoded lower-band is bounded by
+ * STREAM_SIZE_MAX. If a payload with the size larger than STREAM_SIZE_MAX
+ * is received, it is not considered erroneous. */
+ lenEncodedLBBytes = (lenEncodedBytes > STREAM_SIZE_MAX) ?
+ STREAM_SIZE_MAX : lenEncodedBytes;
+
+ /* Copy to lower-band bit-stream structure. */
+ memcpy(instISAC->instLB.ISACdecLB_obj.bitstr_obj.stream, encoded,
+ lenEncodedLBBytes);
+
+ /* We need to initialize numSamplesLB to something; otherwise, in the test
+ for whether we should return -1 below, the compiler might generate code
+ that fools Memcheck (Valgrind) into thinking that the control flow depends
+ on the uninitialized value in numSamplesLB (since WebRtcIsac_DecodeLb will
+ not fill it in if it fails and returns -1). */
+ numSamplesLB = 0;
+
+ /* 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. */
+ numDecodedBytesLBint = WebRtcIsac_DecodeLb(&instISAC->transform_tables,
+ outFrame, decInstLB,
+ &numSamplesLB, isRCUPayload);
+ numDecodedBytesLB = (size_t)numDecodedBytesLBint;
+ if ((numDecodedBytesLBint < 0) ||
+ (numDecodedBytesLB > lenEncodedLBBytes) ||
+ (numSamplesLB > MAX_FRAMESAMPLES)) {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* Error Check, we accept multi-layer bit-stream This will limit number
+ * of iterations of the while loop. Even without this the number
+ * of iterations is limited. */
+ numLayer = 1;
+ totSizeBytes = numDecodedBytesLB;
+ while (totSizeBytes != lenEncodedBytes) {
+ if ((totSizeBytes > lenEncodedBytes) ||
+ (encoded[totSizeBytes] == 0) ||
+ (numLayer > MAX_NUM_LAYERS)) {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+ totSizeBytes += encoded[totSizeBytes];
+ numLayer++;
+ }
+
+ if (instISAC->decoderSamplingRateKHz == kIsacWideband) {
+ for (k = 0; k < numSamplesLB; k++) {
+ if (outFrame[k] > 32767) {
+ decoded[k] = 32767;
+ } else if (outFrame[k] < -32768) {
+ decoded[k] = -32768;
+ } else {
+ decoded[k] = (int16_t)WebRtcIsac_lrint(outFrame[k]);
+ }
+ }
+ numSamplesUB = 0;
+ } else {
+ uint32_t crc;
+ /* We don't accept larger than 30ms (480 samples at lower-band)
+ * frame-size. */
+ for (k = 0; k < numSamplesLB; k++) {
+ if (outFrame[k] > 32767) {
+ outFrameLB[k] = 32767;
+ } else if (outFrame[k] < -32768) {
+ outFrameLB[k] = -32768;
+ } else {
+ outFrameLB[k] = (int16_t)WebRtcIsac_lrint(outFrame[k]);
+ }
+ }
+
+ /* Check for possible error, and if upper-band stream exists. */
+ if (numDecodedBytesLB == lenEncodedBytes) {
+ /* Decoding was successful. No super-wideband bit-stream exists. */
+ numSamplesUB = numSamplesLB;
+ memset(outFrameUB, 0, sizeof(int16_t) * numSamplesUB);
+
+ /* Prepare for the potential increase of signal bandwidth. */
+ instISAC->resetFlag_8kHz = 2;
+ } else {
+ /* This includes the checksum and the bytes that stores the length. */
+ int16_t lenNextStream = encoded[numDecodedBytesLB];
+
+ /* Is this garbage or valid super-wideband bit-stream?
+ * Check if checksum is valid. */
+ if (lenNextStream <= (LEN_CHECK_SUM_WORD8 + 1)) {
+ /* Such a small second layer cannot be super-wideband layer.
+ * It must be a short garbage. */
+ validChecksum = 0;
+ } else {
+ /* Run CRC to see if the checksum match. */
+ WebRtcIsac_GetCrc((int16_t*)(&encoded[numDecodedBytesLB + 1]),
+ lenNextStream - LEN_CHECK_SUM_WORD8 - 1, &crc);
+
+ validChecksum = 1;
+ for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+ validChecksum &= (((crc >> (24 - k * 8)) & 0xFF) ==
+ encoded[numDecodedBytesLB + lenNextStream -
+ LEN_CHECK_SUM_WORD8 + k]);
+ }
+ }
+
+ if (!validChecksum) {
+ /* This is a garbage, we have received a wideband
+ * bit-stream with garbage. */
+ numSamplesUB = numSamplesLB;
+ memset(outFrameUB, 0, sizeof(int16_t) * numSamplesUB);
+ } else {
+ /* A valid super-wideband biststream exists. */
+ enum ISACBandwidth bandwidthKHz;
+ int32_t maxDelayBit;
+
+ /* If we have super-wideband bit-stream, we cannot
+ * have 60 ms frame-size. */
+ if (numSamplesLB > FRAMESAMPLES) {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* The rest of the bit-stream contains the upper-band
+ * bit-stream curently this is the only thing there,
+ * however, we might add more layers. */
+
+ /* Have to exclude one byte where the length is stored
+ * and last 'LEN_CHECK_SUM_WORD8' bytes where the
+ * checksum is stored. */
+ lenNextStream -= (LEN_CHECK_SUM_WORD8 + 1);
+
+ memcpy(decInstUB->bitstr_obj.stream,
+ &encoded[numDecodedBytesLB + 1], lenNextStream);
+
+ /* Reset bit-stream object, this is the first decoding. */
+ WebRtcIsac_ResetBitstream(&(decInstUB->bitstr_obj));
+
+ /* Decode jitter information. */
+ err = WebRtcIsac_DecodeJitterInfo(&decInstUB->bitstr_obj, &maxDelayBit);
+ if (err < 0) {
+ instISAC->errorCode = -err;
+ return -1;
+ }
+
+ /* Update jitter info which is in the upper-band bit-stream
+ * only if the encoder is in super-wideband. Otherwise,
+ * the jitter info is already embedded in bandwidth index
+ * and has been updated. */
+ if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+ err = WebRtcIsac_UpdateUplinkJitter(
+ &(instISAC->bwestimator_obj), maxDelayBit);
+ if (err < 0) {
+ instISAC->errorCode = -err;
+ return -1;
+ }
+ }
+
+ /* Decode bandwidth information. */
+ err = WebRtcIsac_DecodeBandwidth(&decInstUB->bitstr_obj,
+ &bandwidthKHz);
+ if (err < 0) {
+ instISAC->errorCode = -err;
+ return -1;
+ }
+
+ switch (bandwidthKHz) {
+ case isac12kHz: {
+ 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. */
+ if (instISAC->resetFlag_8kHz > 0) {
+ if (instISAC->resetFlag_8kHz == 2) {
+ /* Silence first and a half frame. */
+ memset(outFrame, 0, MAX_FRAMESAMPLES *
+ sizeof(float));
+ } else {
+ const float rampStep = 2.0f / MAX_FRAMESAMPLES;
+ float rampVal = 0;
+ memset(outFrame, 0, (MAX_FRAMESAMPLES >> 1) *
+ sizeof(float));
+
+ /* Ramp up second half of second frame. */
+ for (k = MAX_FRAMESAMPLES / 2; k < MAX_FRAMESAMPLES; k++) {
+ outFrame[k] *= rampVal;
+ rampVal += rampStep;
+ }
+ }
+ instISAC->resetFlag_8kHz -= 1;
+ }
+
+ break;
+ }
+ case isac16kHz: {
+ numDecodedBytesUB = WebRtcIsac_DecodeUb16(
+ &instISAC->transform_tables, outFrame, decInstUB, isRCUPayload);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if (numDecodedBytesUB < 0) {
+ instISAC->errorCode = numDecodedBytesUB;
+ return -1;
+ }
+ if (numDecodedBytesLB + numDecodedBytesUB > lenEncodedBytes) {
+ // We have supposedly decoded more bytes than we were given. Likely
+ // caused by bad input data.
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* It might be less due to garbage. */
+ if ((numDecodedBytesUB != lenNextStream) &&
+ (numDecodedBytesLB + 1 + numDecodedBytesUB >= lenEncodedBytes ||
+ numDecodedBytesUB !=
+ (lenNextStream -
+ encoded[numDecodedBytesLB + 1 + numDecodedBytesUB]))) {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ /* If there is no error Upper-band always decodes
+ * 30 ms (480 samples). */
+ numSamplesUB = FRAMESAMPLES;
+
+ /* Convert to W16. */
+ for (k = 0; k < numSamplesUB; k++) {
+ if (outFrame[k] > 32767) {
+ outFrameUB[k] = 32767;
+ } else if (outFrame[k] < -32768) {
+ outFrameUB[k] = -32768;
+ } else {
+ outFrameUB[k] = (int16_t)WebRtcIsac_lrint(
+ outFrame[k]);
+ }
+ }
+ }
+ }
+
+ speechIdx = 0;
+ while (speechIdx < numSamplesLB) {
+ WebRtcSpl_SynthesisQMF(&outFrameLB[speechIdx], &outFrameUB[speechIdx],
+ FRAMESAMPLES_10ms, &decoded[(speechIdx << 1)],
+ instISAC->synthesisFBState1,
+ instISAC->synthesisFBState2);
+
+ speechIdx += FRAMESAMPLES_10ms;
+ }
+ }
+ *speechType = 0;
+ return (numSamplesLB + numSamplesUB);
+}
+
+
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes a ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the frameSize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+
+int WebRtcIsac_Decode(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t lenEncodedBytes,
+ int16_t* decoded,
+ int16_t* speechType) {
+ int16_t isRCUPayload = 0;
+ return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded,
+ speechType, isRCUPayload);
+}
+
+/****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload in case of packet loss. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC RCU frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+
+
+
+int WebRtcIsac_DecodeRcu(ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ size_t lenEncodedBytes,
+ int16_t* decoded,
+ int16_t* speechType) {
+ int16_t isRCUPayload = 1;
+ return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded,
+ speechType, isRCUPayload);
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the frameSize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames to produce
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : Number of samples in decoded PLC vector
+ */
+size_t WebRtcIsac_DecodePlc(ISACStruct* ISAC_main_inst,
+ int16_t* decoded,
+ size_t noOfLostFrames) {
+ size_t numSamples = 0;
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ /* Limit number of frames to two = 60 millisecond.
+ * Otherwise we exceed data vectors. */
+ if (noOfLostFrames > 2) {
+ noOfLostFrames = 2;
+ }
+
+ /* Get the number of samples per frame */
+ switch (instISAC->decoderSamplingRateKHz) {
+ case kIsacWideband: {
+ numSamples = 480 * noOfLostFrames;
+ break;
+ }
+ case kIsacSuperWideband: {
+ numSamples = 960 * noOfLostFrames;
+ break;
+ }
+ }
+
+ /* Set output samples to zero. */
+ memset(decoded, 0, numSamples * sizeof(int16_t));
+ return numSamples;
+}
+
+
+/****************************************************************************
+ * ControlLb(...) - Internal function for controlling Lower Band
+ * ControlUb(...) - Internal function for controlling Upper Band
+ * WebRtcIsac_Control(...) - API function
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second (between 10000 and 32000)
+ * - frameSize : number of milliseconds per frame (30 or 60)
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+static int16_t ControlLb(ISACLBStruct* instISAC, double rate,
+ int16_t frameSize) {
+ if ((rate >= 10000) && (rate <= 32000)) {
+ instISAC->ISACencLB_obj.bottleneck = rate;
+ } else {
+ return -ISAC_DISALLOWED_BOTTLENECK;
+ }
+
+ if ((frameSize == 30) || (frameSize == 60)) {
+ instISAC->ISACencLB_obj.new_framelength = (FS / 1000) * frameSize;
+ } else {
+ return -ISAC_DISALLOWED_FRAME_LENGTH;
+ }
+
+ return 0;
+}
+
+static int16_t ControlUb(ISACUBStruct* instISAC, double rate) {
+ if ((rate >= 10000) && (rate <= 32000)) {
+ instISAC->ISACencUB_obj.bottleneck = rate;
+ } else {
+ return -ISAC_DISALLOWED_BOTTLENECK;
+ }
+ return 0;
+}
+
+int16_t WebRtcIsac_Control(ISACStruct* ISAC_main_inst,
+ int32_t bottleneckBPS,
+ int frameSize) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ int16_t status;
+ double rateLB;
+ double rateUB;
+ enum ISACBandwidth bandwidthKHz;
+
+ if (instISAC->codingMode == 0) {
+ /* In adaptive mode. */
+ instISAC->errorCode = ISAC_MODE_MISMATCH;
+ return -1;
+ }
+
+ /* Check if encoder initiated */
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+ /* If the sampling rate is 16kHz then bandwith should be 8kHz,
+ * regardless of bottleneck. */
+ bandwidthKHz = isac8kHz;
+ rateLB = (bottleneckBPS > 32000) ? 32000 : bottleneckBPS;
+ rateUB = 0;
+ } else {
+ if (WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB,
+ &bandwidthKHz) < 0) {
+ return -1;
+ }
+ }
+
+ if ((instISAC->encoderSamplingRateKHz == kIsacSuperWideband) &&
+ (frameSize != 30) &&
+ (bandwidthKHz != isac8kHz)) {
+ /* Cannot have 60 ms in super-wideband. */
+ instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+
+ status = ControlLb(&instISAC->instLB, rateLB, (int16_t)frameSize);
+ if (status < 0) {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+ if (bandwidthKHz != isac8kHz) {
+ status = ControlUb(&(instISAC->instUB), rateUB);
+ if (status < 0) {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+ }
+
+
+ /* Check if bandwidth is changing from wideband to super-wideband
+ * then we have to synch data buffer of lower & upper-band. Also
+ * clean up the upper-band data buffer. */
+
+ if ((instISAC->bandwidthKHz == isac8kHz) && (bandwidthKHz != isac8kHz)) {
+ memset(instISAC->instUB.ISACencUB_obj.data_buffer_float, 0,
+ sizeof(float) * (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES));
+
+ if (bandwidthKHz == isac12kHz) {
+ instISAC->instUB.ISACencUB_obj.buffer_index =
+ instISAC->instLB.ISACencLB_obj.buffer_index;
+ } else {
+ instISAC->instUB.ISACencUB_obj.buffer_index =
+ LB_TOTAL_DELAY_SAMPLES + instISAC->instLB.ISACencLB_obj.buffer_index;
+
+ memcpy(&(instISAC->instUB.ISACencUB_obj.lastLPCVec),
+ WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER);
+ }
+ }
+
+ /* Update the payload limit if the bandwidth is changing. */
+ if (instISAC->bandwidthKHz != bandwidthKHz) {
+ instISAC->bandwidthKHz = bandwidthKHz;
+ UpdatePayloadSizeLimit(instISAC);
+ }
+ instISAC->bottleneck = bottleneckBPS;
+ return 0;
+}
+
+void WebRtcIsac_SetInitialBweBottleneck(ISACStruct* ISAC_main_inst,
+ int bottleneck_bits_per_second) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ RTC_DCHECK_GE(bottleneck_bits_per_second, 10000);
+ RTC_DCHECK_LE(bottleneck_bits_per_second, 32000);
+ instISAC->bwestimator_obj.send_bw_avg = (float)bottleneck_bits_per_second;
+}
+
+/****************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rateBPS : initial value of bottleneck in bits/second
+ * 10000 <= rateBPS <= 32000 is accepted
+ * For default bottleneck set rateBPS = 0
+ * - frameSizeMs : number of milliseconds per frame (30 or 60)
+ * - enforceFrameSize : 1 to enforce the given frame-size through out
+ * the adaptation process, 0 to let iSAC change
+ * the frame-size if required.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+int16_t WebRtcIsac_ControlBwe(ISACStruct* ISAC_main_inst,
+ int32_t bottleneckBPS,
+ int frameSizeMs,
+ int16_t enforceFrameSize) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ enum ISACBandwidth bandwidth;
+
+ /* Check if encoder initiated */
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Check that we are in channel-adaptive mode, otherwise, return (-1) */
+ if (instISAC->codingMode != 0) {
+ instISAC->errorCode = ISAC_MODE_MISMATCH;
+ return -1;
+ }
+ if ((frameSizeMs != 30) &&
+ (instISAC->encoderSamplingRateKHz == kIsacSuperWideband)) {
+ return -1;
+ }
+
+ /* Set structure variable if enforceFrameSize is set. ISAC will then
+ * keep the chosen frame size. */
+ if (enforceFrameSize != 0) {
+ instISAC->instLB.ISACencLB_obj.enforceFrameSize = 1;
+ } else {
+ instISAC->instLB.ISACencLB_obj.enforceFrameSize = 0;
+ }
+
+ /* Set the initial rate. If the input value is zero then the default intial
+ * rate is used. Otehrwise, values between 10 to 32 kbps are accepted. */
+ if (bottleneckBPS != 0) {
+ double rateLB;
+ double rateUB;
+ if (WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB,
+ &bandwidth) < 0) {
+ return -1;
+ }
+ instISAC->bwestimator_obj.send_bw_avg = (float)bottleneckBPS;
+ instISAC->bandwidthKHz = bandwidth;
+ }
+
+ /* Set the initial frame-size. If 'enforceFrameSize' is set, the frame-size
+ * will not change */
+ if (frameSizeMs != 0) {
+ if ((frameSizeMs == 30) || (frameSizeMs == 60)) {
+ instISAC->instLB.ISACencLB_obj.new_framelength =
+ (int16_t)((FS / 1000) * frameSizeMs);
+ } else {
+ instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * the other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC structure
+ *
+ * Output:
+ * - bweIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+int16_t WebRtcIsac_GetDownLinkBwIndex(ISACStruct* ISAC_main_inst,
+ int16_t* bweIndex,
+ int16_t* jitterInfo) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ /* Check if encoder initialized. */
+ if ((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+ BIT_MASK_DEC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Call function to get Bandwidth Estimate. */
+ WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj), bweIndex,
+ jitterInfo,
+ instISAC->decoderSamplingRateKHz);
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC structure
+ * - rateIndex : Bandwidth estimate from other side.
+ *
+ * Return value : 0 - ok
+ * -1 - index out of range
+ */
+int16_t WebRtcIsac_UpdateUplinkBw(ISACStruct* ISAC_main_inst,
+ int16_t bweIndex) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ int16_t returnVal;
+
+ /* Check if encoder initiated. */
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Call function to get Bandwidth Estimate. */
+ returnVal = WebRtcIsac_UpdateUplinkBwImpl(
+ &(instISAC->bwestimator_obj), bweIndex,
+ instISAC->encoderSamplingRateKHz);
+
+ if (returnVal < 0) {
+ instISAC->errorCode = -returnVal;
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the
+ * bit-stream.
+ *
+ * Input:
+ * - encoded : Encoded bit-stream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ * - bweIndex : Bandwidth estimate in bit-stream
+ *
+ */
+int16_t WebRtcIsac_ReadBwIndex(const uint8_t* encoded,
+ int16_t* bweIndex) {
+ Bitstr streamdata;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ int k;
+#endif
+ int16_t err;
+
+ WebRtcIsac_ResetBitstream(&(streamdata));
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ for (k = 0; k < 10; k++) {
+ int16_t ek2 = ((const int16_t*)encoded)[k >> 1];
+ streamdata.stream[k] = (uint8_t)((ek2 >> ((k & 1) << 3)) & 0xff);
+ }
+#else
+ memcpy(streamdata.stream, encoded, 10);
+#endif
+
+ /* Decode frame length. */
+ err = WebRtcIsac_DecodeFrameLen(&streamdata, bweIndex);
+ if (err < 0) {
+ return err;
+ }
+
+ /* Decode BW estimation. */
+ err = WebRtcIsac_DecodeSendBW(&streamdata, bweIndex);
+ if (err < 0) {
+ return err;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the number of samples the decoder will generate if
+ * the given payload is decoded.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+int16_t WebRtcIsac_ReadFrameLen(const ISACStruct* ISAC_main_inst,
+ const uint8_t* encoded,
+ int16_t* frameLength) {
+ Bitstr streamdata;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ int k;
+#endif
+ int16_t err;
+ ISACMainStruct* instISAC;
+
+ WebRtcIsac_ResetBitstream(&(streamdata));
+
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ for (k = 0; k < 10; k++) {
+ int16_t ek2 = ((const int16_t*)encoded)[k >> 1];
+ streamdata.stream[k] = (uint8_t)((ek2 >> ((k & 1) << 3)) & 0xff);
+ }
+#else
+ memcpy(streamdata.stream, encoded, 10);
+#endif
+
+ /* Decode frame length. */
+ err = WebRtcIsac_DecodeFrameLen(&streamdata, frameLength);
+ if (err < 0) {
+ return -1;
+ }
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if (instISAC->decoderSamplingRateKHz == kIsacSuperWideband) {
+ /* The decoded frame length indicates the number of samples in
+ * lower-band in this case, multiply by 2 to get the total number
+ * of samples. */
+ *frameLength <<= 1;
+ }
+ return 0;
+}
+
+
+/*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * This function returns the frame length (in samples) of the next packet.
+ * In the case of channel-adaptive mode, iSAC decides on its frame length based
+ * on the estimated bottleneck, this AOI allows a user to prepare for the next
+ * packet (at the encoder).
+ *
+ * The primary usage is in CE to make the iSAC works in channel-adaptive mode
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Return Value : frame lenght in samples
+ *
+ */
+int16_t WebRtcIsac_GetNewFrameLen(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ /* Return new frame length. */
+ if (instISAC->in_sample_rate_hz == 16000)
+ return (instISAC->instLB.ISACencLB_obj.new_framelength);
+ else /* 32000 Hz */
+ return ((instISAC->instLB.ISACencLB_obj.new_framelength) * 2);
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance.
+ * When a function returns -1 an error code will be set for that instance.
+ * The function below extracts the code of the last error that occurred in
+ * the specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+int16_t WebRtcIsac_GetErrorCode(ISACStruct* ISAC_main_inst) {
+ return ((ISACMainStruct*)ISAC_main_inst)->errorCode;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through an in-band
+ * signalling retrieved by bandwidth estimator.
+ * In channel-independent, also called instantaneous mode, the target
+ * bottleneck is provided to the encoder by calling xxx_control(...) (if
+ * xxx_control is never called, the default values are used.).
+ * Note that the output is the iSAC internal operating bottleneck which might
+ * differ slightly from the one provided through xxx_control().
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Output:
+ * - *bottleneck : bottleneck in bits/sec
+ *
+ * Return value : -1 if error happens
+ * 0 bit-rates computed correctly.
+ */
+int16_t WebRtcIsac_GetUplinkBw(ISACStruct* ISAC_main_inst,
+ int32_t* bottleneck) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if (instISAC->codingMode == 0) {
+ /* We are in adaptive mode then get the bottleneck from BWE. */
+ *bottleneck = (int32_t)instISAC->bwestimator_obj.send_bw_avg;
+ } else {
+ *bottleneck = instISAC->bottleneck;
+ }
+
+ if ((*bottleneck > 32000) && (*bottleneck < 38000)) {
+ *bottleneck = 32000;
+ } else if ((*bottleneck > 45000) && (*bottleneck < 50000)) {
+ *bottleneck = 45000;
+ } else if (*bottleneck > 56000) {
+ *bottleneck = 56000;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 ms packets. If the encoder sampling rate
+ * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
+ * encoder sampling rate is 32 kHz the maximum payload size is between 120
+ * and 600 bytes.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, i.e. min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 100 and 400 bytes
+ * if encoder sampling rate is 16 kHz. For
+ * 32 kHz encoder sampling rate valid values
+ * are between 100 and 600 bytes.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+int16_t WebRtcIsac_SetMaxPayloadSize(ISACStruct* ISAC_main_inst,
+ int16_t maxPayloadBytes) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ int16_t status = 0;
+
+ /* Check if encoder initiated */
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if (instISAC->encoderSamplingRateKHz == kIsacSuperWideband) {
+ /* Sanity check. */
+ if (maxPayloadBytes < 120) {
+ /* 'maxRate' is out of valid range
+ * set to the acceptable value and return -1. */
+ maxPayloadBytes = 120;
+ status = -1;
+ }
+
+ /* sanity check */
+ if (maxPayloadBytes > STREAM_SIZE_MAX) {
+ /* maxRate is out of valid range,
+ * set to the acceptable value and return -1. */
+ maxPayloadBytes = STREAM_SIZE_MAX;
+ status = -1;
+ }
+ } else {
+ if (maxPayloadBytes < 120) {
+ /* Max payload-size is out of valid range
+ * set to the acceptable value and return -1. */
+ maxPayloadBytes = 120;
+ status = -1;
+ }
+ if (maxPayloadBytes > STREAM_SIZE_MAX_60) {
+ /* Max payload-size is out of valid range
+ * set to the acceptable value and return -1. */
+ maxPayloadBytes = STREAM_SIZE_MAX_60;
+ status = -1;
+ }
+ }
+ instISAC->maxPayloadSizeBytes = maxPayloadBytes;
+ UpdatePayloadSizeLimit(instISAC);
+ return status;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for
+ * any signal packet. The maximum rate is defined and payload-size per
+ * frame-size in bits per second.
+ *
+ * The codec has a maximum rate of 53400 bits per second (200 bytes per 30
+ * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
+ * if the encoder sampling rate is 32 kHz.
+ *
+ * It is possible to set a maximum rate between 32000 and 53400 bits/sec
+ * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRate : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits/sec in
+ * wideband mode, and 32000 to 160000 bits/sec in
+ * super-wideband mode.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+int16_t WebRtcIsac_SetMaxRate(ISACStruct* ISAC_main_inst,
+ int32_t maxRate) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ int16_t maxRateInBytesPer30Ms;
+ int16_t status = 0;
+
+ /* check if encoder initiated */
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) != BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+ /* Calculate maximum number of bytes per 30 msec packets for the
+ given maximum rate. Multiply with 30/1000 to get number of
+ bits per 30 ms, divide by 8 to get number of bytes per 30 ms:
+ maxRateInBytes = floor((maxRate * 30/1000) / 8); */
+ maxRateInBytesPer30Ms = (int16_t)(maxRate * 3 / 800);
+
+ if (instISAC->encoderSamplingRateKHz == kIsacWideband) {
+ if (maxRate < 32000) {
+ /* 'maxRate' is out of valid range.
+ * Set to the acceptable value and return -1. */
+ maxRateInBytesPer30Ms = 120;
+ status = -1;
+ }
+
+ if (maxRate > 53400) {
+ /* 'maxRate' is out of valid range.
+ * Set to the acceptable value and return -1. */
+ maxRateInBytesPer30Ms = 200;
+ status = -1;
+ }
+ } else {
+ if (maxRateInBytesPer30Ms < 120) {
+ /* 'maxRate' is out of valid range
+ * Set to the acceptable value and return -1. */
+ maxRateInBytesPer30Ms = 120;
+ status = -1;
+ }
+
+ if (maxRateInBytesPer30Ms > STREAM_SIZE_MAX) {
+ /* 'maxRate' is out of valid range.
+ * Set to the acceptable value and return -1. */
+ maxRateInBytesPer30Ms = STREAM_SIZE_MAX;
+ status = -1;
+ }
+ }
+ instISAC->maxRateBytesPer30Ms = maxRateInBytesPer30Ms;
+ UpdatePayloadSizeLimit(instISAC);
+ return status;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetRedPayload(...)
+ *
+ * This function populates "encoded" with the redundant payload of the recently
+ * encodedframe. This function has to be called once that WebRtcIsac_Encode(...)
+ * returns a positive value. Regardless of the frame-size this function will
+ * be called only once after encoding is completed. The bit-stream is
+ * targeted for 16000 bit/sec.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * : -1 - Error
+ */
+int16_t WebRtcIsac_GetRedPayload(ISACStruct* ISAC_main_inst,
+ uint8_t* encoded) {
+ Bitstr iSACBitStreamInst;
+ int16_t streamLenLB;
+ int16_t streamLenUB;
+ int16_t streamLen;
+ int16_t totalLenUB;
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ int k;
+#endif
+
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ }
+
+ WebRtcIsac_ResetBitstream(&(iSACBitStreamInst));
+
+ streamLenLB = WebRtcIsac_EncodeStoredDataLb(
+ &instISAC->instLB.ISACencLB_obj.SaveEnc_obj,
+ &iSACBitStreamInst,
+ instISAC->instLB.ISACencLB_obj.lastBWIdx,
+ RCU_TRANSCODING_SCALE);
+ if (streamLenLB < 0) {
+ return -1;
+ }
+
+ /* convert from bytes to int16_t. */
+ memcpy(encoded, iSACBitStreamInst.stream, streamLenLB);
+ streamLen = streamLenLB;
+ if (instISAC->bandwidthKHz == isac8kHz) {
+ return streamLenLB;
+ }
+
+ streamLenUB = WebRtcIsac_GetRedPayloadUb(
+ &instISAC->instUB.ISACencUB_obj.SaveEnc_obj,
+ &iSACBitStreamInst, instISAC->bandwidthKHz);
+ if (streamLenUB < 0) {
+ /* An error has happened but this is not the error due to a
+ * bit-stream larger than the limit. */
+ return -1;
+ }
+
+ /* We have one byte to write the total length of the upper-band.
+ * The length includes the bit-stream length, check-sum and the
+ * single byte where the length is written to. This is according to
+ * iSAC wideband and how the "garbage" is dealt. */
+ totalLenUB = streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+ if (totalLenUB > 255) {
+ streamLenUB = 0;
+ }
+
+ /* Generate CRC if required. */
+ if ((instISAC->bandwidthKHz != isac8kHz) &&
+ (streamLenUB > 0)) {
+ uint32_t crc;
+ streamLen += totalLenUB;
+ encoded[streamLenLB] = (uint8_t)totalLenUB;
+ memcpy(&encoded[streamLenLB + 1], iSACBitStreamInst.stream,
+ streamLenUB);
+
+ WebRtcIsac_GetCrc((int16_t*)(&(encoded[streamLenLB + 1])),
+ streamLenUB, &crc);
+#ifndef WEBRTC_ARCH_BIG_ENDIAN
+ for (k = 0; k < LEN_CHECK_SUM_WORD8; k++) {
+ encoded[streamLen - LEN_CHECK_SUM_WORD8 + k] =
+ (uint8_t)((crc >> (24 - k * 8)) & 0xFF);
+ }
+#else
+ memcpy(&encoded[streamLenLB + streamLenUB + 1], &crc,
+ LEN_CHECK_SUM_WORD8);
+#endif
+ }
+ return streamLen;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+void WebRtcIsac_version(char* version) {
+ strcpy(version, "4.3.0");
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * This function sets the sampling rate of the encoder. Initialization of the
+ * encoder WILL NOT overwrite the sampling rate of the encoder. The default
+ * value is 16 kHz which is set when the instance is created. The encoding-mode
+ * and the bottleneck remain unchanged by this call, however, the maximum rate
+ * and maximum payload-size will be reset to their default values.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sample_rate_hz : sampling rate in Hertz, valid values are 16000
+ * and 32000.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+int16_t WebRtcIsac_SetEncSampRate(ISACStruct* ISAC_main_inst,
+ uint16_t sample_rate_hz) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ enum IsacSamplingRate encoder_operational_rate;
+
+ if ((sample_rate_hz != 16000) && (sample_rate_hz != 32000)) {
+ /* Sampling Frequency is not supported. */
+ instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+ return -1;
+ }
+ if (sample_rate_hz == 16000) {
+ encoder_operational_rate = kIsacWideband;
+ } else {
+ encoder_operational_rate = kIsacSuperWideband;
+ }
+
+ if ((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT) {
+ if (encoder_operational_rate == kIsacWideband) {
+ instISAC->bandwidthKHz = isac8kHz;
+ } else {
+ instISAC->bandwidthKHz = isac16kHz;
+ }
+ } else {
+ ISACUBStruct* instUB = &(instISAC->instUB);
+ ISACLBStruct* instLB = &(instISAC->instLB);
+ int32_t bottleneck = instISAC->bottleneck;
+ int16_t codingMode = instISAC->codingMode;
+ int16_t frameSizeMs = instLB->ISACencLB_obj.new_framelength /
+ (FS / 1000);
+
+ if ((encoder_operational_rate == kIsacWideband) &&
+ (instISAC->encoderSamplingRateKHz == kIsacSuperWideband)) {
+ /* Changing from super-wideband to wideband.
+ * we don't need to re-initialize the encoder of the lower-band. */
+ instISAC->bandwidthKHz = isac8kHz;
+ if (codingMode == 1) {
+ ControlLb(instLB,
+ (bottleneck > 32000) ? 32000 : bottleneck, FRAMESIZE);
+ }
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30;
+ } else if ((encoder_operational_rate == kIsacSuperWideband) &&
+ (instISAC->encoderSamplingRateKHz == kIsacWideband)) {
+ double bottleneckLB = 0;
+ double bottleneckUB = 0;
+ if (codingMode == 1) {
+ WebRtcIsac_RateAllocation(bottleneck, &bottleneckLB, &bottleneckUB,
+ &(instISAC->bandwidthKHz));
+ }
+
+ instISAC->bandwidthKHz = isac16kHz;
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX;
+
+ EncoderInitLb(instLB, codingMode, encoder_operational_rate);
+ EncoderInitUb(instUB, instISAC->bandwidthKHz);
+
+ memset(instISAC->analysisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+ memset(instISAC->analysisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+
+ if (codingMode == 1) {
+ instISAC->bottleneck = bottleneck;
+ ControlLb(instLB, bottleneckLB,
+ (instISAC->bandwidthKHz == isac8kHz) ? frameSizeMs:FRAMESIZE);
+ if (instISAC->bandwidthKHz > isac8kHz) {
+ ControlUb(instUB, bottleneckUB);
+ }
+ } else {
+ instLB->ISACencLB_obj.enforceFrameSize = 0;
+ instLB->ISACencLB_obj.new_framelength = FRAMESAMPLES;
+ }
+ }
+ }
+ instISAC->encoderSamplingRateKHz = encoder_operational_rate;
+ instISAC->in_sample_rate_hz = sample_rate_hz;
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * This function sets the sampling rate of the decoder. Initialization of the
+ * decoder WILL NOT overwrite the sampling rate of the encoder. The default
+ * value is 16 kHz which is set when the instance is created.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sample_rate_hz : sampling rate in Hertz, valid values are 16000
+ * and 32000.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+int16_t WebRtcIsac_SetDecSampRate(ISACStruct* ISAC_main_inst,
+ uint16_t sample_rate_hz) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ enum IsacSamplingRate decoder_operational_rate;
+
+ if (sample_rate_hz == 16000) {
+ decoder_operational_rate = kIsacWideband;
+ } else if (sample_rate_hz == 32000) {
+ decoder_operational_rate = kIsacSuperWideband;
+ } else {
+ /* Sampling Frequency is not supported. */
+ instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+ return -1;
+ }
+
+ if ((instISAC->decoderSamplingRateKHz == kIsacWideband) &&
+ (decoder_operational_rate == kIsacSuperWideband)) {
+ /* Switching from wideband to super-wideband at the decoder
+ * we need to reset the filter-bank and initialize upper-band decoder. */
+ memset(instISAC->synthesisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+ memset(instISAC->synthesisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(int32_t));
+
+ DecoderInitUb(&instISAC->instUB);
+ }
+ instISAC->decoderSamplingRateKHz = decoder_operational_rate;
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : sampling rate in Hertz. The input to encoder
+ * is expected to be sampled in this rate.
+ *
+ */
+uint16_t WebRtcIsac_EncSampRate(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ return instISAC->in_sample_rate_hz;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : sampling rate in Hertz. Decoder output is
+ * sampled at this rate.
+ *
+ */
+uint16_t WebRtcIsac_DecSampRate(ISACStruct* ISAC_main_inst) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)ISAC_main_inst;
+ return instISAC->decoderSamplingRateKHz == kIsacWideband ? 16000 : 32000;
+}
+
+void WebRtcIsac_SetEncSampRateInDecoder(ISACStruct* inst,
+ int sample_rate_hz) {
+ ISACMainStruct* instISAC = (ISACMainStruct*)inst;
+ RTC_DCHECK_NE(0, instISAC->initFlag & BIT_MASK_DEC_INIT);
+ RTC_DCHECK(!(instISAC->initFlag & BIT_MASK_ENC_INIT));
+ RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000);
+ instISAC->encoderSamplingRateKHz = sample_rate_hz / 1000;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_float_type.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_float_type.h
new file mode 100644
index 0000000000..511bc97ee6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_float_type.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
+
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+
+namespace webrtc {
+
+struct IsacFloat {
+ using instance_type = ISACStruct;
+ static const bool has_swb = true;
+ static inline int16_t Control(instance_type* inst,
+ int32_t rate,
+ int framesize) {
+ return WebRtcIsac_Control(inst, rate, framesize);
+ }
+ static inline int16_t ControlBwe(instance_type* inst,
+ int32_t rate_bps,
+ int frame_size_ms,
+ int16_t enforce_frame_size) {
+ return WebRtcIsac_ControlBwe(inst, rate_bps, frame_size_ms,
+ enforce_frame_size);
+ }
+ static inline int16_t Create(instance_type** inst) {
+ return WebRtcIsac_Create(inst);
+ }
+ static inline int DecodeInternal(instance_type* inst,
+ const uint8_t* encoded,
+ size_t len,
+ int16_t* decoded,
+ int16_t* speech_type) {
+ return WebRtcIsac_Decode(inst, encoded, len, decoded, speech_type);
+ }
+ static inline size_t DecodePlc(instance_type* inst,
+ int16_t* decoded,
+ size_t num_lost_frames) {
+ return WebRtcIsac_DecodePlc(inst, decoded, num_lost_frames);
+ }
+
+ static inline void DecoderInit(instance_type* inst) {
+ WebRtcIsac_DecoderInit(inst);
+ }
+ static inline int Encode(instance_type* inst,
+ const int16_t* speech_in,
+ uint8_t* encoded) {
+ return WebRtcIsac_Encode(inst, speech_in, encoded);
+ }
+ static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
+ return WebRtcIsac_EncoderInit(inst, coding_mode);
+ }
+ static inline uint16_t EncSampRate(instance_type* inst) {
+ return WebRtcIsac_EncSampRate(inst);
+ }
+
+ static inline int16_t Free(instance_type* inst) {
+ return WebRtcIsac_Free(inst);
+ }
+ static inline int16_t GetErrorCode(instance_type* inst) {
+ return WebRtcIsac_GetErrorCode(inst);
+ }
+
+ static inline int16_t GetNewFrameLen(instance_type* inst) {
+ return WebRtcIsac_GetNewFrameLen(inst);
+ }
+ static inline int16_t SetDecSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ return WebRtcIsac_SetDecSampRate(inst, sample_rate_hz);
+ }
+ static inline int16_t SetEncSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ return WebRtcIsac_SetEncSampRate(inst, sample_rate_hz);
+ }
+ static inline void SetEncSampRateInDecoder(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ WebRtcIsac_SetEncSampRateInDecoder(inst, sample_rate_hz);
+ }
+ static inline void SetInitialBweBottleneck(instance_type* inst,
+ int bottleneck_bits_per_second) {
+ WebRtcIsac_SetInitialBweBottleneck(inst, bottleneck_bits_per_second);
+ }
+ static inline int16_t SetMaxPayloadSize(instance_type* inst,
+ int16_t max_payload_size_bytes) {
+ return WebRtcIsac_SetMaxPayloadSize(inst, max_payload_size_bytes);
+ }
+ static inline int16_t SetMaxRate(instance_type* inst, int32_t max_bit_rate) {
+ return WebRtcIsac_SetMaxRate(inst, max_bit_rate);
+ }
+};
+
+} // namespace webrtc
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_FLOAT_TYPE_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
new file mode 100644
index 0000000000..c98b21d86f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+
+#include <string>
+
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+struct WebRtcISACStruct;
+
+namespace webrtc {
+
+// Number of samples in a 60 ms, sampled at 32 kHz.
+const int kIsacNumberOfSamples = 320 * 6;
+// Maximum number of bytes in output bitstream.
+const size_t kMaxBytes = 1000;
+
+class IsacTest : public ::testing::Test {
+ protected:
+ IsacTest();
+ virtual void SetUp();
+
+ WebRtcISACStruct* isac_codec_;
+
+ int16_t speech_data_[kIsacNumberOfSamples];
+ int16_t output_data_[kIsacNumberOfSamples];
+ uint8_t bitstream_[kMaxBytes];
+ uint8_t bitstream_small_[7]; // Simulate sync packets.
+};
+
+IsacTest::IsacTest() : isac_codec_(NULL) {}
+
+void IsacTest::SetUp() {
+ // Read some samples from a speech file, to be used in the encode test.
+ FILE* input_file;
+ const std::string file_name =
+ webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+ input_file = fopen(file_name.c_str(), "rb");
+ ASSERT_TRUE(input_file != NULL);
+ ASSERT_EQ(kIsacNumberOfSamples,
+ static_cast<int32_t>(fread(speech_data_, sizeof(int16_t),
+ kIsacNumberOfSamples, input_file)));
+ fclose(input_file);
+ input_file = NULL;
+}
+
+// Test failing Create.
+TEST_F(IsacTest, IsacCreateFail) {
+ // Test to see that an invalid pointer is caught.
+ EXPECT_EQ(-1, WebRtcIsac_Create(NULL));
+}
+
+// Test failing Free.
+TEST_F(IsacTest, IsacFreeFail) {
+ // Test to see that free function doesn't crash.
+ EXPECT_EQ(0, WebRtcIsac_Free(NULL));
+}
+
+// Test normal Create and Free.
+TEST_F(IsacTest, IsacCreateFree) {
+ EXPECT_EQ(0, WebRtcIsac_Create(&isac_codec_));
+ EXPECT_TRUE(isac_codec_ != NULL);
+ EXPECT_EQ(0, WebRtcIsac_Free(isac_codec_));
+}
+
+TEST_F(IsacTest, IsacUpdateBWE) {
+ // Create encoder memory.
+ EXPECT_EQ(0, WebRtcIsac_Create(&isac_codec_));
+
+ // Init encoder (adaptive mode) and decoder.
+ WebRtcIsac_EncoderInit(isac_codec_, 0);
+ WebRtcIsac_DecoderInit(isac_codec_);
+
+ int encoded_bytes;
+
+ // Test with call with a small packet (sync packet).
+ EXPECT_EQ(-1, WebRtcIsac_UpdateBwEstimate(isac_codec_, bitstream_small_, 7, 1,
+ 12345, 56789));
+
+ // Encode 60 ms of data (needed to create a first packet).
+ encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+ EXPECT_EQ(0, encoded_bytes);
+ encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+ EXPECT_EQ(0, encoded_bytes);
+ encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+ EXPECT_EQ(0, encoded_bytes);
+ encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+ EXPECT_EQ(0, encoded_bytes);
+ encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+ EXPECT_EQ(0, encoded_bytes);
+ encoded_bytes = WebRtcIsac_Encode(isac_codec_, speech_data_, bitstream_);
+ EXPECT_GT(encoded_bytes, 0);
+
+ // Call to update bandwidth estimator with real data.
+ EXPECT_EQ(0, WebRtcIsac_UpdateBwEstimate(isac_codec_, bitstream_,
+ static_cast<size_t>(encoded_bytes),
+ 1, 12345, 56789));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcIsac_Free(isac_codec_));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.c
new file mode 100644
index 0000000000..57cf0c39da
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+
+#include <math.h>
+
+void WebRtcIsac_InitPitchFilter(PitchFiltstr* pitchfiltdata) {
+ int k;
+
+ for (k = 0; k < PITCH_BUFFSIZE; k++) {
+ pitchfiltdata->ubuf[k] = 0.0;
+ }
+ pitchfiltdata->ystate[0] = 0.0;
+ for (k = 1; k < (PITCH_DAMPORDER); k++) {
+ pitchfiltdata->ystate[k] = 0.0;
+ }
+ pitchfiltdata->oldlagp[0] = 50.0;
+ pitchfiltdata->oldgainp[0] = 0.0;
+}
+
+static void WebRtcIsac_InitWeightingFilter(WeightFiltstr* wfdata) {
+ int k;
+ double t, dtmp, dtmp2, denum, denum2;
+
+ for (k = 0; k < PITCH_WLPCBUFLEN; k++)
+ wfdata->buffer[k] = 0.0;
+
+ for (k = 0; k < PITCH_WLPCORDER; k++) {
+ wfdata->istate[k] = 0.0;
+ wfdata->weostate[k] = 0.0;
+ wfdata->whostate[k] = 0.0;
+ }
+
+ /* next part should be in Matlab, writing to a global table */
+ t = 0.5;
+ denum = 1.0 / ((double)PITCH_WLPCWINLEN);
+ denum2 = denum * denum;
+ for (k = 0; k < PITCH_WLPCWINLEN; k++) {
+ dtmp = PITCH_WLPCASYM * t * denum + (1 - PITCH_WLPCASYM) * t * t * denum2;
+ dtmp *= 3.14159265;
+ dtmp2 = sin(dtmp);
+ wfdata->window[k] = dtmp2 * dtmp2;
+ t++;
+ }
+}
+
+void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct* State) {
+ int k;
+
+ for (k = 0; k < PITCH_CORR_LEN2 + PITCH_CORR_STEP2 + PITCH_MAX_LAG / 2 -
+ PITCH_FRAME_LEN / 2 + 2;
+ k++)
+ State->dec_buffer[k] = 0.0;
+ for (k = 0; k < 2 * ALLPASSSECTIONS + 1; k++)
+ State->decimator_state[k] = 0.0;
+ for (k = 0; k < 2; k++)
+ State->hp_state[k] = 0.0;
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->whitened_buf[k] = 0.0;
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = 0.0;
+
+ WebRtcIsac_InitPitchFilter(&(State->PFstr_wght));
+
+ WebRtcIsac_InitPitchFilter(&(State->PFstr));
+
+ WebRtcIsac_InitWeightingFilter(&(State->Wghtstr));
+}
+
+void WebRtcIsac_InitPreFilterbank(PreFiltBankstr* prefiltdata) {
+ int k;
+
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ prefiltdata->INLABUF1[k] = 0;
+ prefiltdata->INLABUF2[k] = 0;
+
+ prefiltdata->INLABUF1_float[k] = 0;
+ prefiltdata->INLABUF2_float[k] = 0;
+ }
+ for (k = 0; k < 2 * (QORDER - 1); k++) {
+ prefiltdata->INSTAT1[k] = 0;
+ prefiltdata->INSTAT2[k] = 0;
+ prefiltdata->INSTATLA1[k] = 0;
+ prefiltdata->INSTATLA2[k] = 0;
+
+ prefiltdata->INSTAT1_float[k] = 0;
+ prefiltdata->INSTAT2_float[k] = 0;
+ prefiltdata->INSTATLA1_float[k] = 0;
+ prefiltdata->INSTATLA2_float[k] = 0;
+ }
+
+ /* High pass filter states */
+ prefiltdata->HPstates[0] = 0.0;
+ prefiltdata->HPstates[1] = 0.0;
+
+ prefiltdata->HPstates_float[0] = 0.0f;
+ prefiltdata->HPstates_float[1] = 0.0f;
+
+ return;
+}
+
+double WebRtcIsac_LevDurb(double* a, double* k, double* r, size_t order) {
+ const double LEVINSON_EPS = 1.0e-10;
+
+ double sum, alpha;
+ size_t m, m_h, i;
+ alpha = 0; // warning -DH
+ a[0] = 1.0;
+ if (r[0] < LEVINSON_EPS) { /* if r[0] <= 0, set LPC coeff. to zero */
+ for (i = 0; i < order; i++) {
+ k[i] = 0;
+ a[i + 1] = 0;
+ }
+ } else {
+ a[1] = k[0] = -r[1] / r[0];
+ alpha = r[0] + r[1] * k[0];
+ for (m = 1; m < order; m++) {
+ sum = r[m + 1];
+ for (i = 0; i < m; i++) {
+ sum += a[i + 1] * r[m - i];
+ }
+ k[m] = -sum / alpha;
+ alpha += k[m] * sum;
+ m_h = (m + 1) >> 1;
+ for (i = 0; i < m_h; i++) {
+ sum = a[i + 1] + k[m] * a[m - i];
+ a[m - i] += k[m] * a[i + 1];
+ a[i + 1] = sum;
+ }
+ a[m + 1] = k[m];
+ }
+ }
+ return alpha;
+}
+
+/* The upper channel all-pass filter factors */
+const float WebRtcIsac_kUpperApFactorsFloat[2] = {0.03470000000000f,
+ 0.38260000000000f};
+
+/* The lower channel all-pass filter factors */
+const float WebRtcIsac_kLowerApFactorsFloat[2] = {0.15440000000000f,
+ 0.74400000000000f};
+
+/* This function performs all-pass filtering--a series of first order all-pass
+ * sections are used to filter the input in a cascade manner.
+ * The input is overwritten!!
+ */
+void WebRtcIsac_AllPassFilter2Float(float* InOut,
+ const float* APSectionFactors,
+ int lengthInOut,
+ int NumberOfSections,
+ float* FilterState) {
+ int n, j;
+ float temp;
+ for (j = 0; j < NumberOfSections; j++) {
+ for (n = 0; n < lengthInOut; n++) {
+ temp = FilterState[j] + APSectionFactors[j] * InOut[n];
+ FilterState[j] = -APSectionFactors[j] * temp + InOut[n];
+ InOut[n] = temp;
+ }
+ }
+}
+
+/* The number of composite all-pass filter factors */
+#define NUMBEROFCOMPOSITEAPSECTIONS 4
+
+/* Function WebRtcIsac_SplitAndFilter
+ * This function creates low-pass and high-pass decimated versions of part of
+ the input signal, and part of the signal in the input 'lookahead buffer'.
+
+ INPUTS:
+ in: a length FRAMESAMPLES array of input samples
+ prefiltdata: input data structure containing the filterbank states
+ and lookahead samples from the previous encoding
+ iteration.
+ OUTPUTS:
+ LP: a FRAMESAMPLES_HALF array of low-pass filtered samples that
+ have been phase equalized. The first QLOOKAHEAD samples are
+ based on the samples in the two prefiltdata->INLABUFx arrays
+ each of length QLOOKAHEAD.
+ The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
+ on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
+ array in[].
+ HP: a FRAMESAMPLES_HALF array of high-pass filtered samples that
+ have been phase equalized. The first QLOOKAHEAD samples are
+ based on the samples in the two prefiltdata->INLABUFx arrays
+ each of length QLOOKAHEAD.
+ The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
+ on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
+ array in[].
+
+ LP_la: a FRAMESAMPLES_HALF array of low-pass filtered samples.
+ These samples are not phase equalized. They are computed
+ from the samples in the in[] array.
+ HP_la: a FRAMESAMPLES_HALF array of high-pass filtered samples
+ that are not phase equalized. They are computed from
+ the in[] vector.
+ prefiltdata: this input data structure's filterbank state and
+ lookahead sample buffers are updated for the next
+ encoding iteration.
+*/
+void WebRtcIsac_SplitAndFilterFloat(float* pin,
+ float* LP,
+ float* HP,
+ double* LP_la,
+ double* HP_la,
+ PreFiltBankstr* prefiltdata) {
+ int k, n;
+ float CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
+ float ForTransform_CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
+ float ForTransform_CompositeAPFilterState2[NUMBEROFCOMPOSITEAPSECTIONS];
+ float tempinoutvec[FRAMESAMPLES + MAX_AR_MODEL_ORDER];
+ float tempin_ch1[FRAMESAMPLES + MAX_AR_MODEL_ORDER];
+ float tempin_ch2[FRAMESAMPLES + MAX_AR_MODEL_ORDER];
+ float in[FRAMESAMPLES];
+ float ftmp;
+
+ /* HPstcoeff_in = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
+ static const float kHpStCoefInFloat[4] = {
+ -1.94895953203325f, 0.94984516000000f, -0.05101826139794f,
+ 0.05015484000000f};
+
+ /* The composite all-pass filter factors */
+ static const float WebRtcIsac_kCompositeApFactorsFloat[4] = {
+ 0.03470000000000f, 0.15440000000000f, 0.38260000000000f,
+ 0.74400000000000f};
+
+ // The matrix for transforming the backward composite state to upper channel
+ // state.
+ static const float WebRtcIsac_kTransform1Float[8] = {
+ -0.00158678506084f, 0.00127157815343f, -0.00104805672709f,
+ 0.00084837248079f, 0.00134467983258f, -0.00107756549387f,
+ 0.00088814793277f, -0.00071893072525f};
+
+ // The matrix for transforming the backward composite state to lower channel
+ // state.
+ static const float WebRtcIsac_kTransform2Float[8] = {
+ -0.00170686041697f, 0.00136780109829f, -0.00112736532350f,
+ 0.00091257055385f, 0.00103094281812f, -0.00082615076557f,
+ 0.00068092756088f, -0.00055119165484f};
+
+ /* High pass filter */
+
+ for (k = 0; k < FRAMESAMPLES; k++) {
+ in[k] = pin[k] + kHpStCoefInFloat[2] * prefiltdata->HPstates_float[0] +
+ kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1];
+ ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] -
+ kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1];
+ prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0];
+ prefiltdata->HPstates_float[0] = ftmp;
+ }
+
+ /* First Channel */
+
+ /*initial state of composite filter is zero */
+ for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) {
+ CompositeAPFilterState[k] = 0.0;
+ }
+ /* put every other sample of input into a temporary vector in reverse
+ * (backward) order*/
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tempinoutvec[k] = in[FRAMESAMPLES - 1 - 2 * k];
+ }
+
+ /* now all-pass filter the backwards vector. Output values overwrite the
+ * input vector. */
+ WebRtcIsac_AllPassFilter2Float(
+ tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat, FRAMESAMPLES_HALF,
+ NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ /* save the backwards filtered output for later forward filtering,
+ but write it in forward order*/
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tempin_ch1[FRAMESAMPLES_HALF + QLOOKAHEAD - 1 - k] = tempinoutvec[k];
+ }
+
+ /* save the backwards filter state becaue it will be transformed
+ later into a forward state */
+ for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) {
+ ForTransform_CompositeAPFilterState[k] = CompositeAPFilterState[k];
+ }
+
+ /* now backwards filter the samples in the lookahead buffer. The samples were
+ placed there in the encoding of the previous frame. The output samples
+ overwrite the input samples */
+ WebRtcIsac_AllPassFilter2Float(
+ prefiltdata->INLABUF1_float, WebRtcIsac_kCompositeApFactorsFloat,
+ QLOOKAHEAD, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ /* save the output, but write it in forward order */
+ /* write the lookahead samples for the next encoding iteration. Every other
+ sample at the end of the input frame is written in reverse order for the
+ lookahead length. Exported in the prefiltdata structure. */
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ tempin_ch1[QLOOKAHEAD - 1 - k] = prefiltdata->INLABUF1_float[k];
+ prefiltdata->INLABUF1_float[k] = in[FRAMESAMPLES - 1 - 2 * k];
+ }
+
+ /* Second Channel. This is exactly like the first channel, except that the
+ even samples are now filtered instead (lower channel). */
+ for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) {
+ CompositeAPFilterState[k] = 0.0;
+ }
+
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tempinoutvec[k] = in[FRAMESAMPLES - 2 - 2 * k];
+ }
+
+ WebRtcIsac_AllPassFilter2Float(
+ tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat, FRAMESAMPLES_HALF,
+ NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tempin_ch2[FRAMESAMPLES_HALF + QLOOKAHEAD - 1 - k] = tempinoutvec[k];
+ }
+
+ for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) {
+ ForTransform_CompositeAPFilterState2[k] = CompositeAPFilterState[k];
+ }
+
+ WebRtcIsac_AllPassFilter2Float(
+ prefiltdata->INLABUF2_float, WebRtcIsac_kCompositeApFactorsFloat,
+ QLOOKAHEAD, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ tempin_ch2[QLOOKAHEAD - 1 - k] = prefiltdata->INLABUF2_float[k];
+ prefiltdata->INLABUF2_float[k] = in[FRAMESAMPLES - 2 - 2 * k];
+ }
+
+ /* Transform filter states from backward to forward */
+ /*At this point, each of the states of the backwards composite filters for the
+ two channels are transformed into forward filtering states for the
+ corresponding forward channel filters. Each channel's forward filtering
+ state from the previous
+ encoding iteration is added to the transformed state to get a proper forward
+ state */
+
+ /* So the existing NUMBEROFCOMPOSITEAPSECTIONS x 1 (4x1) state vector is
+ multiplied by a NUMBEROFCHANNELAPSECTIONSxNUMBEROFCOMPOSITEAPSECTIONS (2x4)
+ transform matrix to get the new state that is added to the previous 2x1
+ input state */
+
+ for (k = 0; k < NUMBEROFCHANNELAPSECTIONS; k++) { /* k is row variable */
+ for (n = 0; n < NUMBEROFCOMPOSITEAPSECTIONS;
+ n++) { /* n is column variable */
+ prefiltdata->INSTAT1_float[k] +=
+ ForTransform_CompositeAPFilterState[n] *
+ WebRtcIsac_kTransform1Float[k * NUMBEROFCHANNELAPSECTIONS + n];
+ prefiltdata->INSTAT2_float[k] +=
+ ForTransform_CompositeAPFilterState2[n] *
+ WebRtcIsac_kTransform2Float[k * NUMBEROFCHANNELAPSECTIONS + n];
+ }
+ }
+
+ /*obtain polyphase components by forward all-pass filtering through each
+ * channel */
+ /* the backward filtered samples are now forward filtered with the
+ * corresponding channel filters */
+ /* The all pass filtering automatically updates the filter states which are
+ exported in the prefiltdata structure */
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,
+ prefiltdata->INSTAT1_float);
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,
+ prefiltdata->INSTAT2_float);
+
+ /* Now Construct low-pass and high-pass signals as combinations of polyphase
+ * components */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ LP[k] = 0.5f * (tempin_ch1[k] + tempin_ch2[k]); /* low pass signal*/
+ HP[k] = 0.5f * (tempin_ch1[k] - tempin_ch2[k]); /* high pass signal*/
+ }
+
+ /* Lookahead LP and HP signals */
+ /* now create low pass and high pass signals of the input vector. However, no
+ backwards filtering is performed, and hence no phase equalization is
+ involved. Also, the input contains some samples that are lookahead samples.
+ The high pass and low pass signals that are created are used outside this
+ function for analysis (not encoding) purposes */
+
+ /* set up input */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tempin_ch1[k] = in[2 * k + 1];
+ tempin_ch2[k] = in[2 * k];
+ }
+
+ /* the input filter states are passed in and updated by the all-pass filtering
+ routine and exported in the prefiltdata structure*/
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,
+ prefiltdata->INSTATLA1_float);
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,
+ prefiltdata->INSTATLA2_float);
+
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ LP_la[k] = (float)(0.5f * (tempin_ch1[k] + tempin_ch2[k])); /*low pass */
+ HP_la[k] = (double)(0.5f * (tempin_ch1[k] - tempin_ch2[k])); /* high pass */
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.h
new file mode 100644
index 0000000000..1aecfc4046
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/isac_vad.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_VAD_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_VAD_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+void WebRtcIsac_InitPitchFilter(PitchFiltstr* pitchfiltdata);
+void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct* state);
+void WebRtcIsac_InitPreFilterbank(PreFiltBankstr* prefiltdata);
+
+double WebRtcIsac_LevDurb(double* a, double* k, double* r, size_t order);
+
+/* The number of all-pass filter factors in an upper or lower channel*/
+#define NUMBEROFCHANNELAPSECTIONS 2
+
+/* The upper channel all-pass filter factors */
+extern const float WebRtcIsac_kUpperApFactorsFloat[2];
+
+/* The lower channel all-pass filter factors */
+extern const float WebRtcIsac_kLowerApFactorsFloat[2];
+
+void WebRtcIsac_AllPassFilter2Float(float* InOut,
+ const float* APSectionFactors,
+ int lengthInOut,
+ int NumberOfSections,
+ float* FilterState);
+void WebRtcIsac_SplitAndFilterFloat(float* in,
+ float* LP,
+ float* HP,
+ double* LP_la,
+ double* HP_la,
+ PreFiltBankstr* prefiltdata);
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ISAC_VAD_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lattice.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lattice.c
new file mode 100644
index 0000000000..d9d2d65665
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lattice.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lattice.c
+ *
+ * contains the normalized lattice filter routines (MA and AR) for iSAC codec
+ *
+ */
+
+#include <math.h>
+#include <memory.h>
+#include <string.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+ float *stateF,
+ float *stateG,
+ float *lat_in,
+ double *filtcoeflo,
+ double *lat_out)
+{
+ int n,k,i,u,temp1;
+ int ord_1 = orderCoef+1;
+ float sth[MAX_AR_MODEL_ORDER];
+ float cth[MAX_AR_MODEL_ORDER];
+ float inv_cth[MAX_AR_MODEL_ORDER];
+ double a[MAX_AR_MODEL_ORDER+1];
+ float f[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], g[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ float gain1;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ /* set the Direct Form coefficients */
+ temp1 = u*ord_1;
+ a[0] = 1;
+ memcpy(a+1, filtcoeflo+temp1+1, sizeof(double) * (ord_1-1));
+
+ /* compute lattice filter coefficients */
+ WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
+
+ /* compute the gain */
+ gain1 = (float)filtcoeflo[temp1];
+ for (k=0;k<orderCoef;k++)
+ {
+ gain1 *= cth[k];
+ inv_cth[k] = 1/cth[k];
+ }
+
+ /* normalized lattice filter */
+ /*****************************/
+
+ /* initial conditions */
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ f[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
+ g[0][i] = lat_in[i + u * HALF_SUBFRAMELEN];
+ }
+
+ /* get the state of f&g for the first input, for all orders */
+ for (i=1;i<ord_1;i++)
+ {
+ f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
+ g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
+ }
+
+ /* filtering */
+ for(k=0;k<orderCoef;k++)
+ {
+ for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+ {
+ f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
+ g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
+ }
+ }
+
+ for(n=0;n<HALF_SUBFRAMELEN;n++)
+ {
+ lat_out[n + u * HALF_SUBFRAMELEN] = gain1 * f[orderCoef][n];
+ }
+
+ /* save the states */
+ for (i=0;i<ord_1;i++)
+ {
+ stateF[i] = f[i][HALF_SUBFRAMELEN-1];
+ stateG[i] = g[i][HALF_SUBFRAMELEN-1];
+ }
+ /* process next frame */
+ }
+
+ return;
+}
+
+
+/*///////////////////AR filter ///////////////////////////////*/
+/* filter the signal using normalized lattice filter */
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
+ float *stateF,
+ float *stateG,
+ double *lat_in,
+ double *lo_filt_coef,
+ float *lat_out)
+{
+ int n,k,i,u,temp1;
+ int ord_1 = orderCoef+1;
+ float sth[MAX_AR_MODEL_ORDER];
+ float cth[MAX_AR_MODEL_ORDER];
+ double a[MAX_AR_MODEL_ORDER+1];
+ float ARf[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], ARg[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ float gain1,inv_gain1;
+
+ for (u=0;u<SUBFRAMES;u++)
+ {
+ /* set the denominator and numerator of the Direct Form */
+ temp1 = u*ord_1;
+ a[0] = 1;
+
+ memcpy(a+1, lo_filt_coef+temp1+1, sizeof(double) * (ord_1-1));
+
+ WebRtcIsac_Dir2Lat(a,orderCoef,sth,cth);
+
+ gain1 = (float)lo_filt_coef[temp1];
+ for (k=0;k<orderCoef;k++)
+ {
+ gain1 = cth[k]*gain1;
+ }
+
+ /* initial conditions */
+ inv_gain1 = 1/gain1;
+ for (i=0;i<HALF_SUBFRAMELEN;i++)
+ {
+ ARf[orderCoef][i] = (float)lat_in[i + u * HALF_SUBFRAMELEN]*inv_gain1;
+ }
+
+
+ for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders
+ {
+ ARf[i][0] = cth[i]*ARf[i+1][0] - sth[i]*stateG[i];
+ ARg[i+1][0] = sth[i]*ARf[i+1][0] + cth[i]* stateG[i];
+ }
+ ARg[0][0] = ARf[0][0];
+
+ for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+ {
+ for(k=orderCoef-1;k>=0;k--)
+ {
+ ARf[k][n+1] = cth[k]*ARf[k+1][n+1] - sth[k]*ARg[k][n];
+ ARg[k+1][n+1] = sth[k]*ARf[k+1][n+1] + cth[k]* ARg[k][n];
+ }
+ ARg[0][n+1] = ARf[0][n+1];
+ }
+
+ memcpy(lat_out+u * HALF_SUBFRAMELEN, &(ARf[0][0]), sizeof(float) * HALF_SUBFRAMELEN);
+
+ /* cannot use memcpy in the following */
+ for (i=0;i<ord_1;i++)
+ {
+ stateF[i] = ARf[i][HALF_SUBFRAMELEN-1];
+ stateG[i] = ARg[i][HALF_SUBFRAMELEN-1];
+ }
+
+ }
+
+ return;
+}
+
+
+/* compute the reflection coefficients using the step-down procedure*/
+/* converts the direct form parameters to lattice form.*/
+/* a and b are vectors which contain the direct form coefficients,
+ according to
+ A(z) = a(1) + a(2)*z + a(3)*z^2 + ... + a(M+1)*z^M
+ B(z) = b(1) + b(2)*z + b(3)*z^2 + ... + b(M+1)*z^M
+*/
+
+void WebRtcIsac_Dir2Lat(double *a,
+ int orderCoef,
+ float *sth,
+ float *cth)
+{
+ int m, k;
+ float tmp[MAX_AR_MODEL_ORDER];
+ float tmp_inv, cth2;
+
+ sth[orderCoef-1] = (float)a[orderCoef];
+ cth2 = 1.0f - sth[orderCoef-1] * sth[orderCoef-1];
+ cth[orderCoef-1] = (float)sqrt(cth2);
+ for (m=orderCoef-1; m>0; m--)
+ {
+ tmp_inv = 1.0f / cth2;
+ for (k=1; k<=m; k++)
+ {
+ tmp[k] = ((float)a[k] - sth[m] * (float)a[m-k+1]) * tmp_inv;
+ }
+
+ for (k=1; k<m; k++)
+ {
+ a[k] = tmp[k];
+ }
+
+ sth[m-1] = tmp[m];
+ cth2 = 1 - sth[m-1] * sth[m-1];
+ cth[m-1] = (float)sqrt(cth2);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c
new file mode 100644
index 0000000000..0fda73bda6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_analysis.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/entropy_coding.h"
+#include "modules/audio_coding/codecs/isac/main/source/filter_functions.h"
+#include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+
+/* window */
+/* Matlab generation code:
+ * t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
+ * for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
+ */
+static const double kLpcCorrWindow[WINLEN] = {
+ 0.00000000, 0.00000001, 0.00000004, 0.00000010, 0.00000020,
+ 0.00000035, 0.00000055, 0.00000083, 0.00000118, 0.00000163,
+ 0.00000218, 0.00000283, 0.00000361, 0.00000453, 0.00000558, 0.00000679,
+ 0.00000817, 0.00000973, 0.00001147, 0.00001342, 0.00001558,
+ 0.00001796, 0.00002058, 0.00002344, 0.00002657, 0.00002997,
+ 0.00003365, 0.00003762, 0.00004190, 0.00004651, 0.00005144, 0.00005673,
+ 0.00006236, 0.00006837, 0.00007476, 0.00008155, 0.00008875,
+ 0.00009636, 0.00010441, 0.00011290, 0.00012186, 0.00013128,
+ 0.00014119, 0.00015160, 0.00016252, 0.00017396, 0.00018594, 0.00019846,
+ 0.00021155, 0.00022521, 0.00023946, 0.00025432, 0.00026978,
+ 0.00028587, 0.00030260, 0.00031998, 0.00033802, 0.00035674,
+ 0.00037615, 0.00039626, 0.00041708, 0.00043863, 0.00046092, 0.00048396,
+ 0.00050775, 0.00053233, 0.00055768, 0.00058384, 0.00061080,
+ 0.00063858, 0.00066720, 0.00069665, 0.00072696, 0.00075813,
+ 0.00079017, 0.00082310, 0.00085692, 0.00089164, 0.00092728, 0.00096384,
+ 0.00100133, 0.00103976, 0.00107914, 0.00111947, 0.00116077,
+ 0.00120304, 0.00124630, 0.00129053, 0.00133577, 0.00138200,
+ 0.00142924, 0.00147749, 0.00152676, 0.00157705, 0.00162836, 0.00168070,
+ 0.00173408, 0.00178850, 0.00184395, 0.00190045, 0.00195799,
+ 0.00201658, 0.00207621, 0.00213688, 0.00219860, 0.00226137,
+ 0.00232518, 0.00239003, 0.00245591, 0.00252284, 0.00259079, 0.00265977,
+ 0.00272977, 0.00280078, 0.00287280, 0.00294582, 0.00301984,
+ 0.00309484, 0.00317081, 0.00324774, 0.00332563, 0.00340446,
+ 0.00348421, 0.00356488, 0.00364644, 0.00372889, 0.00381220, 0.00389636,
+ 0.00398135, 0.00406715, 0.00415374, 0.00424109, 0.00432920,
+ 0.00441802, 0.00450754, 0.00459773, 0.00468857, 0.00478001,
+ 0.00487205, 0.00496464, 0.00505775, 0.00515136, 0.00524542, 0.00533990,
+ 0.00543476, 0.00552997, 0.00562548, 0.00572125, 0.00581725,
+ 0.00591342, 0.00600973, 0.00610612, 0.00620254, 0.00629895,
+ 0.00639530, 0.00649153, 0.00658758, 0.00668341, 0.00677894, 0.00687413,
+ 0.00696891, 0.00706322, 0.00715699, 0.00725016, 0.00734266,
+ 0.00743441, 0.00752535, 0.00761540, 0.00770449, 0.00779254,
+ 0.00787947, 0.00796519, 0.00804963, 0.00813270, 0.00821431, 0.00829437,
+ 0.00837280, 0.00844949, 0.00852436, 0.00859730, 0.00866822,
+ 0.00873701, 0.00880358, 0.00886781, 0.00892960, 0.00898884,
+ 0.00904542, 0.00909923, 0.00915014, 0.00919805, 0.00924283, 0.00928436,
+ 0.00932252, 0.00935718, 0.00938821, 0.00941550, 0.00943890,
+ 0.00945828, 0.00947351, 0.00948446, 0.00949098, 0.00949294,
+ 0.00949020, 0.00948262, 0.00947005, 0.00945235, 0.00942938, 0.00940099,
+ 0.00936704, 0.00932738, 0.00928186, 0.00923034, 0.00917268,
+ 0.00910872, 0.00903832, 0.00896134, 0.00887763, 0.00878706,
+ 0.00868949, 0.00858478, 0.00847280, 0.00835343, 0.00822653, 0.00809199,
+ 0.00794970, 0.00779956, 0.00764145, 0.00747530, 0.00730103,
+ 0.00711857, 0.00692787, 0.00672888, 0.00652158, 0.00630597,
+ 0.00608208, 0.00584994, 0.00560962, 0.00536124, 0.00510493, 0.00484089,
+ 0.00456935, 0.00429062, 0.00400505, 0.00371310, 0.00341532,
+ 0.00311238, 0.00280511, 0.00249452, 0.00218184, 0.00186864,
+ 0.00155690, 0.00124918, 0.00094895, 0.00066112, 0.00039320, 0.00015881
+};
+
+static void WebRtcIsac_GetVars(const double* input,
+ const int16_t* pitchGains_Q12,
+ double* oldEnergy,
+ double* varscale) {
+ double nrg[4], chng, pg;
+ int k;
+
+ double pitchGains[4]={0,0,0,0};;
+
+ /* Calculate energies of first and second frame halfs */
+ nrg[0] = 0.0001;
+ for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES_QUARTER + QLOOKAHEAD) / 2; k++) {
+ nrg[0] += input[k]*input[k];
+ }
+ nrg[1] = 0.0001;
+ for ( ; k < (FRAMESAMPLES_HALF + QLOOKAHEAD) / 2; k++) {
+ nrg[1] += input[k]*input[k];
+ }
+ nrg[2] = 0.0001;
+ for ( ; k < (FRAMESAMPLES*3/4 + QLOOKAHEAD) / 2; k++) {
+ nrg[2] += input[k]*input[k];
+ }
+ nrg[3] = 0.0001;
+ for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+ nrg[3] += input[k]*input[k];
+ }
+
+ /* Calculate average level change */
+ chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+ fabs(10.0 * log10(nrg[2] / nrg[1])) +
+ fabs(10.0 * log10(nrg[1] / nrg[0])) +
+ fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+ /* Find average pitch gain */
+ pg = 0.0;
+ for (k=0; k<4; k++)
+ {
+ pitchGains[k] = ((float)pitchGains_Q12[k])/4096;
+ pg += pitchGains[k];
+ }
+ pg *= 0.25;
+
+ /* If pitch gain is low and energy constant - increase noise level*/
+ /* Matlab code:
+ pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+ */
+ *varscale = 0.0 + 1.0 * exp( -1.4 * exp(-200.0 * pg*pg*pg) / (1.0 + 0.4 * chng) );
+
+ *oldEnergy = nrg[3];
+}
+
+static void WebRtcIsac_GetVarsUB(const double* input,
+ double* oldEnergy,
+ double* varscale) {
+ double nrg[4], chng;
+ int k;
+
+ /* Calculate energies of first and second frame halfs */
+ nrg[0] = 0.0001;
+ for (k = 0; k < (FRAMESAMPLES_QUARTER) / 2; k++) {
+ nrg[0] += input[k]*input[k];
+ }
+ nrg[1] = 0.0001;
+ for ( ; k < (FRAMESAMPLES_HALF) / 2; k++) {
+ nrg[1] += input[k]*input[k];
+ }
+ nrg[2] = 0.0001;
+ for ( ; k < (FRAMESAMPLES*3/4) / 2; k++) {
+ nrg[2] += input[k]*input[k];
+ }
+ nrg[3] = 0.0001;
+ for ( ; k < (FRAMESAMPLES) / 2; k++) {
+ nrg[3] += input[k]*input[k];
+ }
+
+ /* Calculate average level change */
+ chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+ fabs(10.0 * log10(nrg[2] / nrg[1])) +
+ fabs(10.0 * log10(nrg[1] / nrg[0])) +
+ fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+ /* If pitch gain is low and energy constant - increase noise level*/
+ /* Matlab code:
+ pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+ */
+ *varscale = exp( -1.4 / (1.0 + 0.4 * chng) );
+
+ *oldEnergy = nrg[3];
+}
+
+void WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
+ double signal_noise_ratio, const int16_t *pitchGains_Q12,
+ double *lo_coeff, double *hi_coeff)
+{
+ int k, n, j, pos1, pos2;
+ double varscale;
+
+ double DataLo[WINLEN], DataHi[WINLEN];
+ double corrlo[ORDERLO+2], corrlo2[ORDERLO+1];
+ double corrhi[ORDERHI+1];
+ double k_veclo[ORDERLO], k_vechi[ORDERHI];
+
+ double a_LO[ORDERLO+1], a_HI[ORDERHI+1];
+ double tmp, res_nrg;
+
+ double FwdA, FwdB;
+
+ /* hearing threshold level in dB; higher value gives more noise */
+ const double HearThresOffset = -28.0;
+
+ /* bandwdith expansion factors for low- and high band */
+ const double gammaLo = 0.9;
+ const double gammaHi = 0.8;
+
+ /* less-noise-at-low-frequencies factor */
+ double aa;
+
+
+ /* convert from dB to signal level */
+ const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+ double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46; /* divide by sqrt(12) */
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsac_GetVars(inLo, pitchGains_Q12, &(maskdata->OldEnergy), &varscale);
+
+ /* less-noise-at-low-frequencies factor */
+ aa = 0.35 * (0.5 + 0.5 * varscale);
+
+ /* replace data in buffer by new look-ahead data */
+ for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++)
+ maskdata->DataBufferLo[pos1 + WINLEN - QLOOKAHEAD] = inLo[pos1];
+
+ for (k = 0; k < SUBFRAMES; k++) {
+
+ /* Update input buffer and multiply signal with window */
+ for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+ maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 + UPDATE/2];
+ maskdata->DataBufferHi[pos1] = maskdata->DataBufferHi[pos1 + UPDATE/2];
+ DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+ }
+ pos2 = k * UPDATE/2;
+ for (n = 0; n < UPDATE/2; n++, pos1++) {
+ maskdata->DataBufferLo[pos1] = inLo[QLOOKAHEAD + pos2];
+ maskdata->DataBufferHi[pos1] = inHi[pos2++];
+ DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+ }
+
+ /* Get correlation coefficients */
+ WebRtcIsac_AutoCorr(corrlo, DataLo, WINLEN, ORDERLO+1); /* computing autocorrelation */
+ WebRtcIsac_AutoCorr(corrhi, DataHi, WINLEN, ORDERHI);
+
+
+ /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+ corrlo2[0] = (1.0+aa*aa) * corrlo[0] - 2.0*aa * corrlo[1];
+ tmp = (1.0 + aa*aa);
+ for (n = 1; n <= ORDERLO; n++) {
+ corrlo2[n] = tmp * corrlo[n] - aa * (corrlo[n-1] + corrlo[n+1]);
+ }
+ tmp = (1.0+aa) * (1.0+aa);
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhi[n] = tmp * corrhi[n];
+ }
+
+ /* add white noise floor */
+ corrlo2[0] += 1e-6;
+ corrhi[0] += 1e-6;
+
+
+ FwdA = 0.01;
+ FwdB = 0.01;
+
+ /* recursive filtering of correlation over subframes */
+ for (n = 0; n <= ORDERLO; n++) {
+ maskdata->CorrBufLo[n] = FwdA * maskdata->CorrBufLo[n] + corrlo2[n];
+ corrlo2[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufLo[n] + (1.0-FwdB) * corrlo2[n];
+ }
+ for (n = 0; n <= ORDERHI; n++) {
+ maskdata->CorrBufHi[n] = FwdA * maskdata->CorrBufHi[n] + corrhi[n];
+ corrhi[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufHi[n] + (1.0-FwdB) * corrhi[n];
+ }
+
+ /* compute prediction coefficients */
+ WebRtcIsac_LevDurb(a_LO, k_veclo, corrlo2, ORDERLO);
+ WebRtcIsac_LevDurb(a_HI, k_vechi, corrhi, ORDERHI);
+
+ /* bandwidth expansion */
+ tmp = gammaLo;
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LO[n] *= tmp;
+ tmp *= gammaLo;
+ }
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for (j = 0; j <= ORDERLO; j++) {
+ for (n = 0; n <= j; n++) {
+ res_nrg += a_LO[j] * corrlo2[j-n] * a_LO[n];
+ }
+ for (n = j+1; n <= ORDERLO; n++) {
+ res_nrg += a_LO[j] * corrlo2[n-j] * a_LO[n];
+ }
+ }
+
+ /* add hearing threshold and compute the gain */
+ *lo_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+ /* copy coefficients to output array */
+ for (n = 1; n <= ORDERLO; n++) {
+ *lo_coeff++ = a_LO[n];
+ }
+
+
+ /* bandwidth expansion */
+ tmp = gammaHi;
+ for (n = 1; n <= ORDERHI; n++) {
+ a_HI[n] *= tmp;
+ tmp *= gammaHi;
+ }
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for (j = 0; j <= ORDERHI; j++) {
+ for (n = 0; n <= j; n++) {
+ res_nrg += a_HI[j] * corrhi[j-n] * a_HI[n];
+ }
+ for (n = j+1; n <= ORDERHI; n++) {
+ res_nrg += a_HI[j] * corrhi[n-j] * a_HI[n];
+ }
+ }
+
+ /* add hearing threshold and compute of the gain */
+ *hi_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+ /* copy coefficients to output array */
+ for (n = 1; n <= ORDERHI; n++) {
+ *hi_coeff++ = a_HI[n];
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcCoefUb()
+ *
+ * Compute LP coefficients and correlation coefficients. At 12 kHz LP
+ * coefficients of the first and the last sub-frame is computed. At 16 kHz
+ * LP coefficients of 4th, 8th and 12th sub-frames are computed. We always
+ * compute correlation coefficients of all sub-frames.
+ *
+ * Inputs:
+ * -inSignal : Input signal
+ * -maskdata : a structure keeping signal from previous frame.
+ * -bandwidth : specifies if the codec is in 0-16 kHz mode or
+ * 0-12 kHz mode.
+ *
+ * Outputs:
+ * -lpCoeff : pointer to a buffer where A-polynomials are
+ * written to (first coeff is 1 and it is not
+ * written)
+ * -corrMat : a matrix where correlation coefficients of each
+ * sub-frame are written to one row.
+ * -varscale : a scale used to compute LPC gains.
+ */
+void
+WebRtcIsac_GetLpcCoefUb(
+ double* inSignal,
+ MaskFiltstr* maskdata,
+ double* lpCoeff,
+ double corrMat[][UB_LPC_ORDER + 1],
+ double* varscale,
+ int16_t bandwidth)
+{
+ int frameCntr, activeFrameCntr, n, pos1, pos2;
+ int16_t criterion1;
+ int16_t criterion2;
+ int16_t numSubFrames = SUBFRAMES * (1 + (bandwidth == isac16kHz));
+ double data[WINLEN];
+ double corrSubFrame[UB_LPC_ORDER+2];
+ double reflecCoeff[UB_LPC_ORDER];
+
+ double aPolynom[UB_LPC_ORDER+1];
+ double tmp;
+
+ /* bandwdith expansion factors */
+ const double gamma = 0.9;
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsac_GetVarsUB(inSignal, &(maskdata->OldEnergy), varscale);
+
+ /* replace data in buffer by new look-ahead data */
+ for(frameCntr = 0, activeFrameCntr = 0; frameCntr < numSubFrames;
+ frameCntr++)
+ {
+ if(frameCntr == SUBFRAMES)
+ {
+ // we are in 16 kHz
+ varscale++;
+ WebRtcIsac_GetVarsUB(&inSignal[FRAMESAMPLES_HALF],
+ &(maskdata->OldEnergy), varscale);
+ }
+ /* Update input buffer and multiply signal with window */
+ for(pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++)
+ {
+ maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 +
+ UPDATE/2];
+ data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ }
+ pos2 = frameCntr * UPDATE/2;
+ for(n = 0; n < UPDATE/2; n++, pos1++, pos2++)
+ {
+ maskdata->DataBufferLo[pos1] = inSignal[pos2];
+ data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ }
+
+ /* Get correlation coefficients */
+ /* computing autocorrelation */
+ WebRtcIsac_AutoCorr(corrSubFrame, data, WINLEN, UB_LPC_ORDER+1);
+ memcpy(corrMat[frameCntr], corrSubFrame,
+ (UB_LPC_ORDER+1)*sizeof(double));
+
+ criterion1 = ((frameCntr == 0) || (frameCntr == (SUBFRAMES - 1))) &&
+ (bandwidth == isac12kHz);
+ criterion2 = (((frameCntr+1) % 4) == 0) &&
+ (bandwidth == isac16kHz);
+ if(criterion1 || criterion2)
+ {
+ /* add noise */
+ corrSubFrame[0] += 1e-6;
+ /* compute prediction coefficients */
+ WebRtcIsac_LevDurb(aPolynom, reflecCoeff, corrSubFrame,
+ UB_LPC_ORDER);
+
+ /* bandwidth expansion */
+ tmp = gamma;
+ for (n = 1; n <= UB_LPC_ORDER; n++)
+ {
+ *lpCoeff++ = aPolynom[n] * tmp;
+ tmp *= gamma;
+ }
+ activeFrameCntr++;
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcGain()
+ *
+ * Compute the LPC gains for each sub-frame, given the LPC of each sub-frame
+ * and the corresponding correlation coefficients.
+ *
+ * Inputs:
+ * -signal_noise_ratio : the desired SNR in dB.
+ * -numVecs : number of sub-frames
+ * -corrMat : a matrix of correlation coefficients where
+ * each row is a set of correlation coefficients of
+ * one sub-frame.
+ * -varscale : a scale computed when WebRtcIsac_GetLpcCoefUb()
+ * is called.
+ *
+ * Outputs:
+ * -gain : pointer to a buffer where LP gains are written.
+ *
+ */
+void
+WebRtcIsac_GetLpcGain(
+ double signal_noise_ratio,
+ const double* filtCoeffVecs,
+ int numVecs,
+ double* gain,
+ double corrMat[][UB_LPC_ORDER + 1],
+ const double* varscale)
+{
+ int16_t j, n;
+ int16_t subFrameCntr;
+ double aPolynom[ORDERLO + 1];
+ double res_nrg;
+
+ const double HearThresOffset = -28.0;
+ const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+ /* divide by sqrt(12) = 3.46 */
+ const double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;
+
+ aPolynom[0] = 1;
+ for(subFrameCntr = 0; subFrameCntr < numVecs; subFrameCntr++)
+ {
+ if(subFrameCntr == SUBFRAMES)
+ {
+ // we are in second half of a SWB frame. use new varscale
+ varscale++;
+ }
+ memcpy(&aPolynom[1], &filtCoeffVecs[(subFrameCntr * (UB_LPC_ORDER + 1)) +
+ 1], sizeof(double) * UB_LPC_ORDER);
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for(j = 0; j <= UB_LPC_ORDER; j++)
+ {
+ for(n = 0; n <= j; n++)
+ {
+ res_nrg += aPolynom[j] * corrMat[subFrameCntr][j-n] *
+ aPolynom[n];
+ }
+ for(n = j+1; n <= UB_LPC_ORDER; n++)
+ {
+ res_nrg += aPolynom[j] * corrMat[subFrameCntr][n-j] *
+ aPolynom[n];
+ }
+ }
+
+ /* add hearing threshold and compute the gain */
+ gain[subFrameCntr] = S_N_R / (sqrt(res_nrg) / *varscale + H_T_H);
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h
new file mode 100644
index 0000000000..5503e2d49b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_analysis.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+void WebRtcIsac_GetLpcCoefLb(double* inLo,
+ double* inHi,
+ MaskFiltstr* maskdata,
+ double signal_noise_ratio,
+ const int16_t* pitchGains_Q12,
+ double* lo_coeff,
+ double* hi_coeff);
+
+void WebRtcIsac_GetLpcGain(double signal_noise_ratio,
+ const double* filtCoeffVecs,
+ int numVecs,
+ double* gain,
+ double corrLo[][UB_LPC_ORDER + 1],
+ const double* varscale);
+
+void WebRtcIsac_GetLpcCoefUb(double* inSignal,
+ MaskFiltstr* maskdata,
+ double* lpCoeff,
+ double corr[][UB_LPC_ORDER + 1],
+ double* varscale,
+ int16_t bandwidth);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYIS_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
new file mode 100644
index 0000000000..670754065f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.c
+ *
+ * This file defines tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+const double WebRtcIsac_kQSizeLpcGain = 0.100000;
+
+const double WebRtcIsac_kMeanLpcGain = -3.3822;
+
+/*
+* The smallest reconstruction points for quantiztion of
+* LPC gains.
+*/
+const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES] =
+{
+ -0.800000, -1.000000, -1.200000, -2.200000, -3.000000, -12.700000
+};
+
+/*
+* Number of reconstruction points of quantizers for LPC Gains.
+*/
+const int16_t WebRtcIsac_kNumQCellLpcGain[SUBFRAMES] =
+{
+ 17, 20, 25, 45, 77, 170
+};
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const uint16_t WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES] =
+{
+ 8, 10, 12, 22, 38, 85
+};
+
+/*
+* The following 6 vectors define CDF of 6 decorrelated LPC
+* gains.
+*/
+const uint16_t WebRtcIsac_kLpcGainCdfVec0[18] =
+{
+ 0, 10, 27, 83, 234, 568, 1601, 4683, 16830, 57534, 63437,
+ 64767, 65229, 65408, 65483, 65514, 65527, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec1[21] =
+{
+ 0, 15, 33, 84, 185, 385, 807, 1619, 3529, 7850, 19488,
+ 51365, 62437, 64548, 65088, 65304, 65409, 65484, 65507, 65522, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec2[26] =
+{
+ 0, 15, 29, 54, 89, 145, 228, 380, 652, 1493, 4260,
+ 12359, 34133, 50749, 57224, 60814, 62927, 64078, 64742, 65103, 65311, 65418,
+ 65473, 65509, 65521, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec3[46] =
+{
+ 0, 8, 12, 16, 26, 42, 56, 76, 111, 164, 247,
+ 366, 508, 693, 1000, 1442, 2155, 3188, 4854, 7387, 11249, 17617,
+ 30079, 46711, 56291, 60127, 62140, 63258, 63954, 64384, 64690, 64891, 65031,
+ 65139, 65227, 65293, 65351, 65399, 65438, 65467, 65492, 65504, 65510, 65518,
+ 65523, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec4[78] =
+{
+ 0, 17, 29, 39, 51, 70, 104, 154, 234, 324, 443,
+ 590, 760, 971, 1202, 1494, 1845, 2274, 2797, 3366, 4088, 4905,
+ 5899, 7142, 8683, 10625, 12983, 16095, 20637, 28216, 38859, 47237, 51537,
+ 54150, 56066, 57583, 58756, 59685, 60458, 61103, 61659, 62144, 62550, 62886,
+ 63186, 63480, 63743, 63954, 64148, 64320, 64467, 64600, 64719, 64837, 64939,
+ 65014, 65098, 65160, 65211, 65250, 65290, 65325, 65344, 65366, 65391, 65410,
+ 65430, 65447, 65460, 65474, 65487, 65494, 65501, 65509, 65513, 65518, 65520,
+ 65535
+};
+
+const uint16_t WebRtcIsac_kLpcGainCdfVec5[171] =
+{
+ 0, 10, 12, 14, 16, 18, 23, 29, 35, 42, 51,
+ 58, 65, 72, 78, 87, 96, 103, 111, 122, 134, 150,
+ 167, 184, 202, 223, 244, 265, 289, 315, 346, 379, 414,
+ 450, 491, 532, 572, 613, 656, 700, 751, 802, 853, 905,
+ 957, 1021, 1098, 1174, 1250, 1331, 1413, 1490, 1565, 1647, 1730,
+ 1821, 1913, 2004, 2100, 2207, 2314, 2420, 2532, 2652, 2783, 2921,
+ 3056, 3189, 3327, 3468, 3640, 3817, 3993, 4171, 4362, 4554, 4751,
+ 4948, 5142, 5346, 5566, 5799, 6044, 6301, 6565, 6852, 7150, 7470,
+ 7797, 8143, 8492, 8835, 9181, 9547, 9919, 10315, 10718, 11136, 11566,
+ 12015, 12482, 12967, 13458, 13953, 14432, 14903, 15416, 15936, 16452, 16967,
+ 17492, 18024, 18600, 19173, 19736, 20311, 20911, 21490, 22041, 22597, 23157,
+ 23768, 24405, 25034, 25660, 26280, 26899, 27614, 28331, 29015, 29702, 30403,
+ 31107, 31817, 32566, 33381, 34224, 35099, 36112, 37222, 38375, 39549, 40801,
+ 42074, 43350, 44626, 45982, 47354, 48860, 50361, 51845, 53312, 54739, 56026,
+ 57116, 58104, 58996, 59842, 60658, 61488, 62324, 63057, 63769, 64285, 64779,
+ 65076, 65344, 65430, 65500, 65517, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LPC Gains
+*/
+const uint16_t* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES] =
+{
+ WebRtcIsac_kLpcGainCdfVec0, WebRtcIsac_kLpcGainCdfVec1,
+ WebRtcIsac_kLpcGainCdfVec2, WebRtcIsac_kLpcGainCdfVec3,
+ WebRtcIsac_kLpcGainCdfVec4, WebRtcIsac_kLpcGainCdfVec5
+};
+
+/*
+* A matrix to decorrellate LPC gains of subframes.
+*/
+const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES] =
+{
+ {-0.150860, 0.327872, 0.367220, 0.504613, 0.559270, 0.409234},
+ { 0.457128, -0.613591, -0.289283, -0.029734, 0.393760, 0.418240},
+ {-0.626043, 0.136489, -0.439118, -0.448323, 0.135987, 0.420869},
+ { 0.526617, 0.480187, 0.242552, -0.488754, -0.158713, 0.411331},
+ {-0.302587, -0.494953, 0.588112, -0.063035, -0.404290, 0.387510},
+ { 0.086378, 0.147714, -0.428875, 0.548300, -0.570121, 0.401391}
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
new file mode 100644
index 0000000000..39c4a24ef4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.h
+ *
+ * This file declares tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+extern const double WebRtcIsac_kQSizeLpcGain;
+
+extern const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES];
+
+extern const int16_t WebRtcIsac_kNumQCellLpcGain[SUBFRAMES];
+
+extern const uint16_t WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec0[18];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec1[21];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec2[26];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec3[46];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec4[78];
+
+extern const uint16_t WebRtcIsac_kLpcGainCdfVec5[171];
+
+extern const uint16_t* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES];
+
+extern const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES];
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
new file mode 100644
index 0000000000..e3600a7fab
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER] =
+{
+ 0.03748928306641, 0.09453441192543, -0.01112522344398, 0.03800237516842
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+ {-0.00075365493856, -0.05809964887743, -0.23397966154116, 0.97050367376411},
+ { 0.00625021257734, -0.17299965610679, 0.95977735920651, 0.22104179375008},
+ { 0.20543384258374, -0.96202143495696, -0.15301870801552, -0.09432375099565},
+ {-0.97865075648479, -0.20300322280841, -0.02581111653779, -0.01913568980258}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb12
+[UB_LPC_VEC_PER_FRAME][UB_LPC_VEC_PER_FRAME] =
+{
+ { 0.70650597970460, -0.70770707262373},
+ {-0.70770707262373, -0.70650597970460}
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb12 = 0.150000;
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb12
+[UB_LPC_ORDER*UB_LPC_VEC_PER_FRAME] =
+{
+ -0.900000, -1.050000, -1.350000, -1.800000, -1.350000, -1.650000,
+ -2.250000, -3.450000
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const int16_t WebRtcIsac_kLpcShapeNumRecPointUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ 13, 15, 19, 27, 19, 24, 32, 48
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const uint16_t WebRtcIsac_kLpcShapeEntropySearchUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ 6, 7, 9, 13, 9, 12, 16, 24
+};
+
+/*
+* The following 8 vectors define CDF of 8 decorrelated LAR
+* coefficients.
+*/
+const uint16_t WebRtcIsac_kLpcShapeCdfVec0Ub12[14] =
+{
+ 0, 13, 95, 418, 1687, 6498, 21317, 44200, 59029, 63849, 65147,
+ 65449, 65525, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub12[16] =
+{
+ 0, 10, 59, 255, 858, 2667, 8200, 22609, 42988, 57202, 62947,
+ 64743, 65308, 65476, 65522, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub12[20] =
+{
+ 0, 18, 40, 118, 332, 857, 2017, 4822, 11321, 24330, 41279,
+ 54342, 60637, 63394, 64659, 65184, 65398, 65482, 65518, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub12[28] =
+{
+ 0, 21, 38, 90, 196, 398, 770, 1400, 2589, 4650, 8211,
+ 14933, 26044, 39592, 50814, 57452, 60971, 62884, 63995, 64621, 65019, 65273,
+ 65410, 65480, 65514, 65522, 65531, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub12[20] =
+{
+ 0, 7, 46, 141, 403, 969, 2132, 4649, 10633, 24902, 43254,
+ 54665, 59928, 62674, 64173, 64938, 65293, 65464, 65523, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub12[25] =
+{
+ 0, 7, 22, 72, 174, 411, 854, 1737, 3545, 6774, 13165,
+ 25221, 40980, 52821, 58714, 61706, 63472, 64437, 64989, 65287, 65430, 65503,
+ 65525, 65529, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub12[33] =
+{
+ 0, 11, 21, 36, 65, 128, 228, 401, 707, 1241, 2126,
+ 3589, 6060, 10517, 18853, 31114, 42477, 49770, 54271, 57467, 59838, 61569,
+ 62831, 63772, 64433, 64833, 65123, 65306, 65419, 65466, 65499, 65519, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub12[49] =
+{
+ 0, 14, 34, 67, 107, 167, 245, 326, 449, 645, 861,
+ 1155, 1508, 2003, 2669, 3544, 4592, 5961, 7583, 9887, 13256, 18765,
+ 26519, 34077, 40034, 44349, 47795, 50663, 53262, 55473, 57458, 59122, 60592,
+ 61742, 62690, 63391, 63997, 64463, 64794, 65045, 65207, 65309, 65394, 65443,
+ 65478, 65504, 65514, 65523, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const uint16_t* WebRtcIsac_kLpcShapeCdfMatUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ WebRtcIsac_kLpcShapeCdfVec0Ub12, WebRtcIsac_kLpcShapeCdfVec1Ub12,
+ WebRtcIsac_kLpcShapeCdfVec2Ub12, WebRtcIsac_kLpcShapeCdfVec3Ub12,
+ WebRtcIsac_kLpcShapeCdfVec4Ub12, WebRtcIsac_kLpcShapeCdfVec5Ub12,
+ WebRtcIsac_kLpcShapeCdfVec6Ub12, WebRtcIsac_kLpcShapeCdfVec7Ub12
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
new file mode 100644
index 0000000000..7448a1e76b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb12_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+extern const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kMeanLpcGain;
+
+extern const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER]
+ [UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb12[UB_LPC_VEC_PER_FRAME]
+ [UB_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb12;
+
+extern const double
+ WebRtcIsac_kLpcShapeLeftRecPointUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const int16_t
+ WebRtcIsac_kLpcShapeNumRecPointUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const uint16_t
+ WebRtcIsac_kLpcShapeEntropySearchUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec0Ub12[14];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub12[16];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub12[20];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub12[28];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub12[20];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub12[25];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub12[33];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub12[49];
+
+extern const uint16_t*
+ WebRtcIsac_kLpcShapeCdfMatUb12[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
new file mode 100644
index 0000000000..59617fd274
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB16_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER] =
+{
+0.454978, 0.364747, 0.102999, 0.104523
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+ {-0.020528, -0.085858, -0.002431, 0.996093},
+ {-0.033155, 0.036102, 0.998786, 0.004866},
+ { 0.202627, 0.974853, -0.028940, 0.088132},
+ {-0.978479, 0.202454, -0.039785, -0.002811}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb16
+[UB16_LPC_VEC_PER_FRAME][UB16_LPC_VEC_PER_FRAME] =
+{
+ { 0.291675, -0.515786, 0.644927, 0.482658},
+ {-0.647220, 0.479712, 0.289556, 0.516856},
+ { 0.643084, 0.485489, -0.289307, 0.516763},
+ {-0.287185, -0.517823, -0.645389, 0.482553}
+};
+
+/*
+* The following 16 vectors define CDF of 16 decorrelated LAR
+* coefficients.
+*/
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub16[14] =
+{
+ 0, 2, 20, 159, 1034, 5688, 20892, 44653,
+ 59849, 64485, 65383, 65518, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub16[16] =
+{
+ 0, 1, 7, 43, 276, 1496, 6681, 21653,
+ 43891, 58859, 64022, 65248, 65489, 65529, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub16[18] =
+{
+ 0, 1, 9, 54, 238, 933, 3192, 9461,
+ 23226, 42146, 56138, 62413, 64623, 65300, 65473, 65521,
+ 65533, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub16[30] =
+{
+ 0, 2, 4, 8, 17, 36, 75, 155,
+ 329, 683, 1376, 2662, 5047, 9508, 17526, 29027,
+ 40363, 48997, 55096, 59180, 61789, 63407, 64400, 64967,
+ 65273, 65429, 65497, 65526, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub16[16] =
+{
+ 0, 1, 10, 63, 361, 1785, 7407, 22242,
+ 43337, 58125, 63729, 65181, 65472, 65527, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub16[17] =
+{
+ 0, 1, 7, 29, 134, 599, 2443, 8590,
+ 22962, 42635, 56911, 63060, 64940, 65408, 65513, 65531,
+ 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub16[21] =
+{
+ 0, 1, 5, 16, 57, 191, 611, 1808,
+ 4847, 11755, 24612, 40910, 53789, 60698, 63729, 64924,
+ 65346, 65486, 65523, 65532, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub16[36] =
+{
+ 0, 1, 4, 12, 25, 55, 104, 184,
+ 314, 539, 926, 1550, 2479, 3861, 5892, 8845,
+ 13281, 20018, 29019, 38029, 45581, 51557, 56057, 59284,
+ 61517, 63047, 64030, 64648, 65031, 65261, 65402, 65480,
+ 65518, 65530, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec8Ub16[21] =
+{
+ 0, 1, 2, 7, 26, 103, 351, 1149,
+ 3583, 10204, 23846, 41711, 55361, 61917, 64382, 65186,
+ 65433, 65506, 65528, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub160[21] =
+{
+ 0, 6, 19, 63, 205, 638, 1799, 4784,
+ 11721, 24494, 40803, 53805, 60886, 63822, 64931, 65333,
+ 65472, 65517, 65530, 65533, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub161[28] =
+{
+ 0, 1, 3, 11, 31, 86, 221, 506,
+ 1101, 2296, 4486, 8477, 15356, 26079, 38941, 49952,
+ 57165, 61257, 63426, 64549, 65097, 65351, 65463, 65510,
+ 65526, 65532, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub162[55] =
+{
+ 0, 3, 12, 23, 42, 65, 89, 115,
+ 150, 195, 248, 327, 430, 580, 784, 1099,
+ 1586, 2358, 3651, 5899, 9568, 14312, 19158, 23776,
+ 28267, 32663, 36991, 41153, 45098, 48680, 51870, 54729,
+ 57141, 59158, 60772, 62029, 63000, 63761, 64322, 64728,
+ 65000, 65192, 65321, 65411, 65463, 65496, 65514, 65523,
+ 65527, 65529, 65531, 65532, 65533, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub163[26] =
+{
+ 0, 2, 4, 10, 21, 48, 114, 280,
+ 701, 1765, 4555, 11270, 24267, 41213, 54285, 61003,
+ 63767, 64840, 65254, 65421, 65489, 65514, 65526, 65532,
+ 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub164[28] =
+{
+ 0, 1, 3, 6, 15, 36, 82, 196,
+ 453, 1087, 2557, 5923, 13016, 25366, 40449, 52582,
+ 59539, 62896, 64389, 65033, 65316, 65442, 65494, 65519,
+ 65529, 65533, 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub165[34] =
+{
+ 0, 2, 4, 8, 18, 35, 73, 146,
+ 279, 524, 980, 1789, 3235, 5784, 10040, 16998,
+ 27070, 38543, 48499, 55421, 59712, 62257, 63748, 64591,
+ 65041, 65278, 65410, 65474, 65508, 65522, 65530, 65533,
+ 65534, 65535
+};
+
+const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub166[71] =
+{
+ 0, 1, 2, 6, 13, 26, 55, 92,
+ 141, 191, 242, 296, 355, 429, 522, 636,
+ 777, 947, 1162, 1428, 1753, 2137, 2605, 3140,
+ 3743, 4409, 5164, 6016, 6982, 8118, 9451, 10993,
+ 12754, 14810, 17130, 19780, 22864, 26424, 30547, 35222,
+ 40140, 44716, 48698, 52056, 54850, 57162, 59068, 60643,
+ 61877, 62827, 63561, 64113, 64519, 64807, 65019, 65167,
+ 65272, 65343, 65399, 65440, 65471, 65487, 65500, 65509,
+ 65518, 65524, 65527, 65531, 65533, 65534, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const uint16_t* WebRtcIsac_kLpcShapeCdfMatUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] = {
+ WebRtcIsac_kLpcShapeCdfVec01Ub16,
+ WebRtcIsac_kLpcShapeCdfVec1Ub16,
+ WebRtcIsac_kLpcShapeCdfVec2Ub16,
+ WebRtcIsac_kLpcShapeCdfVec3Ub16,
+ WebRtcIsac_kLpcShapeCdfVec4Ub16,
+ WebRtcIsac_kLpcShapeCdfVec5Ub16,
+ WebRtcIsac_kLpcShapeCdfVec6Ub16,
+ WebRtcIsac_kLpcShapeCdfVec7Ub16,
+ WebRtcIsac_kLpcShapeCdfVec8Ub16,
+ WebRtcIsac_kLpcShapeCdfVec01Ub160,
+ WebRtcIsac_kLpcShapeCdfVec01Ub161,
+ WebRtcIsac_kLpcShapeCdfVec01Ub162,
+ WebRtcIsac_kLpcShapeCdfVec01Ub163,
+ WebRtcIsac_kLpcShapeCdfVec01Ub164,
+ WebRtcIsac_kLpcShapeCdfVec01Ub165,
+ WebRtcIsac_kLpcShapeCdfVec01Ub166
+};
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ -0.8250, -0.9750, -1.1250, -2.1750, -0.9750, -1.1250, -1.4250,
+ -2.6250, -1.4250, -1.2750, -1.8750, -3.6750, -1.7250, -1.8750,
+ -2.3250, -5.4750
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const int16_t WebRtcIsac_kLpcShapeNumRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ 13, 15, 17, 29, 15, 16, 20, 35, 20,
+ 20, 27, 54, 25, 27, 33, 70
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const uint16_t WebRtcIsac_kLpcShapeEntropySearchUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ 6, 7, 8, 14, 7, 8, 10, 17, 10,
+ 10, 13, 27, 12, 13, 16, 35
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb16 = 0.150000;
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
new file mode 100644
index 0000000000..51101db936
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb16_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+extern const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER]
+ [UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb16[UB16_LPC_VEC_PER_FRAME]
+ [UB16_LPC_VEC_PER_FRAME];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub16[14];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec1Ub16[16];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec2Ub16[18];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec3Ub16[30];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec4Ub16[16];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec5Ub16[17];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec6Ub16[21];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec7Ub16[36];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec8Ub16[21];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub160[21];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub161[28];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub162[55];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub163[26];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub164[28];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub165[34];
+
+extern const uint16_t WebRtcIsac_kLpcShapeCdfVec01Ub166[71];
+
+extern const uint16_t*
+ WebRtcIsac_kLpcShapeCdfMatUb16[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const double
+ WebRtcIsac_kLpcShapeLeftRecPointUb16[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const int16_t
+ WebRtcIsac_kLpcShapeNumRecPointUb16[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const uint16_t
+ WebRtcIsac_kLpcShapeEntropySearchUb16[UB_LPC_ORDER *
+ UB16_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb16;
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.c
new file mode 100644
index 0000000000..461b92eb8a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* coding tables for the KLT coefficients */
+
+#include "modules/audio_coding/codecs/isac/main/source/lpc_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/* cdf array for model indicator */
+const uint16_t WebRtcIsac_kQKltModelCdf[4] = {
+ 0, 15434, 37548, 65535 };
+
+/* pointer to cdf array for model indicator */
+const uint16_t *WebRtcIsac_kQKltModelCdfPtr[1] = {
+ WebRtcIsac_kQKltModelCdf };
+
+/* initial cdf index for decoder of model indicator */
+const uint16_t WebRtcIsac_kQKltModelInitIndex[1] = { 1 };
+
+/* offset to go from rounded value to quantization index */
+const short WebRtcIsac_kQKltQuantMinGain[12] = {
+ 3, 6, 4, 6, 6, 9, 5, 16, 11, 34, 32, 47 };
+
+
+const short WebRtcIsac_kQKltQuantMinShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 2, 2, 3, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 4, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 3, 4,
+ 4, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 2, 3, 2, 3, 4, 4, 5, 7, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 6, 7, 11, 9, 13, 12, 26 };
+
+/* maximum quantization index */
+const uint16_t WebRtcIsac_kQKltMaxIndGain[12] = {
+ 6, 12, 8, 14, 10, 19, 12, 31, 22, 56, 52, 138 };
+
+const uint16_t WebRtcIsac_kQKltMaxIndShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 2, 2, 2, 2, 4, 4, 5, 6, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 2, 2,
+ 2, 2, 3, 4, 5, 7, 0, 0, 0, 0,
+ 2, 0, 2, 2, 2, 2, 3, 2, 2, 4,
+ 4, 6, 6, 9, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 3, 2, 4, 4, 7, 7,
+ 9, 13, 0, 0, 2, 2, 2, 2, 2, 2,
+ 3, 4, 5, 4, 6, 8, 8, 10, 16, 25,
+ 0, 2, 2, 4, 5, 4, 4, 4, 7, 8,
+ 9, 10, 13, 19, 17, 23, 25, 49 };
+
+/* index offset */
+const uint16_t WebRtcIsac_kQKltOffsetGain[12] = {
+ 0, 7, 20, 29, 44, 55, 75, 88, 120, 143, 200, 253 };
+
+const uint16_t WebRtcIsac_kQKltOffsetShape[108] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 11, 14, 17, 20, 23, 28, 33, 39, 46, 47,
+ 48, 49, 50, 52, 53, 54, 55, 56, 58, 61,
+ 64, 67, 70, 74, 79, 85, 93, 94, 95, 96,
+ 97, 100, 101, 104, 107, 110, 113, 117, 120, 123,
+ 128, 133, 140, 147, 157, 158, 159, 160, 161, 164,
+ 167, 170, 173, 176, 179, 183, 186, 191, 196, 204,
+ 212, 222, 236, 237, 238, 241, 244, 247, 250, 253,
+ 256, 260, 265, 271, 276, 283, 292, 301, 312, 329,
+ 355, 356, 359, 362, 367, 373, 378, 383, 388, 396,
+ 405, 415, 426, 440, 460, 478, 502, 528 };
+
+/* initial cdf index for KLT coefficients */
+const uint16_t WebRtcIsac_kQKltInitIndexGain[12] = {
+ 3, 6, 4, 7, 5, 10, 6, 16, 11, 28, 26, 69};
+
+const uint16_t WebRtcIsac_kQKltInitIndexShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 3, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 2, 1, 1, 2,
+ 2, 3, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 4, 4,
+ 5, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 3, 2, 3, 4, 4, 5, 8, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 5, 7, 10, 9, 12, 13, 25 };
+
+
+/* quantizer representation levels */
+const double WebRtcIsac_kQKltLevelsGain[392] = {
+ -2.78127126, -1.76745590, -0.77913790, -0.00437329, 0.79961206,
+ 1.81775776, 2.81389782, -5.78753143, -4.88384084, -3.89320940,
+ -2.88133610, -1.92859977, -0.86347396, 0.02003888, 0.86140400,
+ 1.89667156, 2.97134967, 3.98781964, 4.91727277, 5.82865898,
+ -4.11195874, -2.80898424, -1.87547977, -0.80943825, -0.00679084,
+ 0.79573851, 1.83953397, 2.67586037, 3.76274082, -6.10933968,
+ -4.93034581, -3.89281296, -2.91530625, -1.89684163, -0.85319130,
+ -0.02275767, 0.86862017, 1.91578276, 2.96107339, 3.96543056,
+ 4.91369908, 5.91058154, 6.83848343, 8.07136925, -5.87470395,
+ -4.84703049, -3.84284597, -2.86168446, -1.89290192, -0.82798145,
+ -0.00080013, 0.82594974, 1.85754329, 2.88351798, 3.96172628,
+ -8.85684885, -7.87387461, -6.97811862, -5.93256270, -4.94301439,
+ -3.95513701, -2.96041544, -1.94031192, -0.87961478, -0.00456201,
+ 0.89911505, 1.91723376, 2.94011511, 3.93302540, 4.97990967,
+ 5.93133404, 7.02181199, 7.92407762, 8.80155440, 10.04665814,
+ -4.82396678, -3.85612158, -2.89482244, -1.89558408, -0.90036978,
+ -0.00677823, 0.90607989, 1.90937981, 2.91175777, 3.91637730,
+ 4.97565723, 5.84771228, 7.11145863, -16.07879840, -15.03776309,
+ -13.93905670, -12.95671800, -11.89171202, -10.95820934, -9.95923714,
+ -8.94357334, -7.99068299, -6.97481009, -5.94826231, -4.96673988,
+ -3.97490466, -2.97846970, -1.95130435, -0.94215262, -0.01444043,
+ 0.96770704, 1.95848598, 2.94107862, 3.95666119, 4.97253085,
+ 5.97191122, 6.93277360, 7.96608727, 8.87958779, 10.00264269,
+ 10.86560820, 12.07449071, 13.04491775, 13.97507061, 14.91845261,
+ -10.85696295, -9.83365357, -9.01245635, -7.95915145, -6.95625003,
+ -5.95362618, -4.93468444, -3.98760978, -2.95044407, -1.97041277,
+ -0.97701799, -0.00840234, 0.97834289, 1.98361415, 2.97802439,
+ 3.96415871, 4.95369042, 5.94101770, 6.92756798, 7.94063998,
+ 8.85951828, 9.97077022, 11.00068503, -33.92030406, -32.81426422,
+ -32.00000000, -31.13243639, -30.11886909, -29.06017570, -28.12598824,
+ -27.22045482, -25.81215858, -25.07849962, -23.93018013, -23.02097643,
+ -21.89529725, -20.99091085, -19.98889048, -18.94327044, -17.96562071,
+ -16.96126218, -15.95054062, -14.98516200, -13.97101012, -13.02106500,
+ -11.98438006, -11.03216748, -9.95930286, -8.97043946, -7.98085082,
+ -6.98360995, -5.98998802, -4.98668173, -4.00032906, -3.00420619,
+ -1.98701132, -0.99324682, -0.00609324, 0.98297834, 1.99483076,
+ 3.00305044, 3.97142097, 4.97525759, 5.98612258, 6.97448236,
+ 7.97575900, 9.01086211, 9.98665542, 11.00541438, 11.98078628,
+ 12.92352471, 14.06849675, 14.99949430, 15.94904834, 16.97440321,
+ 18.04040916, 18.88987609, 20.05312391, 21.00000000, 21.79443341,
+ -31.98578825, -31.00000000, -29.89060567, -28.98555686, -27.97114102,
+ -26.84935410, -26.02402230, -24.94195278, -23.92336849, -22.95552382,
+ -21.97932836, -20.96055470, -19.99649553, -19.03436122, -17.96706525,
+ -17.01139515, -16.01363516, -14.99154248, -14.00298333, -12.99630613,
+ -11.99955519, -10.99000421, -10.00819092, -8.99763648, -7.98431793,
+ -7.01769025, -5.99604690, -4.99980697, -3.99334671, -3.01748192,
+ -2.02051217, -1.00848371, -0.01942358, 1.00477757, 1.95477872,
+ 2.98593031, 3.98779079, 4.96862849, 6.02694771, 6.93983733,
+ 7.89874717, 8.99615862, 10.02367921, 10.96293452, 11.84351528,
+ 12.92207187, 13.85122329, 15.05146877, 15.99371264, 17.00000000,
+ 18.00000000, 19.00000000, 19.82763573, -47.00000000, -46.00000000,
+ -44.87138498, -44.00000000, -43.00000000, -42.00000000, -41.00000000,
+ -39.88966612, -38.98913239, -37.80306486, -37.23584325, -35.94200288,
+ -34.99881301, -34.11361858, -33.06507360, -32.13129135, -30.90891364,
+ -29.81511907, -28.99250380, -28.04535391, -26.99767800, -26.04418164,
+ -24.95687851, -24.04865595, -23.03392645, -21.89366707, -20.93517364,
+ -19.99388660, -18.91620943, -18.03749683, -16.99532379, -15.98683813,
+ -15.06421479, -13.99359211, -12.99714098, -11.97022520, -10.98500279,
+ -9.98834422, -8.95729330, -8.01232284, -7.00253661, -5.99681626,
+ -5.01207817, -3.95914904, -3.01232178, -1.96615919, -0.97687670,
+ 0.01228030, 0.98412288, 2.01753544, 3.00580570, 3.97783510,
+ 4.98846894, 6.01321400, 7.00867732, 8.00416375, 9.01771966,
+ 9.98637729, 10.98255180, 11.99194163, 13.01807333, 14.00999545,
+ 15.00118556, 16.00089224, 17.00584148, 17.98251763, 18.99942091,
+ 19.96917690, 20.97839265, 21.98207297, 23.00171271, 23.99930737,
+ 24.99746061, 26.00936304, 26.98240132, 28.01126868, 29.01395915,
+ 29.98153507, 31.01376711, 31.99876818, 33.00475317, 33.99753994,
+ 34.99493913, 35.98933585, 36.95620160, 37.98428461, 38.99317544,
+ 40.01832073, 40.98048133, 41.95999283, 42.98232091, 43.96523612,
+ 44.99574268, 45.99524194, 47.05464025, 48.03821548, 48.99354366,
+ 49.96400411, 50.98017973, 51.95184408, 52.96291806, 54.00194392,
+ 54.96603783, 55.95623778, 57.03076595, 58.05889901, 58.99081551,
+ 59.97928121, 61.05071612, 62.03971580, 63.01286038, 64.01290338,
+ 65.02074503, 65.99454594, 67.00399425, 67.96571257, 68.95305727,
+ 69.92030664, 70.95594862, 71.98088567, 73.04764124, 74.00285480,
+ 75.02696330, 75.89837673, 76.93459997, 78.16266309, 78.83317543,
+ 80.00000000, 80.87251574, 82.09803524, 83.10671664, 84.00000000,
+ 84.77023523, 86.00000000, 87.00000000, 87.92946897, 88.69159118,
+ 90.00000000, 90.90535270 };
+
+const double WebRtcIsac_kQKltLevelsShape[578] = {
+ 0.00032397, 0.00008053, -0.00061202, -0.00012620, 0.00030437,
+ 0.00054764, -0.00027902, 0.00069360, 0.00029449, -0.80219239,
+ 0.00091089, -0.74514927, -0.00094283, 0.64030631, -0.60509119,
+ 0.00035575, 0.61851665, -0.62129957, 0.00375219, 0.60054900,
+ -0.61554359, 0.00054977, 0.63362016, -1.73118727, -0.65422341,
+ 0.00524568, 0.66165298, 1.76785515, -1.83182018, -0.65997434,
+ -0.00011887, 0.67524299, 1.79933938, -1.76344480, -0.72547708,
+ -0.00133017, 0.73104704, 1.75305377, 2.85164534, -2.80423916,
+ -1.71959639, -0.75419722, -0.00329945, 0.77196760, 1.72211069,
+ 2.87339653, 0.00031089, -0.00015311, 0.00018201, -0.00035035,
+ -0.77357251, 0.00154647, -0.00047625, -0.00045299, 0.00086590,
+ 0.00044762, -0.83383829, 0.00024787, -0.68526258, -0.00122472,
+ 0.64643255, -0.60904942, -0.00448987, 0.62309184, -0.59626442,
+ -0.00574132, 0.62296546, -0.63222115, 0.00013441, 0.63609545,
+ -0.66911055, -0.00369971, 0.66346095, 2.07281301, -1.77184694,
+ -0.67640425, -0.00010145, 0.64818392, 1.74948973, -1.69420224,
+ -0.71943894, -0.00004680, 0.75303493, 1.81075983, 2.80610041,
+ -2.80005755, -1.79866753, -0.77409777, -0.00084220, 0.80141293,
+ 1.78291081, 2.73954236, 3.82994169, 0.00015140, -0.00012766,
+ -0.00034241, -0.00119125, -0.76113497, 0.00069246, 0.76722027,
+ 0.00132862, -0.69107530, 0.00010656, 0.77061578, -0.78012970,
+ 0.00095947, 0.77828502, -0.64787758, 0.00217168, 0.63050167,
+ -0.58601125, 0.00306596, 0.59466308, -0.58603410, 0.00059779,
+ 0.64257970, 1.76512766, -0.61193600, -0.00259517, 0.59767574,
+ -0.61026273, 0.00315811, 0.61725479, -1.69169719, -0.65816029,
+ 0.00067575, 0.65576890, 2.00000000, -1.72689193, -0.69780808,
+ -0.00040990, 0.70668487, 1.74198458, -3.79028154, -3.00000000,
+ -1.73194459, -0.70179341, -0.00106695, 0.71302629, 1.76849782,
+ -2.89332364, -1.78585007, -0.78731491, -0.00132610, 0.79692976,
+ 1.75247009, 2.97828682, -5.26238694, -3.69559829, -2.87286122,
+ -1.84908818, -0.84434577, -0.01167975, 0.84641753, 1.84087672,
+ 2.87628156, 3.83556679, -0.00190204, 0.00092642, 0.00354385,
+ -0.00012982, -0.67742785, 0.00229509, 0.64935672, -0.58444751,
+ 0.00470733, 0.57299534, -0.58456202, -0.00097715, 0.64593607,
+ -0.64060330, -0.00638534, 0.59680157, -0.59287537, 0.00490772,
+ 0.58919707, -0.60306173, -0.00417464, 0.60562100, -1.75218757,
+ -0.63018569, -0.00225922, 0.63863300, -0.63949939, -0.00126421,
+ 0.64268914, -1.75851182, -0.68318060, 0.00510418, 0.69049211,
+ 1.88178506, -1.71136148, -0.72710534, -0.00815559, 0.73412917,
+ 1.79996711, -2.77111145, -1.73940498, -0.78212945, 0.01074476,
+ 0.77688916, 1.76873972, 2.87281379, 3.77554698, -3.75832725,
+ -2.95463235, -1.80451491, -0.80017226, 0.00149902, 0.80729206,
+ 1.78265046, 2.89391793, -3.78236148, -2.83640598, -1.82532067,
+ -0.88844327, -0.00620952, 0.88208030, 1.85757631, 2.81712391,
+ 3.88430176, 5.16179367, -7.00000000, -5.93805408, -4.87172597,
+ -3.87524433, -2.89399744, -1.92359563, -0.92136341, -0.00172725,
+ 0.93087018, 1.90528280, 2.89809686, 3.88085708, 4.89147740,
+ 5.89078692, -0.00239502, 0.00312564, -1.00000000, 0.00178325,
+ 1.00000000, -0.62198029, 0.00143254, 0.65344051, -0.59851220,
+ -0.00676987, 0.61510140, -0.58894151, 0.00385055, 0.59794203,
+ -0.59808568, -0.00038214, 0.57625703, -0.63009713, -0.01107985,
+ 0.61278758, -0.64206758, -0.00154369, 0.65480598, 1.80604162,
+ -1.80909286, -0.67810514, 0.00205762, 0.68571097, 1.79453891,
+ -3.22682422, -1.73808453, -0.71870305, -0.00738594, 0.71486172,
+ 1.73005326, -1.66891897, -0.73689615, -0.00616203, 0.74262409,
+ 1.73807899, -2.92417482, -1.73866741, -0.78133871, 0.00764425,
+ 0.80027264, 1.78668732, 2.74992588, -4.00000000, -2.75578740,
+ -1.83697516, -0.83117035, -0.00355191, 0.83527172, 1.82814700,
+ 2.77377675, 3.80718693, -3.81667698, -2.83575471, -1.83372350,
+ -0.86579471, 0.00547578, 0.87582281, 1.82858793, 2.87265007,
+ 3.91405377, -4.87521600, -3.78999094, -2.86437014, -1.86964365,
+ -0.90618018, 0.00128243, 0.91497811, 1.87374952, 2.83199819,
+ 3.91519130, 4.76632822, -6.68713448, -6.01252467, -4.94587936,
+ -3.88795368, -2.91299088, -1.92592211, -0.95504570, -0.00089980,
+ 0.94565200, 1.93239633, 2.91832808, 3.91363475, 4.88920034,
+ 5.96471415, 6.83905252, 7.86195009, 8.81571018,-12.96141759,
+ -11.73039516,-10.96459719, -9.97382433, -9.04414433, -7.89460619,
+ -6.96628608, -5.93236595, -4.93337924, -3.95479990, -2.96451499,
+ -1.96635876, -0.97271229, -0.00402238, 0.98343930, 1.98348291,
+ 2.96641164, 3.95456471, 4.95517089, 5.98975714, 6.90322073,
+ 7.90468849, 8.85639467, 9.97255498, 10.79006309, 11.81988596,
+ 0.04950500, -1.00000000, -0.01226628, 1.00000000, -0.59479469,
+ -0.10438305, 0.59822144, -2.00000000, -0.67109149, -0.09256692,
+ 0.65171621, 2.00000000, -3.00000000, -1.68391999, -0.76681039,
+ -0.03354151, 0.71509146, 1.77615472, -2.00000000, -0.68661511,
+ -0.02497881, 0.66478398, 2.00000000, -2.00000000, -0.67032784,
+ -0.00920582, 0.64892756, 2.00000000, -2.00000000, -0.68561894,
+ 0.03641869, 0.73021611, 1.68293863, -4.00000000, -2.72024184,
+ -1.80096059, -0.81696185, 0.03604685, 0.79232033, 1.70070730,
+ 3.00000000, -4.00000000, -2.71795670, -1.80482986, -0.86001162,
+ 0.03764903, 0.87723968, 1.79970771, 2.72685932, 3.67589143,
+ -5.00000000, -4.00000000, -2.85492548, -1.78996365, -0.83250358,
+ -0.01376828, 0.84195506, 1.78161105, 2.76754458, 4.00000000,
+ -6.00000000, -5.00000000, -3.82268811, -2.77563624, -1.82608163,
+ -0.86486114, -0.02671886, 0.86693165, 1.88422879, 2.86248347,
+ 3.95632216, -7.00000000, -6.00000000, -5.00000000, -3.77533988,
+ -2.86391432, -1.87052039, -0.90513658, 0.06271236, 0.91083620,
+ 1.85734756, 2.86031688, 3.82019418, 4.94420394, 6.00000000,
+ -11.00000000,-10.00000000, -9.00000000, -8.00000000, -6.91952415,
+ -6.00000000, -4.92044374, -3.87845165, -2.87392362, -1.88413020,
+ -0.91915740, 0.00318517, 0.91602800, 1.89664838, 2.88925058,
+ 3.84123856, 4.78988651, 5.94526812, 6.81953917, 8.00000000,
+ -9.00000000, -8.00000000, -7.03319143, -5.94530963, -4.86669720,
+ -3.92438007, -2.88620396, -1.92848070, -0.94365985, 0.01671855,
+ 0.97349410, 1.93419878, 2.89740109, 3.89662823, 4.83235583,
+ 5.88106535, 6.80328232, 8.00000000,-13.00000000,-12.00000000,
+ -11.00000000,-10.00000000, -9.00000000, -7.86033489, -6.83344055,
+ -5.89844215, -4.90811454, -3.94841298, -2.95820490, -1.98627966,
+ -0.99161468, -0.02286136, 0.96055651, 1.95052433, 2.93969396,
+ 3.94304346, 4.88522624, 5.87434241, 6.78309433, 7.87244101,
+ 9.00000000, 10.00000000,-12.09117356,-11.00000000,-10.00000000,
+ -8.84766108, -7.86934236, -6.98544896, -5.94233429, -4.95583292,
+ -3.95575986, -2.97085529, -1.98955811, -0.99359873, -0.00485413,
+ 0.98298870, 1.98093258, 2.96430203, 3.95540216, 4.96915010,
+ 5.96775124, 6.99236918, 7.96503302, 8.99864542, 9.85857723,
+ 10.96541926, 11.91647197, 12.71060069,-26.00000000,-25.00000000,
+ -24.00585596,-23.11642573,-22.14271284,-20.89800711,-19.87815799,
+ -19.05036354,-17.88555651,-16.86471209,-15.97711073,-14.94012359,
+ -14.02661226,-12.98243228,-11.97489256,-10.97402777, -9.96425624,
+ -9.01085220, -7.97372506, -6.98795002, -5.97271328, -5.00191694,
+ -3.98055849, -2.98458048, -1.99470442, -0.99656768, -0.00825666,
+ 1.00272004, 1.99922218, 2.99357669, 4.01407905, 5.01003897,
+ 5.98115528, 7.00018958, 8.00338125, 8.98981046, 9.98990318,
+ 10.96341479, 11.96866930, 12.99175139, 13.94580443, 14.95745083,
+ 15.98992869, 16.97484646, 17.99630043, 18.93396897, 19.88347741,
+ 20.96532482, 21.92191032, 23.22314702 };
+
+
+/* cdf tables for quantizer indices */
+const uint16_t WebRtcIsac_kQKltCdfGain[404] = {
+ 0, 13, 301, 3730, 61784, 65167, 65489, 65535, 0, 17,
+ 142, 314, 929, 2466, 7678, 56450, 63463, 64740, 65204, 65426,
+ 65527, 65535, 0, 8, 100, 724, 6301, 60105, 65125, 65510,
+ 65531, 65535, 0, 13, 117, 368, 1068, 3010, 11928, 53603,
+ 61177, 63404, 64505, 65108, 65422, 65502, 65531, 65535, 0, 4,
+ 17, 96, 410, 1859, 12125, 54361, 64103, 65305, 65497, 65535,
+ 0, 4, 88, 230, 469, 950, 1746, 3228, 6092, 16592,
+ 44756, 56848, 61256, 63308, 64325, 64920, 65309, 65460, 65502,
+ 65522, 65535, 0, 88, 352, 1675, 6339, 20749, 46686, 59284, 63525,
+ 64949, 65359, 65502, 65527, 65535, 0, 13, 38, 63, 117,
+ 234, 381, 641, 929, 1407, 2043, 2809, 4032, 5753, 8792,
+ 14407, 24308, 38941, 48947, 55403, 59293, 61411, 62688, 63630,
+ 64329, 64840, 65188, 65376, 65472, 65506, 65527, 65531, 65535,
+ 0, 8, 29, 75, 222, 615, 1327, 2801, 5623, 9931, 16094, 24966,
+ 34419, 43458, 50676, 56186, 60055, 62500, 63936, 64765, 65225,
+ 65435, 65514, 65535, 0, 8, 13, 15, 17, 21, 33, 59,
+ 71, 92, 151, 243, 360, 456, 674, 934, 1223, 1583,
+ 1989, 2504, 3031, 3617, 4354, 5154, 6163, 7411, 8780, 10747,
+ 12874, 15591, 18974, 23027, 27436, 32020, 36948, 41830, 46205,
+ 49797, 53042, 56094, 58418, 60360, 61763, 62818, 63559, 64103,
+ 64509, 64798, 65045, 65162, 65288, 65363, 65447, 65506, 65522,
+ 65531, 65533, 65535, 0, 4, 6, 25, 38, 71, 138, 264, 519, 808,
+ 1227, 1825, 2516, 3408, 4279, 5560, 7092, 9197, 11420, 14108,
+ 16947, 20300, 23926, 27459, 31164, 34827, 38575, 42178, 45540,
+ 48747, 51444, 54090, 56426, 58460, 60080, 61595, 62734, 63668,
+ 64275, 64673, 64936, 65112, 65217, 65334, 65426, 65464, 65477,
+ 65489, 65518, 65527, 65529, 65531, 65533, 65535, 0, 2, 4, 8, 10,
+ 12, 14, 16, 21, 33, 50, 71, 84, 92, 105, 138, 180, 255, 318,
+ 377, 435, 473, 511, 590, 682, 758, 913, 1097, 1256, 1449, 1671,
+ 1884, 2169, 2445, 2772, 3157, 3563, 3944, 4375, 4848, 5334, 5820,
+ 6448, 7101, 7716, 8378, 9102, 9956, 10752, 11648, 12707, 13670,
+ 14758, 15910, 17187, 18472, 19627, 20649, 21951, 23169, 24283,
+ 25552, 26862, 28227, 29391, 30764, 31882, 33213, 34432, 35600,
+ 36910, 38116, 39464, 40729, 41872, 43144, 44371, 45514, 46762,
+ 47813, 48968, 50069, 51032, 51974, 52908, 53737, 54603, 55445,
+ 56282, 56990, 57572, 58191, 58840, 59410, 59887, 60264, 60607,
+ 60946, 61269, 61516, 61771, 61960, 62198, 62408, 62558, 62776,
+ 62985, 63207, 63408, 63546, 63739, 63906, 64070, 64237, 64371,
+ 64551, 64677, 64836, 64999, 65095, 65213, 65284, 65338, 65380,
+ 65426, 65447, 65472, 65485, 65487, 65489, 65502, 65510, 65512,
+ 65514, 65516, 65518, 65522, 65531, 65533, 65535 };
+
+
+const uint16_t WebRtcIsac_kQKltCdfShape[686] = {
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4,
+ 65535, 0, 8, 65514, 65535, 0, 29, 65481, 65535, 0,
+ 121, 65439, 65535, 0, 239, 65284, 65535, 0, 8, 779,
+ 64999, 65527, 65535, 0, 8, 888, 64693, 65522, 65535, 0,
+ 29, 2604, 62843, 65497, 65531, 65535, 0, 25, 176, 4576,
+ 61164, 65275, 65527, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 4, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 4, 65535, 0, 33, 65502, 65535,
+ 0, 54, 65481, 65535, 0, 251, 65309, 65535, 0, 611,
+ 65074, 65535, 0, 1273, 64292, 65527, 65535, 0, 4, 1809,
+ 63940, 65518, 65535, 0, 88, 4392, 60603, 65426, 65531, 65535,
+ 0, 25, 419, 7046, 57756, 64961, 65514, 65531, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4, 65531,
+ 65535, 0, 65535, 0, 8, 65531, 65535, 0, 4, 65527,
+ 65535, 0, 17, 65510, 65535, 0, 42, 65481, 65535, 0,
+ 197, 65342, 65531, 65535, 0, 385, 65154, 65535, 0, 1005,
+ 64522, 65535, 0, 8, 1985, 63469, 65533, 65535, 0, 38,
+ 3119, 61884, 65514, 65535, 0, 4, 6, 67, 4961, 60804,
+ 65472, 65535, 0, 17, 565, 9182, 56538, 65087, 65514, 65535,
+ 0, 8, 63, 327, 2118, 14490, 52774, 63839, 65376, 65522,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 17, 65522, 65535, 0, 59, 65489, 65535, 0, 50, 65522,
+ 65535, 0, 54, 65489, 65535, 0, 310, 65179, 65535, 0,
+ 615, 64836, 65535, 0, 4, 1503, 63965, 65535, 0, 2780,
+ 63383, 65535, 0, 21, 3919, 61051, 65527, 65535, 0, 84,
+ 6674, 59929, 65435, 65535, 0, 4, 255, 7976, 55784, 65150,
+ 65518, 65531, 65535, 0, 4, 8, 582, 10726, 53465, 64949,
+ 65518, 65535, 0, 29, 339, 3006, 17555, 49517, 62956, 65200,
+ 65497, 65531, 65535, 0, 2, 33, 138, 565, 2324, 7670,
+ 22089, 45966, 58949, 63479, 64966, 65380, 65518, 65535, 0, 65535,
+ 0, 65535, 0, 2, 65533, 65535, 0, 46, 65514, 65535,
+ 0, 414, 65091, 65535, 0, 540, 64911, 65535, 0, 419,
+ 65162, 65535, 0, 976, 64790, 65535, 0, 2977, 62495, 65531,
+ 65535, 0, 4, 3852, 61034, 65527, 65535, 0, 4, 29,
+ 6021, 60243, 65468, 65535, 0, 84, 6711, 58066, 65418, 65535,
+ 0, 13, 281, 9550, 54917, 65125, 65506, 65535, 0, 2,
+ 63, 984, 12108, 52644, 64342, 65435, 65527, 65535, 0, 29,
+ 251, 2014, 14871, 47553, 62881, 65229, 65518, 65535, 0, 13,
+ 142, 749, 4220, 18497, 45200, 60913, 64823, 65426, 65527, 65535,
+ 0, 13, 71, 264, 1176, 3789, 10500, 24480, 43488, 56324,
+ 62315, 64493, 65242, 65464, 65514, 65522, 65531, 65535, 0, 4,
+ 13, 38, 109, 205, 448, 850, 1708, 3429, 6276, 11371,
+ 19221, 29734, 40955, 49391, 55411, 59460, 62102, 63793, 64656,
+ 65150, 65401, 65485, 65522, 65531, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 1160, 65476, 65535, 0, 2, 6640, 64763, 65533,
+ 65535, 0, 2, 38, 9923, 61009, 65527, 65535, 0, 2,
+ 4949, 63092, 65533, 65535, 0, 2, 3090, 63398, 65533, 65535,
+ 0, 2, 2520, 58744, 65510, 65535, 0, 2, 13, 544,
+ 8784, 51403, 65148, 65533, 65535, 0, 2, 25, 1017, 10412,
+ 43550, 63651, 65489, 65527, 65535, 0, 2, 4, 29, 783,
+ 13377, 52462, 64524, 65495, 65533, 65535, 0, 2, 4, 6,
+ 100, 1817, 18451, 52590, 63559, 65376, 65531, 65535, 0, 2,
+ 4, 6, 46, 385, 2562, 11225, 37416, 60488, 65026, 65487,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 42, 222, 971, 5221, 19811, 45048, 60312, 64486, 65294, 65474,
+ 65525, 65529, 65533, 65535, 0, 2, 4, 8, 71, 167,
+ 666, 2533, 7875, 19622, 38082, 54359, 62108, 64633, 65290, 65495,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 13,
+ 109, 586, 1930, 4949, 11600, 22641, 36125, 48312, 56899, 61495,
+ 63927, 64932, 65389, 65489, 65518, 65531, 65533, 65535, 0, 4,
+ 6, 8, 67, 209, 712, 1838, 4195, 8432, 14432, 22834,
+ 31723, 40523, 48139, 53929, 57865, 60657, 62403, 63584, 64363,
+ 64907, 65167, 65372, 65472, 65514, 65535, 0, 2, 4, 13, 25,
+ 42, 46, 50, 75, 113, 147, 281, 448, 657, 909,
+ 1185, 1591, 1976, 2600, 3676, 5317, 7398, 9914, 12941, 16169,
+ 19477, 22885, 26464, 29851, 33360, 37228, 41139, 44802, 48654,
+ 52058, 55181, 57676, 59581, 61022, 62190, 63107, 63676, 64199,
+ 64547, 64924, 65158, 65313, 65430, 65481, 65518, 65535 };
+
+
+/* pointers to cdf tables for quantizer indices */
+const uint16_t *WebRtcIsac_kQKltCdfPtrGain[12] = {
+ WebRtcIsac_kQKltCdfGain +0 +0, WebRtcIsac_kQKltCdfGain +0 +8,
+ WebRtcIsac_kQKltCdfGain +0 +22, WebRtcIsac_kQKltCdfGain +0 +32,
+ WebRtcIsac_kQKltCdfGain +0 +48, WebRtcIsac_kQKltCdfGain +0 +60,
+ WebRtcIsac_kQKltCdfGain +0 +81, WebRtcIsac_kQKltCdfGain +0 +95,
+ WebRtcIsac_kQKltCdfGain +0 +128, WebRtcIsac_kQKltCdfGain +0 +152,
+ WebRtcIsac_kQKltCdfGain +0 +210, WebRtcIsac_kQKltCdfGain +0 +264 };
+
+const uint16_t *WebRtcIsac_kQKltCdfPtrShape[108] = {
+ WebRtcIsac_kQKltCdfShape +0 +0, WebRtcIsac_kQKltCdfShape +0 +2,
+ WebRtcIsac_kQKltCdfShape +0 +4, WebRtcIsac_kQKltCdfShape +0 +6,
+ WebRtcIsac_kQKltCdfShape +0 +8, WebRtcIsac_kQKltCdfShape +0 +10,
+ WebRtcIsac_kQKltCdfShape +0 +12, WebRtcIsac_kQKltCdfShape +0 +14,
+ WebRtcIsac_kQKltCdfShape +0 +16, WebRtcIsac_kQKltCdfShape +0 +18,
+ WebRtcIsac_kQKltCdfShape +0 +21, WebRtcIsac_kQKltCdfShape +0 +25,
+ WebRtcIsac_kQKltCdfShape +0 +29, WebRtcIsac_kQKltCdfShape +0 +33,
+ WebRtcIsac_kQKltCdfShape +0 +37, WebRtcIsac_kQKltCdfShape +0 +43,
+ WebRtcIsac_kQKltCdfShape +0 +49, WebRtcIsac_kQKltCdfShape +0 +56,
+ WebRtcIsac_kQKltCdfShape +0 +64, WebRtcIsac_kQKltCdfShape +0 +66,
+ WebRtcIsac_kQKltCdfShape +0 +68, WebRtcIsac_kQKltCdfShape +0 +70,
+ WebRtcIsac_kQKltCdfShape +0 +72, WebRtcIsac_kQKltCdfShape +0 +75,
+ WebRtcIsac_kQKltCdfShape +0 +77, WebRtcIsac_kQKltCdfShape +0 +79,
+ WebRtcIsac_kQKltCdfShape +0 +81, WebRtcIsac_kQKltCdfShape +0 +83,
+ WebRtcIsac_kQKltCdfShape +0 +86, WebRtcIsac_kQKltCdfShape +0 +90,
+ WebRtcIsac_kQKltCdfShape +0 +94, WebRtcIsac_kQKltCdfShape +0 +98,
+ WebRtcIsac_kQKltCdfShape +0 +102, WebRtcIsac_kQKltCdfShape +0 +107,
+ WebRtcIsac_kQKltCdfShape +0 +113, WebRtcIsac_kQKltCdfShape +0 +120,
+ WebRtcIsac_kQKltCdfShape +0 +129, WebRtcIsac_kQKltCdfShape +0 +131,
+ WebRtcIsac_kQKltCdfShape +0 +133, WebRtcIsac_kQKltCdfShape +0 +135,
+ WebRtcIsac_kQKltCdfShape +0 +137, WebRtcIsac_kQKltCdfShape +0 +141,
+ WebRtcIsac_kQKltCdfShape +0 +143, WebRtcIsac_kQKltCdfShape +0 +147,
+ WebRtcIsac_kQKltCdfShape +0 +151, WebRtcIsac_kQKltCdfShape +0 +155,
+ WebRtcIsac_kQKltCdfShape +0 +159, WebRtcIsac_kQKltCdfShape +0 +164,
+ WebRtcIsac_kQKltCdfShape +0 +168, WebRtcIsac_kQKltCdfShape +0 +172,
+ WebRtcIsac_kQKltCdfShape +0 +178, WebRtcIsac_kQKltCdfShape +0 +184,
+ WebRtcIsac_kQKltCdfShape +0 +192, WebRtcIsac_kQKltCdfShape +0 +200,
+ WebRtcIsac_kQKltCdfShape +0 +211, WebRtcIsac_kQKltCdfShape +0 +213,
+ WebRtcIsac_kQKltCdfShape +0 +215, WebRtcIsac_kQKltCdfShape +0 +217,
+ WebRtcIsac_kQKltCdfShape +0 +219, WebRtcIsac_kQKltCdfShape +0 +223,
+ WebRtcIsac_kQKltCdfShape +0 +227, WebRtcIsac_kQKltCdfShape +0 +231,
+ WebRtcIsac_kQKltCdfShape +0 +235, WebRtcIsac_kQKltCdfShape +0 +239,
+ WebRtcIsac_kQKltCdfShape +0 +243, WebRtcIsac_kQKltCdfShape +0 +248,
+ WebRtcIsac_kQKltCdfShape +0 +252, WebRtcIsac_kQKltCdfShape +0 +258,
+ WebRtcIsac_kQKltCdfShape +0 +264, WebRtcIsac_kQKltCdfShape +0 +273,
+ WebRtcIsac_kQKltCdfShape +0 +282, WebRtcIsac_kQKltCdfShape +0 +293,
+ WebRtcIsac_kQKltCdfShape +0 +308, WebRtcIsac_kQKltCdfShape +0 +310,
+ WebRtcIsac_kQKltCdfShape +0 +312, WebRtcIsac_kQKltCdfShape +0 +316,
+ WebRtcIsac_kQKltCdfShape +0 +320, WebRtcIsac_kQKltCdfShape +0 +324,
+ WebRtcIsac_kQKltCdfShape +0 +328, WebRtcIsac_kQKltCdfShape +0 +332,
+ WebRtcIsac_kQKltCdfShape +0 +336, WebRtcIsac_kQKltCdfShape +0 +341,
+ WebRtcIsac_kQKltCdfShape +0 +347, WebRtcIsac_kQKltCdfShape +0 +354,
+ WebRtcIsac_kQKltCdfShape +0 +360, WebRtcIsac_kQKltCdfShape +0 +368,
+ WebRtcIsac_kQKltCdfShape +0 +378, WebRtcIsac_kQKltCdfShape +0 +388,
+ WebRtcIsac_kQKltCdfShape +0 +400, WebRtcIsac_kQKltCdfShape +0 +418,
+ WebRtcIsac_kQKltCdfShape +0 +445, WebRtcIsac_kQKltCdfShape +0 +447,
+ WebRtcIsac_kQKltCdfShape +0 +451, WebRtcIsac_kQKltCdfShape +0 +455,
+ WebRtcIsac_kQKltCdfShape +0 +461, WebRtcIsac_kQKltCdfShape +0 +468,
+ WebRtcIsac_kQKltCdfShape +0 +474, WebRtcIsac_kQKltCdfShape +0 +480,
+ WebRtcIsac_kQKltCdfShape +0 +486, WebRtcIsac_kQKltCdfShape +0 +495,
+ WebRtcIsac_kQKltCdfShape +0 +505, WebRtcIsac_kQKltCdfShape +0 +516,
+ WebRtcIsac_kQKltCdfShape +0 +528, WebRtcIsac_kQKltCdfShape +0 +543,
+ WebRtcIsac_kQKltCdfShape +0 +564, WebRtcIsac_kQKltCdfShape +0 +583,
+ WebRtcIsac_kQKltCdfShape +0 +608, WebRtcIsac_kQKltCdfShape +0 +635 };
+
+
+/* left KLT transforms */
+const double WebRtcIsac_kKltT1Gain[4] = {
+ -0.79742827, 0.60341375, 0.60341375, 0.79742827 };
+
+const double WebRtcIsac_kKltT1Shape[324] = {
+ 0.00159597, 0.00049320, 0.00513821, 0.00021066, 0.01338581,
+ -0.00422367, -0.00272072, 0.00935107, 0.02047622, 0.02691189,
+ 0.00478236, 0.03969702, 0.00886698, 0.04877604, -0.10898362,
+ -0.05930891, -0.03415047, 0.98889721, 0.00293558, -0.00035282,
+ 0.01156321, -0.00195341, -0.00937631, 0.01052213, -0.02551163,
+ 0.01644059, 0.03189927, 0.07754773, -0.08742313, -0.03026338,
+ 0.05136248, -0.14395974, 0.17725040, 0.22664856, 0.93380230,
+ 0.07076411, 0.00557890, -0.00222834, 0.01377569, 0.01466808,
+ 0.02847361, -0.00603178, 0.02382480, -0.01210452, 0.03797267,
+ -0.02371480, 0.11260335, -0.07366682, 0.00453436, -0.04136941,
+ -0.07912843, -0.95031418, 0.25295337, -0.05302216, -0.00617554,
+ -0.00044040, -0.00653778, 0.01097838, 0.01529174, 0.01374431,
+ -0.00748512, -0.00020034, 0.02432713, 0.11101570, -0.08556891,
+ 0.09282249, -0.01029446, 0.67556443, -0.67454300, 0.06910063,
+ 0.20866865, -0.10318050, 0.00932175, 0.00524058, 0.00803610,
+ -0.00594676, -0.01082578, 0.01069906, 0.00546768, 0.01565291,
+ 0.06816200, 0.10201227, 0.16812734, 0.22984074, 0.58213170,
+ -0.54138651, -0.51379962, 0.06847390, -0.01920037, -0.04592324,
+ -0.00467394, 0.00328858, 0.00377424, -0.00987448, 0.08222096,
+ -0.00377301, 0.04551941, -0.02592517, 0.16317082, 0.13077530,
+ 0.22702921, -0.31215289, -0.69645962, -0.38047101, -0.39339411,
+ 0.11124777, 0.02508035, -0.00708074, 0.00400344, 0.00040331,
+ 0.01142402, 0.01725406, 0.01635170, 0.14285366, 0.03949233,
+ -0.05905676, 0.05877154, -0.17497577, -0.32479440, 0.80754464,
+ -0.38085603, -0.17055430, -0.03168622, -0.07531451, 0.02942002,
+ -0.02148095, -0.00754114, -0.00322372, 0.00567812, -0.01701521,
+ -0.12358320, 0.11473564, 0.09070136, 0.06533068, -0.22560802,
+ 0.19209022, 0.81605094, 0.36592275, -0.09919829, 0.16667122,
+ 0.16300725, 0.04803807, 0.06739263, -0.00156752, -0.01685302,
+ -0.00905240, -0.02297836, -0.00469939, 0.06310613, -0.16391930,
+ 0.10919511, 0.12529293, 0.85581322, -0.32145522, 0.24539076,
+ 0.07181839, 0.07289591, 0.14066759, 0.10406711, 0.05815518,
+ 0.01072680, -0.00759339, 0.00053486, -0.00044865, 0.03407361,
+ 0.01645348, 0.08758579, 0.27722240, 0.53665485, -0.74853376,
+ -0.01118192, -0.19805430, 0.06130619, -0.09675299, 0.08978480,
+ 0.03405255, -0.00706867, 0.05102045, 0.03250746, 0.01849966,
+ -0.01216314, -0.01184187, -0.01579288, 0.00114807, 0.11376166,
+ 0.88342114, -0.36425379, 0.13863190, 0.12524180, -0.13553892,
+ 0.04715856, -0.12341103, 0.04531568, 0.01899360, -0.00206897,
+ 0.00567768, -0.01444163, 0.00411946, -0.00855896, 0.00381663,
+ -0.01664861, -0.05534280, 0.21328278, 0.20161162, 0.72360394,
+ 0.59130708, -0.08043791, 0.08757349, -0.13893918, -0.05147377,
+ 0.02680690, -0.01144070, 0.00625162, -0.00634215, -0.01248947,
+ -0.00329455, -0.00609625, -0.00136305, -0.05097048, -0.01029851,
+ 0.25065384, -0.16856837, -0.07123372, 0.15992623, -0.39487617,
+ -0.79972301, 0.18118185, -0.04826639, -0.01805578, -0.02927253,
+ -0.16400618, 0.07472763, 0.10376449, 0.01705406, 0.01065801,
+ -0.01500498, 0.02039914, 0.37776349, -0.84484186, 0.10434286,
+ 0.15616990, 0.13474456, -0.00906238, -0.25238368, -0.03820885,
+ -0.10650905, -0.03880833, -0.03660028, -0.09640894, 0.00583314,
+ 0.01922097, 0.01489911, -0.02431117, -0.09372217, 0.39404721,
+ -0.84786223, -0.31277121, 0.03193850, 0.01974060, 0.01887901,
+ 0.00337911, -0.11359599, -0.02792521, -0.03220184, -0.01533311,
+ 0.00015962, -0.04225043, -0.00933965, 0.00675311, 0.00206060,
+ 0.15926771, 0.40199829, -0.80792558, -0.35591604, -0.17169764,
+ 0.02830436, 0.02459982, -0.03438589, 0.00718705, -0.01798329,
+ -0.01594508, -0.00702430, -0.00952419, -0.00962701, -0.01307212,
+ -0.01749740, 0.01299602, 0.00587270, -0.36103108, -0.82039266,
+ -0.43092844, -0.08500097, -0.04361674, -0.00333482, 0.01250434,
+ -0.02538295, -0.00921797, 0.01645071, -0.01400872, 0.00317607,
+ 0.00003277, -0.01617646, -0.00616863, -0.00882661, 0.00466157,
+ 0.00353237, 0.91803104, -0.39503305, -0.02048964, 0.00060125,
+ 0.01980634, 0.00300109, 0.00313880, 0.00657337, 0.00715163,
+ 0.00000261, 0.00854276, -0.00154825, -0.00516128, 0.00909527,
+ 0.00095609, 0.00701196, -0.00221867, -0.00156741 };
+
+/* right KLT transforms */
+const double WebRtcIsac_kKltT2Gain[36] = {
+ 0.14572837, -0.45446306, 0.61990621, -0.52197033, 0.32145074,
+ -0.11026900, -0.20698282, 0.48962182, -0.27127933, -0.33627476,
+ 0.65094037, -0.32715751, 0.40262573, -0.47844405, -0.33876075,
+ 0.44130653, 0.37383966, -0.39964662, -0.51730480, 0.06611973,
+ 0.49030187, 0.47512886, -0.02141226, -0.51129451, -0.58578569,
+ -0.39132064, -0.13187771, 0.15649421, 0.40735596, 0.54396897,
+ 0.40381276, 0.40904942, 0.41179766, 0.41167576, 0.40840251,
+ 0.40468132 };
+
+const double WebRtcIsac_kKltT2Shape[36] = {
+ 0.13427386, -0.35132558, 0.52506528, -0.59419077, 0.45075085,
+ -0.16312057, 0.29857439, -0.58660147, 0.34265431, 0.20879510,
+ -0.56063262, 0.30238345, 0.43308283, -0.41186999, -0.35288681,
+ 0.42768996, 0.36094634, -0.45284910, -0.47116680, 0.02893449,
+ 0.54326135, 0.45249040, -0.06264420, -0.52283830, 0.57137758,
+ 0.44298139, 0.12617554, -0.20819946, -0.42324603, -0.48876443,
+ 0.39597050, 0.40713935, 0.41389880, 0.41512486, 0.41130400,
+ 0.40575001 };
+
+/* means of log gains and LAR coefficients*/
+const double WebRtcIsac_kLpcMeansGain[12] = {
+ -6.86881911, -5.35075273, -6.86792680, -5.36200897, -6.86401538,
+ -5.36921533, -6.86802969, -5.36893966, -6.86538097, -5.36315063,
+ -6.85535304, -5.35155315 };
+
+const double WebRtcIsac_kLpcMeansShape[108] = {
+ -0.91232981, 0.26258634, -0.33716701, 0.08477430, -0.03378426,
+ 0.14423909, 0.07036185, 0.06155019, 0.01490385, 0.04138740,
+ 0.01427317, 0.01288970, 0.83872106, 0.25750199, 0.07988929,
+ -0.01957923, 0.00831390, 0.01770300, -0.90957164, 0.25732216,
+ -0.33385344, 0.08735740, -0.03715332, 0.14584917, 0.06998990,
+ 0.06131968, 0.01504379, 0.04067339, 0.01428039, 0.01406460,
+ 0.83846243, 0.26169862, 0.08109025, -0.01767055, 0.00970539,
+ 0.01954310, -0.90490803, 0.24656405, -0.33578607, 0.08843286,
+ -0.03749139, 0.14443959, 0.07214669, 0.06170993, 0.01449947,
+ 0.04134309, 0.01314762, 0.01413471, 0.83895203, 0.26748062,
+ 0.08197507, -0.01781298, 0.00885967, 0.01922394, -0.90922472,
+ 0.24495889, -0.33921540, 0.08877169, -0.03581332, 0.14199172,
+ 0.07444032, 0.06185940, 0.01502054, 0.04185113, 0.01276579,
+ 0.01355457, 0.83645358, 0.26631720, 0.08119697, -0.01835449,
+ 0.00788512, 0.01846446, -0.90482253, 0.24658310, -0.34019734,
+ 0.08281090, -0.03486038, 0.14359248, 0.07401336, 0.06001471,
+ 0.01528421, 0.04254560, 0.01321472, 0.01240799, 0.83857127,
+ 0.26281654, 0.08174380, -0.02099842, 0.00755176, 0.01699448,
+ -0.90132307, 0.25174308, -0.33838268, 0.07883863, -0.02877906,
+ 0.14105407, 0.07220290, 0.06000352, 0.01684879, 0.04226844,
+ 0.01331331, 0.01269244, 0.83832138, 0.25467485, 0.08118028,
+ -0.02120528, 0.00747832, 0.01567212 };
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.h
new file mode 100644
index 0000000000..56ff22c06c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/lpc_tables.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+#define KLT_STEPSIZE 1.00000000
+#define KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_GAIN_SCALE 4.000f
+#define LPC_LOBAND_SCALE 2.100f
+#define LPC_LOBAND_ORDER ORDERLO
+#define LPC_HIBAND_SCALE 0.450f
+#define LPC_HIBAND_ORDER ORDERHI
+#define LPC_GAIN_ORDER 2
+
+#define LPC_SHAPE_ORDER (LPC_LOBAND_ORDER + LPC_HIBAND_ORDER)
+
+#define KLT_ORDER_GAIN (LPC_GAIN_ORDER * SUBFRAMES)
+#define KLT_ORDER_SHAPE (LPC_SHAPE_ORDER * SUBFRAMES)
+
+/* cdf array for model indicator */
+extern const uint16_t WebRtcIsac_kQKltModelCdf[KLT_NUM_MODELS + 1];
+
+/* pointer to cdf array for model indicator */
+extern const uint16_t* WebRtcIsac_kQKltModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const uint16_t WebRtcIsac_kQKltModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const short WebRtcIsac_kQKltQuantMinGain[12];
+
+extern const short WebRtcIsac_kQKltQuantMinShape[108];
+
+/* maximum quantization index */
+extern const uint16_t WebRtcIsac_kQKltMaxIndGain[12];
+
+extern const uint16_t WebRtcIsac_kQKltMaxIndShape[108];
+
+/* index offset */
+extern const uint16_t WebRtcIsac_kQKltOffsetGain[12];
+
+extern const uint16_t WebRtcIsac_kQKltOffsetShape[108];
+
+/* initial cdf index for KLT coefficients */
+extern const uint16_t WebRtcIsac_kQKltInitIndexGain[12];
+
+extern const uint16_t WebRtcIsac_kQKltInitIndexShape[108];
+
+/* quantizer representation levels */
+extern const double WebRtcIsac_kQKltLevelsGain[392];
+
+extern const double WebRtcIsac_kQKltLevelsShape[578];
+
+/* cdf tables for quantizer indices */
+extern const uint16_t WebRtcIsac_kQKltCdfGain[404];
+
+extern const uint16_t WebRtcIsac_kQKltCdfShape[686];
+
+/* pointers to cdf tables for quantizer indices */
+extern const uint16_t* WebRtcIsac_kQKltCdfPtrGain[12];
+
+extern const uint16_t* WebRtcIsac_kQKltCdfPtrShape[108];
+
+/* left KLT transforms */
+extern const double WebRtcIsac_kKltT1Gain[4];
+
+extern const double WebRtcIsac_kKltT1Shape[324];
+
+/* right KLT transforms */
+extern const double WebRtcIsac_kKltT2Gain[36];
+
+extern const double WebRtcIsac_kKltT2Shape[36];
+
+/* means of log gains and LAR coefficients */
+extern const double WebRtcIsac_kLpcMeansGain[12];
+
+extern const double WebRtcIsac_kLpcMeansShape[108];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
new file mode 100644
index 0000000000..fe9afa4ba2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
+
+#include <math.h>
+
+#include "rtc_base/system/arch.h"
+
+#if defined(WEBRTC_POSIX)
+#define WebRtcIsac_lrint lrint
+#elif (defined(WEBRTC_ARCH_X86) && defined(WIN32))
+static __inline long int WebRtcIsac_lrint(double x_dbl) {
+ long int x_int;
+
+ __asm {
+ fld x_dbl
+ fistp x_int
+ }
+ ;
+
+ return x_int;
+}
+#else // Do a slow but correct implementation of lrint
+
+static __inline long int WebRtcIsac_lrint(double x_dbl) {
+ long int x_int;
+ x_int = (long int)floor(x_dbl + 0.499999999999);
+ return x_int;
+}
+
+#endif
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c
new file mode 100644
index 0000000000..8a19ac1710
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+
+#include <math.h>
+#include <memory.h>
+#include <string.h>
+#ifdef WEBRTC_ANDROID
+#include <stdlib.h>
+#endif
+
+#include "modules/audio_coding/codecs/isac/main/source/filter_functions.h"
+#include "modules/audio_coding/codecs/isac/main/source/pitch_filter.h"
+#include "rtc_base/system/ignore_warnings.h"
+
+static const double kInterpolWin[8] = {-0.00067556028640, 0.02184247643159, -0.12203175715679, 0.60086484101160,
+ 0.60086484101160, -0.12203175715679, 0.02184247643159, -0.00067556028640};
+
+/* interpolation filter */
+__inline static void IntrepolFilter(double *data_ptr, double *intrp)
+{
+ *intrp = kInterpolWin[0] * data_ptr[-3];
+ *intrp += kInterpolWin[1] * data_ptr[-2];
+ *intrp += kInterpolWin[2] * data_ptr[-1];
+ *intrp += kInterpolWin[3] * data_ptr[0];
+ *intrp += kInterpolWin[4] * data_ptr[1];
+ *intrp += kInterpolWin[5] * data_ptr[2];
+ *intrp += kInterpolWin[6] * data_ptr[3];
+ *intrp += kInterpolWin[7] * data_ptr[4];
+}
+
+
+/* 2D parabolic interpolation */
+/* probably some 0.5 factors can be eliminated, and the square-roots can be removed from the Cholesky fact. */
+__inline static void Intrpol2D(double T[3][3], double *x, double *y, double *peak_val)
+{
+ double c, b[2], A[2][2];
+ double t1, t2, d;
+ double delta1, delta2;
+
+
+ // double T[3][3] = {{-1.25, -.25,-.25}, {-.25, .75, .75}, {-.25, .75, .75}};
+ // should result in: delta1 = 0.5; delta2 = 0.0; peak_val = 1.0
+
+ c = T[1][1];
+ b[0] = 0.5 * (T[1][2] + T[2][1] - T[0][1] - T[1][0]);
+ b[1] = 0.5 * (T[1][0] + T[2][1] - T[0][1] - T[1][2]);
+ A[0][1] = -0.5 * (T[0][1] + T[2][1] - T[1][0] - T[1][2]);
+ t1 = 0.5 * (T[0][0] + T[2][2]) - c;
+ t2 = 0.5 * (T[2][0] + T[0][2]) - c;
+ d = (T[0][1] + T[1][2] + T[1][0] + T[2][1]) - 4.0 * c - t1 - t2;
+ A[0][0] = -t1 - 0.5 * d;
+ A[1][1] = -t2 - 0.5 * d;
+
+ /* deal with singularities or ill-conditioned cases */
+ if ( (A[0][0] < 1e-7) || ((A[0][0] * A[1][1] - A[0][1] * A[0][1]) < 1e-7) ) {
+ *peak_val = T[1][1];
+ return;
+ }
+
+ /* Cholesky decomposition: replace A by upper-triangular factor */
+ A[0][0] = sqrt(A[0][0]);
+ A[0][1] = A[0][1] / A[0][0];
+ A[1][1] = sqrt(A[1][1] - A[0][1] * A[0][1]);
+
+ /* compute [x; y] = -0.5 * inv(A) * b */
+ t1 = b[0] / A[0][0];
+ t2 = (b[1] - t1 * A[0][1]) / A[1][1];
+ delta2 = t2 / A[1][1];
+ delta1 = 0.5 * (t1 - delta2 * A[0][1]) / A[0][0];
+ delta2 *= 0.5;
+
+ /* limit norm */
+ t1 = delta1 * delta1 + delta2 * delta2;
+ if (t1 > 1.0) {
+ delta1 /= t1;
+ delta2 /= t1;
+ }
+
+ *peak_val = 0.5 * (b[0] * delta1 + b[1] * delta2) + c;
+
+ *x += delta1;
+ *y += delta2;
+}
+
+
+static void PCorr(const double *in, double *outcorr)
+{
+ double sum, ysum, prod;
+ const double *x, *inptr;
+ int k, n;
+
+ //ysum = 1e-6; /* use this with float (i.s.o. double)! */
+ ysum = 1e-13;
+ sum = 0.0;
+ x = in + PITCH_MAX_LAG/2 + 2;
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ ysum += in[n] * in[n];
+ sum += x[n] * in[n];
+ }
+
+ outcorr += PITCH_LAG_SPAN2 - 1; /* index of last element in array */
+ *outcorr = sum / sqrt(ysum);
+
+ for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+ ysum -= in[k-1] * in[k-1];
+ ysum += in[PITCH_CORR_LEN2 + k - 1] * in[PITCH_CORR_LEN2 + k - 1];
+ sum = 0.0;
+ inptr = &in[k];
+ prod = x[0] * inptr[0];
+ for (n = 1; n < PITCH_CORR_LEN2; n++) {
+ sum += prod;
+ prod = x[n] * inptr[n];
+ }
+ sum += prod;
+ outcorr--;
+ *outcorr = sum / sqrt(ysum);
+ }
+}
+
+static void WebRtcIsac_AllpassFilterForDec(double* InOut,
+ const double* APSectionFactors,
+ size_t lengthInOut,
+ double* FilterState) {
+ // This performs all-pass filtering--a series of first order all-pass
+ // sections are used to filter the input in a cascade manner.
+ size_t n, j;
+ double temp;
+ for (j = 0; j < ALLPASSSECTIONS; j++) {
+ for (n = 0; n < lengthInOut; n += 2) {
+ temp = InOut[n]; // store input
+ InOut[n] = FilterState[j] + APSectionFactors[j] * temp;
+ FilterState[j] = -APSectionFactors[j] * InOut[n] + temp;
+ }
+ }
+}
+
+static void WebRtcIsac_DecimateAllpass(
+ const double* in,
+ double* state_in, // array of size: 2*ALLPASSSECTIONS+1
+ size_t N, // number of input samples
+ double* out) { // array of size N/2
+
+ static const double APupper[ALLPASSSECTIONS] = {0.0347, 0.3826};
+ static const double APlower[ALLPASSSECTIONS] = {0.1544, 0.744};
+
+ size_t n;
+ double data_vec[PITCH_FRAME_LEN];
+
+ /* copy input */
+ memcpy(data_vec + 1, in, sizeof(double) * (N - 1));
+
+ data_vec[0] = state_in[2 * ALLPASSSECTIONS]; // the z^(-1) state
+ state_in[2 * ALLPASSSECTIONS] = in[N - 1];
+
+ WebRtcIsac_AllpassFilterForDec(data_vec + 1, APupper, N, state_in);
+ WebRtcIsac_AllpassFilterForDec(data_vec, APlower, N,
+ state_in + ALLPASSSECTIONS);
+
+ for (n = 0; n < N / 2; n++)
+ out[n] = data_vec[2 * n] + data_vec[2 * n + 1];
+}
+
+RTC_PUSH_IGNORING_WFRAME_LARGER_THAN()
+
+static void WebRtcIsac_InitializePitch(const double* in,
+ const double old_lag,
+ const double old_gain,
+ PitchAnalysisStruct* State,
+ double* lags) {
+ double buf_dec[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
+ double ratio, log_lag, gain_bias;
+ double bias;
+ double corrvec1[PITCH_LAG_SPAN2];
+ double corrvec2[PITCH_LAG_SPAN2];
+ int m, k;
+ // Allocating 10 extra entries at the begining of the CorrSurf
+ double corrSurfBuff[10 + (2*PITCH_BW+3)*(PITCH_LAG_SPAN2+4)];
+ double* CorrSurf[2*PITCH_BW+3];
+ double *CorrSurfPtr1, *CorrSurfPtr2;
+ double LagWin[3] = {0.2, 0.5, 0.98};
+ int ind1, ind2, peaks_ind, peak, max_ind;
+ int peaks[PITCH_MAX_NUM_PEAKS];
+ double adj, gain_tmp;
+ double corr, corr_max;
+ double intrp_a, intrp_b, intrp_c, intrp_d;
+ double peak_vals[PITCH_MAX_NUM_PEAKS];
+ double lags1[PITCH_MAX_NUM_PEAKS];
+ double lags2[PITCH_MAX_NUM_PEAKS];
+ double T[3][3];
+ int row;
+
+ for(k = 0; k < 2*PITCH_BW+3; k++)
+ {
+ CorrSurf[k] = &corrSurfBuff[10 + k * (PITCH_LAG_SPAN2+4)];
+ }
+ /* reset CorrSurf matrix */
+ memset(corrSurfBuff, 0, sizeof(double) * (10 + (2*PITCH_BW+3) * (PITCH_LAG_SPAN2+4)));
+
+ //warnings -DH
+ max_ind = 0;
+ peak = 0;
+
+ /* copy old values from state buffer */
+ memcpy(buf_dec, State->dec_buffer, sizeof(double) * (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2));
+
+ /* decimation; put result after the old values */
+ WebRtcIsac_DecimateAllpass(in, State->decimator_state, PITCH_FRAME_LEN,
+ &buf_dec[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
+
+ /* low-pass filtering */
+ for (k = PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2; k++)
+ buf_dec[k] += 0.75 * buf_dec[k-1] - 0.25 * buf_dec[k-2];
+
+ /* copy end part back into state buffer */
+ memcpy(State->dec_buffer, buf_dec+PITCH_FRAME_LEN/2, sizeof(double) * (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2));
+
+ /* compute correlation for first and second half of the frame */
+ PCorr(buf_dec, corrvec1);
+ PCorr(buf_dec + PITCH_CORR_STEP2, corrvec2);
+
+ /* bias towards pitch lag of previous frame */
+ log_lag = log(0.5 * old_lag);
+ gain_bias = 4.0 * old_gain * old_gain;
+ if (gain_bias > 0.8) gain_bias = 0.8;
+ for (k = 0; k < PITCH_LAG_SPAN2; k++)
+ {
+ ratio = log((double) (k + (PITCH_MIN_LAG/2-2))) - log_lag;
+ bias = 1.0 + gain_bias * exp(-5.0 * ratio * ratio);
+ corrvec1[k] *= bias;
+ }
+
+ /* taper correlation functions */
+ for (k = 0; k < 3; k++) {
+ gain_tmp = LagWin[k];
+ corrvec1[k] *= gain_tmp;
+ corrvec2[k] *= gain_tmp;
+ corrvec1[PITCH_LAG_SPAN2-1-k] *= gain_tmp;
+ corrvec2[PITCH_LAG_SPAN2-1-k] *= gain_tmp;
+ }
+
+ corr_max = 0.0;
+ /* fill middle row of correlation surface */
+ ind1 = 0;
+ ind2 = 0;
+ CorrSurfPtr1 = &CorrSurf[PITCH_BW][2];
+ for (k = 0; k < PITCH_LAG_SPAN2; k++) {
+ corr = corrvec1[ind1++] + corrvec2[ind2++];
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill first and last rows of correlation surface */
+ ind1 = 0;
+ ind2 = PITCH_BW;
+ CorrSurfPtr1 = &CorrSurf[0][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW][PITCH_BW+2];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = 0.2 * ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill second and next to last rows of correlation surface */
+ ind1 = 0;
+ ind2 = PITCH_BW-1;
+ CorrSurfPtr1 = &CorrSurf[1][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW-1][PITCH_BW+1];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW+1; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = 0.9 * ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill remainder of correlation surface */
+ for (m = 2; m < PITCH_BW; m++) {
+ ind1 = 0;
+ ind2 = PITCH_BW - m; /* always larger than ind1 */
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW-m][PITCH_BW+2-m];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW+m; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ }
+
+ /* threshold value to qualify as a peak */
+ corr_max *= 0.6;
+
+ peaks_ind = 0;
+ /* find peaks */
+ for (m = 1; m < PITCH_BW+1; m++) {
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ for (k = 2; k < PITCH_LAG_SPAN2-PITCH_BW-2+m; k++) {
+ corr = CorrSurfPtr1[k];
+ if (corr > corr_max) {
+ if ( (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+5)]) && (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+4)]) ) {
+ if ( (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+4)]) && (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+5)]) ) {
+ /* found a peak; store index into matrix */
+ peaks[peaks_ind++] = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ }
+ }
+ }
+ }
+ }
+ for (m = PITCH_BW+1; m < 2*PITCH_BW; m++) {
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ for (k = 2+m-PITCH_BW; k < PITCH_LAG_SPAN2-2; k++) {
+ corr = CorrSurfPtr1[k];
+ if (corr > corr_max) {
+ if ( (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+5)]) && (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+4)]) ) {
+ if ( (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+4)]) && (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+5)]) ) {
+ /* found a peak; store index into matrix */
+ peaks[peaks_ind++] = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ }
+ }
+ }
+ }
+ }
+
+ if (peaks_ind > 0) {
+ /* examine each peak */
+ CorrSurfPtr1 = &CorrSurf[0][0];
+ for (k = 0; k < peaks_ind; k++) {
+ peak = peaks[k];
+
+ /* compute four interpolated values around current peak */
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)], &intrp_a);
+ IntrepolFilter(&CorrSurfPtr1[peak - 1 ], &intrp_b);
+ IntrepolFilter(&CorrSurfPtr1[peak ], &intrp_c);
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)], &intrp_d);
+
+ /* determine maximum of the interpolated values */
+ corr = CorrSurfPtr1[peak];
+ corr_max = intrp_a;
+ if (intrp_b > corr_max) corr_max = intrp_b;
+ if (intrp_c > corr_max) corr_max = intrp_c;
+ if (intrp_d > corr_max) corr_max = intrp_d;
+
+ /* determine where the peak sits and fill a 3x3 matrix around it */
+ row = peak / (PITCH_LAG_SPAN2+4);
+ lags1[k] = (double) ((peak - row * (PITCH_LAG_SPAN2+4)) + PITCH_MIN_LAG/2 - 4);
+ lags2[k] = (double) (lags1[k] + PITCH_BW - row);
+ if ( corr > corr_max ) {
+ T[0][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[2][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[1][1] = corr;
+ T[0][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ T[2][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ T[1][0] = intrp_a;
+ T[0][1] = intrp_b;
+ T[2][1] = intrp_c;
+ T[1][2] = intrp_d;
+ } else {
+ if (intrp_a == corr_max) {
+ lags1[k] -= 0.5;
+ lags2[k] += 0.5;
+ IntrepolFilter(&CorrSurfPtr1[peak - 2*(PITCH_LAG_SPAN2+5)], &T[0][0]);
+ IntrepolFilter(&CorrSurfPtr1[peak - (2*PITCH_LAG_SPAN2+9)], &T[2][0]);
+ T[1][1] = intrp_a;
+ T[0][2] = intrp_b;
+ T[2][2] = intrp_c;
+ T[1][0] = CorrSurfPtr1[peak - (2*PITCH_LAG_SPAN2+9)];
+ T[0][1] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[2][1] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[1][2] = corr;
+ } else if (intrp_b == corr_max) {
+ lags1[k] -= 0.5;
+ lags2[k] -= 0.5;
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+6)], &T[0][0]);
+ T[2][0] = intrp_a;
+ T[1][1] = intrp_b;
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+3)], &T[0][2]);
+ T[2][2] = intrp_d;
+ T[1][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[0][1] = CorrSurfPtr1[peak - 1];
+ T[2][1] = corr;
+ T[1][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ } else if (intrp_c == corr_max) {
+ lags1[k] += 0.5;
+ lags2[k] += 0.5;
+ T[0][0] = intrp_a;
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)], &T[2][0]);
+ T[1][1] = intrp_c;
+ T[0][2] = intrp_d;
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)], &T[2][2]);
+ T[1][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[0][1] = corr;
+ T[2][1] = CorrSurfPtr1[peak + 1];
+ T[1][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ } else {
+ lags1[k] += 0.5;
+ lags2[k] -= 0.5;
+ T[0][0] = intrp_b;
+ T[2][0] = intrp_c;
+ T[1][1] = intrp_d;
+ IntrepolFilter(&CorrSurfPtr1[peak + 2*(PITCH_LAG_SPAN2+4)], &T[0][2]);
+ IntrepolFilter(&CorrSurfPtr1[peak + (2*PITCH_LAG_SPAN2+9)], &T[2][2]);
+ T[1][0] = corr;
+ T[0][1] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ T[2][1] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ T[1][2] = CorrSurfPtr1[peak + (2*PITCH_LAG_SPAN2+9)];
+ }
+ }
+
+ /* 2D parabolic interpolation gives more accurate lags and peak value */
+ Intrpol2D(T, &lags1[k], &lags2[k], &peak_vals[k]);
+ }
+
+ /* determine the highest peak, after applying a bias towards short lags */
+ corr_max = 0.0;
+ for (k = 0; k < peaks_ind; k++) {
+ corr = peak_vals[k] * pow(PITCH_PEAK_DECAY, log(lags1[k] + lags2[k]));
+ if (corr > corr_max) {
+ corr_max = corr;
+ peak = k;
+ }
+ }
+
+ lags1[peak] *= 2.0;
+ lags2[peak] *= 2.0;
+
+ if (lags1[peak] < (double) PITCH_MIN_LAG) lags1[peak] = (double) PITCH_MIN_LAG;
+ if (lags2[peak] < (double) PITCH_MIN_LAG) lags2[peak] = (double) PITCH_MIN_LAG;
+ if (lags1[peak] > (double) PITCH_MAX_LAG) lags1[peak] = (double) PITCH_MAX_LAG;
+ if (lags2[peak] > (double) PITCH_MAX_LAG) lags2[peak] = (double) PITCH_MAX_LAG;
+
+ /* store lags of highest peak in output array */
+ lags[0] = lags1[peak];
+ lags[1] = lags1[peak];
+ lags[2] = lags2[peak];
+ lags[3] = lags2[peak];
+ }
+ else
+ {
+ row = max_ind / (PITCH_LAG_SPAN2+4);
+ lags1[0] = (double) ((max_ind - row * (PITCH_LAG_SPAN2+4)) + PITCH_MIN_LAG/2 - 4);
+ lags2[0] = (double) (lags1[0] + PITCH_BW - row);
+
+ if (lags1[0] < (double) PITCH_MIN_LAG) lags1[0] = (double) PITCH_MIN_LAG;
+ if (lags2[0] < (double) PITCH_MIN_LAG) lags2[0] = (double) PITCH_MIN_LAG;
+ if (lags1[0] > (double) PITCH_MAX_LAG) lags1[0] = (double) PITCH_MAX_LAG;
+ if (lags2[0] > (double) PITCH_MAX_LAG) lags2[0] = (double) PITCH_MAX_LAG;
+
+ /* store lags of highest peak in output array */
+ lags[0] = lags1[0];
+ lags[1] = lags1[0];
+ lags[2] = lags2[0];
+ lags[3] = lags2[0];
+ }
+}
+
+RTC_POP_IGNORING_WFRAME_LARGER_THAN()
+
+/* create weighting matrix by orthogonalizing a basis of polynomials of increasing order
+ * t = (0:4)';
+ * A = [t.^0, t.^1, t.^2, t.^3, t.^4];
+ * [Q, dummy] = qr(A);
+ * P.Weight = Q * diag([0, .1, .5, 1, 1]) * Q'; */
+static const double kWeight[5][5] = {
+ { 0.29714285714286, -0.30857142857143, -0.05714285714286, 0.05142857142857, 0.01714285714286},
+ {-0.30857142857143, 0.67428571428571, -0.27142857142857, -0.14571428571429, 0.05142857142857},
+ {-0.05714285714286, -0.27142857142857, 0.65714285714286, -0.27142857142857, -0.05714285714286},
+ { 0.05142857142857, -0.14571428571429, -0.27142857142857, 0.67428571428571, -0.30857142857143},
+ { 0.01714285714286, 0.05142857142857, -0.05714285714286, -0.30857142857143, 0.29714285714286}
+};
+
+/* second order high-pass filter */
+static void WebRtcIsac_Highpass(const double* in,
+ double* out,
+ double* state,
+ size_t N) {
+ /* create high-pass filter ocefficients
+ * z = 0.998 * exp(j*2*pi*35/8000);
+ * p = 0.94 * exp(j*2*pi*140/8000);
+ * HP_b = [1, -2*real(z), abs(z)^2];
+ * HP_a = [1, -2*real(p), abs(p)^2]; */
+ static const double a_coef[2] = { 1.86864659625574, -0.88360000000000};
+ static const double b_coef[2] = {-1.99524591718270, 0.99600400000000};
+
+ size_t k;
+
+ for (k=0; k<N; k++) {
+ *out = *in + state[1];
+ state[1] = state[0] + b_coef[0] * *in + a_coef[0] * *out;
+ state[0] = b_coef[1] * *in++ + a_coef[1] * *out++;
+ }
+}
+
+RTC_PUSH_IGNORING_WFRAME_LARGER_THAN()
+
+void WebRtcIsac_PitchAnalysis(const double *in, /* PITCH_FRAME_LEN samples */
+ double *out, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ double *lags,
+ double *gains)
+{
+ double HPin[PITCH_FRAME_LEN];
+ double Weighted[PITCH_FRAME_LEN];
+ double Whitened[PITCH_FRAME_LEN + QLOOKAHEAD];
+ double inbuf[PITCH_FRAME_LEN + QLOOKAHEAD];
+ double out_G[PITCH_FRAME_LEN + QLOOKAHEAD]; // could be removed by using out instead
+ double out_dG[4][PITCH_FRAME_LEN + QLOOKAHEAD];
+ double old_lag, old_gain;
+ double nrg_wht, tmp;
+ double Wnrg, Wfluct, Wgain;
+ double H[4][4];
+ double grad[4];
+ double dG[4];
+ int k, m, n, iter;
+
+ /* high pass filtering using second order pole-zero filter */
+ WebRtcIsac_Highpass(in, HPin, State->hp_state, PITCH_FRAME_LEN);
+
+ /* copy from state into buffer */
+ memcpy(Whitened, State->whitened_buf, sizeof(double) * QLOOKAHEAD);
+
+ /* compute weighted and whitened signals */
+ WebRtcIsac_WeightingFilter(HPin, &Weighted[0], &Whitened[QLOOKAHEAD], &(State->Wghtstr));
+
+ /* copy from buffer into state */
+ memcpy(State->whitened_buf, Whitened+PITCH_FRAME_LEN, sizeof(double) * QLOOKAHEAD);
+
+ old_lag = State->PFstr_wght.oldlagp[0];
+ old_gain = State->PFstr_wght.oldgainp[0];
+
+ /* inital pitch estimate */
+ WebRtcIsac_InitializePitch(Weighted, old_lag, old_gain, State, lags);
+
+
+ /* Iterative optimization of lags - to be done */
+
+ /* compute energy of whitened signal */
+ nrg_wht = 0.0;
+ for (k = 0; k < PITCH_FRAME_LEN + QLOOKAHEAD; k++)
+ nrg_wht += Whitened[k] * Whitened[k];
+
+
+ /* Iterative optimization of gains */
+
+ /* set weights for energy, gain fluctiation, and spectral gain penalty functions */
+ Wnrg = 1.0 / nrg_wht;
+ Wgain = 0.005;
+ Wfluct = 3.0;
+
+ /* set initial gains */
+ for (k = 0; k < 4; k++)
+ gains[k] = PITCH_MAX_GAIN_06;
+
+ /* two iterations should be enough */
+ for (iter = 0; iter < 2; iter++) {
+ /* compute Jacobian of pre-filter output towards gains */
+ WebRtcIsac_PitchfilterPre_gains(Whitened, out_G, out_dG, &(State->PFstr_wght), lags, gains);
+
+ /* gradient and approximate Hessian (lower triangle) for minimizing the filter's output power */
+ for (k = 0; k < 4; k++) {
+ tmp = 0.0;
+ for (n = 0; n < PITCH_FRAME_LEN + QLOOKAHEAD; n++)
+ tmp += out_G[n] * out_dG[k][n];
+ grad[k] = tmp * Wnrg;
+ }
+ for (k = 0; k < 4; k++) {
+ for (m = 0; m <= k; m++) {
+ tmp = 0.0;
+ for (n = 0; n < PITCH_FRAME_LEN + QLOOKAHEAD; n++)
+ tmp += out_dG[m][n] * out_dG[k][n];
+ H[k][m] = tmp * Wnrg;
+ }
+ }
+
+ /* add gradient and Hessian (lower triangle) for dampening fast gain changes */
+ for (k = 0; k < 4; k++) {
+ tmp = kWeight[k+1][0] * old_gain;
+ for (m = 0; m < 4; m++)
+ tmp += kWeight[k+1][m+1] * gains[m];
+ grad[k] += tmp * Wfluct;
+ }
+ for (k = 0; k < 4; k++) {
+ for (m = 0; m <= k; m++) {
+ H[k][m] += kWeight[k+1][m+1] * Wfluct;
+ }
+ }
+
+ /* add gradient and Hessian for dampening gain */
+ for (k = 0; k < 3; k++) {
+ tmp = 1.0 / (1 - gains[k]);
+ grad[k] += tmp * tmp * Wgain;
+ H[k][k] += 2.0 * tmp * (tmp * tmp * Wgain);
+ }
+ tmp = 1.0 / (1 - gains[3]);
+ grad[3] += 1.33 * (tmp * tmp * Wgain);
+ H[3][3] += 2.66 * tmp * (tmp * tmp * Wgain);
+
+
+ /* compute Cholesky factorization of Hessian
+ * by overwritting the upper triangle; scale factors on diagonal
+ * (for non pc-platforms store the inverse of the diagonals seperately to minimize divisions) */
+ H[0][1] = H[1][0] / H[0][0];
+ H[0][2] = H[2][0] / H[0][0];
+ H[0][3] = H[3][0] / H[0][0];
+ H[1][1] -= H[0][0] * H[0][1] * H[0][1];
+ H[1][2] = (H[2][1] - H[0][1] * H[2][0]) / H[1][1];
+ H[1][3] = (H[3][1] - H[0][1] * H[3][0]) / H[1][1];
+ H[2][2] -= H[0][0] * H[0][2] * H[0][2] + H[1][1] * H[1][2] * H[1][2];
+ H[2][3] = (H[3][2] - H[0][2] * H[3][0] - H[1][2] * H[1][1] * H[1][3]) / H[2][2];
+ H[3][3] -= H[0][0] * H[0][3] * H[0][3] + H[1][1] * H[1][3] * H[1][3] + H[2][2] * H[2][3] * H[2][3];
+
+ /* Compute update as delta_gains = -inv(H) * grad */
+ /* copy and negate */
+ for (k = 0; k < 4; k++)
+ dG[k] = -grad[k];
+ /* back substitution */
+ dG[1] -= dG[0] * H[0][1];
+ dG[2] -= dG[0] * H[0][2] + dG[1] * H[1][2];
+ dG[3] -= dG[0] * H[0][3] + dG[1] * H[1][3] + dG[2] * H[2][3];
+ /* scale */
+ for (k = 0; k < 4; k++)
+ dG[k] /= H[k][k];
+ /* back substitution */
+ dG[2] -= dG[3] * H[2][3];
+ dG[1] -= dG[3] * H[1][3] + dG[2] * H[1][2];
+ dG[0] -= dG[3] * H[0][3] + dG[2] * H[0][2] + dG[1] * H[0][1];
+
+ /* update gains and check range */
+ for (k = 0; k < 4; k++) {
+ gains[k] += dG[k];
+ if (gains[k] > PITCH_MAX_GAIN)
+ gains[k] = PITCH_MAX_GAIN;
+ else if (gains[k] < 0.0)
+ gains[k] = 0.0;
+ }
+ }
+
+ /* update state for next frame */
+ WebRtcIsac_PitchfilterPre(Whitened, out, &(State->PFstr_wght), lags, gains);
+
+ /* concatenate previous input's end and current input */
+ memcpy(inbuf, State->inbuf, sizeof(double) * QLOOKAHEAD);
+ memcpy(inbuf+QLOOKAHEAD, in, sizeof(double) * PITCH_FRAME_LEN);
+
+ /* lookahead pitch filtering for masking analysis */
+ WebRtcIsac_PitchfilterPre_la(inbuf, out, &(State->PFstr), lags, gains);
+
+ /* store last part of input */
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = inbuf[k + PITCH_FRAME_LEN];
+}
+
+RTC_POP_IGNORING_WFRAME_LARGER_THAN()
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h
new file mode 100644
index 0000000000..4ab78c20ad
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_estimator.h
+ *
+ * Pitch functions
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_
+
+#include <stddef.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+void WebRtcIsac_PitchAnalysis(
+ const double* in, /* PITCH_FRAME_LEN samples */
+ double* out, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct* State,
+ double* lags,
+ double* gains);
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.c
new file mode 100644
index 0000000000..bf03dfff2e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_estimator.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+#include "rtc_base/compile_assert_c.h"
+
+/*
+ * We are implementing the following filters;
+ *
+ * Pre-filtering:
+ * y(z) = x(z) + damper(z) * gain * (x(z) + y(z)) * z ^ (-lag);
+ *
+ * Post-filtering:
+ * y(z) = x(z) - damper(z) * gain * (x(z) + y(z)) * z ^ (-lag);
+ *
+ * Note that `lag` is a floating number so we perform an interpolation to
+ * obtain the correct `lag`.
+ *
+ */
+
+static const double kDampFilter[PITCH_DAMPORDER] = {-0.07, 0.25, 0.64, 0.25,
+ -0.07};
+
+/* interpolation coefficients; generated by design_pitch_filter.m */
+static const double kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
+ {-0.02239172458614, 0.06653315052934, -0.16515880017569, 0.60701333734125,
+ 0.64671399919202, -0.20249000396417, 0.09926548334755, -0.04765933793109,
+ 0.01754159521746},
+ {-0.01985640750434, 0.05816126837866, -0.13991265473714, 0.44560418147643,
+ 0.79117042386876, -0.20266133815188, 0.09585268418555, -0.04533310458084,
+ 0.01654127246314},
+ {-0.01463300534216, 0.04229888475060, -0.09897034715253, 0.28284326017787,
+ 0.90385267956632, -0.16976950138649, 0.07704272393639, -0.03584218578311,
+ 0.01295781500709},
+ {-0.00764851320885, 0.02184035544377, -0.04985561057281, 0.13083306574393,
+ 0.97545011664662, -0.10177807997561, 0.04400901776474, -0.02010737175166,
+ 0.00719783432422},
+ {-0.00000000000000, 0.00000000000000, -0.00000000000001, 0.00000000000001,
+ 0.99999999999999, 0.00000000000001, -0.00000000000001, 0.00000000000000,
+ -0.00000000000000},
+ {0.00719783432422, -0.02010737175166, 0.04400901776474, -0.10177807997562,
+ 0.97545011664663, 0.13083306574393, -0.04985561057280, 0.02184035544377,
+ -0.00764851320885},
+ {0.01295781500710, -0.03584218578312, 0.07704272393640, -0.16976950138650,
+ 0.90385267956634, 0.28284326017785, -0.09897034715252, 0.04229888475059,
+ -0.01463300534216},
+ {0.01654127246315, -0.04533310458085, 0.09585268418557, -0.20266133815190,
+ 0.79117042386878, 0.44560418147640, -0.13991265473712, 0.05816126837865,
+ -0.01985640750433}
+};
+
+/*
+ * Enumerating the operation of the filter.
+ * iSAC has 4 different pitch-filter which are very similar in their structure.
+ *
+ * kPitchFilterPre : In this mode the filter is operating as pitch
+ * pre-filter. This is used at the encoder.
+ * kPitchFilterPost : In this mode the filter is operating as pitch
+ * post-filter. This is the inverse of pre-filter and used
+ * in the decoder.
+ * kPitchFilterPreLa : This is, in structure, similar to pre-filtering but
+ * utilizing 3 millisecond lookahead. It is used to
+ * obtain the signal for LPC analysis.
+ * kPitchFilterPreGain : This is, in structure, similar to pre-filtering but
+ * differential changes in gain is considered. This is
+ * used to find the optimal gain.
+ */
+typedef enum {
+ kPitchFilterPre, kPitchFilterPost, kPitchFilterPreLa, kPitchFilterPreGain
+} PitchFilterOperation;
+
+/*
+ * Structure with parameters used for pitch-filtering.
+ * buffer : a buffer where the sum of previous inputs and outputs
+ * are stored.
+ * damper_state : the state of the damping filter. The filter is defined by
+ * `kDampFilter`.
+ * interpol_coeff : pointer to a set of coefficient which are used to utilize
+ * fractional pitch by interpolation.
+ * gain : pitch-gain to be applied to the current segment of input.
+ * lag : pitch-lag for the current segment of input.
+ * lag_offset : the offset of lag w.r.t. current sample.
+ * sub_frame : sub-frame index, there are 4 pitch sub-frames in an iSAC
+ * frame.
+ * This specifies the usage of the filter. See
+ * 'PitchFilterOperation' for operational modes.
+ * num_samples : number of samples to be processed in each segment.
+ * index : index of the input and output sample.
+ * damper_state_dg : state of damping filter for different trial gains.
+ * gain_mult : differential changes to gain.
+ */
+typedef struct {
+ double buffer[PITCH_INTBUFFSIZE + QLOOKAHEAD];
+ double damper_state[PITCH_DAMPORDER];
+ const double *interpol_coeff;
+ double gain;
+ double lag;
+ int lag_offset;
+
+ int sub_frame;
+ PitchFilterOperation mode;
+ int num_samples;
+ int index;
+
+ double damper_state_dg[4][PITCH_DAMPORDER];
+ double gain_mult[4];
+} PitchFilterParam;
+
+/**********************************************************************
+ * FilterSegment()
+ * Filter one segment, a quarter of a frame.
+ *
+ * Inputs
+ * in_data : pointer to the input signal of 30 ms at 8 kHz sample-rate.
+ * filter_param : pitch filter parameters.
+ *
+ * Outputs
+ * out_data : pointer to a buffer where the filtered signal is written to.
+ * out_dg : [only used in kPitchFilterPreGain] pointer to a buffer
+ * where the output of different gain values (differential
+ * change to gain) is written.
+ */
+static void FilterSegment(const double* in_data, PitchFilterParam* parameters,
+ double* out_data,
+ double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) {
+ int n;
+ int m;
+ int j;
+ double sum;
+ double sum2;
+ /* Index of `parameters->buffer` where the output is written to. */
+ int pos = parameters->index + PITCH_BUFFSIZE;
+ /* Index of `parameters->buffer` where samples are read for fractional-lag
+ * computation. */
+ int pos_lag = pos - parameters->lag_offset;
+
+ for (n = 0; n < parameters->num_samples; ++n) {
+ /* Shift low pass filter states. */
+ for (m = PITCH_DAMPORDER - 1; m > 0; --m) {
+ parameters->damper_state[m] = parameters->damper_state[m - 1];
+ }
+ /* Filter to get fractional pitch. */
+ sum = 0.0;
+ for (m = 0; m < PITCH_FRACORDER; ++m) {
+ sum += parameters->buffer[pos_lag + m] * parameters->interpol_coeff[m];
+ }
+ /* Multiply with gain. */
+ parameters->damper_state[0] = parameters->gain * sum;
+
+ if (parameters->mode == kPitchFilterPreGain) {
+ int lag_index = parameters->index - parameters->lag_offset;
+ int m_tmp = (lag_index < 0) ? -lag_index : 0;
+ /* Update the damper state for the new sample. */
+ for (m = PITCH_DAMPORDER - 1; m > 0; --m) {
+ for (j = 0; j < 4; ++j) {
+ parameters->damper_state_dg[j][m] =
+ parameters->damper_state_dg[j][m - 1];
+ }
+ }
+
+ for (j = 0; j < parameters->sub_frame + 1; ++j) {
+ /* Filter for fractional pitch. */
+ sum2 = 0.0;
+ for (m = PITCH_FRACORDER-1; m >= m_tmp; --m) {
+ /* `lag_index + m` is always larger than or equal to zero, see how
+ * m_tmp is computed. This is equivalent to assume samples outside
+ * `out_dg[j]` are zero. */
+ sum2 += out_dg[j][lag_index + m] * parameters->interpol_coeff[m];
+ }
+ /* Add the contribution of differential gain change. */
+ parameters->damper_state_dg[j][0] = parameters->gain_mult[j] * sum +
+ parameters->gain * sum2;
+ }
+
+ /* Filter with damping filter, and store the results. */
+ for (j = 0; j < parameters->sub_frame + 1; ++j) {
+ sum = 0.0;
+ for (m = 0; m < PITCH_DAMPORDER; ++m) {
+ sum -= parameters->damper_state_dg[j][m] * kDampFilter[m];
+ }
+ out_dg[j][parameters->index] = sum;
+ }
+ }
+ /* Filter with damping filter. */
+ sum = 0.0;
+ for (m = 0; m < PITCH_DAMPORDER; ++m) {
+ sum += parameters->damper_state[m] * kDampFilter[m];
+ }
+
+ /* Subtract from input and update buffer. */
+ out_data[parameters->index] = in_data[parameters->index] - sum;
+ parameters->buffer[pos] = in_data[parameters->index] +
+ out_data[parameters->index];
+
+ ++parameters->index;
+ ++pos;
+ ++pos_lag;
+ }
+ return;
+}
+
+/* Update filter parameters based on the pitch-gains and pitch-lags. */
+static void Update(PitchFilterParam* parameters) {
+ double fraction;
+ int fraction_index;
+ /* Compute integer lag-offset. */
+ parameters->lag_offset = WebRtcIsac_lrint(parameters->lag + PITCH_FILTDELAY +
+ 0.5);
+ /* Find correct set of coefficients for computing fractional pitch. */
+ fraction = parameters->lag_offset - (parameters->lag + PITCH_FILTDELAY);
+ fraction_index = WebRtcIsac_lrint(PITCH_FRACS * fraction - 0.5);
+ parameters->interpol_coeff = kIntrpCoef[fraction_index];
+
+ if (parameters->mode == kPitchFilterPreGain) {
+ /* If in this mode make a differential change to pitch gain. */
+ parameters->gain_mult[parameters->sub_frame] += 0.2;
+ if (parameters->gain_mult[parameters->sub_frame] > 1.0) {
+ parameters->gain_mult[parameters->sub_frame] = 1.0;
+ }
+ if (parameters->sub_frame > 0) {
+ parameters->gain_mult[parameters->sub_frame - 1] -= 0.2;
+ }
+ }
+}
+
+/******************************************************************************
+ * FilterFrame()
+ * Filter a frame of 30 millisecond, given pitch-lags and pitch-gains.
+ *
+ * Inputs
+ * in_data : pointer to the input signal of 30 ms at 8 kHz sample-rate.
+ * lags : pointer to pitch-lags, 4 lags per frame.
+ * gains : pointer to pitch-gians, 4 gains per frame.
+ * mode : defining the functionality of the filter. It takes the
+ * following values.
+ * kPitchFilterPre: Pitch pre-filter, used at encoder.
+ * kPitchFilterPost: Pitch post-filter, used at decoder.
+ * kPitchFilterPreLa: Pitch pre-filter with lookahead.
+ * kPitchFilterPreGain: Pitch pre-filter used to otain optimal
+ * pitch-gains.
+ *
+ * Outputs
+ * out_data : pointer to a buffer where the filtered signal is written to.
+ * out_dg : [only used in kPitchFilterPreGain] pointer to a buffer
+ * where the output of different gain values (differential
+ * change to gain) is written.
+ */
+static void FilterFrame(const double* in_data, PitchFiltstr* filter_state,
+ double* lags, double* gains, PitchFilterOperation mode,
+ double* out_data,
+ double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) {
+ PitchFilterParam filter_parameters;
+ double gain_delta, lag_delta;
+ double old_lag, old_gain;
+ int n;
+ int m;
+ const double kEnhancer = 1.3;
+
+ /* Set up buffer and states. */
+ filter_parameters.index = 0;
+ filter_parameters.lag_offset = 0;
+ filter_parameters.mode = mode;
+ /* Copy states to local variables. */
+ memcpy(filter_parameters.buffer, filter_state->ubuf,
+ sizeof(filter_state->ubuf));
+ RTC_COMPILE_ASSERT(sizeof(filter_parameters.buffer) >=
+ sizeof(filter_state->ubuf));
+ memset(filter_parameters.buffer +
+ sizeof(filter_state->ubuf) / sizeof(filter_state->ubuf[0]),
+ 0, sizeof(filter_parameters.buffer) - sizeof(filter_state->ubuf));
+ memcpy(filter_parameters.damper_state, filter_state->ystate,
+ sizeof(filter_state->ystate));
+
+ if (mode == kPitchFilterPreGain) {
+ /* Clear buffers. */
+ memset(filter_parameters.gain_mult, 0, sizeof(filter_parameters.gain_mult));
+ memset(filter_parameters.damper_state_dg, 0,
+ sizeof(filter_parameters.damper_state_dg));
+ for (n = 0; n < PITCH_SUBFRAMES; ++n) {
+ //memset(out_dg[n], 0, sizeof(double) * (PITCH_FRAME_LEN + QLOOKAHEAD));
+ memset(out_dg[n], 0, sizeof(out_dg[n]));
+ }
+ } else if (mode == kPitchFilterPost) {
+ /* Make output more periodic. Negative sign is to change the structure
+ * of the filter. */
+ for (n = 0; n < PITCH_SUBFRAMES; ++n) {
+ gains[n] *= -kEnhancer;
+ }
+ }
+
+ old_lag = *filter_state->oldlagp;
+ old_gain = *filter_state->oldgainp;
+
+ /* No interpolation if pitch lag step is big. */
+ if ((lags[0] > (PITCH_UPSTEP * old_lag)) ||
+ (lags[0] < (PITCH_DOWNSTEP * old_lag))) {
+ old_lag = lags[0];
+ old_gain = gains[0];
+
+ if (mode == kPitchFilterPreGain) {
+ filter_parameters.gain_mult[0] = 1.0;
+ }
+ }
+
+ filter_parameters.num_samples = PITCH_UPDATE;
+ for (m = 0; m < PITCH_SUBFRAMES; ++m) {
+ /* Set the sub-frame value. */
+ filter_parameters.sub_frame = m;
+ /* Calculate interpolation steps for pitch-lag and pitch-gain. */
+ lag_delta = (lags[m] - old_lag) / PITCH_GRAN_PER_SUBFRAME;
+ filter_parameters.lag = old_lag;
+ gain_delta = (gains[m] - old_gain) / PITCH_GRAN_PER_SUBFRAME;
+ filter_parameters.gain = old_gain;
+ /* Store for the next sub-frame. */
+ old_lag = lags[m];
+ old_gain = gains[m];
+
+ for (n = 0; n < PITCH_GRAN_PER_SUBFRAME; ++n) {
+ /* Step-wise interpolation of pitch gains and lags. As pitch-lag changes,
+ * some parameters of filter need to be update. */
+ filter_parameters.gain += gain_delta;
+ filter_parameters.lag += lag_delta;
+ /* Update parameters according to new lag value. */
+ Update(&filter_parameters);
+ /* Filter a segment of input. */
+ FilterSegment(in_data, &filter_parameters, out_data, out_dg);
+ }
+ }
+
+ if (mode != kPitchFilterPreGain) {
+ /* Export buffer and states. */
+ memcpy(filter_state->ubuf, &filter_parameters.buffer[PITCH_FRAME_LEN],
+ sizeof(filter_state->ubuf));
+ memcpy(filter_state->ystate, filter_parameters.damper_state,
+ sizeof(filter_state->ystate));
+
+ /* Store for the next frame. */
+ *filter_state->oldlagp = old_lag;
+ *filter_state->oldgainp = old_gain;
+ }
+
+ if ((mode == kPitchFilterPreGain) || (mode == kPitchFilterPreLa)) {
+ /* Filter the lookahead segment, this is treated as the last sub-frame. So
+ * set `pf_param` to last sub-frame. */
+ filter_parameters.sub_frame = PITCH_SUBFRAMES - 1;
+ filter_parameters.num_samples = QLOOKAHEAD;
+ FilterSegment(in_data, &filter_parameters, out_data, out_dg);
+ }
+}
+
+void WebRtcIsac_PitchfilterPre(double* in_data, double* out_data,
+ PitchFiltstr* pf_state, double* lags,
+ double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPre, out_data, NULL);
+}
+
+void WebRtcIsac_PitchfilterPre_la(double* in_data, double* out_data,
+ PitchFiltstr* pf_state, double* lags,
+ double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreLa, out_data,
+ NULL);
+}
+
+void WebRtcIsac_PitchfilterPre_gains(
+ double* in_data, double* out_data,
+ double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD], PitchFiltstr *pf_state,
+ double* lags, double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreGain, out_data,
+ out_dg);
+}
+
+void WebRtcIsac_PitchfilterPost(double* in_data, double* out_data,
+ PitchFiltstr* pf_state, double* lags,
+ double* gains) {
+ FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPost, out_data, NULL);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.h
new file mode 100644
index 0000000000..9a232de87b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_filter.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_FILTER_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_FILTER_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+void WebRtcIsac_PitchfilterPre(double* indat,
+ double* outdat,
+ PitchFiltstr* pfp,
+ double* lags,
+ double* gains);
+
+void WebRtcIsac_PitchfilterPost(double* indat,
+ double* outdat,
+ PitchFiltstr* pfp,
+ double* lags,
+ double* gains);
+
+void WebRtcIsac_PitchfilterPre_la(double* indat,
+ double* outdat,
+ PitchFiltstr* pfp,
+ double* lags,
+ double* gains);
+
+void WebRtcIsac_PitchfilterPre_gains(
+ double* indat,
+ double* outdat,
+ double out_dG[][PITCH_FRAME_LEN + QLOOKAHEAD],
+ PitchFiltstr* pfp,
+ double* lags,
+ double* gains);
+
+#endif // MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_FILTER_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c
new file mode 100644
index 0000000000..080432c3a5
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+const uint16_t WebRtcIsac_kQPitchGainCdf[255] = {
+ 0, 2, 4, 6, 64, 901, 903, 905, 16954, 16956,
+ 16961, 17360, 17362, 17364, 17366, 17368, 17370, 17372, 17374, 17411,
+ 17514, 17516, 17583, 18790, 18796, 18802, 20760, 20777, 20782, 21722,
+ 21724, 21728, 21738, 21740, 21742, 21744, 21746, 21748, 22224, 22227,
+ 22230, 23214, 23229, 23239, 25086, 25108, 25120, 26088, 26094, 26098,
+ 26175, 26177, 26179, 26181, 26183, 26185, 26484, 26507, 26522, 27705,
+ 27731, 27750, 29767, 29799, 29817, 30866, 30883, 30885, 31025, 31029,
+ 31031, 31033, 31035, 31037, 31114, 31126, 31134, 32687, 32722, 32767,
+ 35718, 35742, 35757, 36943, 36952, 36954, 37115, 37128, 37130, 37132,
+ 37134, 37136, 37143, 37145, 37152, 38843, 38863, 38897, 47458, 47467,
+ 47474, 49040, 49061, 49063, 49145, 49157, 49159, 49161, 49163, 49165,
+ 49167, 49169, 49171, 49757, 49770, 49782, 61333, 61344, 61346, 62860,
+ 62883, 62885, 62887, 62889, 62891, 62893, 62895, 62897, 62899, 62901,
+ 62903, 62905, 62907, 62909, 65496, 65498, 65500, 65521, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kIndexLowerLimitGain[3] = {
+ -7, -2, -1};
+
+const int16_t WebRtcIsac_kIndexUpperLimitGain[3] = {
+ 0, 3, 1};
+
+const uint16_t WebRtcIsac_kIndexMultsGain[2] = {
+ 18, 3};
+
+/* size of cdf table */
+const uint16_t WebRtcIsac_kQCdfTableSizeGain[1] = {
+ 256};
+
+///////////////////////////FIXED POINT
+/* mean values of pitch filter gains in FIXED point */
+const int16_t WebRtcIsac_kQMeanGain1Q12[144] = {
+ 843, 1092, 1336, 1222, 1405, 1656, 1500, 1815, 1843, 1838, 1839, 1843, 1843, 1843, 1843, 1843,
+ 1843, 1843, 814, 846, 1092, 1013, 1174, 1383, 1391, 1511, 1584, 1734, 1753, 1843, 1843, 1843,
+ 1843, 1843, 1843, 1843, 524, 689, 777, 845, 947, 1069, 1090, 1263, 1380, 1447, 1559, 1676,
+ 1645, 1749, 1843, 1843, 1843, 1843, 81, 477, 563, 611, 706, 806, 849, 1012, 1192, 1128,
+ 1330, 1489, 1425, 1576, 1826, 1741, 1843, 1843, 0, 290, 305, 356, 488, 575, 602, 741,
+ 890, 835, 1079, 1196, 1182, 1376, 1519, 1506, 1680, 1843, 0, 47, 97, 69, 289, 381,
+ 385, 474, 617, 664, 803, 1079, 935, 1160, 1269, 1265, 1506, 1741, 0, 0, 0, 0,
+ 112, 120, 190, 283, 442, 343, 526, 809, 684, 935, 1134, 1020, 1265, 1506, 0, 0,
+ 0, 0, 0, 0, 0, 111, 256, 87, 373, 597, 430, 684, 935, 770, 1020, 1265};
+
+const int16_t WebRtcIsac_kQMeanGain2Q12[144] = {
+ 1760, 1525, 1285, 1747, 1671, 1393, 1843, 1826, 1555, 1843, 1784, 1606, 1843, 1843, 1711, 1843,
+ 1843, 1814, 1389, 1275, 1040, 1564, 1414, 1252, 1610, 1495, 1343, 1753, 1592, 1405, 1804, 1720,
+ 1475, 1843, 1814, 1581, 1208, 1061, 856, 1349, 1148, 994, 1390, 1253, 1111, 1495, 1343, 1178,
+ 1770, 1465, 1234, 1814, 1581, 1342, 1040, 793, 713, 1053, 895, 737, 1128, 1003, 861, 1277,
+ 1094, 981, 1475, 1192, 1019, 1581, 1342, 1098, 855, 570, 483, 833, 648, 540, 948, 744,
+ 572, 1009, 844, 636, 1234, 934, 685, 1342, 1217, 984, 537, 318, 124, 603, 423, 350,
+ 687, 479, 322, 791, 581, 430, 987, 671, 488, 1098, 849, 597, 283, 27, 0, 397,
+ 222, 38, 513, 271, 124, 624, 325, 157, 737, 484, 233, 849, 597, 343, 27, 0,
+ 0, 141, 0, 0, 256, 69, 0, 370, 87, 0, 484, 229, 0, 597, 343, 87};
+
+const int16_t WebRtcIsac_kQMeanGain3Q12[144] = {
+ 1843, 1843, 1711, 1843, 1818, 1606, 1843, 1827, 1511, 1814, 1639, 1393, 1760, 1525, 1285, 1656,
+ 1419, 1176, 1835, 1718, 1475, 1841, 1650, 1387, 1648, 1498, 1287, 1600, 1411, 1176, 1522, 1299,
+ 1040, 1419, 1176, 928, 1773, 1461, 1128, 1532, 1355, 1202, 1429, 1260, 1115, 1398, 1151, 1025,
+ 1172, 1080, 790, 1176, 928, 677, 1475, 1147, 1019, 1276, 1096, 922, 1214, 1010, 901, 1057,
+ 893, 800, 1040, 796, 734, 928, 677, 424, 1137, 897, 753, 1120, 830, 710, 875, 751,
+ 601, 795, 642, 583, 790, 544, 475, 677, 474, 140, 987, 750, 482, 697, 573, 450,
+ 691, 487, 303, 661, 394, 332, 537, 303, 220, 424, 168, 0, 737, 484, 229, 624,
+ 348, 153, 441, 261, 136, 397, 166, 51, 283, 27, 0, 168, 0, 0, 484, 229,
+ 0, 370, 57, 0, 256, 43, 0, 141, 0, 0, 27, 0, 0, 0, 0, 0};
+
+
+const int16_t WebRtcIsac_kQMeanGain4Q12[144] = {
+ 1843, 1843, 1843, 1843, 1841, 1843, 1500, 1821, 1843, 1222, 1434, 1656, 843, 1092, 1336, 504,
+ 757, 1007, 1843, 1843, 1843, 1838, 1791, 1843, 1265, 1505, 1599, 965, 1219, 1425, 730, 821,
+ 1092, 249, 504, 757, 1783, 1819, 1843, 1351, 1567, 1727, 1096, 1268, 1409, 805, 961, 1131,
+ 444, 670, 843, 0, 249, 504, 1425, 1655, 1743, 1096, 1324, 1448, 822, 1019, 1199, 490,
+ 704, 867, 81, 450, 555, 0, 0, 249, 1247, 1428, 1530, 881, 1073, 1283, 610, 759,
+ 939, 278, 464, 645, 0, 200, 270, 0, 0, 0, 935, 1163, 1410, 528, 790, 1068,
+ 377, 499, 717, 173, 240, 274, 0, 43, 62, 0, 0, 0, 684, 935, 1182, 343,
+ 551, 735, 161, 262, 423, 0, 55, 27, 0, 0, 0, 0, 0, 0, 430, 684,
+ 935, 87, 377, 597, 0, 46, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
new file mode 100644
index 0000000000..145fd4e6aa
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include <stdint.h>
+
+/* header file for coding tables for the pitch filter side-info in the entropy
+ * coder */
+/********************* Pitch Filter Gain Coefficient Tables
+ * ************************/
+/* cdf for quantized pitch filter gains */
+extern const uint16_t WebRtcIsac_kQPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kIndexLowerLimitGain[3];
+
+extern const int16_t WebRtcIsac_kIndexUpperLimitGain[3];
+extern const uint16_t WebRtcIsac_kIndexMultsGain[2];
+
+/* mean values of pitch filter gains */
+//(Y)
+extern const int16_t WebRtcIsac_kQMeanGain1Q12[144];
+extern const int16_t WebRtcIsac_kQMeanGain2Q12[144];
+extern const int16_t WebRtcIsac_kQMeanGain3Q12[144];
+extern const int16_t WebRtcIsac_kQMeanGain4Q12[144];
+//(Y)
+
+/* size of cdf table */
+extern const uint16_t WebRtcIsac_kQCdfTableSizeGain[1];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c
new file mode 100644
index 0000000000..57d12021ac
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsac_kQPitchLagCdf1Lo[127] = {
+ 0, 134, 336, 549, 778, 998, 1264, 1512, 1777, 2070,
+ 2423, 2794, 3051, 3361, 3708, 3979, 4315, 4610, 4933, 5269,
+ 5575, 5896, 6155, 6480, 6816, 7129, 7477, 7764, 8061, 8358,
+ 8718, 9020, 9390, 9783, 10177, 10543, 10885, 11342, 11795, 12213,
+ 12680, 13096, 13524, 13919, 14436, 14903, 15349, 15795, 16267, 16734,
+ 17266, 17697, 18130, 18632, 19080, 19447, 19884, 20315, 20735, 21288,
+ 21764, 22264, 22723, 23193, 23680, 24111, 24557, 25022, 25537, 26082,
+ 26543, 27090, 27620, 28139, 28652, 29149, 29634, 30175, 30692, 31273,
+ 31866, 32506, 33059, 33650, 34296, 34955, 35629, 36295, 36967, 37726,
+ 38559, 39458, 40364, 41293, 42256, 43215, 44231, 45253, 46274, 47359,
+ 48482, 49678, 50810, 51853, 53016, 54148, 55235, 56263, 57282, 58363,
+ 59288, 60179, 61076, 61806, 62474, 63129, 63656, 64160, 64533, 64856,
+ 65152, 65535, 65535, 65535, 65535, 65535, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf2Lo[20] = {
+ 0, 429, 3558, 5861, 8558, 11639, 15210, 19502, 24773, 31983,
+ 42602, 48567, 52601, 55676, 58160, 60172, 61889, 63235, 65383, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf3Lo[2] = {
+ 0, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf4Lo[10] = {
+ 0, 2966, 6368, 11182, 19431, 37793, 48532, 55353, 60626, 65535};
+
+const uint16_t *WebRtcIsac_kQPitchLagCdfPtrLo[4] = {WebRtcIsac_kQPitchLagCdf1Lo, WebRtcIsac_kQPitchLagCdf2Lo, WebRtcIsac_kQPitchLagCdf3Lo, WebRtcIsac_kQPitchLagCdf4Lo};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsac_kQPitchLagCdfSizeLo[1] = {128};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kQIndexLowerLimitLagLo[4] = {
+-140, -9, 0, -4};
+
+const int16_t WebRtcIsac_kQIndexUpperLimitLagLo[4] = {
+-20, 9, 0, 4};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsac_kQInitIndexLagLo[3] = {
+ 10, 1, 5};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Lo[19] = {
+-17.21385070, -15.82678944, -14.07123081, -12.03003877, -10.01311864, -8.00794627, -5.91162987, -3.89231876, -1.90220980, -0.01879275,
+ 1.89144232, 3.88123171, 5.92146992, 7.96435361, 9.98923648, 11.98266347, 13.96101002, 15.74855713, 17.10976611};
+
+const double WebRtcIsac_kQMeanLag3Lo[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Lo[9] = {
+-7.76246496, -5.92083980, -3.94095226, -1.89502305, 0.03724681, 1.93054221, 3.96443467, 5.91726366, 7.78434291};
+
+const double WebRtcIsac_kQPitchLagStepsizeLo = 2.000000;
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsac_kQPitchLagCdf1Mid[255] = {
+ 0, 28, 61, 88, 121, 149, 233, 331, 475, 559,
+ 624, 661, 689, 712, 745, 791, 815, 843, 866, 922,
+ 959, 1024, 1061, 1117, 1178, 1238, 1280, 1350, 1453, 1513,
+ 1564, 1625, 1671, 1741, 1788, 1904, 2072, 2421, 2626, 2770,
+ 2840, 2900, 2942, 3012, 3068, 3115, 3147, 3194, 3254, 3319,
+ 3366, 3520, 3678, 3780, 3850, 3911, 3957, 4032, 4106, 4185,
+ 4292, 4474, 4683, 4842, 5019, 5191, 5321, 5428, 5540, 5675,
+ 5763, 5847, 5959, 6127, 6304, 6564, 6839, 7090, 7263, 7421,
+ 7556, 7728, 7872, 7984, 8142, 8361, 8580, 8743, 8938, 9227,
+ 9409, 9539, 9674, 9795, 9930, 10060, 10177, 10382, 10614, 10861,
+ 11038, 11271, 11415, 11629, 11792, 12044, 12193, 12416, 12574, 12821,
+ 13007, 13235, 13445, 13654, 13901, 14134, 14488, 15000, 15703, 16285,
+ 16504, 16797, 17086, 17328, 17579, 17807, 17998, 18268, 18538, 18836,
+ 19087, 19274, 19474, 19716, 19935, 20270, 20833, 21303, 21532, 21741,
+ 21978, 22207, 22523, 22770, 23054, 23613, 23943, 24204, 24399, 24651,
+ 24832, 25074, 25270, 25549, 25759, 26015, 26150, 26424, 26713, 27048,
+ 27342, 27504, 27681, 27854, 28021, 28207, 28412, 28664, 28859, 29064,
+ 29278, 29548, 29748, 30107, 30377, 30656, 30856, 31164, 31452, 31755,
+ 32011, 32328, 32626, 32919, 33319, 33789, 34329, 34925, 35396, 35973,
+ 36443, 36964, 37551, 38156, 38724, 39357, 40023, 40908, 41587, 42602,
+ 43924, 45037, 45810, 46597, 47421, 48291, 49092, 50051, 51448, 52719,
+ 53440, 54241, 54944, 55977, 56676, 57299, 57872, 58389, 59059, 59688,
+ 60237, 60782, 61094, 61573, 61890, 62290, 62658, 63030, 63217, 63454,
+ 63622, 63882, 64003, 64273, 64427, 64529, 64581, 64697, 64758, 64902,
+ 65414, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf2Mid[36] = {
+ 0, 71, 335, 581, 836, 1039, 1323, 1795, 2258, 2608,
+ 3005, 3591, 4243, 5344, 7163, 10583, 16848, 28078, 49448, 57007,
+ 60357, 61850, 62837, 63437, 63872, 64188, 64377, 64614, 64774, 64949,
+ 65039, 65115, 65223, 65360, 65474, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf3Mid[2] = {
+ 0, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf4Mid[20] = {
+ 0, 28, 246, 459, 667, 1045, 1523, 2337, 4337, 11347,
+ 44231, 56709, 60781, 62243, 63161, 63969, 64608, 65062, 65502, 65535};
+
+const uint16_t *WebRtcIsac_kQPitchLagCdfPtrMid[4] = {WebRtcIsac_kQPitchLagCdf1Mid, WebRtcIsac_kQPitchLagCdf2Mid, WebRtcIsac_kQPitchLagCdf3Mid, WebRtcIsac_kQPitchLagCdf4Mid};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsac_kQPitchLagCdfSizeMid[1] = {256};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kQIndexLowerLimitLagMid[4] = {
+-280, -17, 0, -9};
+
+const int16_t WebRtcIsac_kQIndexUpperLimitLagMid[4] = {
+-40, 17, 0, 9};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsac_kQInitIndexLagMid[3] = {
+ 18, 1, 10};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Mid[35] = {
+-16.89183900, -15.86949778, -15.05476653, -14.00664348, -13.02793036, -12.07324237, -11.00542532, -10.11250602, -8.90792971, -8.02474753,
+-7.00426767, -5.94055287, -4.98251338, -3.91053158, -2.98820425, -1.93524245, -0.92978085, -0.01722509, 0.91317387, 1.92973955,
+ 2.96908851, 3.93728974, 4.96308471, 5.92244151, 7.08673497, 8.00993708, 9.04656316, 9.98538742, 10.97851694, 11.94772884,
+ 13.02426166, 14.00039951, 15.01347042, 15.80758023, 16.94086895};
+
+const double WebRtcIsac_kQMeanLag3Mid[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Mid[19] = {
+-8.60409403, -7.89198395, -7.03450280, -5.86260421, -4.93822322, -3.93078706, -2.91302322, -1.91824007, -0.87003282, 0.02822649,
+ 0.89951758, 1.87495484, 2.91802604, 3.96874074, 5.06571703, 5.93618227, 7.00520185, 7.88497726, 8.64160364};
+
+const double WebRtcIsac_kQPitchLagStepsizeMid = 1.000000;
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const uint16_t WebRtcIsac_kQPitchLagCdf1Hi[511] = {
+ 0, 7, 18, 33, 69, 105, 156, 228, 315, 612,
+ 680, 691, 709, 724, 735, 738, 742, 746, 749, 753,
+ 756, 760, 764, 774, 782, 785, 789, 796, 800, 803,
+ 807, 814, 818, 822, 829, 832, 847, 854, 858, 869,
+ 876, 883, 898, 908, 934, 977, 1010, 1050, 1060, 1064,
+ 1075, 1078, 1086, 1089, 1093, 1104, 1111, 1122, 1133, 1136,
+ 1151, 1162, 1183, 1209, 1252, 1281, 1339, 1364, 1386, 1401,
+ 1411, 1415, 1426, 1430, 1433, 1440, 1448, 1455, 1462, 1477,
+ 1487, 1495, 1502, 1506, 1509, 1516, 1524, 1531, 1535, 1542,
+ 1553, 1556, 1578, 1589, 1611, 1625, 1639, 1643, 1654, 1665,
+ 1672, 1687, 1694, 1705, 1708, 1719, 1730, 1744, 1752, 1759,
+ 1791, 1795, 1820, 1867, 1886, 1915, 1936, 1943, 1965, 1987,
+ 2041, 2099, 2161, 2175, 2200, 2211, 2226, 2233, 2244, 2251,
+ 2266, 2280, 2287, 2298, 2309, 2316, 2331, 2342, 2356, 2378,
+ 2403, 2418, 2447, 2497, 2544, 2602, 2863, 2895, 2903, 2935,
+ 2950, 2971, 3004, 3011, 3018, 3029, 3040, 3062, 3087, 3127,
+ 3152, 3170, 3199, 3243, 3293, 3322, 3340, 3377, 3402, 3427,
+ 3474, 3518, 3543, 3579, 3601, 3637, 3659, 3706, 3731, 3760,
+ 3818, 3847, 3869, 3901, 3920, 3952, 4068, 4169, 4220, 4271,
+ 4524, 4571, 4604, 4632, 4672, 4730, 4777, 4806, 4857, 4904,
+ 4951, 5002, 5031, 5060, 5107, 5150, 5212, 5266, 5331, 5382,
+ 5432, 5490, 5544, 5610, 5700, 5762, 5812, 5874, 5972, 6022,
+ 6091, 6163, 6232, 6305, 6402, 6540, 6685, 6880, 7090, 7271,
+ 7379, 7452, 7542, 7625, 7687, 7770, 7843, 7911, 7966, 8024,
+ 8096, 8190, 8252, 8320, 8411, 8501, 8585, 8639, 8751, 8842,
+ 8918, 8986, 9066, 9127, 9203, 9269, 9345, 9406, 9464, 9536,
+ 9612, 9667, 9735, 9844, 9931, 10036, 10119, 10199, 10260, 10358,
+ 10441, 10514, 10666, 10734, 10872, 10951, 11053, 11125, 11223, 11324,
+ 11516, 11664, 11737, 11816, 11892, 12008, 12120, 12200, 12280, 12392,
+ 12490, 12576, 12685, 12812, 12917, 13003, 13108, 13210, 13300, 13384,
+ 13470, 13579, 13673, 13771, 13879, 13999, 14136, 14201, 14368, 14614,
+ 14759, 14867, 14958, 15030, 15121, 15189, 15280, 15385, 15461, 15555,
+ 15653, 15768, 15884, 15971, 16069, 16145, 16210, 16279, 16380, 16463,
+ 16539, 16615, 16688, 16818, 16919, 17017, 18041, 18338, 18523, 18649,
+ 18790, 18917, 19047, 19167, 19315, 19460, 19601, 19731, 19858, 20068,
+ 20173, 20318, 20466, 20625, 20741, 20911, 21045, 21201, 21396, 21588,
+ 21816, 22022, 22305, 22547, 22786, 23072, 23322, 23600, 23879, 24168,
+ 24433, 24769, 25120, 25511, 25895, 26289, 26792, 27219, 27683, 28077,
+ 28566, 29094, 29546, 29977, 30491, 30991, 31573, 32105, 32594, 33173,
+ 33788, 34497, 35181, 35833, 36488, 37255, 37921, 38645, 39275, 39894,
+ 40505, 41167, 41790, 42431, 43096, 43723, 44385, 45134, 45858, 46607,
+ 47349, 48091, 48768, 49405, 49955, 50555, 51167, 51985, 52611, 53078,
+ 53494, 53965, 54435, 54996, 55601, 56125, 56563, 56838, 57244, 57566,
+ 57967, 58297, 58771, 59093, 59419, 59647, 59886, 60143, 60461, 60693,
+ 60917, 61170, 61416, 61634, 61891, 62122, 62310, 62455, 62632, 62839,
+ 63103, 63436, 63639, 63805, 63906, 64015, 64192, 64355, 64475, 64558,
+ 64663, 64742, 64811, 64865, 64916, 64956, 64981, 65025, 65068, 65115,
+ 65195, 65314, 65419, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf2Hi[68] = {
+ 0, 7, 11, 22, 37, 52, 56, 59, 81, 85,
+ 89, 96, 115, 130, 137, 152, 170, 181, 193, 200,
+ 207, 233, 237, 259, 289, 318, 363, 433, 592, 992,
+ 1607, 3062, 6149, 12206, 25522, 48368, 58223, 61918, 63640, 64584,
+ 64943, 65098, 65206, 65268, 65294, 65335, 65350, 65372, 65387, 65402,
+ 65413, 65420, 65428, 65435, 65439, 65450, 65454, 65468, 65472, 65476,
+ 65483, 65491, 65498, 65505, 65516, 65520, 65528, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf3Hi[2] = {
+ 0, 65535};
+
+const uint16_t WebRtcIsac_kQPitchLagCdf4Hi[35] = {
+ 0, 7, 19, 30, 41, 48, 63, 74, 82, 96,
+ 122, 152, 215, 330, 701, 2611, 10931, 48106, 61177, 64341,
+ 65112, 65238, 65309, 65338, 65364, 65379, 65401, 65427, 65453, 65465,
+ 65476, 65490, 65509, 65528, 65535};
+
+const uint16_t *WebRtcIsac_kQPitchLagCdfPtrHi[4] = {WebRtcIsac_kQPitchLagCdf1Hi, WebRtcIsac_kQPitchLagCdf2Hi, WebRtcIsac_kQPitchLagCdf3Hi, WebRtcIsac_kQPitchLagCdf4Hi};
+
+/* size of first cdf table */
+const uint16_t WebRtcIsac_kQPitchLagCdfSizeHi[1] = {512};
+
+/* index limits and ranges */
+const int16_t WebRtcIsac_kQindexLowerLimitLagHi[4] = {
+-552, -34, 0, -16};
+
+const int16_t WebRtcIsac_kQindexUpperLimitLagHi[4] = {
+-80, 32, 0, 17};
+
+/* initial index for arithmetic decoder */
+const uint16_t WebRtcIsac_kQInitIndexLagHi[3] = {
+ 34, 1, 18};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Hi[67] = {
+-17.07263295, -16.50000000, -15.83966081, -15.55613708, -14.96948007, -14.50000000, -14.00000000, -13.48377986, -13.00000000, -12.50000000,
+-11.93199636, -11.44530414, -11.04197641, -10.39910301, -10.15202337, -9.51322461, -8.93357741, -8.46456632, -8.10270672, -7.53751847,
+-6.98686404, -6.50000000, -6.08463150, -5.46872991, -5.00864717, -4.50163760, -4.01382410, -3.43856708, -2.96898001, -2.46554810,
+-1.96861004, -1.47106701, -0.97197237, -0.46561654, -0.00531409, 0.45767857, 0.96777907, 1.47507903, 1.97740425, 2.46695420,
+ 3.00695774, 3.47167185, 4.02712538, 4.49280007, 5.01087640, 5.48191963, 6.04916550, 6.51511058, 6.97297819, 7.46565499,
+ 8.01489405, 8.39912001, 8.91819757, 9.50000000, 10.11654065, 10.50000000, 11.03712583, 11.50000000, 12.00000000, 12.38964346,
+ 12.89466127, 13.43657881, 13.96013840, 14.46279912, 15.00000000, 15.39412269, 15.96662441};
+
+const double WebRtcIsac_kQMeanLag3Hi[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Hi[34] = {
+-7.98331221, -7.47988769, -7.03626557, -6.52708003, -6.06982173, -5.51856292, -5.05827033, -4.45909878, -3.99125864, -3.45308135,
+-3.02328139, -2.47297273, -1.94341995, -1.44699056, -0.93612243, -0.43012406, 0.01120357, 0.44054812, 0.93199883, 1.45669587,
+ 1.97218322, 2.50187419, 2.98748690, 3.49343202, 4.01660147, 4.50984306, 5.01402683, 5.58936797, 5.91787793, 6.59998900,
+ 6.85034315, 7.53503316, 7.87711194, 8.53631648};
+
+const double WebRtcIsac_kQPitchLagStepsizeHi = 0.500000;
+
+/* transform matrix */
+const double WebRtcIsac_kTransform[4][4] = {
+{-0.50000000, -0.50000000, -0.50000000, -0.50000000},
+{ 0.67082039, 0.22360680, -0.22360680, -0.67082039},
+{ 0.50000000, -0.50000000, -0.50000000, 0.50000000},
+{ 0.22360680, -0.67082039, 0.67082039, -0.22360680}};
+
+/* transpose transform matrix */
+const double WebRtcIsac_kTransformTranspose[4][4] = {
+{-0.50000000, 0.67082039, 0.50000000, 0.22360680},
+{-0.50000000, 0.22360680, -0.50000000, -0.67082039},
+{-0.50000000, -0.22360680, -0.50000000, 0.67082039},
+{-0.50000000, -0.67082039, 0.50000000, -0.22360680}};
+
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
new file mode 100644
index 0000000000..b48e358a5a
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy
+ * coder.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+
+#include <stdint.h>
+
+/* header file for coding tables for the pitch filter side-info in the entropy
+ * coder */
+/********************* Pitch Filter Lag Coefficient Tables
+ * ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsac_kQPitchLagCdf1Lo[127];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf2Lo[20];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf3Lo[2];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf4Lo[10];
+
+extern const uint16_t* WebRtcIsac_kQPitchLagCdfPtrLo[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsac_kQPitchLagCdfSizeLo[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kQIndexLowerLimitLagLo[4];
+extern const int16_t WebRtcIsac_kQIndexUpperLimitLagLo[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsac_kQInitIndexLagLo[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Lo[19];
+extern const double WebRtcIsac_kQMeanLag3Lo[1];
+extern const double WebRtcIsac_kQMeanLag4Lo[9];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeLo;
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsac_kQPitchLagCdf1Mid[255];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf2Mid[36];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf3Mid[2];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf4Mid[20];
+
+extern const uint16_t* WebRtcIsac_kQPitchLagCdfPtrMid[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsac_kQPitchLagCdfSizeMid[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kQIndexLowerLimitLagMid[4];
+extern const int16_t WebRtcIsac_kQIndexUpperLimitLagMid[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsac_kQInitIndexLagMid[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Mid[35];
+extern const double WebRtcIsac_kQMeanLag3Mid[1];
+extern const double WebRtcIsac_kQMeanLag4Mid[19];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeMid;
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const uint16_t WebRtcIsac_kQPitchLagCdf1Hi[511];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf2Hi[68];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf3Hi[2];
+extern const uint16_t WebRtcIsac_kQPitchLagCdf4Hi[35];
+
+extern const uint16_t* WebRtcIsac_kQPitchLagCdfPtrHi[4];
+
+/* size of first cdf table */
+extern const uint16_t WebRtcIsac_kQPitchLagCdfSizeHi[1];
+
+/* index limits and ranges */
+extern const int16_t WebRtcIsac_kQindexLowerLimitLagHi[4];
+extern const int16_t WebRtcIsac_kQindexUpperLimitLagHi[4];
+
+/* initial index for arithmetic decoder */
+extern const uint16_t WebRtcIsac_kQInitIndexLagHi[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Hi[67];
+extern const double WebRtcIsac_kQMeanLag3Hi[1];
+extern const double WebRtcIsac_kQMeanLag4Hi[34];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeHi;
+
+/* transform matrix */
+extern const double WebRtcIsac_kTransform[4][4];
+
+/* transpose transform matrix */
+extern const double WebRtcIsac_kTransformTranspose[4][4];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/settings.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/settings.h
new file mode 100644
index 0000000000..abce90c4f5
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/settings.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * settings.h
+ *
+ * Declaration of #defines used in the iSAC codec
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_
+
+/* sampling frequency (Hz) */
+#define FS 16000
+
+/* number of samples per frame (either 320 (20ms), 480 (30ms) or 960 (60ms)) */
+#define INITIAL_FRAMESAMPLES 960
+
+/* do not modify the following; this will have to be modified if we
+ * have a 20ms framesize option */
+/**********************************************************************/
+/* miliseconds */
+#define FRAMESIZE 30
+/* number of samples per frame processed in the encoder, 480 */
+#define FRAMESAMPLES 480 /* ((FRAMESIZE*FS)/1000) */
+#define FRAMESAMPLES_HALF 240
+#define FRAMESAMPLES_QUARTER 120
+/**********************************************************************/
+
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+#define MAX_SWBFRAMESAMPLES (MAX_FRAMESAMPLES * 2)
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms ((10 * FS) / 1000)
+#define SWBFRAMESAMPLES_10ms (FRAMESAMPLES_10ms * 2)
+/* number of samples in 30 ms frame */
+#define FRAMESAMPLES_30ms 480
+/* number of subframes */
+#define SUBFRAMES 6
+/* length of a subframe */
+#define UPDATE 80
+/* length of half a subframe (low/high band) */
+#define HALF_SUBFRAMELEN (UPDATE / 2)
+/* samples of look ahead (in a half-band, so actually
+ * half the samples of look ahead @ FS) */
+#define QLOOKAHEAD 24 /* 3 ms */
+/* order of AR model in spectral entropy coder */
+#define AR_ORDER 6
+/* order of LP model in spectral entropy coder */
+#define LP_ORDER 0
+
+/* window length (masking analysis) */
+#define WINLEN 256
+/* order of low-band pole filter used to approximate masking curve */
+#define ORDERLO 12
+/* order of hi-band pole filter used to approximate masking curve */
+#define ORDERHI 6
+
+#define UB_LPC_ORDER 4
+#define UB_LPC_VEC_PER_FRAME 2
+#define UB16_LPC_VEC_PER_FRAME 4
+#define UB_ACTIVE_SUBFRAMES 2
+#define UB_MAX_LPC_ORDER 6
+#define UB_INTERPOL_SEGMENTS 1
+#define UB16_INTERPOL_SEGMENTS 3
+#define LB_TOTAL_DELAY_SAMPLES 48
+enum ISACBandwidth { isac8kHz = 8, isac12kHz = 12, isac16kHz = 16 };
+enum ISACBand {
+ kIsacLowerBand = 0,
+ kIsacUpperBand12 = 1,
+ kIsacUpperBand16 = 2
+};
+enum IsacSamplingRate { kIsacWideband = 16, kIsacSuperWideband = 32 };
+#define UB_LPC_GAIN_DIM SUBFRAMES
+#define FB_STATE_SIZE_WORD32 6
+
+/* order for post_filter_bank */
+#define POSTQORDER 3
+/* order for pre-filterbank */
+#define QORDER 3
+/* another order */
+#define QORDER_ALL (POSTQORDER + QORDER - 1)
+/* for decimator */
+#define ALLPASSSECTIONS 2
+
+/* array size for byte stream in number of bytes. */
+/* The old maximum size still needed for the decoding */
+#define STREAM_SIZE_MAX 600
+#define STREAM_SIZE_MAX_30 200 /* 200 bytes=53.4 kbps @ 30 ms.framelength */
+#define STREAM_SIZE_MAX_60 400 /* 400 bytes=53.4 kbps @ 60 ms.framelength */
+
+/* storage size for bit counts */
+#define BIT_COUNTER_SIZE 30
+/* maximum order of any AR model or filter */
+#define MAX_AR_MODEL_ORDER 12 // 50
+
+/* For pitch analysis */
+#define PITCH_FRAME_LEN (FRAMESAMPLES_HALF) /* 30 ms */
+#define PITCH_MAX_LAG 140 /* 57 Hz */
+#define PITCH_MIN_LAG 20 /* 400 Hz */
+#define PITCH_MAX_GAIN 0.45
+#define PITCH_MAX_GAIN_06 0.27 /* PITCH_MAX_GAIN*0.6 */
+#define PITCH_MAX_GAIN_Q12 1843
+#define PITCH_LAG_SPAN2 (PITCH_MAX_LAG / 2 - PITCH_MIN_LAG / 2 + 5)
+#define PITCH_CORR_LEN2 60 /* 15 ms */
+#define PITCH_CORR_STEP2 (PITCH_FRAME_LEN / 4)
+#define PITCH_BW 11 /* half the band width of correlation surface */
+#define PITCH_SUBFRAMES 4
+#define PITCH_GRAN_PER_SUBFRAME 5
+#define PITCH_SUBFRAME_LEN (PITCH_FRAME_LEN / PITCH_SUBFRAMES)
+#define PITCH_UPDATE (PITCH_SUBFRAME_LEN / PITCH_GRAN_PER_SUBFRAME)
+/* maximum number of peaks to be examined in correlation surface */
+#define PITCH_MAX_NUM_PEAKS 10
+#define PITCH_PEAK_DECAY 0.85
+/* For weighting filter */
+#define PITCH_WLPCORDER 6
+#define PITCH_WLPCWINLEN PITCH_FRAME_LEN
+#define PITCH_WLPCASYM 0.3 /* asymmetry parameter */
+#define PITCH_WLPCBUFLEN PITCH_WLPCWINLEN
+/* For pitch filter */
+/* Extra 50 for fraction and LP filters */
+#define PITCH_BUFFSIZE (PITCH_MAX_LAG + 50)
+#define PITCH_INTBUFFSIZE (PITCH_FRAME_LEN + PITCH_BUFFSIZE)
+/* Max rel. step for interpolation */
+#define PITCH_UPSTEP 1.5
+/* Max rel. step for interpolation */
+#define PITCH_DOWNSTEP 0.67
+#define PITCH_FRACS 8
+#define PITCH_FRACORDER 9
+#define PITCH_DAMPORDER 5
+#define PITCH_FILTDELAY 1.5f
+/* stepsize for quantization of the pitch Gain */
+#define PITCH_GAIN_STEPSIZE 0.125
+
+/* Order of high pass filter */
+#define HPORDER 2
+
+/* some mathematical constants */
+/* log2(exp) */
+#define LOG2EXP 1.44269504088896
+#define PI 3.14159265358979
+
+/* Maximum number of iterations allowed to limit payload size */
+#define MAX_PAYLOAD_LIMIT_ITERATION 5
+
+/* Redundant Coding */
+#define RCU_BOTTLENECK_BPS 16000
+#define RCU_TRANSCODING_SCALE 0.40f
+#define RCU_TRANSCODING_SCALE_INVERSE 2.5f
+
+#define RCU_TRANSCODING_SCALE_UB 0.50f
+#define RCU_TRANSCODING_SCALE_UB_INVERSE 2.0f
+
+/* Define Error codes */
+/* 6000 General */
+#define ISAC_MEMORY_ALLOCATION_FAILED 6010
+#define ISAC_MODE_MISMATCH 6020
+#define ISAC_DISALLOWED_BOTTLENECK 6030
+#define ISAC_DISALLOWED_FRAME_LENGTH 6040
+#define ISAC_UNSUPPORTED_SAMPLING_FREQUENCY 6050
+
+/* 6200 Bandwidth estimator */
+#define ISAC_RANGE_ERROR_BW_ESTIMATOR 6240
+/* 6400 Encoder */
+#define ISAC_ENCODER_NOT_INITIATED 6410
+#define ISAC_DISALLOWED_CODING_MODE 6420
+#define ISAC_DISALLOWED_FRAME_MODE_ENCODER 6430
+#define ISAC_DISALLOWED_BITSTREAM_LENGTH 6440
+#define ISAC_PAYLOAD_LARGER_THAN_LIMIT 6450
+#define ISAC_DISALLOWED_ENCODER_BANDWIDTH 6460
+/* 6600 Decoder */
+#define ISAC_DECODER_NOT_INITIATED 6610
+#define ISAC_EMPTY_PACKET 6620
+#define ISAC_DISALLOWED_FRAME_MODE_DECODER 6630
+#define ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH 6640
+#define ISAC_RANGE_ERROR_DECODE_BANDWIDTH 6650
+#define ISAC_RANGE_ERROR_DECODE_PITCH_GAIN 6660
+#define ISAC_RANGE_ERROR_DECODE_PITCH_LAG 6670
+#define ISAC_RANGE_ERROR_DECODE_LPC 6680
+#define ISAC_RANGE_ERROR_DECODE_SPECTRUM 6690
+#define ISAC_LENGTH_MISMATCH 6730
+#define ISAC_RANGE_ERROR_DECODE_BANDWITH 6740
+#define ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER 6750
+#define ISAC_DISALLOWED_LPC_MODEL 6760
+/* 6800 Call setup formats */
+#define ISAC_INCOMPATIBLE_FORMATS 6810
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c
new file mode 100644
index 0000000000..839d5d4586
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+const uint16_t WebRtcIsac_kQArRc1Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0, 2, 4, 129, 7707, 57485, 65495, 65527, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 2 */
+const uint16_t WebRtcIsac_kQArRc2Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0, 2, 4, 7, 531, 25298, 64525, 65526, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 3 */
+const uint16_t WebRtcIsac_kQArRc3Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0, 2, 4, 6, 620, 22898, 64843, 65527, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 4 */
+const uint16_t WebRtcIsac_kQArRc4Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0, 2, 4, 6, 35, 10034, 60733, 65506, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 5 */
+const uint16_t WebRtcIsac_kQArRc5Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0, 2, 4, 6, 36, 7567, 56727, 65385, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 6 */
+const uint16_t WebRtcIsac_kQArRc6Cdf[NUM_AR_RC_QUANT_BAUNDARY] = {
+ 0, 2, 4, 6, 14, 6579, 57360, 65409, 65529, 65531,
+ 65533, 65535};
+
+/* representation levels for quantized reflection coefficient 1 */
+const int16_t WebRtcIsac_kQArRc1Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+ -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const int16_t WebRtcIsac_kQArRc2Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+ -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const int16_t WebRtcIsac_kQArRc3Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const int16_t WebRtcIsac_kQArRc4Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const int16_t WebRtcIsac_kQArRc5Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const int16_t WebRtcIsac_kQArRc6Levels[NUM_AR_RC_QUANT_BAUNDARY - 1] = {
+-32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const int16_t WebRtcIsac_kQArBoundaryLevels[NUM_AR_RC_QUANT_BAUNDARY] = {
+-32768, -31441, -27566, -21458, -13612, -4663, 4663, 13612, 21458, 27566, 31441,
+32767
+};
+
+/* initial index for AR reflection coefficient quantizer and cdf table search */
+const uint16_t WebRtcIsac_kQArRcInitIndex[6] = {
+ 5, 5, 5, 5, 5, 5};
+
+/* pointers to AR cdf tables */
+const uint16_t *WebRtcIsac_kQArRcCdfPtr[AR_ORDER] = {
+ WebRtcIsac_kQArRc1Cdf, WebRtcIsac_kQArRc2Cdf, WebRtcIsac_kQArRc3Cdf,
+ WebRtcIsac_kQArRc4Cdf, WebRtcIsac_kQArRc5Cdf, WebRtcIsac_kQArRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const int16_t *WebRtcIsac_kQArRcLevelsPtr[AR_ORDER] = {
+ WebRtcIsac_kQArRc1Levels, WebRtcIsac_kQArRc2Levels, WebRtcIsac_kQArRc3Levels,
+ WebRtcIsac_kQArRc4Levels, WebRtcIsac_kQArRc5Levels, WebRtcIsac_kQArRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+const uint16_t WebRtcIsac_kQGainCdf[19] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 1172,
+ 11119, 29411, 51699, 64445, 65527, 65529, 65531, 65533, 65535};
+
+/* representation levels for quantized squared Gain coefficient */
+const int32_t WebRtcIsac_kQGain2Levels[18] = {
+// 17, 28, 46, 76, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+ 128, 128, 128, 128, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+/* quantization boundary levels for squared Gain coefficient */
+const int32_t WebRtcIsac_kQGain2BoundaryLevels[19] = {
+0, 21, 35, 59, 99, 166, 280, 475, 815, 1414, 2495, 4505, 8397, 16405, 34431, 81359, 240497, 921600, 0x7FFFFFFF};
+
+/* pointers to Gain cdf table */
+const uint16_t *WebRtcIsac_kQGainCdf_ptr[1] = {WebRtcIsac_kQGainCdf};
+
+/* Gain initial index for gain quantizer and cdf table search */
+const uint16_t WebRtcIsac_kQGainInitIndex[1] = {11};
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+const int16_t WebRtcIsac_kCos[6][60] = {
+{512, 512, 511, 510, 508, 507, 505, 502, 499, 496, 493, 489, 485, 480, 476, 470, 465, 459, 453, 447,
+440, 433, 426, 418, 410, 402, 394, 385, 376, 367, 357, 348, 338, 327, 317, 306, 295, 284, 273, 262,
+250, 238, 226, 214, 202, 190, 177, 165, 152, 139, 126, 113, 100, 87, 73, 60, 47, 33, 20, 7},
+{512, 510, 508, 503, 498, 491, 483, 473, 462, 450, 437, 422, 406, 389, 371, 352, 333, 312, 290, 268,
+244, 220, 196, 171, 145, 120, 93, 67, 40, 13, -13, -40, -67, -93, -120, -145, -171, -196, -220, -244,
+-268, -290, -312, -333, -352, -371, -389, -406, -422, -437, -450, -462, -473, -483, -491, -498, -503, -508, -510, -512},
+{512, 508, 502, 493, 480, 465, 447, 426, 402, 376, 348, 317, 284, 250, 214, 177, 139, 100, 60, 20,
+-20, -60, -100, -139, -177, -214, -250, -284, -317, -348, -376, -402, -426, -447, -465, -480, -493, -502, -508, -512,
+-512, -508, -502, -493, -480, -465, -447, -426, -402, -376, -348, -317, -284, -250, -214, -177, -139, -100, -60, -20},
+{511, 506, 495, 478, 456, 429, 398, 362, 322, 279, 232, 183, 133, 80, 27, -27, -80, -133, -183, -232,
+-279, -322, -362, -398, -429, -456, -478, -495, -506, -511, -511, -506, -495, -478, -456, -429, -398, -362, -322, -279,
+-232, -183, -133, -80, -27, 27, 80, 133, 183, 232, 279, 322, 362, 398, 429, 456, 478, 495, 506, 511},
+{511, 502, 485, 459, 426, 385, 338, 284, 226, 165, 100, 33, -33, -100, -165, -226, -284, -338, -385, -426,
+-459, -485, -502, -511, -511, -502, -485, -459, -426, -385, -338, -284, -226, -165, -100, -33, 33, 100, 165, 226,
+284, 338, 385, 426, 459, 485, 502, 511, 511, 502, 485, 459, 426, 385, 338, 284, 226, 165, 100, 33},
+{510, 498, 473, 437, 389, 333, 268, 196, 120, 40, -40, -120, -196, -268, -333, -389, -437, -473, -498, -510,
+-510, -498, -473, -437, -389, -333, -268, -196, -120, -40, 40, 120, 196, 268, 333, 389, 437, 473, 498, 510,
+510, 498, 473, 437, 389, 333, 268, 196, 120, 40, -40, -120, -196, -268, -333, -389, -437, -473, -498, -510}
+};
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h
new file mode 100644
index 0000000000..d272be0dc3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.h
+ *
+ * This file contains definitions of tables with AR coefficients,
+ * Gain coefficients and cosine tables.
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+
+#define NUM_AR_RC_QUANT_BAUNDARY 12
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const uint16_t WebRtcIsac_kQArRc1Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const uint16_t WebRtcIsac_kQArRc2Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const uint16_t WebRtcIsac_kQArRc3Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const uint16_t WebRtcIsac_kQArRc4Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const uint16_t WebRtcIsac_kQArRc5Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const uint16_t WebRtcIsac_kQArRc6Cdf[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* quantization boundary levels for reflection coefficients */
+extern const int16_t WebRtcIsac_kQArBoundaryLevels[NUM_AR_RC_QUANT_BAUNDARY];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search
+ */
+extern const uint16_t WebRtcIsac_kQArRcInitIndex[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const uint16_t* WebRtcIsac_kQArRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const int16_t* WebRtcIsac_kQArRcLevelsPtr[AR_ORDER];
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const uint16_t WebRtcIsac_kQGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const int32_t WebRtcIsac_kQGain2Levels[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const int32_t WebRtcIsac_kQGain2BoundaryLevels[19];
+
+/* pointer to Gain cdf table */
+extern const uint16_t* WebRtcIsac_kQGainCdf_ptr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const uint16_t WebRtcIsac_kQGainInitIndex[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const int16_t WebRtcIsac_kCos[6][60];
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ \
+ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/structs.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/structs.h
new file mode 100644
index 0000000000..6861ca42bd
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/structs.h
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * structs.h
+ *
+ * This header file contains all the structs used in the ISAC codec
+ *
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_
+
+#include "modules/audio_coding/codecs/isac/bandwidth_info.h"
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/third_party/fft/fft.h"
+
+typedef struct Bitstreamstruct {
+ uint8_t stream[STREAM_SIZE_MAX];
+ uint32_t W_upper;
+ uint32_t streamval;
+ uint32_t stream_index;
+
+} Bitstr;
+
+typedef struct {
+ double DataBufferLo[WINLEN];
+ double DataBufferHi[WINLEN];
+
+ double CorrBufLo[ORDERLO + 1];
+ double CorrBufHi[ORDERHI + 1];
+
+ float PreStateLoF[ORDERLO + 1];
+ float PreStateLoG[ORDERLO + 1];
+ float PreStateHiF[ORDERHI + 1];
+ float PreStateHiG[ORDERHI + 1];
+ float PostStateLoF[ORDERLO + 1];
+ float PostStateLoG[ORDERLO + 1];
+ float PostStateHiF[ORDERHI + 1];
+ float PostStateHiG[ORDERHI + 1];
+
+ double OldEnergy;
+
+} MaskFiltstr;
+
+typedef struct {
+ // state vectors for each of the two analysis filters
+ double INSTAT1[2 * (QORDER - 1)];
+ double INSTAT2[2 * (QORDER - 1)];
+ double INSTATLA1[2 * (QORDER - 1)];
+ double INSTATLA2[2 * (QORDER - 1)];
+ double INLABUF1[QLOOKAHEAD];
+ double INLABUF2[QLOOKAHEAD];
+
+ float INSTAT1_float[2 * (QORDER - 1)];
+ float INSTAT2_float[2 * (QORDER - 1)];
+ float INSTATLA1_float[2 * (QORDER - 1)];
+ float INSTATLA2_float[2 * (QORDER - 1)];
+ float INLABUF1_float[QLOOKAHEAD];
+ float INLABUF2_float[QLOOKAHEAD];
+
+ /* High pass filter */
+ double HPstates[HPORDER];
+ float HPstates_float[HPORDER];
+
+} PreFiltBankstr;
+
+typedef struct {
+ // state vectors for each of the two analysis filters
+ double STATE_0_LOWER[2 * POSTQORDER];
+ double STATE_0_UPPER[2 * POSTQORDER];
+
+ /* High pass filter */
+ double HPstates1[HPORDER];
+ double HPstates2[HPORDER];
+
+ float STATE_0_LOWER_float[2 * POSTQORDER];
+ float STATE_0_UPPER_float[2 * POSTQORDER];
+
+ float HPstates1_float[HPORDER];
+ float HPstates2_float[HPORDER];
+
+} PostFiltBankstr;
+
+typedef struct {
+ // data buffer for pitch filter
+ double ubuf[PITCH_BUFFSIZE];
+
+ // low pass state vector
+ double ystate[PITCH_DAMPORDER];
+
+ // old lag and gain
+ double oldlagp[1];
+ double oldgainp[1];
+
+} PitchFiltstr;
+
+typedef struct {
+ // data buffer
+ double buffer[PITCH_WLPCBUFLEN];
+
+ // state vectors
+ double istate[PITCH_WLPCORDER];
+ double weostate[PITCH_WLPCORDER];
+ double whostate[PITCH_WLPCORDER];
+
+ // LPC window -> should be a global array because constant
+ double window[PITCH_WLPCWINLEN];
+
+} WeightFiltstr;
+
+typedef struct {
+ // for inital estimator
+ double dec_buffer[PITCH_CORR_LEN2 + PITCH_CORR_STEP2 + PITCH_MAX_LAG / 2 -
+ PITCH_FRAME_LEN / 2 + 2];
+ double decimator_state[2 * ALLPASSSECTIONS + 1];
+ double hp_state[2];
+
+ double whitened_buf[QLOOKAHEAD];
+
+ double inbuf[QLOOKAHEAD];
+
+ PitchFiltstr PFstr_wght;
+ PitchFiltstr PFstr;
+ WeightFiltstr Wghtstr;
+
+} PitchAnalysisStruct;
+
+/* Have instance of struct together with other iSAC structs */
+typedef struct {
+ /* Previous frame length (in ms) */
+ int32_t prev_frame_length;
+
+ /* Previous RTP timestamp from received
+ packet (in samples relative beginning) */
+ int32_t prev_rec_rtp_number;
+
+ /* Send timestamp for previous packet (in ms using timeGetTime()) */
+ uint32_t prev_rec_send_ts;
+
+ /* Arrival time for previous packet (in ms using timeGetTime()) */
+ uint32_t prev_rec_arr_ts;
+
+ /* rate of previous packet, derived from RTP timestamps (in bits/s) */
+ float prev_rec_rtp_rate;
+
+ /* Time sinse the last update of the BN estimate (in ms) */
+ uint32_t last_update_ts;
+
+ /* Time sinse the last reduction (in ms) */
+ uint32_t last_reduction_ts;
+
+ /* How many times the estimate was update in the beginning */
+ int32_t count_tot_updates_rec;
+
+ /* The estimated bottle neck rate from there to here (in bits/s) */
+ int32_t rec_bw;
+ float rec_bw_inv;
+ float rec_bw_avg;
+ float rec_bw_avg_Q;
+
+ /* The estimated mean absolute jitter value,
+ as seen on this side (in ms) */
+ float rec_jitter;
+ float rec_jitter_short_term;
+ float rec_jitter_short_term_abs;
+ float rec_max_delay;
+ float rec_max_delay_avg_Q;
+
+ /* (assumed) bitrate for headers (bps) */
+ float rec_header_rate;
+
+ /* The estimated bottle neck rate from here to there (in bits/s) */
+ float send_bw_avg;
+
+ /* The estimated mean absolute jitter value, as seen on
+ the other siee (in ms) */
+ float send_max_delay_avg;
+
+ // number of packets received since last update
+ int num_pkts_rec;
+
+ int num_consec_rec_pkts_over_30k;
+
+ // flag for marking that a high speed network has been
+ // detected downstream
+ int hsn_detect_rec;
+
+ int num_consec_snt_pkts_over_30k;
+
+ // flag for marking that a high speed network has
+ // been detected upstream
+ int hsn_detect_snd;
+
+ uint32_t start_wait_period;
+
+ int in_wait_period;
+
+ int change_to_WB;
+
+ uint32_t senderTimestamp;
+ uint32_t receiverTimestamp;
+ // enum IsacSamplingRate incomingStreamSampFreq;
+ uint16_t numConsecLatePkts;
+ float consecLatency;
+ int16_t inWaitLatePkts;
+
+ IsacBandwidthInfo external_bw_info;
+} BwEstimatorstr;
+
+typedef struct {
+ /* boolean, flags if previous packet exceeded B.N. */
+ int PrevExceed;
+ /* ms */
+ int ExceedAgo;
+ /* packets left to send in current burst */
+ int BurstCounter;
+ /* packets */
+ int InitCounter;
+ /* ms remaining in buffer when next packet will be sent */
+ double StillBuffered;
+
+} RateModel;
+
+/* The following strutc is used to store data from encoding, to make it
+ fast and easy to construct a new bitstream with a different Bandwidth
+ estimate. All values (except framelength and minBytes) is double size to
+ handle 60 ms of data.
+*/
+typedef struct {
+ /* Used to keep track of if it is first or second part of 60 msec packet */
+ int startIdx;
+
+ /* Frame length in samples */
+ int16_t framelength;
+
+ /* Pitch Gain */
+ int pitchGain_index[2];
+
+ /* Pitch Lag */
+ double meanGain[2];
+ int pitchIndex[PITCH_SUBFRAMES * 2];
+
+ /* LPC */
+ int LPCindex_s[108 * 2]; /* KLT_ORDER_SHAPE = 108 */
+ int LPCindex_g[12 * 2]; /* KLT_ORDER_GAIN = 12 */
+ double LPCcoeffs_lo[(ORDERLO + 1) * SUBFRAMES * 2];
+ double LPCcoeffs_hi[(ORDERHI + 1) * SUBFRAMES * 2];
+
+ /* Encode Spec */
+ int16_t fre[FRAMESAMPLES];
+ int16_t fim[FRAMESAMPLES];
+ int16_t AvgPitchGain[2];
+
+ /* Used in adaptive mode only */
+ int minBytes;
+
+} IsacSaveEncoderData;
+
+typedef struct {
+ int indexLPCShape[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ double lpcGain[SUBFRAMES << 1];
+ int lpcGainIndex[SUBFRAMES << 1];
+
+ Bitstr bitStreamObj;
+
+ int16_t realFFT[FRAMESAMPLES_HALF];
+ int16_t imagFFT[FRAMESAMPLES_HALF];
+} ISACUBSaveEncDataStruct;
+
+typedef struct {
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PitchAnalysisStruct pitchanalysisstr_obj;
+ FFTstr fftstr_obj;
+ IsacSaveEncoderData SaveEnc_obj;
+
+ int buffer_index;
+ int16_t current_framesamples;
+
+ float data_buffer_float[FRAMESAMPLES_30ms];
+
+ int frame_nb;
+ double bottleneck;
+ int16_t new_framelength;
+ double s2nr;
+
+ /* Maximum allowed number of bits for a 30 msec packet */
+ int16_t payloadLimitBytes30;
+ /* Maximum allowed number of bits for a 30 msec packet */
+ int16_t payloadLimitBytes60;
+ /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ int16_t maxPayloadBytes;
+ /* Maximum allowed rate in bytes per 30 msec packet */
+ int16_t maxRateInBytes;
+
+ /*---
+ If set to 1 iSAC will not adapt the frame-size, if used in
+ channel-adaptive mode. The initial value will be used for all rates.
+ ---*/
+ int16_t enforceFrameSize;
+
+ /*-----
+ This records the BWE index the encoder injected into the bit-stream.
+ It will be used in RCU. The same BWE index of main payload will be in
+ the redundant payload. We can not retrieve it from BWE because it is
+ a recursive procedure (WebRtcIsac_GetDownlinkBwJitIndexImpl) and has to be
+ called only once per each encode.
+ -----*/
+ int16_t lastBWIdx;
+} ISACLBEncStruct;
+
+typedef struct {
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ FFTstr fftstr_obj;
+ ISACUBSaveEncDataStruct SaveEnc_obj;
+
+ int buffer_index;
+ float data_buffer_float[MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES];
+ double bottleneck;
+ /* Maximum allowed number of bits for a 30 msec packet */
+ // int16_t payloadLimitBytes30;
+ /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ // int16_t maxPayloadBytes;
+ int16_t maxPayloadSizeBytes;
+
+ double lastLPCVec[UB_LPC_ORDER];
+ int16_t numBytesUsed;
+ int16_t lastJitterInfo;
+} ISACUBEncStruct;
+
+typedef struct {
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ FFTstr fftstr_obj;
+
+} ISACLBDecStruct;
+
+typedef struct {
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ FFTstr fftstr_obj;
+
+} ISACUBDecStruct;
+
+typedef struct {
+ ISACLBEncStruct ISACencLB_obj;
+ ISACLBDecStruct ISACdecLB_obj;
+} ISACLBStruct;
+
+typedef struct {
+ ISACUBEncStruct ISACencUB_obj;
+ ISACUBDecStruct ISACdecUB_obj;
+} ISACUBStruct;
+
+/*
+ This struct is used to take a snapshot of the entropy coder and LPC gains
+ right before encoding LPC gains. This allows us to go back to that state
+ if we like to limit the payload size.
+*/
+typedef struct {
+ /* 6 lower-band & 6 upper-band */
+ double loFiltGain[SUBFRAMES];
+ double hiFiltGain[SUBFRAMES];
+ /* Upper boundary of interval W */
+ uint32_t W_upper;
+ uint32_t streamval;
+ /* Index to the current position in bytestream */
+ uint32_t stream_index;
+ 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
+ ISACLBStruct instLB;
+ // upper-band codec instance
+ ISACUBStruct instUB;
+
+ // Bandwidth Estimator and model for the rate.
+ BwEstimatorstr bwestimator_obj;
+ RateModel rate_data_obj;
+ double MaxDelay;
+
+ /* 0 = adaptive; 1 = instantaneous */
+ int16_t codingMode;
+
+ // overall bottleneck of the codec
+ int32_t bottleneck;
+
+ // QMF Filter state
+ int32_t analysisFBState1[FB_STATE_SIZE_WORD32];
+ int32_t analysisFBState2[FB_STATE_SIZE_WORD32];
+ int32_t synthesisFBState1[FB_STATE_SIZE_WORD32];
+ int32_t synthesisFBState2[FB_STATE_SIZE_WORD32];
+
+ // Error Code
+ int16_t errorCode;
+
+ // bandwidth of the encoded audio 8, 12 or 16 kHz
+ enum ISACBandwidth bandwidthKHz;
+ // Sampling rate of audio, encoder and decode, 8 or 16 kHz
+ enum IsacSamplingRate encoderSamplingRateKHz;
+ enum IsacSamplingRate decoderSamplingRateKHz;
+ // Flag to keep track of initializations, lower & upper-band
+ // encoder and decoder.
+ int16_t initFlag;
+
+ // Flag to to indicate signal bandwidth switch
+ int16_t resetFlag_8kHz;
+
+ // Maximum allowed rate, measured in Bytes per 30 ms.
+ int16_t maxRateBytesPer30Ms;
+ // Maximum allowed payload-size, measured in Bytes.
+ int16_t maxPayloadSizeBytes;
+ /* The expected sampling rate of the input signal. Valid values are 16000
+ * and 32000. This is not the operation sampling rate of the codec. */
+ uint16_t in_sample_rate_hz;
+
+ // Trig tables for WebRtcIsac_Time2Spec and WebRtcIsac_Spec2time.
+ TransformTables transform_tables;
+} ISACMainStruct;
+
+#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/transform.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/transform.c
new file mode 100644
index 0000000000..082ad941c4
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/source/transform.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+
+#include "modules/audio_coding/codecs/isac/main/source/settings.h"
+#include "modules/audio_coding/codecs/isac/main/source/codec.h"
+#include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+#include "modules/third_party/fft/fft.h"
+
+void WebRtcIsac_InitTransform(TransformTables* tables) {
+ int k;
+ double fact, phase;
+
+ fact = PI / (FRAMESAMPLES_HALF);
+ phase = 0.0;
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ 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++) {
+ tables->costab2[k] = cos(phase);
+ tables->sintab2[k] = sin(phase);
+ phase += fact;
+ }
+}
+
+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;
+ double tmpre[FRAMESAMPLES_HALF], tmpim[FRAMESAMPLES_HALF];
+
+
+ dims[0] = FRAMESAMPLES_HALF;
+
+
+ /* Multiply with complex exponentials and combine into one complex vector */
+ fact = 0.5 / sqrt(FRAMESAMPLES_HALF);
+ for (k = 0; k < FRAMESAMPLES_HALF; 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;
+ }
+
+
+ /* Get DFT */
+ WebRtcIsac_Fftns(1, dims, tmpre, tmpim, -1, 1.0, fftstr_obj);
+
+ /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ xr = tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+ yi = -tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+ xi = tmpim[k] - tmpim[FRAMESAMPLES_HALF - 1 - k];
+ yr = tmpim[k] + tmpim[FRAMESAMPLES_HALF - 1 - 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);
+ outimQ7[FRAMESAMPLES_HALF - 1 - k] = (int16_t)WebRtcIsac_lrint((-yr * tmp1r + yi * tmp1i) * 128.0);
+ }
+}
+
+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;
+
+ int dims;
+
+ dims = FRAMESAMPLES_HALF;
+
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ /* Move zero in time to beginning of frames */
+ 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;
+ yi = -inre[FRAMESAMPLES_HALF - 1 - k] * tmp1r + inim[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+
+ /* Combine into one vector, z = x + j * y */
+ outre1[k] = xr - yi;
+ outre1[FRAMESAMPLES_HALF - 1 - k] = xr + yi;
+ outre2[k] = xi + yr;
+ outre2[FRAMESAMPLES_HALF - 1 - k] = -xi + yr;
+ }
+
+
+ /* Get IDFT */
+ WebRtcIsac_Fftns(1, &dims, outre1, outre2, 1, FRAMESAMPLES_HALF, fftstr_obj);
+
+
+ /* Demodulate and separate */
+ fact = sqrt(FRAMESAMPLES_HALF);
+ for (k = 0; k < FRAMESAMPLES_HALF; 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;
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc
new file mode 100644
index 0000000000..ee72b07dc3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/ReleaseTest-API/ReleaseTest-API.cc
@@ -0,0 +1,942 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// ReleaseTest-API.cpp : Defines the entry point for the console application.
+//
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <iostream>
+
+/* include API */
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+/* Defines */
+#define SEED_FILE \
+ "randseed.txt" /* Used when running decoder on garbage data \
+ */
+#define MAX_FRAMESAMPLES \
+ 960 /* max number of samples per frame \
+ (= 60 ms frame & 16 kHz) or \
+ (= 30 ms frame & 32 kHz) */
+#define FRAMESAMPLES_10ms 160 /* number of samples per 10ms frame */
+#define SWBFRAMESAMPLES_10ms 320
+//#define FS 16000 /* sampling frequency (Hz) */
+
+#ifdef WIN32
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000 /* Runtime statistics */
+#endif
+#endif
+
+int main(int argc, char* argv[]) {
+ char inname[100], outname[100], bottleneck_file[100], vadfile[100];
+ FILE *inp, *outp, *f_bn = NULL, *vadp = NULL, *bandwidthp;
+ int framecnt, endfile;
+
+ size_t i;
+ int errtype, VADusage = 0, packetLossPercent = 0;
+ int16_t CodingMode;
+ int32_t bottleneck = 0;
+ int framesize = 30; /* ms */
+ int cur_framesmpls, err;
+
+ /* Runtime statistics */
+ double starttime, runtime, length_file;
+
+ size_t stream_len = 0;
+ int declen = 0, declenTC = 0;
+ bool lostFrame = false;
+
+ int16_t shortdata[SWBFRAMESAMPLES_10ms];
+ int16_t vaddata[SWBFRAMESAMPLES_10ms * 3];
+ int16_t decoded[MAX_FRAMESAMPLES << 1];
+ int16_t decodedTC[MAX_FRAMESAMPLES << 1];
+ uint16_t streamdata[500];
+ int16_t speechType[1];
+ int16_t rateBPS = 0;
+ int16_t fixedFL = 0;
+ int16_t payloadSize = 0;
+ int32_t payloadRate = 0;
+ int setControlBWE = 0;
+ short FL, testNum;
+ char version_number[20];
+ FILE* plFile;
+ int32_t sendBN;
+
+#if !defined(NDEBUG)
+ FILE* fy;
+ double kbps;
+#endif
+ size_t totalbits = 0;
+ int totalsmpls = 0;
+
+ /* If use GNS file */
+ FILE* fp_gns = NULL;
+ char gns_file[100];
+ size_t maxStreamLen30 = 0;
+ size_t maxStreamLen60 = 0;
+ short sampFreqKHz = 32;
+ short samplesIn10Ms;
+ // FILE logFile;
+ bool doTransCoding = false;
+ int32_t rateTransCoding = 0;
+ uint8_t streamDataTransCoding[1200];
+ size_t streamLenTransCoding = 0;
+ FILE* transCodingFile = NULL;
+ FILE* transcodingBitstream = NULL;
+ size_t numTransCodingBytes = 0;
+
+ /* only one structure used for ISAC encoder */
+ ISACStruct* ISAC_main_inst = NULL;
+ ISACStruct* decoderTransCoding = NULL;
+
+ BottleNeckModel BN_data;
+
+#if !defined(NDEBUG)
+ fy = fopen("bit_rate.dat", "w");
+ fclose(fy);
+ fy = fopen("bytes_frames.dat", "w");
+ fclose(fy);
+#endif
+
+ /* Handling wrong input arguments in the command line */
+ if ((argc < 3) || (argc > 17)) {
+ printf("\n\nWrong number of arguments or flag values.\n\n");
+
+ printf("\n");
+ WebRtcIsac_version(version_number);
+ printf("iSAC-swb version %s \n\n", version_number);
+
+ printf("Usage:\n\n");
+ printf("%s [-I] bottleneck_value infile outfile \n\n", argv[0]);
+ printf("with:\n");
+ printf("[-FS num] : sampling frequency in kHz, valid values are\n");
+ printf(" 16 & 32, with 16 as default.\n");
+ printf("[-I] : if -I option is specified, the coder will use\n");
+ printf(" an instantaneous Bottleneck value. If not, it\n");
+ printf(" will be an adaptive Bottleneck value.\n");
+ printf("[-assign] : Use Assign API.\n");
+ printf("[-B num] : the value of the bottleneck provided either\n");
+ printf(" as a fixed value in bits/sec (e.g. 25000) or\n");
+ printf(" read from a file (e.g. bottleneck.txt)\n");
+ printf("[-INITRATE num] : Set a new value for initial rate. Note! Only\n");
+ printf(" used in adaptive mode.\n");
+ printf("[-FL num] : Set (initial) frame length in msec. Valid\n");
+ printf(" lengths are 30 and 60 msec.\n");
+ printf("[-FIXED_FL] : Frame length will be fixed to initial value.\n");
+ printf("[-MAX num] : Set the limit for the payload size of iSAC\n");
+ printf(" in bytes. Minimum 100 maximum 400.\n");
+ printf("[-MAXRATE num] : Set the maxrate for iSAC in bits per second.\n");
+ printf(" Minimum 32000, maximum 53400.\n");
+ printf("[-F num] : if -F option is specified, the test function\n");
+ printf(" will run the iSAC API fault scenario\n");
+ printf(" specified by the supplied number.\n");
+ printf(" F 1 - Call encoder prior to init encoder call\n");
+ printf(" F 2 - Call decoder prior to init decoder call\n");
+ printf(" F 3 - Call decoder prior to encoder call\n");
+ printf(" F 4 - Call decoder with a too short coded\n");
+ printf(" sequence\n");
+ printf(" F 5 - Call decoder with a too long coded\n");
+ printf(" sequence\n");
+ printf(" F 6 - Call decoder with random bit stream\n");
+ printf(" F 7 - Call init encoder/decoder at random\n");
+ printf(" during a call\n");
+ printf(" F 8 - Call encoder/decoder without having\n");
+ printf(" allocated memory for encoder/decoder\n");
+ printf(" instance\n");
+ printf(" F 9 - Call decodeB without calling decodeA\n");
+ printf(" F 10 - Call decodeB with garbage data\n");
+ printf("[-PL num] : if -PL option is specified \n");
+ printf("[-T rate file] : test trans-coding with target bottleneck\n");
+ printf(" 'rate' bits/sec\n");
+ printf(" the output file is written to 'file'\n");
+ printf("[-LOOP num] : number of times to repeat coding the input\n");
+ printf(" file for stress testing\n");
+ // printf("[-CE num] : Test of APIs used by Conference Engine.\n");
+ // printf(" CE 1 - getNewBitstream, getBWE \n");
+ // printf(" (CE 2 - RESERVED for transcoding)\n");
+ // printf(" CE 3 - getSendBWE, setSendBWE. \n");
+ // printf("-L filename : write the logging info into file
+ // (appending)\n");
+ printf("infile : Normal speech input file\n");
+ printf("outfile : Speech output file\n");
+ exit(0);
+ }
+
+ /* Print version number */
+ printf("-------------------------------------------------\n");
+ WebRtcIsac_version(version_number);
+ printf("iSAC version %s \n\n", version_number);
+
+ /* Loop over all command line arguments */
+ CodingMode = 0;
+ testNum = 0;
+ // logFile = NULL;
+ char transCodingFileName[500];
+ int16_t totFileLoop = 0;
+ int16_t numFileLoop = 0;
+ for (i = 1; i + 2 < static_cast<size_t>(argc); i++) {
+ if (!strcmp("-LOOP", argv[i])) {
+ i++;
+ totFileLoop = (int16_t)atol(argv[i]);
+ if (totFileLoop <= 0) {
+ fprintf(stderr, "Invalid number of runs for the given input file, %d.",
+ totFileLoop);
+ exit(0);
+ }
+ }
+
+ if (!strcmp("-T", argv[i])) {
+ doTransCoding = true;
+ i++;
+ rateTransCoding = atoi(argv[i]);
+ i++;
+ strcpy(transCodingFileName, argv[i]);
+ }
+
+ /* Set Sampling Rate */
+ if (!strcmp("-FS", argv[i])) {
+ i++;
+ sampFreqKHz = atoi(argv[i]);
+ }
+
+ /* Instantaneous mode */
+ if (!strcmp("-I", argv[i])) {
+ printf("Instantaneous BottleNeck\n");
+ CodingMode = 1;
+ }
+
+ /* Set (initial) bottleneck value */
+ if (!strcmp("-INITRATE", argv[i])) {
+ rateBPS = atoi(argv[i + 1]);
+ setControlBWE = 1;
+ if ((rateBPS < 10000) || (rateBPS > 32000)) {
+ printf(
+ "\n%d is not a initial rate. Valid values are in the range "
+ "10000 to 32000.\n",
+ rateBPS);
+ exit(0);
+ }
+ printf("New initial rate: %d\n", rateBPS);
+ i++;
+ }
+
+ /* Set (initial) framelength */
+ if (!strcmp("-FL", argv[i])) {
+ framesize = atoi(argv[i + 1]);
+ if ((framesize != 30) && (framesize != 60)) {
+ printf(
+ "\n%d is not a valid frame length. Valid length are 30 and 60 "
+ "msec.\n",
+ framesize);
+ exit(0);
+ }
+ setControlBWE = 1;
+ printf("Frame Length: %d\n", framesize);
+ i++;
+ }
+
+ /* Fixed frame length */
+ if (!strcmp("-FIXED_FL", argv[i])) {
+ fixedFL = 1;
+ setControlBWE = 1;
+ printf("Fixed Frame Length\n");
+ }
+
+ /* Set maximum allowed payload size in bytes */
+ if (!strcmp("-MAX", argv[i])) {
+ payloadSize = atoi(argv[i + 1]);
+ printf("Maximum Payload Size: %d\n", payloadSize);
+ i++;
+ }
+
+ /* Set maximum rate in bytes */
+ if (!strcmp("-MAXRATE", argv[i])) {
+ payloadRate = atoi(argv[i + 1]);
+ printf("Maximum Rate in kbps: %d\n", payloadRate);
+ i++;
+ }
+
+ /* Test of fault scenarious */
+ if (!strcmp("-F", argv[i])) {
+ testNum = atoi(argv[i + 1]);
+ printf("Fault test: %d\n", testNum);
+ if (testNum < 1 || testNum > 10) {
+ printf(
+ "\n%d is not a valid Fault Scenario number. Valid Fault "
+ "Scenarios are numbered 1-10.\n",
+ testNum);
+ exit(0);
+ }
+ i++;
+ }
+
+ /* Packet loss test */
+ if (!strcmp("-PL", argv[i])) {
+ if (isdigit(static_cast<unsigned char>(*argv[i + 1]))) {
+ packetLossPercent = atoi(argv[i + 1]);
+ if ((packetLossPercent < 0) | (packetLossPercent > 100)) {
+ printf("\nInvalid packet loss perentage \n");
+ exit(0);
+ }
+ if (packetLossPercent > 0) {
+ printf("Simulating %d %% of independent packet loss\n",
+ packetLossPercent);
+ } else {
+ printf("\nNo Packet Loss Is Simulated \n");
+ }
+ } else {
+ plFile = fopen(argv[i + 1], "rb");
+ if (plFile == NULL) {
+ printf("\n couldn't open the frameloss file: %s\n", argv[i + 1]);
+ exit(0);
+ }
+ printf("Simulating packet loss through the given channel file: %s\n",
+ argv[i + 1]);
+ }
+ i++;
+ }
+
+ /* Random packetlosses */
+ if (!strcmp("-rnd", argv[i])) {
+ srand((unsigned int)time(NULL));
+ printf("Random pattern in lossed packets \n");
+ }
+
+ /* Use gns file */
+ if (!strcmp("-G", argv[i])) {
+ sscanf(argv[i + 1], "%s", gns_file);
+ fp_gns = fopen(gns_file, "rb");
+ if (fp_gns == NULL) {
+ printf("Cannot read file %s.\n", gns_file);
+ exit(0);
+ }
+ i++;
+ }
+
+ // make it with '-B'
+ /* Get Bottleneck value */
+ if (!strcmp("-B", argv[i])) {
+ i++;
+ bottleneck = atoi(argv[i]);
+ if (bottleneck == 0) {
+ sscanf(argv[i], "%s", bottleneck_file);
+ f_bn = fopen(bottleneck_file, "rb");
+ if (f_bn == NULL) {
+ printf(
+ "Error No value provided for BottleNeck and cannot read file "
+ "%s.\n",
+ bottleneck_file);
+ exit(0);
+ } else {
+ printf("reading bottleneck rates from file %s\n\n", bottleneck_file);
+ if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+ /* Set pointer to beginning of file */
+ fseek(f_bn, 0L, SEEK_SET);
+ if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+ exit(0);
+ }
+ }
+
+ /* Bottleneck is a cosine function
+ * Matlab code for writing the bottleneck file:
+ * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
+ * fid = fopen('bottleneck.txt', 'wb');
+ * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
+ */
+ }
+ } else {
+ printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
+ }
+ }
+ /* Run Conference Engine APIs */
+ // Do not test it in the first release
+ //
+ // if(!strcmp ("-CE", argv[i]))
+ // {
+ // testCE = atoi(argv[i + 1]);
+ // if(testCE==1)
+ // {
+ // i++;
+ // scale = (float)atof( argv[i+1] );
+ // }
+ // else if(testCE == 2)
+ // {
+ // printf("\nCE-test 2 (transcoding) not implemented.\n");
+ // exit(0);
+ // }
+ // else if(testCE < 1 || testCE > 3)
+ // {
+ // printf("\n%d is not a valid CE-test number. Valid CE tests
+ // are 1-3.\n", testCE);
+ // exit(0);
+ // }
+ // printf("CE-test number: %d\n", testCE);
+ // i++;
+ // }
+ }
+
+ if (CodingMode == 0) {
+ printf("\nAdaptive BottleNeck\n");
+ }
+
+ switch (sampFreqKHz) {
+ case 16: {
+ printf("iSAC Wideband.\n");
+ samplesIn10Ms = FRAMESAMPLES_10ms;
+ break;
+ }
+ case 32: {
+ printf("iSAC Supper-Wideband.\n");
+ samplesIn10Ms = SWBFRAMESAMPLES_10ms;
+ break;
+ }
+ default:
+ printf("Unsupported sampling frequency %d kHz", sampFreqKHz);
+ exit(0);
+ }
+
+ /* Get Input and Output files */
+ sscanf(argv[argc - 2], "%s", inname);
+ sscanf(argv[argc - 1], "%s", outname);
+ printf("\nInput file: %s\n", inname);
+ printf("Output file: %s\n\n", outname);
+ if ((inp = fopen(inname, "rb")) == NULL) {
+ printf(" Error iSAC Cannot read file %s.\n", inname);
+ std::cout << std::flush;
+ exit(1);
+ }
+
+ if ((outp = fopen(outname, "wb")) == NULL) {
+ printf(" Error iSAC Cannot write file %s.\n", outname);
+ std::cout << std::flush;
+ getc(stdin);
+ exit(1);
+ }
+ if (VADusage) {
+ if ((vadp = fopen(vadfile, "rb")) == NULL) {
+ printf(" Error iSAC Cannot read file %s.\n", vadfile);
+ std::cout << std::flush;
+ exit(1);
+ }
+ }
+
+ if ((bandwidthp = fopen("bwe.pcm", "wb")) == NULL) {
+ printf(" Error iSAC Cannot read file %s.\n", "bwe.pcm");
+ std::cout << std::flush;
+ exit(1);
+ }
+
+ starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */
+
+ /* Initialize the ISAC and BN structs */
+ if (testNum != 8) {
+ err = WebRtcIsac_Create(&ISAC_main_inst);
+ WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
+ WebRtcIsac_SetDecSampRate(ISAC_main_inst,
+ sampFreqKHz >= 32 ? 32000 : 16000);
+ /* Error check */
+ if (err < 0) {
+ printf("\n\n Error in create.\n\n");
+ std::cout << std::flush;
+ exit(EXIT_FAILURE);
+ }
+ }
+ BN_data.arrival_time = 0;
+ BN_data.sample_count = 0;
+ BN_data.rtp_number = 0;
+
+ /* Initialize encoder and decoder */
+ framecnt = 0;
+ endfile = 0;
+
+ if (doTransCoding) {
+ WebRtcIsac_Create(&decoderTransCoding);
+ WebRtcIsac_SetEncSampRate(decoderTransCoding, sampFreqKHz * 1000);
+ WebRtcIsac_SetDecSampRate(decoderTransCoding,
+ sampFreqKHz >= 32 ? 32000 : 16000);
+ WebRtcIsac_DecoderInit(decoderTransCoding);
+ transCodingFile = fopen(transCodingFileName, "wb");
+ if (transCodingFile == NULL) {
+ printf("Could not open %s to output trans-coding.\n",
+ transCodingFileName);
+ exit(0);
+ }
+ strcat(transCodingFileName, ".bit");
+ transcodingBitstream = fopen(transCodingFileName, "wb");
+ if (transcodingBitstream == NULL) {
+ printf("Could not open %s to write the bit-stream of transcoder.\n",
+ transCodingFileName);
+ exit(0);
+ }
+ }
+
+ if (testNum != 1) {
+ if (WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode) < 0) {
+ printf("Error could not initialize the encoder \n");
+ std::cout << std::flush;
+ return 0;
+ }
+ }
+ if (testNum != 2)
+ WebRtcIsac_DecoderInit(ISAC_main_inst);
+ if (CodingMode == 1) {
+ err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in initialization (control): %d.\n\n", errtype);
+ std::cout << std::flush;
+ if (testNum == 0) {
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ if ((setControlBWE) && (CodingMode == 0)) {
+ err = WebRtcIsac_ControlBwe(ISAC_main_inst, rateBPS, framesize, fixedFL);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+
+ printf("\n\n Error in Control BWE: %d.\n\n", errtype);
+ std::cout << std::flush;
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (payloadSize != 0) {
+ err = WebRtcIsac_SetMaxPayloadSize(ISAC_main_inst, payloadSize);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in SetMaxPayloadSize: %d.\n\n", errtype);
+ std::cout << std::flush;
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (payloadRate != 0) {
+ err = WebRtcIsac_SetMaxRate(ISAC_main_inst, payloadRate);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in SetMaxRateInBytes: %d.\n\n", errtype);
+ std::cout << std::flush;
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ *speechType = 1;
+
+ std::cout << "\n" << std::flush;
+
+ length_file = 0;
+ int16_t bnIdxTC = 0;
+ int16_t jitterInfoTC = 0;
+ while (endfile == 0) {
+ /* Call init functions at random, fault test number 7 */
+ if (testNum == 7 && (rand() % 2 == 0)) {
+ err = WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
+ /* Error check */
+ if (err < 0) {
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ printf("\n\n Error in encoderinit: %d.\n\n", errtype);
+ std::cout << std::flush;
+ }
+
+ WebRtcIsac_DecoderInit(ISAC_main_inst);
+ }
+
+ cur_framesmpls = 0;
+ while (1) {
+ int stream_len_int = 0;
+
+ /* Read 10 ms speech block */
+ endfile = readframe(shortdata, inp, samplesIn10Ms);
+
+ if (endfile) {
+ numFileLoop++;
+ if (numFileLoop < totFileLoop) {
+ rewind(inp);
+ framecnt = 0;
+ fprintf(stderr, "\n");
+ endfile = readframe(shortdata, inp, samplesIn10Ms);
+ }
+ }
+
+ if (testNum == 7) {
+ srand((unsigned int)time(NULL));
+ }
+
+ /* iSAC encoding */
+ if (!(testNum == 3 && framecnt == 0)) {
+ stream_len_int =
+ WebRtcIsac_Encode(ISAC_main_inst, shortdata, (uint8_t*)streamdata);
+ if ((payloadSize != 0) && (stream_len_int > payloadSize)) {
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+
+ printf("\nError: Streamsize out of range %d\n",
+ stream_len_int - payloadSize);
+ std::cout << std::flush;
+ }
+
+ WebRtcIsac_GetUplinkBw(ISAC_main_inst, &sendBN);
+
+ if (stream_len_int > 0) {
+ if (doTransCoding) {
+ int16_t indexStream;
+ uint8_t auxUW8;
+
+ /******************** Main Transcoding stream ********************/
+ WebRtcIsac_GetDownLinkBwIndex(ISAC_main_inst, &bnIdxTC,
+ &jitterInfoTC);
+ int streamLenTransCoding_int = WebRtcIsac_GetNewBitStream(
+ ISAC_main_inst, bnIdxTC, jitterInfoTC, rateTransCoding,
+ streamDataTransCoding, false);
+ if (streamLenTransCoding_int < 0) {
+ fprintf(stderr, "Error in trans-coding\n");
+ exit(0);
+ }
+ streamLenTransCoding =
+ static_cast<size_t>(streamLenTransCoding_int);
+ auxUW8 = (uint8_t)(((streamLenTransCoding & 0xFF00) >> 8) & 0x00FF);
+ if (fwrite(&auxUW8, sizeof(uint8_t), 1, transcodingBitstream) !=
+ 1) {
+ return -1;
+ }
+
+ auxUW8 = (uint8_t)(streamLenTransCoding & 0x00FF);
+ if (fwrite(&auxUW8, sizeof(uint8_t), 1, transcodingBitstream) !=
+ 1) {
+ return -1;
+ }
+
+ if (fwrite(streamDataTransCoding, sizeof(uint8_t),
+ streamLenTransCoding,
+ transcodingBitstream) != streamLenTransCoding) {
+ return -1;
+ }
+
+ WebRtcIsac_ReadBwIndex(streamDataTransCoding, &indexStream);
+ if (indexStream != bnIdxTC) {
+ fprintf(stderr,
+ "Error in inserting Bandwidth index into transcoding "
+ "stream.\n");
+ exit(0);
+ }
+ numTransCodingBytes += streamLenTransCoding;
+ }
+ }
+ } else {
+ break;
+ }
+
+ if (stream_len_int < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ fprintf(stderr, "Error in encoder: %d.\n", errtype);
+ std::cout << std::flush;
+ exit(0);
+ }
+ stream_len = static_cast<size_t>(stream_len_int);
+
+ cur_framesmpls += samplesIn10Ms;
+ /* exit encoder loop if the encoder returned a bitstream */
+ if (stream_len != 0)
+ break;
+ }
+
+ /* read next bottleneck rate */
+ if (f_bn != NULL) {
+ if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+ /* Set pointer to beginning of file */
+ fseek(f_bn, 0L, SEEK_SET);
+ if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
+ exit(0);
+ }
+ }
+ if (CodingMode == 1) {
+ WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
+ }
+ }
+
+ length_file += cur_framesmpls;
+ if (cur_framesmpls == (3 * samplesIn10Ms)) {
+ maxStreamLen30 =
+ (stream_len > maxStreamLen30) ? stream_len : maxStreamLen30;
+ } else {
+ maxStreamLen60 =
+ (stream_len > maxStreamLen60) ? stream_len : maxStreamLen60;
+ }
+
+ if (!lostFrame) {
+ lostFrame = ((rand() % 100) < packetLossPercent);
+ } else {
+ lostFrame = false;
+ }
+
+ // RED.
+ if (lostFrame) {
+ int stream_len_int = WebRtcIsac_GetRedPayload(
+ ISAC_main_inst, reinterpret_cast<uint8_t*>(streamdata));
+ if (stream_len_int < 0) {
+ fprintf(stderr, "Error getting RED payload\n");
+ exit(0);
+ }
+ stream_len = static_cast<size_t>(stream_len_int);
+
+ if (doTransCoding) {
+ int streamLenTransCoding_int = WebRtcIsac_GetNewBitStream(
+ ISAC_main_inst, bnIdxTC, jitterInfoTC, rateTransCoding,
+ streamDataTransCoding, true);
+ if (streamLenTransCoding_int < 0) {
+ fprintf(stderr, "Error in RED trans-coding\n");
+ exit(0);
+ }
+ streamLenTransCoding = static_cast<size_t>(streamLenTransCoding_int);
+ }
+ }
+
+ /* make coded sequence to short be inreasing */
+ /* the length the decoder expects */
+ if (testNum == 4) {
+ stream_len += 10;
+ }
+
+ /* make coded sequence to long be decreasing */
+ /* the length the decoder expects */
+ if (testNum == 5) {
+ stream_len -= 10;
+ }
+
+ if (testNum == 6) {
+ srand((unsigned int)time(NULL));
+ for (i = 0; i < stream_len; i++) {
+ streamdata[i] = rand();
+ }
+ }
+
+ if (VADusage) {
+ readframe(vaddata, vadp, samplesIn10Ms * 3);
+ }
+
+ /* simulate packet handling through NetEq and the modem */
+ if (!(testNum == 3 && framecnt == 0)) {
+ get_arrival_time(cur_framesmpls, stream_len, bottleneck, &BN_data,
+ sampFreqKHz * 1000, sampFreqKHz * 1000);
+ }
+
+ if (VADusage && (framecnt > 10 && vaddata[0] == 0)) {
+ BN_data.rtp_number--;
+ } else {
+ /* Error test number 10, garbage data */
+ if (testNum == 10) {
+ /* Test to run decoder with garbage data */
+ for (i = 0; i < stream_len; i++) {
+ streamdata[i] = (short)(streamdata[i]) + (short)rand();
+ }
+ }
+
+ if (testNum != 9) {
+ err = WebRtcIsac_UpdateBwEstimate(
+ ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata),
+ stream_len, BN_data.rtp_number, BN_data.sample_count,
+ BN_data.arrival_time);
+
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+
+ printf("Error: in decoder: %d.", errtype);
+ std::cout << std::flush;
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ }
+ }
+
+ /* Call getFramelen, only used here for function test */
+ err = WebRtcIsac_ReadFrameLen(
+ ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata), &FL);
+ if (err < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ printf(" Error: in getFrameLen %d.", errtype);
+ std::cout << std::flush;
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ }
+
+ // iSAC decoding
+
+ if (lostFrame) {
+ declen = WebRtcIsac_DecodeRcu(
+ ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata),
+ stream_len, decoded, speechType);
+
+ if (doTransCoding) {
+ declenTC =
+ WebRtcIsac_DecodeRcu(decoderTransCoding, streamDataTransCoding,
+ streamLenTransCoding, decodedTC, speechType);
+ }
+ } else {
+ declen = WebRtcIsac_Decode(ISAC_main_inst,
+ reinterpret_cast<const uint8_t*>(streamdata),
+ stream_len, decoded, speechType);
+ if (doTransCoding) {
+ declenTC =
+ WebRtcIsac_Decode(decoderTransCoding, streamDataTransCoding,
+ streamLenTransCoding, decodedTC, speechType);
+ }
+ }
+
+ if (declen < 0) {
+ /* exit if returned with error */
+ errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ printf(" Error: in decoder %d.", errtype);
+ std::cout << std::flush;
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ }
+
+ if (declenTC < 0) {
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ printf(" Error: in decoding the transcoded stream");
+ std::cout << std::flush;
+ if (testNum == 0) {
+ printf("\n\n");
+ }
+ }
+ }
+ /* Write decoded speech frame to file */
+ if ((declen > 0) && (numFileLoop == 0)) {
+ if (fwrite(decoded, sizeof(int16_t), declen, outp) !=
+ static_cast<size_t>(declen)) {
+ return -1;
+ }
+ }
+
+ if ((declenTC > 0) && (numFileLoop == 0)) {
+ if (fwrite(decodedTC, sizeof(int16_t), declen, transCodingFile) !=
+ static_cast<size_t>(declen)) {
+ return -1;
+ }
+ }
+
+ fprintf(stderr, "\rframe = %5d ", framecnt);
+ fflush(stderr);
+ framecnt++;
+
+ /* Error test number 10, garbage data */
+ // if (testNum == 10)
+ // {
+ // /* Test to run decoder with garbage data */
+ // if ((seedfile = fopen(SEED_FILE, "a+t")) == NULL) {
+ // fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
+ // } else {
+ // fprintf(seedfile, "ok\n\n");
+ // fclose(seedfile);
+ // }
+ // }
+ /* Error test number 10, garbage data */
+ // if (testNum == 10) {
+ // /* Test to run decoder with garbage data */
+ // for (i = 0; i < stream_len; i++) {
+ // streamdata[i] = (short) (streamdata[i] + (short) rand());
+ // }
+ // }
+
+ totalsmpls += declen;
+ totalbits += 8 * stream_len;
+#if !defined(NDEBUG)
+ kbps = ((double)sampFreqKHz * 1000.) / ((double)cur_framesmpls) * 8.0 *
+ stream_len / 1000.0; // kbits/s
+ fy = fopen("bit_rate.dat", "a");
+ fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
+ fclose(fy);
+
+#endif
+ }
+ printf("\n");
+ printf("total bits = %zu bits\n", totalbits);
+ printf("measured average bitrate = %0.3f kbits/s\n",
+ (double)totalbits * (sampFreqKHz) / totalsmpls);
+ if (doTransCoding) {
+ printf("Transcoding average bit-rate = %0.3f kbps\n",
+ (double)numTransCodingBytes * 8.0 * (sampFreqKHz) / totalsmpls);
+ fclose(transCodingFile);
+ }
+ printf("\n");
+
+ /* Runtime statistics */
+ runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
+ length_file = length_file / (sampFreqKHz * 1000.);
+
+ printf("\n\nLength of speech file: %.1f s\n", length_file);
+ printf("Time to run iSAC: %.2f s (%.2f %% of realtime)\n\n", runtime,
+ (100 * runtime / length_file));
+
+ if (maxStreamLen30 != 0) {
+ printf(
+ "Maximum payload size 30ms Frames %zu"
+ " bytes (%0.3f kbps)\n",
+ maxStreamLen30, maxStreamLen30 * 8 / 30.);
+ }
+ if (maxStreamLen60 != 0) {
+ printf(
+ "Maximum payload size 60ms Frames %zu"
+ " bytes (%0.3f kbps)\n",
+ maxStreamLen60, maxStreamLen60 * 8 / 60.);
+ }
+ // fprintf(stderr, "\n");
+
+ fprintf(stderr, " %.1f s", length_file);
+ fprintf(stderr, " %0.1f kbps",
+ (double)totalbits * (sampFreqKHz) / totalsmpls);
+ if (maxStreamLen30 != 0) {
+ fprintf(stderr, " plmax-30ms %zu bytes (%0.0f kbps)", maxStreamLen30,
+ maxStreamLen30 * 8 / 30.);
+ }
+ if (maxStreamLen60 != 0) {
+ fprintf(stderr, " plmax-60ms %zu bytes (%0.0f kbps)", maxStreamLen60,
+ maxStreamLen60 * 8 / 60.);
+ }
+ if (doTransCoding) {
+ fprintf(stderr, " transcoding rate %.0f kbps",
+ (double)numTransCodingBytes * 8.0 * (sampFreqKHz) / totalsmpls);
+ }
+
+ fclose(inp);
+ fclose(outp);
+ WebRtcIsac_Free(ISAC_main_inst);
+
+ exit(0);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc
new file mode 100644
index 0000000000..549163fc44
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/SwitchingSampRate/SwitchingSampRate.cc
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// SwitchingSampRate.cpp : Defines the entry point for the console
+// application.
+//
+
+#include <iostream>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+#define MAX_FILE_NAME 500
+#define MAX_NUM_CLIENTS 2
+
+#define NUM_CLIENTS 2
+
+int main(int argc, char* argv[]) {
+ char fileNameWB[MAX_FILE_NAME];
+ char fileNameSWB[MAX_FILE_NAME];
+
+ char outFileName[MAX_NUM_CLIENTS][MAX_FILE_NAME];
+
+ FILE* inFile[MAX_NUM_CLIENTS];
+ FILE* outFile[MAX_NUM_CLIENTS];
+
+ ISACStruct* codecInstance[MAX_NUM_CLIENTS];
+ int32_t resamplerState[MAX_NUM_CLIENTS][8];
+
+ int encoderSampRate[MAX_NUM_CLIENTS];
+
+ int minBn = 16000;
+ int maxBn = 56000;
+
+ int bnWB = 32000;
+ int bnSWB = 56000;
+
+ strcpy(outFileName[0], "switchSampRate_out1.pcm");
+ strcpy(outFileName[1], "switchSampRate_out2.pcm");
+
+ short clientCntr;
+
+ size_t lenEncodedInBytes[MAX_NUM_CLIENTS];
+ unsigned int lenAudioIn10ms[MAX_NUM_CLIENTS];
+ size_t lenEncodedInBytesTmp[MAX_NUM_CLIENTS];
+ unsigned int lenAudioIn10msTmp[MAX_NUM_CLIENTS];
+ BottleNeckModel* packetData[MAX_NUM_CLIENTS];
+
+ char versionNumber[100];
+ short samplesIn10ms[MAX_NUM_CLIENTS];
+ int bottleneck[MAX_NUM_CLIENTS];
+
+ printf("\n\n");
+ printf("____________________________________________\n\n");
+ WebRtcIsac_version(versionNumber);
+ printf(" iSAC-swb version %s\n", versionNumber);
+ printf("____________________________________________\n");
+
+ fileNameWB[0] = '\0';
+ fileNameSWB[0] = '\0';
+
+ char myFlag[20];
+ strcpy(myFlag, "-wb");
+ // READ THE WIDEBAND AND SUPER-WIDEBAND FILE NAMES
+ if (readParamString(argc, argv, myFlag, fileNameWB, MAX_FILE_NAME) <= 0) {
+ printf("No wideband file is specified");
+ }
+
+ strcpy(myFlag, "-swb");
+ if (readParamString(argc, argv, myFlag, fileNameSWB, MAX_FILE_NAME) <= 0) {
+ printf("No super-wideband file is specified");
+ }
+
+ // THE FIRST CLIENT STARTS IN WIDEBAND
+ encoderSampRate[0] = 16000;
+ OPEN_FILE_RB(inFile[0], fileNameWB);
+
+ // THE SECOND CLIENT STARTS IN SUPER-WIDEBAND
+ encoderSampRate[1] = 32000;
+ OPEN_FILE_RB(inFile[1], fileNameSWB);
+
+ strcpy(myFlag, "-I");
+ short codingMode = readSwitch(argc, argv, myFlag);
+
+ for (clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) {
+ codecInstance[clientCntr] = NULL;
+
+ printf("\n");
+ printf("Client %d\n", clientCntr + 1);
+ printf("---------\n");
+ printf("Starting %s", (encoderSampRate[clientCntr] == 16000)
+ ? "wideband"
+ : "super-wideband");
+
+ // Open output File Name
+ OPEN_FILE_WB(outFile[clientCntr], outFileName[clientCntr]);
+ printf("Output File...................... %s\n", outFileName[clientCntr]);
+
+ samplesIn10ms[clientCntr] = encoderSampRate[clientCntr] * 10;
+
+ if (codingMode == 1) {
+ bottleneck[clientCntr] = (clientCntr) ? bnSWB : bnWB;
+ } else {
+ bottleneck[clientCntr] = (clientCntr) ? minBn : maxBn;
+ }
+
+ printf("Bottleneck....................... %0.3f kbits/sec \n",
+ bottleneck[clientCntr] / 1000.0);
+
+ // coding-mode
+ printf(
+ "Encoding Mode.................... %s\n",
+ (codingMode == 1) ? "Channel-Independent (Instantaneous)" : "Adaptive");
+
+ lenEncodedInBytes[clientCntr] = 0;
+ lenAudioIn10ms[clientCntr] = 0;
+ lenEncodedInBytesTmp[clientCntr] = 0;
+ lenAudioIn10msTmp[clientCntr] = 0;
+
+ packetData[clientCntr] = (BottleNeckModel*)new (BottleNeckModel);
+ if (packetData[clientCntr] == NULL) {
+ printf("Could not allocate memory for packetData \n");
+ return -1;
+ }
+ memset(packetData[clientCntr], 0, sizeof(BottleNeckModel));
+ memset(resamplerState[clientCntr], 0, sizeof(int32_t) * 8);
+ }
+
+ for (clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) {
+ // Create
+ if (WebRtcIsac_Create(&codecInstance[clientCntr])) {
+ printf("Could not creat client %d\n", clientCntr + 1);
+ return -1;
+ }
+
+ WebRtcIsac_SetEncSampRate(codecInstance[clientCntr],
+ encoderSampRate[clientCntr]);
+
+ WebRtcIsac_SetDecSampRate(
+ codecInstance[clientCntr],
+ encoderSampRate[clientCntr + (1 - ((clientCntr & 1) << 1))]);
+
+ // Initialize Encoder
+ if (WebRtcIsac_EncoderInit(codecInstance[clientCntr], codingMode) < 0) {
+ printf("Could not initialize client, %d\n", clientCntr + 1);
+ return -1;
+ }
+
+ WebRtcIsac_DecoderInit(codecInstance[clientCntr]);
+
+ // setup Rate if in Instantaneous mode
+ if (codingMode != 0) {
+ // ONLY Clients who are not in Adaptive mode
+ if (WebRtcIsac_Control(codecInstance[clientCntr], bottleneck[clientCntr],
+ 30) < 0) {
+ printf("Could not setup bottleneck and frame-size for client %d\n",
+ clientCntr + 1);
+ return -1;
+ }
+ }
+ }
+
+ size_t streamLen;
+ short numSamplesRead;
+ size_t lenDecodedAudio;
+ short senderIdx;
+ short receiverIdx;
+
+ printf("\n");
+ short num10ms[MAX_NUM_CLIENTS];
+ memset(num10ms, 0, sizeof(short) * MAX_NUM_CLIENTS);
+ FILE* arrivalTimeFile1 = fopen("arrivalTime1.dat", "wb");
+ FILE* arrivalTimeFile2 = fopen("arrivalTime2.dat", "wb");
+ short numPrint[MAX_NUM_CLIENTS];
+ memset(numPrint, 0, sizeof(short) * MAX_NUM_CLIENTS);
+
+ // Audio Buffers
+ short silence10ms[10 * 32];
+ memset(silence10ms, 0, 320 * sizeof(short));
+ short audioBuff10ms[10 * 32];
+ short audioBuff60ms[60 * 32];
+ short resampledAudio60ms[60 * 32];
+
+ unsigned short bitStream[600 + 600];
+ short speechType[1];
+
+ short numSampFreqChanged = 0;
+ while (numSampFreqChanged < 10) {
+ for (clientCntr = 0; clientCntr < NUM_CLIENTS; clientCntr++) {
+ // Encoding/decoding for this pair of clients, if there is
+ // audio for any of them
+ // if(audioLeft[clientCntr] || audioLeft[clientCntr + 1])
+ //{
+ // for(pairCntr = 0; pairCntr < 2; pairCntr++)
+ //{
+ senderIdx = clientCntr; // + pairCntr;
+ receiverIdx = 1 - clientCntr; // + (1 - pairCntr);
+
+ // if(num10ms[senderIdx] > 6)
+ //{
+ // printf("Too many frames read for client %d",
+ // senderIdx + 1);
+ // return -1;
+ //}
+
+ numSamplesRead =
+ (short)fread(audioBuff10ms, sizeof(short), samplesIn10ms[senderIdx],
+ inFile[senderIdx]);
+ if (numSamplesRead != samplesIn10ms[senderIdx]) {
+ // file finished switch encoder sampling frequency.
+ printf("Changing Encoder Sampling frequency in client %d to ",
+ senderIdx + 1);
+ fclose(inFile[senderIdx]);
+ numSampFreqChanged++;
+ if (encoderSampRate[senderIdx] == 16000) {
+ printf("super-wideband.\n");
+ OPEN_FILE_RB(inFile[senderIdx], fileNameSWB);
+ encoderSampRate[senderIdx] = 32000;
+ } else {
+ printf("wideband.\n");
+ OPEN_FILE_RB(inFile[senderIdx], fileNameWB);
+ encoderSampRate[senderIdx] = 16000;
+ }
+ WebRtcIsac_SetEncSampRate(codecInstance[senderIdx],
+ encoderSampRate[senderIdx]);
+ WebRtcIsac_SetDecSampRate(codecInstance[receiverIdx],
+ encoderSampRate[senderIdx]);
+
+ samplesIn10ms[clientCntr] = encoderSampRate[clientCntr] * 10;
+
+ numSamplesRead =
+ (short)fread(audioBuff10ms, sizeof(short), samplesIn10ms[senderIdx],
+ inFile[senderIdx]);
+ if (numSamplesRead != samplesIn10ms[senderIdx]) {
+ printf(" File %s for client %d has not enough audio\n",
+ (encoderSampRate[senderIdx] == 16000) ? "wideband"
+ : "super-wideband",
+ senderIdx + 1);
+ return -1;
+ }
+ }
+ num10ms[senderIdx]++;
+
+ // sanity check
+ // if(num10ms[senderIdx] > 6)
+ //{
+ // printf("Client %d has got more than 60 ms audio and encoded no
+ // packet.\n",
+ // senderIdx);
+ // return -1;
+ //}
+
+ // Encode
+
+ int streamLen_int = WebRtcIsac_Encode(codecInstance[senderIdx],
+ audioBuff10ms, (uint8_t*)bitStream);
+ int16_t ggg;
+ if (streamLen_int > 0) {
+ if ((WebRtcIsac_ReadFrameLen(
+ codecInstance[receiverIdx],
+ reinterpret_cast<const uint8_t*>(bitStream), &ggg)) < 0)
+ printf("ERROR\n");
+ }
+
+ // Sanity check
+ if (streamLen_int < 0) {
+ printf(" Encoder error in client %d \n", senderIdx + 1);
+ return -1;
+ }
+ streamLen = static_cast<size_t>(streamLen_int);
+
+ if (streamLen > 0) {
+ // Packet generated; model sending through a channel, do bandwidth
+ // estimation at the receiver and decode.
+ lenEncodedInBytes[senderIdx] += streamLen;
+ lenAudioIn10ms[senderIdx] += (unsigned int)num10ms[senderIdx];
+ lenEncodedInBytesTmp[senderIdx] += streamLen;
+ lenAudioIn10msTmp[senderIdx] += (unsigned int)num10ms[senderIdx];
+
+ // Print after ~5 sec.
+ if (lenAudioIn10msTmp[senderIdx] >= 100) {
+ numPrint[senderIdx]++;
+ printf(" %d, %6.3f => %6.3f ", senderIdx + 1,
+ bottleneck[senderIdx] / 1000.0,
+ lenEncodedInBytesTmp[senderIdx] * 0.8 /
+ lenAudioIn10msTmp[senderIdx]);
+
+ if (codingMode == 0) {
+ int32_t bn;
+ WebRtcIsac_GetUplinkBw(codecInstance[senderIdx], &bn);
+ printf("[%d] ", bn);
+ }
+ // int16_t rateIndexLB;
+ // int16_t rateIndexUB;
+ // WebRtcIsac_GetDownLinkBwIndex(codecInstance[receiverIdx],
+ // &rateIndexLB, &rateIndexUB);
+ // printf(" (%2d, %2d) ", rateIndexLB, rateIndexUB);
+
+ std::cout << std::flush;
+ lenEncodedInBytesTmp[senderIdx] = 0;
+ lenAudioIn10msTmp[senderIdx] = 0;
+ // if(senderIdx == (NUM_CLIENTS - 1))
+ //{
+ printf(" %0.1f \n", lenAudioIn10ms[senderIdx] * 10. / 1000);
+ //}
+
+ // After ~20 sec change the bottleneck.
+ // if((numPrint[senderIdx] == 4) && (codingMode == 0))
+ // {
+ // numPrint[senderIdx] = 0;
+ // if(codingMode == 0)
+ // {
+ // int newBottleneck = bottleneck[senderIdx] +
+ // (bottleneckChange[senderIdx] * 1000);
+
+ // if(bottleneckChange[senderIdx] > 0)
+ // {
+ // if(newBottleneck >maxBn)
+ // {
+ // bottleneckChange[senderIdx] = -1;
+ // newBottleneck = bottleneck[senderIdx] +
+ // (bottleneckChange[senderIdx] * 1000);
+ // if(newBottleneck > minBn)
+ // {
+ // bottleneck[senderIdx] = newBottleneck;
+ // }
+ // }
+ // else
+ // {
+ // bottleneck[senderIdx] = newBottleneck;
+ // }
+ // }
+ // else
+ // {
+ // if(newBottleneck < minBn)
+ // {
+ // bottleneckChange[senderIdx] = 1;
+ // newBottleneck = bottleneck[senderIdx] +
+ // (bottleneckChange[senderIdx] * 1000);
+ // if(newBottleneck < maxBn)
+ // {
+ // bottleneck[senderIdx] = newBottleneck;
+ // }
+ // }
+ // else
+ // {
+ // bottleneck[senderIdx] = newBottleneck;
+ // }
+ // }
+ // }
+ // }
+ }
+
+ // model a channel of given bottleneck, to get the receive timestamp
+ get_arrival_time(num10ms[senderIdx] * samplesIn10ms[senderIdx],
+ streamLen, bottleneck[senderIdx],
+ packetData[senderIdx],
+ encoderSampRate[senderIdx] * 1000,
+ encoderSampRate[senderIdx] * 1000);
+
+ // Write the arrival time.
+ if (senderIdx == 0) {
+ if (fwrite(&(packetData[senderIdx]->arrival_time),
+ sizeof(unsigned int), 1, arrivalTimeFile1) != 1) {
+ return -1;
+ }
+ } else {
+ if (fwrite(&(packetData[senderIdx]->arrival_time),
+ sizeof(unsigned int), 1, arrivalTimeFile2) != 1) {
+ return -1;
+ }
+ }
+
+ // BWE
+ if (WebRtcIsac_UpdateBwEstimate(
+ codecInstance[receiverIdx],
+ reinterpret_cast<const uint8_t*>(bitStream), streamLen,
+ packetData[senderIdx]->rtp_number,
+ packetData[senderIdx]->sample_count,
+ packetData[senderIdx]->arrival_time) < 0) {
+ printf(" BWE Error at client %d \n", receiverIdx + 1);
+ return -1;
+ }
+ /**/
+ // Decode
+ int lenDecodedAudio_int =
+ WebRtcIsac_Decode(codecInstance[receiverIdx],
+ reinterpret_cast<const uint8_t*>(bitStream),
+ streamLen, audioBuff60ms, speechType);
+ if (lenDecodedAudio_int < 0) {
+ printf(" Decoder error in client %d \n", receiverIdx + 1);
+ return -1;
+ }
+ lenDecodedAudio = static_cast<size_t>(lenDecodedAudio_int);
+
+ if (encoderSampRate[senderIdx] == 16000) {
+ WebRtcSpl_UpsampleBy2(audioBuff60ms, lenDecodedAudio,
+ resampledAudio60ms,
+ resamplerState[receiverIdx]);
+ if (fwrite(resampledAudio60ms, sizeof(short), lenDecodedAudio << 1,
+ outFile[receiverIdx]) != lenDecodedAudio << 1) {
+ return -1;
+ }
+ } else {
+ if (fwrite(audioBuff60ms, sizeof(short), lenDecodedAudio,
+ outFile[receiverIdx]) != lenDecodedAudio) {
+ return -1;
+ }
+ }
+ num10ms[senderIdx] = 0;
+ }
+ //}
+ //}
+ }
+ }
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/simpleKenny.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/simpleKenny.c
new file mode 100644
index 0000000000..4446ff7806
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/test/simpleKenny.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* kenny.c - Main function for the iSAC coder */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef WIN32
+#include "windows.h"
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000
+#endif
+#endif
+
+#include <math.h>
+
+/* include API */
+#include "modules/audio_coding/codecs/isac/main/include/isac.h"
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES_SWB 1920
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_SWB_10ms 320
+#define FRAMESAMPLES_WB_10ms 160
+
+/* sampling frequency (Hz) */
+#define FS_SWB 32000
+#define FS_WB 16000
+
+unsigned long framecnt = 0;
+
+int main(int argc, char* argv[]) {
+ //--- File IO ----
+ FILE* inp;
+ FILE* outp;
+ char inname[500];
+ char outname[500];
+
+ /* Runtime statistics */
+ double rate;
+ double rateRCU;
+ size_t totalbits = 0;
+ unsigned long totalBitsRCU = 0;
+ unsigned long totalsmpls = 0;
+
+ int32_t bottleneck = 39;
+ int frameSize = 30; /* ms */
+ int16_t codingMode = 1;
+ int16_t shortdata[FRAMESAMPLES_SWB_10ms];
+ int16_t decoded[MAX_FRAMESAMPLES_SWB];
+ int16_t speechType[1];
+ int16_t payloadLimit;
+ int32_t rateLimit;
+ ISACStruct* ISAC_main_inst;
+
+ size_t stream_len = 0;
+ int declen = 0;
+ int16_t err;
+ int cur_framesmpls;
+ int endfile;
+#ifdef WIN32
+ double length_file;
+ double runtime;
+ char outDrive[10];
+ char outPath[500];
+ char outPrefix[500];
+ char outSuffix[500];
+ char bitrateFileName[500];
+ FILE* bitrateFile;
+ double starttime;
+ double rateLB = 0;
+ double rateUB = 0;
+#endif
+ FILE* histFile;
+ FILE* averageFile;
+ int sampFreqKHz;
+ int samplesIn10Ms;
+ size_t maxStreamLen = 0;
+ char histFileName[500];
+ char averageFileName[500];
+ unsigned int hist[600];
+ double tmpSumStreamLen = 0;
+ unsigned int packetCntr = 0;
+ unsigned int lostPacketCntr = 0;
+ uint8_t payload[1200];
+ uint8_t payloadRCU[1200];
+ uint16_t packetLossPercent = 0;
+ int16_t rcuStreamLen = 0;
+ int onlyEncode;
+ int onlyDecode;
+
+ BottleNeckModel packetData;
+ packetData.arrival_time = 0;
+ packetData.sample_count = 0;
+ packetData.rtp_number = 0;
+ memset(hist, 0, sizeof(hist));
+
+ /* handling wrong input arguments in the command line */
+ if (argc < 5) {
+ printf("\n\nWrong number of arguments or flag values.\n\n");
+
+ printf("Usage:\n\n");
+ printf("%s infile outfile -bn bottleneck [options]\n\n", argv[0]);
+ printf("with:\n");
+ printf("-I.............. indicates encoding in instantaneous mode.\n");
+ printf("-bn bottleneck.. the value of the bottleneck in bit/sec, e.g.\n");
+ printf(" 39742, in instantaneous (channel-independent)\n");
+ printf(" mode.\n\n");
+ printf("infile.......... Normal speech input file\n\n");
+ printf("outfile......... Speech output file\n\n");
+ printf("OPTIONS\n");
+ printf("-------\n");
+ printf("-fs sampFreq.... sampling frequency of codec 16 or 32 (default)\n");
+ printf(" kHz.\n");
+ printf("-plim payloadLim payload limit in bytes, default is the maximum\n");
+ printf(" possible.\n");
+ printf("-rlim rateLim... rate limit in bits/sec, default is the maximum\n");
+ printf(" possible.\n");
+ printf("-h file......... record histogram and *append* to 'file'.\n");
+ printf("-ave file....... record average rate of 3 sec intervales and\n");
+ printf(" *append* to 'file'.\n");
+ printf("-ploss.......... packet-loss percentage.\n");
+ printf("-enc............ do only encoding and store the bit-stream\n");
+ printf("-dec............ the input file is a bit-stream, decode it.\n\n");
+ printf("Example usage:\n\n");
+ printf("%s speechIn.pcm speechOut.pcm -B 40000 -fs 32\n\n", argv[0]);
+
+ exit(0);
+ }
+
+ /* Get Bottleneck value */
+ bottleneck = readParamInt(argc, argv, "-bn", 50000);
+ fprintf(stderr, "\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
+
+ /* Get Input and Output files */
+ sscanf(argv[1], "%s", inname);
+ sscanf(argv[2], "%s", outname);
+ codingMode = readSwitch(argc, argv, "-I");
+ sampFreqKHz = (int16_t)readParamInt(argc, argv, "-fs", 32);
+ if (readParamString(argc, argv, "-h", histFileName, 500) > 0) {
+ histFile = fopen(histFileName, "a");
+ if (histFile == NULL) {
+ printf("cannot open hist file %s", histFileName);
+ exit(0);
+ }
+ } else {
+ // NO recording of hitstogram
+ histFile = NULL;
+ }
+
+ packetLossPercent = readParamInt(argc, argv, "-ploss", 0);
+
+ if (readParamString(argc, argv, "-ave", averageFileName, 500) > 0) {
+ averageFile = fopen(averageFileName, "a");
+ if (averageFile == NULL) {
+ printf("cannot open file to write rate %s", averageFileName);
+ exit(0);
+ }
+ } else {
+ averageFile = NULL;
+ }
+
+ onlyEncode = readSwitch(argc, argv, "-enc");
+ onlyDecode = readSwitch(argc, argv, "-dec");
+
+ switch (sampFreqKHz) {
+ case 16: {
+ samplesIn10Ms = 160;
+ break;
+ }
+ case 32: {
+ samplesIn10Ms = 320;
+ break;
+ }
+ default:
+ printf("A sampling frequency of %d kHz is not supported, valid values are"
+ " 8 and 16.\n", sampFreqKHz);
+ exit(-1);
+ }
+ payloadLimit = (int16_t)readParamInt(argc, argv, "-plim", 400);
+ rateLimit = readParamInt(argc, argv, "-rlim", 106800);
+
+ if ((inp = fopen(inname, "rb")) == NULL) {
+ printf(" iSAC: Cannot read file %s.\n", inname);
+ exit(1);
+ }
+ if ((outp = fopen(outname, "wb")) == NULL) {
+ printf(" iSAC: Cannot write file %s.\n", outname);
+ exit(1);
+ }
+
+#ifdef WIN32
+ _splitpath(outname, outDrive, outPath, outPrefix, outSuffix);
+ _makepath(bitrateFileName, outDrive, outPath, "bitrate", ".txt");
+
+ bitrateFile = fopen(bitrateFileName, "a");
+ fprintf(bitrateFile, "%% %s \n", inname);
+#endif
+
+ printf("\n");
+ printf("Input.................... %s\n", inname);
+ printf("Output................... %s\n", outname);
+ printf("Encoding Mode............ %s\n",
+ (codingMode == 1) ? "Channel-Independent" : "Channel-Adaptive");
+ printf("Bottleneck............... %d bits/sec\n", bottleneck);
+ printf("Packet-loss Percentage... %d\n", packetLossPercent);
+ printf("\n");
+
+#ifdef WIN32
+ starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */
+#endif
+
+ /* Initialize the ISAC and BN structs */
+ err = WebRtcIsac_Create(&ISAC_main_inst);
+
+ WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
+ WebRtcIsac_SetDecSampRate(ISAC_main_inst, sampFreqKHz >= 32 ? 32000 : 16000);
+ /* Error check */
+ if (err < 0) {
+ fprintf(stderr, "\n\n Error in create.\n\n");
+ exit(EXIT_FAILURE);
+ }
+
+ framecnt = 0;
+ endfile = 0;
+
+ /* Initialize encoder and decoder */
+ if (WebRtcIsac_EncoderInit(ISAC_main_inst, codingMode) < 0) {
+ printf("cannot initialize encoder\n");
+ return -1;
+ }
+ WebRtcIsac_DecoderInit(ISAC_main_inst);
+
+ if (codingMode == 1) {
+ if (WebRtcIsac_Control(ISAC_main_inst, bottleneck, frameSize) < 0) {
+ printf("cannot set bottleneck\n");
+ return -1;
+ }
+ } else {
+ if (WebRtcIsac_ControlBwe(ISAC_main_inst, 15000, 30, 1) < 0) {
+ printf("cannot configure BWE\n");
+ return -1;
+ }
+ }
+
+ if (WebRtcIsac_SetMaxPayloadSize(ISAC_main_inst, payloadLimit) < 0) {
+ printf("cannot set maximum payload size %d.\n", payloadLimit);
+ return -1;
+ }
+
+ if (rateLimit < 106800) {
+ if (WebRtcIsac_SetMaxRate(ISAC_main_inst, rateLimit) < 0) {
+ printf("cannot set the maximum rate %d.\n", rateLimit);
+ return -1;
+ }
+ }
+
+ while (endfile == 0) {
+ fprintf(stderr, " \rframe = %7li", framecnt);
+
+ //============== Readind from the file and encoding =================
+ cur_framesmpls = 0;
+ stream_len = 0;
+
+ if (onlyDecode) {
+ uint8_t auxUW8;
+ if (fread(&auxUW8, sizeof(uint8_t), 1, inp) < 1) {
+ break;
+ }
+ stream_len = auxUW8 << 8;
+ if (fread(&auxUW8, sizeof(uint8_t), 1, inp) < 1) {
+ break;
+ }
+ stream_len |= auxUW8;
+ if (fread(payload, 1, stream_len, inp) < stream_len) {
+ printf("last payload is corrupted\n");
+ break;
+ }
+ } else {
+ while (stream_len == 0) {
+ int stream_len_int;
+
+ // Read 10 ms speech block
+ endfile = readframe(shortdata, inp, samplesIn10Ms);
+ if (endfile) {
+ break;
+ }
+ cur_framesmpls += samplesIn10Ms;
+
+ //-------- iSAC encoding ---------
+ stream_len_int = WebRtcIsac_Encode(ISAC_main_inst, shortdata, payload);
+
+ if (stream_len_int < 0) {
+ // exit if returned with error
+ // errType=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ fprintf(stderr, "\nError in encoder\n");
+ getc(stdin);
+ exit(EXIT_FAILURE);
+ }
+ stream_len = (size_t)stream_len_int;
+ }
+ //===================================================================
+ if (endfile) {
+ break;
+ }
+
+ rcuStreamLen = WebRtcIsac_GetRedPayload(ISAC_main_inst, payloadRCU);
+ if (rcuStreamLen < 0) {
+ fprintf(stderr, "\nError getting RED payload\n");
+ getc(stdin);
+ exit(EXIT_FAILURE);
+ }
+
+ get_arrival_time(cur_framesmpls, stream_len, bottleneck, &packetData,
+ sampFreqKHz * 1000, sampFreqKHz * 1000);
+ if (WebRtcIsac_UpdateBwEstimate(
+ ISAC_main_inst, payload, stream_len, packetData.rtp_number,
+ packetData.sample_count, packetData.arrival_time) < 0) {
+ printf(" BWE Error at client\n");
+ return -1;
+ }
+ }
+
+ if (endfile) {
+ break;
+ }
+
+ maxStreamLen = (stream_len > maxStreamLen) ? stream_len : maxStreamLen;
+ packetCntr++;
+
+ hist[stream_len]++;
+ if (averageFile != NULL) {
+ tmpSumStreamLen += stream_len;
+ if (packetCntr == 100) {
+ // kbps
+ fprintf(averageFile, "%8.3f ",
+ tmpSumStreamLen * 8.0 / (30.0 * packetCntr));
+ packetCntr = 0;
+ tmpSumStreamLen = 0;
+ }
+ }
+
+ if (onlyEncode) {
+ uint8_t auxUW8;
+ auxUW8 = (uint8_t)(((stream_len & 0x7F00) >> 8) & 0xFF);
+ if (fwrite(&auxUW8, sizeof(uint8_t), 1, outp) != 1) {
+ return -1;
+ }
+
+ auxUW8 = (uint8_t)(stream_len & 0xFF);
+ if (fwrite(&auxUW8, sizeof(uint8_t), 1, outp) != 1) {
+ return -1;
+ }
+ if (fwrite(payload, 1, stream_len, outp) != stream_len) {
+ return -1;
+ }
+ } else {
+ //======================= iSAC decoding ===========================
+
+ if ((rand() % 100) < packetLossPercent) {
+ declen = WebRtcIsac_DecodeRcu(ISAC_main_inst, payloadRCU,
+ (size_t)rcuStreamLen, decoded,
+ speechType);
+ lostPacketCntr++;
+ } else {
+ declen = WebRtcIsac_Decode(ISAC_main_inst, payload, stream_len, decoded,
+ speechType);
+ }
+ if (declen <= 0) {
+ // errType=WebRtcIsac_GetErrorCode(ISAC_main_inst);
+ fprintf(stderr, "\nError in decoder.\n");
+ getc(stdin);
+ exit(1);
+ }
+
+ // Write decoded speech frame to file
+ if (fwrite(decoded, sizeof(int16_t), declen, outp) != (size_t)declen) {
+ return -1;
+ }
+ cur_framesmpls = declen;
+ }
+ // Update Statistics
+ framecnt++;
+ totalsmpls += cur_framesmpls;
+ if (stream_len > 0) {
+ totalbits += 8 * stream_len;
+ }
+ if (rcuStreamLen > 0) {
+ totalBitsRCU += 8 * rcuStreamLen;
+ }
+ }
+
+ rate = ((double)totalbits * (sampFreqKHz)) / (double)totalsmpls;
+ rateRCU = ((double)totalBitsRCU * (sampFreqKHz)) / (double)totalsmpls;
+
+ printf("\n\n");
+ printf("Sampling Rate............... %d kHz\n", sampFreqKHz);
+ printf("Payload Limit............... %d bytes \n", payloadLimit);
+ printf("Rate Limit.................. %d bits/sec \n", rateLimit);
+
+#ifdef WIN32
+ fprintf(bitrateFile, "%d %10lu %d %6.3f %6.3f %6.3f\n",
+ sampFreqKHz, framecnt, bottleneck, rateLB, rateUB, rate);
+ fclose(bitrateFile);
+#endif // WIN32
+
+ printf("\n");
+ printf("Measured bit-rate........... %0.3f kbps\n", rate);
+ printf("Measured RCU bit-ratre...... %0.3f kbps\n", rateRCU);
+ printf("Maximum bit-rate/payloadsize %0.3f / %zu\n",
+ maxStreamLen * 8 / 0.03, maxStreamLen);
+ printf("Measured packet-loss........ %0.1f%% \n",
+ 100.0f * (float)lostPacketCntr / (float)packetCntr);
+
+ printf("\n");
+
+/* Runtime statistics */
+#ifdef WIN32
+ runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
+ length_file = ((double)framecnt * (double)declen / (sampFreqKHz * 1000));
+ printf("Length of speech file....... %.1f s\n", length_file);
+ printf("Time to run iSAC............ %.2f s (%.2f %% of realtime)\n\n",
+ runtime, (100 * runtime / length_file));
+#endif
+ printf("\n\n_______________________________________________\n");
+
+ if (histFile != NULL) {
+ int n;
+ for (n = 0; n < 600; n++) {
+ fprintf(histFile, "%6d ", hist[n]);
+ }
+ fprintf(histFile, "\n");
+ fclose(histFile);
+ }
+ if (averageFile != NULL) {
+ if (packetCntr > 0) {
+ fprintf(averageFile, "%8.3f ",
+ tmpSumStreamLen * 8.0 / (30.0 * packetCntr));
+ }
+ fprintf(averageFile, "\n");
+ fclose(averageFile);
+ }
+
+ fclose(inp);
+ fclose(outp);
+
+ WebRtcIsac_Free(ISAC_main_inst);
+
+ exit(0);
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.c b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.c
new file mode 100644
index 0000000000..56547b11c2
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "modules/audio_coding/codecs/isac/main/util/utility.h"
+
+/* function for reading audio data from PCM file */
+int
+readframe(
+ short* data,
+ FILE* inp,
+ int length)
+{
+ short k, rlen, status = 0;
+ unsigned char* ptrUChar;
+ ptrUChar = (unsigned char*)data;
+
+ rlen = (short)fread(data, sizeof(short), length, inp);
+ if (rlen < length) {
+ for (k = rlen; k < length; k++)
+ data[k] = 0;
+ status = 1;
+ }
+
+ // Assuming that our PCM files are written in Intel machines
+ for(k = 0; k < length; k++)
+ {
+ data[k] = (short)ptrUChar[k<<1] | ((((short)ptrUChar[(k<<1) + 1]) << 8) & 0xFF00);
+ }
+
+ return status;
+}
+
+short
+readSwitch(
+ int argc,
+ char* argv[],
+ char* strID)
+{
+ short n;
+ for(n = 0; n < argc; n++)
+ {
+ if(strcmp(argv[n], strID) == 0)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+double
+readParamDouble(
+ int argc,
+ char* argv[],
+ char* strID,
+ double defaultVal)
+{
+ double returnVal = defaultVal;
+ short n;
+ for(n = 0; n < argc; n++)
+ {
+ if(strcmp(argv[n], strID) == 0)
+ {
+ n++;
+ if(n < argc)
+ {
+ returnVal = atof(argv[n]);
+ }
+ break;
+ }
+ }
+ return returnVal;
+}
+
+int
+readParamInt(
+ int argc,
+ char* argv[],
+ char* strID,
+ int defaultVal)
+{
+ int returnVal = defaultVal;
+ short n;
+ for(n = 0; n < argc; n++)
+ {
+ if(strcmp(argv[n], strID) == 0)
+ {
+ n++;
+ if(n < argc)
+ {
+ returnVal = atoi(argv[n]);
+ }
+ break;
+ }
+ }
+ return returnVal;
+}
+
+int
+readParamString(
+ int argc,
+ char* argv[],
+ char* strID,
+ char* stringParam,
+ int maxSize)
+{
+ int paramLenght = 0;
+ short n;
+ for(n = 0; n < argc; n++)
+ {
+ if(strcmp(argv[n], strID) == 0)
+ {
+ n++;
+ if(n < argc)
+ {
+ strncpy(stringParam, argv[n], maxSize);
+ paramLenght = (int)strlen(argv[n]);
+ }
+ break;
+ }
+ }
+ return paramLenght;
+}
+
+void
+get_arrival_time(
+ int current_framesamples, /* samples */
+ size_t packet_size, /* bytes */
+ int bottleneck, /* excluding headers; bits/s */
+ BottleNeckModel* BN_data,
+ short senderSampFreqHz,
+ short receiverSampFreqHz)
+{
+ unsigned int travelTimeMs;
+ const int headerSizeByte = 35;
+
+ int headerRate;
+
+ BN_data->whenPackGeneratedMs += (current_framesamples / (senderSampFreqHz / 1000));
+
+ headerRate = headerSizeByte * 8 * senderSampFreqHz / current_framesamples; /* bits/s */
+
+ /* everything in samples */
+ BN_data->sample_count = BN_data->sample_count + current_framesamples;
+
+ //travelTimeMs = ((packet_size + HeaderSize) * 8 * sampFreqHz) /
+ // (bottleneck + HeaderRate)
+ travelTimeMs = (unsigned int)floor((double)((packet_size + headerSizeByte) * 8 * 1000)
+ / (double)(bottleneck + headerRate) + 0.5);
+
+ if(BN_data->whenPrevPackLeftMs > BN_data->whenPackGeneratedMs)
+ {
+ BN_data->whenPrevPackLeftMs += travelTimeMs;
+ }
+ else
+ {
+ BN_data->whenPrevPackLeftMs = BN_data->whenPackGeneratedMs +
+ travelTimeMs;
+ }
+
+ BN_data->arrival_time = (BN_data->whenPrevPackLeftMs *
+ (receiverSampFreqHz / 1000));
+
+// if (BN_data->arrival_time < BN_data->sample_count)
+// BN_data->arrival_time = BN_data->sample_count;
+
+ BN_data->rtp_number++;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.h b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.h
new file mode 100644
index 0000000000..1acc54251b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/isac/main/util/utility.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_UTIL_UTILITY_H_
+#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_UTIL_UTILITY_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define OPEN_FILE_WB(filePtr, fullPath) \
+ do { \
+ if (fullPath != NULL) { \
+ filePtr = fopen(fullPath, "wb"); \
+ if (filePtr == NULL) { \
+ printf("could not open %s to write to.", fullPath); \
+ return -1; \
+ } \
+ } else { \
+ filePtr = NULL; \
+ } \
+ } while (0)
+
+#define OPEN_FILE_AB(filePtr, fullPath) \
+ do { \
+ if (fullPath != NULL) { \
+ filePtr = fopen(fullPath, "ab"); \
+ if (filePtr == NULL) { \
+ printf("could not open %s to write to.", fullPath); \
+ return -1; \
+ } \
+ } else { \
+ filePtr = NULL; \
+ } \
+ } while (0)
+
+#define OPEN_FILE_RB(filePtr, fullPath) \
+ do { \
+ if (fullPath != NULL) { \
+ filePtr = fopen(fullPath, "rb"); \
+ if (filePtr == NULL) { \
+ printf("could not open %s to read from.", fullPath); \
+ return -1; \
+ } \
+ } else { \
+ filePtr = NULL; \
+ } \
+ } while (0)
+
+#define WRITE_FILE_D(bufferPtr, len, filePtr) \
+ do { \
+ if (filePtr != NULL) { \
+ double dummy[1000]; \
+ int cntr; \
+ for (cntr = 0; cntr < (len); cntr++) { \
+ dummy[cntr] = (double)bufferPtr[cntr]; \
+ } \
+ fwrite(dummy, sizeof(double), len, filePtr); \
+ fflush(filePtr); \
+ } \
+ } while (0)
+
+typedef struct {
+ unsigned int whenPackGeneratedMs;
+ unsigned int whenPrevPackLeftMs;
+ unsigned int sendTimeMs; /* milisecond */
+ unsigned int arrival_time; /* samples */
+ unsigned int sample_count; /* samples, also used as "send time stamp" */
+ unsigned int rtp_number;
+} BottleNeckModel;
+
+void get_arrival_time(int current_framesamples, /* samples */
+ size_t packet_size, /* bytes */
+ int bottleneck, /* excluding headers; bits/s */
+ BottleNeckModel* BN_data,
+ short senderSampFreqHz,
+ short receiverSampFreqHz);
+
+/* function for reading audio data from PCM file */
+int readframe(short* data, FILE* inp, int length);
+
+short readSwitch(int argc, char* argv[], char* strID);
+
+double readParamDouble(int argc, char* argv[], char* strID, double defaultVal);
+
+int readParamInt(int argc, char* argv[], char* strID, int defaultVal);
+
+int readParamString(int argc,
+ char* argv[],
+ char* strID,
+ char* stringParam,
+ int maxSize);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.cc b/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.cc
new file mode 100644
index 0000000000..dacf325082
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.cc
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+LegacyEncodedAudioFrame::LegacyEncodedAudioFrame(AudioDecoder* decoder,
+ rtc::Buffer&& payload)
+ : decoder_(decoder), payload_(std::move(payload)) {}
+
+LegacyEncodedAudioFrame::~LegacyEncodedAudioFrame() = default;
+
+size_t LegacyEncodedAudioFrame::Duration() const {
+ const int ret = decoder_->PacketDuration(payload_.data(), payload_.size());
+ return (ret < 0) ? 0 : static_cast<size_t>(ret);
+}
+
+absl::optional<AudioDecoder::EncodedAudioFrame::DecodeResult>
+LegacyEncodedAudioFrame::Decode(rtc::ArrayView<int16_t> decoded) const {
+ AudioDecoder::SpeechType speech_type = AudioDecoder::kSpeech;
+ const int ret = decoder_->Decode(
+ payload_.data(), payload_.size(), decoder_->SampleRateHz(),
+ decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);
+
+ if (ret < 0)
+ return absl::nullopt;
+
+ return DecodeResult{static_cast<size_t>(ret), speech_type};
+}
+
+std::vector<AudioDecoder::ParseResult> LegacyEncodedAudioFrame::SplitBySamples(
+ AudioDecoder* decoder,
+ rtc::Buffer&& payload,
+ uint32_t timestamp,
+ size_t bytes_per_ms,
+ uint32_t timestamps_per_ms) {
+ RTC_DCHECK(payload.data());
+ std::vector<AudioDecoder::ParseResult> results;
+ size_t split_size_bytes = payload.size();
+
+ // Find a "chunk size" >= 20 ms and < 40 ms.
+ const size_t min_chunk_size = bytes_per_ms * 20;
+ if (min_chunk_size >= payload.size()) {
+ std::unique_ptr<LegacyEncodedAudioFrame> frame(
+ new LegacyEncodedAudioFrame(decoder, std::move(payload)));
+ results.emplace_back(timestamp, 0, std::move(frame));
+ } else {
+ // Reduce the split size by half as long as `split_size_bytes` is at least
+ // twice the minimum chunk size (so that the resulting size is at least as
+ // large as the minimum chunk size).
+ while (split_size_bytes >= 2 * min_chunk_size) {
+ split_size_bytes /= 2;
+ }
+
+ const uint32_t timestamps_per_chunk = static_cast<uint32_t>(
+ split_size_bytes * timestamps_per_ms / bytes_per_ms);
+ size_t byte_offset;
+ uint32_t timestamp_offset;
+ for (byte_offset = 0, timestamp_offset = 0; byte_offset < payload.size();
+ byte_offset += split_size_bytes,
+ timestamp_offset += timestamps_per_chunk) {
+ split_size_bytes =
+ std::min(split_size_bytes, payload.size() - byte_offset);
+ rtc::Buffer new_payload(payload.data() + byte_offset, split_size_bytes);
+ std::unique_ptr<LegacyEncodedAudioFrame> frame(
+ new LegacyEncodedAudioFrame(decoder, std::move(new_payload)));
+ results.emplace_back(timestamp + timestamp_offset, 0, std::move(frame));
+ }
+ }
+
+ return results;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h b/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h
new file mode 100644
index 0000000000..21da1367ed
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_LEGACY_ENCODED_AUDIO_FRAME_H_
+#define MODULES_AUDIO_CODING_CODECS_LEGACY_ENCODED_AUDIO_FRAME_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/audio_codecs/audio_decoder.h"
+#include "rtc_base/buffer.h"
+
+namespace webrtc {
+
+class LegacyEncodedAudioFrame final : public AudioDecoder::EncodedAudioFrame {
+ public:
+ LegacyEncodedAudioFrame(AudioDecoder* decoder, rtc::Buffer&& payload);
+ ~LegacyEncodedAudioFrame() override;
+
+ static std::vector<AudioDecoder::ParseResult> SplitBySamples(
+ AudioDecoder* decoder,
+ rtc::Buffer&& payload,
+ uint32_t timestamp,
+ size_t bytes_per_ms,
+ uint32_t timestamps_per_ms);
+
+ size_t Duration() const override;
+
+ absl::optional<DecodeResult> Decode(
+ rtc::ArrayView<int16_t> decoded) const override;
+
+ // For testing:
+ const rtc::Buffer& payload() const { return payload_; }
+
+ private:
+ AudioDecoder* const decoder_;
+ const rtc::Buffer payload_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_LEGACY_ENCODED_AUDIO_FRAME_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
new file mode 100644
index 0000000000..f81aeeea80
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+
+#include "rtc_base/numerics/safe_conversions.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+enum class NetEqDecoder {
+ kDecoderPCMu,
+ kDecoderPCMa,
+ kDecoderPCMu_2ch,
+ kDecoderPCMa_2ch,
+ kDecoderPCM16B,
+ kDecoderPCM16Bwb,
+ kDecoderPCM16Bswb32kHz,
+ kDecoderPCM16Bswb48kHz,
+ kDecoderPCM16B_2ch,
+ kDecoderPCM16Bwb_2ch,
+ kDecoderPCM16Bswb32kHz_2ch,
+ kDecoderPCM16Bswb48kHz_2ch,
+ kDecoderPCM16B_5ch,
+ kDecoderG722,
+};
+
+class SplitBySamplesTest : public ::testing::TestWithParam<NetEqDecoder> {
+ protected:
+ virtual void SetUp() {
+ decoder_type_ = GetParam();
+ switch (decoder_type_) {
+ case NetEqDecoder::kDecoderPCMu:
+ case NetEqDecoder::kDecoderPCMa:
+ bytes_per_ms_ = 8;
+ samples_per_ms_ = 8;
+ break;
+ case NetEqDecoder::kDecoderPCMu_2ch:
+ case NetEqDecoder::kDecoderPCMa_2ch:
+ bytes_per_ms_ = 2 * 8;
+ samples_per_ms_ = 8;
+ break;
+ case NetEqDecoder::kDecoderG722:
+ bytes_per_ms_ = 8;
+ samples_per_ms_ = 16;
+ break;
+ case NetEqDecoder::kDecoderPCM16B:
+ bytes_per_ms_ = 16;
+ samples_per_ms_ = 8;
+ break;
+ case NetEqDecoder::kDecoderPCM16Bwb:
+ bytes_per_ms_ = 32;
+ samples_per_ms_ = 16;
+ break;
+ case NetEqDecoder::kDecoderPCM16Bswb32kHz:
+ bytes_per_ms_ = 64;
+ samples_per_ms_ = 32;
+ break;
+ case NetEqDecoder::kDecoderPCM16Bswb48kHz:
+ bytes_per_ms_ = 96;
+ samples_per_ms_ = 48;
+ break;
+ case NetEqDecoder::kDecoderPCM16B_2ch:
+ bytes_per_ms_ = 2 * 16;
+ samples_per_ms_ = 8;
+ break;
+ case NetEqDecoder::kDecoderPCM16Bwb_2ch:
+ bytes_per_ms_ = 2 * 32;
+ samples_per_ms_ = 16;
+ break;
+ case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch:
+ bytes_per_ms_ = 2 * 64;
+ samples_per_ms_ = 32;
+ break;
+ case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch:
+ bytes_per_ms_ = 2 * 96;
+ samples_per_ms_ = 48;
+ break;
+ case NetEqDecoder::kDecoderPCM16B_5ch:
+ bytes_per_ms_ = 5 * 16;
+ samples_per_ms_ = 8;
+ break;
+ default:
+ RTC_DCHECK_NOTREACHED();
+ break;
+ }
+ }
+ size_t bytes_per_ms_;
+ int samples_per_ms_;
+ NetEqDecoder decoder_type_;
+};
+
+// Test splitting sample-based payloads.
+TEST_P(SplitBySamplesTest, PayloadSizes) {
+ constexpr uint32_t kBaseTimestamp = 0x12345678;
+ struct ExpectedSplit {
+ size_t payload_size_ms;
+ size_t num_frames;
+ // For simplicity. We only expect up to two packets per split.
+ size_t frame_sizes[2];
+ };
+ // The payloads are expected to be split as follows:
+ // 10 ms -> 10 ms
+ // 20 ms -> 20 ms
+ // 30 ms -> 30 ms
+ // 40 ms -> 20 + 20 ms
+ // 50 ms -> 25 + 25 ms
+ // 60 ms -> 30 + 30 ms
+ ExpectedSplit expected_splits[] = {{10, 1, {10}}, {20, 1, {20}},
+ {30, 1, {30}}, {40, 2, {20, 20}},
+ {50, 2, {25, 25}}, {60, 2, {30, 30}}};
+
+ for (const auto& expected_split : expected_splits) {
+ // The payload values are set to steadily increase (modulo 256), so that the
+ // resulting frames can be checked and we can be reasonably certain no
+ // sample was missed or repeated.
+ const auto generate_payload = [](size_t num_bytes) {
+ rtc::Buffer payload(num_bytes);
+ uint8_t value = 0;
+ // Allow wrap-around of value in counter below.
+ for (size_t i = 0; i != payload.size(); ++i, ++value) {
+ payload[i] = value;
+ }
+ return payload;
+ };
+
+ const auto results = LegacyEncodedAudioFrame::SplitBySamples(
+ nullptr,
+ generate_payload(expected_split.payload_size_ms * bytes_per_ms_),
+ kBaseTimestamp, bytes_per_ms_, samples_per_ms_);
+
+ EXPECT_EQ(expected_split.num_frames, results.size());
+ uint32_t expected_timestamp = kBaseTimestamp;
+ uint8_t value = 0;
+ for (size_t i = 0; i != expected_split.num_frames; ++i) {
+ const auto& result = results[i];
+ const LegacyEncodedAudioFrame* frame =
+ static_cast<const LegacyEncodedAudioFrame*>(result.frame.get());
+ const size_t length_bytes = expected_split.frame_sizes[i] * bytes_per_ms_;
+ EXPECT_EQ(length_bytes, frame->payload().size());
+ EXPECT_EQ(expected_timestamp, result.timestamp);
+ const rtc::Buffer& payload = frame->payload();
+ // Allow wrap-around of value in counter below.
+ for (size_t i = 0; i != payload.size(); ++i, ++value) {
+ ASSERT_EQ(value, payload[i]);
+ }
+
+ expected_timestamp += rtc::checked_cast<uint32_t>(
+ expected_split.frame_sizes[i] * samples_per_ms_);
+ }
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ LegacyEncodedAudioFrame,
+ SplitBySamplesTest,
+ ::testing::Values(NetEqDecoder::kDecoderPCMu,
+ NetEqDecoder::kDecoderPCMa,
+ NetEqDecoder::kDecoderPCMu_2ch,
+ NetEqDecoder::kDecoderPCMa_2ch,
+ NetEqDecoder::kDecoderG722,
+ NetEqDecoder::kDecoderPCM16B,
+ NetEqDecoder::kDecoderPCM16Bwb,
+ NetEqDecoder::kDecoderPCM16Bswb32kHz,
+ NetEqDecoder::kDecoderPCM16Bswb48kHz,
+ NetEqDecoder::kDecoderPCM16B_2ch,
+ NetEqDecoder::kDecoderPCM16Bwb_2ch,
+ NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch,
+ NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch,
+ NetEqDecoder::kDecoderPCM16B_5ch));
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/DEPS b/third_party/libwebrtc/modules/audio_coding/codecs/opus/DEPS
new file mode 100644
index 0000000000..c2530726ad
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ "opus_inst\.h": [
+ "+third_party/opus",
+ ],
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.cc
new file mode 100644
index 0000000000..03c02186d0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
+
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+
+absl::optional<std::string> GetFormatParameter(const SdpAudioFormat& format,
+ absl::string_view param) {
+ auto it = format.parameters.find(std::string(param));
+ if (it == format.parameters.end())
+ return absl::nullopt;
+
+ return it->second;
+}
+
+// Parses a comma-separated string "1,2,0,6" into a std::vector<unsigned char>.
+template <>
+absl::optional<std::vector<unsigned char>> GetFormatParameter(
+ const SdpAudioFormat& format,
+ absl::string_view param) {
+ std::vector<unsigned char> result;
+ const std::string comma_separated_list =
+ GetFormatParameter(format, param).value_or("");
+ size_t pos = 0;
+ while (pos < comma_separated_list.size()) {
+ const size_t next_comma = comma_separated_list.find(',', pos);
+ const size_t distance_to_next_comma = next_comma == std::string::npos
+ ? std::string::npos
+ : (next_comma - pos);
+ auto substring_with_number =
+ comma_separated_list.substr(pos, distance_to_next_comma);
+ auto conv = rtc::StringToNumber<int>(substring_with_number);
+ if (!conv.has_value()) {
+ return absl::nullopt;
+ }
+ result.push_back(*conv);
+ pos += substring_with_number.size() + 1;
+ }
+ return result;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.h
new file mode 100644
index 0000000000..5ebb51b577
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_coder_opus_common.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_CODER_OPUS_COMMON_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_CODER_OPUS_COMMON_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_decoder.h"
+#include "api/audio_codecs/audio_format.h"
+#include "rtc_base/string_to_number.h"
+
+namespace webrtc {
+
+absl::optional<std::string> GetFormatParameter(const SdpAudioFormat& format,
+ absl::string_view param);
+
+template <typename T>
+absl::optional<T> GetFormatParameter(const SdpAudioFormat& format,
+ absl::string_view param) {
+ return rtc::StringToNumber<T>(GetFormatParameter(format, param).value_or(""));
+}
+
+template <>
+absl::optional<std::vector<unsigned char>> GetFormatParameter(
+ const SdpAudioFormat& format,
+ absl::string_view param);
+
+class OpusFrame : public AudioDecoder::EncodedAudioFrame {
+ public:
+ OpusFrame(AudioDecoder* decoder,
+ rtc::Buffer&& payload,
+ bool is_primary_payload)
+ : decoder_(decoder),
+ payload_(std::move(payload)),
+ is_primary_payload_(is_primary_payload) {}
+
+ size_t Duration() const override {
+ int ret;
+ if (is_primary_payload_) {
+ ret = decoder_->PacketDuration(payload_.data(), payload_.size());
+ } else {
+ ret = decoder_->PacketDurationRedundant(payload_.data(), payload_.size());
+ }
+ return (ret < 0) ? 0 : static_cast<size_t>(ret);
+ }
+
+ bool IsDtxPacket() const override { return payload_.size() <= 2; }
+
+ absl::optional<DecodeResult> Decode(
+ rtc::ArrayView<int16_t> decoded) const override {
+ AudioDecoder::SpeechType speech_type = AudioDecoder::kSpeech;
+ int ret;
+ if (is_primary_payload_) {
+ ret = decoder_->Decode(
+ payload_.data(), payload_.size(), decoder_->SampleRateHz(),
+ decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);
+ } else {
+ ret = decoder_->DecodeRedundant(
+ payload_.data(), payload_.size(), decoder_->SampleRateHz(),
+ decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);
+ }
+
+ if (ret < 0)
+ return absl::nullopt;
+
+ return DecodeResult{static_cast<size_t>(ret), speech_type};
+ }
+
+ private:
+ AudioDecoder* const decoder_;
+ const rtc::Buffer payload_;
+ const bool is_primary_payload_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_CODER_OPUS_COMMON_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.cc
new file mode 100644
index 0000000000..285ea89959
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.cc
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.h"
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
+#include "rtc_base/string_to_number.h"
+
+namespace webrtc {
+
+std::unique_ptr<AudioDecoderMultiChannelOpusImpl>
+AudioDecoderMultiChannelOpusImpl::MakeAudioDecoder(
+ AudioDecoderMultiChannelOpusConfig config) {
+ if (!config.IsOk()) {
+ RTC_DCHECK_NOTREACHED();
+ return nullptr;
+ }
+ // Fill the pointer with a working decoder through the C interface. This
+ // allocates memory.
+ OpusDecInst* dec_state = nullptr;
+ const int error = WebRtcOpus_MultistreamDecoderCreate(
+ &dec_state, config.num_channels, config.num_streams,
+ config.coupled_streams, config.channel_mapping.data());
+ if (error != 0) {
+ return nullptr;
+ }
+
+ // Pass the ownership to DecoderImpl. Not using 'make_unique' because the
+ // c-tor is private.
+ return std::unique_ptr<AudioDecoderMultiChannelOpusImpl>(
+ new AudioDecoderMultiChannelOpusImpl(dec_state, config));
+}
+
+AudioDecoderMultiChannelOpusImpl::AudioDecoderMultiChannelOpusImpl(
+ OpusDecInst* dec_state,
+ AudioDecoderMultiChannelOpusConfig config)
+ : dec_state_(dec_state), config_(config) {
+ RTC_DCHECK(dec_state);
+ WebRtcOpus_DecoderInit(dec_state_);
+}
+
+AudioDecoderMultiChannelOpusImpl::~AudioDecoderMultiChannelOpusImpl() {
+ WebRtcOpus_DecoderFree(dec_state_);
+}
+
+absl::optional<AudioDecoderMultiChannelOpusConfig>
+AudioDecoderMultiChannelOpusImpl::SdpToConfig(const SdpAudioFormat& format) {
+ AudioDecoderMultiChannelOpusConfig config;
+ config.num_channels = format.num_channels;
+ auto num_streams = GetFormatParameter<int>(format, "num_streams");
+ if (!num_streams.has_value()) {
+ return absl::nullopt;
+ }
+ config.num_streams = *num_streams;
+
+ auto coupled_streams = GetFormatParameter<int>(format, "coupled_streams");
+ if (!coupled_streams.has_value()) {
+ return absl::nullopt;
+ }
+ config.coupled_streams = *coupled_streams;
+
+ auto channel_mapping =
+ GetFormatParameter<std::vector<unsigned char>>(format, "channel_mapping");
+ if (!channel_mapping.has_value()) {
+ return absl::nullopt;
+ }
+ config.channel_mapping = *channel_mapping;
+ if (!config.IsOk()) {
+ return absl::nullopt;
+ }
+ return config;
+}
+
+std::vector<AudioDecoder::ParseResult>
+AudioDecoderMultiChannelOpusImpl::ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ std::vector<ParseResult> results;
+
+ if (PacketHasFec(payload.data(), payload.size())) {
+ const int duration =
+ PacketDurationRedundant(payload.data(), payload.size());
+ RTC_DCHECK_GE(duration, 0);
+ rtc::Buffer payload_copy(payload.data(), payload.size());
+ std::unique_ptr<EncodedAudioFrame> fec_frame(
+ new OpusFrame(this, std::move(payload_copy), false));
+ results.emplace_back(timestamp - duration, 1, std::move(fec_frame));
+ }
+ std::unique_ptr<EncodedAudioFrame> frame(
+ new OpusFrame(this, std::move(payload), true));
+ results.emplace_back(timestamp, 0, std::move(frame));
+ return results;
+}
+
+int AudioDecoderMultiChannelOpusImpl::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(sample_rate_hz, 48000);
+ int16_t temp_type = 1; // Default is speech.
+ int ret =
+ WebRtcOpus_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
+ if (ret > 0)
+ ret *= static_cast<int>(
+ config_.num_channels); // Return total number of samples.
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+int AudioDecoderMultiChannelOpusImpl::DecodeRedundantInternal(
+ const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ if (!PacketHasFec(encoded, encoded_len)) {
+ // This packet is a RED packet.
+ return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
+ speech_type);
+ }
+
+ RTC_DCHECK_EQ(sample_rate_hz, 48000);
+ int16_t temp_type = 1; // Default is speech.
+ int ret = WebRtcOpus_DecodeFec(dec_state_, encoded, encoded_len, decoded,
+ &temp_type);
+ if (ret > 0)
+ ret *= static_cast<int>(
+ config_.num_channels); // Return total number of samples.
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+void AudioDecoderMultiChannelOpusImpl::Reset() {
+ WebRtcOpus_DecoderInit(dec_state_);
+}
+
+int AudioDecoderMultiChannelOpusImpl::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ return WebRtcOpus_DurationEst(dec_state_, encoded, encoded_len);
+}
+
+int AudioDecoderMultiChannelOpusImpl::PacketDurationRedundant(
+ const uint8_t* encoded,
+ size_t encoded_len) const {
+ if (!PacketHasFec(encoded, encoded_len)) {
+ // This packet is a RED packet.
+ return PacketDuration(encoded, encoded_len);
+ }
+
+ return WebRtcOpus_FecDurationEst(encoded, encoded_len, 48000);
+}
+
+bool AudioDecoderMultiChannelOpusImpl::PacketHasFec(const uint8_t* encoded,
+ size_t encoded_len) const {
+ int fec;
+ fec = WebRtcOpus_PacketHasFec(encoded, encoded_len);
+ return (fec == 1);
+}
+
+int AudioDecoderMultiChannelOpusImpl::SampleRateHz() const {
+ return 48000;
+}
+
+size_t AudioDecoderMultiChannelOpusImpl::Channels() const {
+ return config_.num_channels;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.h
new file mode 100644
index 0000000000..2ff47a8a53
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_IMPL_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_IMPL_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <vector>
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "api/audio_codecs/audio_format.h"
+#include "api/audio_codecs/opus/audio_decoder_multi_channel_opus_config.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "rtc_base/buffer.h"
+
+namespace webrtc {
+
+class AudioDecoderMultiChannelOpusImpl final : public AudioDecoder {
+ public:
+ static std::unique_ptr<AudioDecoderMultiChannelOpusImpl> MakeAudioDecoder(
+ AudioDecoderMultiChannelOpusConfig config);
+
+ ~AudioDecoderMultiChannelOpusImpl() override;
+
+ AudioDecoderMultiChannelOpusImpl(const AudioDecoderMultiChannelOpusImpl&) =
+ delete;
+ AudioDecoderMultiChannelOpusImpl& operator=(
+ const AudioDecoderMultiChannelOpusImpl&) = delete;
+
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ void Reset() override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const override;
+ bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ static absl::optional<AudioDecoderMultiChannelOpusConfig> SdpToConfig(
+ const SdpAudioFormat& format);
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+ int DecodeRedundantInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ AudioDecoderMultiChannelOpusImpl(OpusDecInst* dec_state,
+ AudioDecoderMultiChannelOpusConfig config);
+
+ OpusDecInst* dec_state_;
+ const AudioDecoderMultiChannelOpusConfig config_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_IMPL_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_unittest.cc
new file mode 100644
index 0000000000..57e2107f3c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_unittest.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h"
+
+#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+using ::testing::NiceMock;
+using ::testing::Return;
+
+TEST(AudioDecoderMultiOpusTest, GetFormatParameter) {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 4,
+ {{"channel_mapping", "0,1,2,3"},
+ {"coupled_streams", "2"},
+ {"num_streams", "2"}});
+
+ EXPECT_EQ(GetFormatParameter(sdp_format, "channel_mapping"),
+ absl::optional<std::string>("0,1,2,3"));
+
+ EXPECT_EQ(GetFormatParameter<int>(sdp_format, "coupled_streams"),
+ absl::optional<int>(2));
+
+ EXPECT_EQ(GetFormatParameter(sdp_format, "missing"), absl::nullopt);
+
+ EXPECT_EQ(GetFormatParameter<int>(sdp_format, "channel_mapping"),
+ absl::nullopt);
+}
+
+TEST(AudioDecoderMultiOpusTest, InvalidChannelMappings) {
+ {
+ // Can't use channel 3 if there are only 2 channels.
+ const SdpAudioFormat sdp_format("multiopus", 48000, 2,
+ {{"channel_mapping", "3,0"},
+ {"coupled_streams", "1"},
+ {"num_streams", "2"}});
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+ EXPECT_FALSE(decoder_config.has_value());
+ }
+ {
+ // The mapping is too long. There are only 5 channels, but 6 elements in the
+ // mapping.
+ const SdpAudioFormat sdp_format("multiopus", 48000, 5,
+ {{"channel_mapping", "0,1,2,3,4,5"},
+ {"coupled_streams", "0"},
+ {"num_streams", "2"}});
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+ EXPECT_FALSE(decoder_config.has_value());
+ }
+ {
+ // The mapping doesn't parse correctly.
+ const SdpAudioFormat sdp_format(
+ "multiopus", 48000, 5,
+ {{"channel_mapping", "0,1,two,3,4"}, {"coupled_streams", "0"}});
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+ EXPECT_FALSE(decoder_config.has_value());
+ }
+}
+
+TEST(AudioDecoderMultiOpusTest, ValidSdpToConfigProducesCorrectConfig) {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 4,
+ {{"channel_mapping", "3,1,2,0"},
+ {"coupled_streams", "2"},
+ {"num_streams", "2"}});
+
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ ASSERT_TRUE(decoder_config.has_value());
+ EXPECT_TRUE(decoder_config->IsOk());
+ EXPECT_EQ(decoder_config->coupled_streams, 2);
+ EXPECT_THAT(decoder_config->channel_mapping,
+ ::testing::ContainerEq(std::vector<unsigned char>({3, 1, 2, 0})));
+}
+
+TEST(AudioDecoderMultiOpusTest, InvalidSdpToConfigDoesNotProduceConfig) {
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 4,
+ {{"channel_mapping", "0,1,2,3"},
+ {"coupled_stream", "2"},
+ {"num_streams", "2"}});
+
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ EXPECT_FALSE(decoder_config.has_value());
+ }
+
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 4,
+ {{"channel_mapping", "0,1,2 3"},
+ {"coupled_streams", "2"},
+ {"num_streams", "2"}});
+
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ EXPECT_FALSE(decoder_config.has_value());
+ }
+}
+
+TEST(AudioDecoderMultiOpusTest, CodecsCanBeCreated) {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 4,
+ {{"channel_mapping", "0,1,2,3"},
+ {"coupled_streams", "2"},
+ {"num_streams", "2"}});
+
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ ASSERT_TRUE(decoder_config.has_value());
+
+ const std::unique_ptr<AudioDecoder> opus_decoder =
+ AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config);
+
+ EXPECT_TRUE(opus_decoder);
+}
+
+TEST(AudioDecoderMultiOpusTest, AdvertisedCodecsCanBeCreated) {
+ std::vector<AudioCodecSpec> specs;
+ AudioDecoderMultiChannelOpus::AppendSupportedDecoders(&specs);
+
+ EXPECT_FALSE(specs.empty());
+
+ for (const AudioCodecSpec& spec : specs) {
+ const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
+ AudioDecoderMultiChannelOpus::SdpToConfig(spec.format);
+ ASSERT_TRUE(decoder_config.has_value());
+
+ const std::unique_ptr<AudioDecoder> opus_decoder =
+ AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config);
+
+ EXPECT_TRUE(opus_decoder);
+ }
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
new file mode 100644
index 0000000000..cff9685548
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
+
+#include <memory>
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels,
+ int sample_rate_hz)
+ : channels_{num_channels}, sample_rate_hz_{sample_rate_hz} {
+ RTC_DCHECK(num_channels == 1 || num_channels == 2);
+ RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 48000);
+ const int error =
+ WebRtcOpus_DecoderCreate(&dec_state_, channels_, sample_rate_hz_);
+ RTC_DCHECK(error == 0);
+ WebRtcOpus_DecoderInit(dec_state_);
+}
+
+AudioDecoderOpusImpl::~AudioDecoderOpusImpl() {
+ WebRtcOpus_DecoderFree(dec_state_);
+}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderOpusImpl::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ std::vector<ParseResult> results;
+
+ if (PacketHasFec(payload.data(), payload.size())) {
+ const int duration =
+ PacketDurationRedundant(payload.data(), payload.size());
+ RTC_DCHECK_GE(duration, 0);
+ rtc::Buffer payload_copy(payload.data(), payload.size());
+ std::unique_ptr<EncodedAudioFrame> fec_frame(
+ new OpusFrame(this, std::move(payload_copy), false));
+ results.emplace_back(timestamp - duration, 1, std::move(fec_frame));
+ }
+ std::unique_ptr<EncodedAudioFrame> frame(
+ new OpusFrame(this, std::move(payload), true));
+ results.emplace_back(timestamp, 0, std::move(frame));
+ return results;
+}
+
+int AudioDecoderOpusImpl::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(sample_rate_hz, sample_rate_hz_);
+ int16_t temp_type = 1; // Default is speech.
+ int ret =
+ WebRtcOpus_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
+ if (ret > 0)
+ ret *= static_cast<int>(channels_); // Return total number of samples.
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+int AudioDecoderOpusImpl::DecodeRedundantInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ if (!PacketHasFec(encoded, encoded_len)) {
+ // This packet is a RED packet.
+ return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
+ speech_type);
+ }
+
+ RTC_DCHECK_EQ(sample_rate_hz, sample_rate_hz_);
+ int16_t temp_type = 1; // Default is speech.
+ int ret = WebRtcOpus_DecodeFec(dec_state_, encoded, encoded_len, decoded,
+ &temp_type);
+ if (ret > 0)
+ ret *= static_cast<int>(channels_); // Return total number of samples.
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+void AudioDecoderOpusImpl::Reset() {
+ WebRtcOpus_DecoderInit(dec_state_);
+}
+
+int AudioDecoderOpusImpl::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ return WebRtcOpus_DurationEst(dec_state_, encoded, encoded_len);
+}
+
+int AudioDecoderOpusImpl::PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const {
+ if (!PacketHasFec(encoded, encoded_len)) {
+ // This packet is a RED packet.
+ return PacketDuration(encoded, encoded_len);
+ }
+
+ return WebRtcOpus_FecDurationEst(encoded, encoded_len, sample_rate_hz_);
+}
+
+bool AudioDecoderOpusImpl::PacketHasFec(const uint8_t* encoded,
+ size_t encoded_len) const {
+ int fec;
+ fec = WebRtcOpus_PacketHasFec(encoded, encoded_len);
+ return (fec == 1);
+}
+
+int AudioDecoderOpusImpl::SampleRateHz() const {
+ return sample_rate_hz_;
+}
+
+size_t AudioDecoderOpusImpl::Channels() const {
+ return channels_;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h
new file mode 100644
index 0000000000..e8fd0440bc
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_OPUS_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_OPUS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "rtc_base/buffer.h"
+
+namespace webrtc {
+
+class AudioDecoderOpusImpl final : public AudioDecoder {
+ public:
+ explicit AudioDecoderOpusImpl(size_t num_channels,
+ int sample_rate_hz = 48000);
+ ~AudioDecoderOpusImpl() override;
+
+ AudioDecoderOpusImpl(const AudioDecoderOpusImpl&) = delete;
+ AudioDecoderOpusImpl& operator=(const AudioDecoderOpusImpl&) = delete;
+
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ void Reset() override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int PacketDurationRedundant(const uint8_t* encoded,
+ size_t encoded_len) const override;
+ bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+ int DecodeRedundantInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ OpusDecInst* dec_state_;
+ const size_t channels_;
+ const int sample_rate_hz_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_OPUS_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.cc
new file mode 100644
index 0000000000..38a11c123d
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.cc
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * LEFT TO DO:
+ * - WRITE TESTS for the stuff in this file.
+ * - Check the creation, maybe make it safer by returning an empty optional or
+ * unique_ptr. --- It looks OK, but RecreateEncoderInstance can perhaps crash
+ * on a valid config. Can run it in the fuzzer for some time. Should prbl also
+ * fuzz the config.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.h"
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/match.h"
+#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
+#include "rtc_base/arraysize.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/string_to_number.h"
+
+namespace webrtc {
+
+namespace {
+
+// Recommended bitrates for one channel:
+// 8-12 kb/s for NB speech,
+// 16-20 kb/s for WB speech,
+// 28-40 kb/s for FB speech,
+// 48-64 kb/s for FB mono music, and
+// 64-128 kb/s for FB stereo music.
+// The current implementation multiplies these values by the number of channels.
+constexpr int kOpusBitrateNbBps = 12000;
+constexpr int kOpusBitrateWbBps = 20000;
+constexpr int kOpusBitrateFbBps = 32000;
+
+constexpr int kDefaultMaxPlaybackRate = 48000;
+// These two lists must be sorted from low to high
+#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
+constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60, 120};
+#else
+constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60};
+#endif
+
+int GetBitrateBps(const AudioEncoderMultiChannelOpusConfig& config) {
+ RTC_DCHECK(config.IsOk());
+ return config.bitrate_bps;
+}
+int GetMaxPlaybackRate(const SdpAudioFormat& format) {
+ const auto param = GetFormatParameter<int>(format, "maxplaybackrate");
+ if (param && *param >= 8000) {
+ return std::min(*param, kDefaultMaxPlaybackRate);
+ }
+ return kDefaultMaxPlaybackRate;
+}
+
+int GetFrameSizeMs(const SdpAudioFormat& format) {
+ const auto ptime = GetFormatParameter<int>(format, "ptime");
+ if (ptime.has_value()) {
+ // Pick the next highest supported frame length from
+ // kOpusSupportedFrameLengths.
+ for (const int supported_frame_length : kOpusSupportedFrameLengths) {
+ if (supported_frame_length >= *ptime) {
+ return supported_frame_length;
+ }
+ }
+ // If none was found, return the largest supported frame length.
+ return *(std::end(kOpusSupportedFrameLengths) - 1);
+ }
+
+ return AudioEncoderOpusConfig::kDefaultFrameSizeMs;
+}
+
+int CalculateDefaultBitrate(int max_playback_rate, size_t num_channels) {
+ const int bitrate = [&] {
+ if (max_playback_rate <= 8000) {
+ return kOpusBitrateNbBps * rtc::dchecked_cast<int>(num_channels);
+ } else if (max_playback_rate <= 16000) {
+ return kOpusBitrateWbBps * rtc::dchecked_cast<int>(num_channels);
+ } else {
+ return kOpusBitrateFbBps * rtc::dchecked_cast<int>(num_channels);
+ }
+ }();
+ RTC_DCHECK_GE(bitrate, AudioEncoderMultiChannelOpusConfig::kMinBitrateBps);
+ return bitrate;
+}
+
+// Get the maxaveragebitrate parameter in string-form, so we can properly figure
+// out how invalid it is and accurately log invalid values.
+int CalculateBitrate(int max_playback_rate_hz,
+ size_t num_channels,
+ absl::optional<std::string> bitrate_param) {
+ const int default_bitrate =
+ CalculateDefaultBitrate(max_playback_rate_hz, num_channels);
+
+ if (bitrate_param) {
+ const auto bitrate = rtc::StringToNumber<int>(*bitrate_param);
+ if (bitrate) {
+ const int chosen_bitrate =
+ std::max(AudioEncoderOpusConfig::kMinBitrateBps,
+ std::min(*bitrate, AudioEncoderOpusConfig::kMaxBitrateBps));
+ if (bitrate != chosen_bitrate) {
+ RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate " << *bitrate
+ << " clamped to " << chosen_bitrate;
+ }
+ return chosen_bitrate;
+ }
+ RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate \"" << *bitrate_param
+ << "\" replaced by default bitrate " << default_bitrate;
+ }
+
+ return default_bitrate;
+}
+
+} // namespace
+
+std::unique_ptr<AudioEncoder>
+AudioEncoderMultiChannelOpusImpl::MakeAudioEncoder(
+ const AudioEncoderMultiChannelOpusConfig& config,
+ int payload_type) {
+ if (!config.IsOk()) {
+ RTC_DCHECK_NOTREACHED();
+ return nullptr;
+ }
+ return std::make_unique<AudioEncoderMultiChannelOpusImpl>(config,
+ payload_type);
+}
+
+AudioEncoderMultiChannelOpusImpl::AudioEncoderMultiChannelOpusImpl(
+ const AudioEncoderMultiChannelOpusConfig& config,
+ int payload_type)
+ : payload_type_(payload_type), inst_(nullptr) {
+ RTC_DCHECK(0 <= payload_type && payload_type <= 127);
+
+ RTC_CHECK(RecreateEncoderInstance(config));
+}
+
+AudioEncoderMultiChannelOpusImpl::~AudioEncoderMultiChannelOpusImpl() {
+ RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
+}
+
+size_t AudioEncoderMultiChannelOpusImpl::SufficientOutputBufferSize() const {
+ // Calculate the number of bytes we expect the encoder to produce,
+ // then multiply by two to give a wide margin for error.
+ const size_t bytes_per_millisecond =
+ static_cast<size_t>(GetBitrateBps(config_) / (1000 * 8) + 1);
+ const size_t approx_encoded_bytes =
+ Num10msFramesPerPacket() * 10 * bytes_per_millisecond;
+ return 2 * approx_encoded_bytes;
+}
+
+void AudioEncoderMultiChannelOpusImpl::Reset() {
+ RTC_CHECK(RecreateEncoderInstance(config_));
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderMultiChannelOpusImpl::GetFrameLengthRange() const {
+ return {{TimeDelta::Millis(config_.frame_size_ms),
+ TimeDelta::Millis(config_.frame_size_ms)}};
+}
+
+// If the given config is OK, recreate the Opus encoder instance with those
+// settings, save the config, and return true. Otherwise, do nothing and return
+// false.
+bool AudioEncoderMultiChannelOpusImpl::RecreateEncoderInstance(
+ const AudioEncoderMultiChannelOpusConfig& config) {
+ if (!config.IsOk())
+ return false;
+ config_ = config;
+ if (inst_)
+ RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
+ input_buffer_.clear();
+ input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame());
+ RTC_CHECK_EQ(
+ 0, WebRtcOpus_MultistreamEncoderCreate(
+ &inst_, config.num_channels,
+ config.application ==
+ AudioEncoderMultiChannelOpusConfig::ApplicationMode::kVoip
+ ? 0
+ : 1,
+ config.num_streams, config.coupled_streams,
+ config.channel_mapping.data()));
+ const int bitrate = GetBitrateBps(config);
+ RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
+ RTC_LOG(LS_VERBOSE) << "Set Opus bitrate to " << bitrate << " bps.";
+ if (config.fec_enabled) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
+ RTC_LOG(LS_VERBOSE) << "Opus enable FEC";
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
+ RTC_LOG(LS_VERBOSE) << "Opus disable FEC";
+ }
+ RTC_CHECK_EQ(
+ 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz));
+ RTC_LOG(LS_VERBOSE) << "Set Opus playback rate to "
+ << config.max_playback_rate_hz << " hz.";
+
+ // Use the DEFAULT complexity.
+ RTC_CHECK_EQ(
+ 0, WebRtcOpus_SetComplexity(inst_, AudioEncoderOpusConfig().complexity));
+ RTC_LOG(LS_VERBOSE) << "Set Opus coding complexity to "
+ << AudioEncoderOpusConfig().complexity;
+
+ if (config.dtx_enabled) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
+ RTC_LOG(LS_VERBOSE) << "Opus enable DTX";
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
+ RTC_LOG(LS_VERBOSE) << "Opus disable DTX";
+ }
+
+ if (config.cbr_enabled) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableCbr(inst_));
+ RTC_LOG(LS_VERBOSE) << "Opus enable CBR";
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableCbr(inst_));
+ RTC_LOG(LS_VERBOSE) << "Opus disable CBR";
+ }
+ num_channels_to_encode_ = NumChannels();
+ next_frame_length_ms_ = config_.frame_size_ms;
+ RTC_LOG(LS_VERBOSE) << "Set Opus frame length to " << config_.frame_size_ms
+ << " ms";
+ return true;
+}
+
+absl::optional<AudioEncoderMultiChannelOpusConfig>
+AudioEncoderMultiChannelOpusImpl::SdpToConfig(const SdpAudioFormat& format) {
+ if (!absl::EqualsIgnoreCase(format.name, "multiopus") ||
+ format.clockrate_hz != 48000) {
+ return absl::nullopt;
+ }
+
+ AudioEncoderMultiChannelOpusConfig config;
+ config.num_channels = format.num_channels;
+ config.frame_size_ms = GetFrameSizeMs(format);
+ config.max_playback_rate_hz = GetMaxPlaybackRate(format);
+ config.fec_enabled = (GetFormatParameter(format, "useinbandfec") == "1");
+ config.dtx_enabled = (GetFormatParameter(format, "usedtx") == "1");
+ config.cbr_enabled = (GetFormatParameter(format, "cbr") == "1");
+ config.bitrate_bps =
+ CalculateBitrate(config.max_playback_rate_hz, config.num_channels,
+ GetFormatParameter(format, "maxaveragebitrate"));
+ config.application =
+ config.num_channels == 1
+ ? AudioEncoderMultiChannelOpusConfig::ApplicationMode::kVoip
+ : AudioEncoderMultiChannelOpusConfig::ApplicationMode::kAudio;
+
+ config.supported_frame_lengths_ms.clear();
+ std::copy(std::begin(kOpusSupportedFrameLengths),
+ std::end(kOpusSupportedFrameLengths),
+ std::back_inserter(config.supported_frame_lengths_ms));
+
+ auto num_streams = GetFormatParameter<int>(format, "num_streams");
+ if (!num_streams.has_value()) {
+ return absl::nullopt;
+ }
+ config.num_streams = *num_streams;
+
+ auto coupled_streams = GetFormatParameter<int>(format, "coupled_streams");
+ if (!coupled_streams.has_value()) {
+ return absl::nullopt;
+ }
+ config.coupled_streams = *coupled_streams;
+
+ auto channel_mapping =
+ GetFormatParameter<std::vector<unsigned char>>(format, "channel_mapping");
+ if (!channel_mapping.has_value()) {
+ return absl::nullopt;
+ }
+ config.channel_mapping = *channel_mapping;
+
+ if (!config.IsOk()) {
+ return absl::nullopt;
+ }
+ return config;
+}
+
+AudioCodecInfo AudioEncoderMultiChannelOpusImpl::QueryAudioEncoder(
+ const AudioEncoderMultiChannelOpusConfig& config) {
+ RTC_DCHECK(config.IsOk());
+ AudioCodecInfo info(48000, config.num_channels, config.bitrate_bps,
+ AudioEncoderOpusConfig::kMinBitrateBps,
+ AudioEncoderOpusConfig::kMaxBitrateBps);
+ info.allow_comfort_noise = false;
+ info.supports_network_adaption = false;
+ return info;
+}
+
+size_t AudioEncoderMultiChannelOpusImpl::Num10msFramesPerPacket() const {
+ return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10));
+}
+size_t AudioEncoderMultiChannelOpusImpl::SamplesPer10msFrame() const {
+ return rtc::CheckedDivExact(48000, 100) * config_.num_channels;
+}
+int AudioEncoderMultiChannelOpusImpl::SampleRateHz() const {
+ return 48000;
+}
+size_t AudioEncoderMultiChannelOpusImpl::NumChannels() const {
+ return config_.num_channels;
+}
+size_t AudioEncoderMultiChannelOpusImpl::Num10MsFramesInNextPacket() const {
+ return Num10msFramesPerPacket();
+}
+size_t AudioEncoderMultiChannelOpusImpl::Max10MsFramesInAPacket() const {
+ return Num10msFramesPerPacket();
+}
+int AudioEncoderMultiChannelOpusImpl::GetTargetBitrate() const {
+ return GetBitrateBps(config_);
+}
+
+AudioEncoder::EncodedInfo AudioEncoderMultiChannelOpusImpl::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ if (input_buffer_.empty())
+ first_timestamp_in_buffer_ = rtp_timestamp;
+
+ input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend());
+ if (input_buffer_.size() <
+ (Num10msFramesPerPacket() * SamplesPer10msFrame())) {
+ return EncodedInfo();
+ }
+ RTC_CHECK_EQ(input_buffer_.size(),
+ Num10msFramesPerPacket() * SamplesPer10msFrame());
+
+ const size_t max_encoded_bytes = SufficientOutputBufferSize();
+ EncodedInfo info;
+ info.encoded_bytes = encoded->AppendData(
+ max_encoded_bytes, [&](rtc::ArrayView<uint8_t> encoded) {
+ int status = WebRtcOpus_Encode(
+ inst_, &input_buffer_[0],
+ rtc::CheckedDivExact(input_buffer_.size(), config_.num_channels),
+ rtc::saturated_cast<int16_t>(max_encoded_bytes), encoded.data());
+
+ RTC_CHECK_GE(status, 0); // Fails only if fed invalid data.
+
+ return static_cast<size_t>(status);
+ });
+ input_buffer_.clear();
+
+ // Will use new packet size for next encoding.
+ config_.frame_size_ms = next_frame_length_ms_;
+
+ info.encoded_timestamp = first_timestamp_in_buffer_;
+ info.payload_type = payload_type_;
+ info.send_even_if_empty = true; // Allows Opus to send empty packets.
+
+ info.speech = true;
+ info.encoder_type = CodecType::kOther;
+
+ return info;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.h
new file mode 100644
index 0000000000..8a7210515c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_IMPL_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_IMPL_H_
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/audio_codecs/audio_format.h"
+#include "api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.h"
+#include "api/units/time_delta.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+
+namespace webrtc {
+
+class RtcEventLog;
+
+class AudioEncoderMultiChannelOpusImpl final : public AudioEncoder {
+ public:
+ AudioEncoderMultiChannelOpusImpl(
+ const AudioEncoderMultiChannelOpusConfig& config,
+ int payload_type);
+ ~AudioEncoderMultiChannelOpusImpl() override;
+
+ AudioEncoderMultiChannelOpusImpl(const AudioEncoderMultiChannelOpusImpl&) =
+ delete;
+ AudioEncoderMultiChannelOpusImpl& operator=(
+ const AudioEncoderMultiChannelOpusImpl&) = delete;
+
+ // Static interface for use by BuiltinAudioEncoderFactory.
+ static constexpr const char* GetPayloadName() { return "multiopus"; }
+ static absl::optional<AudioCodecInfo> QueryAudioEncoder(
+ const SdpAudioFormat& format);
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+
+ void Reset() override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+
+ protected:
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+
+ private:
+ static absl::optional<AudioEncoderMultiChannelOpusConfig> SdpToConfig(
+ const SdpAudioFormat& format);
+ static AudioCodecInfo QueryAudioEncoder(
+ const AudioEncoderMultiChannelOpusConfig& config);
+ static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
+ const AudioEncoderMultiChannelOpusConfig&,
+ int payload_type);
+
+ size_t Num10msFramesPerPacket() const;
+ size_t SamplesPer10msFrame() const;
+ size_t SufficientOutputBufferSize() const;
+ bool RecreateEncoderInstance(
+ const AudioEncoderMultiChannelOpusConfig& config);
+ void SetFrameLength(int frame_length_ms);
+ void SetNumChannelsToEncode(size_t num_channels_to_encode);
+ void SetProjectedPacketLossRate(float fraction);
+
+ AudioEncoderMultiChannelOpusConfig config_;
+ const int payload_type_;
+ std::vector<int16_t> input_buffer_;
+ OpusEncInst* inst_;
+ uint32_t first_timestamp_in_buffer_;
+ size_t num_channels_to_encode_;
+ int next_frame_length_ms_;
+
+ friend struct AudioEncoderMultiChannelOpus;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_IMPL_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_unittest.cc
new file mode 100644
index 0000000000..92f6f2c169
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_unittest.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h"
+
+#include "test/gmock.h"
+
+namespace webrtc {
+using ::testing::NiceMock;
+using ::testing::Return;
+
+namespace {
+constexpr int kOpusPayloadType = 120;
+} // namespace
+
+TEST(AudioEncoderMultiOpusTest, CheckConfigValidity) {
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 2,
+ {{"channel_mapping", "3,0"},
+ {"coupled_streams", "1"},
+ {"num_streams", "2"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ // Maps input channel 0 to coded channel 3, which doesn't exist.
+ EXPECT_FALSE(encoder_config.has_value());
+ }
+
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 2,
+ {{"channel_mapping", "0"},
+ {"coupled_streams", "1"},
+ {"num_streams", "2"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ // The mapping is too short.
+ EXPECT_FALSE(encoder_config.has_value());
+ }
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 3,
+ {{"channel_mapping", "0,0,0"},
+ {"coupled_streams", "0"},
+ {"num_streams", "1"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ // Coded channel 0 comes from both input channels 0, 1 and 2.
+ EXPECT_FALSE(encoder_config.has_value());
+ }
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 3,
+ {{"channel_mapping", "0,255,255"},
+ {"coupled_streams", "0"},
+ {"num_streams", "1"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+ ASSERT_TRUE(encoder_config.has_value());
+
+ // This is fine, because channels 1, 2 are set to be ignored.
+ EXPECT_TRUE(encoder_config->IsOk());
+ }
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 3,
+ {{"channel_mapping", "0,255,255"},
+ {"coupled_streams", "0"},
+ {"num_streams", "2"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+
+ // This is NOT fine, because channels nothing says how coded channel 1
+ // should be coded.
+ EXPECT_FALSE(encoder_config.has_value());
+ }
+}
+
+TEST(AudioEncoderMultiOpusTest, ConfigValuesAreParsedCorrectly) {
+ SdpAudioFormat sdp_format({"multiopus",
+ 48000,
+ 6,
+ {{"minptime", "10"},
+ {"useinbandfec", "1"},
+ {"channel_mapping", "0,4,1,2,3,5"},
+ {"num_streams", "4"},
+ {"coupled_streams", "2"}}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+ ASSERT_TRUE(encoder_config.has_value());
+
+ EXPECT_EQ(encoder_config->coupled_streams, 2);
+ EXPECT_EQ(encoder_config->num_streams, 4);
+ EXPECT_THAT(
+ encoder_config->channel_mapping,
+ testing::ContainerEq(std::vector<unsigned char>({0, 4, 1, 2, 3, 5})));
+}
+
+TEST(AudioEncoderMultiOpusTest, CreateFromValidConfig) {
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 3,
+ {{"channel_mapping", "0,255,255"},
+ {"coupled_streams", "0"},
+ {"num_streams", "2"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+ ASSERT_FALSE(encoder_config.has_value());
+ }
+ {
+ const SdpAudioFormat sdp_format("multiopus", 48000, 3,
+ {{"channel_mapping", "1,255,0"},
+ {"coupled_streams", "1"},
+ {"num_streams", "1"}});
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
+ ASSERT_TRUE(encoder_config.has_value());
+
+ EXPECT_THAT(encoder_config->channel_mapping,
+ testing::ContainerEq(std::vector<unsigned char>({1, 255, 0})));
+
+ EXPECT_TRUE(encoder_config->IsOk());
+
+ const std::unique_ptr<AudioEncoder> opus_encoder =
+ AudioEncoderMultiChannelOpus::MakeAudioEncoder(*encoder_config,
+ kOpusPayloadType);
+
+ // Creating an encoder from a valid config should work.
+ EXPECT_TRUE(opus_encoder);
+ }
+}
+
+TEST(AudioEncoderMultiOpusTest, AdvertisedCodecsCanBeCreated) {
+ std::vector<AudioCodecSpec> specs;
+ AudioEncoderMultiChannelOpus::AppendSupportedEncoders(&specs);
+
+ EXPECT_FALSE(specs.empty());
+
+ for (const AudioCodecSpec& spec : specs) {
+ const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
+ AudioEncoderMultiChannelOpus::SdpToConfig(spec.format);
+ ASSERT_TRUE(encoder_config.has_value());
+
+ const std::unique_ptr<AudioEncoder> opus_encoder =
+ AudioEncoderMultiChannelOpus::MakeAudioEncoder(*encoder_config,
+ kOpusPayloadType);
+
+ EXPECT_TRUE(opus_encoder);
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
new file mode 100644
index 0000000000..c9b1aefe69
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
+#include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
+#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "rtc_base/arraysize.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/exp_filter.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/numerics/safe_minmax.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/string_to_number.h"
+#include "rtc_base/time_utils.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+namespace {
+
+// Codec parameters for Opus.
+// draft-spittka-payload-rtp-opus-03
+
+// Recommended bitrates:
+// 8-12 kb/s for NB speech,
+// 16-20 kb/s for WB speech,
+// 28-40 kb/s for FB speech,
+// 48-64 kb/s for FB mono music, and
+// 64-128 kb/s for FB stereo music.
+// The current implementation applies the following values to mono signals,
+// and multiplies them by 2 for stereo.
+constexpr int kOpusBitrateNbBps = 12000;
+constexpr int kOpusBitrateWbBps = 20000;
+constexpr int kOpusBitrateFbBps = 32000;
+
+constexpr int kRtpTimestampRateHz = 48000;
+constexpr int kDefaultMaxPlaybackRate = 48000;
+
+// These two lists must be sorted from low to high
+#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
+constexpr int kANASupportedFrameLengths[] = {20, 40, 60, 120};
+constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60, 120};
+#else
+constexpr int kANASupportedFrameLengths[] = {20, 40, 60};
+constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60};
+#endif
+
+// PacketLossFractionSmoother uses an exponential filter with a time constant
+// of -1.0 / ln(0.9999) = 10000 ms.
+constexpr float kAlphaForPacketLossFractionSmoother = 0.9999f;
+constexpr float kMaxPacketLossFraction = 0.2f;
+
+int CalculateDefaultBitrate(int max_playback_rate, size_t num_channels) {
+ const int bitrate = [&] {
+ if (max_playback_rate <= 8000) {
+ return kOpusBitrateNbBps * rtc::dchecked_cast<int>(num_channels);
+ } else if (max_playback_rate <= 16000) {
+ return kOpusBitrateWbBps * rtc::dchecked_cast<int>(num_channels);
+ } else {
+ return kOpusBitrateFbBps * rtc::dchecked_cast<int>(num_channels);
+ }
+ }();
+ RTC_DCHECK_GE(bitrate, AudioEncoderOpusConfig::kMinBitrateBps);
+ RTC_DCHECK_LE(bitrate, AudioEncoderOpusConfig::kMaxBitrateBps);
+ return bitrate;
+}
+
+// Get the maxaveragebitrate parameter in string-form, so we can properly figure
+// out how invalid it is and accurately log invalid values.
+int CalculateBitrate(int max_playback_rate_hz,
+ size_t num_channels,
+ absl::optional<std::string> bitrate_param) {
+ const int default_bitrate =
+ CalculateDefaultBitrate(max_playback_rate_hz, num_channels);
+
+ if (bitrate_param) {
+ const auto bitrate = rtc::StringToNumber<int>(*bitrate_param);
+ if (bitrate) {
+ const int chosen_bitrate =
+ std::max(AudioEncoderOpusConfig::kMinBitrateBps,
+ std::min(*bitrate, AudioEncoderOpusConfig::kMaxBitrateBps));
+ if (bitrate != chosen_bitrate) {
+ RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate " << *bitrate
+ << " clamped to " << chosen_bitrate;
+ }
+ return chosen_bitrate;
+ }
+ RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate \"" << *bitrate_param
+ << "\" replaced by default bitrate " << default_bitrate;
+ }
+
+ return default_bitrate;
+}
+
+int GetChannelCount(const SdpAudioFormat& format) {
+ const auto param = GetFormatParameter(format, "stereo");
+ if (param == "1") {
+ return 2;
+ } else {
+ return 1;
+ }
+}
+
+int GetMaxPlaybackRate(const SdpAudioFormat& format) {
+ const auto param = GetFormatParameter<int>(format, "maxplaybackrate");
+ if (param && *param >= 8000) {
+ return std::min(*param, kDefaultMaxPlaybackRate);
+ }
+ return kDefaultMaxPlaybackRate;
+}
+
+int GetFrameSizeMs(const SdpAudioFormat& format) {
+ const auto ptime = GetFormatParameter<int>(format, "ptime");
+ if (ptime) {
+ // Pick the next highest supported frame length from
+ // kOpusSupportedFrameLengths.
+ for (const int supported_frame_length : kOpusSupportedFrameLengths) {
+ if (supported_frame_length >= *ptime) {
+ return supported_frame_length;
+ }
+ }
+ // If none was found, return the largest supported frame length.
+ return *(std::end(kOpusSupportedFrameLengths) - 1);
+ }
+
+ return AudioEncoderOpusConfig::kDefaultFrameSizeMs;
+}
+
+void FindSupportedFrameLengths(int min_frame_length_ms,
+ int max_frame_length_ms,
+ std::vector<int>* out) {
+ out->clear();
+ std::copy_if(std::begin(kANASupportedFrameLengths),
+ std::end(kANASupportedFrameLengths), std::back_inserter(*out),
+ [&](int frame_length_ms) {
+ return frame_length_ms >= min_frame_length_ms &&
+ frame_length_ms <= max_frame_length_ms;
+ });
+ RTC_DCHECK(std::is_sorted(out->begin(), out->end()));
+}
+
+int GetBitrateBps(const AudioEncoderOpusConfig& config) {
+ RTC_DCHECK(config.IsOk());
+ return *config.bitrate_bps;
+}
+
+std::vector<float> GetBitrateMultipliers() {
+ constexpr char kBitrateMultipliersName[] =
+ "WebRTC-Audio-OpusBitrateMultipliers";
+ const bool use_bitrate_multipliers =
+ webrtc::field_trial::IsEnabled(kBitrateMultipliersName);
+ if (use_bitrate_multipliers) {
+ const std::string field_trial_string =
+ webrtc::field_trial::FindFullName(kBitrateMultipliersName);
+ std::vector<std::string> pieces;
+ rtc::tokenize(field_trial_string, '-', &pieces);
+ if (pieces.size() < 2 || pieces[0] != "Enabled") {
+ RTC_LOG(LS_WARNING) << "Invalid parameters for "
+ << kBitrateMultipliersName
+ << ", not using custom values.";
+ return std::vector<float>();
+ }
+ std::vector<float> multipliers(pieces.size() - 1);
+ for (size_t i = 1; i < pieces.size(); i++) {
+ if (!rtc::FromString(pieces[i], &multipliers[i - 1])) {
+ RTC_LOG(LS_WARNING)
+ << "Invalid parameters for " << kBitrateMultipliersName
+ << ", not using custom values.";
+ return std::vector<float>();
+ }
+ }
+ RTC_LOG(LS_INFO) << "Using custom bitrate multipliers: "
+ << field_trial_string;
+ return multipliers;
+ }
+ return std::vector<float>();
+}
+
+int GetMultipliedBitrate(int bitrate, const std::vector<float>& multipliers) {
+ // The multipliers are valid from 5 kbps.
+ const size_t bitrate_kbps = static_cast<size_t>(bitrate / 1000);
+ if (bitrate_kbps < 5 || bitrate_kbps >= multipliers.size() + 5) {
+ return bitrate;
+ }
+ return static_cast<int>(multipliers[bitrate_kbps - 5] * bitrate);
+}
+} // namespace
+
+void AudioEncoderOpusImpl::AppendSupportedEncoders(
+ std::vector<AudioCodecSpec>* specs) {
+ const SdpAudioFormat fmt = {"opus",
+ kRtpTimestampRateHz,
+ 2,
+ {{"minptime", "10"}, {"useinbandfec", "1"}}};
+ const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
+ specs->push_back({fmt, info});
+}
+
+AudioCodecInfo AudioEncoderOpusImpl::QueryAudioEncoder(
+ const AudioEncoderOpusConfig& config) {
+ RTC_DCHECK(config.IsOk());
+ AudioCodecInfo info(config.sample_rate_hz, config.num_channels,
+ *config.bitrate_bps,
+ AudioEncoderOpusConfig::kMinBitrateBps,
+ AudioEncoderOpusConfig::kMaxBitrateBps);
+ info.allow_comfort_noise = false;
+ info.supports_network_adaption = true;
+ return info;
+}
+
+std::unique_ptr<AudioEncoder> AudioEncoderOpusImpl::MakeAudioEncoder(
+ const AudioEncoderOpusConfig& config,
+ int payload_type) {
+ if (!config.IsOk()) {
+ RTC_DCHECK_NOTREACHED();
+ return nullptr;
+ }
+ return std::make_unique<AudioEncoderOpusImpl>(config, payload_type);
+}
+
+absl::optional<AudioEncoderOpusConfig> AudioEncoderOpusImpl::SdpToConfig(
+ const SdpAudioFormat& format) {
+ if (!absl::EqualsIgnoreCase(format.name, "opus") ||
+ format.clockrate_hz != kRtpTimestampRateHz) {
+ return absl::nullopt;
+ }
+
+ AudioEncoderOpusConfig config;
+ config.num_channels = GetChannelCount(format);
+ config.frame_size_ms = GetFrameSizeMs(format);
+ config.max_playback_rate_hz = GetMaxPlaybackRate(format);
+ config.fec_enabled = (GetFormatParameter(format, "useinbandfec") == "1");
+ config.dtx_enabled = (GetFormatParameter(format, "usedtx") == "1");
+ config.cbr_enabled = (GetFormatParameter(format, "cbr") == "1");
+ config.bitrate_bps =
+ CalculateBitrate(config.max_playback_rate_hz, config.num_channels,
+ GetFormatParameter(format, "maxaveragebitrate"));
+ config.application = config.num_channels == 1
+ ? AudioEncoderOpusConfig::ApplicationMode::kVoip
+ : AudioEncoderOpusConfig::ApplicationMode::kAudio;
+
+ constexpr int kMinANAFrameLength = kANASupportedFrameLengths[0];
+ constexpr int kMaxANAFrameLength =
+ kANASupportedFrameLengths[arraysize(kANASupportedFrameLengths) - 1];
+
+ // For now, minptime and maxptime are only used with ANA. If ptime is outside
+ // of this range, it will get adjusted once ANA takes hold. Ideally, we'd know
+ // if ANA was to be used when setting up the config, and adjust accordingly.
+ const int min_frame_length_ms =
+ GetFormatParameter<int>(format, "minptime").value_or(kMinANAFrameLength);
+ const int max_frame_length_ms =
+ GetFormatParameter<int>(format, "maxptime").value_or(kMaxANAFrameLength);
+
+ FindSupportedFrameLengths(min_frame_length_ms, max_frame_length_ms,
+ &config.supported_frame_lengths_ms);
+ if (!config.IsOk()) {
+ RTC_DCHECK_NOTREACHED();
+ return absl::nullopt;
+ }
+ return config;
+}
+
+absl::optional<int> AudioEncoderOpusImpl::GetNewComplexity(
+ const AudioEncoderOpusConfig& config) {
+ RTC_DCHECK(config.IsOk());
+ const int bitrate_bps = GetBitrateBps(config);
+ if (bitrate_bps >= config.complexity_threshold_bps -
+ config.complexity_threshold_window_bps &&
+ bitrate_bps <= config.complexity_threshold_bps +
+ config.complexity_threshold_window_bps) {
+ // Within the hysteresis window; make no change.
+ return absl::nullopt;
+ } else {
+ return bitrate_bps <= config.complexity_threshold_bps
+ ? config.low_rate_complexity
+ : config.complexity;
+ }
+}
+
+absl::optional<int> AudioEncoderOpusImpl::GetNewBandwidth(
+ const AudioEncoderOpusConfig& config,
+ OpusEncInst* inst) {
+ constexpr int kMinWidebandBitrate = 8000;
+ constexpr int kMaxNarrowbandBitrate = 9000;
+ constexpr int kAutomaticThreshold = 11000;
+ RTC_DCHECK(config.IsOk());
+ const int bitrate = GetBitrateBps(config);
+ if (bitrate > kAutomaticThreshold) {
+ return absl::optional<int>(OPUS_AUTO);
+ }
+ const int bandwidth = WebRtcOpus_GetBandwidth(inst);
+ RTC_DCHECK_GE(bandwidth, 0);
+ if (bitrate > kMaxNarrowbandBitrate && bandwidth < OPUS_BANDWIDTH_WIDEBAND) {
+ return absl::optional<int>(OPUS_BANDWIDTH_WIDEBAND);
+ } else if (bitrate < kMinWidebandBitrate &&
+ bandwidth > OPUS_BANDWIDTH_NARROWBAND) {
+ return absl::optional<int>(OPUS_BANDWIDTH_NARROWBAND);
+ }
+ return absl::optional<int>();
+}
+
+class AudioEncoderOpusImpl::PacketLossFractionSmoother {
+ public:
+ explicit PacketLossFractionSmoother()
+ : last_sample_time_ms_(rtc::TimeMillis()),
+ smoother_(kAlphaForPacketLossFractionSmoother) {}
+
+ // Gets the smoothed packet loss fraction.
+ float GetAverage() const {
+ float value = smoother_.filtered();
+ return (value == rtc::ExpFilter::kValueUndefined) ? 0.0f : value;
+ }
+
+ // Add new observation to the packet loss fraction smoother.
+ void AddSample(float packet_loss_fraction) {
+ int64_t now_ms = rtc::TimeMillis();
+ smoother_.Apply(static_cast<float>(now_ms - last_sample_time_ms_),
+ packet_loss_fraction);
+ last_sample_time_ms_ = now_ms;
+ }
+
+ private:
+ int64_t last_sample_time_ms_;
+
+ // An exponential filter is used to smooth the packet loss fraction.
+ rtc::ExpFilter smoother_;
+};
+
+AudioEncoderOpusImpl::AudioEncoderOpusImpl(const AudioEncoderOpusConfig& config,
+ int payload_type)
+ : AudioEncoderOpusImpl(
+ config,
+ payload_type,
+ [this](absl::string_view config_string, RtcEventLog* event_log) {
+ return DefaultAudioNetworkAdaptorCreator(config_string, event_log);
+ },
+ // We choose 5sec as initial time constant due to empirical data.
+ std::make_unique<SmoothingFilterImpl>(5000)) {}
+
+AudioEncoderOpusImpl::AudioEncoderOpusImpl(
+ const AudioEncoderOpusConfig& config,
+ int payload_type,
+ const AudioNetworkAdaptorCreator& audio_network_adaptor_creator,
+ std::unique_ptr<SmoothingFilter> bitrate_smoother)
+ : payload_type_(payload_type),
+ send_side_bwe_with_overhead_(
+ !webrtc::field_trial::IsDisabled("WebRTC-SendSideBwe-WithOverhead")),
+ use_stable_target_for_adaptation_(!webrtc::field_trial::IsDisabled(
+ "WebRTC-Audio-StableTargetAdaptation")),
+ adjust_bandwidth_(
+ webrtc::field_trial::IsEnabled("WebRTC-AdjustOpusBandwidth")),
+ bitrate_changed_(true),
+ bitrate_multipliers_(GetBitrateMultipliers()),
+ packet_loss_rate_(0.0),
+ inst_(nullptr),
+ packet_loss_fraction_smoother_(new PacketLossFractionSmoother()),
+ audio_network_adaptor_creator_(audio_network_adaptor_creator),
+ bitrate_smoother_(std::move(bitrate_smoother)),
+ consecutive_dtx_frames_(0) {
+ RTC_DCHECK(0 <= payload_type && payload_type <= 127);
+
+ // Sanity check of the redundant payload type field that we want to get rid
+ // of. See https://bugs.chromium.org/p/webrtc/issues/detail?id=7847
+ RTC_CHECK(config.payload_type == -1 || config.payload_type == payload_type);
+
+ RTC_CHECK(RecreateEncoderInstance(config));
+ SetProjectedPacketLossRate(packet_loss_rate_);
+}
+
+AudioEncoderOpusImpl::AudioEncoderOpusImpl(int payload_type,
+ const SdpAudioFormat& format)
+ : AudioEncoderOpusImpl(*SdpToConfig(format), payload_type) {}
+
+AudioEncoderOpusImpl::~AudioEncoderOpusImpl() {
+ RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
+}
+
+int AudioEncoderOpusImpl::SampleRateHz() const {
+ return config_.sample_rate_hz;
+}
+
+size_t AudioEncoderOpusImpl::NumChannels() const {
+ return config_.num_channels;
+}
+
+int AudioEncoderOpusImpl::RtpTimestampRateHz() const {
+ return kRtpTimestampRateHz;
+}
+
+size_t AudioEncoderOpusImpl::Num10MsFramesInNextPacket() const {
+ return Num10msFramesPerPacket();
+}
+
+size_t AudioEncoderOpusImpl::Max10MsFramesInAPacket() const {
+ return Num10msFramesPerPacket();
+}
+
+int AudioEncoderOpusImpl::GetTargetBitrate() const {
+ return GetBitrateBps(config_);
+}
+
+void AudioEncoderOpusImpl::Reset() {
+ RTC_CHECK(RecreateEncoderInstance(config_));
+}
+
+bool AudioEncoderOpusImpl::SetFec(bool enable) {
+ if (enable) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
+ }
+ config_.fec_enabled = enable;
+ return true;
+}
+
+bool AudioEncoderOpusImpl::SetDtx(bool enable) {
+ if (enable) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
+ }
+ config_.dtx_enabled = enable;
+ return true;
+}
+
+bool AudioEncoderOpusImpl::GetDtx() const {
+ return config_.dtx_enabled;
+}
+
+bool AudioEncoderOpusImpl::SetApplication(Application application) {
+ auto conf = config_;
+ switch (application) {
+ case Application::kSpeech:
+ conf.application = AudioEncoderOpusConfig::ApplicationMode::kVoip;
+ break;
+ case Application::kAudio:
+ conf.application = AudioEncoderOpusConfig::ApplicationMode::kAudio;
+ break;
+ }
+ return RecreateEncoderInstance(conf);
+}
+
+void AudioEncoderOpusImpl::SetMaxPlaybackRate(int frequency_hz) {
+ auto conf = config_;
+ conf.max_playback_rate_hz = frequency_hz;
+ RTC_CHECK(RecreateEncoderInstance(conf));
+}
+
+bool AudioEncoderOpusImpl::EnableAudioNetworkAdaptor(
+ const std::string& config_string,
+ RtcEventLog* event_log) {
+ audio_network_adaptor_ =
+ audio_network_adaptor_creator_(config_string, event_log);
+ return audio_network_adaptor_.get() != nullptr;
+}
+
+void AudioEncoderOpusImpl::DisableAudioNetworkAdaptor() {
+ audio_network_adaptor_.reset(nullptr);
+}
+
+void AudioEncoderOpusImpl::OnReceivedUplinkPacketLossFraction(
+ float uplink_packet_loss_fraction) {
+ if (audio_network_adaptor_) {
+ audio_network_adaptor_->SetUplinkPacketLossFraction(
+ uplink_packet_loss_fraction);
+ ApplyAudioNetworkAdaptor();
+ }
+ packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction);
+ float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage();
+ SetProjectedPacketLossRate(average_fraction_loss);
+}
+
+void AudioEncoderOpusImpl::OnReceivedTargetAudioBitrate(
+ int target_audio_bitrate_bps) {
+ SetTargetBitrate(target_audio_bitrate_bps);
+}
+
+void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms,
+ absl::optional<int64_t> stable_target_bitrate_bps) {
+ if (audio_network_adaptor_) {
+ audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
+ if (use_stable_target_for_adaptation_) {
+ if (stable_target_bitrate_bps)
+ audio_network_adaptor_->SetUplinkBandwidth(*stable_target_bitrate_bps);
+ } else {
+ // We give smoothed bitrate allocation to audio network adaptor as
+ // the uplink bandwidth.
+ // The BWE spikes should not affect the bitrate smoother more than 25%.
+ // To simplify the calculations we use a step response as input signal.
+ // The step response of an exponential filter is
+ // u(t) = 1 - e^(-t / time_constant).
+ // In order to limit the affect of a BWE spike within 25% of its value
+ // before
+ // the next BWE update, we would choose a time constant that fulfills
+ // 1 - e^(-bwe_period_ms / time_constant) < 0.25
+ // Then 4 * bwe_period_ms is a good choice.
+ if (bwe_period_ms)
+ bitrate_smoother_->SetTimeConstantMs(*bwe_period_ms * 4);
+ bitrate_smoother_->AddSample(target_audio_bitrate_bps);
+ }
+
+ ApplyAudioNetworkAdaptor();
+ } else if (send_side_bwe_with_overhead_) {
+ if (!overhead_bytes_per_packet_) {
+ RTC_LOG(LS_INFO)
+ << "AudioEncoderOpusImpl: Overhead unknown, target audio bitrate "
+ << target_audio_bitrate_bps << " bps is ignored.";
+ return;
+ }
+ const int overhead_bps = static_cast<int>(
+ *overhead_bytes_per_packet_ * 8 * 100 / Num10MsFramesInNextPacket());
+ SetTargetBitrate(
+ std::min(AudioEncoderOpusConfig::kMaxBitrateBps,
+ std::max(AudioEncoderOpusConfig::kMinBitrateBps,
+ target_audio_bitrate_bps - overhead_bps)));
+ } else {
+ SetTargetBitrate(target_audio_bitrate_bps);
+ }
+}
+void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) {
+ OnReceivedUplinkBandwidth(target_audio_bitrate_bps, bwe_period_ms,
+ absl::nullopt);
+}
+
+void AudioEncoderOpusImpl::OnReceivedUplinkAllocation(
+ BitrateAllocationUpdate update) {
+ OnReceivedUplinkBandwidth(update.target_bitrate.bps(), update.bwe_period.ms(),
+ update.stable_target_bitrate.bps());
+}
+
+void AudioEncoderOpusImpl::OnReceivedRtt(int rtt_ms) {
+ if (!audio_network_adaptor_)
+ return;
+ audio_network_adaptor_->SetRtt(rtt_ms);
+ ApplyAudioNetworkAdaptor();
+}
+
+void AudioEncoderOpusImpl::OnReceivedOverhead(
+ size_t overhead_bytes_per_packet) {
+ if (audio_network_adaptor_) {
+ audio_network_adaptor_->SetOverhead(overhead_bytes_per_packet);
+ ApplyAudioNetworkAdaptor();
+ } else {
+ overhead_bytes_per_packet_ = overhead_bytes_per_packet;
+ }
+}
+
+void AudioEncoderOpusImpl::SetReceiverFrameLengthRange(
+ int min_frame_length_ms,
+ int max_frame_length_ms) {
+ // Ensure that `SetReceiverFrameLengthRange` is called before
+ // `EnableAudioNetworkAdaptor`, otherwise we need to recreate
+ // `audio_network_adaptor_`, which is not a needed use case.
+ RTC_DCHECK(!audio_network_adaptor_);
+ FindSupportedFrameLengths(min_frame_length_ms, max_frame_length_ms,
+ &config_.supported_frame_lengths_ms);
+}
+
+AudioEncoder::EncodedInfo AudioEncoderOpusImpl::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ MaybeUpdateUplinkBandwidth();
+
+ if (input_buffer_.empty())
+ first_timestamp_in_buffer_ = rtp_timestamp;
+
+ input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend());
+ if (input_buffer_.size() <
+ (Num10msFramesPerPacket() * SamplesPer10msFrame())) {
+ return EncodedInfo();
+ }
+ RTC_CHECK_EQ(input_buffer_.size(),
+ Num10msFramesPerPacket() * SamplesPer10msFrame());
+
+ const size_t max_encoded_bytes = SufficientOutputBufferSize();
+ EncodedInfo info;
+ info.encoded_bytes = encoded->AppendData(
+ max_encoded_bytes, [&](rtc::ArrayView<uint8_t> encoded) {
+ int status = WebRtcOpus_Encode(
+ inst_, &input_buffer_[0],
+ rtc::CheckedDivExact(input_buffer_.size(), config_.num_channels),
+ rtc::saturated_cast<int16_t>(max_encoded_bytes), encoded.data());
+
+ RTC_CHECK_GE(status, 0); // Fails only if fed invalid data.
+
+ return static_cast<size_t>(status);
+ });
+ input_buffer_.clear();
+
+ bool dtx_frame = (info.encoded_bytes <= 2);
+
+ // Will use new packet size for next encoding.
+ config_.frame_size_ms = next_frame_length_ms_;
+
+ if (adjust_bandwidth_ && bitrate_changed_) {
+ const auto bandwidth = GetNewBandwidth(config_, inst_);
+ if (bandwidth) {
+ RTC_CHECK_EQ(0, WebRtcOpus_SetBandwidth(inst_, *bandwidth));
+ }
+ bitrate_changed_ = false;
+ }
+
+ info.encoded_timestamp = first_timestamp_in_buffer_;
+ info.payload_type = payload_type_;
+ info.send_even_if_empty = true; // Allows Opus to send empty packets.
+ // After 20 DTX frames (MAX_CONSECUTIVE_DTX) Opus will send a frame
+ // coding the background noise. Avoid flagging this frame as speech
+ // (even though there is a probability of the frame being speech).
+ info.speech = !dtx_frame && (consecutive_dtx_frames_ != 20);
+ info.encoder_type = CodecType::kOpus;
+
+ // Increase or reset DTX counter.
+ consecutive_dtx_frames_ = (dtx_frame) ? (consecutive_dtx_frames_ + 1) : (0);
+
+ return info;
+}
+
+size_t AudioEncoderOpusImpl::Num10msFramesPerPacket() const {
+ return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10));
+}
+
+size_t AudioEncoderOpusImpl::SamplesPer10msFrame() const {
+ return rtc::CheckedDivExact(config_.sample_rate_hz, 100) *
+ config_.num_channels;
+}
+
+size_t AudioEncoderOpusImpl::SufficientOutputBufferSize() const {
+ // Calculate the number of bytes we expect the encoder to produce,
+ // then multiply by two to give a wide margin for error.
+ const size_t bytes_per_millisecond =
+ static_cast<size_t>(GetBitrateBps(config_) / (1000 * 8) + 1);
+ const size_t approx_encoded_bytes =
+ Num10msFramesPerPacket() * 10 * bytes_per_millisecond;
+ return 2 * approx_encoded_bytes;
+}
+
+// If the given config is OK, recreate the Opus encoder instance with those
+// settings, save the config, and return true. Otherwise, do nothing and return
+// false.
+bool AudioEncoderOpusImpl::RecreateEncoderInstance(
+ const AudioEncoderOpusConfig& config) {
+ if (!config.IsOk())
+ return false;
+ config_ = config;
+ if (inst_)
+ RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
+ input_buffer_.clear();
+ input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame());
+ RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(
+ &inst_, config.num_channels,
+ config.application ==
+ AudioEncoderOpusConfig::ApplicationMode::kVoip
+ ? 0
+ : 1,
+ config.sample_rate_hz));
+ const int bitrate = GetBitrateBps(config);
+ RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
+ RTC_LOG(LS_VERBOSE) << "Set Opus bitrate to " << bitrate << " bps.";
+ if (config.fec_enabled) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
+ }
+ RTC_CHECK_EQ(
+ 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz));
+ // Use the default complexity if the start bitrate is within the hysteresis
+ // window.
+ complexity_ = GetNewComplexity(config).value_or(config.complexity);
+ RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
+ bitrate_changed_ = true;
+ if (config.dtx_enabled) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
+ }
+ RTC_CHECK_EQ(0,
+ WebRtcOpus_SetPacketLossRate(
+ inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
+ if (config.cbr_enabled) {
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableCbr(inst_));
+ } else {
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableCbr(inst_));
+ }
+ num_channels_to_encode_ = NumChannels();
+ next_frame_length_ms_ = config_.frame_size_ms;
+ return true;
+}
+
+void AudioEncoderOpusImpl::SetFrameLength(int frame_length_ms) {
+ if (next_frame_length_ms_ != frame_length_ms) {
+ RTC_LOG(LS_VERBOSE) << "Update Opus frame length "
+ << "from " << next_frame_length_ms_ << " ms "
+ << "to " << frame_length_ms << " ms.";
+ }
+ next_frame_length_ms_ = frame_length_ms;
+}
+
+void AudioEncoderOpusImpl::SetNumChannelsToEncode(
+ size_t num_channels_to_encode) {
+ RTC_DCHECK_GT(num_channels_to_encode, 0);
+ RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels);
+
+ if (num_channels_to_encode_ == num_channels_to_encode)
+ return;
+
+ RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode));
+ num_channels_to_encode_ = num_channels_to_encode;
+}
+
+void AudioEncoderOpusImpl::SetProjectedPacketLossRate(float fraction) {
+ fraction = std::min(std::max(fraction, 0.0f), kMaxPacketLossFraction);
+ if (packet_loss_rate_ != fraction) {
+ packet_loss_rate_ = fraction;
+ RTC_CHECK_EQ(
+ 0, WebRtcOpus_SetPacketLossRate(
+ inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
+ }
+}
+
+void AudioEncoderOpusImpl::SetTargetBitrate(int bits_per_second) {
+ const int new_bitrate = rtc::SafeClamp<int>(
+ bits_per_second, AudioEncoderOpusConfig::kMinBitrateBps,
+ AudioEncoderOpusConfig::kMaxBitrateBps);
+ if (config_.bitrate_bps && *config_.bitrate_bps != new_bitrate) {
+ config_.bitrate_bps = new_bitrate;
+ RTC_DCHECK(config_.IsOk());
+ const int bitrate = GetBitrateBps(config_);
+ RTC_CHECK_EQ(
+ 0, WebRtcOpus_SetBitRate(
+ inst_, GetMultipliedBitrate(bitrate, bitrate_multipliers_)));
+ RTC_LOG(LS_VERBOSE) << "Set Opus bitrate to " << bitrate << " bps.";
+ bitrate_changed_ = true;
+ }
+
+ const auto new_complexity = GetNewComplexity(config_);
+ if (new_complexity && complexity_ != *new_complexity) {
+ complexity_ = *new_complexity;
+ RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
+ }
+}
+
+void AudioEncoderOpusImpl::ApplyAudioNetworkAdaptor() {
+ auto config = audio_network_adaptor_->GetEncoderRuntimeConfig();
+
+ if (config.bitrate_bps)
+ SetTargetBitrate(*config.bitrate_bps);
+ if (config.frame_length_ms)
+ SetFrameLength(*config.frame_length_ms);
+ if (config.enable_dtx)
+ SetDtx(*config.enable_dtx);
+ if (config.num_channels)
+ SetNumChannelsToEncode(*config.num_channels);
+}
+
+std::unique_ptr<AudioNetworkAdaptor>
+AudioEncoderOpusImpl::DefaultAudioNetworkAdaptorCreator(
+ absl::string_view config_string,
+ RtcEventLog* event_log) const {
+ AudioNetworkAdaptorImpl::Config config;
+ config.event_log = event_log;
+ return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl(
+ config, ControllerManagerImpl::Create(
+ config_string, NumChannels(), supported_frame_lengths_ms(),
+ AudioEncoderOpusConfig::kMinBitrateBps,
+ num_channels_to_encode_, next_frame_length_ms_,
+ GetTargetBitrate(), config_.fec_enabled, GetDtx())));
+}
+
+void AudioEncoderOpusImpl::MaybeUpdateUplinkBandwidth() {
+ if (audio_network_adaptor_ && !use_stable_target_for_adaptation_) {
+ int64_t now_ms = rtc::TimeMillis();
+ if (!bitrate_smoother_last_update_time_ ||
+ now_ms - *bitrate_smoother_last_update_time_ >=
+ config_.uplink_bandwidth_update_interval_ms) {
+ absl::optional<float> smoothed_bitrate = bitrate_smoother_->GetAverage();
+ if (smoothed_bitrate)
+ audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate);
+ bitrate_smoother_last_update_time_ = now_ms;
+ }
+ }
+}
+
+ANAStats AudioEncoderOpusImpl::GetANAStats() const {
+ if (audio_network_adaptor_) {
+ return audio_network_adaptor_->GetStats();
+ }
+ return ANAStats();
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta> >
+AudioEncoderOpusImpl::GetFrameLengthRange() const {
+ if (config_.supported_frame_lengths_ms.empty()) {
+ return absl::nullopt;
+ } else if (audio_network_adaptor_) {
+ return {{TimeDelta::Millis(config_.supported_frame_lengths_ms.front()),
+ TimeDelta::Millis(config_.supported_frame_lengths_ms.back())}};
+ } else {
+ return {{TimeDelta::Millis(config_.frame_size_ms),
+ TimeDelta::Millis(config_.frame_size_ms)}};
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h
new file mode 100644
index 0000000000..a0c42af121
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/audio_codecs/audio_format.h"
+#include "api/audio_codecs/opus/audio_encoder_opus_config.h"
+#include "common_audio/smoothing_filter.h"
+#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+
+namespace webrtc {
+
+class RtcEventLog;
+
+class AudioEncoderOpusImpl final : public AudioEncoder {
+ public:
+ // Returns empty if the current bitrate falls within the hysteresis window,
+ // defined by complexity_threshold_bps +/- complexity_threshold_window_bps.
+ // Otherwise, returns the current complexity depending on whether the
+ // current bitrate is above or below complexity_threshold_bps.
+ static absl::optional<int> GetNewComplexity(
+ const AudioEncoderOpusConfig& config);
+
+ // Returns OPUS_AUTO if the the current bitrate is above wideband threshold.
+ // Returns empty if it is below, but bandwidth coincides with the desired one.
+ // Otherwise returns the desired bandwidth.
+ static absl::optional<int> GetNewBandwidth(
+ const AudioEncoderOpusConfig& config,
+ OpusEncInst* inst);
+
+ using AudioNetworkAdaptorCreator =
+ std::function<std::unique_ptr<AudioNetworkAdaptor>(absl::string_view,
+ RtcEventLog*)>;
+
+ AudioEncoderOpusImpl(const AudioEncoderOpusConfig& config, int payload_type);
+
+ // Dependency injection for testing.
+ AudioEncoderOpusImpl(
+ const AudioEncoderOpusConfig& config,
+ int payload_type,
+ const AudioNetworkAdaptorCreator& audio_network_adaptor_creator,
+ std::unique_ptr<SmoothingFilter> bitrate_smoother);
+
+ AudioEncoderOpusImpl(int payload_type, const SdpAudioFormat& format);
+ ~AudioEncoderOpusImpl() override;
+
+ AudioEncoderOpusImpl(const AudioEncoderOpusImpl&) = delete;
+ AudioEncoderOpusImpl& operator=(const AudioEncoderOpusImpl&) = delete;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ int RtpTimestampRateHz() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+
+ void Reset() override;
+ bool SetFec(bool enable) override;
+
+ // Set Opus DTX. Once enabled, Opus stops transmission, when it detects
+ // voice being inactive. During that, it still sends 2 packets (one for
+ // content, one for signaling) about every 400 ms.
+ bool SetDtx(bool enable) override;
+ bool GetDtx() const override;
+
+ bool SetApplication(Application application) override;
+ void SetMaxPlaybackRate(int frequency_hz) override;
+ bool EnableAudioNetworkAdaptor(const std::string& config_string,
+ RtcEventLog* event_log) override;
+ void DisableAudioNetworkAdaptor() override;
+ void OnReceivedUplinkPacketLossFraction(
+ float uplink_packet_loss_fraction) override;
+ void OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) override;
+ void OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) override;
+ void OnReceivedUplinkAllocation(BitrateAllocationUpdate update) override;
+ void OnReceivedRtt(int rtt_ms) override;
+ void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
+ void SetReceiverFrameLengthRange(int min_frame_length_ms,
+ int max_frame_length_ms) override;
+ ANAStats GetANAStats() const override;
+ absl::optional<std::pair<TimeDelta, TimeDelta> > GetFrameLengthRange()
+ const override;
+ rtc::ArrayView<const int> supported_frame_lengths_ms() const {
+ return config_.supported_frame_lengths_ms;
+ }
+
+ // Getters for testing.
+ float packet_loss_rate() const { return packet_loss_rate_; }
+ AudioEncoderOpusConfig::ApplicationMode application() const {
+ return config_.application;
+ }
+ bool fec_enabled() const { return config_.fec_enabled; }
+ size_t num_channels_to_encode() const { return num_channels_to_encode_; }
+ int next_frame_length_ms() const { return next_frame_length_ms_; }
+
+ protected:
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+
+ private:
+ class PacketLossFractionSmoother;
+
+ static absl::optional<AudioEncoderOpusConfig> SdpToConfig(
+ const SdpAudioFormat& format);
+ static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
+ static AudioCodecInfo QueryAudioEncoder(const AudioEncoderOpusConfig& config);
+ static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
+ const AudioEncoderOpusConfig&,
+ int payload_type);
+
+ size_t Num10msFramesPerPacket() const;
+ size_t SamplesPer10msFrame() const;
+ size_t SufficientOutputBufferSize() const;
+ bool RecreateEncoderInstance(const AudioEncoderOpusConfig& config);
+ void SetFrameLength(int frame_length_ms);
+ void SetNumChannelsToEncode(size_t num_channels_to_encode);
+ void SetProjectedPacketLossRate(float fraction);
+
+ void OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms,
+ absl::optional<int64_t> link_capacity_allocation);
+
+ // TODO(minyue): remove "override" when we can deprecate
+ // `AudioEncoder::SetTargetBitrate`.
+ void SetTargetBitrate(int target_bps) override;
+
+ void ApplyAudioNetworkAdaptor();
+ std::unique_ptr<AudioNetworkAdaptor> DefaultAudioNetworkAdaptorCreator(
+ absl::string_view config_string,
+ RtcEventLog* event_log) const;
+
+ void MaybeUpdateUplinkBandwidth();
+
+ AudioEncoderOpusConfig config_;
+ const int payload_type_;
+ const bool send_side_bwe_with_overhead_;
+ const bool use_stable_target_for_adaptation_;
+ const bool adjust_bandwidth_;
+ bool bitrate_changed_;
+ // A multiplier for bitrates at 5 kbps and higher. The target bitrate
+ // will be multiplied by these multipliers, each multiplier is applied to a
+ // 1 kbps range.
+ std::vector<float> bitrate_multipliers_;
+ float packet_loss_rate_;
+ std::vector<int16_t> input_buffer_;
+ OpusEncInst* inst_;
+ uint32_t first_timestamp_in_buffer_;
+ size_t num_channels_to_encode_;
+ int next_frame_length_ms_;
+ int complexity_;
+ std::unique_ptr<PacketLossFractionSmoother> packet_loss_fraction_smoother_;
+ const AudioNetworkAdaptorCreator audio_network_adaptor_creator_;
+ std::unique_ptr<AudioNetworkAdaptor> audio_network_adaptor_;
+ absl::optional<size_t> overhead_bytes_per_packet_;
+ const std::unique_ptr<SmoothingFilter> bitrate_smoother_;
+ absl::optional<int64_t> bitrate_smoother_last_update_time_;
+ int consecutive_dtx_frames_;
+
+ friend struct AudioEncoderOpus;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
new file mode 100644
index 0000000000..43e8a7a80f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
@@ -0,0 +1,906 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/opus/audio_encoder_opus.h"
+
+#include <array>
+#include <memory>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "common_audio/mocks/mock_smoothing_filter.h"
+#include "modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h"
+#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "modules/audio_coding/neteq/tools/audio_loop.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/fake_clock.h"
+#include "test/field_trial.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+using ::testing::NiceMock;
+using ::testing::Return;
+
+namespace {
+
+constexpr int kDefaultOpusPayloadType = 105;
+constexpr int kDefaultOpusRate = 32000;
+constexpr int kDefaultOpusPacSize = 960;
+constexpr int64_t kInitialTimeUs = 12345678;
+
+AudioEncoderOpusConfig CreateConfigWithParameters(
+ const SdpAudioFormat::Parameters& params) {
+ const SdpAudioFormat format("opus", 48000, 2, params);
+ return *AudioEncoderOpus::SdpToConfig(format);
+}
+
+struct AudioEncoderOpusStates {
+ MockAudioNetworkAdaptor* mock_audio_network_adaptor;
+ MockSmoothingFilter* mock_bitrate_smoother;
+ std::unique_ptr<AudioEncoderOpusImpl> encoder;
+ std::unique_ptr<rtc::ScopedFakeClock> fake_clock;
+ AudioEncoderOpusConfig config;
+};
+
+std::unique_ptr<AudioEncoderOpusStates> CreateCodec(int sample_rate_hz,
+ size_t num_channels) {
+ std::unique_ptr<AudioEncoderOpusStates> states =
+ std::make_unique<AudioEncoderOpusStates>();
+ states->mock_audio_network_adaptor = nullptr;
+ states->fake_clock.reset(new rtc::ScopedFakeClock());
+ states->fake_clock->SetTime(Timestamp::Micros(kInitialTimeUs));
+
+ MockAudioNetworkAdaptor** mock_ptr = &states->mock_audio_network_adaptor;
+ AudioEncoderOpusImpl::AudioNetworkAdaptorCreator creator =
+ [mock_ptr](absl::string_view, RtcEventLog* event_log) {
+ std::unique_ptr<MockAudioNetworkAdaptor> adaptor(
+ new NiceMock<MockAudioNetworkAdaptor>());
+ EXPECT_CALL(*adaptor, Die());
+ *mock_ptr = adaptor.get();
+ return adaptor;
+ };
+
+ AudioEncoderOpusConfig config;
+ config.frame_size_ms = rtc::CheckedDivExact(kDefaultOpusPacSize, 48);
+ config.sample_rate_hz = sample_rate_hz;
+ config.num_channels = num_channels;
+ config.bitrate_bps = kDefaultOpusRate;
+ config.application = num_channels == 1
+ ? AudioEncoderOpusConfig::ApplicationMode::kVoip
+ : AudioEncoderOpusConfig::ApplicationMode::kAudio;
+ config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
+ states->config = config;
+
+ std::unique_ptr<MockSmoothingFilter> bitrate_smoother(
+ new MockSmoothingFilter());
+ states->mock_bitrate_smoother = bitrate_smoother.get();
+
+ states->encoder.reset(
+ new AudioEncoderOpusImpl(states->config, kDefaultOpusPayloadType, creator,
+ std::move(bitrate_smoother)));
+ return states;
+}
+
+AudioEncoderRuntimeConfig CreateEncoderRuntimeConfig() {
+ constexpr int kBitrate = 40000;
+ constexpr int kFrameLength = 60;
+ constexpr bool kEnableDtx = false;
+ constexpr size_t kNumChannels = 1;
+ AudioEncoderRuntimeConfig config;
+ config.bitrate_bps = kBitrate;
+ config.frame_length_ms = kFrameLength;
+ config.enable_dtx = kEnableDtx;
+ config.num_channels = kNumChannels;
+ return config;
+}
+
+void CheckEncoderRuntimeConfig(const AudioEncoderOpusImpl* encoder,
+ const AudioEncoderRuntimeConfig& config) {
+ EXPECT_EQ(*config.bitrate_bps, encoder->GetTargetBitrate());
+ EXPECT_EQ(*config.frame_length_ms, encoder->next_frame_length_ms());
+ EXPECT_EQ(*config.enable_dtx, encoder->GetDtx());
+ EXPECT_EQ(*config.num_channels, encoder->num_channels_to_encode());
+}
+
+// Create 10ms audio data blocks for a total packet size of "packet_size_ms".
+std::unique_ptr<test::AudioLoop> Create10msAudioBlocks(
+ const std::unique_ptr<AudioEncoderOpusImpl>& encoder,
+ int packet_size_ms) {
+ const std::string file_name =
+ test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+
+ std::unique_ptr<test::AudioLoop> speech_data(new test::AudioLoop());
+ int audio_samples_per_ms =
+ rtc::CheckedDivExact(encoder->SampleRateHz(), 1000);
+ if (!speech_data->Init(
+ file_name,
+ packet_size_ms * audio_samples_per_ms *
+ encoder->num_channels_to_encode(),
+ 10 * audio_samples_per_ms * encoder->num_channels_to_encode()))
+ return nullptr;
+ return speech_data;
+}
+
+} // namespace
+
+class AudioEncoderOpusTest : public ::testing::TestWithParam<int> {
+ protected:
+ int sample_rate_hz_{GetParam()};
+};
+INSTANTIATE_TEST_SUITE_P(Param,
+ AudioEncoderOpusTest,
+ ::testing::Values(16000, 48000));
+
+TEST_P(AudioEncoderOpusTest, DefaultApplicationModeMono) {
+ auto states = CreateCodec(sample_rate_hz_, 1);
+ EXPECT_EQ(AudioEncoderOpusConfig::ApplicationMode::kVoip,
+ states->encoder->application());
+}
+
+TEST_P(AudioEncoderOpusTest, DefaultApplicationModeStereo) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ EXPECT_EQ(AudioEncoderOpusConfig::ApplicationMode::kAudio,
+ states->encoder->application());
+}
+
+TEST_P(AudioEncoderOpusTest, ChangeApplicationMode) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ EXPECT_TRUE(
+ states->encoder->SetApplication(AudioEncoder::Application::kSpeech));
+ EXPECT_EQ(AudioEncoderOpusConfig::ApplicationMode::kVoip,
+ states->encoder->application());
+}
+
+TEST_P(AudioEncoderOpusTest, ResetWontChangeApplicationMode) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+
+ // Trigger a reset.
+ states->encoder->Reset();
+ // Verify that the mode is still kAudio.
+ EXPECT_EQ(AudioEncoderOpusConfig::ApplicationMode::kAudio,
+ states->encoder->application());
+
+ // Now change to kVoip.
+ EXPECT_TRUE(
+ states->encoder->SetApplication(AudioEncoder::Application::kSpeech));
+ EXPECT_EQ(AudioEncoderOpusConfig::ApplicationMode::kVoip,
+ states->encoder->application());
+
+ // Trigger a reset again.
+ states->encoder->Reset();
+ // Verify that the mode is still kVoip.
+ EXPECT_EQ(AudioEncoderOpusConfig::ApplicationMode::kVoip,
+ states->encoder->application());
+}
+
+TEST_P(AudioEncoderOpusTest, ToggleDtx) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ // Enable DTX
+ EXPECT_TRUE(states->encoder->SetDtx(true));
+ EXPECT_TRUE(states->encoder->GetDtx());
+ // Turn off DTX.
+ EXPECT_TRUE(states->encoder->SetDtx(false));
+ EXPECT_FALSE(states->encoder->GetDtx());
+}
+
+TEST_P(AudioEncoderOpusTest,
+ OnReceivedUplinkBandwidthWithoutAudioNetworkAdaptor) {
+ auto states = CreateCodec(sample_rate_hz_, 1);
+ // Constants are replicated from audio_states->encoderopus.cc.
+ const int kMinBitrateBps = 6000;
+ const int kMaxBitrateBps = 510000;
+ const int kOverheadBytesPerPacket = 64;
+ states->encoder->OnReceivedOverhead(kOverheadBytesPerPacket);
+ const int kOverheadBps = 8 * kOverheadBytesPerPacket *
+ rtc::CheckedDivExact(48000, kDefaultOpusPacSize);
+ // Set a too low bitrate.
+ states->encoder->OnReceivedUplinkBandwidth(kMinBitrateBps + kOverheadBps - 1,
+ absl::nullopt);
+ EXPECT_EQ(kMinBitrateBps, states->encoder->GetTargetBitrate());
+ // Set a too high bitrate.
+ states->encoder->OnReceivedUplinkBandwidth(kMaxBitrateBps + kOverheadBps + 1,
+ absl::nullopt);
+ EXPECT_EQ(kMaxBitrateBps, states->encoder->GetTargetBitrate());
+ // Set the minimum rate.
+ states->encoder->OnReceivedUplinkBandwidth(kMinBitrateBps + kOverheadBps,
+ absl::nullopt);
+ EXPECT_EQ(kMinBitrateBps, states->encoder->GetTargetBitrate());
+ // Set the maximum rate.
+ states->encoder->OnReceivedUplinkBandwidth(kMaxBitrateBps + kOverheadBps,
+ absl::nullopt);
+ EXPECT_EQ(kMaxBitrateBps, states->encoder->GetTargetBitrate());
+ // Set rates from kMaxBitrateBps up to 32000 bps.
+ for (int rate = kMinBitrateBps + kOverheadBps; rate <= 32000 + kOverheadBps;
+ rate += 1000) {
+ states->encoder->OnReceivedUplinkBandwidth(rate, absl::nullopt);
+ EXPECT_EQ(rate - kOverheadBps, states->encoder->GetTargetBitrate());
+ }
+}
+
+TEST_P(AudioEncoderOpusTest, SetReceiverFrameLengthRange) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ // Before calling to `SetReceiverFrameLengthRange`,
+ // `supported_frame_lengths_ms` should contain only the frame length being
+ // used.
+ using ::testing::ElementsAre;
+ EXPECT_THAT(states->encoder->supported_frame_lengths_ms(),
+ ElementsAre(states->encoder->next_frame_length_ms()));
+ states->encoder->SetReceiverFrameLengthRange(0, 12345);
+ states->encoder->SetReceiverFrameLengthRange(21, 60);
+ EXPECT_THAT(states->encoder->supported_frame_lengths_ms(),
+ ElementsAre(40, 60));
+ states->encoder->SetReceiverFrameLengthRange(20, 59);
+ EXPECT_THAT(states->encoder->supported_frame_lengths_ms(),
+ ElementsAre(20, 40));
+}
+
+TEST_P(AudioEncoderOpusTest,
+ InvokeAudioNetworkAdaptorOnReceivedUplinkPacketLossFraction) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+
+ auto config = CreateEncoderRuntimeConfig();
+ EXPECT_CALL(*states->mock_audio_network_adaptor, GetEncoderRuntimeConfig())
+ .WillOnce(Return(config));
+
+ // Since using mock audio network adaptor, any packet loss fraction is fine.
+ constexpr float kUplinkPacketLoss = 0.1f;
+ EXPECT_CALL(*states->mock_audio_network_adaptor,
+ SetUplinkPacketLossFraction(kUplinkPacketLoss));
+ states->encoder->OnReceivedUplinkPacketLossFraction(kUplinkPacketLoss);
+
+ CheckEncoderRuntimeConfig(states->encoder.get(), config);
+}
+
+TEST_P(AudioEncoderOpusTest,
+ InvokeAudioNetworkAdaptorOnReceivedUplinkBandwidth) {
+ test::ScopedFieldTrials override_field_trials(
+ "WebRTC-Audio-StableTargetAdaptation/Disabled/");
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+
+ auto config = CreateEncoderRuntimeConfig();
+ EXPECT_CALL(*states->mock_audio_network_adaptor, GetEncoderRuntimeConfig())
+ .WillOnce(Return(config));
+
+ // Since using mock audio network adaptor, any target audio bitrate is fine.
+ constexpr int kTargetAudioBitrate = 30000;
+ constexpr int64_t kProbingIntervalMs = 3000;
+ EXPECT_CALL(*states->mock_audio_network_adaptor,
+ SetTargetAudioBitrate(kTargetAudioBitrate));
+ EXPECT_CALL(*states->mock_bitrate_smoother,
+ SetTimeConstantMs(kProbingIntervalMs * 4));
+ EXPECT_CALL(*states->mock_bitrate_smoother, AddSample(kTargetAudioBitrate));
+ states->encoder->OnReceivedUplinkBandwidth(kTargetAudioBitrate,
+ kProbingIntervalMs);
+
+ CheckEncoderRuntimeConfig(states->encoder.get(), config);
+}
+
+TEST_P(AudioEncoderOpusTest,
+ InvokeAudioNetworkAdaptorOnReceivedUplinkAllocation) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+
+ auto config = CreateEncoderRuntimeConfig();
+ EXPECT_CALL(*states->mock_audio_network_adaptor, GetEncoderRuntimeConfig())
+ .WillOnce(Return(config));
+
+ BitrateAllocationUpdate update;
+ update.target_bitrate = DataRate::BitsPerSec(30000);
+ update.stable_target_bitrate = DataRate::BitsPerSec(20000);
+ update.bwe_period = TimeDelta::Millis(200);
+ EXPECT_CALL(*states->mock_audio_network_adaptor,
+ SetTargetAudioBitrate(update.target_bitrate.bps()));
+ EXPECT_CALL(*states->mock_audio_network_adaptor,
+ SetUplinkBandwidth(update.stable_target_bitrate.bps()));
+ states->encoder->OnReceivedUplinkAllocation(update);
+
+ CheckEncoderRuntimeConfig(states->encoder.get(), config);
+}
+
+TEST_P(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnReceivedRtt) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+
+ auto config = CreateEncoderRuntimeConfig();
+ EXPECT_CALL(*states->mock_audio_network_adaptor, GetEncoderRuntimeConfig())
+ .WillOnce(Return(config));
+
+ // Since using mock audio network adaptor, any rtt is fine.
+ constexpr int kRtt = 30;
+ EXPECT_CALL(*states->mock_audio_network_adaptor, SetRtt(kRtt));
+ states->encoder->OnReceivedRtt(kRtt);
+
+ CheckEncoderRuntimeConfig(states->encoder.get(), config);
+}
+
+TEST_P(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnReceivedOverhead) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+
+ auto config = CreateEncoderRuntimeConfig();
+ EXPECT_CALL(*states->mock_audio_network_adaptor, GetEncoderRuntimeConfig())
+ .WillOnce(Return(config));
+
+ // Since using mock audio network adaptor, any overhead is fine.
+ constexpr size_t kOverhead = 64;
+ EXPECT_CALL(*states->mock_audio_network_adaptor, SetOverhead(kOverhead));
+ states->encoder->OnReceivedOverhead(kOverhead);
+
+ CheckEncoderRuntimeConfig(states->encoder.get(), config);
+}
+
+TEST_P(AudioEncoderOpusTest,
+ PacketLossFractionSmoothedOnSetUplinkPacketLossFraction) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+
+ // The values are carefully chosen so that if no smoothing is made, the test
+ // will fail.
+ constexpr float kPacketLossFraction_1 = 0.02f;
+ constexpr float kPacketLossFraction_2 = 0.198f;
+ // `kSecondSampleTimeMs` is chosen to ease the calculation since
+ // 0.9999 ^ 6931 = 0.5.
+ constexpr int64_t kSecondSampleTimeMs = 6931;
+
+ // First time, no filtering.
+ states->encoder->OnReceivedUplinkPacketLossFraction(kPacketLossFraction_1);
+ EXPECT_FLOAT_EQ(0.02f, states->encoder->packet_loss_rate());
+
+ states->fake_clock->AdvanceTime(TimeDelta::Millis(kSecondSampleTimeMs));
+ states->encoder->OnReceivedUplinkPacketLossFraction(kPacketLossFraction_2);
+
+ // Now the output of packet loss fraction smoother should be
+ // (0.02 + 0.198) / 2 = 0.109.
+ EXPECT_NEAR(0.109f, states->encoder->packet_loss_rate(), 0.001);
+}
+
+TEST_P(AudioEncoderOpusTest, PacketLossRateUpperBounded) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+
+ states->encoder->OnReceivedUplinkPacketLossFraction(0.5);
+ EXPECT_FLOAT_EQ(0.2f, states->encoder->packet_loss_rate());
+}
+
+TEST_P(AudioEncoderOpusTest, DoNotInvokeSetTargetBitrateIfOverheadUnknown) {
+ test::ScopedFieldTrials override_field_trials(
+ "WebRTC-SendSideBwe-WithOverhead/Enabled/");
+
+ auto states = CreateCodec(sample_rate_hz_, 2);
+
+ states->encoder->OnReceivedUplinkBandwidth(kDefaultOpusRate * 2,
+ absl::nullopt);
+
+ // Since `OnReceivedOverhead` has not been called, the codec bitrate should
+ // not change.
+ EXPECT_EQ(kDefaultOpusRate, states->encoder->GetTargetBitrate());
+}
+
+// Verifies that the complexity adaptation in the config works as intended.
+TEST(AudioEncoderOpusTest, ConfigComplexityAdaptation) {
+ AudioEncoderOpusConfig config;
+ config.low_rate_complexity = 8;
+ config.complexity = 6;
+
+ // Bitrate within hysteresis window. Expect empty output.
+ config.bitrate_bps = 12500;
+ EXPECT_EQ(absl::nullopt, AudioEncoderOpusImpl::GetNewComplexity(config));
+
+ // Bitrate below hysteresis window. Expect higher complexity.
+ config.bitrate_bps = 10999;
+ EXPECT_EQ(8, AudioEncoderOpusImpl::GetNewComplexity(config));
+
+ // Bitrate within hysteresis window. Expect empty output.
+ config.bitrate_bps = 12500;
+ EXPECT_EQ(absl::nullopt, AudioEncoderOpusImpl::GetNewComplexity(config));
+
+ // Bitrate above hysteresis window. Expect lower complexity.
+ config.bitrate_bps = 14001;
+ EXPECT_EQ(6, AudioEncoderOpusImpl::GetNewComplexity(config));
+}
+
+// Verifies that the bandwidth adaptation in the config works as intended.
+TEST_P(AudioEncoderOpusTest, ConfigBandwidthAdaptation) {
+ AudioEncoderOpusConfig config;
+ const size_t opus_rate_khz = rtc::CheckedDivExact(sample_rate_hz_, 1000);
+ const std::vector<int16_t> silence(
+ opus_rate_khz * config.frame_size_ms * config.num_channels, 0);
+ constexpr size_t kMaxBytes = 1000;
+ uint8_t bitstream[kMaxBytes];
+
+ OpusEncInst* inst;
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(
+ &inst, config.num_channels,
+ config.application ==
+ AudioEncoderOpusConfig::ApplicationMode::kVoip
+ ? 0
+ : 1,
+ sample_rate_hz_));
+
+ // Bitrate below minmum wideband. Expect narrowband.
+ config.bitrate_bps = absl::optional<int>(7999);
+ auto bandwidth = AudioEncoderOpusImpl::GetNewBandwidth(config, inst);
+ EXPECT_EQ(absl::optional<int>(OPUS_BANDWIDTH_NARROWBAND), bandwidth);
+ WebRtcOpus_SetBandwidth(inst, *bandwidth);
+ // It is necessary to encode here because Opus has some logic in the encoder
+ // that goes from the user-set bandwidth to the used and returned one.
+ WebRtcOpus_Encode(inst, silence.data(),
+ rtc::CheckedDivExact(silence.size(), config.num_channels),
+ kMaxBytes, bitstream);
+
+ // Bitrate not yet above maximum narrowband. Expect empty.
+ config.bitrate_bps = absl::optional<int>(9000);
+ bandwidth = AudioEncoderOpusImpl::GetNewBandwidth(config, inst);
+ EXPECT_EQ(absl::optional<int>(), bandwidth);
+
+ // Bitrate above maximum narrowband. Expect wideband.
+ config.bitrate_bps = absl::optional<int>(9001);
+ bandwidth = AudioEncoderOpusImpl::GetNewBandwidth(config, inst);
+ EXPECT_EQ(absl::optional<int>(OPUS_BANDWIDTH_WIDEBAND), bandwidth);
+ WebRtcOpus_SetBandwidth(inst, *bandwidth);
+ // It is necessary to encode here because Opus has some logic in the encoder
+ // that goes from the user-set bandwidth to the used and returned one.
+ WebRtcOpus_Encode(inst, silence.data(),
+ rtc::CheckedDivExact(silence.size(), config.num_channels),
+ kMaxBytes, bitstream);
+
+ // Bitrate not yet below minimum wideband. Expect empty.
+ config.bitrate_bps = absl::optional<int>(8000);
+ bandwidth = AudioEncoderOpusImpl::GetNewBandwidth(config, inst);
+ EXPECT_EQ(absl::optional<int>(), bandwidth);
+
+ // Bitrate above automatic threshold. Expect automatic.
+ config.bitrate_bps = absl::optional<int>(12001);
+ bandwidth = AudioEncoderOpusImpl::GetNewBandwidth(config, inst);
+ EXPECT_EQ(absl::optional<int>(OPUS_AUTO), bandwidth);
+
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(inst));
+}
+
+TEST_P(AudioEncoderOpusTest, EmptyConfigDoesNotAffectEncoderSettings) {
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+
+ auto config = CreateEncoderRuntimeConfig();
+ AudioEncoderRuntimeConfig empty_config;
+
+ EXPECT_CALL(*states->mock_audio_network_adaptor, GetEncoderRuntimeConfig())
+ .WillOnce(Return(config))
+ .WillOnce(Return(empty_config));
+
+ constexpr size_t kOverhead = 64;
+ EXPECT_CALL(*states->mock_audio_network_adaptor, SetOverhead(kOverhead))
+ .Times(2);
+ states->encoder->OnReceivedOverhead(kOverhead);
+ states->encoder->OnReceivedOverhead(kOverhead);
+
+ CheckEncoderRuntimeConfig(states->encoder.get(), config);
+}
+
+TEST_P(AudioEncoderOpusTest, UpdateUplinkBandwidthInAudioNetworkAdaptor) {
+ test::ScopedFieldTrials override_field_trials(
+ "WebRTC-Audio-StableTargetAdaptation/Disabled/");
+ auto states = CreateCodec(sample_rate_hz_, 2);
+ states->encoder->EnableAudioNetworkAdaptor("", nullptr);
+ const size_t opus_rate_khz = rtc::CheckedDivExact(sample_rate_hz_, 1000);
+ const std::vector<int16_t> audio(opus_rate_khz * 10 * 2, 0);
+ rtc::Buffer encoded;
+ EXPECT_CALL(*states->mock_bitrate_smoother, GetAverage())
+ .WillOnce(Return(50000));
+ EXPECT_CALL(*states->mock_audio_network_adaptor, SetUplinkBandwidth(50000));
+ states->encoder->Encode(
+ 0, rtc::ArrayView<const int16_t>(audio.data(), audio.size()), &encoded);
+
+ // Repeat update uplink bandwidth tests.
+ for (int i = 0; i < 5; i++) {
+ // Don't update till it is time to update again.
+ states->fake_clock->AdvanceTime(TimeDelta::Millis(
+ states->config.uplink_bandwidth_update_interval_ms - 1));
+ states->encoder->Encode(
+ 0, rtc::ArrayView<const int16_t>(audio.data(), audio.size()), &encoded);
+
+ // Update when it is time to update.
+ EXPECT_CALL(*states->mock_bitrate_smoother, GetAverage())
+ .WillOnce(Return(40000));
+ EXPECT_CALL(*states->mock_audio_network_adaptor, SetUplinkBandwidth(40000));
+ states->fake_clock->AdvanceTime(TimeDelta::Millis(1));
+ states->encoder->Encode(
+ 0, rtc::ArrayView<const int16_t>(audio.data(), audio.size()), &encoded);
+ }
+}
+
+TEST_P(AudioEncoderOpusTest, EncodeAtMinBitrate) {
+ auto states = CreateCodec(sample_rate_hz_, 1);
+ constexpr int kNumPacketsToEncode = 2;
+ auto audio_frames =
+ Create10msAudioBlocks(states->encoder, kNumPacketsToEncode * 20);
+ ASSERT_TRUE(audio_frames) << "Create10msAudioBlocks failed";
+ rtc::Buffer encoded;
+ uint32_t rtp_timestamp = 12345; // Just a number not important to this test.
+
+ states->encoder->OnReceivedUplinkBandwidth(0, absl::nullopt);
+ for (int packet_index = 0; packet_index < kNumPacketsToEncode;
+ packet_index++) {
+ // Make sure we are not encoding before we have enough data for
+ // a 20ms packet.
+ for (int index = 0; index < 1; index++) {
+ states->encoder->Encode(rtp_timestamp, audio_frames->GetNextBlock(),
+ &encoded);
+ EXPECT_EQ(0u, encoded.size());
+ }
+
+ // Should encode now.
+ states->encoder->Encode(rtp_timestamp, audio_frames->GetNextBlock(),
+ &encoded);
+ EXPECT_GT(encoded.size(), 0u);
+ encoded.Clear();
+ }
+}
+
+TEST(AudioEncoderOpusTest, TestConfigDefaults) {
+ const auto config_opt = AudioEncoderOpus::SdpToConfig({"opus", 48000, 2});
+ ASSERT_TRUE(config_opt);
+ EXPECT_EQ(48000, config_opt->max_playback_rate_hz);
+ EXPECT_EQ(1u, config_opt->num_channels);
+ EXPECT_FALSE(config_opt->fec_enabled);
+ EXPECT_FALSE(config_opt->dtx_enabled);
+ EXPECT_EQ(20, config_opt->frame_size_ms);
+}
+
+TEST(AudioEncoderOpusTest, TestConfigFromParams) {
+ const auto config1 = CreateConfigWithParameters({{"stereo", "0"}});
+ EXPECT_EQ(1U, config1.num_channels);
+
+ const auto config2 = CreateConfigWithParameters({{"stereo", "1"}});
+ EXPECT_EQ(2U, config2.num_channels);
+
+ const auto config3 = CreateConfigWithParameters({{"useinbandfec", "0"}});
+ EXPECT_FALSE(config3.fec_enabled);
+
+ const auto config4 = CreateConfigWithParameters({{"useinbandfec", "1"}});
+ EXPECT_TRUE(config4.fec_enabled);
+
+ const auto config5 = CreateConfigWithParameters({{"usedtx", "0"}});
+ EXPECT_FALSE(config5.dtx_enabled);
+
+ const auto config6 = CreateConfigWithParameters({{"usedtx", "1"}});
+ EXPECT_TRUE(config6.dtx_enabled);
+
+ const auto config7 = CreateConfigWithParameters({{"cbr", "0"}});
+ EXPECT_FALSE(config7.cbr_enabled);
+
+ const auto config8 = CreateConfigWithParameters({{"cbr", "1"}});
+ EXPECT_TRUE(config8.cbr_enabled);
+
+ const auto config9 =
+ CreateConfigWithParameters({{"maxplaybackrate", "12345"}});
+ EXPECT_EQ(12345, config9.max_playback_rate_hz);
+
+ const auto config10 =
+ CreateConfigWithParameters({{"maxaveragebitrate", "96000"}});
+ EXPECT_EQ(96000, config10.bitrate_bps);
+
+ const auto config11 = CreateConfigWithParameters({{"maxptime", "40"}});
+ for (int frame_length : config11.supported_frame_lengths_ms) {
+ EXPECT_LE(frame_length, 40);
+ }
+
+ const auto config12 = CreateConfigWithParameters({{"minptime", "40"}});
+ for (int frame_length : config12.supported_frame_lengths_ms) {
+ EXPECT_GE(frame_length, 40);
+ }
+
+ const auto config13 = CreateConfigWithParameters({{"ptime", "40"}});
+ EXPECT_EQ(40, config13.frame_size_ms);
+
+ constexpr int kMinSupportedFrameLength = 10;
+ constexpr int kMaxSupportedFrameLength =
+ WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
+
+ const auto config14 = CreateConfigWithParameters({{"ptime", "1"}});
+ EXPECT_EQ(kMinSupportedFrameLength, config14.frame_size_ms);
+
+ const auto config15 = CreateConfigWithParameters({{"ptime", "2000"}});
+ EXPECT_EQ(kMaxSupportedFrameLength, config15.frame_size_ms);
+}
+
+TEST(AudioEncoderOpusTest, TestConfigFromInvalidParams) {
+ const webrtc::SdpAudioFormat format("opus", 48000, 2);
+ const auto default_config = *AudioEncoderOpus::SdpToConfig(format);
+#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
+ const std::vector<int> default_supported_frame_lengths_ms({20, 40, 60, 120});
+#else
+ const std::vector<int> default_supported_frame_lengths_ms({20, 40, 60});
+#endif
+
+ AudioEncoderOpusConfig config;
+ config = CreateConfigWithParameters({{"stereo", "invalid"}});
+ EXPECT_EQ(default_config.num_channels, config.num_channels);
+
+ config = CreateConfigWithParameters({{"useinbandfec", "invalid"}});
+ EXPECT_EQ(default_config.fec_enabled, config.fec_enabled);
+
+ config = CreateConfigWithParameters({{"usedtx", "invalid"}});
+ EXPECT_EQ(default_config.dtx_enabled, config.dtx_enabled);
+
+ config = CreateConfigWithParameters({{"cbr", "invalid"}});
+ EXPECT_EQ(default_config.dtx_enabled, config.dtx_enabled);
+
+ config = CreateConfigWithParameters({{"maxplaybackrate", "0"}});
+ EXPECT_EQ(default_config.max_playback_rate_hz, config.max_playback_rate_hz);
+
+ config = CreateConfigWithParameters({{"maxplaybackrate", "-23"}});
+ EXPECT_EQ(default_config.max_playback_rate_hz, config.max_playback_rate_hz);
+
+ config = CreateConfigWithParameters({{"maxplaybackrate", "not a number!"}});
+ EXPECT_EQ(default_config.max_playback_rate_hz, config.max_playback_rate_hz);
+
+ config = CreateConfigWithParameters({{"maxaveragebitrate", "0"}});
+ EXPECT_EQ(6000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters({{"maxaveragebitrate", "-1000"}});
+ EXPECT_EQ(6000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters({{"maxaveragebitrate", "1024000"}});
+ EXPECT_EQ(510000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters({{"maxaveragebitrate", "not a number!"}});
+ EXPECT_EQ(default_config.bitrate_bps, config.bitrate_bps);
+
+ config = CreateConfigWithParameters({{"maxptime", "invalid"}});
+ EXPECT_EQ(default_supported_frame_lengths_ms,
+ config.supported_frame_lengths_ms);
+
+ config = CreateConfigWithParameters({{"minptime", "invalid"}});
+ EXPECT_EQ(default_supported_frame_lengths_ms,
+ config.supported_frame_lengths_ms);
+
+ config = CreateConfigWithParameters({{"ptime", "invalid"}});
+ EXPECT_EQ(default_supported_frame_lengths_ms,
+ config.supported_frame_lengths_ms);
+}
+
+// Test that bitrate will be overridden by the "maxaveragebitrate" parameter.
+// Also test that the "maxaveragebitrate" can't be set to values outside the
+// range of 6000 and 510000
+TEST(AudioEncoderOpusTest, SetSendCodecOpusMaxAverageBitrate) {
+ // Ignore if less than 6000.
+ const auto config1 = AudioEncoderOpus::SdpToConfig(
+ {"opus", 48000, 2, {{"maxaveragebitrate", "5999"}}});
+ EXPECT_EQ(6000, config1->bitrate_bps);
+
+ // Ignore if larger than 510000.
+ const auto config2 = AudioEncoderOpus::SdpToConfig(
+ {"opus", 48000, 2, {{"maxaveragebitrate", "510001"}}});
+ EXPECT_EQ(510000, config2->bitrate_bps);
+
+ const auto config3 = AudioEncoderOpus::SdpToConfig(
+ {"opus", 48000, 2, {{"maxaveragebitrate", "200000"}}});
+ EXPECT_EQ(200000, config3->bitrate_bps);
+}
+
+// Test maxplaybackrate <= 8000 triggers Opus narrow band mode.
+TEST(AudioEncoderOpusTest, SetMaxPlaybackRateNb) {
+ auto config = CreateConfigWithParameters({{"maxplaybackrate", "8000"}});
+ EXPECT_EQ(8000, config.max_playback_rate_hz);
+ EXPECT_EQ(12000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters(
+ {{"maxplaybackrate", "8000"}, {"stereo", "1"}});
+ EXPECT_EQ(8000, config.max_playback_rate_hz);
+ EXPECT_EQ(24000, config.bitrate_bps);
+}
+
+// Test 8000 < maxplaybackrate <= 12000 triggers Opus medium band mode.
+TEST(AudioEncoderOpusTest, SetMaxPlaybackRateMb) {
+ auto config = CreateConfigWithParameters({{"maxplaybackrate", "8001"}});
+ EXPECT_EQ(8001, config.max_playback_rate_hz);
+ EXPECT_EQ(20000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters(
+ {{"maxplaybackrate", "8001"}, {"stereo", "1"}});
+ EXPECT_EQ(8001, config.max_playback_rate_hz);
+ EXPECT_EQ(40000, config.bitrate_bps);
+}
+
+// Test 12000 < maxplaybackrate <= 16000 triggers Opus wide band mode.
+TEST(AudioEncoderOpusTest, SetMaxPlaybackRateWb) {
+ auto config = CreateConfigWithParameters({{"maxplaybackrate", "12001"}});
+ EXPECT_EQ(12001, config.max_playback_rate_hz);
+ EXPECT_EQ(20000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters(
+ {{"maxplaybackrate", "12001"}, {"stereo", "1"}});
+ EXPECT_EQ(12001, config.max_playback_rate_hz);
+ EXPECT_EQ(40000, config.bitrate_bps);
+}
+
+// Test 16000 < maxplaybackrate <= 24000 triggers Opus super wide band mode.
+TEST(AudioEncoderOpusTest, SetMaxPlaybackRateSwb) {
+ auto config = CreateConfigWithParameters({{"maxplaybackrate", "16001"}});
+ EXPECT_EQ(16001, config.max_playback_rate_hz);
+ EXPECT_EQ(32000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters(
+ {{"maxplaybackrate", "16001"}, {"stereo", "1"}});
+ EXPECT_EQ(16001, config.max_playback_rate_hz);
+ EXPECT_EQ(64000, config.bitrate_bps);
+}
+
+// Test 24000 < maxplaybackrate triggers Opus full band mode.
+TEST(AudioEncoderOpusTest, SetMaxPlaybackRateFb) {
+ auto config = CreateConfigWithParameters({{"maxplaybackrate", "24001"}});
+ EXPECT_EQ(24001, config.max_playback_rate_hz);
+ EXPECT_EQ(32000, config.bitrate_bps);
+
+ config = CreateConfigWithParameters(
+ {{"maxplaybackrate", "24001"}, {"stereo", "1"}});
+ EXPECT_EQ(24001, config.max_playback_rate_hz);
+ EXPECT_EQ(64000, config.bitrate_bps);
+}
+
+TEST_P(AudioEncoderOpusTest, OpusFlagDtxAsNonSpeech) {
+ // Create encoder with DTX enabled.
+ AudioEncoderOpusConfig config;
+ config.dtx_enabled = true;
+ config.sample_rate_hz = sample_rate_hz_;
+ constexpr int payload_type = 17;
+ const auto encoder = AudioEncoderOpus::MakeAudioEncoder(config, payload_type);
+
+ // Open file containing speech and silence.
+ const std::string kInputFileName =
+ webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+ test::AudioLoop audio_loop;
+ // Use the file as if it were sampled at our desired input rate.
+ const size_t max_loop_length_samples =
+ sample_rate_hz_ * 10; // Max 10 second loop.
+ const size_t input_block_size_samples =
+ 10 * sample_rate_hz_ / 1000; // 10 ms.
+ EXPECT_TRUE(audio_loop.Init(kInputFileName, max_loop_length_samples,
+ input_block_size_samples));
+
+ // Encode.
+ AudioEncoder::EncodedInfo info;
+ rtc::Buffer encoded(500);
+ int nonspeech_frames = 0;
+ int max_nonspeech_frames = 0;
+ int dtx_frames = 0;
+ int max_dtx_frames = 0;
+ uint32_t rtp_timestamp = 0u;
+ for (size_t i = 0; i < 500; ++i) {
+ encoded.Clear();
+
+ // Every second call to the encoder will generate an Opus packet.
+ for (int j = 0; j < 2; j++) {
+ info =
+ encoder->Encode(rtp_timestamp, audio_loop.GetNextBlock(), &encoded);
+ rtp_timestamp += input_block_size_samples;
+ }
+
+ // Bookkeeping of number of DTX frames.
+ if (info.encoded_bytes <= 2) {
+ ++dtx_frames;
+ } else {
+ if (dtx_frames > max_dtx_frames)
+ max_dtx_frames = dtx_frames;
+ dtx_frames = 0;
+ }
+
+ // Bookkeeping of number of non-speech frames.
+ if (info.speech == 0) {
+ ++nonspeech_frames;
+ } else {
+ if (nonspeech_frames > max_nonspeech_frames)
+ max_nonspeech_frames = nonspeech_frames;
+ nonspeech_frames = 0;
+ }
+ }
+
+ // Maximum number of consecutive non-speech packets should exceed 15.
+ EXPECT_GT(max_nonspeech_frames, 15);
+}
+
+TEST(AudioEncoderOpusTest, OpusDtxFilteringHighEnergyRefreshPackets) {
+ test::ScopedFieldTrials override_field_trials(
+ "WebRTC-Audio-OpusAvoidNoisePumpingDuringDtx/Enabled/");
+ const std::string kInputFileName =
+ webrtc::test::ResourcePath("audio_coding/testfile16kHz", "pcm");
+ constexpr int kSampleRateHz = 16000;
+ AudioEncoderOpusConfig config;
+ config.dtx_enabled = true;
+ config.sample_rate_hz = kSampleRateHz;
+ constexpr int payload_type = 17;
+ const auto encoder = AudioEncoderOpus::MakeAudioEncoder(config, payload_type);
+ test::AudioLoop audio_loop;
+ constexpr size_t kMaxLoopLengthSaples = kSampleRateHz * 11.6f;
+ constexpr size_t kInputBlockSizeSamples = kSampleRateHz / 100;
+ EXPECT_TRUE(audio_loop.Init(kInputFileName, kMaxLoopLengthSaples,
+ kInputBlockSizeSamples));
+ AudioEncoder::EncodedInfo info;
+ rtc::Buffer encoded(500);
+ // Encode the audio file and store the last part that corresponds to silence.
+ constexpr size_t kSilenceDurationSamples = kSampleRateHz * 0.2f;
+ std::array<int16_t, kSilenceDurationSamples> silence;
+ uint32_t rtp_timestamp = 0;
+ bool last_packet_dtx_frame = false;
+ bool opus_entered_dtx = false;
+ bool silence_filled = false;
+ size_t timestamp_start_silence = 0;
+ while (!silence_filled && rtp_timestamp < kMaxLoopLengthSaples) {
+ encoded.Clear();
+ // Every second call to the encoder will generate an Opus packet.
+ for (int j = 0; j < 2; j++) {
+ auto next_frame = audio_loop.GetNextBlock();
+ info = encoder->Encode(rtp_timestamp, next_frame, &encoded);
+ if (opus_entered_dtx) {
+ size_t silence_frame_start = rtp_timestamp - timestamp_start_silence;
+ silence_filled = silence_frame_start >= kSilenceDurationSamples;
+ if (!silence_filled) {
+ std::copy(next_frame.begin(), next_frame.end(),
+ silence.begin() + silence_frame_start);
+ }
+ }
+ rtp_timestamp += kInputBlockSizeSamples;
+ }
+ EXPECT_TRUE(info.encoded_bytes > 0 || last_packet_dtx_frame);
+ last_packet_dtx_frame = info.encoded_bytes > 0 ? info.encoded_bytes <= 2
+ : last_packet_dtx_frame;
+ if (info.encoded_bytes <= 2 && !opus_entered_dtx) {
+ timestamp_start_silence = rtp_timestamp;
+ }
+ opus_entered_dtx = info.encoded_bytes <= 2;
+ }
+
+ EXPECT_TRUE(silence_filled);
+ // The copied 200 ms of silence is used for creating 6 bursts that are fed to
+ // the encoder, the first three ones with a larger energy and the last three
+ // with a lower energy. This test verifies that the encoder just sends refresh
+ // DTX packets during the last bursts.
+ int number_non_empty_packets_during_increase = 0;
+ int number_non_empty_packets_during_decrease = 0;
+ for (size_t burst = 0; burst < 6; ++burst) {
+ uint32_t rtp_timestamp_start = rtp_timestamp;
+ const bool increase_noise = burst < 3;
+ const float gain = increase_noise ? 1.4f : 0.0f;
+ while (rtp_timestamp < rtp_timestamp_start + kSilenceDurationSamples) {
+ encoded.Clear();
+ // Every second call to the encoder will generate an Opus packet.
+ for (int j = 0; j < 2; j++) {
+ std::array<int16_t, kInputBlockSizeSamples> silence_frame;
+ size_t silence_frame_start = rtp_timestamp - rtp_timestamp_start;
+ std::transform(
+ silence.begin() + silence_frame_start,
+ silence.begin() + silence_frame_start + kInputBlockSizeSamples,
+ silence_frame.begin(), [gain](float s) { return gain * s; });
+ info = encoder->Encode(rtp_timestamp, silence_frame, &encoded);
+ rtp_timestamp += kInputBlockSizeSamples;
+ }
+ EXPECT_TRUE(info.encoded_bytes > 0 || last_packet_dtx_frame);
+ last_packet_dtx_frame = info.encoded_bytes > 0 ? info.encoded_bytes <= 2
+ : last_packet_dtx_frame;
+ // Tracking the number of non empty packets.
+ if (increase_noise && info.encoded_bytes > 2) {
+ number_non_empty_packets_during_increase++;
+ }
+ if (!increase_noise && info.encoded_bytes > 2) {
+ number_non_empty_packets_during_decrease++;
+ }
+ }
+ }
+ // Check that the refresh DTX packets are just sent during the decrease energy
+ // region.
+ EXPECT_EQ(number_non_empty_packets_during_increase, 0);
+ EXPECT_GT(number_non_empty_packets_during_decrease, 0);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
new file mode 100644
index 0000000000..38b60c6187
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/opus/audio_decoder_opus.h"
+#include "api/audio_codecs/opus/audio_encoder_opus.h"
+#include "common_audio/include/audio_util.h"
+#include "common_audio/window_generator.h"
+#include "modules/audio_coding/codecs/opus/test/lapped_transform.h"
+#include "modules/audio_coding/neteq/tools/audio_loop.h"
+#include "test/field_trial.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+namespace {
+
+constexpr size_t kNumChannels = 1u;
+constexpr int kSampleRateHz = 48000;
+constexpr size_t kMaxLoopLengthSamples = kSampleRateHz * 50; // 50 seconds.
+constexpr size_t kInputBlockSizeSamples = 10 * kSampleRateHz / 1000; // 10 ms
+constexpr size_t kOutputBlockSizeSamples = 20 * kSampleRateHz / 1000; // 20 ms
+constexpr size_t kFftSize = 1024;
+constexpr size_t kNarrowbandSize = 4000 * kFftSize / kSampleRateHz;
+constexpr float kKbdAlpha = 1.5f;
+
+class PowerRatioEstimator : public LappedTransform::Callback {
+ public:
+ PowerRatioEstimator() : low_pow_(0.f), high_pow_(0.f) {
+ WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_);
+ transform_.reset(new LappedTransform(kNumChannels, 0u,
+ kInputBlockSizeSamples, window_,
+ kFftSize, kFftSize / 2, this));
+ }
+
+ void ProcessBlock(float* data) { transform_->ProcessChunk(&data, nullptr); }
+
+ float PowerRatio() { return high_pow_ / low_pow_; }
+
+ protected:
+ void ProcessAudioBlock(const std::complex<float>* const* input,
+ size_t num_input_channels,
+ size_t num_freq_bins,
+ size_t num_output_channels,
+ std::complex<float>* const* output) override {
+ float low_pow = 0.f;
+ float high_pow = 0.f;
+ for (size_t i = 0u; i < num_input_channels; ++i) {
+ for (size_t j = 0u; j < kNarrowbandSize; ++j) {
+ float low_mag = std::abs(input[i][j]);
+ low_pow += low_mag * low_mag;
+ float high_mag = std::abs(input[i][j + kNarrowbandSize]);
+ high_pow += high_mag * high_mag;
+ }
+ }
+ low_pow_ += low_pow / (num_input_channels * kFftSize);
+ high_pow_ += high_pow / (num_input_channels * kFftSize);
+ }
+
+ private:
+ std::unique_ptr<LappedTransform> transform_;
+ float window_[kFftSize];
+ float low_pow_;
+ float high_pow_;
+};
+
+float EncodedPowerRatio(AudioEncoder* encoder,
+ AudioDecoder* decoder,
+ test::AudioLoop* audio_loop) {
+ // Encode and decode.
+ uint32_t rtp_timestamp = 0u;
+ constexpr size_t kBufferSize = 500;
+ rtc::Buffer encoded(kBufferSize);
+ std::vector<int16_t> decoded(kOutputBlockSizeSamples);
+ std::vector<float> decoded_float(kOutputBlockSizeSamples);
+ AudioDecoder::SpeechType speech_type = AudioDecoder::kSpeech;
+ PowerRatioEstimator power_ratio_estimator;
+ for (size_t i = 0; i < 1000; ++i) {
+ encoded.Clear();
+ AudioEncoder::EncodedInfo encoder_info =
+ encoder->Encode(rtp_timestamp, audio_loop->GetNextBlock(), &encoded);
+ rtp_timestamp += kInputBlockSizeSamples;
+ if (encoded.size() > 0) {
+ int decoder_info = decoder->Decode(
+ encoded.data(), encoded.size(), kSampleRateHz,
+ decoded.size() * sizeof(decoded[0]), decoded.data(), &speech_type);
+ if (decoder_info > 0) {
+ S16ToFloat(decoded.data(), decoded.size(), decoded_float.data());
+ power_ratio_estimator.ProcessBlock(decoded_float.data());
+ }
+ }
+ }
+ return power_ratio_estimator.PowerRatio();
+}
+
+} // namespace
+
+// TODO(ivoc): Remove this test, WebRTC-AdjustOpusBandwidth is obsolete.
+TEST(BandwidthAdaptationTest, BandwidthAdaptationTest) {
+ test::ScopedFieldTrials override_field_trials(
+ "WebRTC-AdjustOpusBandwidth/Enabled/");
+
+ constexpr float kMaxNarrowbandRatio = 0.0035f;
+ constexpr float kMinWidebandRatio = 0.01f;
+
+ // Create encoder.
+ AudioEncoderOpusConfig enc_config;
+ enc_config.bitrate_bps = absl::optional<int>(7999);
+ enc_config.num_channels = kNumChannels;
+ constexpr int payload_type = 17;
+ auto encoder = AudioEncoderOpus::MakeAudioEncoder(enc_config, payload_type);
+
+ // Create decoder.
+ AudioDecoderOpus::Config dec_config;
+ dec_config.num_channels = kNumChannels;
+ auto decoder = AudioDecoderOpus::MakeAudioDecoder(dec_config);
+
+ // Open speech file.
+ const std::string kInputFileName =
+ webrtc::test::ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm");
+ test::AudioLoop audio_loop;
+ EXPECT_EQ(kSampleRateHz, encoder->SampleRateHz());
+ ASSERT_TRUE(audio_loop.Init(kInputFileName, kMaxLoopLengthSamples,
+ kInputBlockSizeSamples));
+
+ EXPECT_LT(EncodedPowerRatio(encoder.get(), decoder.get(), &audio_loop),
+ kMaxNarrowbandRatio);
+
+ encoder->OnReceivedTargetAudioBitrate(9000);
+ EXPECT_LT(EncodedPowerRatio(encoder.get(), decoder.get(), &audio_loop),
+ kMaxNarrowbandRatio);
+
+ encoder->OnReceivedTargetAudioBitrate(9001);
+ EXPECT_GT(EncodedPowerRatio(encoder.get(), decoder.get(), &audio_loop),
+ kMinWidebandRatio);
+
+ encoder->OnReceivedTargetAudioBitrate(8000);
+ EXPECT_GT(EncodedPowerRatio(encoder.get(), decoder.get(), &audio_loop),
+ kMinWidebandRatio);
+
+ encoder->OnReceivedTargetAudioBitrate(12001);
+ EXPECT_GT(EncodedPowerRatio(encoder.get(), decoder.get(), &audio_loop),
+ kMinWidebandRatio);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
new file mode 100644
index 0000000000..6388f33303
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/audio_codecs/opus/audio_encoder_opus.h"
+#include "modules/audio_coding/neteq/tools/audio_loop.h"
+#include "rtc_base/time_utils.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+#include "test/testsupport/perf_test.h"
+
+namespace webrtc {
+
+namespace {
+int64_t RunComplexityTest(const AudioEncoderOpusConfig& config) {
+ // Create encoder.
+ constexpr int payload_type = 17;
+ const auto encoder = AudioEncoderOpus::MakeAudioEncoder(config, payload_type);
+ // Open speech file.
+ const std::string kInputFileName =
+ webrtc::test::ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm");
+ test::AudioLoop audio_loop;
+ constexpr int kSampleRateHz = 48000;
+ EXPECT_EQ(kSampleRateHz, encoder->SampleRateHz());
+ constexpr size_t kMaxLoopLengthSamples =
+ kSampleRateHz * 10; // 10 second loop.
+ constexpr size_t kInputBlockSizeSamples =
+ 10 * kSampleRateHz / 1000; // 60 ms.
+ EXPECT_TRUE(audio_loop.Init(kInputFileName, kMaxLoopLengthSamples,
+ kInputBlockSizeSamples));
+ // Encode.
+ const int64_t start_time_ms = rtc::TimeMillis();
+ AudioEncoder::EncodedInfo info;
+ rtc::Buffer encoded(500);
+ uint32_t rtp_timestamp = 0u;
+ for (size_t i = 0; i < 10000; ++i) {
+ encoded.Clear();
+ info = encoder->Encode(rtp_timestamp, audio_loop.GetNextBlock(), &encoded);
+ rtp_timestamp += kInputBlockSizeSamples;
+ }
+ return rtc::TimeMillis() - start_time_ms;
+}
+} // namespace
+
+// This test encodes an audio file using Opus twice with different bitrates
+// (~11 kbps and 15.5 kbps). The runtime for each is measured, and the ratio
+// between the two is calculated and tracked. This test explicitly sets the
+// low_rate_complexity to 9. When running on desktop platforms, this is the same
+// as the regular complexity, and the expectation is that the resulting ratio
+// should be less than 100% (since the encoder runs faster at lower bitrates,
+// given a fixed complexity setting). On the other hand, when running on
+// mobiles, the regular complexity is 5, and we expect the resulting ratio to
+// be higher, since we have explicitly asked for a higher complexity setting at
+// the lower rate.
+TEST(AudioEncoderOpusComplexityAdaptationTest, Adaptation_On) {
+ // Create config.
+ AudioEncoderOpusConfig config;
+ // The limit -- including the hysteresis window -- at which the complexity
+ // shuold be increased.
+ config.bitrate_bps = 11000 - 1;
+ config.low_rate_complexity = 9;
+ int64_t runtime_10999bps = RunComplexityTest(config);
+
+ config.bitrate_bps = 15500;
+ int64_t runtime_15500bps = RunComplexityTest(config);
+
+ test::PrintResult("opus_encoding_complexity_ratio", "", "adaptation_on",
+ 100.0 * runtime_10999bps / runtime_15500bps, "percent",
+ true);
+}
+
+// This test is identical to the one above, but without the complexity
+// adaptation enabled (neither on desktop, nor on mobile). The expectation is
+// that the resulting ratio is less than 100% at all times.
+TEST(AudioEncoderOpusComplexityAdaptationTest, Adaptation_Off) {
+ // Create config.
+ AudioEncoderOpusConfig config;
+ // The limit -- including the hysteresis window -- at which the complexity
+ // shuold be increased (but not in this test since complexity adaptation is
+ // disabled).
+ config.bitrate_bps = 11000 - 1;
+ int64_t runtime_10999bps = RunComplexityTest(config);
+
+ config.bitrate_bps = 15500;
+ int64_t runtime_15500bps = RunComplexityTest(config);
+
+ test::PrintResult("opus_encoding_complexity_ratio", "", "adaptation_off",
+ 100.0 * runtime_10999bps / runtime_15500bps, "percent",
+ true);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
new file mode 100644
index 0000000000..815f26e31c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+using std::get;
+using std::string;
+using std::tuple;
+using ::testing::TestWithParam;
+
+namespace webrtc {
+
+// Define coding parameter as <channels, bit_rate, filename, extension>.
+typedef tuple<size_t, int, string, string> coding_param;
+typedef struct mode mode;
+
+struct mode {
+ bool fec;
+ uint8_t target_packet_loss_rate;
+};
+
+const int kOpusBlockDurationMs = 20;
+const int kOpusSamplingKhz = 48;
+
+class OpusFecTest : public TestWithParam<coding_param> {
+ protected:
+ OpusFecTest();
+
+ void SetUp() override;
+ void TearDown() override;
+
+ virtual void EncodeABlock();
+
+ virtual void DecodeABlock(bool lost_previous, bool lost_current);
+
+ int block_duration_ms_;
+ int sampling_khz_;
+ size_t block_length_sample_;
+
+ size_t channels_;
+ int bit_rate_;
+
+ size_t data_pointer_;
+ size_t loop_length_samples_;
+ size_t max_bytes_;
+ size_t encoded_bytes_;
+
+ WebRtcOpusEncInst* opus_encoder_;
+ WebRtcOpusDecInst* opus_decoder_;
+
+ string in_filename_;
+
+ std::unique_ptr<int16_t[]> in_data_;
+ std::unique_ptr<int16_t[]> out_data_;
+ std::unique_ptr<uint8_t[]> bit_stream_;
+};
+
+void OpusFecTest::SetUp() {
+ channels_ = get<0>(GetParam());
+ bit_rate_ = get<1>(GetParam());
+ printf("Coding %zu channel signal at %d bps.\n", channels_, bit_rate_);
+
+ in_filename_ = test::ResourcePath(get<2>(GetParam()), get<3>(GetParam()));
+
+ FILE* fp = fopen(in_filename_.c_str(), "rb");
+ ASSERT_FALSE(fp == NULL);
+
+ // Obtain file size.
+ fseek(fp, 0, SEEK_END);
+ loop_length_samples_ = ftell(fp) / sizeof(int16_t);
+ rewind(fp);
+
+ // Allocate memory to contain the whole file.
+ in_data_.reset(
+ new int16_t[loop_length_samples_ + block_length_sample_ * channels_]);
+
+ // Copy the file into the buffer.
+ ASSERT_EQ(fread(&in_data_[0], sizeof(int16_t), loop_length_samples_, fp),
+ loop_length_samples_);
+ fclose(fp);
+
+ // The audio will be used in a looped manner. To ease the acquisition of an
+ // audio frame that crosses the end of the excerpt, we add an extra block
+ // length of samples to the end of the array, starting over again from the
+ // beginning of the array. Audio frames cross the end of the excerpt always
+ // appear as a continuum of memory.
+ memcpy(&in_data_[loop_length_samples_], &in_data_[0],
+ block_length_sample_ * channels_ * sizeof(int16_t));
+
+ // Maximum number of bytes in output bitstream.
+ max_bytes_ = block_length_sample_ * channels_ * sizeof(int16_t);
+
+ out_data_.reset(new int16_t[2 * block_length_sample_ * channels_]);
+ bit_stream_.reset(new uint8_t[max_bytes_]);
+
+ // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+ int app = channels_ == 1 ? 0 : 1;
+
+ // Create encoder memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app, 48000));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_, 48000));
+ // Set bitrate.
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
+}
+
+void OpusFecTest::TearDown() {
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+OpusFecTest::OpusFecTest()
+ : block_duration_ms_(kOpusBlockDurationMs),
+ sampling_khz_(kOpusSamplingKhz),
+ block_length_sample_(
+ static_cast<size_t>(block_duration_ms_ * sampling_khz_)),
+ data_pointer_(0),
+ max_bytes_(0),
+ encoded_bytes_(0),
+ opus_encoder_(NULL),
+ opus_decoder_(NULL) {}
+
+void OpusFecTest::EncodeABlock() {
+ int value =
+ WebRtcOpus_Encode(opus_encoder_, &in_data_[data_pointer_],
+ block_length_sample_, max_bytes_, &bit_stream_[0]);
+ EXPECT_GT(value, 0);
+
+ encoded_bytes_ = static_cast<size_t>(value);
+}
+
+void OpusFecTest::DecodeABlock(bool lost_previous, bool lost_current) {
+ int16_t audio_type;
+ int value_1 = 0, value_2 = 0;
+
+ if (lost_previous) {
+ // Decode previous frame.
+ if (!lost_current &&
+ WebRtcOpus_PacketHasFec(&bit_stream_[0], encoded_bytes_) == 1) {
+ value_1 =
+ WebRtcOpus_DecodeFec(opus_decoder_, &bit_stream_[0], encoded_bytes_,
+ &out_data_[0], &audio_type);
+ } else {
+ // Call decoder PLC.
+ while (value_1 < static_cast<int>(block_length_sample_)) {
+ int ret = WebRtcOpus_Decode(opus_decoder_, NULL, 0, &out_data_[value_1],
+ &audio_type);
+ EXPECT_EQ(ret, sampling_khz_ * 10); // Should return 10 ms of samples.
+ value_1 += ret;
+ }
+ }
+ EXPECT_EQ(static_cast<int>(block_length_sample_), value_1);
+ }
+
+ if (!lost_current) {
+ // Decode current frame.
+ value_2 = WebRtcOpus_Decode(opus_decoder_, &bit_stream_[0], encoded_bytes_,
+ &out_data_[value_1 * channels_], &audio_type);
+ EXPECT_EQ(static_cast<int>(block_length_sample_), value_2);
+ }
+}
+
+TEST_P(OpusFecTest, RandomPacketLossTest) {
+ const int kDurationMs = 200000;
+ int time_now_ms, fec_frames;
+ int actual_packet_loss_rate;
+ bool lost_current, lost_previous;
+ mode mode_set[3] = {{true, 0}, {false, 0}, {true, 50}};
+
+ lost_current = false;
+ for (int i = 0; i < 3; i++) {
+ if (mode_set[i].fec) {
+ EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(
+ opus_encoder_, mode_set[i].target_packet_loss_rate));
+ printf("FEC is ON, target at packet loss rate %d percent.\n",
+ mode_set[i].target_packet_loss_rate);
+ } else {
+ EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
+ printf("FEC is OFF.\n");
+ }
+ // In this test, we let the target packet loss rate match the actual rate.
+ actual_packet_loss_rate = mode_set[i].target_packet_loss_rate;
+ // Run every mode a certain time.
+ time_now_ms = 0;
+ fec_frames = 0;
+ while (time_now_ms < kDurationMs) {
+ // Encode & decode.
+ EncodeABlock();
+
+ // Check if payload has FEC.
+ int fec = WebRtcOpus_PacketHasFec(&bit_stream_[0], encoded_bytes_);
+
+ // If FEC is disabled or the target packet loss rate is set to 0, there
+ // should be no FEC in the bit stream.
+ if (!mode_set[i].fec || mode_set[i].target_packet_loss_rate == 0) {
+ EXPECT_EQ(fec, 0);
+ } else if (fec == 1) {
+ fec_frames++;
+ }
+
+ lost_previous = lost_current;
+ lost_current = rand() < actual_packet_loss_rate * (RAND_MAX / 100);
+ DecodeABlock(lost_previous, lost_current);
+
+ time_now_ms += block_duration_ms_;
+
+ // `data_pointer_` is incremented and wrapped across
+ // `loop_length_samples_`.
+ data_pointer_ = (data_pointer_ + block_length_sample_ * channels_) %
+ loop_length_samples_;
+ }
+ if (mode_set[i].fec) {
+ printf("%.2f percent frames has FEC.\n",
+ static_cast<float>(fec_frames) * block_duration_ms_ / 2000);
+ }
+ }
+}
+
+const coding_param param_set[] = {
+ std::make_tuple(1,
+ 64000,
+ string("audio_coding/testfile32kHz"),
+ string("pcm")),
+ std::make_tuple(1,
+ 32000,
+ string("audio_coding/testfile32kHz"),
+ string("pcm")),
+ std::make_tuple(2,
+ 64000,
+ string("audio_coding/teststereo32kHz"),
+ string("pcm"))};
+
+// 64 kbps, stereo
+INSTANTIATE_TEST_SUITE_P(AllTest, OpusFecTest, ::testing::ValuesIn(param_set));
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_inst.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_inst.h
new file mode 100644
index 0000000000..b3a493b157
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_inst.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_
+
+#include <stddef.h>
+
+#include "rtc_base/ignore_wundef.h"
+
+RTC_PUSH_IGNORING_WUNDEF()
+#if defined(WEBRTC_MOZILLA_BUILD)
+#include "opus.h"
+#include "opus_multistream.h"
+#else
+#include "third_party/opus/src/include/opus.h"
+#include "third_party/opus/src/include/opus_multistream.h"
+#endif
+RTC_POP_IGNORING_WUNDEF()
+
+struct WebRtcOpusEncInst {
+ OpusEncoder* encoder;
+ OpusMSEncoder* multistream_encoder;
+ size_t channels;
+ int in_dtx_mode;
+ bool avoid_noise_pumping_during_dtx;
+ int sample_rate_hz;
+ float smooth_energy_non_active_frames;
+};
+
+struct WebRtcOpusDecInst {
+ OpusDecoder* decoder;
+ OpusMSDecoder* multistream_decoder;
+ int prev_decoded_samples;
+ bool plc_use_prev_decoded_samples;
+ size_t channels;
+ int in_dtx_mode;
+ int sample_rate_hz;
+};
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc
new file mode 100644
index 0000000000..033791971f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc
@@ -0,0 +1,878 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+
+#include <cstdlib>
+
+#include <numeric>
+
+#include "api/array_view.h"
+#include "rtc_base/checks.h"
+#include "system_wrappers/include/field_trial.h"
+
+enum {
+#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
+ /* Maximum supported frame size in WebRTC is 120 ms. */
+ kWebRtcOpusMaxEncodeFrameSizeMs = 120,
+#else
+ /* Maximum supported frame size in WebRTC is 60 ms. */
+ kWebRtcOpusMaxEncodeFrameSizeMs = 60,
+#endif
+
+ /* The format allows up to 120 ms frames. Since we don't control the other
+ * side, we must allow for packets of that size. NetEq is currently limited
+ * to 60 ms on the receive side. */
+ kWebRtcOpusMaxDecodeFrameSizeMs = 120,
+
+ // Duration of audio that each call to packet loss concealment covers.
+ kWebRtcOpusPlcFrameSizeMs = 10,
+};
+
+constexpr char kPlcUsePrevDecodedSamplesFieldTrial[] =
+ "WebRTC-Audio-OpusPlcUsePrevDecodedSamples";
+
+constexpr char kAvoidNoisePumpingDuringDtxFieldTrial[] =
+ "WebRTC-Audio-OpusAvoidNoisePumpingDuringDtx";
+
+static int FrameSizePerChannel(int frame_size_ms, int sample_rate_hz) {
+ RTC_DCHECK_GT(frame_size_ms, 0);
+ RTC_DCHECK_EQ(frame_size_ms % 10, 0);
+ RTC_DCHECK_GT(sample_rate_hz, 0);
+ RTC_DCHECK_EQ(sample_rate_hz % 1000, 0);
+ return frame_size_ms * (sample_rate_hz / 1000);
+}
+
+// Maximum sample count per channel.
+static int MaxFrameSizePerChannel(int sample_rate_hz) {
+ return FrameSizePerChannel(kWebRtcOpusMaxDecodeFrameSizeMs, sample_rate_hz);
+}
+
+// Default sample count per channel.
+static int DefaultFrameSizePerChannel(int sample_rate_hz) {
+ return FrameSizePerChannel(20, sample_rate_hz);
+}
+
+// Returns true if the `encoded` payload corresponds to a refresh DTX packet
+// whose energy is larger than the expected for non activity packets.
+static bool WebRtcOpus_IsHighEnergyRefreshDtxPacket(
+ OpusEncInst* inst,
+ rtc::ArrayView<const int16_t> frame,
+ rtc::ArrayView<const uint8_t> encoded) {
+ if (encoded.size() <= 2) {
+ return false;
+ }
+ int number_frames =
+ frame.size() / DefaultFrameSizePerChannel(inst->sample_rate_hz);
+ if (number_frames > 0 &&
+ WebRtcOpus_PacketHasVoiceActivity(encoded.data(), encoded.size()) == 0) {
+ const float average_frame_energy =
+ std::accumulate(frame.begin(), frame.end(), 0.0f,
+ [](float a, int32_t b) { return a + b * b; }) /
+ number_frames;
+ if (WebRtcOpus_GetInDtx(inst) == 1 &&
+ average_frame_energy >= inst->smooth_energy_non_active_frames * 0.5f) {
+ // This is a refresh DTX packet as the encoder is in DTX and has
+ // produced a payload > 2 bytes. This refresh packet has a higher energy
+ // than the smooth energy of non activity frames (with a 3 dB negative
+ // margin) and, therefore, it is flagged as a high energy refresh DTX
+ // packet.
+ return true;
+ }
+ // The average energy is tracked in a similar way as the modeling of the
+ // comfort noise in the Silk decoder in Opus
+ // (third_party/opus/src/silk/CNG.c).
+ if (average_frame_energy < inst->smooth_energy_non_active_frames * 0.5f) {
+ inst->smooth_energy_non_active_frames = average_frame_energy;
+ } else {
+ inst->smooth_energy_non_active_frames +=
+ (average_frame_energy - inst->smooth_energy_non_active_frames) *
+ 0.25f;
+ }
+ }
+ return false;
+}
+
+int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
+ size_t channels,
+ int32_t application,
+ int sample_rate_hz) {
+ int opus_app;
+ if (!inst)
+ return -1;
+
+ switch (application) {
+ case 0:
+ opus_app = OPUS_APPLICATION_VOIP;
+ break;
+ case 1:
+ opus_app = OPUS_APPLICATION_AUDIO;
+ break;
+ default:
+ return -1;
+ }
+
+ OpusEncInst* state =
+ reinterpret_cast<OpusEncInst*>(calloc(1, sizeof(OpusEncInst)));
+ RTC_DCHECK(state);
+
+ int error;
+ state->encoder = opus_encoder_create(
+ sample_rate_hz, static_cast<int>(channels), opus_app, &error);
+
+ if (error != OPUS_OK || (!state->encoder && !state->multistream_encoder)) {
+ WebRtcOpus_EncoderFree(state);
+ return -1;
+ }
+
+ state->in_dtx_mode = 0;
+ state->channels = channels;
+ state->sample_rate_hz = sample_rate_hz;
+ state->smooth_energy_non_active_frames = 0.0f;
+ state->avoid_noise_pumping_during_dtx =
+ webrtc::field_trial::IsEnabled(kAvoidNoisePumpingDuringDtxFieldTrial);
+
+ *inst = state;
+ return 0;
+}
+
+int16_t WebRtcOpus_MultistreamEncoderCreate(
+ OpusEncInst** inst,
+ size_t channels,
+ int32_t application,
+ size_t streams,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping) {
+ int opus_app;
+ if (!inst)
+ return -1;
+
+ switch (application) {
+ case 0:
+ opus_app = OPUS_APPLICATION_VOIP;
+ break;
+ case 1:
+ opus_app = OPUS_APPLICATION_AUDIO;
+ break;
+ default:
+ return -1;
+ }
+
+ OpusEncInst* state =
+ reinterpret_cast<OpusEncInst*>(calloc(1, sizeof(OpusEncInst)));
+ RTC_DCHECK(state);
+
+ int error;
+ const int sample_rate_hz = 48000;
+ state->multistream_encoder = opus_multistream_encoder_create(
+ sample_rate_hz, channels, streams, coupled_streams, channel_mapping,
+ opus_app, &error);
+
+ if (error != OPUS_OK || (!state->encoder && !state->multistream_encoder)) {
+ WebRtcOpus_EncoderFree(state);
+ return -1;
+ }
+
+ state->in_dtx_mode = 0;
+ state->channels = channels;
+ state->sample_rate_hz = sample_rate_hz;
+ state->smooth_energy_non_active_frames = 0.0f;
+ state->avoid_noise_pumping_during_dtx = false;
+
+ *inst = state;
+ return 0;
+}
+
+int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
+ if (inst) {
+ if (inst->encoder) {
+ opus_encoder_destroy(inst->encoder);
+ } else {
+ opus_multistream_encoder_destroy(inst->multistream_encoder);
+ }
+ free(inst);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int WebRtcOpus_Encode(OpusEncInst* inst,
+ const int16_t* audio_in,
+ size_t samples,
+ size_t length_encoded_buffer,
+ uint8_t* encoded) {
+ int res;
+
+ if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
+ return -1;
+ }
+
+ if (inst->encoder) {
+ res = opus_encode(inst->encoder, (const opus_int16*)audio_in,
+ static_cast<int>(samples), encoded,
+ static_cast<opus_int32>(length_encoded_buffer));
+ } else {
+ res = opus_multistream_encode(
+ inst->multistream_encoder, (const opus_int16*)audio_in,
+ static_cast<int>(samples), encoded,
+ static_cast<opus_int32>(length_encoded_buffer));
+ }
+
+ if (res <= 0) {
+ return -1;
+ }
+
+ if (res <= 2) {
+ // Indicates DTX since the packet has nothing but a header. In principle,
+ // there is no need to send this packet. However, we do transmit the first
+ // occurrence to let the decoder know that the encoder enters DTX mode.
+ if (inst->in_dtx_mode) {
+ return 0;
+ } else {
+ inst->in_dtx_mode = 1;
+ return res;
+ }
+ }
+
+ if (inst->avoid_noise_pumping_during_dtx && WebRtcOpus_GetUseDtx(inst) == 1 &&
+ WebRtcOpus_IsHighEnergyRefreshDtxPacket(
+ inst, rtc::MakeArrayView(audio_in, samples),
+ rtc::MakeArrayView(encoded, res))) {
+ // This packet is a high energy refresh DTX packet. For avoiding an increase
+ // of the energy in the DTX region at the decoder, this packet is
+ // substituted by a TOC byte with one empty frame.
+ // The number of frames described in the TOC byte
+ // (https://tools.ietf.org/html/rfc6716#section-3.1) are overwritten to
+ // always indicate one frame (last two bits equal to 0).
+ encoded[0] = encoded[0] & 0b11111100;
+ inst->in_dtx_mode = 1;
+ // The payload is just the TOC byte and has 1 byte as length.
+ return 1;
+ }
+ inst->in_dtx_mode = 0;
+ return res;
+}
+
+#define ENCODER_CTL(inst, vargs) \
+ (inst->encoder \
+ ? opus_encoder_ctl(inst->encoder, vargs) \
+ : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs))
+
+int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_BITRATE(rate));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_PACKET_LOSS_PERC(loss_rate));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz) {
+ opus_int32 set_bandwidth;
+
+ if (!inst)
+ return -1;
+
+ if (frequency_hz <= 8000) {
+ set_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
+ } else if (frequency_hz <= 12000) {
+ set_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
+ } else if (frequency_hz <= 16000) {
+ set_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
+ } else if (frequency_hz <= 24000) {
+ set_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
+ } else {
+ set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
+ }
+ return ENCODER_CTL(inst, OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
+}
+
+int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
+ int32_t* result_hz) {
+ if (inst->encoder) {
+ if (opus_encoder_ctl(inst->encoder, OPUS_GET_MAX_BANDWIDTH(result_hz)) ==
+ OPUS_OK) {
+ return 0;
+ }
+ return -1;
+ }
+
+ opus_int32 max_bandwidth;
+ int s;
+ int ret;
+
+ max_bandwidth = 0;
+ ret = OPUS_OK;
+ s = 0;
+ while (ret == OPUS_OK) {
+ OpusEncoder* enc;
+ opus_int32 bandwidth;
+
+ ret = ENCODER_CTL(inst, OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
+ if (ret == OPUS_BAD_ARG)
+ break;
+ if (ret != OPUS_OK)
+ return -1;
+ if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
+ return -1;
+
+ if (max_bandwidth != 0 && max_bandwidth != bandwidth)
+ return -1;
+
+ max_bandwidth = bandwidth;
+ s++;
+ }
+ *result_hz = max_bandwidth;
+ return 0;
+}
+
+int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(1));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(0));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst) {
+ if (!inst) {
+ return -1;
+ }
+
+ // To prevent Opus from entering CELT-only mode by forcing signal type to
+ // voice to make sure that DTX behaves correctly. Currently, DTX does not
+ // last long during a pure silence, if the signal type is not forced.
+ // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
+ // without it.
+ int ret = ENCODER_CTL(inst, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
+ if (ret != OPUS_OK)
+ return ret;
+
+ return ENCODER_CTL(inst, OPUS_SET_DTX(1));
+}
+
+int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
+ if (inst) {
+ int ret = ENCODER_CTL(inst, OPUS_SET_SIGNAL(OPUS_AUTO));
+ if (ret != OPUS_OK)
+ return ret;
+ return ENCODER_CTL(inst, OPUS_SET_DTX(0));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_GetUseDtx(OpusEncInst* inst) {
+ if (inst) {
+ opus_int32 use_dtx;
+ if (ENCODER_CTL(inst, OPUS_GET_DTX(&use_dtx)) == 0) {
+ return use_dtx;
+ }
+ }
+ return -1;
+}
+
+int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_VBR(0));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_VBR(1));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_COMPLEXITY(complexity));
+ } else {
+ return -1;
+ }
+}
+
+int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst) {
+ if (!inst) {
+ return -1;
+ }
+ int32_t bandwidth;
+ if (ENCODER_CTL(inst, OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
+ return bandwidth;
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
+ if (inst) {
+ return ENCODER_CTL(inst, OPUS_SET_BANDWIDTH(bandwidth));
+ } else {
+ return -1;
+ }
+}
+
+int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
+ if (!inst)
+ return -1;
+ if (num_channels == 0) {
+ return ENCODER_CTL(inst, OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
+ } else if (num_channels == 1 || num_channels == 2) {
+ return ENCODER_CTL(inst, OPUS_SET_FORCE_CHANNELS(num_channels));
+ } else {
+ return -1;
+ }
+}
+
+int32_t WebRtcOpus_GetInDtx(OpusEncInst* inst) {
+ if (!inst) {
+ return -1;
+ }
+#ifdef OPUS_GET_IN_DTX
+ int32_t in_dtx;
+ if (ENCODER_CTL(inst, OPUS_GET_IN_DTX(&in_dtx)) == 0) {
+ return in_dtx;
+ }
+#endif
+ return -1;
+}
+
+int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst,
+ size_t channels,
+ int sample_rate_hz) {
+ int error;
+ OpusDecInst* state;
+
+ if (inst != NULL) {
+ // Create Opus decoder state.
+ state = reinterpret_cast<OpusDecInst*>(calloc(1, sizeof(OpusDecInst)));
+ if (state == NULL) {
+ return -1;
+ }
+
+ state->decoder =
+ opus_decoder_create(sample_rate_hz, static_cast<int>(channels), &error);
+ if (error == OPUS_OK && state->decoder) {
+ // Creation of memory all ok.
+ state->channels = channels;
+ state->sample_rate_hz = sample_rate_hz;
+ state->plc_use_prev_decoded_samples =
+ webrtc::field_trial::IsEnabled(kPlcUsePrevDecodedSamplesFieldTrial);
+ if (state->plc_use_prev_decoded_samples) {
+ state->prev_decoded_samples =
+ DefaultFrameSizePerChannel(state->sample_rate_hz);
+ }
+ state->in_dtx_mode = 0;
+ *inst = state;
+ return 0;
+ }
+
+ // If memory allocation was unsuccessful, free the entire state.
+ if (state->decoder) {
+ opus_decoder_destroy(state->decoder);
+ }
+ free(state);
+ }
+ return -1;
+}
+
+int16_t WebRtcOpus_MultistreamDecoderCreate(
+ OpusDecInst** inst,
+ size_t channels,
+ size_t streams,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping) {
+ int error;
+ OpusDecInst* state;
+
+ if (inst != NULL) {
+ // Create Opus decoder state.
+ state = reinterpret_cast<OpusDecInst*>(calloc(1, sizeof(OpusDecInst)));
+ if (state == NULL) {
+ return -1;
+ }
+
+ // Create new memory, always at 48000 Hz.
+ state->multistream_decoder = opus_multistream_decoder_create(
+ 48000, channels, streams, coupled_streams, channel_mapping, &error);
+
+ if (error == OPUS_OK && state->multistream_decoder) {
+ // Creation of memory all ok.
+ state->channels = channels;
+ state->sample_rate_hz = 48000;
+ state->plc_use_prev_decoded_samples =
+ webrtc::field_trial::IsEnabled(kPlcUsePrevDecodedSamplesFieldTrial);
+ if (state->plc_use_prev_decoded_samples) {
+ state->prev_decoded_samples =
+ DefaultFrameSizePerChannel(state->sample_rate_hz);
+ }
+ state->in_dtx_mode = 0;
+ *inst = state;
+ return 0;
+ }
+
+ // If memory allocation was unsuccessful, free the entire state.
+ opus_multistream_decoder_destroy(state->multistream_decoder);
+ free(state);
+ }
+ return -1;
+}
+
+int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
+ if (inst) {
+ if (inst->decoder) {
+ opus_decoder_destroy(inst->decoder);
+ } else if (inst->multistream_decoder) {
+ opus_multistream_decoder_destroy(inst->multistream_decoder);
+ }
+ free(inst);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) {
+ return inst->channels;
+}
+
+void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
+ if (inst->decoder) {
+ opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
+ } else {
+ opus_multistream_decoder_ctl(inst->multistream_decoder, OPUS_RESET_STATE);
+ }
+ inst->in_dtx_mode = 0;
+}
+
+/* For decoder to determine if it is to output speech or comfort noise. */
+static int16_t DetermineAudioType(OpusDecInst* inst, size_t encoded_bytes) {
+ // Audio type becomes comfort noise if `encoded_byte` is 1 and keeps
+ // to be so if the following `encoded_byte` are 0 or 1.
+ if (encoded_bytes == 0 && inst->in_dtx_mode) {
+ return 2; // Comfort noise.
+ } else if (encoded_bytes == 1 || encoded_bytes == 2) {
+ // TODO(henrik.lundin): There is a slight risk that a 2-byte payload is in
+ // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
+ // interpreted as comfort noise output, but such a payload is probably
+ // faulty anyway.
+
+ // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
+ // single-stream packets glued together with some packet size bytes in
+ // between. See https://tools.ietf.org/html/rfc6716#appendix-B
+ inst->in_dtx_mode = 1;
+ return 2; // Comfort noise.
+ } else {
+ inst->in_dtx_mode = 0;
+ return 0; // Speech.
+ }
+}
+
+/* `frame_size` is set to maximum Opus frame size in the normal case, and
+ * is set to the number of samples needed for PLC in case of losses.
+ * It is up to the caller to make sure the value is correct. */
+static int DecodeNative(OpusDecInst* inst,
+ const uint8_t* encoded,
+ size_t encoded_bytes,
+ int frame_size,
+ int16_t* decoded,
+ int16_t* audio_type,
+ int decode_fec) {
+ int res = -1;
+ if (inst->decoder) {
+ res = opus_decode(
+ inst->decoder, encoded, static_cast<opus_int32>(encoded_bytes),
+ reinterpret_cast<opus_int16*>(decoded), frame_size, decode_fec);
+ } else {
+ res = opus_multistream_decode(inst->multistream_decoder, encoded,
+ static_cast<opus_int32>(encoded_bytes),
+ reinterpret_cast<opus_int16*>(decoded),
+ frame_size, decode_fec);
+ }
+
+ if (res <= 0)
+ return -1;
+
+ *audio_type = DetermineAudioType(inst, encoded_bytes);
+
+ return res;
+}
+
+static int DecodePlc(OpusDecInst* inst, int16_t* decoded) {
+ int16_t audio_type = 0;
+ int decoded_samples;
+ int plc_samples =
+ FrameSizePerChannel(kWebRtcOpusPlcFrameSizeMs, inst->sample_rate_hz);
+
+ if (inst->plc_use_prev_decoded_samples) {
+ /* The number of samples we ask for is `number_of_lost_frames` times
+ * `prev_decoded_samples_`. Limit the number of samples to maximum
+ * `MaxFrameSizePerChannel()`. */
+ plc_samples = inst->prev_decoded_samples;
+ const int max_samples_per_channel =
+ MaxFrameSizePerChannel(inst->sample_rate_hz);
+ plc_samples = plc_samples <= max_samples_per_channel
+ ? plc_samples
+ : max_samples_per_channel;
+ }
+ decoded_samples =
+ DecodeNative(inst, NULL, 0, plc_samples, decoded, &audio_type, 0);
+ if (decoded_samples < 0) {
+ return -1;
+ }
+
+ return decoded_samples;
+}
+
+int WebRtcOpus_Decode(OpusDecInst* inst,
+ const uint8_t* encoded,
+ size_t encoded_bytes,
+ int16_t* decoded,
+ int16_t* audio_type) {
+ int decoded_samples;
+
+ if (encoded_bytes == 0) {
+ *audio_type = DetermineAudioType(inst, encoded_bytes);
+ decoded_samples = DecodePlc(inst, decoded);
+ } else {
+ decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
+ MaxFrameSizePerChannel(inst->sample_rate_hz),
+ decoded, audio_type, 0);
+ }
+ if (decoded_samples < 0) {
+ return -1;
+ }
+
+ if (inst->plc_use_prev_decoded_samples) {
+ /* Update decoded sample memory, to be used by the PLC in case of losses. */
+ inst->prev_decoded_samples = decoded_samples;
+ }
+
+ return decoded_samples;
+}
+
+int WebRtcOpus_DecodeFec(OpusDecInst* inst,
+ const uint8_t* encoded,
+ size_t encoded_bytes,
+ int16_t* decoded,
+ int16_t* audio_type) {
+ int decoded_samples;
+ int fec_samples;
+
+ if (WebRtcOpus_PacketHasFec(encoded, encoded_bytes) != 1) {
+ return 0;
+ }
+
+ fec_samples =
+ opus_packet_get_samples_per_frame(encoded, inst->sample_rate_hz);
+
+ decoded_samples = DecodeNative(inst, encoded, encoded_bytes, fec_samples,
+ decoded, audio_type, 1);
+ if (decoded_samples < 0) {
+ return -1;
+ }
+
+ return decoded_samples;
+}
+
+int WebRtcOpus_DurationEst(OpusDecInst* inst,
+ const uint8_t* payload,
+ size_t payload_length_bytes) {
+ if (payload_length_bytes == 0) {
+ // WebRtcOpus_Decode calls PLC when payload length is zero. So we return
+ // PLC duration correspondingly.
+ return WebRtcOpus_PlcDuration(inst);
+ }
+
+ int frames, samples;
+ frames = opus_packet_get_nb_frames(
+ payload, static_cast<opus_int32>(payload_length_bytes));
+ if (frames < 0) {
+ /* Invalid payload data. */
+ return 0;
+ }
+ samples =
+ frames * opus_packet_get_samples_per_frame(payload, inst->sample_rate_hz);
+ if (samples > 120 * inst->sample_rate_hz / 1000) {
+ // More than 120 ms' worth of samples.
+ return 0;
+ }
+ return samples;
+}
+
+int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
+ if (inst->plc_use_prev_decoded_samples) {
+ /* The number of samples we ask for is `number_of_lost_frames` times
+ * `prev_decoded_samples_`. Limit the number of samples to maximum
+ * `MaxFrameSizePerChannel()`. */
+ const int plc_samples = inst->prev_decoded_samples;
+ const int max_samples_per_channel =
+ MaxFrameSizePerChannel(inst->sample_rate_hz);
+ return plc_samples <= max_samples_per_channel ? plc_samples
+ : max_samples_per_channel;
+ }
+ return FrameSizePerChannel(kWebRtcOpusPlcFrameSizeMs, inst->sample_rate_hz);
+}
+
+int WebRtcOpus_FecDurationEst(const uint8_t* payload,
+ size_t payload_length_bytes,
+ int sample_rate_hz) {
+ if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
+ return 0;
+ }
+ const int samples =
+ opus_packet_get_samples_per_frame(payload, sample_rate_hz);
+ const int samples_per_ms = sample_rate_hz / 1000;
+ if (samples < 10 * samples_per_ms || samples > 120 * samples_per_ms) {
+ /* Invalid payload duration. */
+ return 0;
+ }
+ return samples;
+}
+
+int WebRtcOpus_NumSilkFrames(const uint8_t* payload) {
+ // For computing the payload length in ms, the sample rate is not important
+ // since it cancels out. We use 48 kHz, but any valid sample rate would work.
+ int payload_length_ms =
+ opus_packet_get_samples_per_frame(payload, 48000) / 48;
+ if (payload_length_ms < 10)
+ payload_length_ms = 10;
+
+ int silk_frames;
+ switch (payload_length_ms) {
+ case 10:
+ case 20:
+ silk_frames = 1;
+ break;
+ case 40:
+ silk_frames = 2;
+ break;
+ case 60:
+ silk_frames = 3;
+ break;
+ default:
+ return 0; // It is actually even an invalid packet.
+ }
+ return silk_frames;
+}
+
+// This method is based on Definition of the Opus Audio Codec
+// (https://tools.ietf.org/html/rfc6716). Basically, this method is based on
+// parsing the LP layer of an Opus packet, particularly the LBRR flag.
+int WebRtcOpus_PacketHasFec(const uint8_t* payload,
+ size_t payload_length_bytes) {
+ if (payload == NULL || payload_length_bytes == 0)
+ return 0;
+
+ // In CELT_ONLY mode, packets should not have FEC.
+ if (payload[0] & 0x80)
+ return 0;
+
+ int silk_frames = WebRtcOpus_NumSilkFrames(payload);
+ if (silk_frames == 0)
+ return 0; // Not valid.
+
+ const int channels = opus_packet_get_nb_channels(payload);
+ RTC_DCHECK(channels == 1 || channels == 2);
+
+ // Max number of frames in an Opus packet is 48.
+ opus_int16 frame_sizes[48];
+ const unsigned char* frame_data[48];
+
+ // Parse packet to get the frames. But we only care about the first frame,
+ // since we can only decode the FEC from the first one.
+ if (opus_packet_parse(payload, static_cast<opus_int32>(payload_length_bytes),
+ NULL, frame_data, frame_sizes, NULL) < 0) {
+ return 0;
+ }
+
+ if (frame_sizes[0] < 1) {
+ return 0;
+ }
+
+ // A frame starts with the LP layer. The LP layer begins with two to eight
+ // header bits.These consist of one VAD bit per SILK frame (up to 3),
+ // followed by a single flag indicating the presence of LBRR frames.
+ // For a stereo packet, these first flags correspond to the mid channel, and
+ // a second set of flags is included for the side channel. Because these are
+ // the first symbols decoded by the range coder and because they are coded
+ // as binary values with uniform probability, they can be extracted directly
+ // from the most significant bits of the first byte of compressed data.
+ for (int n = 0; n < channels; n++) {
+ // The LBRR bit for channel 1 is on the (`silk_frames` + 1)-th bit, and
+ // that of channel 2 is on the |(`silk_frames` + 1) * 2 + 1|-th bit.
+ if (frame_data[0][0] & (0x80 >> ((n + 1) * (silk_frames + 1) - 1)))
+ return 1;
+ }
+
+ return 0;
+}
+
+int WebRtcOpus_PacketHasVoiceActivity(const uint8_t* payload,
+ size_t payload_length_bytes) {
+ if (payload == NULL || payload_length_bytes == 0)
+ return 0;
+
+ // In CELT_ONLY mode we can not determine whether there is VAD.
+ if (payload[0] & 0x80)
+ return -1;
+
+ int silk_frames = WebRtcOpus_NumSilkFrames(payload);
+ if (silk_frames == 0)
+ return -1;
+
+ const int channels = opus_packet_get_nb_channels(payload);
+ RTC_DCHECK(channels == 1 || channels == 2);
+
+ // Max number of frames in an Opus packet is 48.
+ opus_int16 frame_sizes[48];
+ const unsigned char* frame_data[48];
+
+ // Parse packet to get the frames.
+ int frames =
+ opus_packet_parse(payload, static_cast<opus_int32>(payload_length_bytes),
+ NULL, frame_data, frame_sizes, NULL);
+ if (frames < 0)
+ return -1;
+
+ // Iterate over all Opus frames which may contain multiple SILK frames.
+ for (int frame = 0; frame < frames; frame++) {
+ if (frame_sizes[frame] < 1) {
+ continue;
+ }
+ if (frame_data[frame][0] >> (8 - silk_frames))
+ return 1;
+ if (channels == 2 &&
+ (frame_data[frame][0] << (silk_frames + 1)) >> (8 - silk_frames))
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.h
new file mode 100644
index 0000000000..89159ce1c0
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.h
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INTERFACE_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INTERFACE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/opus/opus_inst.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Opaque wrapper types for the codec state.
+typedef struct WebRtcOpusEncInst OpusEncInst;
+typedef struct WebRtcOpusDecInst OpusDecInst;
+
+/****************************************************************************
+ * WebRtcOpus_EncoderCreate(...)
+ *
+ * This function creates an Opus encoder that encodes mono or stereo.
+ *
+ * Input:
+ * - channels : number of channels; 1 or 2.
+ * - application : 0 - VOIP applications.
+ * Favor speech intelligibility.
+ * 1 - Audio applications.
+ * Favor faithfulness to the original input.
+ * - sample_rate_hz : sample rate of input audio
+ *
+ * Output:
+ * - inst : a pointer to Encoder context that is created
+ * if success.
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
+ size_t channels,
+ int32_t application,
+ int sample_rate_hz);
+
+/****************************************************************************
+ * WebRtcOpus_MultistreamEncoderCreate(...)
+ *
+ * This function creates an Opus encoder with any supported channel count.
+ *
+ * Input:
+ * - channels : number of channels in the input of the encoder.
+ * - application : 0 - VOIP applications.
+ * Favor speech intelligibility.
+ * 1 - Audio applications.
+ * Favor faithfulness to the original input.
+ * - streams : number of streams, as described in RFC 7845.
+ * - coupled_streams : number of coupled streams, as described in
+ * RFC 7845.
+ * - channel_mapping : the channel mapping; pointer to array of
+ * `channel` bytes, as described in RFC 7845.
+ *
+ * Output:
+ * - inst : a pointer to Encoder context that is created
+ * if success.
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_MultistreamEncoderCreate(
+ OpusEncInst** inst,
+ size_t channels,
+ int32_t application,
+ size_t streams,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping);
+
+int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_Encode(...)
+ *
+ * This function encodes audio as a series of Opus frames and inserts
+ * it into a packet. Input buffer can be any length.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - audio_in : Input speech data buffer
+ * - samples : Samples per channel in audio_in
+ * - length_encoded_buffer : Output buffer size
+ *
+ * Output:
+ * - encoded : Output compressed data buffer
+ *
+ * Return value : >=0 - Length (in bytes) of coded data
+ * -1 - Error
+ */
+int WebRtcOpus_Encode(OpusEncInst* inst,
+ const int16_t* audio_in,
+ size_t samples,
+ size_t length_encoded_buffer,
+ uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcOpus_SetBitRate(...)
+ *
+ * This function adjusts the target bitrate of the encoder.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - rate : New target bitrate
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate);
+
+/****************************************************************************
+ * WebRtcOpus_SetPacketLossRate(...)
+ *
+ * This function configures the encoder's expected packet loss percentage.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - loss_rate : loss percentage in the range 0-100, inclusive.
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate);
+
+/****************************************************************************
+ * WebRtcOpus_SetMaxPlaybackRate(...)
+ *
+ * Configures the maximum playback rate for encoding. Due to hardware
+ * limitations, the receiver may render audio up to a playback rate. Opus
+ * encoder can use this information to optimize for network usage and encoding
+ * complexity. This will affect the audio bandwidth in the coded audio. However,
+ * the input/output sample rate is not affected.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - frequency_hz : Maximum playback rate in Hz.
+ * This parameter can take any value. The relation
+ * between the value and the Opus internal mode is
+ * as following:
+ * frequency_hz <= 8000 narrow band
+ * 8000 < frequency_hz <= 12000 medium band
+ * 12000 < frequency_hz <= 16000 wide band
+ * 16000 < frequency_hz <= 24000 super wide band
+ * frequency_hz > 24000 full band
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz);
+
+/****************************************************************************
+ * WebRtcOpus_GetMaxPlaybackRate(...)
+ *
+ * Queries the maximum playback rate for encoding. If different single-stream
+ * encoders have different maximum playback rates, this function fails.
+ *
+ * Input:
+ * - inst : Encoder context.
+ * Output:
+ * - result_hz : The maximum playback rate in Hz.
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
+ int32_t* result_hz);
+
+/* TODO(minyue): Check whether an API to check the FEC and the packet loss rate
+ * is needed. It might not be very useful since there are not many use cases and
+ * the caller can always maintain the states. */
+
+/****************************************************************************
+ * WebRtcOpus_EnableFec()
+ *
+ * This function enables FEC for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_EnableFec(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_DisableFec()
+ *
+ * This function disables FEC for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_DisableFec(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_EnableDtx()
+ *
+ * This function enables Opus internal DTX for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_EnableDtx(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_DisableDtx()
+ *
+ * This function disables Opus internal DTX for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_GetUseDtx()
+ *
+ * This function gets the DTX configuration used for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Encoder does not use DTX.
+ * 1 - Encoder uses DTX.
+ * -1 - Error.
+ */
+int16_t WebRtcOpus_GetUseDtx(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_EnableCbr()
+ *
+ * This function enables CBR for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_DisableCbr()
+ *
+ * This function disables CBR for encoding.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst);
+
+/*
+ * WebRtcOpus_SetComplexity(...)
+ *
+ * This function adjusts the computational complexity. The effect is the same as
+ * calling the complexity setting of Opus as an Opus encoder related CTL.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - complexity : New target complexity (0-10, inclusive)
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity);
+
+/*
+ * WebRtcOpus_GetBandwidth(...)
+ *
+ * This function returns the current bandwidth.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : Bandwidth - Success
+ * -1 - Error
+ */
+int32_t WebRtcOpus_GetBandwidth(OpusEncInst* inst);
+
+/*
+ * WebRtcOpus_SetBandwidth(...)
+ *
+ * By default Opus decides which bandwidth to encode the signal in depending on
+ * the the bitrate. This function overrules the previous setting and forces the
+ * encoder to encode in narrowband/wideband/fullband/etc.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - bandwidth : New target bandwidth. Valid values are:
+ * OPUS_BANDWIDTH_NARROWBAND
+ * OPUS_BANDWIDTH_MEDIUMBAND
+ * OPUS_BANDWIDTH_WIDEBAND
+ * OPUS_BANDWIDTH_SUPERWIDEBAND
+ * OPUS_BANDWIDTH_FULLBAND
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth);
+
+/*
+ * WebRtcOpus_GetInDtx(...)
+ *
+ * Gets the DTX state of the encoder.
+ *
+ * Input:
+ * - inst : Encoder context
+ *
+ * Return value : -1 - Error.
+ * 1 - Last encoded frame was comfort noise update during DTX.
+ * 0 - Last encoded frame was encoded with encoder not in DTX.
+ */
+int32_t WebRtcOpus_GetInDtx(OpusEncInst* inst);
+
+/*
+ * WebRtcOpus_SetForceChannels(...)
+ *
+ * If the encoder is initialized as a stereo encoder, Opus will by default
+ * decide whether to encode in mono or stereo based on the bitrate. This
+ * function overrules the previous setting, and forces the encoder to encode
+ * in auto/mono/stereo.
+ *
+ * If the Encoder is initialized as a mono encoder, and one tries to force
+ * stereo, the function will return an error.
+ *
+ * Input:
+ * - inst : Encoder context
+ * - num_channels : 0 - Not forced
+ * 1 - Mono
+ * 2 - Stereo
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels);
+
+int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst,
+ size_t channels,
+ int sample_rate_hz);
+
+/****************************************************************************
+ * WebRtcOpus_MultistreamDecoderCreate(...)
+ *
+ * This function creates an Opus decoder with any supported channel count.
+ *
+ * Input:
+ * - channels : number of output channels that the decoder
+ * will produce.
+ * - streams : number of encoded streams, as described in
+ * RFC 7845.
+ * - coupled_streams : number of coupled streams, as described in
+ * RFC 7845.
+ * - channel_mapping : the channel mapping; pointer to array of
+ * `channel` bytes, as described in RFC 7845.
+ *
+ * Output:
+ * - inst : a pointer to a Decoder context that is created
+ * if success.
+ *
+ * Return value : 0 - Success
+ * -1 - Error
+ */
+int16_t WebRtcOpus_MultistreamDecoderCreate(
+ OpusDecInst** inst,
+ size_t channels,
+ size_t streams,
+ size_t coupled_streams,
+ const unsigned char* channel_mapping);
+
+int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_DecoderChannels(...)
+ *
+ * This function returns the number of channels created for Opus decoder.
+ */
+size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_DecoderInit(...)
+ *
+ * This function resets state of the decoder.
+ *
+ * Input:
+ * - inst : Decoder context
+ */
+void WebRtcOpus_DecoderInit(OpusDecInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_Decode(...)
+ *
+ * This function decodes an Opus packet into one or more audio frames at the
+ * ACM interface's sampling rate (32 kHz).
+ *
+ * Input:
+ * - inst : Decoder context
+ * - encoded : Encoded data
+ * - encoded_bytes : Bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ * - audio_type : 1 normal, 2 CNG (for Opus it should
+ * always return 1 since we're not using Opus's
+ * built-in DTX/CNG scheme)
+ *
+ * Return value : >0 - Samples per channel in decoded vector
+ * -1 - Error
+ */
+int WebRtcOpus_Decode(OpusDecInst* inst,
+ const uint8_t* encoded,
+ size_t encoded_bytes,
+ int16_t* decoded,
+ int16_t* audio_type);
+
+/****************************************************************************
+ * WebRtcOpus_DecodeFec(...)
+ *
+ * This function decodes the FEC data from an Opus packet into one or more audio
+ * frames at the ACM interface's sampling rate (32 kHz).
+ *
+ * Input:
+ * - inst : Decoder context
+ * - encoded : Encoded data
+ * - encoded_bytes : Bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector (previous frame)
+ *
+ * Return value : >0 - Samples per channel in decoded vector
+ * 0 - No FEC data in the packet
+ * -1 - Error
+ */
+int WebRtcOpus_DecodeFec(OpusDecInst* inst,
+ const uint8_t* encoded,
+ size_t encoded_bytes,
+ int16_t* decoded,
+ int16_t* audio_type);
+
+/****************************************************************************
+ * WebRtcOpus_DurationEst(...)
+ *
+ * This function calculates the duration of an opus packet.
+ * Input:
+ * - inst : Decoder context
+ * - payload : Encoded data pointer
+ * - payload_length_bytes : Bytes of encoded data
+ *
+ * Return value : The duration of the packet, in samples per
+ * channel.
+ */
+int WebRtcOpus_DurationEst(OpusDecInst* inst,
+ const uint8_t* payload,
+ size_t payload_length_bytes);
+
+/****************************************************************************
+ * WebRtcOpus_PlcDuration(...)
+ *
+ * This function calculates the duration of a frame returned by packet loss
+ * concealment (PLC).
+ *
+ * Input:
+ * - inst : Decoder context
+ *
+ * Return value : The duration of a frame returned by PLC, in
+ * samples per channel.
+ */
+int WebRtcOpus_PlcDuration(OpusDecInst* inst);
+
+/* TODO(minyue): Check whether it is needed to add a decoder context to the
+ * arguments, like WebRtcOpus_DurationEst(...). In fact, the packet itself tells
+ * the duration. The decoder context in WebRtcOpus_DurationEst(...) is not used.
+ * So it may be advisable to remove it from WebRtcOpus_DurationEst(...). */
+
+/****************************************************************************
+ * WebRtcOpus_FecDurationEst(...)
+ *
+ * This function calculates the duration of the FEC data within an opus packet.
+ * Input:
+ * - payload : Encoded data pointer
+ * - payload_length_bytes : Bytes of encoded data
+ * - sample_rate_hz : Sample rate of output audio
+ *
+ * Return value : >0 - The duration of the FEC data in the
+ * packet in samples per channel.
+ * 0 - No FEC data in the packet.
+ */
+int WebRtcOpus_FecDurationEst(const uint8_t* payload,
+ size_t payload_length_bytes,
+ int sample_rate_hz);
+
+/****************************************************************************
+ * WebRtcOpus_PacketHasFec(...)
+ *
+ * This function detects if an opus packet has FEC.
+ * Input:
+ * - payload : Encoded data pointer
+ * - payload_length_bytes : Bytes of encoded data
+ *
+ * Return value : 0 - the packet does NOT contain FEC.
+ * 1 - the packet contains FEC.
+ */
+int WebRtcOpus_PacketHasFec(const uint8_t* payload,
+ size_t payload_length_bytes);
+
+/****************************************************************************
+ * WebRtcOpus_PacketHasVoiceActivity(...)
+ *
+ * This function returns the SILK VAD information encoded in the opus packet.
+ * For CELT-only packets that do not have VAD information, it returns -1.
+ * Input:
+ * - payload : Encoded data pointer
+ * - payload_length_bytes : Bytes of encoded data
+ *
+ * Return value : 0 - no frame had the VAD flag set.
+ * 1 - at least one frame had the VAD flag set.
+ * -1 - VAD status could not be determined.
+ */
+int WebRtcOpus_PacketHasVoiceActivity(const uint8_t* payload,
+ size_t payload_length_bytes);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INTERFACE_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
new file mode 100644
index 0000000000..4477e8a5f8
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
+
+using ::std::string;
+
+namespace webrtc {
+
+static const int kOpusBlockDurationMs = 20;
+static const int kOpusSamplingKhz = 48;
+
+class OpusSpeedTest : public AudioCodecSpeedTest {
+ protected:
+ OpusSpeedTest();
+ void SetUp() override;
+ void TearDown() override;
+ float EncodeABlock(int16_t* in_data,
+ uint8_t* bit_stream,
+ size_t max_bytes,
+ size_t* encoded_bytes) override;
+ float DecodeABlock(const uint8_t* bit_stream,
+ size_t encoded_bytes,
+ int16_t* out_data) override;
+ WebRtcOpusEncInst* opus_encoder_;
+ WebRtcOpusDecInst* opus_decoder_;
+};
+
+OpusSpeedTest::OpusSpeedTest()
+ : AudioCodecSpeedTest(kOpusBlockDurationMs,
+ kOpusSamplingKhz,
+ kOpusSamplingKhz),
+ opus_encoder_(NULL),
+ opus_decoder_(NULL) {}
+
+void OpusSpeedTest::SetUp() {
+ AudioCodecSpeedTest::SetUp();
+ // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
+ int app = channels_ == 1 ? 0 : 1;
+ /* Create encoder memory. */
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app, 48000));
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_, 48000));
+ /* Set bitrate. */
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
+}
+
+void OpusSpeedTest::TearDown() {
+ AudioCodecSpeedTest::TearDown();
+ /* Free memory. */
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+float OpusSpeedTest::EncodeABlock(int16_t* in_data,
+ uint8_t* bit_stream,
+ size_t max_bytes,
+ size_t* encoded_bytes) {
+ clock_t clocks = clock();
+ int value = WebRtcOpus_Encode(opus_encoder_, in_data, input_length_sample_,
+ max_bytes, bit_stream);
+ clocks = clock() - clocks;
+ EXPECT_GT(value, 0);
+ *encoded_bytes = static_cast<size_t>(value);
+ return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+float OpusSpeedTest::DecodeABlock(const uint8_t* bit_stream,
+ size_t encoded_bytes,
+ int16_t* out_data) {
+ int value;
+ int16_t audio_type;
+ clock_t clocks = clock();
+ value = WebRtcOpus_Decode(opus_decoder_, bit_stream, encoded_bytes, out_data,
+ &audio_type);
+ clocks = clock() - clocks;
+ EXPECT_EQ(output_length_sample_, static_cast<size_t>(value));
+ return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+/* Test audio length in second. */
+constexpr size_t kDurationSec = 400;
+
+#define ADD_TEST(complexity) \
+ TEST_P(OpusSpeedTest, OpusSetComplexityTest##complexity) { \
+ /* Set complexity. */ \
+ printf("Setting complexity to %d ...\n", complexity); \
+ EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, complexity)); \
+ EncodeDecode(kDurationSec); \
+ }
+
+ADD_TEST(10)
+ADD_TEST(9)
+ADD_TEST(8)
+ADD_TEST(7)
+ADD_TEST(6)
+ADD_TEST(5)
+ADD_TEST(4)
+ADD_TEST(3)
+ADD_TEST(2)
+ADD_TEST(1)
+ADD_TEST(0)
+
+#define ADD_BANDWIDTH_TEST(bandwidth) \
+ TEST_P(OpusSpeedTest, OpusSetBandwidthTest##bandwidth) { \
+ /* Set bandwidth. */ \
+ printf("Setting bandwidth to %d ...\n", bandwidth); \
+ EXPECT_EQ(0, WebRtcOpus_SetBandwidth(opus_encoder_, bandwidth)); \
+ EncodeDecode(kDurationSec); \
+ }
+
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_NARROWBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_MEDIUMBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_WIDEBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_SUPERWIDEBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_FULLBAND)
+
+// List all test cases: (channel, bit rat, filename, extension).
+const coding_param param_set[] = {
+ std::make_tuple(1,
+ 64000,
+ string("audio_coding/speech_mono_32_48kHz"),
+ string("pcm"),
+ true),
+ std::make_tuple(1,
+ 32000,
+ string("audio_coding/speech_mono_32_48kHz"),
+ string("pcm"),
+ true),
+ std::make_tuple(2,
+ 64000,
+ string("audio_coding/music_stereo_48kHz"),
+ string("pcm"),
+ true)};
+
+INSTANTIATE_TEST_SUITE_P(AllTest,
+ OpusSpeedTest,
+ ::testing::ValuesIn(param_set));
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
new file mode 100644
index 0000000000..b40d73805f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -0,0 +1,978 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+#include <string>
+
+#include "modules/audio_coding/codecs/opus/opus_inst.h"
+#include "modules/audio_coding/codecs/opus/opus_interface.h"
+#include "modules/audio_coding/neteq/tools/audio_loop.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+namespace webrtc {
+
+namespace {
+// Equivalent to SDP params
+// {{"channel_mapping", "0,1,2,3"}, {"coupled_streams", "2"}}.
+constexpr unsigned char kQuadChannelMapping[] = {0, 1, 2, 3};
+constexpr int kQuadTotalStreams = 2;
+constexpr int kQuadCoupledStreams = 2;
+
+constexpr unsigned char kStereoChannelMapping[] = {0, 1};
+constexpr int kStereoTotalStreams = 1;
+constexpr int kStereoCoupledStreams = 1;
+
+constexpr unsigned char kMonoChannelMapping[] = {0};
+constexpr int kMonoTotalStreams = 1;
+constexpr int kMonoCoupledStreams = 0;
+
+void CreateSingleOrMultiStreamEncoder(WebRtcOpusEncInst** opus_encoder,
+ int channels,
+ int application,
+ bool use_multistream,
+ int encoder_sample_rate_hz) {
+ EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream);
+ if (use_multistream) {
+ EXPECT_EQ(encoder_sample_rate_hz, 48000);
+ if (channels == 1) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+ opus_encoder, channels, application, kMonoTotalStreams,
+ kMonoCoupledStreams, kMonoChannelMapping));
+ } else if (channels == 2) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+ opus_encoder, channels, application, kStereoTotalStreams,
+ kStereoCoupledStreams, kStereoChannelMapping));
+ } else if (channels == 4) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate(
+ opus_encoder, channels, application, kQuadTotalStreams,
+ kQuadCoupledStreams, kQuadChannelMapping));
+ } else {
+ EXPECT_TRUE(false) << channels;
+ }
+ } else {
+ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(opus_encoder, channels, application,
+ encoder_sample_rate_hz));
+ }
+}
+
+void CreateSingleOrMultiStreamDecoder(WebRtcOpusDecInst** opus_decoder,
+ int channels,
+ bool use_multistream,
+ int decoder_sample_rate_hz) {
+ EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream);
+ if (use_multistream) {
+ EXPECT_EQ(decoder_sample_rate_hz, 48000);
+ if (channels == 1) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
+ opus_decoder, channels, kMonoTotalStreams,
+ kMonoCoupledStreams, kMonoChannelMapping));
+ } else if (channels == 2) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
+ opus_decoder, channels, kStereoTotalStreams,
+ kStereoCoupledStreams, kStereoChannelMapping));
+ } else if (channels == 4) {
+ EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
+ opus_decoder, channels, kQuadTotalStreams,
+ kQuadCoupledStreams, kQuadChannelMapping));
+ } else {
+ EXPECT_TRUE(false) << channels;
+ }
+ } else {
+ EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels,
+ decoder_sample_rate_hz));
+ }
+}
+
+int SamplesPerChannel(int sample_rate_hz, int duration_ms) {
+ const int samples_per_ms = rtc::CheckedDivExact(sample_rate_hz, 1000);
+ return samples_per_ms * duration_ms;
+}
+
+using test::AudioLoop;
+using ::testing::Combine;
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+// Maximum number of bytes in output bitstream.
+const size_t kMaxBytes = 2000;
+
+class OpusTest
+ : public TestWithParam<::testing::tuple<size_t, int, bool, int, int>> {
+ protected:
+ OpusTest() = default;
+
+ void TestDtxEffect(bool dtx, int block_length_ms);
+
+ void TestCbrEffect(bool dtx, int block_length_ms);
+
+ // Prepare `speech_data_` for encoding, read from a hard-coded file.
+ // After preparation, `speech_data_.GetNextBlock()` returns a pointer to a
+ // block of `block_length_ms` milliseconds. The data is looped every
+ // `loop_length_ms` milliseconds.
+ void PrepareSpeechData(int block_length_ms, int loop_length_ms);
+
+ int EncodeDecode(WebRtcOpusEncInst* encoder,
+ rtc::ArrayView<const int16_t> input_audio,
+ WebRtcOpusDecInst* decoder,
+ int16_t* output_audio,
+ int16_t* audio_type);
+
+ void SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
+ opus_int32 expect,
+ int32_t set);
+
+ void CheckAudioBounded(const int16_t* audio,
+ size_t samples,
+ size_t channels,
+ uint16_t bound) const;
+
+ WebRtcOpusEncInst* opus_encoder_ = nullptr;
+ WebRtcOpusDecInst* opus_decoder_ = nullptr;
+ AudioLoop speech_data_;
+ uint8_t bitstream_[kMaxBytes];
+ size_t encoded_bytes_ = 0;
+ const size_t channels_{std::get<0>(GetParam())};
+ const int application_{std::get<1>(GetParam())};
+ const bool use_multistream_{std::get<2>(GetParam())};
+ const int encoder_sample_rate_hz_{std::get<3>(GetParam())};
+ const int decoder_sample_rate_hz_{std::get<4>(GetParam())};
+};
+
+} // namespace
+
+// Singlestream: Try all combinations.
+INSTANTIATE_TEST_SUITE_P(Singlestream,
+ OpusTest,
+ testing::Combine(testing::Values(1, 2),
+ testing::Values(0, 1),
+ testing::Values(false),
+ testing::Values(16000, 48000),
+ testing::Values(16000, 48000)));
+
+// Multistream: Some representative cases (only 48 kHz for now).
+INSTANTIATE_TEST_SUITE_P(
+ Multistream,
+ OpusTest,
+ testing::Values(std::make_tuple(1, 0, true, 48000, 48000),
+ std::make_tuple(2, 1, true, 48000, 48000),
+ std::make_tuple(4, 0, true, 48000, 48000),
+ std::make_tuple(4, 1, true, 48000, 48000)));
+
+void OpusTest::PrepareSpeechData(int block_length_ms, int loop_length_ms) {
+ std::map<int, std::string> channel_to_basename = {
+ {1, "audio_coding/testfile32kHz"},
+ {2, "audio_coding/teststereo32kHz"},
+ {4, "audio_coding/speech_4_channels_48k_one_second"}};
+ std::map<int, std::string> channel_to_suffix = {
+ {1, "pcm"}, {2, "pcm"}, {4, "wav"}};
+ const std::string file_name = webrtc::test::ResourcePath(
+ channel_to_basename[channels_], channel_to_suffix[channels_]);
+ if (loop_length_ms < block_length_ms) {
+ loop_length_ms = block_length_ms;
+ }
+ const int sample_rate_khz =
+ rtc::CheckedDivExact(encoder_sample_rate_hz_, 1000);
+ EXPECT_TRUE(speech_data_.Init(file_name,
+ loop_length_ms * sample_rate_khz * channels_,
+ block_length_ms * sample_rate_khz * channels_));
+}
+
+void OpusTest::SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
+ opus_int32 expect,
+ int32_t set) {
+ opus_int32 bandwidth;
+ EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
+ EXPECT_EQ(0, WebRtcOpus_GetMaxPlaybackRate(opus_encoder_, &bandwidth));
+ EXPECT_EQ(expect, bandwidth);
+}
+
+void OpusTest::CheckAudioBounded(const int16_t* audio,
+ size_t samples,
+ size_t channels,
+ uint16_t bound) const {
+ for (size_t i = 0; i < samples; ++i) {
+ for (size_t c = 0; c < channels; ++c) {
+ ASSERT_GE(audio[i * channels + c], -bound);
+ ASSERT_LE(audio[i * channels + c], bound);
+ }
+ }
+}
+
+int OpusTest::EncodeDecode(WebRtcOpusEncInst* encoder,
+ rtc::ArrayView<const int16_t> input_audio,
+ WebRtcOpusDecInst* decoder,
+ int16_t* output_audio,
+ int16_t* audio_type) {
+ const int input_samples_per_channel =
+ rtc::CheckedDivExact(input_audio.size(), channels_);
+ int encoded_bytes_int =
+ WebRtcOpus_Encode(encoder, input_audio.data(), input_samples_per_channel,
+ kMaxBytes, bitstream_);
+ EXPECT_GE(encoded_bytes_int, 0);
+ encoded_bytes_ = static_cast<size_t>(encoded_bytes_int);
+ if (encoded_bytes_ != 0) {
+ int est_len = WebRtcOpus_DurationEst(decoder, bitstream_, encoded_bytes_);
+ int act_len = WebRtcOpus_Decode(decoder, bitstream_, encoded_bytes_,
+ output_audio, audio_type);
+ EXPECT_EQ(est_len, act_len);
+ return act_len;
+ } else {
+ int total_dtx_len = 0;
+ const int output_samples_per_channel = input_samples_per_channel *
+ decoder_sample_rate_hz_ /
+ encoder_sample_rate_hz_;
+ while (total_dtx_len < output_samples_per_channel) {
+ int est_len = WebRtcOpus_DurationEst(decoder, NULL, 0);
+ int act_len = WebRtcOpus_Decode(decoder, NULL, 0,
+ &output_audio[total_dtx_len * channels_],
+ audio_type);
+ EXPECT_EQ(est_len, act_len);
+ total_dtx_len += act_len;
+ }
+ return total_dtx_len;
+ }
+}
+
+// Test if encoder/decoder can enter DTX mode properly and do not enter DTX when
+// they should not. This test is signal dependent.
+void OpusTest::TestDtxEffect(bool dtx, int block_length_ms) {
+ PrepareSpeechData(block_length_ms, 2000);
+ const size_t input_samples =
+ rtc::CheckedDivExact(encoder_sample_rate_hz_, 1000) * block_length_ms;
+ const size_t output_samples =
+ rtc::CheckedDivExact(decoder_sample_rate_hz_, 1000) * block_length_ms;
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ // Set bitrate.
+ EXPECT_EQ(
+ 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
+
+ // Set input audio as silence.
+ std::vector<int16_t> silence(input_samples * channels_, 0);
+
+ // Setting DTX.
+ EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_)
+ : WebRtcOpus_DisableDtx(opus_encoder_));
+
+ int16_t audio_type;
+ int16_t* output_data_decode = new int16_t[output_samples * channels_];
+
+ for (int i = 0; i < 100; ++i) {
+ EXPECT_EQ(output_samples,
+ static_cast<size_t>(EncodeDecode(
+ opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
+ output_data_decode, &audio_type)));
+ // If not DTX, it should never enter DTX mode. If DTX, we do not care since
+ // whether it enters DTX depends on the signal type.
+ if (!dtx) {
+ EXPECT_GT(encoded_bytes_, 1U);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, audio_type); // Speech.
+ }
+ }
+
+ // We input some silent segments. In DTX mode, the encoder will stop sending.
+ // However, DTX may happen after a while.
+ for (int i = 0; i < 30; ++i) {
+ EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+ opus_encoder_, silence, opus_decoder_,
+ output_data_decode, &audio_type)));
+ if (!dtx) {
+ EXPECT_GT(encoded_bytes_, 1U);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, audio_type); // Speech.
+ } else if (encoded_bytes_ == 1) {
+ EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(2, audio_type); // Comfort noise.
+ break;
+ }
+ }
+
+ // When Opus is in DTX, it wakes up in a regular basis. It sends two packets,
+ // one with an arbitrary size and the other of 1-byte, then stops sending for
+ // a certain number of frames.
+
+ // `max_dtx_frames` is the maximum number of frames Opus can stay in DTX.
+ // TODO(kwiberg): Why does this number depend on the encoding sample rate?
+ const int max_dtx_frames =
+ (encoder_sample_rate_hz_ == 16000 ? 800 : 400) / block_length_ms + 1;
+
+ // We run `kRunTimeMs` milliseconds of pure silence.
+ const int kRunTimeMs = 4500;
+
+ // We check that, after a `kCheckTimeMs` milliseconds (given that the CNG in
+ // Opus needs time to adapt), the absolute values of DTX decoded signal are
+ // bounded by `kOutputValueBound`.
+ const int kCheckTimeMs = 4000;
+
+#if defined(OPUS_FIXED_POINT)
+ // Fixed-point Opus generates a random (comfort) noise, which has a less
+ // predictable value bound than its floating-point Opus. This value depends on
+ // input signal, and the time window for checking the output values (between
+ // `kCheckTimeMs` and `kRunTimeMs`).
+ const uint16_t kOutputValueBound = 30;
+
+#else
+ const uint16_t kOutputValueBound = 2;
+#endif
+
+ int time = 0;
+ while (time < kRunTimeMs) {
+ // DTX mode is maintained for maximum `max_dtx_frames` frames.
+ int i = 0;
+ for (; i < max_dtx_frames; ++i) {
+ time += block_length_ms;
+ EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+ opus_encoder_, silence, opus_decoder_,
+ output_data_decode, &audio_type)));
+ if (dtx) {
+ if (encoded_bytes_ > 1)
+ break;
+ EXPECT_EQ(0U, encoded_bytes_) // Send 0 byte.
+ << "Opus should have entered DTX mode.";
+ EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(2, audio_type); // Comfort noise.
+ if (time >= kCheckTimeMs) {
+ CheckAudioBounded(output_data_decode, output_samples, channels_,
+ kOutputValueBound);
+ }
+ } else {
+ EXPECT_GT(encoded_bytes_, 1U);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, audio_type); // Speech.
+ }
+ }
+
+ if (dtx) {
+ // With DTX, Opus must stop transmission for some time.
+ EXPECT_GT(i, 1);
+ }
+
+ // We expect a normal payload.
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, audio_type); // Speech.
+
+ // Enters DTX again immediately.
+ time += block_length_ms;
+ EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+ opus_encoder_, silence, opus_decoder_,
+ output_data_decode, &audio_type)));
+ if (dtx) {
+ EXPECT_EQ(1U, encoded_bytes_); // Send 1 byte.
+ EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(2, audio_type); // Comfort noise.
+ if (time >= kCheckTimeMs) {
+ CheckAudioBounded(output_data_decode, output_samples, channels_,
+ kOutputValueBound);
+ }
+ } else {
+ EXPECT_GT(encoded_bytes_, 1U);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, audio_type); // Speech.
+ }
+ }
+
+ silence[0] = 10000;
+ if (dtx) {
+ // Verify that encoder/decoder can jump out from DTX mode.
+ EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode(
+ opus_encoder_, silence, opus_decoder_,
+ output_data_decode, &audio_type)));
+ EXPECT_GT(encoded_bytes_, 1U);
+ EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
+ EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
+ EXPECT_EQ(0, audio_type); // Speech.
+ }
+
+ // Free memory.
+ delete[] output_data_decode;
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+// Test if CBR does what we expect.
+void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) {
+ PrepareSpeechData(block_length_ms, 2000);
+ const size_t output_samples =
+ rtc::CheckedDivExact(decoder_sample_rate_hz_, 1000) * block_length_ms;
+
+ int32_t max_pkt_size_diff = 0;
+ int32_t prev_pkt_size = 0;
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ // Set bitrate.
+ EXPECT_EQ(
+ 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
+
+ // Setting CBR.
+ EXPECT_EQ(0, cbr ? WebRtcOpus_EnableCbr(opus_encoder_)
+ : WebRtcOpus_DisableCbr(opus_encoder_));
+
+ int16_t audio_type;
+ std::vector<int16_t> audio_out(output_samples * channels_);
+ for (int i = 0; i < 100; ++i) {
+ EXPECT_EQ(output_samples,
+ static_cast<size_t>(
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ opus_decoder_, audio_out.data(), &audio_type)));
+
+ if (prev_pkt_size > 0) {
+ int32_t diff = std::abs((int32_t)encoded_bytes_ - prev_pkt_size);
+ max_pkt_size_diff = std::max(max_pkt_size_diff, diff);
+ }
+ prev_pkt_size = rtc::checked_cast<int32_t>(encoded_bytes_);
+ }
+
+ if (cbr) {
+ EXPECT_EQ(max_pkt_size_diff, 0);
+ } else {
+ EXPECT_GT(max_pkt_size_diff, 0);
+ }
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+// Test failing Create.
+TEST(OpusTest, OpusCreateFail) {
+ WebRtcOpusEncInst* opus_encoder;
+ WebRtcOpusDecInst* opus_decoder;
+
+ // Test to see that an invalid pointer is caught.
+ EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0, 48000));
+ // Invalid channel number.
+ EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0, 48000));
+ // Invalid applciation mode.
+ EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2, 48000));
+ // Invalid sample rate.
+ EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 0, 12345));
+
+ EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1, 48000));
+ // Invalid channel number.
+ EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257, 48000));
+ // Invalid sample rate.
+ EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 1, 12345));
+}
+
+// Test failing Free.
+TEST(OpusTest, OpusFreeFail) {
+ // Test to see that an invalid pointer is caught.
+ EXPECT_EQ(-1, WebRtcOpus_EncoderFree(NULL));
+ EXPECT_EQ(-1, WebRtcOpus_DecoderFree(NULL));
+}
+
+// Test normal Create and Free.
+TEST_P(OpusTest, OpusCreateFree) {
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+ EXPECT_TRUE(opus_encoder_ != NULL);
+ EXPECT_TRUE(opus_decoder_ != NULL);
+ // Free encoder and decoder memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+#define ENCODER_CTL(inst, vargs) \
+ inst->encoder \
+ ? opus_encoder_ctl(inst->encoder, vargs) \
+ : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs)
+
+TEST_P(OpusTest, OpusEncodeDecode) {
+ PrepareSpeechData(20, 20);
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ // Set bitrate.
+ EXPECT_EQ(
+ 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
+
+ // Check number of channels for decoder.
+ EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
+
+ // Check application mode.
+ opus_int32 app;
+ ENCODER_CTL(opus_encoder_, OPUS_GET_APPLICATION(&app));
+ EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO,
+ app);
+
+ // Encode & decode.
+ int16_t audio_type;
+ const int decode_samples_per_channel =
+ SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
+ int16_t* output_data_decode =
+ new int16_t[decode_samples_per_channel * channels_];
+ EXPECT_EQ(decode_samples_per_channel,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ opus_decoder_, output_data_decode, &audio_type));
+
+ // Free memory.
+ delete[] output_data_decode;
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+TEST_P(OpusTest, OpusSetBitRate) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
+
+ // Create encoder memory, try with different bitrates.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
+ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 600000));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+TEST_P(OpusTest, OpusSetComplexity) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
+
+ // Create encoder memory, try with different complexities.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+
+ EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
+ EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
+ EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 11));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+TEST_P(OpusTest, OpusSetBandwidth) {
+ if (channels_ > 2) {
+ // TODO(webrtc:10217): investigate why multi-stream Opus reports
+ // narrowband when it's configured with FULLBAND.
+ return;
+ }
+ PrepareSpeechData(20, 20);
+
+ int16_t audio_type;
+ const int decode_samples_per_channel =
+ SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
+ std::unique_ptr<int16_t[]> output_data_decode(
+ new int16_t[decode_samples_per_channel * channels_]());
+
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1,
+ WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND));
+ EXPECT_EQ(-1, WebRtcOpus_GetBandwidth(opus_encoder_));
+
+ // Create encoder memory, try with different bandwidths.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
+ OPUS_BANDWIDTH_NARROWBAND - 1));
+ EXPECT_EQ(0,
+ WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND));
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
+ output_data_decode.get(), &audio_type);
+ EXPECT_EQ(OPUS_BANDWIDTH_NARROWBAND, WebRtcOpus_GetBandwidth(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND));
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
+ output_data_decode.get(), &audio_type);
+ EXPECT_EQ(encoder_sample_rate_hz_ == 16000 ? OPUS_BANDWIDTH_WIDEBAND
+ : OPUS_BANDWIDTH_FULLBAND,
+ WebRtcOpus_GetBandwidth(opus_encoder_));
+ EXPECT_EQ(
+ -1, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND + 1));
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
+ output_data_decode.get(), &audio_type);
+ EXPECT_EQ(encoder_sample_rate_hz_ == 16000 ? OPUS_BANDWIDTH_WIDEBAND
+ : OPUS_BANDWIDTH_FULLBAND,
+ WebRtcOpus_GetBandwidth(opus_encoder_));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+TEST_P(OpusTest, OpusForceChannels) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
+
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ ASSERT_NE(nullptr, opus_encoder_);
+
+ if (channels_ >= 2) {
+ EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
+ EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 2));
+ EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
+ EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 0));
+ } else {
+ EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 2));
+ EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
+ EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 0));
+ }
+
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+// Encode and decode one frame, initialize the decoder and
+// decode once more.
+TEST_P(OpusTest, OpusDecodeInit) {
+ PrepareSpeechData(20, 20);
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ // Encode & decode.
+ int16_t audio_type;
+ const int decode_samples_per_channel =
+ SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
+ int16_t* output_data_decode =
+ new int16_t[decode_samples_per_channel * channels_];
+ EXPECT_EQ(decode_samples_per_channel,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ opus_decoder_, output_data_decode, &audio_type));
+
+ WebRtcOpus_DecoderInit(opus_decoder_);
+
+ EXPECT_EQ(decode_samples_per_channel,
+ WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
+ output_data_decode, &audio_type));
+
+ // Free memory.
+ delete[] output_data_decode;
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+TEST_P(OpusTest, OpusEnableDisableFec) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_encoder_));
+ EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+
+ EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+TEST_P(OpusTest, OpusEnableDisableDtx) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_encoder_));
+ EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+
+ opus_int32 dtx;
+
+ // DTX is off by default.
+ ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
+ EXPECT_EQ(0, dtx);
+
+ // Test to enable DTX.
+ EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
+ ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
+ EXPECT_EQ(1, dtx);
+
+ // Test to disable DTX.
+ EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
+ ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
+ EXPECT_EQ(0, dtx);
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+TEST_P(OpusTest, OpusDtxOff) {
+ TestDtxEffect(false, 10);
+ TestDtxEffect(false, 20);
+ TestDtxEffect(false, 40);
+}
+
+TEST_P(OpusTest, OpusDtxOn) {
+ if (channels_ > 2) {
+ // TODO(webrtc:10218): adapt the test to the sizes and order of multi-stream
+ // DTX packets.
+ return;
+ }
+ TestDtxEffect(true, 10);
+ TestDtxEffect(true, 20);
+ TestDtxEffect(true, 40);
+}
+
+TEST_P(OpusTest, OpusCbrOff) {
+ TestCbrEffect(false, 10);
+ TestCbrEffect(false, 20);
+ TestCbrEffect(false, 40);
+}
+
+TEST_P(OpusTest, OpusCbrOn) {
+ TestCbrEffect(true, 10);
+ TestCbrEffect(true, 20);
+ TestCbrEffect(true, 40);
+}
+
+TEST_P(OpusTest, OpusSetPacketLossRate) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+
+ EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
+ EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
+ EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 101));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+TEST_P(OpusTest, OpusSetMaxPlaybackRate) {
+ // Test without creating encoder memory.
+ EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 24000);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 16001);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 16000);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 12001);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 12000);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 8001);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 8000);
+ SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 4000);
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+}
+
+// Test PLC.
+TEST_P(OpusTest, OpusDecodePlc) {
+ PrepareSpeechData(20, 20);
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ // Set bitrate.
+ EXPECT_EQ(
+ 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
+
+ // Check number of channels for decoder.
+ EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
+
+ // Encode & decode.
+ int16_t audio_type;
+ const int decode_samples_per_channel =
+ SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
+ int16_t* output_data_decode =
+ new int16_t[decode_samples_per_channel * channels_];
+ EXPECT_EQ(decode_samples_per_channel,
+ EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
+ opus_decoder_, output_data_decode, &audio_type));
+
+ // Call decoder PLC.
+ constexpr int kPlcDurationMs = 10;
+ const int plc_samples = decoder_sample_rate_hz_ * kPlcDurationMs / 1000;
+ int16_t* plc_buffer = new int16_t[plc_samples * channels_];
+ EXPECT_EQ(plc_samples,
+ WebRtcOpus_Decode(opus_decoder_, NULL, 0, plc_buffer, &audio_type));
+
+ // Free memory.
+ delete[] plc_buffer;
+ delete[] output_data_decode;
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+// Duration estimation.
+TEST_P(OpusTest, OpusDurationEstimation) {
+ PrepareSpeechData(20, 20);
+
+ // Create.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+
+ // 10 ms. We use only first 10 ms of a 20 ms block.
+ auto speech_block = speech_data_.GetNextBlock();
+ int encoded_bytes_int = WebRtcOpus_Encode(
+ opus_encoder_, speech_block.data(),
+ rtc::CheckedDivExact(speech_block.size(), 2 * channels_), kMaxBytes,
+ bitstream_);
+ EXPECT_GE(encoded_bytes_int, 0);
+ EXPECT_EQ(SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/10),
+ WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
+ static_cast<size_t>(encoded_bytes_int)));
+
+ // 20 ms
+ speech_block = speech_data_.GetNextBlock();
+ encoded_bytes_int =
+ WebRtcOpus_Encode(opus_encoder_, speech_block.data(),
+ rtc::CheckedDivExact(speech_block.size(), channels_),
+ kMaxBytes, bitstream_);
+ EXPECT_GE(encoded_bytes_int, 0);
+ EXPECT_EQ(SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20),
+ WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
+ static_cast<size_t>(encoded_bytes_int)));
+
+ // Free memory.
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+TEST_P(OpusTest, OpusDecodeRepacketized) {
+ if (channels_ > 2) {
+ // As per the Opus documentation
+ // https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__repacketizer.html#details,
+ // multiple streams are not supported.
+ return;
+ }
+ constexpr size_t kPackets = 6;
+
+ PrepareSpeechData(20, 20 * kPackets);
+
+ // Create encoder memory.
+ CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
+ use_multistream_, encoder_sample_rate_hz_);
+ ASSERT_NE(nullptr, opus_encoder_);
+ CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
+ decoder_sample_rate_hz_);
+ ASSERT_NE(nullptr, opus_decoder_);
+
+ // Set bitrate.
+ EXPECT_EQ(
+ 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
+
+ // Check number of channels for decoder.
+ EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
+
+ // Encode & decode.
+ int16_t audio_type;
+ const int decode_samples_per_channel =
+ SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
+ std::unique_ptr<int16_t[]> output_data_decode(
+ new int16_t[kPackets * decode_samples_per_channel * channels_]);
+ OpusRepacketizer* rp = opus_repacketizer_create();
+
+ size_t num_packets = 0;
+ constexpr size_t kMaxCycles = 100;
+ for (size_t idx = 0; idx < kMaxCycles; ++idx) {
+ auto speech_block = speech_data_.GetNextBlock();
+ encoded_bytes_ =
+ WebRtcOpus_Encode(opus_encoder_, speech_block.data(),
+ rtc::CheckedDivExact(speech_block.size(), channels_),
+ kMaxBytes, bitstream_);
+ if (opus_repacketizer_cat(rp, bitstream_,
+ rtc::checked_cast<opus_int32>(encoded_bytes_)) ==
+ OPUS_OK) {
+ ++num_packets;
+ if (num_packets == kPackets) {
+ break;
+ }
+ } else {
+ // Opus repacketizer cannot guarantee a success. We try again if it fails.
+ opus_repacketizer_init(rp);
+ num_packets = 0;
+ }
+ }
+ EXPECT_EQ(kPackets, num_packets);
+
+ encoded_bytes_ = opus_repacketizer_out(rp, bitstream_, kMaxBytes);
+
+ EXPECT_EQ(decode_samples_per_channel * kPackets,
+ static_cast<size_t>(WebRtcOpus_DurationEst(
+ opus_decoder_, bitstream_, encoded_bytes_)));
+
+ EXPECT_EQ(decode_samples_per_channel * kPackets,
+ static_cast<size_t>(
+ WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
+ output_data_decode.get(), &audio_type)));
+
+ // Free memory.
+ opus_repacketizer_destroy(rp);
+ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+ EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+TEST(OpusVadTest, CeltUnknownStatus) {
+ const uint8_t celt[] = {0x80};
+ EXPECT_EQ(WebRtcOpus_PacketHasVoiceActivity(celt, 1), -1);
+}
+
+TEST(OpusVadTest, Mono20msVadSet) {
+ uint8_t silk20msMonoVad[] = {0x78, 0x80};
+ EXPECT_TRUE(WebRtcOpus_PacketHasVoiceActivity(silk20msMonoVad, 2));
+}
+
+TEST(OpusVadTest, Mono20MsVadUnset) {
+ uint8_t silk20msMonoSilence[] = {0x78, 0x00};
+ EXPECT_FALSE(WebRtcOpus_PacketHasVoiceActivity(silk20msMonoSilence, 2));
+}
+
+TEST(OpusVadTest, Stereo20MsVadOnSideChannel) {
+ uint8_t silk20msStereoVadSideChannel[] = {0x78 | 0x04, 0x20};
+ EXPECT_TRUE(
+ WebRtcOpus_PacketHasVoiceActivity(silk20msStereoVadSideChannel, 2));
+}
+
+TEST(OpusVadTest, TwoOpusMonoFramesVadOnSecond) {
+ uint8_t twoMonoFrames[] = {0x78 | 0x1, 0x00, 0x80};
+ EXPECT_TRUE(WebRtcOpus_PacketHasVoiceActivity(twoMonoFrames, 3));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/BUILD.gn b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/BUILD.gn
new file mode 100644
index 0000000000..8bc0bf5e0e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/BUILD.gn
@@ -0,0 +1,55 @@
+# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("../../../../../webrtc.gni")
+
+visibility = [
+ ":*",
+ "../../../:*",
+]
+
+if (rtc_include_tests) {
+ rtc_library("test") {
+ testonly = true
+
+ sources = [
+ "audio_ring_buffer.cc",
+ "audio_ring_buffer.h",
+ "blocker.cc",
+ "blocker.h",
+ "lapped_transform.cc",
+ "lapped_transform.h",
+ ]
+
+ deps = [
+ "../../../../../common_audio",
+ "../../../../../common_audio:common_audio_c",
+ "../../../../../rtc_base:checks",
+ "../../../../../rtc_base/memory:aligned_malloc",
+ ]
+ }
+
+ rtc_library("test_unittest") {
+ testonly = true
+
+ sources = [
+ "audio_ring_buffer_unittest.cc",
+ "blocker_unittest.cc",
+ "lapped_transform_unittest.cc",
+ ]
+
+ deps = [
+ ":test",
+ "../../../../../common_audio",
+ "../../../../../common_audio:common_audio_c",
+ "../../../../../rtc_base:macromagic",
+ "../../../../../test:test_support",
+ "//testing/gtest",
+ ]
+ }
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.cc
new file mode 100644
index 0000000000..2a71b43d2c
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/test/audio_ring_buffer.h"
+
+#include "common_audio/ring_buffer.h"
+#include "rtc_base/checks.h"
+
+// This is a simple multi-channel wrapper over the ring_buffer.h C interface.
+
+namespace webrtc {
+
+AudioRingBuffer::AudioRingBuffer(size_t channels, size_t max_frames) {
+ buffers_.reserve(channels);
+ for (size_t i = 0; i < channels; ++i)
+ buffers_.push_back(WebRtc_CreateBuffer(max_frames, sizeof(float)));
+}
+
+AudioRingBuffer::~AudioRingBuffer() {
+ for (auto* buf : buffers_)
+ WebRtc_FreeBuffer(buf);
+}
+
+void AudioRingBuffer::Write(const float* const* data,
+ size_t channels,
+ size_t frames) {
+ RTC_DCHECK_EQ(buffers_.size(), channels);
+ for (size_t i = 0; i < channels; ++i) {
+ const size_t written = WebRtc_WriteBuffer(buffers_[i], data[i], frames);
+ RTC_CHECK_EQ(written, frames);
+ }
+}
+
+void AudioRingBuffer::Read(float* const* data, size_t channels, size_t frames) {
+ RTC_DCHECK_EQ(buffers_.size(), channels);
+ for (size_t i = 0; i < channels; ++i) {
+ const size_t read =
+ WebRtc_ReadBuffer(buffers_[i], nullptr, data[i], frames);
+ RTC_CHECK_EQ(read, frames);
+ }
+}
+
+size_t AudioRingBuffer::ReadFramesAvailable() const {
+ // All buffers have the same amount available.
+ return WebRtc_available_read(buffers_[0]);
+}
+
+size_t AudioRingBuffer::WriteFramesAvailable() const {
+ // All buffers have the same amount available.
+ return WebRtc_available_write(buffers_[0]);
+}
+
+void AudioRingBuffer::MoveReadPositionForward(size_t frames) {
+ for (auto* buf : buffers_) {
+ const size_t moved =
+ static_cast<size_t>(WebRtc_MoveReadPtr(buf, static_cast<int>(frames)));
+ RTC_CHECK_EQ(moved, frames);
+ }
+}
+
+void AudioRingBuffer::MoveReadPositionBackward(size_t frames) {
+ for (auto* buf : buffers_) {
+ const size_t moved = static_cast<size_t>(
+ -WebRtc_MoveReadPtr(buf, -static_cast<int>(frames)));
+ RTC_CHECK_EQ(moved, frames);
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.h
new file mode 100644
index 0000000000..a280ca2410
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_TEST_AUDIO_RING_BUFFER_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_TEST_AUDIO_RING_BUFFER_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <vector>
+
+struct RingBuffer;
+
+namespace webrtc {
+
+// A ring buffer tailored for float deinterleaved audio. Any operation that
+// cannot be performed as requested will cause a crash (e.g. insufficient data
+// in the buffer to fulfill a read request.)
+class AudioRingBuffer final {
+ public:
+ // Specify the number of channels and maximum number of frames the buffer will
+ // contain.
+ AudioRingBuffer(size_t channels, size_t max_frames);
+ ~AudioRingBuffer();
+
+ // Copies `data` to the buffer and advances the write pointer. `channels` must
+ // be the same as at creation time.
+ void Write(const float* const* data, size_t channels, size_t frames);
+
+ // Copies from the buffer to `data` and advances the read pointer. `channels`
+ // must be the same as at creation time.
+ void Read(float* const* data, size_t channels, size_t frames);
+
+ size_t ReadFramesAvailable() const;
+ size_t WriteFramesAvailable() const;
+
+ // Moves the read position. The forward version advances the read pointer
+ // towards the write pointer and the backward verison withdraws the read
+ // pointer away from the write pointer (i.e. flushing and stuffing the buffer
+ // respectively.)
+ void MoveReadPositionForward(size_t frames);
+ void MoveReadPositionBackward(size_t frames);
+
+ private:
+ // TODO(kwiberg): Use std::vector<std::unique_ptr<RingBuffer>> instead.
+ std::vector<RingBuffer*> buffers_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_TEST_AUDIO_RING_BUFFER_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer_unittest.cc
new file mode 100644
index 0000000000..6dbc8ee9fe
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/audio_ring_buffer_unittest.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/test/audio_ring_buffer.h"
+
+#include <memory>
+
+#include "common_audio/channel_buffer.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+class AudioRingBufferTest
+ : public ::testing::TestWithParam< ::testing::tuple<int, int, int, int> > {
+};
+
+void ReadAndWriteTest(const ChannelBuffer<float>& input,
+ size_t num_write_chunk_frames,
+ size_t num_read_chunk_frames,
+ size_t buffer_frames,
+ ChannelBuffer<float>* output) {
+ const size_t num_channels = input.num_channels();
+ const size_t total_frames = input.num_frames();
+ AudioRingBuffer buf(num_channels, buffer_frames);
+ std::unique_ptr<float*[]> slice(new float*[num_channels]);
+
+ size_t input_pos = 0;
+ size_t output_pos = 0;
+ while (input_pos + buf.WriteFramesAvailable() < total_frames) {
+ // Write until the buffer is as full as possible.
+ while (buf.WriteFramesAvailable() >= num_write_chunk_frames) {
+ buf.Write(input.Slice(slice.get(), input_pos), num_channels,
+ num_write_chunk_frames);
+ input_pos += num_write_chunk_frames;
+ }
+ // Read until the buffer is as empty as possible.
+ while (buf.ReadFramesAvailable() >= num_read_chunk_frames) {
+ EXPECT_LT(output_pos, total_frames);
+ buf.Read(output->Slice(slice.get(), output_pos), num_channels,
+ num_read_chunk_frames);
+ output_pos += num_read_chunk_frames;
+ }
+ }
+
+ // Write and read the last bit.
+ if (input_pos < total_frames) {
+ buf.Write(input.Slice(slice.get(), input_pos), num_channels,
+ total_frames - input_pos);
+ }
+ if (buf.ReadFramesAvailable()) {
+ buf.Read(output->Slice(slice.get(), output_pos), num_channels,
+ buf.ReadFramesAvailable());
+ }
+ EXPECT_EQ(0u, buf.ReadFramesAvailable());
+}
+
+TEST_P(AudioRingBufferTest, ReadDataMatchesWrittenData) {
+ const size_t kFrames = 5000;
+ const size_t num_channels = ::testing::get<3>(GetParam());
+
+ // Initialize the input data to an increasing sequence.
+ ChannelBuffer<float> input(kFrames, static_cast<int>(num_channels));
+ for (size_t i = 0; i < num_channels; ++i)
+ for (size_t j = 0; j < kFrames; ++j)
+ input.channels()[i][j] = (i + 1) * (j + 1);
+
+ ChannelBuffer<float> output(kFrames, static_cast<int>(num_channels));
+ ReadAndWriteTest(input, ::testing::get<0>(GetParam()),
+ ::testing::get<1>(GetParam()), ::testing::get<2>(GetParam()),
+ &output);
+
+ // Verify the read data matches the input.
+ for (size_t i = 0; i < num_channels; ++i)
+ for (size_t j = 0; j < kFrames; ++j)
+ EXPECT_EQ(input.channels()[i][j], output.channels()[i][j]);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ AudioRingBufferTest,
+ AudioRingBufferTest,
+ ::testing::Combine(::testing::Values(10, 20, 42), // num_write_chunk_frames
+ ::testing::Values(1, 10, 17), // num_read_chunk_frames
+ ::testing::Values(100, 256), // buffer_frames
+ ::testing::Values(1, 4))); // num_channels
+
+TEST_F(AudioRingBufferTest, MoveReadPosition) {
+ const size_t kNumChannels = 1;
+ const float kInputArray[] = {1, 2, 3, 4};
+ const size_t kNumFrames = sizeof(kInputArray) / sizeof(*kInputArray);
+ ChannelBuffer<float> input(kNumFrames, kNumChannels);
+ input.SetDataForTesting(kInputArray, kNumFrames);
+ AudioRingBuffer buf(kNumChannels, kNumFrames);
+ buf.Write(input.channels(), kNumChannels, kNumFrames);
+
+ buf.MoveReadPositionForward(3);
+ ChannelBuffer<float> output(1, kNumChannels);
+ buf.Read(output.channels(), kNumChannels, 1);
+ EXPECT_EQ(4, output.channels()[0][0]);
+ buf.MoveReadPositionBackward(3);
+ buf.Read(output.channels(), kNumChannels, 1);
+ EXPECT_EQ(2, output.channels()[0][0]);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.cc
new file mode 100644
index 0000000000..33406cead9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.cc
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/test/blocker.h"
+
+#include <string.h>
+
+#include "rtc_base/checks.h"
+
+namespace {
+
+// Adds `a` and `b` frame by frame into `result` (basically matrix addition).
+void AddFrames(const float* const* a,
+ size_t a_start_index,
+ const float* const* b,
+ int b_start_index,
+ size_t num_frames,
+ size_t num_channels,
+ float* const* result,
+ size_t result_start_index) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ for (size_t j = 0; j < num_frames; ++j) {
+ result[i][j + result_start_index] =
+ a[i][j + a_start_index] + b[i][j + b_start_index];
+ }
+ }
+}
+
+// Copies `src` into `dst` channel by channel.
+void CopyFrames(const float* const* src,
+ size_t src_start_index,
+ size_t num_frames,
+ size_t num_channels,
+ float* const* dst,
+ size_t dst_start_index) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ memcpy(&dst[i][dst_start_index], &src[i][src_start_index],
+ num_frames * sizeof(dst[i][dst_start_index]));
+ }
+}
+
+// Moves `src` into `dst` channel by channel.
+void MoveFrames(const float* const* src,
+ size_t src_start_index,
+ size_t num_frames,
+ size_t num_channels,
+ float* const* dst,
+ size_t dst_start_index) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ memmove(&dst[i][dst_start_index], &src[i][src_start_index],
+ num_frames * sizeof(dst[i][dst_start_index]));
+ }
+}
+
+void ZeroOut(float* const* buffer,
+ size_t starting_idx,
+ size_t num_frames,
+ size_t num_channels) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ memset(&buffer[i][starting_idx], 0,
+ num_frames * sizeof(buffer[i][starting_idx]));
+ }
+}
+
+// Pointwise multiplies each channel of `frames` with `window`. Results are
+// stored in `frames`.
+void ApplyWindow(const float* window,
+ size_t num_frames,
+ size_t num_channels,
+ float* const* frames) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ for (size_t j = 0; j < num_frames; ++j) {
+ frames[i][j] = frames[i][j] * window[j];
+ }
+ }
+}
+
+size_t gcd(size_t a, size_t b) {
+ size_t tmp;
+ while (b) {
+ tmp = a;
+ a = b;
+ b = tmp % b;
+ }
+ return a;
+}
+
+} // namespace
+
+namespace webrtc {
+
+Blocker::Blocker(size_t chunk_size,
+ size_t block_size,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ const float* window,
+ size_t shift_amount,
+ BlockerCallback* callback)
+ : chunk_size_(chunk_size),
+ block_size_(block_size),
+ num_input_channels_(num_input_channels),
+ num_output_channels_(num_output_channels),
+ initial_delay_(block_size_ - gcd(chunk_size, shift_amount)),
+ frame_offset_(0),
+ input_buffer_(num_input_channels_, chunk_size_ + initial_delay_),
+ output_buffer_(chunk_size_ + initial_delay_, num_output_channels_),
+ input_block_(block_size_, num_input_channels_),
+ output_block_(block_size_, num_output_channels_),
+ window_(new float[block_size_]),
+ shift_amount_(shift_amount),
+ callback_(callback) {
+ RTC_CHECK_LE(num_output_channels_, num_input_channels_);
+ RTC_CHECK_LE(shift_amount_, block_size_);
+
+ memcpy(window_.get(), window, block_size_ * sizeof(*window_.get()));
+ input_buffer_.MoveReadPositionBackward(initial_delay_);
+}
+
+Blocker::~Blocker() = default;
+
+// When block_size < chunk_size the input and output buffers look like this:
+//
+// delay* chunk_size chunk_size + delay*
+// buffer: <-------------|---------------------|---------------|>
+// _a_ _b_ _c_
+//
+// On each call to ProcessChunk():
+// 1. New input gets read into sections _b_ and _c_ of the input buffer.
+// 2. We block starting from frame_offset.
+// 3. We block until we reach a block `bl` that doesn't contain any frames
+// from sections _a_ or _b_ of the input buffer.
+// 4. We window the current block, fire the callback for processing, window
+// again, and overlap/add to the output buffer.
+// 5. We copy sections _a_ and _b_ of the output buffer into output.
+// 6. For both the input and the output buffers, we copy section _c_ into
+// section _a_.
+// 7. We set the new frame_offset to be the difference between the first frame
+// of `bl` and the border between sections _b_ and _c_.
+//
+// When block_size > chunk_size the input and output buffers look like this:
+//
+// chunk_size delay* chunk_size + delay*
+// buffer: <-------------|---------------------|---------------|>
+// _a_ _b_ _c_
+//
+// On each call to ProcessChunk():
+// The procedure is the same as above, except for:
+// 1. New input gets read into section _c_ of the input buffer.
+// 3. We block until we reach a block `bl` that doesn't contain any frames
+// from section _a_ of the input buffer.
+// 5. We copy section _a_ of the output buffer into output.
+// 6. For both the input and the output buffers, we copy sections _b_ and _c_
+// into section _a_ and _b_.
+// 7. We set the new frame_offset to be the difference between the first frame
+// of `bl` and the border between sections _a_ and _b_.
+//
+// * delay here refers to inintial_delay_
+//
+// TODO(claguna): Look at using ring buffers to eliminate some copies.
+void Blocker::ProcessChunk(const float* const* input,
+ size_t chunk_size,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output) {
+ RTC_CHECK_EQ(chunk_size, chunk_size_);
+ RTC_CHECK_EQ(num_input_channels, num_input_channels_);
+ RTC_CHECK_EQ(num_output_channels, num_output_channels_);
+
+ input_buffer_.Write(input, num_input_channels, chunk_size_);
+ size_t first_frame_in_block = frame_offset_;
+
+ // Loop through blocks.
+ while (first_frame_in_block < chunk_size_) {
+ input_buffer_.Read(input_block_.channels(), num_input_channels,
+ block_size_);
+ input_buffer_.MoveReadPositionBackward(block_size_ - shift_amount_);
+
+ ApplyWindow(window_.get(), block_size_, num_input_channels_,
+ input_block_.channels());
+ callback_->ProcessBlock(input_block_.channels(), block_size_,
+ num_input_channels_, num_output_channels_,
+ output_block_.channels());
+ ApplyWindow(window_.get(), block_size_, num_output_channels_,
+ output_block_.channels());
+
+ AddFrames(output_buffer_.channels(), first_frame_in_block,
+ output_block_.channels(), 0, block_size_, num_output_channels_,
+ output_buffer_.channels(), first_frame_in_block);
+
+ first_frame_in_block += shift_amount_;
+ }
+
+ // Copy output buffer to output
+ CopyFrames(output_buffer_.channels(), 0, chunk_size_, num_output_channels_,
+ output, 0);
+
+ // Copy output buffer [chunk_size_, chunk_size_ + initial_delay]
+ // to output buffer [0, initial_delay], zero the rest.
+ MoveFrames(output_buffer_.channels(), chunk_size, initial_delay_,
+ num_output_channels_, output_buffer_.channels(), 0);
+ ZeroOut(output_buffer_.channels(), initial_delay_, chunk_size_,
+ num_output_channels_);
+
+ // Calculate new starting frames.
+ frame_offset_ = first_frame_in_block - chunk_size_;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.h
new file mode 100644
index 0000000000..59b7e29621
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_TEST_BLOCKER_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_TEST_BLOCKER_H_
+
+#include <memory>
+
+#include "common_audio/channel_buffer.h"
+#include "modules/audio_coding/codecs/opus/test/audio_ring_buffer.h"
+
+namespace webrtc {
+
+// The callback function to process audio in the time domain. Input has already
+// been windowed, and output will be windowed. The number of input channels
+// must be >= the number of output channels.
+class BlockerCallback {
+ public:
+ virtual ~BlockerCallback() {}
+
+ virtual void ProcessBlock(const float* const* input,
+ size_t num_frames,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output) = 0;
+};
+
+// The main purpose of Blocker is to abstract away the fact that often we
+// receive a different number of audio frames than our transform takes. For
+// example, most FFTs work best when the fft-size is a power of 2, but suppose
+// we receive 20ms of audio at a sample rate of 48000. That comes to 960 frames
+// of audio, which is not a power of 2. Blocker allows us to specify the
+// transform and all other necessary processing via the Process() callback
+// function without any constraints on the transform-size
+// (read: `block_size_`) or received-audio-size (read: `chunk_size_`).
+// We handle this for the multichannel audio case, allowing for different
+// numbers of input and output channels (for example, beamforming takes 2 or
+// more input channels and returns 1 output channel). Audio signals are
+// represented as deinterleaved floats in the range [-1, 1].
+//
+// Blocker is responsible for:
+// - blocking audio while handling potential discontinuities on the edges
+// of chunks
+// - windowing blocks before sending them to Process()
+// - windowing processed blocks, and overlap-adding them together before
+// sending back a processed chunk
+//
+// To use blocker:
+// 1. Impelment a BlockerCallback object `bc`.
+// 2. Instantiate a Blocker object `b`, passing in `bc`.
+// 3. As you receive audio, call b.ProcessChunk() to get processed audio.
+//
+// A small amount of delay is added to the first received chunk to deal with
+// the difference in chunk/block sizes. This delay is <= chunk_size.
+//
+// Ownership of window is retained by the caller. That is, Blocker makes a
+// copy of window and does not attempt to delete it.
+class Blocker {
+ public:
+ Blocker(size_t chunk_size,
+ size_t block_size,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ const float* window,
+ size_t shift_amount,
+ BlockerCallback* callback);
+ ~Blocker();
+
+ void ProcessChunk(const float* const* input,
+ size_t chunk_size,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output);
+
+ size_t initial_delay() const { return initial_delay_; }
+
+ private:
+ const size_t chunk_size_;
+ const size_t block_size_;
+ const size_t num_input_channels_;
+ const size_t num_output_channels_;
+
+ // The number of frames of delay to add at the beginning of the first chunk.
+ const size_t initial_delay_;
+
+ // The frame index into the input buffer where the first block should be read
+ // from. This is necessary because shift_amount_ is not necessarily a
+ // multiple of chunk_size_, so blocks won't line up at the start of the
+ // buffer.
+ size_t frame_offset_;
+
+ // Since blocks nearly always overlap, there are certain blocks that require
+ // frames from the end of one chunk and the beginning of the next chunk. The
+ // input and output buffers are responsible for saving those frames between
+ // calls to ProcessChunk().
+ //
+ // Both contain |initial delay| + `chunk_size` frames. The input is a fairly
+ // standard FIFO, but due to the overlap-add it's harder to use an
+ // AudioRingBuffer for the output.
+ AudioRingBuffer input_buffer_;
+ ChannelBuffer<float> output_buffer_;
+
+ // Space for the input block (can't wrap because of windowing).
+ ChannelBuffer<float> input_block_;
+
+ // Space for the output block (can't wrap because of overlap/add).
+ ChannelBuffer<float> output_block_;
+
+ std::unique_ptr<float[]> window_;
+
+ // The amount of frames between the start of contiguous blocks. For example,
+ // `shift_amount_` = `block_size_` / 2 for a Hann window.
+ size_t shift_amount_;
+
+ BlockerCallback* callback_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_TEST_BLOCKER_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker_unittest.cc
new file mode 100644
index 0000000000..9c8e789ba9
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/blocker_unittest.cc
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/test/blocker.h"
+
+#include <memory>
+
+#include "rtc_base/arraysize.h"
+#include "test/gtest.h"
+
+namespace {
+
+// Callback Function to add 3 to every sample in the signal.
+class PlusThreeBlockerCallback : public webrtc::BlockerCallback {
+ public:
+ void ProcessBlock(const float* const* input,
+ size_t num_frames,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output) override {
+ for (size_t i = 0; i < num_output_channels; ++i) {
+ for (size_t j = 0; j < num_frames; ++j) {
+ output[i][j] = input[i][j] + 3;
+ }
+ }
+ }
+};
+
+// No-op Callback Function.
+class CopyBlockerCallback : public webrtc::BlockerCallback {
+ public:
+ void ProcessBlock(const float* const* input,
+ size_t num_frames,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output) override {
+ for (size_t i = 0; i < num_output_channels; ++i) {
+ for (size_t j = 0; j < num_frames; ++j) {
+ output[i][j] = input[i][j];
+ }
+ }
+ }
+};
+
+} // namespace
+
+namespace webrtc {
+
+// Tests blocking with a window that multiplies the signal by 2, a callback
+// that adds 3 to each sample in the signal, and different combinations of chunk
+// size, block size, and shift amount.
+class BlockerTest : public ::testing::Test {
+ protected:
+ void RunTest(Blocker* blocker,
+ size_t chunk_size,
+ size_t num_frames,
+ const float* const* input,
+ float* const* input_chunk,
+ float* const* output,
+ float* const* output_chunk,
+ size_t num_input_channels,
+ size_t num_output_channels) {
+ size_t start = 0;
+ size_t end = chunk_size - 1;
+ while (end < num_frames) {
+ CopyTo(input_chunk, 0, start, num_input_channels, chunk_size, input);
+ blocker->ProcessChunk(input_chunk, chunk_size, num_input_channels,
+ num_output_channels, output_chunk);
+ CopyTo(output, start, 0, num_output_channels, chunk_size, output_chunk);
+
+ start += chunk_size;
+ end += chunk_size;
+ }
+ }
+
+ void ValidateSignalEquality(const float* const* expected,
+ const float* const* actual,
+ size_t num_channels,
+ size_t num_frames) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ for (size_t j = 0; j < num_frames; ++j) {
+ EXPECT_FLOAT_EQ(expected[i][j], actual[i][j]);
+ }
+ }
+ }
+
+ void ValidateInitialDelay(const float* const* output,
+ size_t num_channels,
+ size_t num_frames,
+ size_t initial_delay) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ for (size_t j = 0; j < num_frames; ++j) {
+ if (j < initial_delay) {
+ EXPECT_FLOAT_EQ(output[i][j], 0.f);
+ } else {
+ EXPECT_GT(output[i][j], 0.f);
+ }
+ }
+ }
+ }
+
+ static void CopyTo(float* const* dst,
+ size_t start_index_dst,
+ size_t start_index_src,
+ size_t num_channels,
+ size_t num_frames,
+ const float* const* src) {
+ for (size_t i = 0; i < num_channels; ++i) {
+ memcpy(&dst[i][start_index_dst], &src[i][start_index_src],
+ num_frames * sizeof(float));
+ }
+ }
+};
+
+TEST_F(BlockerTest, TestBlockerMutuallyPrimeChunkandBlockSize) {
+ const size_t kNumInputChannels = 3;
+ const size_t kNumOutputChannels = 2;
+ const size_t kNumFrames = 10;
+ const size_t kBlockSize = 4;
+ const size_t kChunkSize = 5;
+ const size_t kShiftAmount = 2;
+
+ const float kInput[kNumInputChannels][kNumFrames] = {
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+ {3, 3, 3, 3, 3, 3, 3, 3, 3, 3}};
+ ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
+ input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput));
+
+ const float kExpectedOutput[kNumInputChannels][kNumFrames] = {
+ {6, 6, 12, 20, 20, 20, 20, 20, 20, 20},
+ {6, 6, 12, 28, 28, 28, 28, 28, 28, 28}};
+ ChannelBuffer<float> expected_output_cb(kNumFrames, kNumInputChannels);
+ expected_output_cb.SetDataForTesting(
+ kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput));
+
+ const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f};
+
+ ChannelBuffer<float> actual_output_cb(kNumFrames, kNumOutputChannels);
+ ChannelBuffer<float> input_chunk_cb(kChunkSize, kNumInputChannels);
+ ChannelBuffer<float> output_chunk_cb(kChunkSize, kNumOutputChannels);
+
+ PlusThreeBlockerCallback callback;
+ Blocker blocker(kChunkSize, kBlockSize, kNumInputChannels, kNumOutputChannels,
+ kWindow, kShiftAmount, &callback);
+
+ RunTest(&blocker, kChunkSize, kNumFrames, input_cb.channels(),
+ input_chunk_cb.channels(), actual_output_cb.channels(),
+ output_chunk_cb.channels(), kNumInputChannels, kNumOutputChannels);
+
+ ValidateSignalEquality(expected_output_cb.channels(),
+ actual_output_cb.channels(), kNumOutputChannels,
+ kNumFrames);
+}
+
+TEST_F(BlockerTest, TestBlockerMutuallyPrimeShiftAndBlockSize) {
+ const size_t kNumInputChannels = 3;
+ const size_t kNumOutputChannels = 2;
+ const size_t kNumFrames = 12;
+ const size_t kBlockSize = 4;
+ const size_t kChunkSize = 6;
+ const size_t kShiftAmount = 3;
+
+ const float kInput[kNumInputChannels][kNumFrames] = {
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+ {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}};
+ ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
+ input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput));
+
+ const float kExpectedOutput[kNumOutputChannels][kNumFrames] = {
+ {6, 10, 10, 20, 10, 10, 20, 10, 10, 20, 10, 10},
+ {6, 14, 14, 28, 14, 14, 28, 14, 14, 28, 14, 14}};
+ ChannelBuffer<float> expected_output_cb(kNumFrames, kNumOutputChannels);
+ expected_output_cb.SetDataForTesting(
+ kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput));
+
+ const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f};
+
+ ChannelBuffer<float> actual_output_cb(kNumFrames, kNumOutputChannels);
+ ChannelBuffer<float> input_chunk_cb(kChunkSize, kNumInputChannels);
+ ChannelBuffer<float> output_chunk_cb(kChunkSize, kNumOutputChannels);
+
+ PlusThreeBlockerCallback callback;
+ Blocker blocker(kChunkSize, kBlockSize, kNumInputChannels, kNumOutputChannels,
+ kWindow, kShiftAmount, &callback);
+
+ RunTest(&blocker, kChunkSize, kNumFrames, input_cb.channels(),
+ input_chunk_cb.channels(), actual_output_cb.channels(),
+ output_chunk_cb.channels(), kNumInputChannels, kNumOutputChannels);
+
+ ValidateSignalEquality(expected_output_cb.channels(),
+ actual_output_cb.channels(), kNumOutputChannels,
+ kNumFrames);
+}
+
+TEST_F(BlockerTest, TestBlockerNoOverlap) {
+ const size_t kNumInputChannels = 3;
+ const size_t kNumOutputChannels = 2;
+ const size_t kNumFrames = 12;
+ const size_t kBlockSize = 4;
+ const size_t kChunkSize = 4;
+ const size_t kShiftAmount = 4;
+
+ const float kInput[kNumInputChannels][kNumFrames] = {
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+ {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}};
+ ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
+ input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput));
+
+ const float kExpectedOutput[kNumOutputChannels][kNumFrames] = {
+ {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
+ {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}};
+ ChannelBuffer<float> expected_output_cb(kNumFrames, kNumOutputChannels);
+ expected_output_cb.SetDataForTesting(
+ kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput));
+
+ const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f};
+
+ ChannelBuffer<float> actual_output_cb(kNumFrames, kNumOutputChannels);
+ ChannelBuffer<float> input_chunk_cb(kChunkSize, kNumInputChannels);
+ ChannelBuffer<float> output_chunk_cb(kChunkSize, kNumOutputChannels);
+
+ PlusThreeBlockerCallback callback;
+ Blocker blocker(kChunkSize, kBlockSize, kNumInputChannels, kNumOutputChannels,
+ kWindow, kShiftAmount, &callback);
+
+ RunTest(&blocker, kChunkSize, kNumFrames, input_cb.channels(),
+ input_chunk_cb.channels(), actual_output_cb.channels(),
+ output_chunk_cb.channels(), kNumInputChannels, kNumOutputChannels);
+
+ ValidateSignalEquality(expected_output_cb.channels(),
+ actual_output_cb.channels(), kNumOutputChannels,
+ kNumFrames);
+}
+
+TEST_F(BlockerTest, InitialDelaysAreMinimum) {
+ const size_t kNumInputChannels = 3;
+ const size_t kNumOutputChannels = 2;
+ const size_t kNumFrames = 1280;
+ const size_t kChunkSize[] = {80, 80, 80, 80, 80, 80,
+ 160, 160, 160, 160, 160, 160};
+ const size_t kBlockSize[] = {64, 64, 64, 128, 128, 128,
+ 128, 128, 128, 256, 256, 256};
+ const size_t kShiftAmount[] = {16, 32, 64, 32, 64, 128,
+ 32, 64, 128, 64, 128, 256};
+ const size_t kInitialDelay[] = {48, 48, 48, 112, 112, 112,
+ 96, 96, 96, 224, 224, 224};
+
+ float input[kNumInputChannels][kNumFrames];
+ for (size_t i = 0; i < kNumInputChannels; ++i) {
+ for (size_t j = 0; j < kNumFrames; ++j) {
+ input[i][j] = i + 1;
+ }
+ }
+ ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
+ input_cb.SetDataForTesting(input[0], sizeof(input) / sizeof(**input));
+
+ ChannelBuffer<float> output_cb(kNumFrames, kNumOutputChannels);
+
+ CopyBlockerCallback callback;
+
+ for (size_t i = 0; i < arraysize(kChunkSize); ++i) {
+ std::unique_ptr<float[]> window(new float[kBlockSize[i]]);
+ for (size_t j = 0; j < kBlockSize[i]; ++j) {
+ window[j] = 1.f;
+ }
+
+ ChannelBuffer<float> input_chunk_cb(kChunkSize[i], kNumInputChannels);
+ ChannelBuffer<float> output_chunk_cb(kChunkSize[i], kNumOutputChannels);
+
+ Blocker blocker(kChunkSize[i], kBlockSize[i], kNumInputChannels,
+ kNumOutputChannels, window.get(), kShiftAmount[i],
+ &callback);
+
+ RunTest(&blocker, kChunkSize[i], kNumFrames, input_cb.channels(),
+ input_chunk_cb.channels(), output_cb.channels(),
+ output_chunk_cb.channels(), kNumInputChannels, kNumOutputChannels);
+
+ ValidateInitialDelay(output_cb.channels(), kNumOutputChannels, kNumFrames,
+ kInitialDelay[i]);
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.cc
new file mode 100644
index 0000000000..b1a6526bba
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/test/lapped_transform.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+
+#include "common_audio/real_fourier.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+void LappedTransform::BlockThunk::ProcessBlock(const float* const* input,
+ size_t num_frames,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output) {
+ RTC_CHECK_EQ(num_input_channels, parent_->num_in_channels_);
+ RTC_CHECK_EQ(num_output_channels, parent_->num_out_channels_);
+ RTC_CHECK_EQ(parent_->block_length_, num_frames);
+
+ for (size_t i = 0; i < num_input_channels; ++i) {
+ memcpy(parent_->real_buf_.Row(i), input[i], num_frames * sizeof(*input[0]));
+ parent_->fft_->Forward(parent_->real_buf_.Row(i),
+ parent_->cplx_pre_.Row(i));
+ }
+
+ size_t block_length =
+ RealFourier::ComplexLength(RealFourier::FftOrder(num_frames));
+ RTC_CHECK_EQ(parent_->cplx_length_, block_length);
+ parent_->block_processor_->ProcessAudioBlock(
+ parent_->cplx_pre_.Array(), num_input_channels, parent_->cplx_length_,
+ num_output_channels, parent_->cplx_post_.Array());
+
+ for (size_t i = 0; i < num_output_channels; ++i) {
+ parent_->fft_->Inverse(parent_->cplx_post_.Row(i),
+ parent_->real_buf_.Row(i));
+ memcpy(output[i], parent_->real_buf_.Row(i),
+ num_frames * sizeof(*input[0]));
+ }
+}
+
+LappedTransform::LappedTransform(size_t num_in_channels,
+ size_t num_out_channels,
+ size_t chunk_length,
+ const float* window,
+ size_t block_length,
+ size_t shift_amount,
+ Callback* callback)
+ : blocker_callback_(this),
+ num_in_channels_(num_in_channels),
+ num_out_channels_(num_out_channels),
+ block_length_(block_length),
+ chunk_length_(chunk_length),
+ block_processor_(callback),
+ blocker_(chunk_length_,
+ block_length_,
+ num_in_channels_,
+ num_out_channels_,
+ window,
+ shift_amount,
+ &blocker_callback_),
+ fft_(RealFourier::Create(RealFourier::FftOrder(block_length_))),
+ cplx_length_(RealFourier::ComplexLength(fft_->order())),
+ real_buf_(num_in_channels,
+ block_length_,
+ RealFourier::kFftBufferAlignment),
+ cplx_pre_(num_in_channels,
+ cplx_length_,
+ RealFourier::kFftBufferAlignment),
+ cplx_post_(num_out_channels,
+ cplx_length_,
+ RealFourier::kFftBufferAlignment) {
+ RTC_CHECK(num_in_channels_ > 0);
+ RTC_CHECK_GT(block_length_, 0);
+ RTC_CHECK_GT(chunk_length_, 0);
+ RTC_CHECK(block_processor_);
+
+ // block_length_ power of 2?
+ RTC_CHECK_EQ(0, block_length_ & (block_length_ - 1));
+}
+
+LappedTransform::~LappedTransform() = default;
+
+void LappedTransform::ProcessChunk(const float* const* in_chunk,
+ float* const* out_chunk) {
+ blocker_.ProcessChunk(in_chunk, chunk_length_, num_in_channels_,
+ num_out_channels_, out_chunk);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.h b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.h
new file mode 100644
index 0000000000..bb25c34a9e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_OPUS_TEST_LAPPED_TRANSFORM_H_
+#define MODULES_AUDIO_CODING_CODECS_OPUS_TEST_LAPPED_TRANSFORM_H_
+
+#include <complex>
+#include <memory>
+
+#include "common_audio/real_fourier.h"
+#include "modules/audio_coding/codecs/opus/test/blocker.h"
+#include "rtc_base/memory/aligned_malloc.h"
+
+namespace webrtc {
+
+// Wrapper class for aligned arrays. Every row (and the first dimension) are
+// aligned to the given byte alignment.
+template <typename T>
+class AlignedArray {
+ public:
+ AlignedArray(size_t rows, size_t cols, size_t alignment)
+ : rows_(rows), cols_(cols) {
+ RTC_CHECK_GT(alignment, 0);
+ head_row_ =
+ static_cast<T**>(AlignedMalloc(rows_ * sizeof(*head_row_), alignment));
+ for (size_t i = 0; i < rows_; ++i) {
+ head_row_[i] = static_cast<T*>(
+ AlignedMalloc(cols_ * sizeof(**head_row_), alignment));
+ }
+ }
+
+ ~AlignedArray() {
+ for (size_t i = 0; i < rows_; ++i) {
+ AlignedFree(head_row_[i]);
+ }
+ AlignedFree(head_row_);
+ }
+
+ T* const* Array() { return head_row_; }
+
+ const T* const* Array() const { return head_row_; }
+
+ T* Row(size_t row) {
+ RTC_CHECK_LE(row, rows_);
+ return head_row_[row];
+ }
+
+ const T* Row(size_t row) const {
+ RTC_CHECK_LE(row, rows_);
+ return head_row_[row];
+ }
+
+ private:
+ size_t rows_;
+ size_t cols_;
+ T** head_row_;
+};
+
+// Helper class for audio processing modules which operate on frequency domain
+// input derived from the windowed time domain audio stream.
+//
+// The input audio chunk is sliced into possibly overlapping blocks, multiplied
+// by a window and transformed with an FFT implementation. The transformed data
+// is supplied to the given callback for processing. The processed output is
+// then inverse transformed into the time domain and spliced back into a chunk
+// which constitutes the final output of this processing module.
+class LappedTransform {
+ public:
+ class Callback {
+ public:
+ virtual ~Callback() {}
+
+ virtual void ProcessAudioBlock(const std::complex<float>* const* in_block,
+ size_t num_in_channels,
+ size_t frames,
+ size_t num_out_channels,
+ std::complex<float>* const* out_block) = 0;
+ };
+
+ // Construct a transform instance. `chunk_length` is the number of samples in
+ // each channel. `window` defines the window, owned by the caller (a copy is
+ // made internally); `window` should have length equal to `block_length`.
+ // `block_length` defines the length of a block, in samples.
+ // `shift_amount` is in samples. `callback` is the caller-owned audio
+ // processing function called for each block of the input chunk.
+ LappedTransform(size_t num_in_channels,
+ size_t num_out_channels,
+ size_t chunk_length,
+ const float* window,
+ size_t block_length,
+ size_t shift_amount,
+ Callback* callback);
+ ~LappedTransform();
+
+ // Main audio processing helper method. Internally slices `in_chunk` into
+ // blocks, transforms them to frequency domain, calls the callback for each
+ // block and returns a de-blocked time domain chunk of audio through
+ // `out_chunk`. Both buffers are caller-owned.
+ void ProcessChunk(const float* const* in_chunk, float* const* out_chunk);
+
+ // Get the chunk length.
+ //
+ // The chunk length is the number of samples per channel that must be passed
+ // to ProcessChunk via the parameter in_chunk.
+ //
+ // Returns the same chunk_length passed to the LappedTransform constructor.
+ size_t chunk_length() const { return chunk_length_; }
+
+ // Get the number of input channels.
+ //
+ // This is the number of arrays that must be passed to ProcessChunk via
+ // in_chunk.
+ //
+ // Returns the same num_in_channels passed to the LappedTransform constructor.
+ size_t num_in_channels() const { return num_in_channels_; }
+
+ // Get the number of output channels.
+ //
+ // This is the number of arrays that must be passed to ProcessChunk via
+ // out_chunk.
+ //
+ // Returns the same num_out_channels passed to the LappedTransform
+ // constructor.
+ size_t num_out_channels() const { return num_out_channels_; }
+
+ // Returns the initial delay.
+ //
+ // This is the delay introduced by the `blocker_` to be able to get and return
+ // chunks of `chunk_length`, but process blocks of `block_length`.
+ size_t initial_delay() const { return blocker_.initial_delay(); }
+
+ private:
+ // Internal middleware callback, given to the blocker. Transforms each block
+ // and hands it over to the processing method given at construction time.
+ class BlockThunk : public BlockerCallback {
+ public:
+ explicit BlockThunk(LappedTransform* parent) : parent_(parent) {}
+
+ void ProcessBlock(const float* const* input,
+ size_t num_frames,
+ size_t num_input_channels,
+ size_t num_output_channels,
+ float* const* output) override;
+
+ private:
+ LappedTransform* const parent_;
+ } blocker_callback_;
+
+ const size_t num_in_channels_;
+ const size_t num_out_channels_;
+
+ const size_t block_length_;
+ const size_t chunk_length_;
+
+ Callback* const block_processor_;
+ Blocker blocker_;
+
+ // TODO(alessiob): Replace RealFourier with a different FFT library.
+ std::unique_ptr<RealFourier> fft_;
+ const size_t cplx_length_;
+ AlignedArray<float> real_buf_;
+ AlignedArray<std::complex<float> > cplx_pre_;
+ AlignedArray<std::complex<float> > cplx_post_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_OPUS_TEST_LAPPED_TRANSFORM_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform_unittest.cc
new file mode 100644
index 0000000000..1003ed52e5
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/test/lapped_transform_unittest.cc
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/test/lapped_transform.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstring>
+
+#include "test/gtest.h"
+
+using std::complex;
+
+namespace {
+
+class NoopCallback : public webrtc::LappedTransform::Callback {
+ public:
+ NoopCallback() : block_num_(0) {}
+
+ void ProcessAudioBlock(const complex<float>* const* in_block,
+ size_t in_channels,
+ size_t frames,
+ size_t out_channels,
+ complex<float>* const* out_block) override {
+ RTC_CHECK_EQ(in_channels, out_channels);
+ for (size_t i = 0; i < out_channels; ++i) {
+ memcpy(out_block[i], in_block[i], sizeof(**in_block) * frames);
+ }
+ ++block_num_;
+ }
+
+ size_t block_num() { return block_num_; }
+
+ private:
+ size_t block_num_;
+};
+
+class FftCheckerCallback : public webrtc::LappedTransform::Callback {
+ public:
+ FftCheckerCallback() : block_num_(0) {}
+
+ void ProcessAudioBlock(const complex<float>* const* in_block,
+ size_t in_channels,
+ size_t frames,
+ size_t out_channels,
+ complex<float>* const* out_block) override {
+ RTC_CHECK_EQ(in_channels, out_channels);
+
+ size_t full_length = (frames - 1) * 2;
+ ++block_num_;
+
+ if (block_num_ > 0) {
+ ASSERT_NEAR(in_block[0][0].real(), static_cast<float>(full_length),
+ 1e-5f);
+ ASSERT_NEAR(in_block[0][0].imag(), 0.0f, 1e-5f);
+ for (size_t i = 1; i < frames; ++i) {
+ ASSERT_NEAR(in_block[0][i].real(), 0.0f, 1e-5f);
+ ASSERT_NEAR(in_block[0][i].imag(), 0.0f, 1e-5f);
+ }
+ }
+ }
+
+ size_t block_num() { return block_num_; }
+
+ private:
+ size_t block_num_;
+};
+
+void SetFloatArray(float value, int rows, int cols, float* const* array) {
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < cols; ++j) {
+ array[i][j] = value;
+ }
+ }
+}
+
+} // namespace
+
+namespace webrtc {
+
+TEST(LappedTransformTest, Windowless) {
+ const size_t kChannels = 3;
+ const size_t kChunkLength = 512;
+ const size_t kBlockLength = 64;
+ const size_t kShiftAmount = 64;
+ NoopCallback noop;
+
+ // Rectangular window.
+ float window[kBlockLength];
+ std::fill(window, &window[kBlockLength], 1.0f);
+
+ LappedTransform trans(kChannels, kChannels, kChunkLength, window,
+ kBlockLength, kShiftAmount, &noop);
+ float in_buffer[kChannels][kChunkLength];
+ float* in_chunk[kChannels];
+ float out_buffer[kChannels][kChunkLength];
+ float* out_chunk[kChannels];
+
+ in_chunk[0] = in_buffer[0];
+ in_chunk[1] = in_buffer[1];
+ in_chunk[2] = in_buffer[2];
+ out_chunk[0] = out_buffer[0];
+ out_chunk[1] = out_buffer[1];
+ out_chunk[2] = out_buffer[2];
+ SetFloatArray(2.0f, kChannels, kChunkLength, in_chunk);
+ SetFloatArray(-1.0f, kChannels, kChunkLength, out_chunk);
+
+ trans.ProcessChunk(in_chunk, out_chunk);
+
+ for (size_t i = 0; i < kChannels; ++i) {
+ for (size_t j = 0; j < kChunkLength; ++j) {
+ ASSERT_NEAR(out_chunk[i][j], 2.0f, 1e-5f);
+ }
+ }
+
+ ASSERT_EQ(kChunkLength / kBlockLength, noop.block_num());
+}
+
+TEST(LappedTransformTest, IdentityProcessor) {
+ const size_t kChunkLength = 512;
+ const size_t kBlockLength = 64;
+ const size_t kShiftAmount = 32;
+ NoopCallback noop;
+
+ // Identity window for |overlap = block_size / 2|.
+ float window[kBlockLength];
+ std::fill(window, &window[kBlockLength], std::sqrt(0.5f));
+
+ LappedTransform trans(1, 1, kChunkLength, window, kBlockLength, kShiftAmount,
+ &noop);
+ float in_buffer[kChunkLength];
+ float* in_chunk = in_buffer;
+ float out_buffer[kChunkLength];
+ float* out_chunk = out_buffer;
+
+ SetFloatArray(2.0f, 1, kChunkLength, &in_chunk);
+ SetFloatArray(-1.0f, 1, kChunkLength, &out_chunk);
+
+ trans.ProcessChunk(&in_chunk, &out_chunk);
+
+ for (size_t i = 0; i < kChunkLength; ++i) {
+ ASSERT_NEAR(out_chunk[i], (i < kBlockLength - kShiftAmount) ? 0.0f : 2.0f,
+ 1e-5f);
+ }
+
+ ASSERT_EQ(kChunkLength / kShiftAmount, noop.block_num());
+}
+
+TEST(LappedTransformTest, Callbacks) {
+ const size_t kChunkLength = 512;
+ const size_t kBlockLength = 64;
+ FftCheckerCallback call;
+
+ // Rectangular window.
+ float window[kBlockLength];
+ std::fill(window, &window[kBlockLength], 1.0f);
+
+ LappedTransform trans(1, 1, kChunkLength, window, kBlockLength, kBlockLength,
+ &call);
+ float in_buffer[kChunkLength];
+ float* in_chunk = in_buffer;
+ float out_buffer[kChunkLength];
+ float* out_chunk = out_buffer;
+
+ SetFloatArray(1.0f, 1, kChunkLength, &in_chunk);
+ SetFloatArray(-1.0f, 1, kChunkLength, &out_chunk);
+
+ trans.ProcessChunk(&in_chunk, &out_chunk);
+
+ ASSERT_EQ(kChunkLength / kBlockLength, call.block_num());
+}
+
+TEST(LappedTransformTest, chunk_length) {
+ const size_t kBlockLength = 64;
+ FftCheckerCallback call;
+ const float window[kBlockLength] = {};
+
+ // Make sure that chunk_length returns the same value passed to the
+ // LappedTransform constructor.
+ {
+ const size_t kExpectedChunkLength = 512;
+ const LappedTransform trans(1, 1, kExpectedChunkLength, window,
+ kBlockLength, kBlockLength, &call);
+
+ EXPECT_EQ(kExpectedChunkLength, trans.chunk_length());
+ }
+ {
+ const size_t kExpectedChunkLength = 160;
+ const LappedTransform trans(1, 1, kExpectedChunkLength, window,
+ kBlockLength, kBlockLength, &call);
+
+ EXPECT_EQ(kExpectedChunkLength, trans.chunk_length());
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
new file mode 100644
index 0000000000..7761efe8b3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h"
+
+#include <utility>
+
+#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
+#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+AudioDecoderPcm16B::AudioDecoderPcm16B(int sample_rate_hz, size_t num_channels)
+ : sample_rate_hz_(sample_rate_hz), num_channels_(num_channels) {
+ RTC_DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
+ sample_rate_hz == 32000 || sample_rate_hz == 48000)
+ << "Unsupported sample rate " << sample_rate_hz;
+ RTC_DCHECK_GE(num_channels, 1);
+}
+
+void AudioDecoderPcm16B::Reset() {}
+
+int AudioDecoderPcm16B::SampleRateHz() const {
+ return sample_rate_hz_;
+}
+
+size_t AudioDecoderPcm16B::Channels() const {
+ return num_channels_;
+}
+
+int AudioDecoderPcm16B::DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ RTC_DCHECK_EQ(sample_rate_hz_, sample_rate_hz);
+ // Adjust the encoded length down to ensure the same number of samples in each
+ // channel.
+ const size_t encoded_len_adjusted =
+ PacketDuration(encoded, encoded_len) * 2 *
+ Channels(); // 2 bytes per sample per channel
+ size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len_adjusted, decoded);
+ *speech_type = ConvertSpeechType(1);
+ return static_cast<int>(ret);
+}
+
+std::vector<AudioDecoder::ParseResult> AudioDecoderPcm16B::ParsePayload(
+ rtc::Buffer&& payload,
+ uint32_t timestamp) {
+ const int samples_per_ms = rtc::CheckedDivExact(sample_rate_hz_, 1000);
+ return LegacyEncodedAudioFrame::SplitBySamples(
+ this, std::move(payload), timestamp, samples_per_ms * 2 * num_channels_,
+ samples_per_ms);
+}
+
+int AudioDecoderPcm16B::PacketDuration(const uint8_t* encoded,
+ size_t encoded_len) const {
+ // Two encoded byte per sample per channel.
+ return static_cast<int>(encoded_len / (2 * Channels()));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
new file mode 100644
index 0000000000..6f50161d3f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_DECODER_PCM16B_H_
+#define MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_DECODER_PCM16B_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "rtc_base/buffer.h"
+
+namespace webrtc {
+
+class AudioDecoderPcm16B final : public AudioDecoder {
+ public:
+ AudioDecoderPcm16B(int sample_rate_hz, size_t num_channels);
+
+ AudioDecoderPcm16B(const AudioDecoderPcm16B&) = delete;
+ AudioDecoderPcm16B& operator=(const AudioDecoderPcm16B&) = delete;
+
+ void Reset() override;
+ std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
+ uint32_t timestamp) override;
+ int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+ int SampleRateHz() const override;
+ size_t Channels() const override;
+
+ protected:
+ int DecodeInternal(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override;
+
+ private:
+ const int sample_rate_hz_;
+ const size_t num_channels_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_DECODER_PCM16B_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
new file mode 100644
index 0000000000..9445b1ee3e
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
+
+#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+size_t AudioEncoderPcm16B::EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) {
+ return WebRtcPcm16b_Encode(audio, input_len, encoded);
+}
+
+size_t AudioEncoderPcm16B::BytesPerSample() const {
+ return 2;
+}
+
+AudioEncoder::CodecType AudioEncoderPcm16B::GetCodecType() const {
+ return CodecType::kOther;
+}
+
+bool AudioEncoderPcm16B::Config::IsOk() const {
+ if ((sample_rate_hz != 8000) && (sample_rate_hz != 16000) &&
+ (sample_rate_hz != 32000) && (sample_rate_hz != 48000))
+ return false;
+ return AudioEncoderPcm::Config::IsOk();
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
new file mode 100644
index 0000000000..c363b40b3f
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_ENCODER_PCM16B_H_
+#define MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_ENCODER_PCM16B_H_
+
+#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
+
+namespace webrtc {
+
+class AudioEncoderPcm16B final : public AudioEncoderPcm {
+ public:
+ struct Config : public AudioEncoderPcm::Config {
+ public:
+ Config() : AudioEncoderPcm::Config(107), sample_rate_hz(8000) {}
+ bool IsOk() const;
+
+ int sample_rate_hz;
+ };
+
+ explicit AudioEncoderPcm16B(const Config& config)
+ : AudioEncoderPcm(config, config.sample_rate_hz) {}
+
+ AudioEncoderPcm16B(const AudioEncoderPcm16B&) = delete;
+ AudioEncoderPcm16B& operator=(const AudioEncoderPcm16B&) = delete;
+
+ protected:
+ size_t EncodeCall(const int16_t* audio,
+ size_t input_len,
+ uint8_t* encoded) override;
+
+ size_t BytesPerSample() const override;
+
+ AudioEncoder::CodecType GetCodecType() const override;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_ENCODER_PCM16B_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.c b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.c
new file mode 100644
index 0000000000..2f6dce5f41
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
+
+size_t WebRtcPcm16b_Encode(const int16_t* speech,
+ size_t len,
+ uint8_t* encoded) {
+ size_t i;
+ for (i = 0; i < len; ++i) {
+ uint16_t s = speech[i];
+ encoded[2 * i] = s >> 8;
+ encoded[2 * i + 1] = s;
+ }
+ return 2 * len;
+}
+
+size_t WebRtcPcm16b_Decode(const uint8_t* encoded,
+ size_t len,
+ int16_t* speech) {
+ size_t i;
+ for (i = 0; i < len / 2; ++i)
+ speech[i] = encoded[2 * i] << 8 | encoded[2 * i + 1];
+ return len / 2;
+}
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h
new file mode 100644
index 0000000000..75d1efda3b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_PCM16B_PCM16B_H_
+#define MODULES_AUDIO_CODING_CODECS_PCM16B_PCM16B_H_
+/*
+ * Define the fixpoint numeric formats
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * WebRtcPcm16b_Encode(...)
+ *
+ * "Encode" a sample vector to 16 bit linear (Encoded standard is big endian)
+ *
+ * Input:
+ * - speech : Input speech vector
+ * - len : Number of samples in speech vector
+ *
+ * Output:
+ * - encoded : Encoded data vector (big endian 16 bit)
+ *
+ * Returned value : Length (in bytes) of coded data.
+ * Always equal to twice the len input parameter.
+ */
+
+size_t WebRtcPcm16b_Encode(const int16_t* speech, size_t len, uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcPcm16b_Decode(...)
+ *
+ * "Decode" a vector to 16 bit linear (Encoded standard is big endian)
+ *
+ * Input:
+ * - encoded : Encoded data vector (big endian 16 bit)
+ * - len : Number of bytes in encoded
+ *
+ * Output:
+ * - speech : Decoded speech vector
+ *
+ * Returned value : Samples in speech
+ */
+
+size_t WebRtcPcm16b_Decode(const uint8_t* encoded, size_t len, int16_t* speech);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MODULES_AUDIO_CODING_CODECS_PCM16B_PCM16B_H_ */
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.cc b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.cc
new file mode 100644
index 0000000000..ecf91b45ac
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/pcm16b/pcm16b_common.h"
+
+#include <stdint.h>
+
+#include <initializer_list>
+
+namespace webrtc {
+
+void Pcm16BAppendSupportedCodecSpecs(std::vector<AudioCodecSpec>* specs) {
+ for (uint8_t num_channels : {1, 2}) {
+ for (int sample_rate_hz : {8000, 16000, 32000}) {
+ specs->push_back(
+ {{"L16", sample_rate_hz, num_channels},
+ {sample_rate_hz, num_channels, sample_rate_hz * num_channels * 16}});
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.h b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.h
new file mode 100644
index 0000000000..3fae717ff3
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/pcm16b/pcm16b_common.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_PCM16B_PCM16B_COMMON_H_
+#define MODULES_AUDIO_CODING_CODECS_PCM16B_PCM16B_COMMON_H_
+
+#include <vector>
+
+#include "api/audio_codecs/audio_format.h"
+
+namespace webrtc {
+void Pcm16BAppendSupportedCodecSpecs(std::vector<AudioCodecSpec>* specs);
+}
+
+#endif // MODULES_AUDIO_CODING_CODECS_PCM16B_PCM16B_COMMON_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc b/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc
new file mode 100644
index 0000000000..724bba52d6
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
+
+#include <string.h>
+
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/byte_order.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+static constexpr const int kRedMaxPacketSize =
+ 1 << 10; // RED packets must be less than 1024 bytes to fit the 10 bit
+ // block length.
+static constexpr const size_t kRedMaxTimestampDelta =
+ 1 << 14; // RED packets can encode a timestamp delta of 14 bits.
+static constexpr const size_t kAudioMaxRtpPacketLen =
+ 1200; // The typical MTU is 1200 bytes.
+
+static constexpr size_t kRedHeaderLength = 4; // 4 bytes RED header.
+static constexpr size_t kRedLastHeaderLength =
+ 1; // reduced size for last RED header.
+
+static constexpr size_t kRedNumberOfRedundantEncodings =
+ 1; // The level of redundancy we support.
+
+AudioEncoderCopyRed::Config::Config() = default;
+AudioEncoderCopyRed::Config::Config(Config&&) = default;
+AudioEncoderCopyRed::Config::~Config() = default;
+
+size_t GetMaxRedundancyFromFieldTrial(const FieldTrialsView& field_trials) {
+ const std::string red_trial =
+ field_trials.Lookup("WebRTC-Audio-Red-For-Opus");
+ size_t redundancy = 0;
+ if (sscanf(red_trial.c_str(), "Enabled-%zu", &redundancy) != 1 ||
+ redundancy > 9) {
+ return kRedNumberOfRedundantEncodings;
+ }
+ return redundancy;
+}
+
+AudioEncoderCopyRed::AudioEncoderCopyRed(Config&& config,
+ const FieldTrialsView& field_trials)
+ : speech_encoder_(std::move(config.speech_encoder)),
+ primary_encoded_(0, kAudioMaxRtpPacketLen),
+ max_packet_length_(kAudioMaxRtpPacketLen),
+ red_payload_type_(config.payload_type) {
+ RTC_CHECK(speech_encoder_) << "Speech encoder not provided.";
+
+ auto number_of_redundant_encodings =
+ GetMaxRedundancyFromFieldTrial(field_trials);
+ for (size_t i = 0; i < number_of_redundant_encodings; i++) {
+ std::pair<EncodedInfo, rtc::Buffer> redundant;
+ redundant.second.EnsureCapacity(kAudioMaxRtpPacketLen);
+ redundant_encodings_.push_front(std::move(redundant));
+ }
+}
+
+AudioEncoderCopyRed::~AudioEncoderCopyRed() = default;
+
+int AudioEncoderCopyRed::SampleRateHz() const {
+ return speech_encoder_->SampleRateHz();
+}
+
+size_t AudioEncoderCopyRed::NumChannels() const {
+ return speech_encoder_->NumChannels();
+}
+
+int AudioEncoderCopyRed::RtpTimestampRateHz() const {
+ return speech_encoder_->RtpTimestampRateHz();
+}
+
+size_t AudioEncoderCopyRed::Num10MsFramesInNextPacket() const {
+ return speech_encoder_->Num10MsFramesInNextPacket();
+}
+
+size_t AudioEncoderCopyRed::Max10MsFramesInAPacket() const {
+ return speech_encoder_->Max10MsFramesInAPacket();
+}
+
+int AudioEncoderCopyRed::GetTargetBitrate() const {
+ return speech_encoder_->GetTargetBitrate();
+}
+
+AudioEncoder::EncodedInfo AudioEncoderCopyRed::EncodeImpl(
+ uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ primary_encoded_.Clear();
+ EncodedInfo info =
+ speech_encoder_->Encode(rtp_timestamp, audio, &primary_encoded_);
+ RTC_CHECK(info.redundant.empty()) << "Cannot use nested redundant encoders.";
+ RTC_DCHECK_EQ(primary_encoded_.size(), info.encoded_bytes);
+
+ if (info.encoded_bytes == 0 || info.encoded_bytes >= kRedMaxPacketSize) {
+ return info;
+ }
+ RTC_DCHECK_GT(max_packet_length_, info.encoded_bytes);
+
+ size_t header_length_bytes = kRedLastHeaderLength;
+ size_t bytes_available = max_packet_length_ - info.encoded_bytes;
+ auto it = redundant_encodings_.begin();
+
+ // Determine how much redundancy we can fit into our packet by
+ // iterating forward. This is determined both by the length as well
+ // as the timestamp difference. The latter can occur with opus DTX which
+ // has timestamp gaps of 400ms which exceeds REDs timestamp delta field size.
+ for (; it != redundant_encodings_.end(); it++) {
+ if (bytes_available < kRedHeaderLength + it->first.encoded_bytes) {
+ break;
+ }
+ if (it->first.encoded_bytes == 0) {
+ break;
+ }
+ if (rtp_timestamp - it->first.encoded_timestamp >= kRedMaxTimestampDelta) {
+ break;
+ }
+ bytes_available -= kRedHeaderLength + it->first.encoded_bytes;
+ header_length_bytes += kRedHeaderLength;
+ }
+
+ // Allocate room for RFC 2198 header.
+ encoded->SetSize(header_length_bytes);
+
+ // Iterate backwards and append the data.
+ size_t header_offset = 0;
+ while (it-- != redundant_encodings_.begin()) {
+ encoded->AppendData(it->second);
+
+ const uint32_t timestamp_delta =
+ info.encoded_timestamp - it->first.encoded_timestamp;
+ encoded->data()[header_offset] = it->first.payload_type | 0x80;
+ rtc::SetBE16(static_cast<uint8_t*>(encoded->data()) + header_offset + 1,
+ (timestamp_delta << 2) | (it->first.encoded_bytes >> 8));
+ encoded->data()[header_offset + 3] = it->first.encoded_bytes & 0xff;
+ header_offset += kRedHeaderLength;
+ info.redundant.push_back(it->first);
+ }
+
+ // `info` will be implicitly cast to an EncodedInfoLeaf struct, effectively
+ // discarding the (empty) vector of redundant information. This is
+ // intentional.
+ if (header_length_bytes > kRedHeaderLength) {
+ info.redundant.push_back(info);
+ RTC_DCHECK_EQ(info.speech,
+ info.redundant[info.redundant.size() - 1].speech);
+ }
+
+ encoded->AppendData(primary_encoded_);
+ RTC_DCHECK_EQ(header_offset, header_length_bytes - 1);
+ encoded->data()[header_offset] = info.payload_type;
+
+ // Shift the redundant encodings.
+ auto rit = redundant_encodings_.rbegin();
+ for (auto next = std::next(rit); next != redundant_encodings_.rend();
+ rit++, next = std::next(rit)) {
+ rit->first = next->first;
+ rit->second.SetData(next->second);
+ }
+ it = redundant_encodings_.begin();
+ if (it != redundant_encodings_.end()) {
+ it->first = info;
+ it->second.SetData(primary_encoded_);
+ }
+
+ // Update main EncodedInfo.
+ info.payload_type = red_payload_type_;
+ info.encoded_bytes = encoded->size();
+ return info;
+}
+
+void AudioEncoderCopyRed::Reset() {
+ speech_encoder_->Reset();
+ auto number_of_redundant_encodings = redundant_encodings_.size();
+ redundant_encodings_.clear();
+ for (size_t i = 0; i < number_of_redundant_encodings; i++) {
+ std::pair<EncodedInfo, rtc::Buffer> redundant;
+ redundant.second.EnsureCapacity(kAudioMaxRtpPacketLen);
+ redundant_encodings_.push_front(std::move(redundant));
+ }
+}
+
+bool AudioEncoderCopyRed::SetFec(bool enable) {
+ return speech_encoder_->SetFec(enable);
+}
+
+bool AudioEncoderCopyRed::SetDtx(bool enable) {
+ return speech_encoder_->SetDtx(enable);
+}
+
+bool AudioEncoderCopyRed::GetDtx() const {
+ return speech_encoder_->GetDtx();
+}
+
+bool AudioEncoderCopyRed::SetApplication(Application application) {
+ return speech_encoder_->SetApplication(application);
+}
+
+void AudioEncoderCopyRed::SetMaxPlaybackRate(int frequency_hz) {
+ speech_encoder_->SetMaxPlaybackRate(frequency_hz);
+}
+
+bool AudioEncoderCopyRed::EnableAudioNetworkAdaptor(
+ const std::string& config_string,
+ RtcEventLog* event_log) {
+ return speech_encoder_->EnableAudioNetworkAdaptor(config_string, event_log);
+}
+
+void AudioEncoderCopyRed::DisableAudioNetworkAdaptor() {
+ speech_encoder_->DisableAudioNetworkAdaptor();
+}
+
+void AudioEncoderCopyRed::OnReceivedUplinkPacketLossFraction(
+ float uplink_packet_loss_fraction) {
+ speech_encoder_->OnReceivedUplinkPacketLossFraction(
+ uplink_packet_loss_fraction);
+}
+
+void AudioEncoderCopyRed::OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) {
+ speech_encoder_->OnReceivedUplinkBandwidth(target_audio_bitrate_bps,
+ bwe_period_ms);
+}
+
+void AudioEncoderCopyRed::OnReceivedUplinkAllocation(
+ BitrateAllocationUpdate update) {
+ speech_encoder_->OnReceivedUplinkAllocation(update);
+}
+
+absl::optional<std::pair<TimeDelta, TimeDelta>>
+AudioEncoderCopyRed::GetFrameLengthRange() const {
+ return speech_encoder_->GetFrameLengthRange();
+}
+
+void AudioEncoderCopyRed::OnReceivedRtt(int rtt_ms) {
+ speech_encoder_->OnReceivedRtt(rtt_ms);
+}
+
+void AudioEncoderCopyRed::OnReceivedOverhead(size_t overhead_bytes_per_packet) {
+ max_packet_length_ = kAudioMaxRtpPacketLen - overhead_bytes_per_packet;
+ return speech_encoder_->OnReceivedOverhead(overhead_bytes_per_packet);
+}
+
+void AudioEncoderCopyRed::SetReceiverFrameLengthRange(int min_frame_length_ms,
+ int max_frame_length_ms) {
+ return speech_encoder_->SetReceiverFrameLengthRange(min_frame_length_ms,
+ max_frame_length_ms);
+}
+
+ANAStats AudioEncoderCopyRed::GetANAStats() const {
+ return speech_encoder_->GetANAStats();
+}
+
+rtc::ArrayView<std::unique_ptr<AudioEncoder>>
+AudioEncoderCopyRed::ReclaimContainedEncoders() {
+ return rtc::ArrayView<std::unique_ptr<AudioEncoder>>(&speech_encoder_, 1);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
new file mode 100644
index 0000000000..359b5eaa17
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_RED_AUDIO_ENCODER_COPY_RED_H_
+#define MODULES_AUDIO_CODING_CODECS_RED_AUDIO_ENCODER_COPY_RED_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <list>
+#include <memory>
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "api/field_trials_view.h"
+#include "api/units/time_delta.h"
+#include "rtc_base/buffer.h"
+
+namespace webrtc {
+
+// This class implements redundant audio coding as described in
+// https://tools.ietf.org/html/rfc2198
+// The class object will have an underlying AudioEncoder object that performs
+// the actual encodings. The current class will gather the N latest encodings
+// from the underlying codec into one packet. Currently N is hard-coded to 2.
+
+class AudioEncoderCopyRed final : public AudioEncoder {
+ public:
+ struct Config {
+ Config();
+ Config(Config&&);
+ ~Config();
+ int payload_type;
+ std::unique_ptr<AudioEncoder> speech_encoder;
+ };
+
+ AudioEncoderCopyRed(Config&& config, const FieldTrialsView& field_trials);
+
+ ~AudioEncoderCopyRed() override;
+
+ AudioEncoderCopyRed(const AudioEncoderCopyRed&) = delete;
+ AudioEncoderCopyRed& operator=(const AudioEncoderCopyRed&) = delete;
+
+ int SampleRateHz() const override;
+ size_t NumChannels() const override;
+ int RtpTimestampRateHz() const override;
+ size_t Num10MsFramesInNextPacket() const override;
+ size_t Max10MsFramesInAPacket() const override;
+ int GetTargetBitrate() const override;
+
+ void Reset() override;
+ bool SetFec(bool enable) override;
+
+ bool SetDtx(bool enable) override;
+ bool GetDtx() const override;
+
+ bool SetApplication(Application application) override;
+ void SetMaxPlaybackRate(int frequency_hz) override;
+ bool EnableAudioNetworkAdaptor(const std::string& config_string,
+ RtcEventLog* event_log) override;
+ void DisableAudioNetworkAdaptor() override;
+ void OnReceivedUplinkPacketLossFraction(
+ float uplink_packet_loss_fraction) override;
+ void OnReceivedUplinkBandwidth(
+ int target_audio_bitrate_bps,
+ absl::optional<int64_t> bwe_period_ms) override;
+ void OnReceivedUplinkAllocation(BitrateAllocationUpdate update) override;
+ void OnReceivedRtt(int rtt_ms) override;
+ void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
+ void SetReceiverFrameLengthRange(int min_frame_length_ms,
+ int max_frame_length_ms) override;
+ ANAStats GetANAStats() const override;
+ absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
+ const override;
+ rtc::ArrayView<std::unique_ptr<AudioEncoder>> ReclaimContainedEncoders()
+ override;
+
+ protected:
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override;
+
+ private:
+ std::unique_ptr<AudioEncoder> speech_encoder_;
+ rtc::Buffer primary_encoded_;
+ size_t max_packet_length_;
+ int red_payload_type_;
+ std::list<std::pair<EncodedInfo, rtc::Buffer>> redundant_encodings_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_RED_AUDIO_ENCODER_COPY_RED_H_
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc
new file mode 100644
index 0000000000..795a996624
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
+
+#include <memory>
+#include <vector>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "test/field_trial.h"
+#include "test/gtest.h"
+#include "test/mock_audio_encoder.h"
+#include "test/scoped_key_value_config.h"
+#include "test/testsupport/rtc_expect_death.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::MockFunction;
+using ::testing::Not;
+using ::testing::Optional;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+namespace webrtc {
+
+namespace {
+static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo.
+static const size_t kRedLastHeaderLength =
+ 1; // 1 byte RED header for the last element.
+}
+
+class AudioEncoderCopyRedTest : public ::testing::Test {
+ protected:
+ AudioEncoderCopyRedTest()
+ : mock_encoder_(new MockAudioEncoder),
+ timestamp_(4711),
+ sample_rate_hz_(16000),
+ num_audio_samples_10ms(sample_rate_hz_ / 100),
+ red_payload_type_(200) {
+ AudioEncoderCopyRed::Config config;
+ config.payload_type = red_payload_type_;
+ config.speech_encoder = std::unique_ptr<AudioEncoder>(mock_encoder_);
+ red_.reset(new AudioEncoderCopyRed(std::move(config), field_trials_));
+ memset(audio_, 0, sizeof(audio_));
+ EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(1U));
+ EXPECT_CALL(*mock_encoder_, SampleRateHz())
+ .WillRepeatedly(Return(sample_rate_hz_));
+ }
+
+ void TearDown() override { red_.reset(); }
+
+ void Encode() {
+ ASSERT_TRUE(red_.get() != NULL);
+ encoded_.Clear();
+ encoded_info_ = red_->Encode(
+ timestamp_,
+ rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms),
+ &encoded_);
+ timestamp_ += rtc::checked_cast<uint32_t>(num_audio_samples_10ms);
+ }
+
+ test::ScopedKeyValueConfig field_trials_;
+ MockAudioEncoder* mock_encoder_;
+ std::unique_ptr<AudioEncoderCopyRed> red_;
+ uint32_t timestamp_;
+ int16_t audio_[kMaxNumSamples];
+ const int sample_rate_hz_;
+ size_t num_audio_samples_10ms;
+ rtc::Buffer encoded_;
+ AudioEncoder::EncodedInfo encoded_info_;
+ const int red_payload_type_;
+};
+
+TEST_F(AudioEncoderCopyRedTest, CreateAndDestroy) {}
+
+TEST_F(AudioEncoderCopyRedTest, CheckSampleRatePropagation) {
+ EXPECT_CALL(*mock_encoder_, SampleRateHz()).WillOnce(Return(17));
+ EXPECT_EQ(17, red_->SampleRateHz());
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckNumChannelsPropagation) {
+ EXPECT_CALL(*mock_encoder_, NumChannels()).WillOnce(Return(17U));
+ EXPECT_EQ(17U, red_->NumChannels());
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckFrameSizePropagation) {
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillOnce(Return(17U));
+ EXPECT_EQ(17U, red_->Num10MsFramesInNextPacket());
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckMaxFrameSizePropagation) {
+ EXPECT_CALL(*mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(17U));
+ EXPECT_EQ(17U, red_->Max10MsFramesInAPacket());
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckTargetAudioBitratePropagation) {
+ EXPECT_CALL(*mock_encoder_,
+ OnReceivedUplinkBandwidth(4711, absl::optional<int64_t>()));
+ red_->OnReceivedUplinkBandwidth(4711, absl::nullopt);
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckPacketLossFractionPropagation) {
+ EXPECT_CALL(*mock_encoder_, OnReceivedUplinkPacketLossFraction(0.5));
+ red_->OnReceivedUplinkPacketLossFraction(0.5);
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckGetFrameLengthRangePropagation) {
+ auto expected_range =
+ std::make_pair(TimeDelta::Millis(20), TimeDelta::Millis(20));
+ EXPECT_CALL(*mock_encoder_, GetFrameLengthRange())
+ .WillRepeatedly(Return(absl::make_optional(expected_range)));
+ EXPECT_THAT(red_->GetFrameLengthRange(), Optional(Eq(expected_range)));
+}
+
+// Checks that the an Encode() call is immediately propagated to the speech
+// encoder.
+TEST_F(AudioEncoderCopyRedTest, CheckImmediateEncode) {
+ // Interleaving the EXPECT_CALL sequence with expectations on the MockFunction
+ // check ensures that exactly one call to EncodeImpl happens in each
+ // Encode call.
+ InSequence s;
+ MockFunction<void(int check_point_id)> check;
+ for (int i = 1; i <= 6; ++i) {
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillRepeatedly(Return(AudioEncoder::EncodedInfo()));
+ EXPECT_CALL(check, Call(i));
+ Encode();
+ check.Call(i);
+ }
+}
+
+// Checks that no output is produced if the underlying codec doesn't emit any
+// new data, even if the RED codec is loaded with a secondary encoding.
+TEST_F(AudioEncoderCopyRedTest, CheckNoOutput) {
+ static const size_t kEncodedSize = 17;
+ static const size_t kHeaderLenBytes = 5;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(kEncodedSize)))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(0)))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(kEncodedSize)));
+ }
+
+ // Start with one Encode() call that will produce output.
+ Encode();
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ EXPECT_EQ(0u, encoded_info_.redundant.size());
+ EXPECT_EQ(kEncodedSize + kRedLastHeaderLength, encoded_info_.encoded_bytes);
+
+ // Next call to the speech encoder will not produce any output.
+ Encode();
+ EXPECT_EQ(0u, encoded_info_.encoded_bytes);
+
+ // Final call to the speech encoder will produce output.
+ Encode();
+ EXPECT_EQ(2 * kEncodedSize + kHeaderLenBytes, encoded_info_.encoded_bytes);
+ ASSERT_EQ(2u, encoded_info_.redundant.size());
+}
+
+// Checks that the correct payload sizes are populated into the redundancy
+// information for a redundancy level of 1.
+TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes1) {
+ // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence
+ // of calls.
+ static const int kNumPackets = 10;
+ InSequence s;
+ for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) {
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(encode_size)));
+ }
+
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ Encode();
+ EXPECT_EQ(0u, encoded_info_.redundant.size());
+ EXPECT_EQ(kRedLastHeaderLength + 1u, encoded_info_.encoded_bytes);
+
+ for (size_t i = 2; i <= kNumPackets; ++i) {
+ Encode();
+ ASSERT_EQ(2u, encoded_info_.redundant.size());
+ EXPECT_EQ(i, encoded_info_.redundant[1].encoded_bytes);
+ EXPECT_EQ(i - 1, encoded_info_.redundant[0].encoded_bytes);
+ EXPECT_EQ(5 + i + (i - 1), encoded_info_.encoded_bytes);
+ }
+}
+
+// Checks that the correct payload sizes are populated into the redundancy
+// information for a redundancy level of 0.
+TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes0) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ field_trials_, "WebRTC-Audio-Red-For-Opus/Enabled-0/");
+ // Recreate the RED encoder to take the new field trial setting into account.
+ AudioEncoderCopyRed::Config config;
+ config.payload_type = red_payload_type_;
+ config.speech_encoder = std::move(red_->ReclaimContainedEncoders()[0]);
+ red_.reset(new AudioEncoderCopyRed(std::move(config), field_trials));
+
+ // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence
+ // of calls.
+ static const int kNumPackets = 10;
+ InSequence s;
+ for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) {
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(encode_size)));
+ }
+
+ for (size_t i = 1; i <= kNumPackets; ++i) {
+ Encode();
+ ASSERT_EQ(0u, encoded_info_.redundant.size());
+ EXPECT_EQ(1 + i, encoded_info_.encoded_bytes);
+ }
+}
+// Checks that the correct payload sizes are populated into the redundancy
+// information for a redundancy level of 2.
+TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes2) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ field_trials_, "WebRTC-Audio-Red-For-Opus/Enabled-2/");
+ // Recreate the RED encoder to take the new field trial setting into account.
+ AudioEncoderCopyRed::Config config;
+ config.payload_type = red_payload_type_;
+ config.speech_encoder = std::move(red_->ReclaimContainedEncoders()[0]);
+ red_.reset(new AudioEncoderCopyRed(std::move(config), field_trials));
+
+ // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence
+ // of calls.
+ static const int kNumPackets = 10;
+ InSequence s;
+ for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) {
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(encode_size)));
+ }
+
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ Encode();
+ EXPECT_EQ(0u, encoded_info_.redundant.size());
+ EXPECT_EQ(kRedLastHeaderLength + 1u, encoded_info_.encoded_bytes);
+
+ // Second call is also special since it does not include a tertiary
+ // payload.
+ Encode();
+ EXPECT_EQ(2u, encoded_info_.redundant.size());
+ EXPECT_EQ(8u, encoded_info_.encoded_bytes);
+
+ for (size_t i = 3; i <= kNumPackets; ++i) {
+ Encode();
+ ASSERT_EQ(3u, encoded_info_.redundant.size());
+ EXPECT_EQ(i, encoded_info_.redundant[2].encoded_bytes);
+ EXPECT_EQ(i - 1, encoded_info_.redundant[1].encoded_bytes);
+ EXPECT_EQ(i - 2, encoded_info_.redundant[0].encoded_bytes);
+ EXPECT_EQ(9 + i + (i - 1) + (i - 2), encoded_info_.encoded_bytes);
+ }
+}
+
+// Checks that the correct payload sizes are populated into the redundancy
+// information for a redundancy level of 3.
+TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes3) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ field_trials_, "WebRTC-Audio-Red-For-Opus/Enabled-3/");
+ // Recreate the RED encoder to take the new field trial setting into account.
+ AudioEncoderCopyRed::Config config;
+ config.payload_type = red_payload_type_;
+ config.speech_encoder = std::move(red_->ReclaimContainedEncoders()[0]);
+ red_.reset(new AudioEncoderCopyRed(std::move(config), field_trials_));
+
+ // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence
+ // of calls.
+ static const int kNumPackets = 10;
+ InSequence s;
+ for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) {
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(encode_size)));
+ }
+
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ Encode();
+ EXPECT_EQ(0u, encoded_info_.redundant.size());
+ EXPECT_EQ(kRedLastHeaderLength + 1u, encoded_info_.encoded_bytes);
+
+ // Second call is also special since it does not include a tertiary
+ // payload.
+ Encode();
+ EXPECT_EQ(2u, encoded_info_.redundant.size());
+ EXPECT_EQ(8u, encoded_info_.encoded_bytes);
+
+ // Third call is also special since it does not include a quaternary
+ // payload.
+ Encode();
+ EXPECT_EQ(3u, encoded_info_.redundant.size());
+ EXPECT_EQ(15u, encoded_info_.encoded_bytes);
+
+ for (size_t i = 4; i <= kNumPackets; ++i) {
+ Encode();
+ ASSERT_EQ(4u, encoded_info_.redundant.size());
+ EXPECT_EQ(i, encoded_info_.redundant[3].encoded_bytes);
+ EXPECT_EQ(i - 1, encoded_info_.redundant[2].encoded_bytes);
+ EXPECT_EQ(i - 2, encoded_info_.redundant[1].encoded_bytes);
+ EXPECT_EQ(i - 3, encoded_info_.redundant[0].encoded_bytes);
+ EXPECT_EQ(13 + i + (i - 1) + (i - 2) + (i - 3),
+ encoded_info_.encoded_bytes);
+ }
+}
+
+// Checks that the correct timestamps are returned.
+TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) {
+ uint32_t primary_timestamp = timestamp_;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 17;
+ info.encoded_timestamp = timestamp_;
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ Encode();
+ EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp);
+
+ uint32_t secondary_timestamp = primary_timestamp;
+ primary_timestamp = timestamp_;
+ info.encoded_timestamp = timestamp_;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+
+ Encode();
+ ASSERT_EQ(2u, encoded_info_.redundant.size());
+ EXPECT_EQ(primary_timestamp, encoded_info_.redundant[1].encoded_timestamp);
+ EXPECT_EQ(secondary_timestamp, encoded_info_.redundant[0].encoded_timestamp);
+ EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp);
+}
+
+// Checks that the primary and secondary payloads are written correctly.
+TEST_F(AudioEncoderCopyRedTest, CheckPayloads) {
+ // Let the mock encoder write payloads with increasing values. The first
+ // payload will have values 0, 1, 2, ..., kPayloadLenBytes - 1.
+ static const size_t kPayloadLenBytes = 5;
+ static const size_t kHeaderLenBytes = 5;
+ uint8_t payload[kPayloadLenBytes];
+ for (uint8_t i = 0; i < kPayloadLenBytes; ++i) {
+ payload[i] = i;
+ }
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillRepeatedly(Invoke(MockAudioEncoder::CopyEncoding(payload)));
+
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ Encode();
+ EXPECT_EQ(kRedLastHeaderLength + kPayloadLenBytes,
+ encoded_info_.encoded_bytes);
+ for (size_t i = 0; i < kPayloadLenBytes; ++i) {
+ EXPECT_EQ(i, encoded_.data()[kRedLastHeaderLength + i]);
+ }
+
+ for (int j = 0; j < 1; ++j) {
+ // Increment all values of the payload by 10.
+ for (size_t i = 0; i < kPayloadLenBytes; ++i)
+ payload[i] += 10;
+
+ Encode();
+ ASSERT_EQ(2u, encoded_info_.redundant.size());
+ EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[0].encoded_bytes);
+ EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[1].encoded_bytes);
+ for (size_t i = 0; i < kPayloadLenBytes; ++i) {
+ // Check secondary payload.
+ EXPECT_EQ(j * 10 + i, encoded_.data()[kHeaderLenBytes + i]);
+
+ // Check primary payload.
+ EXPECT_EQ((j + 1) * 10 + i,
+ encoded_.data()[kHeaderLenBytes + i + kPayloadLenBytes]);
+ }
+ }
+}
+
+// Checks correct propagation of payload type.
+TEST_F(AudioEncoderCopyRedTest, CheckPayloadType) {
+ const int primary_payload_type = red_payload_type_ + 1;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 17;
+ info.payload_type = primary_payload_type;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+
+ // First call is a special case, since it does not include a secondary
+ // payload.
+ Encode();
+ ASSERT_EQ(0u, encoded_info_.redundant.size());
+
+ const int secondary_payload_type = red_payload_type_ + 2;
+ info.payload_type = secondary_payload_type;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+
+ Encode();
+ ASSERT_EQ(2u, encoded_info_.redundant.size());
+ EXPECT_EQ(secondary_payload_type, encoded_info_.redundant[1].payload_type);
+ EXPECT_EQ(primary_payload_type, encoded_info_.redundant[0].payload_type);
+ EXPECT_EQ(red_payload_type_, encoded_info_.payload_type);
+}
+
+TEST_F(AudioEncoderCopyRedTest, CheckRFC2198Header) {
+ const int primary_payload_type = red_payload_type_ + 1;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 10;
+ info.encoded_timestamp = timestamp_;
+ info.payload_type = primary_payload_type;
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode();
+ info.encoded_timestamp = timestamp_; // update timestamp.
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Second call will produce a redundant encoding.
+
+ EXPECT_EQ(encoded_.size(),
+ 5u + 2 * 10u); // header size + two encoded payloads.
+ EXPECT_EQ(encoded_[0], primary_payload_type | 0x80);
+
+ uint32_t timestamp_delta = encoded_info_.encoded_timestamp -
+ encoded_info_.redundant[0].encoded_timestamp;
+ // Timestamp delta is encoded as a 14 bit value.
+ EXPECT_EQ(encoded_[1], timestamp_delta >> 6);
+ EXPECT_EQ(static_cast<uint8_t>(encoded_[2] >> 2), timestamp_delta & 0x3f);
+ // Redundant length is encoded as 10 bit value.
+ EXPECT_EQ(encoded_[2] & 0x3u, encoded_info_.redundant[1].encoded_bytes >> 8);
+ EXPECT_EQ(encoded_[3], encoded_info_.redundant[1].encoded_bytes & 0xff);
+ EXPECT_EQ(encoded_[4], primary_payload_type);
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Third call will produce a redundant encoding with double
+ // redundancy.
+
+ EXPECT_EQ(encoded_.size(),
+ 5u + 2 * 10u); // header size + two encoded payloads.
+ EXPECT_EQ(encoded_[0], primary_payload_type | 0x80);
+
+ timestamp_delta = encoded_info_.encoded_timestamp -
+ encoded_info_.redundant[0].encoded_timestamp;
+ // Timestamp delta is encoded as a 14 bit value.
+ EXPECT_EQ(encoded_[1], timestamp_delta >> 6);
+ EXPECT_EQ(static_cast<uint8_t>(encoded_[2] >> 2), timestamp_delta & 0x3f);
+ // Redundant length is encoded as 10 bit value.
+ EXPECT_EQ(encoded_[2] & 0x3u, encoded_info_.redundant[1].encoded_bytes >> 8);
+ EXPECT_EQ(encoded_[3], encoded_info_.redundant[1].encoded_bytes & 0xff);
+
+ EXPECT_EQ(encoded_[4], primary_payload_type | 0x80);
+ timestamp_delta = encoded_info_.encoded_timestamp -
+ encoded_info_.redundant[1].encoded_timestamp;
+}
+
+// Variant with a redundancy of 0.
+TEST_F(AudioEncoderCopyRedTest, CheckRFC2198Header0) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ field_trials_, "WebRTC-Audio-Red-For-Opus/Enabled-0/");
+ // Recreate the RED encoder to take the new field trial setting into account.
+ AudioEncoderCopyRed::Config config;
+ config.payload_type = red_payload_type_;
+ config.speech_encoder = std::move(red_->ReclaimContainedEncoders()[0]);
+ red_.reset(new AudioEncoderCopyRed(std::move(config), field_trials));
+
+ const int primary_payload_type = red_payload_type_ + 1;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 10;
+ info.encoded_timestamp = timestamp_;
+ info.payload_type = primary_payload_type;
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode();
+ info.encoded_timestamp = timestamp_; // update timestamp.
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Second call will not produce a redundant encoding.
+
+ EXPECT_EQ(encoded_.size(),
+ 1u + 1 * 10u); // header size + one encoded payloads.
+ EXPECT_EQ(encoded_[0], primary_payload_type);
+}
+// Variant with a redundancy of 2.
+TEST_F(AudioEncoderCopyRedTest, CheckRFC2198Header2) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ field_trials_, "WebRTC-Audio-Red-For-Opus/Enabled-2/");
+ // Recreate the RED encoder to take the new field trial setting into account.
+ AudioEncoderCopyRed::Config config;
+ config.payload_type = red_payload_type_;
+ config.speech_encoder = std::move(red_->ReclaimContainedEncoders()[0]);
+ red_.reset(new AudioEncoderCopyRed(std::move(config), field_trials));
+
+ const int primary_payload_type = red_payload_type_ + 1;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 10;
+ info.encoded_timestamp = timestamp_;
+ info.payload_type = primary_payload_type;
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode();
+ info.encoded_timestamp = timestamp_; // update timestamp.
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Second call will produce a redundant encoding.
+
+ EXPECT_EQ(encoded_.size(),
+ 5u + 2 * 10u); // header size + two encoded payloads.
+ EXPECT_EQ(encoded_[0], primary_payload_type | 0x80);
+
+ uint32_t timestamp_delta = encoded_info_.encoded_timestamp -
+ encoded_info_.redundant[0].encoded_timestamp;
+ // Timestamp delta is encoded as a 14 bit value.
+ EXPECT_EQ(encoded_[1], timestamp_delta >> 6);
+ EXPECT_EQ(static_cast<uint8_t>(encoded_[2] >> 2), timestamp_delta & 0x3f);
+ // Redundant length is encoded as 10 bit value.
+ EXPECT_EQ(encoded_[2] & 0x3u, encoded_info_.redundant[1].encoded_bytes >> 8);
+ EXPECT_EQ(encoded_[3], encoded_info_.redundant[1].encoded_bytes & 0xff);
+ EXPECT_EQ(encoded_[4], primary_payload_type);
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Third call will produce a redundant encoding with double
+ // redundancy.
+
+ EXPECT_EQ(encoded_.size(),
+ 9u + 3 * 10u); // header size + three encoded payloads.
+ EXPECT_EQ(encoded_[0], primary_payload_type | 0x80);
+
+ timestamp_delta = encoded_info_.encoded_timestamp -
+ encoded_info_.redundant[0].encoded_timestamp;
+ // Timestamp delta is encoded as a 14 bit value.
+ EXPECT_EQ(encoded_[1], timestamp_delta >> 6);
+ EXPECT_EQ(static_cast<uint8_t>(encoded_[2] >> 2), timestamp_delta & 0x3f);
+ // Redundant length is encoded as 10 bit value.
+ EXPECT_EQ(encoded_[2] & 0x3u, encoded_info_.redundant[1].encoded_bytes >> 8);
+ EXPECT_EQ(encoded_[3], encoded_info_.redundant[1].encoded_bytes & 0xff);
+
+ EXPECT_EQ(encoded_[4], primary_payload_type | 0x80);
+ timestamp_delta = encoded_info_.encoded_timestamp -
+ encoded_info_.redundant[1].encoded_timestamp;
+ // Timestamp delta is encoded as a 14 bit value.
+ EXPECT_EQ(encoded_[5], timestamp_delta >> 6);
+ EXPECT_EQ(static_cast<uint8_t>(encoded_[6] >> 2), timestamp_delta & 0x3f);
+ // Redundant length is encoded as 10 bit value.
+ EXPECT_EQ(encoded_[6] & 0x3u, encoded_info_.redundant[1].encoded_bytes >> 8);
+ EXPECT_EQ(encoded_[7], encoded_info_.redundant[1].encoded_bytes & 0xff);
+ EXPECT_EQ(encoded_[8], primary_payload_type);
+}
+
+TEST_F(AudioEncoderCopyRedTest, RespectsPayloadMTU) {
+ const int primary_payload_type = red_payload_type_ + 1;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 600;
+ info.encoded_timestamp = timestamp_;
+ info.payload_type = primary_payload_type;
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode();
+ info.encoded_timestamp = timestamp_; // update timestamp.
+ info.encoded_bytes = 500;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Second call will produce a redundant encoding.
+
+ EXPECT_EQ(encoded_.size(), 5u + 600u + 500u);
+
+ info.encoded_timestamp = timestamp_; // update timestamp.
+ info.encoded_bytes = 400;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode(); // Third call will drop the oldest packet.
+ EXPECT_EQ(encoded_.size(), 5u + 500u + 400u);
+}
+
+TEST_F(AudioEncoderCopyRedTest, LargeTimestampGap) {
+ const int primary_payload_type = red_payload_type_ + 1;
+ AudioEncoder::EncodedInfo info;
+ info.encoded_bytes = 100;
+ info.encoded_timestamp = timestamp_;
+ info.payload_type = primary_payload_type;
+
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode();
+ // Update timestamp to simulate a 400ms gap like the one
+ // opus DTX causes.
+ timestamp_ += 19200;
+ info.encoded_timestamp = timestamp_; // update timestamp.
+ info.encoded_bytes = 200;
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
+ Encode();
+
+ // The old packet will be dropped.
+ EXPECT_EQ(encoded_.size(), 1u + 200u);
+}
+
+#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+// This test fixture tests various error conditions that makes the
+// AudioEncoderCng die via CHECKs.
+class AudioEncoderCopyRedDeathTest : public AudioEncoderCopyRedTest {
+ protected:
+ AudioEncoderCopyRedDeathTest() : AudioEncoderCopyRedTest() {}
+};
+
+TEST_F(AudioEncoderCopyRedDeathTest, WrongFrameSize) {
+ num_audio_samples_10ms *= 2; // 20 ms frame.
+ RTC_EXPECT_DEATH(Encode(), "");
+ num_audio_samples_10ms = 0; // Zero samples.
+ RTC_EXPECT_DEATH(Encode(), "");
+}
+
+TEST_F(AudioEncoderCopyRedDeathTest, NullSpeechEncoder) {
+ test::ScopedKeyValueConfig field_trials;
+ AudioEncoderCopyRed* red = NULL;
+ AudioEncoderCopyRed::Config config;
+ config.speech_encoder = NULL;
+ RTC_EXPECT_DEATH(
+ red = new AudioEncoderCopyRed(std::move(config), field_trials),
+ "Speech encoder not provided.");
+ // The delete operation is needed to avoid leak reports from memcheck.
+ delete red;
+}
+
+#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc b/third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
new file mode 100644
index 0000000000..537e6fcede
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
+
+#include "rtc_base/checks.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
+
+using ::std::get;
+
+namespace webrtc {
+
+AudioCodecSpeedTest::AudioCodecSpeedTest(int block_duration_ms,
+ int input_sampling_khz,
+ int output_sampling_khz)
+ : block_duration_ms_(block_duration_ms),
+ input_sampling_khz_(input_sampling_khz),
+ output_sampling_khz_(output_sampling_khz),
+ input_length_sample_(
+ static_cast<size_t>(block_duration_ms_ * input_sampling_khz_)),
+ output_length_sample_(
+ static_cast<size_t>(block_duration_ms_ * output_sampling_khz_)),
+ data_pointer_(0),
+ loop_length_samples_(0),
+ max_bytes_(0),
+ encoded_bytes_(0),
+ encoding_time_ms_(0.0),
+ decoding_time_ms_(0.0),
+ out_file_(NULL) {}
+
+void AudioCodecSpeedTest::SetUp() {
+ channels_ = get<0>(GetParam());
+ bit_rate_ = get<1>(GetParam());
+ in_filename_ = test::ResourcePath(get<2>(GetParam()), get<3>(GetParam()));
+ save_out_data_ = get<4>(GetParam());
+
+ FILE* fp = fopen(in_filename_.c_str(), "rb");
+ RTC_DCHECK(fp);
+
+ // Obtain file size.
+ fseek(fp, 0, SEEK_END);
+ loop_length_samples_ = ftell(fp) / sizeof(int16_t);
+ rewind(fp);
+
+ // Allocate memory to contain the whole file.
+ in_data_.reset(
+ new int16_t[loop_length_samples_ + input_length_sample_ * channels_]);
+
+ data_pointer_ = 0;
+
+ // Copy the file into the buffer.
+ ASSERT_EQ(fread(&in_data_[0], sizeof(int16_t), loop_length_samples_, fp),
+ loop_length_samples_);
+ fclose(fp);
+
+ // Add an extra block length of samples to the end of the array, starting
+ // over again from the beginning of the array. This is done to simplify
+ // the reading process when reading over the end of the loop.
+ memcpy(&in_data_[loop_length_samples_], &in_data_[0],
+ input_length_sample_ * channels_ * sizeof(int16_t));
+
+ max_bytes_ = input_length_sample_ * channels_ * sizeof(int16_t);
+ out_data_.reset(new int16_t[output_length_sample_ * channels_]);
+ bit_stream_.reset(new uint8_t[max_bytes_]);
+
+ if (save_out_data_) {
+ std::string out_filename =
+ ::testing::UnitTest::GetInstance()->current_test_info()->name();
+
+ // Erase '/'
+ size_t found;
+ while ((found = out_filename.find('/')) != std::string::npos)
+ out_filename.replace(found, 1, "_");
+
+ out_filename = test::OutputPath() + out_filename + ".pcm";
+
+ out_file_ = fopen(out_filename.c_str(), "wb");
+ RTC_DCHECK(out_file_);
+
+ printf("Output to be saved in %s.\n", out_filename.c_str());
+ }
+}
+
+void AudioCodecSpeedTest::TearDown() {
+ if (save_out_data_) {
+ fclose(out_file_);
+ }
+}
+
+void AudioCodecSpeedTest::EncodeDecode(size_t audio_duration_sec) {
+ size_t time_now_ms = 0;
+ float time_ms;
+
+ printf("Coding %d kHz-sampled %zu-channel audio at %d bps ...\n",
+ input_sampling_khz_, channels_, bit_rate_);
+
+ while (time_now_ms < audio_duration_sec * 1000) {
+ // Encode & decode.
+ time_ms = EncodeABlock(&in_data_[data_pointer_], &bit_stream_[0],
+ max_bytes_, &encoded_bytes_);
+ encoding_time_ms_ += time_ms;
+ time_ms = DecodeABlock(&bit_stream_[0], encoded_bytes_, &out_data_[0]);
+ decoding_time_ms_ += time_ms;
+ if (save_out_data_) {
+ fwrite(&out_data_[0], sizeof(int16_t), output_length_sample_ * channels_,
+ out_file_);
+ }
+ data_pointer_ = (data_pointer_ + input_length_sample_ * channels_) %
+ loop_length_samples_;
+ time_now_ms += block_duration_ms_;
+ }
+
+ printf("Encoding: %.2f%% real time,\nDecoding: %.2f%% real time.\n",
+ (encoding_time_ms_ / audio_duration_sec) / 10.0,
+ (decoding_time_ms_ / audio_duration_sec) / 10.0);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h b/third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
new file mode 100644
index 0000000000..c5f1d7c259
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_CODECS_TOOLS_AUDIO_CODEC_SPEED_TEST_H_
+#define MODULES_AUDIO_CODING_CODECS_TOOLS_AUDIO_CODEC_SPEED_TEST_H_
+
+#include <memory>
+#include <string>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+
+// Define coding parameter as
+// <channels, bit_rate, file_name, extension, if_save_output>.
+typedef std::tuple<size_t, int, std::string, std::string, bool> coding_param;
+
+class AudioCodecSpeedTest : public ::testing::TestWithParam<coding_param> {
+ protected:
+ AudioCodecSpeedTest(int block_duration_ms,
+ int input_sampling_khz,
+ int output_sampling_khz);
+ virtual void SetUp();
+ virtual void TearDown();
+
+ // EncodeABlock(...) does the following:
+ // 1. encodes a block of audio, saved in `in_data`,
+ // 2. save the bit stream to `bit_stream` of `max_bytes` bytes in size,
+ // 3. assign `encoded_bytes` with the length of the bit stream (in bytes),
+ // 4. return the cost of time (in millisecond) spent on actual encoding.
+ virtual float EncodeABlock(int16_t* in_data,
+ uint8_t* bit_stream,
+ size_t max_bytes,
+ size_t* encoded_bytes) = 0;
+
+ // DecodeABlock(...) does the following:
+ // 1. decodes the bit stream in `bit_stream` with a length of `encoded_bytes`
+ // (in bytes),
+ // 2. save the decoded audio in `out_data`,
+ // 3. return the cost of time (in millisecond) spent on actual decoding.
+ virtual float DecodeABlock(const uint8_t* bit_stream,
+ size_t encoded_bytes,
+ int16_t* out_data) = 0;
+
+ // Encoding and decode an audio of `audio_duration` (in seconds) and
+ // record the runtime for encoding and decoding separately.
+ void EncodeDecode(size_t audio_duration);
+
+ int block_duration_ms_;
+ int input_sampling_khz_;
+ int output_sampling_khz_;
+
+ // Number of samples-per-channel in a frame.
+ size_t input_length_sample_;
+
+ // Expected output number of samples-per-channel in a frame.
+ size_t output_length_sample_;
+
+ std::unique_ptr<int16_t[]> in_data_;
+ std::unique_ptr<int16_t[]> out_data_;
+ size_t data_pointer_;
+ size_t loop_length_samples_;
+ std::unique_ptr<uint8_t[]> bit_stream_;
+
+ // Maximum number of bytes in output bitstream for a frame of audio.
+ size_t max_bytes_;
+
+ size_t encoded_bytes_;
+ float encoding_time_ms_;
+ float decoding_time_ms_;
+ FILE* out_file_;
+
+ size_t channels_;
+
+ // Bit rate is in bit-per-second.
+ int bit_rate_;
+
+ std::string in_filename_;
+
+ // Determines whether to save the output to file.
+ bool save_out_data_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_CODING_CODECS_TOOLS_AUDIO_CODEC_SPEED_TEST_H_