1 /* File format: AMR (c) 2007 robs@users.sourceforge.net
2 *
3 * This library is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or (at
6 * your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #include <string.h>
19 #include <math.h>
20
21 #ifdef AMR_OPENCORE
22
23 LSX_DLENTRIES_TO_FUNCTIONS(AMR_OPENCORE_FUNC_ENTRIES)
24
25 typedef struct amr_opencore_funcs {
26 LSX_DLENTRIES_TO_PTRS(AMR_OPENCORE_FUNC_ENTRIES, amr_dl);
27 } amr_opencore_funcs;
28
29 #endif /* AMR_OPENCORE */
30
31 #ifdef AMR_GP3
32
33 LSX_DLENTRIES_TO_FUNCTIONS(AMR_GP3_FUNC_ENTRIES)
34
35 typedef struct amr_gp3_funcs {
36 LSX_DLENTRIES_TO_PTRS(AMR_GP3_FUNC_ENTRIES, amr_dl);
37 } amr_gp3_funcs;
38
39 #endif /* AMR_GP3 */
40
41 #if defined(AMR_OPENCORE) && defined (AMR_GP3)
42 #define AMR_CALL(p, opencoreFunc, gp3Func, args) \
43 ((p)->loaded_opencore ? ((p)->opencore.opencoreFunc args) : ((p)->gp3.gp3Func args))
44 #if AMR_OPENCORE_ENABLE_ENCODE
45 #define AMR_CALL_ENCODER AMR_CALL
46 #else
47 #define AMR_CALL_ENCODER(p, opencoreFunc, gp3Func, args) \
48 ((p)->gp3.gp3Func args)
49 #endif
50 #elif defined(AMR_OPENCORE)
51 #define AMR_CALL(p, opencoreFunc, gp3Func, args) \
52 ((p)->opencore.opencoreFunc args)
53 #define AMR_CALL_ENCODER AMR_CALL
54 #elif defined(AMR_GP3)
55 #define AMR_CALL(p, opencoreFunc, gp3Func, args) \
56 ((p)->gp3.gp3Func args)
57 #define AMR_CALL_ENCODER AMR_CALL
58 #endif
59
60 typedef struct amr_priv_t {
61 void* state;
62 unsigned mode;
63 size_t pcm_index;
64 int loaded_opencore;
65 #ifdef AMR_OPENCORE
66 amr_opencore_funcs opencore;
67 #endif /* AMR_OPENCORE */
68 #ifdef AMR_GP3
69 amr_gp3_funcs gp3;
70 #endif /* AMR_GP3 */
71 short pcm[AMR_FRAME];
72 } priv_t;
73
decode_1_frame(sox_format_t * ft)74 static size_t decode_1_frame(sox_format_t * ft)
75 {
76 priv_t * p = (priv_t *)ft->priv;
77 size_t n_1;
78 uint8_t coded[AMR_CODED_MAX];
79
80 if (lsx_readbuf(ft, &coded[0], (size_t)1) != 1)
81 return AMR_FRAME;
82 n_1 = amr_block_size[(coded[0] >> 3) & 0x0F] - 1;
83 if (lsx_readbuf(ft, &coded[1], n_1) != n_1)
84 return AMR_FRAME;
85 AMR_CALL(p, AmrOpencoreDecoderDecode, AmrGp3DecoderDecode, (p->state, coded, p->pcm, 0));
86 return 0;
87 }
88
openlibrary(priv_t * p,int encoding)89 static int openlibrary(priv_t* p, int encoding)
90 {
91 int open_library_result;
92
93 (void)encoding;
94 #ifdef AMR_OPENCORE
95 if (AMR_OPENCORE_ENABLE_ENCODE || !encoding)
96 {
97 LSX_DLLIBRARY_TRYOPEN(
98 0,
99 &p->opencore,
100 amr_dl,
101 AMR_OPENCORE_FUNC_ENTRIES,
102 AMR_OPENCORE_DESC,
103 amr_opencore_library_names,
104 open_library_result);
105 if (!open_library_result)
106 {
107 p->loaded_opencore = 1;
108 return SOX_SUCCESS;
109 }
110 }
111 else
112 {
113 lsx_report("Not attempting to load " AMR_OPENCORE_DESC " because it does not support encoding.");
114 }
115 #endif /* AMR_OPENCORE */
116
117 #ifdef AMR_GP3
118 LSX_DLLIBRARY_TRYOPEN(
119 0,
120 &p->gp3,
121 amr_dl,
122 AMR_GP3_FUNC_ENTRIES,
123 AMR_GP3_DESC,
124 amr_gp3_library_names,
125 open_library_result);
126 if (!open_library_result)
127 return SOX_SUCCESS;
128 #endif /* AMR_GP3 */
129
130 lsx_fail(
131 "Unable to open "
132 #ifdef AMR_OPENCORE
133 AMR_OPENCORE_DESC
134 #endif
135 #if defined(AMR_OPENCORE) && defined(AMR_GP3)
136 " or "
137 #endif
138 #ifdef AMR_GP3
139 AMR_GP3_DESC
140 #endif
141 ".");
142 return SOX_EOF;
143 }
144
closelibrary(priv_t * p)145 static void closelibrary(priv_t* p)
146 {
147 #ifdef AMR_OPENCORE
148 LSX_DLLIBRARY_CLOSE(&p->opencore, amr_dl);
149 #endif
150 #ifdef AMR_GP3
151 LSX_DLLIBRARY_CLOSE(&p->gp3, amr_dl);
152 #endif
153 }
154
amr_duration_frames(sox_format_t * ft)155 static size_t amr_duration_frames(sox_format_t * ft)
156 {
157 off_t frame_size, data_start_offset = lsx_tell(ft);
158 size_t frames;
159 uint8_t coded;
160
161 for (frames = 0; lsx_readbuf(ft, &coded, (size_t)1) == 1; ++frames) {
162 frame_size = amr_block_size[coded >> 3 & 15];
163 if (lsx_seeki(ft, frame_size - 1, SEEK_CUR)) {
164 lsx_fail("seek");
165 break;
166 }
167 }
168 lsx_debug("frames=%lu", (unsigned long)frames);
169 lsx_seeki(ft, data_start_offset, SEEK_SET);
170 return frames;
171 }
172
startread(sox_format_t * ft)173 static int startread(sox_format_t * ft)
174 {
175 priv_t * p = (priv_t *)ft->priv;
176 char buffer[sizeof(amr_magic) - 1];
177 int open_library_result;
178
179 if (lsx_readchars(ft, buffer, sizeof(buffer)))
180 return SOX_EOF;
181 if (memcmp(buffer, amr_magic, sizeof(buffer))) {
182 lsx_fail_errno(ft, SOX_EHDR, "invalid magic number");
183 return SOX_EOF;
184 }
185
186 open_library_result = openlibrary(p, 0);
187 if (open_library_result != SOX_SUCCESS)
188 return open_library_result;
189
190 p->pcm_index = AMR_FRAME;
191 p->state = AMR_CALL(p, AmrOpencoreDecoderInit, AmrGp3DecoderInit, ());
192 if (!p->state)
193 {
194 closelibrary(p);
195 lsx_fail("AMR decoder failed to initialize.");
196 return SOX_EOF;
197 }
198
199 ft->signal.rate = AMR_RATE;
200 ft->encoding.encoding = AMR_ENCODING;
201 ft->signal.channels = 1;
202 ft->signal.length = ft->signal.length != SOX_IGNORE_LENGTH && ft->seekable?
203 (size_t)(amr_duration_frames(ft) * .02 * ft->signal.rate +.5) : SOX_UNSPEC;
204 return SOX_SUCCESS;
205 }
206
read_samples(sox_format_t * ft,sox_sample_t * buf,size_t len)207 static size_t read_samples(sox_format_t * ft, sox_sample_t * buf, size_t len)
208 {
209 priv_t * p = (priv_t *)ft->priv;
210 size_t done;
211
212 for (done = 0; done < len; done++) {
213 if (p->pcm_index >= AMR_FRAME)
214 p->pcm_index = decode_1_frame(ft);
215 if (p->pcm_index >= AMR_FRAME)
216 break;
217 *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(p->pcm[p->pcm_index++], ft->clips);
218 }
219 return done;
220 }
221
stopread(sox_format_t * ft)222 static int stopread(sox_format_t * ft)
223 {
224 priv_t * p = (priv_t *)ft->priv;
225 AMR_CALL(p, AmrOpencoreDecoderExit, AmrGp3DecoderExit, (p->state));
226 closelibrary(p);
227 return SOX_SUCCESS;
228 }
229
startwrite(sox_format_t * ft)230 static int startwrite(sox_format_t * ft)
231 {
232 #if !defined(AMR_GP3) && !AMR_OPENCORE_ENABLE_ENCODE
233 lsx_fail_errno(ft, SOX_EOF, "SoX was compiled without AMR-WB encoding support.");
234 return SOX_EOF;
235 #else
236 priv_t * p = (priv_t *)ft->priv;
237 int open_library_result;
238
239 if (ft->encoding.compression != HUGE_VAL) {
240 p->mode = (unsigned)ft->encoding.compression;
241 if (p->mode != ft->encoding.compression || p->mode > AMR_MODE_MAX) {
242 lsx_fail_errno(ft, SOX_EINVAL, "compression level must be a whole number from 0 to %i", AMR_MODE_MAX);
243 return SOX_EOF;
244 }
245 }
246 else p->mode = 0;
247
248 open_library_result = openlibrary(p, 1);
249 if (open_library_result != SOX_SUCCESS)
250 return open_library_result;
251
252 #define IGNORE_WARNING \
253 p->state = AMR_CALL_ENCODER(p, AmrOpencoreEncoderInit, AmrGp3EncoderInit, ());
254 #include "ignore-warning.h"
255 if (!p->state)
256 {
257 closelibrary(p);
258 lsx_fail("AMR encoder failed to initialize.");
259 return SOX_EOF;
260 }
261
262 lsx_writes(ft, amr_magic);
263 p->pcm_index = 0;
264 return SOX_SUCCESS;
265 #endif
266 }
267
268 #if defined(AMR_GP3) || AMR_OPENCORE_ENABLE_ENCODE
269
encode_1_frame(sox_format_t * ft)270 static sox_bool encode_1_frame(sox_format_t * ft)
271 {
272 priv_t * p = (priv_t *)ft->priv;
273 uint8_t coded[AMR_CODED_MAX];
274 #define IGNORE_WARNING \
275 int n = AMR_CALL_ENCODER(p, AmrOpencoreEncoderEncode, AmrGp3EncoderEncode, (p->state, p->mode, p->pcm, coded, 1));
276 #include "ignore-warning.h"
277 sox_bool result = lsx_writebuf(ft, coded, (size_t) (size_t) (unsigned)n) == (unsigned)n;
278 if (!result)
279 lsx_fail_errno(ft, errno, "write error");
280 return result;
281 }
282
write_samples(sox_format_t * ft,const sox_sample_t * buf,size_t len)283 static size_t write_samples(sox_format_t * ft, const sox_sample_t * buf, size_t len)
284 {
285 priv_t * p = (priv_t *)ft->priv;
286 size_t done;
287
288 for (done = 0; done < len; ++done) {
289 SOX_SAMPLE_LOCALS;
290 p->pcm[p->pcm_index++] = SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
291 if (p->pcm_index == AMR_FRAME) {
292 p->pcm_index = 0;
293 if (!encode_1_frame(ft))
294 return 0;
295 }
296 }
297 return done;
298 }
299
stopwrite(sox_format_t * ft)300 static int stopwrite(sox_format_t * ft)
301 {
302 priv_t * p = (priv_t *)ft->priv;
303 int result = SOX_SUCCESS;
304
305 if (p->pcm_index) {
306 do {
307 p->pcm[p->pcm_index++] = 0;
308 } while (p->pcm_index < AMR_FRAME);
309 if (!encode_1_frame(ft))
310 result = SOX_EOF;
311 }
312 AMR_CALL_ENCODER(p, AmrOpencoreEncoderExit, AmrGp3EncoderExit, (p->state));
313 return result;
314 }
315
316 #else
317
318 #define write_samples NULL
319 #define stopwrite NULL
320
321 #endif /* defined(AMR_GP3) || AMR_OPENCORE_ENABLE_ENCODE */
322
323 sox_format_handler_t const * AMR_FORMAT_FN(void);
AMR_FORMAT_FN(void)324 sox_format_handler_t const * AMR_FORMAT_FN(void)
325 {
326 static char const * const names[] = {AMR_NAMES, NULL};
327 static sox_rate_t const write_rates[] = {AMR_RATE, 0};
328 static unsigned const write_encodings[] = {AMR_ENCODING, 0, 0};
329 static sox_format_handler_t handler = {
330 SOX_LIB_VERSION_CODE,
331 AMR_DESC,
332 names, SOX_FILE_MONO,
333 startread, read_samples, stopread,
334 startwrite, write_samples, stopwrite,
335 NULL, write_encodings, write_rates, sizeof(priv_t)
336 };
337 return &handler;
338 }
339