179 lines
4.8 KiB
C
179 lines
4.8 KiB
C
/* Iridium AMBE vocoder - AMBE API */
|
|
|
|
/* (C) 2015 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
|
|
* @{
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "ambe.h"
|
|
#include "private.h"
|
|
|
|
|
|
/*! \brief Allocates and inits a decoder object
|
|
* \returns A newly allocated and initialized decoder
|
|
*/
|
|
struct ir77_ambe_decoder *
|
|
ir77_ambe_decode_alloc(void)
|
|
{
|
|
struct ir77_ambe_decoder *dec;
|
|
|
|
dec = calloc(1, sizeof(struct ir77_ambe_decoder));
|
|
if (!dec)
|
|
return NULL;
|
|
|
|
ir77_ambe_synth_init(&dec->synth);
|
|
|
|
dec->sf_prev.w0 = 0.09378;
|
|
dec->sf_prev.f0 = dec->sf_prev.w0 / (2 * M_PIf);
|
|
dec->sf_prev.L = 30;
|
|
|
|
return dec;
|
|
}
|
|
|
|
/*! \brief Release a decoder object created by \ref ir77_ambe_decode_alloc
|
|
* \param[in] dec Decoder object
|
|
*/
|
|
void
|
|
ir77_ambe_decode_release(struct ir77_ambe_decoder *dec)
|
|
{
|
|
free(dec);
|
|
}
|
|
|
|
|
|
/*! \brief Decodes an AMBE frame to audio
|
|
* \param[in] dec Decoder object
|
|
* \param[out] audio Output audio buffers
|
|
* \param[in] N number of audio samples to produce (== 360 for now)
|
|
* \param[in] frame Frame data (as de-prioritized 103 ubits), Must be speech !
|
|
* \returns 0 for success. Negative error code otherwise.
|
|
*/
|
|
static int
|
|
ir77_ambe_decode_speech(struct ir77_ambe_decoder *dec,
|
|
int16_t *audio, int N, const ubit_t *frame_lin)
|
|
{
|
|
struct ir77_ambe_raw_params rp;
|
|
struct ir77_ambe_subframe sf[2];
|
|
|
|
/* Read out params */
|
|
ir77_ambe_frame_unpack_raw(&rp, frame_lin);
|
|
|
|
/* Decode params */
|
|
ir77_ambe_frame_decode_params(sf, &dec->sf_prev, &rp);
|
|
|
|
/* Expand them */
|
|
ir77_ambe_subframe_expand(&sf[0]);
|
|
ir77_ambe_subframe_expand(&sf[1]);
|
|
|
|
/* Perform the actual audio synthesis */
|
|
ir77_ambe_synth_enhance(&dec->synth, &sf[0]);
|
|
ir77_ambe_synth_enhance(&dec->synth, &sf[1]);
|
|
|
|
ir77_ambe_synth_audio(&dec->synth, audio , &sf[0], &dec->sf_prev);
|
|
ir77_ambe_synth_audio(&dec->synth, audio + 180, &sf[1], &sf[0]);
|
|
|
|
/* Save previous subframe */
|
|
memcpy(&dec->sf_prev, &sf[1], sizeof(struct ir77_ambe_subframe));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*! \brief Decodes an AMBE superframe (=2 frames) to audio
|
|
* \param[in] dec Decoder object
|
|
* \param[out] audio Output audio buffers
|
|
* \param[in] N number of audio samples to produce (== 720 for now)
|
|
* \param[in] superframe SuperFrame data (39 bytes = 312 bits)
|
|
* \returns Number of successfully decoded frames. Negative error code otherwise.
|
|
*/
|
|
int
|
|
ir77_ambe_decode_superframe(struct ir77_ambe_decoder *dec,
|
|
int16_t *audio, int N,
|
|
const uint8_t *superframe)
|
|
{
|
|
ubit_t superframe_bits[312];
|
|
ubit_t frame_bits[156];
|
|
int frames = 0, i;
|
|
|
|
/* Unpack to ubits */
|
|
osmo_pbit2ubit_ext(superframe_bits, 0, superframe, 0, 312, 1);
|
|
|
|
/* Process each frame */
|
|
for (i=0; i<2; i++)
|
|
{
|
|
ubit_t frame[103], frame_lin[103];
|
|
enum ir77_ambe_frame_type type;
|
|
int err[6];
|
|
uint32_t seed;
|
|
|
|
/* De-interleave */
|
|
ir77_ambe_interleave(frame_bits, superframe_bits+i, 2, 156, 1);
|
|
|
|
/* De-FEC */
|
|
err[0] = ir77_ambe_golay24_decode(&frame[ 0], &frame_bits[ 0], &seed);
|
|
|
|
ir77_ambe_scramble(&frame_bits[24], &frame_bits[24], 156-24-33, seed);
|
|
|
|
err[1] = ir77_ambe_golay23_decode (&frame[12], &frame_bits[ 24], NULL);
|
|
err[2] = ir77_ambe_golay23_decode (&frame[24], &frame_bits[ 47], NULL);
|
|
err[3] = ir77_ambe_golay23_decode (&frame[36], &frame_bits[ 70], NULL);
|
|
err[4] = ir77_ambe_hamming1511_decode(&frame[48], &frame_bits[ 93]);
|
|
err[5] = ir77_ambe_hamming1511_decode(&frame[59], &frame_bits[108]);
|
|
|
|
memcpy(&frame[70], &frame_bits[123], 33);
|
|
|
|
/* Skip bad frames */
|
|
if ((err[1] + err[2] + err[3]) > 6) {
|
|
memset(&audio[360*i], 0x0, sizeof(int16_t) * 360);
|
|
continue;
|
|
}
|
|
|
|
frames++;
|
|
|
|
/* De-prioritize */
|
|
ir77_ambe_prioritize(frame_lin, frame, 1);
|
|
|
|
/* Classify frame */
|
|
type = ir77_ambe_frame_classify(frame_lin);
|
|
|
|
/* Decode appropriately */
|
|
switch (type)
|
|
{
|
|
case AMBE_SPEECH:
|
|
ir77_ambe_decode_speech(dec, &audio[360*i], 360, frame_lin);
|
|
break;
|
|
|
|
case AMBE_TONE:
|
|
ir77_ambe_decode_tone(dec, &audio[360*i], 360, frame_lin);
|
|
break;
|
|
|
|
case AMBE_SILENCE:
|
|
case AMBE_INVALID:
|
|
memset(&audio[360*i], 0x0, sizeof(int16_t) * 360);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return frames;
|
|
}
|
|
|
|
/*! @} */
|