164 lines
4.2 KiB
C
164 lines
4.2 KiB
C
/* GMR-1 AMBE vocoder - internal API */
|
|
|
|
/* (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/ambe.c
|
|
* \brief Osmocom GMR-1 AMBE internal API
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "private.h"
|
|
|
|
|
|
/*! \brief Initializes decoder state
|
|
* \param[in] dec Decoder state structure
|
|
*/
|
|
void
|
|
ambe_decode_init(struct ambe_decoder *dec)
|
|
{
|
|
memset(dec, 0x00, sizeof(struct ambe_decoder));
|
|
|
|
ambe_synth_init(&dec->synth);
|
|
|
|
dec->sf_prev.w0 = 0.09378f;
|
|
dec->sf_prev.f0 = dec->sf_prev.w0 / (2 * M_PIf);
|
|
dec->sf_prev.L = 30;
|
|
}
|
|
|
|
/*! \brief Release all resources associated with a decoder
|
|
* \param[in] dec Decoder state structure
|
|
*/
|
|
void
|
|
ambe_decode_fini(struct ambe_decoder *dec)
|
|
{
|
|
/* nothing to do */
|
|
}
|
|
|
|
|
|
/*! \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
|
|
ambe_classify_frame(const uint8_t *frame)
|
|
{
|
|
switch (frame[0] & 0xfc) {
|
|
case 0xfc:
|
|
return AMBE_TONE;
|
|
|
|
case 0xf8:
|
|
return AMBE_SILENCE;
|
|
|
|
default:
|
|
return AMBE_SPEECH;
|
|
};
|
|
}
|
|
|
|
/*! \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
|
|
ambe_decode_speech(struct ambe_decoder *dec,
|
|
int16_t *audio, int N,
|
|
const uint8_t *frame, int bad)
|
|
{
|
|
struct ambe_raw_params rp;
|
|
struct ambe_subframe sf[2];
|
|
|
|
/* Unpack frame */
|
|
ambe_frame_unpack_raw(&rp, frame);
|
|
|
|
/* Decode subframe parameters */
|
|
ambe_frame_decode_params(sf, &dec->sf_prev, &rp);
|
|
|
|
/* Expand parameters for synthesis */
|
|
ambe_subframe_expand(&sf[0]);
|
|
ambe_subframe_expand(&sf[1]);
|
|
|
|
/* Perform the actual audio synthesis */
|
|
ambe_synth_enhance(&dec->synth, &sf[0]);
|
|
ambe_synth_audio(&dec->synth, audio, &sf[0], &dec->sf_prev);
|
|
|
|
ambe_synth_enhance(&dec->synth, &sf[1]);
|
|
ambe_synth_audio(&dec->synth, audio + 80, &sf[1], &sf[0]);
|
|
|
|
/* Save subframe */
|
|
memcpy(&dec->sf_prev, &sf[1], sizeof(struct ambe_subframe));
|
|
|
|
/* Done */
|
|
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
|
|
ambe_decode_frame(struct ambe_decoder *dec,
|
|
int16_t *audio, int N,
|
|
const uint8_t *frame, int bad)
|
|
{
|
|
switch(ambe_classify_frame(frame)) {
|
|
case AMBE_SPEECH:
|
|
return ambe_decode_speech(dec, audio, N, frame, bad);
|
|
|
|
case AMBE_SILENCE:
|
|
/* FIXME: Comfort noise */
|
|
memset(audio, 0, 160*sizeof(int16_t));
|
|
return 0;
|
|
|
|
case AMBE_TONE:
|
|
return ambe_decode_tone(dec, audio, N, frame);
|
|
}
|
|
|
|
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
|
|
ambe_decode_dtx(struct ambe_decoder *dec,
|
|
int16_t *audio, int N)
|
|
{
|
|
/* FIXME: Comfort noise */
|
|
memset(audio, 0x00, sizeof(int16_t) * N);
|
|
return 0;
|
|
}
|
|
|
|
/*! @} */
|