/* GMR-1 AMBE vocoder - Speech parameters to/from frame */ /* (C) 2011-2019 by Sylvain Munaut * 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 . */ /*! \addtogroup codec_private * @{ */ /*! \file codec/frame.c * \brief Osmocom GMR-1 AMBE speech parameters to/from frame */ #include #include #include #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<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_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; iMlog, sf->L, sf_prev->Mlog, sf_prev->L); for (i=0; iL; 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; jLb[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; iL; 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; iL; 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; iL; 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; } } /*! @} */