/* * BandwidthDetector.cpp * * Copyright 2019 HIMSA II K/S - www.himsa.dk. Represented by EHIMA - www.ehima.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "BandwidthDetector.hpp" #include namespace Lc3Enc { static const uint8_t I_bw_start_table[5][4] = { {53, 0, 0, 0}, // N_bw=1 {47, 59, 0, 0}, // N_bw=2 {44, 54, 60, 0}, // N_bw=3 {41, 51, 57, 61} // N_bw=4 }; static const uint8_t I_bw_stop_table[5][4] = { {63, 0, 0, 0}, // N_bw=1 {56, 63, 0, 0}, // N_bw=2 {52, 59, 63, 0}, // N_bw=3 {49, 55, 60, 63} // N_bw=4 }; static const uint8_t I_bw_start_table_7p5ms[5][4] = { {51, 0, 0, 0}, // N_bw=1 {45, 58, 0, 0}, // N_bw=2 {42, 53, 60, 0}, // N_bw=3 {40, 51, 57, 61} // N_bw=4 }; static const uint8_t I_bw_stop_table_7p5ms[5][4] = { {63, 0, 0, 0}, // N_bw=1 {55, 63, 0, 0}, // N_bw=2 {51, 58, 63, 0}, // N_bw=3 {48, 55, 60, 63} // N_bw=4 }; static const uint8_t nbits_bw_table[5] = {0, 1, 2, 2, 3}; // see 3.4.2.4 Bandwidth interpretation (d09r02_F2F) static const uint8_t T_Q[4] = {20, 10, 10, 10}; static const uint8_t T_C[4] = {15, 23, 20, 20}; static const uint8_t L_10ms[4] = {4, 4, 3, 1}; static const uint8_t L_7p5ms[4] = {4, 4, 3, 2}; BandwidthDetector::BandwidthDetector(const Lc3Config& lc3Config_) : lc3Config(lc3Config_), N_bw(calc_N_bw(lc3Config.Fs_ind)), nbits_bw(nbits_bw_table[calc_N_bw(lc3Config.Fs_ind)]), P_bw(0), I_bw_start( (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? I_bw_start_table[N_bw-1] : I_bw_start_table_7p5ms[N_bw-1] ), I_bw_stop( (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? I_bw_stop_table[N_bw-1] : I_bw_stop_table_7p5ms[N_bw-1] ), L( (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? L_10ms : L_7p5ms ) { } BandwidthDetector::~BandwidthDetector() { } uint8_t BandwidthDetector::calc_N_bw(uint8_t fs_ind) { // see Table 3.5: Parameter table bandwidth detector // 3.3.5.2 Parameters (d09r02_F2F) return fs_ind; } void BandwidthDetector::run(const double* const E_B) { if (0 == N_bw) { return; } // 3.3.5.1 Algorithm (first stage) (d09r02_F2F) // Note: it seems like there is no need to compute // the entire specified sequence of flahs F_Q[k] // when we start searching for an active band // from the highest fequency band to lower bands uint8_t bw_0 = 0; for (uint8_t k=N_bw-1; k < N_bw; k--) // stops when 0-- goes to 255 { uint8_t width = I_bw_stop[k] - I_bw_start[k] +1; double Q = 0.0; for (uint8_t n = I_bw_start[k]; n <= I_bw_stop[k]; n++) { Q += E_B[n] / width; } if ( Q >= T_Q[k] ) { // activity detected (not quiet) -> this is the band index to be selected bw_0 = k+1; break; } } // 3.3.5.1 Algorithm (second stage) (d09r02_F2F) if (N_bw == bw_0) { P_bw = bw_0; } else { double Cmax=0; for (uint8_t n = I_bw_start[bw_0]-L[bw_0]+1; n <= I_bw_start[bw_0]+1; n++) { double C = 10*log10( E_B[n-L[bw_0]] / E_B[n] ); if (C > Cmax) { Cmax = C; } } if (Cmax > T_C[bw_0]) { P_bw = bw_0; } else { P_bw = N_bw; } } } void BandwidthDetector::registerDatapoints(DatapointContainer* datapoints) { if (nullptr != datapoints) { datapoints->addDatapoint( "P_bw", &P_bw, sizeof(P_bw) ); } } }//namespace Lc3Enc