150 lines
4.2 KiB
C++
150 lines
4.2 KiB
C++
/*
|
|
* 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 <cmath>
|
|
|
|
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
|