codec: Documentation

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2013-12-17 18:14:43 +01:00
parent df95ae699f
commit 074f93ad74
7 changed files with 116 additions and 39 deletions

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*! \addtogroup codec/private /*! \addtogroup codec_private
* @{ * @{
*/ */
@ -33,6 +33,9 @@
#include "private.h" #include "private.h"
/*! \brief Initializes decoder state
* \param[in] dec Decoder state structure
*/
void void
ambe_decode_init(struct ambe_decoder *dec) ambe_decode_init(struct ambe_decoder *dec)
{ {
@ -40,6 +43,9 @@ ambe_decode_init(struct ambe_decoder *dec)
mbe_initMbeParms(&dec->mp_prev); mbe_initMbeParms(&dec->mp_prev);
} }
/*! \brief Release all resources associated with a decoder
* \param[in] dec Decoder state structure
*/
void void
ambe_decode_fini(struct ambe_decoder *dec) ambe_decode_fini(struct ambe_decoder *dec)
{ {
@ -47,6 +53,10 @@ ambe_decode_fini(struct ambe_decoder *dec)
} }
/*! \brief Identify the type of frame
* \param[in] frame Frame data (10 bytes = 80 bits)
* \returns See \ref ambe_frame_type for possible return values
*/
static enum ambe_frame_type static enum ambe_frame_type
ambe_classify_frame(const uint8_t *frame) ambe_classify_frame(const uint8_t *frame)
{ {
@ -62,6 +72,10 @@ ambe_classify_frame(const uint8_t *frame)
}; };
} }
/*! \brief Converts an internal \ref ambe_subframe to a mbelib's \ref mbe_parameters
* \param[out] mp mbelib's parameters structure to fill in
* \param[in] sf Internal suframe data
*/
static void static void
ambe_subframe_to_mbelib(mbe_parms *mp, struct ambe_subframe *sf) ambe_subframe_to_mbelib(mbe_parms *mp, struct ambe_subframe *sf)
{ {
@ -82,6 +96,14 @@ ambe_subframe_to_mbelib(mbe_parms *mp, struct ambe_subframe *sf)
} }
} }
/*! \brief Decodes an AMBE speech frame to audio
* \param[in] dec Decoder state structure
* \param[out] audio Output audio buffer
* \param[in] N number of audio samples to produce (152..168)
* \param[in] frame Frame data (10 bytes = 80 bits)
* \param[in] bad Bad Frame Indicator. Set to 1 if frame is corrupt
* \returns 0 for success. Negative error code otherwise.
*/
static int static int
ambe_decode_speech(struct ambe_decoder *dec, ambe_decode_speech(struct ambe_decoder *dec,
int16_t *audio, int N, int16_t *audio, int N,
@ -117,6 +139,14 @@ ambe_decode_speech(struct ambe_decoder *dec,
return 0; return 0;
} }
/*! \brief Decodes an AMBE frame to audio
* \param[in] dec Decoder state structure
* \param[out] audio Output audio buffer
* \param[in] N number of audio samples to produce (152..168)
* \param[in] frame Frame data (10 bytes = 80 bits)
* \param[in] bad Bad Frame Indicator. Set to 1 if frame is corrupt
* \returns 0 for success. Negative error code otherwise.
*/
int int
ambe_decode_frame(struct ambe_decoder *dec, ambe_decode_frame(struct ambe_decoder *dec,
int16_t *audio, int N, int16_t *audio, int N,
@ -138,6 +168,11 @@ ambe_decode_frame(struct ambe_decoder *dec,
return -EINVAL; return -EINVAL;
} }
/*! \brief Generates audio for DTX period
* \param[in] dec Decoder state structure
* \param[out] audio Output audio buffer
* \param[in] N number of audio samples to produce (152..168)
*/
int int
ambe_decode_dtx(struct ambe_decoder *dec, ambe_decode_dtx(struct ambe_decoder *dec,
int16_t *audio, int N) int16_t *audio, int N)

View File

@ -37,7 +37,7 @@
/*! \brief Structure for GMR1 codec state */ /*! \brief Structure for GMR1 codec state */
struct gmr1_codec struct gmr1_codec
{ {
struct ambe_decoder dec; /*< \brief decoder state */ struct ambe_decoder dec; /*!< \brief Decoder state */
}; };

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*! \addtogroup codec/private /*! \addtogroup codec_private
* @{ * @{
*/ */
@ -32,6 +32,13 @@
#include "private.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 static inline uint8_t
_get_bits(const uint8_t *frame, int p, int l, int s) _get_bits(const uint8_t *frame, int p, int l, int s)
{ {
@ -46,6 +53,10 @@ _get_bits(const uint8_t *frame, int p, int l, int s)
return (v & ((1<<l)-1)) << s; 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 void
ambe_frame_unpack_raw(struct ambe_raw_params *rp, const uint8_t *frame) ambe_frame_unpack_raw(struct ambe_raw_params *rp, const uint8_t *frame)
{ {
@ -67,6 +78,12 @@ ambe_frame_unpack_raw(struct ambe_raw_params *rp, const uint8_t *frame)
rp->sf0_perr_58 = _get_bits(p, 44, 2, 3) | _get_bits(p, 77, 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 static float
ambe_interpolate_f0log(float f0log_prev, float f0log_cur, int rule) ambe_interpolate_f0log(float f0log_prev, float f0log_cur, int rule)
{ {
@ -104,6 +121,9 @@ ambe_interpolate_f0log(float f0log_prev, float f0log_cur, int rule)
return 0.0f; /* Not reached */ 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 static void
ambe_subframe_compute_L_Lb(struct ambe_subframe *sf) ambe_subframe_compute_L_Lb(struct ambe_subframe *sf)
{ {
@ -120,6 +140,12 @@ ambe_subframe_compute_L_Lb(struct ambe_subframe *sf)
sf->Lb[3] = ambe_hpg_tbl[sf->L - 9][3]; 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 static void
ambe_resample_mag(float *mag_dst, int L_dst, float *mag_src, int L_src) ambe_resample_mag(float *mag_dst, int L_dst, float *mag_src, int L_src)
{ {
@ -154,6 +180,11 @@ ambe_resample_mag(float *mag_dst, int L_dst, float *mag_src, int L_src)
mag_dst[i] -= avg; 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 static void
ambe_subframe1_compute_mag(struct ambe_subframe *sf, ambe_subframe1_compute_mag(struct ambe_subframe *sf,
struct ambe_subframe *sf_prev, struct ambe_subframe *sf_prev,
@ -224,6 +255,12 @@ ambe_subframe1_compute_mag(struct ambe_subframe *sf,
sf->Mlog[i] += ofs; 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 static void
ambe_subframe0_compute_mag(struct ambe_subframe *sf, ambe_subframe0_compute_mag(struct ambe_subframe *sf,
struct ambe_subframe *sf1_prev, struct ambe_subframe *sf1_prev,
@ -263,6 +300,11 @@ ambe_subframe0_compute_mag(struct ambe_subframe *sf,
sf->Mlog[i] = gain + corr[i] + (alpha * mag_p[i]) + ((1.0f - alpha) * mag_c[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
*/
int int
ambe_frame_decode_params(struct ambe_subframe *sf, ambe_frame_decode_params(struct ambe_subframe *sf,
struct ambe_subframe *sf_prev, struct ambe_subframe *sf_prev,

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*! \addtogroup codec/private /*! \addtogroup codec_private
* @{ * @{
*/ */

View File

@ -20,8 +20,8 @@
#ifndef __OSMO_GMR1_CODEC_PRIVATE_H__ #ifndef __OSMO_GMR1_CODEC_PRIVATE_H__
#define __OSMO_GMR1_CODEC_PRIVATE_H__ #define __OSMO_GMR1_CODEC_PRIVATE_H__
/*! \defgroup codec/private AMBE vocoder - internal API /*! \defgroup codec_private AMBE vocoder - internal API
* \ingroup codec/private * \ingroup codec
* @{ * @{
*/ */
@ -34,15 +34,15 @@
#include "mbelib.h" #include "mbelib.h"
#define AMBE_RATE 8000 /*< \brief AMBE sample rate */ #define AMBE_RATE 8000 /*!< \brief AMBE sample rate (Hz) */
/*! \brief AMBE possible frame types */ /*! \brief AMBE possible frame types */
enum ambe_frame_type enum ambe_frame_type
{ {
AMBE_SPEECH, /*< \brief Speed frame */ AMBE_SPEECH, /*!< \brief Speech frame */
AMBE_SILENCE, /*< \brief Silence indication frame */ AMBE_SILENCE, /*!< \brief Silence indication frame */
AMBE_TONE, /*< \brief Tone frame */ AMBE_TONE, /*!< \brief Tone frame */
}; };
/*! \brief AMBE encoded frame raw parameters */ /*! \brief AMBE encoded frame raw parameters */

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*! \addtogroup codec/private /*! \addtogroup codec_private
* @{ * @{
*/ */
@ -28,7 +28,7 @@
#include <stdint.h> #include <stdint.h>
/*! \brief Number of harmonics per group for a given L (starts at L=9) */ /*! \brief Number of harmonics per group for a given L (starts at L=9) */
const uint8_t ambe_hpg_tbl[48][4] = { extern const uint8_t ambe_hpg_tbl[48][4] = {
{ 2, 2, 2, 3} /* L = 9 */, { 2, 2, 2, 3} /* L = 9 */,
{ 2, 2, 3, 3}, { 2, 2, 3, 3},
{ 2, 3, 3, 3}, { 2, 3, 3, 3},
@ -79,8 +79,8 @@ const uint8_t ambe_hpg_tbl[48][4] = {
{ 11, 13, 15, 17}, /* L = 56 */ { 11, 13, 15, 17}, /* L = 56 */
}; };
/* \brief Gain (subframe 0, subframe 1) */ /*! \brief Gain (subframe 0, subframe 1) */
const float ambe_gain_tbl[256][2] = { extern const float ambe_gain_tbl[256][2] = {
{ -0.250000f, -0.250000f }, { -0.250000f, -0.250000f },
{ +0.500000f, -0.500000f }, { +0.500000f, -0.500000f },
{ +0.750000f, +0.750000f }, { +0.750000f, +0.750000f },
@ -340,7 +340,7 @@ const float ambe_gain_tbl[256][2] = {
}; };
/*! \brief V/UV decisions (subframe 0 = low byte. MSBs = low freq) */ /*! \brief V/UV decisions (subframe 0 = low byte. MSBs = low freq) */
const uint16_t ambe_v_uv_tbl[64] = { extern const uint16_t ambe_v_uv_tbl[64] = {
0x0000, 0xffff, 0xc0c0, 0xe0e0, 0xf0f0, 0x8080, 0xfefe, 0x0080, 0x0000, 0xffff, 0xc0c0, 0xe0e0, 0xf0f0, 0x8080, 0xfefe, 0x0080,
0xfcfc, 0x80c0, 0xf8f8, 0x8000, 0x00c0, 0xfffe, 0xfeff, 0xc000, 0xfcfc, 0x80c0, 0xf8f8, 0x8000, 0x00c0, 0xfffe, 0xfeff, 0xc000,
0xf0e0, 0xc0e0, 0xfbfb, 0xfcfe, 0xf8f0, 0xfdfd, 0xfffb, 0xe000, 0xf0e0, 0xc0e0, 0xfbfb, 0xfcfe, 0xf8f0, 0xfdfd, 0xfffb, 0xe000,
@ -351,8 +351,8 @@ const uint16_t ambe_v_uv_tbl[64] = {
0x1000, 0xe0e1, 0xe0f8, 0xf2f0, 0xf8ff, 0xfafe, 0xfff7, 0xdfdf, 0x1000, 0xe0e1, 0xe0f8, 0xf2f0, 0xf8ff, 0xfafe, 0xfff7, 0xdfdf,
}; };
/* \brief PRBA[1:2] */ /*! \brief PRBA[1:2] */
const float ambe_prba12_tbl[128][2] = { extern const float ambe_prba12_tbl[128][2] = {
{ -0.042480f, +0.271484f }, { -0.042480f, +0.271484f },
{ -0.082031f, +0.219727f }, { -0.082031f, +0.219727f },
{ -0.579102f, +0.062988f }, { -0.579102f, +0.062988f },
@ -483,8 +483,8 @@ const float ambe_prba12_tbl[128][2] = {
{ +0.425781f, -0.049316f }, { +0.425781f, -0.049316f },
}; };
/* \brief PRBA[3:4] */ /*! \brief PRBA[3:4] */
const float ambe_prba34_tbl[64][2] = { extern const float ambe_prba34_tbl[64][2] = {
{ +0.439453f, +0.273438f }, { +0.439453f, +0.273438f },
{ +0.307129f, +0.220215f }, { +0.307129f, +0.220215f },
{ +0.338867f, +0.147949f }, { +0.338867f, +0.147949f },
@ -551,8 +551,8 @@ const float ambe_prba34_tbl[64][2] = {
{ -0.333496f, -0.238770f }, { -0.333496f, -0.238770f },
}; };
/* \brief PRBA[5:7] */ /*! \brief PRBA[5:7] */
const float ambe_prba57_tbl[128][3] = { extern const float ambe_prba57_tbl[128][3] = {
{ +0.012695f, -0.156250f, -0.120605f }, { +0.012695f, -0.156250f, -0.120605f },
{ -0.009277f, -0.090332f, -0.065918f }, { -0.009277f, -0.090332f, -0.065918f },
{ -0.062500f, -0.173340f, -0.151855f }, { -0.062500f, -0.173340f, -0.151855f },
@ -683,8 +683,8 @@ const float ambe_prba57_tbl[128][3] = {
{ -0.042480f, +0.068359f, +0.100586f }, { -0.042480f, +0.068359f, +0.100586f },
}; };
/* \brief HOC for 1st frequency block */ /*! \brief HOC for 1st frequency block */
const float ambe_hoc0_tbl[128][4] = { extern const float ambe_hoc0_tbl[128][4] = {
{ +0.368652f, -0.230469f, -0.191406f, +0.158203f }, { +0.368652f, -0.230469f, -0.191406f, +0.158203f },
{ +0.300781f, -0.079102f, -0.018066f, +0.124512f }, { +0.300781f, -0.079102f, -0.018066f, +0.124512f },
{ +0.318848f, -0.202637f, +0.081055f, -0.000977f }, { +0.318848f, -0.202637f, +0.081055f, -0.000977f },
@ -815,8 +815,8 @@ const float ambe_hoc0_tbl[128][4] = {
{ -0.461914f, +0.264160f, +0.172363f, -0.184082f }, { -0.461914f, +0.264160f, +0.172363f, -0.184082f },
}; };
/* \brief HOC for 2nd frequency block */ /*! \brief HOC for 2nd frequency block */
const float ambe_hoc1_tbl[64][4] = { extern const float ambe_hoc1_tbl[64][4] = {
{ -0.364258f, +0.365723f, +0.244141f, +0.045410f }, { -0.364258f, +0.365723f, +0.244141f, +0.045410f },
{ -0.579102f, +0.200684f, -0.009766f, +0.049316f }, { -0.579102f, +0.200684f, -0.009766f, +0.049316f },
{ -0.227051f, +0.341309f, -0.048828f, -0.008301f }, { -0.227051f, +0.341309f, -0.048828f, -0.008301f },
@ -883,8 +883,8 @@ const float ambe_hoc1_tbl[64][4] = {
{ +0.332520f, -0.322754f, -0.201172f, -0.001465f }, { +0.332520f, -0.322754f, -0.201172f, -0.001465f },
}; };
/* \brief HOC for 3rd frequency block */ /*! \brief HOC for 3rd frequency block */
const float ambe_hoc2_tbl[64][4] = { extern const float ambe_hoc2_tbl[64][4] = {
{ -0.107422f, +0.202637f, +0.255859f, -0.011719f }, { -0.107422f, +0.202637f, +0.255859f, -0.011719f },
{ -0.214844f, -0.538086f, -0.206543f, +0.003418f }, { -0.214844f, -0.538086f, -0.206543f, +0.003418f },
{ -0.027832f, -0.366211f, -0.125488f, +0.198730f }, { -0.027832f, -0.366211f, -0.125488f, +0.198730f },
@ -951,8 +951,8 @@ const float ambe_hoc2_tbl[64][4] = {
{ +0.104492f, +0.204590f, -0.219238f, +0.086914f }, { +0.104492f, +0.204590f, -0.219238f, +0.086914f },
}; };
/* \brief HOC for last frequency block */ /*! \brief HOC for last frequency block */
const float ambe_hoc3_tbl[64][4] = { extern const float ambe_hoc3_tbl[64][4] = {
{ +0.168457f, +0.110352f, +0.166504f, -0.110840f }, { +0.168457f, +0.110352f, +0.166504f, -0.110840f },
{ +0.338379f, +0.063965f, +0.101074f, +0.089844f }, { +0.338379f, +0.063965f, +0.101074f, +0.089844f },
{ +0.256836f, -0.126465f, +0.064941f, -0.130371f }, { +0.256836f, -0.126465f, +0.064941f, -0.130371f },
@ -1019,16 +1019,16 @@ const float ambe_hoc3_tbl[64][4] = {
{ +1.952637f, +3.729004f, +2.333496f, +3.879395f }, { +1.952637f, +3.729004f, +2.333496f, +3.879395f },
}; };
/* \brief Interpolation ratios for subframe 0 magnitude prediction */ /*! \brief Interpolation ratios for subframe 0 magnitude prediction */
const float ambe_sf0_interp_tbl[4] = { extern const float ambe_sf0_interp_tbl[4] = {
0.90f, 0.90f,
0.70f, 0.70f,
0.50f, 0.50f,
0.17f, 0.17f,
}; };
/* \brief Prediction Error [1:4] for subframe 0 */ /*! \brief Prediction Error [1:4] for subframe 0 */
const float ambe_sf0_perr14_tbl[64][4] = { extern const float ambe_sf0_perr14_tbl[64][4] = {
{ -0.106445f, +0.011230f, -0.166992f, -0.022461f }, { -0.106445f, +0.011230f, -0.166992f, -0.022461f },
{ -0.056641f, +0.166504f, -0.139648f, -0.102051f }, { -0.056641f, +0.166504f, -0.139648f, -0.102051f },
{ -0.004883f, +0.052246f, -0.106934f, +0.084961f }, { -0.004883f, +0.052246f, -0.106934f, +0.084961f },
@ -1095,8 +1095,8 @@ const float ambe_sf0_perr14_tbl[64][4] = {
{ +0.178223f, -0.077148f, +0.190918f, +0.095215f }, { +0.178223f, -0.077148f, +0.190918f, +0.095215f },
}; };
/* \brief Prediction Error [5:8] for subframe 0 */ /*! \brief Prediction Error [5:8] for subframe 0 */
const float ambe_sf0_perr58_tbl[32][4] = { extern const float ambe_sf0_perr58_tbl[32][4] = {
{ -0.006836f, +0.065430f, +0.135254f, +0.032715f }, { -0.006836f, +0.065430f, +0.135254f, +0.032715f },
{ -0.019531f, +0.053223f, +0.054688f, -0.052734f }, { -0.019531f, +0.053223f, +0.054688f, -0.052734f },
{ -0.143066f, +0.037598f, +0.059082f, +0.054688f }, { -0.143066f, +0.037598f, +0.059082f, +0.054688f },

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*! \addtogroup codec/private /*! \addtogroup codec_private
* @{ * @{
*/ */
@ -35,9 +35,9 @@
/*! \brief Structure describing a dual-frequency tone */ /*! \brief Structure describing a dual-frequency tone */
struct tone_desc { struct tone_desc {
char *name; char *name; /*!< \brief Tone description */
int f1; int f1; /*!< \brief Frequency 1 (Hz) */
int f2; int f2; /*!< \brief Frequency 2 (Hz) */
}; };
/*! \brief DTMF tones descriptions */ /*! \brief DTMF tones descriptions */