2010-10-29 09:44:40 +00:00
|
|
|
/* 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/>.
|
|
|
|
*/
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2017-08-30 13:26:02 +00:00
|
|
|
#include <osmocom/gapk/codecs.h>
|
|
|
|
#include <osmocom/gapk/formats.h>
|
|
|
|
#include <osmocom/gapk/utils.h>
|
2010-10-29 09:44:40 +00:00
|
|
|
|
|
|
|
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 ? ¶ms_voiced[0] : ¶ms_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 ? ¶ms_voiced[0] : ¶ms_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
|
2017-05-28 08:20:54 +00:00
|
|
|
hr_ref_dec_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
2010-10-29 09:44:40 +00:00
|
|
|
{
|
|
|
|
uint16_t *hr_ref = (uint16_t *)dst;
|
|
|
|
int rv;
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
assert(src_len == HR_CANON_LEN);
|
|
|
|
|
2010-10-29 09:44:40 +00:00
|
|
|
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 */
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
return HR_REF_DEC_LEN;
|
2010-10-29 09:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-28 08:20:54 +00:00
|
|
|
hr_ref_dec_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
2010-10-29 09:44:40 +00:00
|
|
|
{
|
|
|
|
const uint16_t *hr_ref = (const uint16_t *)src;
|
|
|
|
int rv;
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
assert(src_len == HR_REF_DEC_LEN);
|
|
|
|
|
2010-10-29 09:44:40 +00:00
|
|
|
rv = hr_ref_to_canon(dst, hr_ref);
|
|
|
|
if (rv)
|
|
|
|
return rv;
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
return HR_CANON_LEN;
|
2010-10-29 09:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-28 08:20:54 +00:00
|
|
|
hr_ref_enc_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
2010-10-29 09:44:40 +00:00
|
|
|
{
|
|
|
|
uint16_t *hr_ref = (uint16_t *)dst;
|
|
|
|
int rv;
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
assert(src_len == HR_CANON_LEN);
|
|
|
|
|
2010-10-29 09:44:40 +00:00
|
|
|
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 */
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
return HR_REF_ENC_LEN;
|
2010-10-29 09:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-28 08:20:54 +00:00
|
|
|
hr_ref_enc_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
2010-10-29 09:44:40 +00:00
|
|
|
{
|
|
|
|
const uint16_t *hr_ref = (const uint16_t *)src;
|
|
|
|
int rv;
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
assert(src_len == HR_REF_ENC_LEN);
|
|
|
|
|
2010-10-29 09:44:40 +00:00
|
|
|
rv = hr_ref_to_canon(dst, hr_ref);
|
|
|
|
if (rv)
|
|
|
|
return rv;
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
return HR_CANON_LEN;
|
2010-10-29 09:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const struct 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",
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
.frame_len = HR_REF_DEC_LEN,
|
2010-10-29 09:44:40 +00:00
|
|
|
.conv_from_canon = hr_ref_dec_from_canon,
|
|
|
|
.conv_to_canon = hr_ref_dec_to_canon,
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct 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",
|
|
|
|
|
2017-05-28 08:20:54 +00:00
|
|
|
.frame_len = HR_REF_ENC_LEN,
|
2010-10-29 09:44:40 +00:00
|
|
|
.conv_from_canon = hr_ref_enc_from_canon,
|
|
|
|
.conv_to_canon = hr_ref_enc_to_canon,
|
|
|
|
};
|