blob: 7a96d3ec3266a378a4f00cd79366523edbb098fc [file] [log] [blame]
Sylvain Munautf9059832010-10-29 11:44:40 +02001/* 3GPP Reference HR vocoder file formats
2 *
3 * See http://ftp.3gpp.org/Specs/2001-06/Ph2/06_series/0606-421/0606_421.zip
4 */
5
6/*
7 * This file is part of gapk (GSM Audio Pocket Knife).
8 *
9 * gapk is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * gapk is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with gapk. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <gapk/codecs.h>
24#include <gapk/formats.h>
25#include <gapk/utils.h>
26
27
28static const int params_unvoiced[] = {
29 5, /* R0 */
30 11, /* k1Tok3 */
31 9, /* k4Tok6 */
32 8, /* k7Tok10 */
33 1, /* softInterpolation */
34 2, /* voicingDecision */
35 7, /* code1_1 */
36 7, /* code2_1 */
37 5, /* gsp0_1 */
38 7, /* code1_2 */
39 7, /* code2_2 */
40 5, /* gsp0_2 */
41 7, /* code1_3 */
42 7, /* code2_3 */
43 5, /* gsp0_3 */
44 7, /* code1_4 */
45 7, /* code2_4 */
46 5, /* gsp0_4 */
47};
48
49static const int params_voiced[] = {
50 5, /* R0 */
51 11, /* k1Tok3 */
52 9, /* k4Tok6 */
53 8, /* k7Tok10 */
54 1, /* softInterpolation */
55 2, /* voicingDecision */
56 8, /* frameLag */
57 9, /* code_1 */
58 5, /* gsp0_1 */
59 4, /* deltaLag_2 */
60 9, /* code_2 */
61 5, /* gsp0_2 */
62 4, /* deltaLag_3 */
63 9, /* code_3 */
64 5, /* gsp0_3 */
65 4, /* deltaLag_4 */
66 9, /* code_4 */
67 5, /* gsp0_4 */
68};
69
70
71static int
72hr_ref_from_canon(uint16_t *hr_ref, const uint8_t *canon)
73{
74 int i, j, voiced;
75 const int *params;
76
77 voiced = (msb_get_bit(canon, 34) << 1) | msb_get_bit(canon, 35);
78 params = voiced ? &params_voiced[0] : &params_unvoiced[0];
79
80 for (i=0,j=0; i<18; i++)
81 {
82 uint16_t w;
83 int l, k;
84
85 l = params[i];
86
87 w = 0;
88 for (k=0; k<l; k++)
89 w = (w << 1) | msb_get_bit(canon, j+k);
90 hr_ref[i] = w;
91
92 j += l;
93 }
94
95 return 0;
96}
97
98static int
99hr_ref_to_canon(uint8_t *canon, const uint16_t *hr_ref)
100{
101 int i, j, voiced;
102 const int *params;
103
104 voiced = hr_ref[5]; /* voicingDecision */
105 params = voiced ? &params_voiced[0] : &params_unvoiced[0];
106
107 for (i=0,j=0; i<18; i++)
108 {
109 uint16_t w;
110 int l, k;
111
112 l = params[i];
113
114 w = hr_ref[i];
115 for (k=0; k<l; k++)
116 msb_put_bit(canon, j+k, w & (1<<(l-k-1)));
117
118 j += l;
119 }
120
121 return 0;
122}
123
124static int
125hr_ref_dec_from_canon(uint8_t *dst, const uint8_t *src)
126{
127 uint16_t *hr_ref = (uint16_t *)dst;
128 int rv;
129
130 rv = hr_ref_from_canon(hr_ref, src);
131 if (rv)
132 return rv;
133
134 hr_ref[18] = 0; /* BFI : 1 bit */
135 hr_ref[19] = 0; /* UFI : 1 bit */
136 hr_ref[20] = 0; /* SID : 2 bit */
137 hr_ref[21] = 0; /* TAF : 1 bit */
138
139 return 0;
140}
141
142static int
143hr_ref_dec_to_canon(uint8_t *dst, const uint8_t *src)
144{
145 const uint16_t *hr_ref = (const uint16_t *)src;
146 int rv;
147
148 rv = hr_ref_to_canon(dst, hr_ref);
149 if (rv)
150 return rv;
151
152 return 0;
153}
154
155static int
156hr_ref_enc_from_canon(uint8_t *dst, const uint8_t *src)
157{
158 uint16_t *hr_ref = (uint16_t *)dst;
159 int rv;
160
161 rv = hr_ref_from_canon(hr_ref, src);
162 if (rv)
163 return rv;
164
165 hr_ref[18] = 0; /* SP : 1 bit */
166 hr_ref[19] = 0; /* VAD : 1 bit */
167
168 return 0;
169}
170
171static int
172hr_ref_enc_to_canon(uint8_t *dst, const uint8_t *src)
173{
174 const uint16_t *hr_ref = (const uint16_t *)src;
175 int rv;
176
177 rv = hr_ref_to_canon(dst, hr_ref);
178 if (rv)
179 return rv;
180
181 return 0;
182}
183
184
185const struct format_desc fmt_hr_ref_dec = {
186 .type = FMT_HR_REF_DEC,
187 .codec_type = CODEC_HR,
188 .name = "hr-ref-dec",
189 .description = "3GPP HR Reference decoder code parameters file format",
190
191 .frame_len = 22 * sizeof(uint16_t),
192 .conv_from_canon = hr_ref_dec_from_canon,
193 .conv_to_canon = hr_ref_dec_to_canon,
194};
195
196const struct format_desc fmt_hr_ref_enc = {
197 .type = FMT_HR_REF_ENC,
198 .codec_type = CODEC_HR,
199 .name = "hr-ref-enc",
200 .description = "3GPP HR Reference encoder code parameters file format",
201
202 .frame_len = 20 * sizeof(uint16_t),
203 .conv_from_canon = hr_ref_enc_from_canon,
204 .conv_to_canon = hr_ref_enc_to_canon,
205};