1 /* libSoX Internal header
2  *
3  *   This file is meant for libSoX internal use only
4  *
5  * Copyright 2001-2012 Chris Bagwell and SoX Contributors
6  *
7  * This source code is freely redistributable and may be used for
8  * any purpose.  This copyright notice must be maintained.
9  * Chris Bagwell And SoX Contributors are not responsible for
10  * the consequences of using this software.
11  */
12 
13 #ifndef SOX_I_H
14 #define SOX_I_H
15 
16 #include "soxomp.h"  /* Note: soxomp.h includes soxconfig.h */
17 #include "sox.h"
18 
19 #if defined HAVE_FMEMOPEN
20 #define _GNU_SOURCE
21 #endif
22 
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 #include "util.h"
28 
29 #if defined(LSX_EFF_ALIAS)
30 #undef lsx_debug
31 #undef lsx_fail
32 #undef lsx_report
33 #undef lsx_warn
34 #define lsx_debug sox_globals.subsystem=effp->handler.name,lsx_debug_impl
35 #define lsx_fail sox_globals.subsystem=effp->handler.name,lsx_fail_impl
36 #define lsx_report sox_globals.subsystem=effp->handler.name,lsx_report_impl
37 #define lsx_warn sox_globals.subsystem=effp->handler.name,lsx_warn_impl
38 #endif
39 
40 #define RANQD1 ranqd1(sox_globals.ranqd1)
41 #define DRANQD1 dranqd1(sox_globals.ranqd1)
42 
43 typedef enum {SOX_SHORT, SOX_INT, SOX_FLOAT, SOX_DOUBLE} sox_data_t;
44 typedef enum {SOX_WAVE_SINE, SOX_WAVE_TRIANGLE} lsx_wave_t;
45 lsx_enum_item const * lsx_get_wave_enum(void);
46 
47 /* Define fseeko and ftello for platforms lacking them */
48 #ifndef HAVE_FSEEKO
49 #define fseeko fseek
50 #define ftello ftell
51 #endif
52 
53 #ifdef _FILE_OFFSET_BITS
54 assert_static(sizeof(off_t) == _FILE_OFFSET_BITS >> 3, OFF_T_BUILD_PROBLEM);
55 #endif
56 
57 FILE * lsx_tmpfile(void);
58 
59 void lsx_debug_more_impl(char const * fmt, ...) LSX_PRINTF12;
60 void lsx_debug_most_impl(char const * fmt, ...) LSX_PRINTF12;
61 
62 #define lsx_debug_more sox_get_globals()->subsystem=__FILE__,lsx_debug_more_impl
63 #define lsx_debug_most sox_get_globals()->subsystem=__FILE__,lsx_debug_most_impl
64 
65 /* Digitise one cycle of a wave and store it as
66  * a table of samples of a specified data-type.
67  */
68 void lsx_generate_wave_table(
69     lsx_wave_t wave_type,
70     sox_data_t data_type,
71     void * table,       /* Really of type indicated by data_type. */
72     size_t table_size,  /* Number of points on the x-axis. */
73     double min,         /* Minimum value on the y-axis. (e.g. -1) */
74     double max,         /* Maximum value on the y-axis. (e.g. +1) */
75     double phase);      /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */
76 char const * lsx_parsesamples(sox_rate_t rate, const char *str, uint64_t *samples, int def);
77 char const * lsx_parseposition(sox_rate_t rate, const char *str, uint64_t *samples, uint64_t latest, uint64_t end, int def);
78 int lsx_parse_note(char const * text, char * * end_ptr);
79 double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key);
80 #define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX)
81 FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename, sox_bool text_mode);
82 
83 void lsx_prepare_spline3(double const * x, double const * y, int n,
84     double start_1d, double end_1d, double * y_2d);
85 double lsx_spline3(double const * x, double const * y, double const * y_2d,
86     int n, double x1);
87 
88 double lsx_bessel_I_0(double x);
89 int lsx_set_dft_length(int num_taps);
90 void init_fft_cache(void);
91 void clear_fft_cache(void);
92 #define lsx_is_power_of_2(x) !(x < 2 || (x & (x - 1)))
93 void lsx_safe_rdft(int len, int type, double * d);
94 void lsx_safe_cdft(int len, int type, double * d);
95 void lsx_power_spectrum(int n, double const * in, double * out);
96 void lsx_power_spectrum_f(int n, float const * in, float * out);
97 void lsx_apply_hann_f(float h[], const int num_points);
98 void lsx_apply_hann(double h[], const int num_points);
99 void lsx_apply_hamming(double h[], const int num_points);
100 void lsx_apply_bartlett(double h[], const int num_points);
101 void lsx_apply_blackman(double h[], const int num_points, double alpha);
102 void lsx_apply_blackman_nutall(double h[], const int num_points);
103 double lsx_kaiser_beta(double att, double tr_bw);
104 void lsx_apply_kaiser(double h[], const int num_points, double beta);
105 void lsx_apply_dolph(double h[], const int num_points, double att);
106 double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho,
107     double scale, sox_bool dc_norm);
108 void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps);
109 double * lsx_design_lpf(
110     double Fp,      /* End of pass-band */
111     double Fs,      /* Start of stop-band */
112     double Fn,      /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */
113     double att,     /* Stop-band attenuation in dB */
114     int * num_taps, /* 0: value will be estimated */
115     int k,          /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */
116     double beta);   /* <0: value will be estimated */
117 void lsx_fir_to_phase(double * * h, int * len,
118     int * post_len, double phase0);
119 void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2);
120 void lsx_save_samples(sox_sample_t * const dest, double const * const src,
121     size_t const n, sox_uint64_t * const clips);
122 void lsx_load_samples(double * const dest, sox_sample_t const * const src,
123     size_t const n);
124 
125 #ifdef HAVE_BYTESWAP_H
126 #include <byteswap.h>
127 #define lsx_swapw(x) bswap_16(x)
128 #define lsx_swapdw(x) bswap_32(x)
129 #elif defined(_MSC_VER)
130 #define lsx_swapw(x) _byteswap_ushort(x)
131 #define lsx_swapdw(x) _byteswap_ulong(x)
132 #else
133 #define lsx_swapw(uw) (((uw >> 8) | (uw << 8)) & 0xffff)
134 #define lsx_swapdw(udw) ((udw >> 24) | ((udw >> 8) & 0xff00) | ((udw << 8) & 0xff0000) | (udw << 24))
135 #endif
136 
137 
138 
139 /*------------------------ Implemented in libsoxio.c -------------------------*/
140 
141 /* Read and write basic data types from "ft" stream. */
142 size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len);
143 int lsx_skipbytes(sox_format_t * ft, size_t n);
144 int lsx_padbytes(sox_format_t * ft, size_t n);
145 size_t lsx_writebuf(sox_format_t * ft, void const *buf, size_t len);
146 int lsx_reads(sox_format_t * ft, char *c, size_t len);
147 int lsx_writes(sox_format_t * ft, char const * c);
148 void lsx_set_signal_defaults(sox_format_t * ft);
149 #define lsx_writechars(ft, chars, len) (lsx_writebuf(ft, chars, len) == len? SOX_SUCCESS : SOX_EOF)
150 
151 size_t lsx_read_3_buf(sox_format_t * ft, sox_uint24_t *buf, size_t len);
152 size_t lsx_read_b_buf(sox_format_t * ft, uint8_t *buf, size_t len);
153 size_t lsx_read_df_buf(sox_format_t * ft, double *buf, size_t len);
154 size_t lsx_read_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len);
155 size_t lsx_read_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len);
156 size_t lsx_read_f_buf(sox_format_t * ft, float *buf, size_t len);
157 size_t lsx_read_w_buf(sox_format_t * ft, uint16_t *buf, size_t len);
158 
159 size_t lsx_write_3_buf(sox_format_t * ft, sox_uint24_t *buf, size_t len);
160 size_t lsx_write_b_buf(sox_format_t * ft, uint8_t *buf, size_t len);
161 size_t lsx_write_df_buf(sox_format_t * ft, double *buf, size_t len);
162 size_t lsx_write_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len);
163 size_t lsx_write_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len);
164 size_t lsx_write_f_buf(sox_format_t * ft, float *buf, size_t len);
165 size_t lsx_write_w_buf(sox_format_t * ft, uint16_t *buf, size_t len);
166 
167 int lsx_read3(sox_format_t * ft, sox_uint24_t * u3);
168 int lsx_readb(sox_format_t * ft, uint8_t * ub);
169 int lsx_readchars(sox_format_t * ft, char * chars, size_t len);
170 int lsx_readdf(sox_format_t * ft, double * d);
171 int lsx_readdw(sox_format_t * ft, uint32_t * udw);
172 int lsx_readqw(sox_format_t * ft, uint64_t * udw);
173 int lsx_readf(sox_format_t * ft, float * f);
174 int lsx_readw(sox_format_t * ft, uint16_t * uw);
175 
176 #if 1 /* FIXME: use defines */
lsx_readsb(sox_format_t * ft,int8_t * sb)177 UNUSED static int lsx_readsb(sox_format_t * ft, int8_t * sb)
178 {return lsx_readb(ft, (uint8_t *)sb);}
lsx_readsw(sox_format_t * ft,int16_t * sw)179 UNUSED static int lsx_readsw(sox_format_t * ft, int16_t * sw)
180 {return lsx_readw(ft, (uint16_t *)sw);}
181 #else
182 #define lsx_readsb(ft, sb) lsx_readb(ft, (uint8_t *)sb)
183 #define lsx_readsw(ft, sw) lsx_readb(ft, (uint16_t *)sw)
184 #endif
185 
186 int lsx_read_fields(sox_format_t *ft, uint32_t *len,  const char *spec, ...);
187 
188 int lsx_write3(sox_format_t * ft, unsigned u3);
189 int lsx_writeb(sox_format_t * ft, unsigned ub);
190 int lsx_writedf(sox_format_t * ft, double d);
191 int lsx_writedw(sox_format_t * ft, unsigned udw);
192 int lsx_writeqw(sox_format_t * ft, uint64_t uqw);
193 int lsx_writef(sox_format_t * ft, double f);
194 int lsx_writew(sox_format_t * ft, unsigned uw);
195 
196 int lsx_writesb(sox_format_t * ft, signed);
197 int lsx_writesw(sox_format_t * ft, signed);
198 
199 int lsx_eof(sox_format_t * ft);
200 int lsx_error(sox_format_t * ft);
201 int lsx_flush(sox_format_t * ft);
202 int lsx_seeki(sox_format_t * ft, off_t offset, int whence);
203 int lsx_unreadb(sox_format_t * ft, unsigned ub);
204 /* uint64_t lsx_filelength(sox_format_t * ft); Temporarily Moved to sox.h. */
205 off_t lsx_tell(sox_format_t * ft);
206 void lsx_clearerr(sox_format_t * ft);
207 void lsx_rewind(sox_format_t * ft);
208 
209 int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample);
210 
211 void lsx_fail_errno(sox_format_t *, int, const char *, ...)
212 #ifdef __GNUC__
213 __attribute__ ((format (printf, 3, 4)));
214 #else
215 ;
216 #endif
217 
218 typedef struct sox_formats_globals { /* Global parameters (for formats) */
219   sox_globals_t * global_info;
220 } sox_formats_globals;
221 
222 
223 
224 /*------------------------------ File Handlers -------------------------------*/
225 
226 int lsx_check_read_params(sox_format_t * ft, unsigned channels,
227     sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
228     uint64_t num_samples, sox_bool check_length);
229 #define LSX_FORMAT_HANDLER(name) \
230 sox_format_handler_t const * lsx_##name##_format_fn(void); \
231 sox_format_handler_t const * lsx_##name##_format_fn(void)
232 #define div_bits(size, bits) ((uint64_t)(size) * 8 / bits)
233 
234 /* Raw I/O */
235 int lsx_rawstartread(sox_format_t * ft);
236 size_t lsx_rawread(sox_format_t * ft, sox_sample_t *buf, size_t nsamp);
237 int lsx_rawstopread(sox_format_t * ft);
238 int lsx_rawstartwrite(sox_format_t * ft);
239 size_t lsx_rawwrite(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp);
240 int lsx_rawseek(sox_format_t * ft, uint64_t offset);
241 int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, sox_bool default_channels, sox_bool default_length, sox_encoding_t encoding, unsigned bits_per_sample);
242 #define lsx_rawstartread(ft) lsx_rawstart(ft, sox_false, sox_false, sox_false, SOX_ENCODING_UNKNOWN, 0)
243 #define lsx_rawstartwrite lsx_rawstartread
244 #define lsx_rawstopread NULL
245 #define lsx_rawstopwrite NULL
246 
247 extern sox_format_handler_t const * lsx_sndfile_format_fn(void);
248 
249 char * lsx_cat_comments(sox_comments_t comments);
250 
251 /*--------------------------------- Effects ----------------------------------*/
252 
253 int lsx_flow_copy(sox_effect_t * effp, const sox_sample_t * ibuf,
254     sox_sample_t * obuf, size_t * isamp, size_t * osamp);
255 int lsx_usage(sox_effect_t * effp);
256 char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n);
257 #define EFFECT(f) extern sox_effect_handler_t const * lsx_##f##_effect_fn(void);
258 #include "effects.h"
259 #undef EFFECT
260 
261 #define NUMERIC_PARAMETER(name, min, max) { \
262   char * end_ptr; \
263   double d; \
264   if (argc == 0) break; \
265   d = strtod(*argv, &end_ptr); \
266   if (end_ptr != *argv) { \
267     if (d < min || d > max || *end_ptr != '\0') {\
268       lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
269       return lsx_usage(effp); \
270     } \
271     p->name = d; \
272     --argc, ++argv; \
273   } \
274 }
275 
276 #define TEXTUAL_PARAMETER(name, enum_table) { \
277   lsx_enum_item const * e; \
278   if (argc == 0) break; \
279   e = lsx_find_enum_text(*argv, enum_table, 0); \
280   if (e != NULL) { \
281     p->name = e->value; \
282     --argc, ++argv; \
283   } \
284 }
285 
286 #define GETOPT_LOCAL_NUMERIC(state, ch, name, min, max) case ch:{ \
287   char * end_ptr; \
288   double d = strtod(state.arg, &end_ptr); \
289   if (end_ptr == state.arg || d < min || d > max || *end_ptr != '\0') {\
290     lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
291     return lsx_usage(effp); \
292   } \
293   name = d; \
294   break; \
295 }
296 #define GETOPT_NUMERIC(state, ch, name, min, max) GETOPT_LOCAL_NUMERIC(state, ch, p->name, min, max)
297 
298 int lsx_effect_set_imin(sox_effect_t * effp, size_t imin);
299 
300 int lsx_effects_init(void);
301 int lsx_effects_quit(void);
302 
303 /*--------------------------------- Dynamic Library ----------------------------------*/
304 
305 #if defined(HAVE_LIBLTDL)
306     #include <ltdl.h>
307     typedef lt_dlhandle lsx_dlhandle;
308 #else
309     struct lsx_dlhandle_tag;
310     typedef struct lsx_dlhandle_tag *lsx_dlhandle;
311 #endif
312 
313 typedef void (*lsx_dlptr)(void);
314 
315 typedef struct lsx_dlfunction_info
316 {
317     const char* name;
318     lsx_dlptr static_func;
319     lsx_dlptr stub_func;
320 } lsx_dlfunction_info;
321 
322 int lsx_open_dllibrary(
323     int show_error_on_failure,
324     const char* library_description,
325     const char * const library_names[],
326     const lsx_dlfunction_info func_infos[],
327     lsx_dlptr selected_funcs[],
328     lsx_dlhandle* pdl);
329 
330 void lsx_close_dllibrary(
331     lsx_dlhandle dl);
332 
333 #define LSX_DLENTRIES_APPLY__(entries, f, x) entries(f, x)
334 
335 #define LSX_DLENTRY_TO_PTR__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
336     func_return (*func_ptr) func_args;
337 
338 #define LSX_DLENTRIES_TO_FUNCTIONS__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
339     func_return func_name func_args;
340 
341 /* LSX_DLENTRIES_TO_PTRS: Given an ENTRIES macro and the name of the dlhandle
342    variable, declares the corresponding function pointer variables and the
343    dlhandle variable. */
344 #define LSX_DLENTRIES_TO_PTRS(entries, dlhandle) \
345     LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRY_TO_PTR__, 0) \
346     lsx_dlhandle dlhandle
347 
348 /* LSX_DLENTRIES_TO_FUNCTIONS: Given an ENTRIES macro, declares the corresponding
349    functions. */
350 #define LSX_DLENTRIES_TO_FUNCTIONS(entries) \
351     LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRIES_TO_FUNCTIONS__, 0)
352 
353 #define LSX_DLLIBRARY_OPEN1__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
354     { #func_name, (lsx_dlptr)(static_func), (lsx_dlptr)(stub_func) },
355 
356 #define LSX_DLLIBRARY_OPEN2__(ptr_container, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
357     (ptr_container)->func_ptr = (func_return (*)func_args)lsx_dlfunction_open_library_funcs[lsx_dlfunction_open_library_index++];
358 
359 /* LSX_DLLIBRARY_OPEN: Input an ENTRIES macro, the library's description,
360    a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }),
361    the name of the dlhandle variable, the name of the structure that contains
362    the function pointer and dlhandle variables, and the name of the variable in
363    which the result of the lsx_open_dllibrary call should be stored. This will
364    call lsx_open_dllibrary and copy the resulting function pointers into the
365    structure members. If the library cannot be opened, show a failure message. */
366 #define LSX_DLLIBRARY_OPEN(ptr_container, dlhandle, entries, library_description, library_names, return_var) \
367     LSX_DLLIBRARY_TRYOPEN(1, ptr_container, dlhandle, entries, library_description, library_names, return_var)
368 
369 /* LSX_DLLIBRARY_TRYOPEN: Input an ENTRIES macro, the library's description,
370    a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }),
371    the name of the dlhandle variable, the name of the structure that contains
372    the function pointer and dlhandle variables, and the name of the variable in
373    which the result of the lsx_open_dllibrary call should be stored. This will
374    call lsx_open_dllibrary and copy the resulting function pointers into the
375    structure members. If the library cannot be opened, show a report or a failure
376    message, depending on whether error_on_failure is non-zero. */
377 #define LSX_DLLIBRARY_TRYOPEN(error_on_failure, ptr_container, dlhandle, entries, library_description, library_names, return_var) \
378     do { \
379       lsx_dlfunction_info lsx_dlfunction_open_library_infos[] = { \
380         LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN1__, 0) \
381         {NULL,NULL,NULL} }; \
382       int lsx_dlfunction_open_library_index = 0; \
383       lsx_dlptr lsx_dlfunction_open_library_funcs[sizeof(lsx_dlfunction_open_library_infos)/sizeof(lsx_dlfunction_open_library_infos[0])]; \
384       (return_var) = lsx_open_dllibrary((error_on_failure), (library_description), (library_names), lsx_dlfunction_open_library_infos, lsx_dlfunction_open_library_funcs, &(ptr_container)->dlhandle); \
385       LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN2__, ptr_container) \
386     } while(0)
387 
388 #define LSX_DLLIBRARY_CLOSE(ptr_container, dlhandle) \
389     lsx_close_dllibrary((ptr_container)->dlhandle)
390 
391   /* LSX_DLENTRY_STATIC: For use in creating an ENTRIES macro. func is
392      expected to be available at link time. If not present, link will fail. */
393 #define LSX_DLENTRY_STATIC(f,x, ret, func, args)  f(x, ret, func, args, func, NULL, func)
394 
395   /* LSX_DLENTRY_DYNAMIC: For use in creating an ENTRIES macro. func need
396      not be available at link time (and if present, the link time version will
397      not be used). func will be loaded via dlsym. If this function is not
398      found in the shared library, the shared library will not be used. */
399 #define LSX_DLENTRY_DYNAMIC(f,x, ret, func, args) f(x, ret, func, args, NULL, NULL, func)
400 
401   /* LSX_DLENTRY_STUB: For use in creating an ENTRIES macro. func need not
402      be available at link time (and if present, the link time version will not
403      be used). If using DL_LAME, the func may be loaded via dlopen/dlsym, but
404      if not found, the shared library will still be used if all of the
405      non-stub functions are found. If the function is not found via dlsym (or
406      if we are not loading any shared libraries), the stub will be used. This
407      assumes that the name of the stub function is the name of the function +
408      "_stub". */
409 #define LSX_DLENTRY_STUB(f,x, ret, func, args)    f(x, ret, func, args, NULL, func##_stub, func)
410 
411   /* LSX_DLFUNC_IS_STUB: returns true if the named function is a do-nothing
412      stub. Assumes that the name of the stub function is the name of the
413      function + "_stub". */
414 #define LSX_DLFUNC_IS_STUB(ptr_container, func) ((ptr_container)->func == func##_stub)
415 
416 #endif
417