gapk/src/fmt_hr_ref.c

215 lines
4.3 KiB
C
Raw Normal View History

/* 3GPP Reference HR vocoder file formats
*
* See http://ftp.3gpp.org/Specs/2001-06/Ph2/06_series/0606-421/0606_421.zip
*/
/*
* This file is part of gapk (GSM Audio Pocket Knife).
*
* gapk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gapk 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <osmocom/gapk/codecs.h>
#include <osmocom/gapk/formats.h>
#include <osmocom/gapk/utils.h>
static const int params_unvoiced[] = {
5, /* R0 */
11, /* k1Tok3 */
9, /* k4Tok6 */
8, /* k7Tok10 */
1, /* softInterpolation */
2, /* voicingDecision */
7, /* code1_1 */
7, /* code2_1 */
5, /* gsp0_1 */
7, /* code1_2 */
7, /* code2_2 */
5, /* gsp0_2 */
7, /* code1_3 */
7, /* code2_3 */
5, /* gsp0_3 */
7, /* code1_4 */
7, /* code2_4 */
5, /* gsp0_4 */
};
static const int params_voiced[] = {
5, /* R0 */
11, /* k1Tok3 */
9, /* k4Tok6 */
8, /* k7Tok10 */
1, /* softInterpolation */
2, /* voicingDecision */
8, /* frameLag */
9, /* code_1 */
5, /* gsp0_1 */
4, /* deltaLag_2 */
9, /* code_2 */
5, /* gsp0_2 */
4, /* deltaLag_3 */
9, /* code_3 */
5, /* gsp0_3 */
4, /* deltaLag_4 */
9, /* code_4 */
5, /* gsp0_4 */
};
static int
hr_ref_from_canon(uint16_t *hr_ref, const uint8_t *canon)
{
int i, j, voiced;
const int *params;
voiced = (msb_get_bit(canon, 34) << 1) | msb_get_bit(canon, 35);
params = voiced ? &params_voiced[0] : &params_unvoiced[0];
for (i=0,j=0; i<18; i++)
{
uint16_t w;
int l, k;
l = params[i];
w = 0;
for (k=0; k<l; k++)
w = (w << 1) | msb_get_bit(canon, j+k);
hr_ref[i] = w;
j += l;
}
return 0;
}
static int
hr_ref_to_canon(uint8_t *canon, const uint16_t *hr_ref)
{
int i, j, voiced;
const int *params;
voiced = hr_ref[5]; /* voicingDecision */
params = voiced ? &params_voiced[0] : &params_unvoiced[0];
for (i=0,j=0; i<18; i++)
{
uint16_t w;
int l, k;
l = params[i];
w = hr_ref[i];
for (k=0; k<l; k++)
msb_put_bit(canon, j+k, w & (1<<(l-k-1)));
j += l;
}
return 0;
}
static int
hr_ref_dec_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
uint16_t *hr_ref = (uint16_t *)dst;
int rv;
assert(src_len == HR_CANON_LEN);
rv = hr_ref_from_canon(hr_ref, src);
if (rv)
return rv;
hr_ref[18] = 0; /* BFI : 1 bit */
hr_ref[19] = 0; /* UFI : 1 bit */
hr_ref[20] = 0; /* SID : 2 bit */
hr_ref[21] = 0; /* TAF : 1 bit */
return HR_REF_DEC_LEN;
}
static int
hr_ref_dec_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
const uint16_t *hr_ref = (const uint16_t *)src;
int rv;
assert(src_len == HR_REF_DEC_LEN);
rv = hr_ref_to_canon(dst, hr_ref);
if (rv)
return rv;
return HR_CANON_LEN;
}
static int
hr_ref_enc_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
uint16_t *hr_ref = (uint16_t *)dst;
int rv;
assert(src_len == HR_CANON_LEN);
rv = hr_ref_from_canon(hr_ref, src);
if (rv)
return rv;
hr_ref[18] = 0; /* SP : 1 bit */
hr_ref[19] = 0; /* VAD : 1 bit */
return HR_REF_ENC_LEN;
}
static int
hr_ref_enc_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
const uint16_t *hr_ref = (const uint16_t *)src;
int rv;
assert(src_len == HR_REF_ENC_LEN);
rv = hr_ref_to_canon(dst, hr_ref);
if (rv)
return rv;
return HR_CANON_LEN;
}
const struct osmo_gapk_format_desc fmt_hr_ref_dec = {
.type = FMT_HR_REF_DEC,
.codec_type = CODEC_HR,
.name = "hr-ref-dec",
.description = "3GPP HR Reference decoder code parameters file format",
.frame_len = HR_REF_DEC_LEN,
.conv_from_canon = hr_ref_dec_from_canon,
.conv_to_canon = hr_ref_dec_to_canon,
};
const struct osmo_gapk_format_desc fmt_hr_ref_enc = {
.type = FMT_HR_REF_ENC,
.codec_type = CODEC_HR,
.name = "hr-ref-enc",
.description = "3GPP HR Reference encoder code parameters file format",
.frame_len = HR_REF_ENC_LEN,
.conv_from_canon = hr_ref_enc_from_canon,
.conv_to_canon = hr_ref_enc_to_canon,
};