unplugged-vendor/system/bt/embdrv/lc3/Decoder/MPVQ.cpp

180 lines
5.8 KiB
C++

/*
* MPVQ.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 "MPVQ.hpp"
#include <cstdbool>
#include "SnsQuantizationTables.hpp"
namespace Lc3Dec
{
// declare local helper functions
void mind2vec_tab ( short dim_in, /* i: dimension */
short k_max_local, /* i: nb unit pulses */
short leading_sign, /* i: leading sign */
unsigned int ind, /* i: MPVQ-index */
short *vec_out, /* o: pulse train */
unsigned int MPVQ_offsets [][11] /* i: offset matrix */
);
void mind2vec_one( short k_val_in, /* i: nb unit pulses */
short leading_sign, /* i: leading sign -1, 1 */
short *vec_out /* o: updated pulse train */
);
short setval_update_sign (
short k_delta, /* i */
short k_max_local_in, /* i */
short *leading_sign, /* i/o */
unsigned int *ind_in, /* i/o */
short *vec_out /* i/o */
);
short get_lead_sign(unsigned int *ind_in );
//
// Implementation
//
void MPVQdeenum(uint8_t dim_in, /* i : dimension of vec_out */
uint8_t k_val_in, /* i : number of unit pulses */
int16_t LS_ind, /* i : leading sign index */
int32_t MPVQ_ind, /* i : MPVQ shape index */
int16_t *vec_out /* o : PVQ integer pulse train */
)
{
for (uint8_t i=0; i < dim_in; i++)
{
vec_out[i] = 0;
}
short leading_sign = 1;
if ( LS_ind != 0 ){
leading_sign = -1;
}
mind2vec_tab ( dim_in,
k_val_in,
leading_sign,
MPVQ_ind,
vec_out,
MPVQ_offsets );
}
void mind2vec_tab ( short dim_in, /* i: dimension */
short k_max_local, /* i: nb unit pulses */
short leading_sign, /* i: leading sign */
unsigned int ind, /* i: MPVQ-index */
short *vec_out, /* o: pulse train */
unsigned int MPVQ_offsets [][11] /* i: offset matrix */
)
{
/* init */
unsigned int* h_row_ptr = &(MPVQ_offsets[(dim_in-1)][0]);
short k_acc = k_max_local;
/* loop over positions */
for (uint8_t pos = 0; pos < dim_in; pos++)
{
short k_delta;
if (ind != 0)
{
k_acc = k_max_local;;
unsigned int UL_tmp_offset = h_row_ptr[k_acc];
bool wrap_flag = (ind < UL_tmp_offset ) ;
unsigned int UL_diff=0;
if (!wrap_flag)
{
// Note: due to android build using a integer-overflow sanitizer, we have to avoid
// computing the following difference when ind < UL_tmp_offset
UL_diff = ind - UL_tmp_offset;
}
while (wrap_flag)
{
k_acc--;
wrap_flag = (ind < h_row_ptr[k_acc]);
if (!wrap_flag)
{
// Note: due to android build using a integer-overflow sanitizer, we have to avoid
// computing the following difference when ind < UL_tmp_offset
UL_diff = ind - h_row_ptr[k_acc];
}
}
ind = UL_diff;
k_delta = k_max_local - k_acc;
}
else
{
mind2vec_one(k_max_local, leading_sign, &vec_out[pos]);
break;
}
k_max_local = setval_update_sign(
k_delta,
k_max_local,
&leading_sign,
&ind,
&vec_out[pos]);
h_row_ptr -= 11; /* reduce dimension in MPVQ_offsets table */
}
}
void mind2vec_one( short k_val_in, /* i: nb unit pulses */
short leading_sign, /* i: leading sign -1, 1 */
short *vec_out /* o: updated pulse train */
)
{
short amp = k_val_in;
if ( leading_sign < 0 )
{
amp = -k_val_in ;
}
*vec_out = amp;
}
short setval_update_sign (
short k_delta, /* i */
short k_max_local_in, /* i */
short *leading_sign, /* i/o */
unsigned int *ind_in, /* i/o; needed to change type compared to spec */
short *vec_out /* i/o */
)
{
short k_max_local_out = k_max_local_in;
if (k_delta != 0)
{
mind2vec_one(k_delta, *leading_sign, vec_out);
*leading_sign = get_lead_sign( ind_in );
k_max_local_out -= k_delta ;
}
return k_max_local_out;
}
short get_lead_sign(unsigned int *ind ) // renamed "ind_in" from spec to just "ind" (as already found by yao.wang 28.06.2019)
{
short leading_sign = +1;
if ( ((*ind)&0x1 ) != 0 )
{
leading_sign = -1;
}
(*ind) = (*ind >> 1);
return leading_sign;
}
}//namespace Lc3Dec