osmo-gmr/src/codec/frame.c

376 lines
10 KiB
C

/* GMR-1 AMBE vocoder - Speech parameters to/from frame */
/* (C) 2011-2019 by Sylvain Munaut <tnt@246tNt.com>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*! \addtogroup codec_private
* @{
*/
/*! \file codec/frame.c
* \brief Osmocom GMR-1 AMBE speech parameters to/from frame
*/
#include <math.h>
#include <stdint.h>
#include <string.h>
#include "private.h"
/*! \brief Grab the requested bits from a frame and shift them up as requested
* \param[in] frame Frame data bytes
* \param[in] p Position of the first bit to grab
* \param[in] l Number of bits to grab (max 8)
* \param[in] s How many bits to shift the result up
* \returns The selected bits as a uint8_t
*/
static inline uint8_t
_get_bits(const uint8_t *frame, int p, int l, int s)
{
uint8_t v;
if ((p & 7) + l > 8) {
v = ((frame[p>>3] << 8) | frame[(p>>3)+1]) >> (16 - (p&7) - l);
} else {
v = frame[p>>3] >> (8 - (p&7) - l);
}
return (v & ((1<<l)-1)) << s;
}
/*! \brief Unpack a frame into its raw encoded parameters
* \param[out] rp Encoded frame raw parameters to unpack into
* \param[in] frame Frame data (10 bytes = 80 bits)
*/
void
ambe_frame_unpack_raw(struct ambe_raw_params *rp, const uint8_t *frame)
{
const uint8_t *p = frame;
rp->pitch = _get_bits(p, 0, 7, 0);
rp->pitch_interp = _get_bits(p, 48, 2, 0);
rp->gain = _get_bits(p, 7, 6, 2) | _get_bits(p, 50, 2, 0);
rp->v_uv = _get_bits(p, 13, 6, 0);
rp->sf1_prba12 = _get_bits(p, 19, 6, 1) | _get_bits(p, 52, 1, 0);
rp->sf1_prba34 = _get_bits(p, 25, 3, 3) | _get_bits(p, 53, 3, 0);
rp->sf1_prba57 = _get_bits(p, 28, 3, 4) | _get_bits(p, 56, 4, 0);
rp->sf1_hoc[0] = _get_bits(p, 31, 3, 4) | _get_bits(p, 60, 4, 0);
rp->sf1_hoc[1] = _get_bits(p, 34, 3, 3) | _get_bits(p, 64, 3, 0);
rp->sf1_hoc[2] = _get_bits(p, 37, 2, 4) | _get_bits(p, 67, 4, 0);
rp->sf1_hoc[3] = _get_bits(p, 39, 2, 3) | _get_bits(p, 71, 3, 0);
rp->sf0_mag_interp = _get_bits(p, 46, 2, 0);
rp->sf0_perr_14 = _get_bits(p, 41, 3, 3) | _get_bits(p, 74, 3, 0);
rp->sf0_perr_58 = _get_bits(p, 44, 2, 3) | _get_bits(p, 77, 3, 0);
}
/*! \brief Interpolates fundamental between subframes
* \param[in] f0log_prev log(fund(-1)) Previous subframe log freq
* \param[in] f0log_cur log(fund(0)) Current subframe log freq
* \param[in] rule Which interpolation rule to apply
* \returns The interpolated log(fund) frequency
*/
static float
ambe_interpolate_f0log(float f0log_prev, float f0log_cur, int rule)
{
if (f0log_cur != f0log_prev) {
switch (rule) {
case 0:
return f0log_cur;
case 1:
return (0.65f * f0log_cur)
+ (0.35f * f0log_prev);
case 2:
return (f0log_cur + f0log_prev) / 2.0f;
case 3:
return f0log_prev;
}
} else {
float step = 4.2672e-2f;
switch (rule) {
case 0:
case 1:
return f0log_cur;
case 2:
return f0log_cur + step;
case 3:
return f0log_cur - step;
}
}
return 0.0f; /* Not reached */
}
/*! \brief Computes and fill-in L and Lb vaues for a given subframe (from f0)
* \param[in] sf Subframe
*/
static void
ambe_subframe_compute_L_Lb(struct ambe_subframe *sf)
{
sf->L = (int)floorf(0.4751f / sf->f0);
if (sf->L < 9)
sf->L = 9;
else if (sf->L > 56)
sf->L = 56;
sf->Lb[0] = ambe_hpg_tbl[sf->L - 9][0];
sf->Lb[1] = ambe_hpg_tbl[sf->L - 9][1];
sf->Lb[2] = ambe_hpg_tbl[sf->L - 9][2];
sf->Lb[3] = ambe_hpg_tbl[sf->L - 9][3];
}
/*! \brief Resample and "ac-couple" (remove mean) a magnitude array to a new L
* \param[in] mag_dst Destination magnitude array (L_dst elements)
* \param[in] L_dst Target number of magnitudes
* \param[in] mag_src Source magnitude array (L_src elements)
* \param[in] L_src Source number of magnitudes
*/
static void
ambe_resample_mag(float *mag_dst, int L_dst, float *mag_src, int L_src)
{
float avg, step, pos;
int i;
avg = 0.0f;
step = (float)L_src / (float)L_dst;
pos = step;
for (i=0; i<L_dst; i++)
{
int posi = (int)floorf(pos);
if (posi == 0) {
mag_dst[i] = mag_src[0];
} else if (posi >= L_src) {
mag_dst[i] = mag_src[L_src-1];
} else {
float alpha = pos - posi;
mag_dst[i] = mag_src[posi-1] * (1.0f - alpha)
+ mag_src[posi] * alpha;
}
avg += mag_dst[i];
pos += step;
}
avg /= L_dst;
for (i=0; i<L_dst; i++)
mag_dst[i] -= avg;
}
/*! \brief Compute the spectral magnitudes of subframe 1 from raw params
* \param[inout] sf Current subframe1 data
* \param[in] sf_prev Previous subframe1 data
* \param[in] rp Encoded frame raw parameters
*/
static void
ambe_subframe1_compute_mag(struct ambe_subframe *sf,
struct ambe_subframe *sf_prev,
struct ambe_raw_params *rp)
{
int i, j, k;
/* Prediction */
ambe_resample_mag(sf->Mlog, sf->L, sf_prev->Mlog, sf_prev->L);
for (i=0; i<sf->L; i++)
sf->Mlog[i] *= 0.65f;
/* PRBA */
float prba[8];
float Ri[8];
prba[0] = 0.0f;
prba[1] = ambe_prba12_tbl[rp->sf1_prba12][0];
prba[2] = ambe_prba12_tbl[rp->sf1_prba12][1];
prba[3] = ambe_prba34_tbl[rp->sf1_prba34][0];
prba[4] = ambe_prba34_tbl[rp->sf1_prba34][1];
prba[5] = ambe_prba57_tbl[rp->sf1_prba57][0];
prba[6] = ambe_prba57_tbl[rp->sf1_prba57][1];
prba[7] = ambe_prba57_tbl[rp->sf1_prba57][2];
ambe_idct(Ri, prba, 8, 8);
/* Process each block */
float rconst = (1.0f / (2.0f * (float)M_SQRT2));
float sum = 0.0f;
k = 0;
for (i=0; i<4; i++) {
const float *hoc_tbl[] = {
ambe_hoc0_tbl[rp->sf1_hoc[0]],
ambe_hoc1_tbl[rp->sf1_hoc[1]],
ambe_hoc2_tbl[rp->sf1_hoc[2]],
ambe_hoc3_tbl[rp->sf1_hoc[3]],
};
float C[6], c[17];
/* From PRBA through 2x2 xform */
C[0] = (Ri[i<<1] + Ri[(i<<1)+1]) * 0.5f;
C[1] = (Ri[i<<1] - Ri[(i<<1)+1]) * rconst;
/* HOC */
C[2] = hoc_tbl[i][0];
C[3] = hoc_tbl[i][1];
C[4] = hoc_tbl[i][2];
C[5] = hoc_tbl[i][3];
/* De-DCT */
ambe_idct(c, C, sf->Lb[i], 6);
/* Set magnitudes */
for (j=0; j<sf->Lb[i]; j++)
sf->Mlog[k++] += c[j];
sum += C[0] * sf->Lb[i];
}
/* Adjust to final gain value */
float ofs = sf->gain - (0.5f * log2f(sf->L)) - (sum / sf->L);
for (i=0; i<sf->L; i++)
sf->Mlog[i] += ofs;
}
/*! \brief Compute the spectral magnitudes of subframe 0 from raw params & sf1
* \param[inout] sf Current subframe0 data
* \param[in] sf1_prev Previous subframe 1 data
* \param[in] sf1_cur Current subframe 1 data
* \param[in] rp Encoded frame raw parameters
*/
static void
ambe_subframe0_compute_mag(struct ambe_subframe *sf,
struct ambe_subframe *sf1_prev,
struct ambe_subframe *sf1_cur,
struct ambe_raw_params *rp)
{
float mag_p[56], mag_c[56], alpha;
float perr[9], corr[56];
float gain;
int i;
/* Base for interpolation */
ambe_resample_mag(mag_p, sf->L, sf1_prev->Mlog, sf1_prev->L);
ambe_resample_mag(mag_c, sf->L, sf1_cur->Mlog, sf1_cur->L );
/* Interpolate / Prediction coefficient */
alpha = ambe_sf0_interp_tbl[rp->sf0_mag_interp];
/* Correction */
perr[0] = 0.0f;
perr[1] = ambe_sf0_perr14_tbl[rp->sf0_perr_14][0];
perr[2] = ambe_sf0_perr14_tbl[rp->sf0_perr_14][1];
perr[3] = ambe_sf0_perr14_tbl[rp->sf0_perr_14][2];
perr[4] = ambe_sf0_perr14_tbl[rp->sf0_perr_14][3];
perr[5] = ambe_sf0_perr58_tbl[rp->sf0_perr_58][0];
perr[6] = ambe_sf0_perr58_tbl[rp->sf0_perr_58][1];
perr[7] = ambe_sf0_perr58_tbl[rp->sf0_perr_58][2];
perr[8] = ambe_sf0_perr58_tbl[rp->sf0_perr_58][3];
ambe_idct(corr, perr, sf->L, 9);
/* Target gain value */
gain = sf->gain - (0.5f * log2f(sf->L));
/* Build final value */
for (i=0; i<sf->L; i++)
sf->Mlog[i] = gain + corr[i] + (alpha * mag_p[i]) + ((1.0f - alpha) * mag_c[i]);
}
/*! \brief Decodes the speech parameters for both subframes from raw params
* \param[out] sf Array of 2 subframes data to fill-in
* \param[in] sf_prev Previous subframe 1 data
* \param[in] rp Encoded frame raw parameters
*/
void
ambe_frame_decode_params(struct ambe_subframe *sf,
struct ambe_subframe *sf_prev,
struct ambe_raw_params *rp)
{
uint16_t v_uv;
int i;
/* Fundamental */
sf[1].f0log = -4.312f - 2.1336e-2f * (rp->pitch /* + 0.5 */);
sf[1].f0 = powf(2.0f, sf[1].f0log);
sf[0].f0log = ambe_interpolate_f0log(sf_prev->f0log, sf[1].f0log,
rp->pitch_interp);
sf[0].f0 = powf(2.0f, sf[0].f0log);
/* Harmonics count (total and per-block) */
ambe_subframe_compute_L_Lb(&sf[0]);
ambe_subframe_compute_L_Lb(&sf[1]);
/* Voicing decision */
v_uv = ambe_v_uv_tbl[rp->v_uv];
for (i=0; i<8; i++) {
sf[0].v_uv[i] = (v_uv >> ( 7-i)) & 1;
sf[1].v_uv[i] = (v_uv >> (15-i)) & 1;
}
/* Gain */
sf[0].gain = (0.5f * sf_prev->gain) + ambe_gain_tbl[rp->gain][0];
sf[1].gain = (0.5f * sf_prev->gain) + ambe_gain_tbl[rp->gain][1];
if (sf[0].gain > 13.0f)
sf[0].gain = 13.0f;
if (sf[1].gain > 13.0f)
sf[1].gain = 13.0f;
/* Subframe 1 spectral magnitudes */
ambe_subframe1_compute_mag(&sf[1], sf_prev, rp);
/* Subframe 0 spectral magnitudes */
ambe_subframe0_compute_mag(&sf[0], sf_prev, &sf[1], rp);
}
/*! \brief Expands the decoded subframe params to prepare for synthesis
* \param[in] sf The subframe to expand
*/
void
ambe_subframe_expand(struct ambe_subframe *sf)
{
float unvc;
int i;
sf->w0 = sf->f0 * (2.0f * M_PIf);
unvc = 0.2046f / sqrtf(sf->w0); /* ??? */
for (i=0; i<sf->L; i++) {
int j = (int)(i * 16.0f * sf->f0);
sf->Vl[i] = sf->v_uv[j];
sf->Ml[i] = powf(2.0, sf->Mlog[i]) / 6.0f;
if (!sf->Vl[i])
sf->Ml[i] *= unvc;
}
}
/*! @} */