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