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_write3(sox_format_t * ft, unsigned u3);
187 int lsx_writeb(sox_format_t * ft, unsigned ub);
188 int lsx_writedf(sox_format_t * ft, double d);
189 int lsx_writedw(sox_format_t * ft, unsigned udw);
190 int lsx_writeqw(sox_format_t * ft, uint64_t uqw);
191 int lsx_writef(sox_format_t * ft, double f);
192 int lsx_writew(sox_format_t * ft, unsigned uw);
193 
194 int lsx_writesb(sox_format_t * ft, signed);
195 int lsx_writesw(sox_format_t * ft, signed);
196 
197 int lsx_eof(sox_format_t * ft);
198 int lsx_error(sox_format_t * ft);
199 int lsx_flush(sox_format_t * ft);
200 int lsx_seeki(sox_format_t * ft, off_t offset, int whence);
201 int lsx_unreadb(sox_format_t * ft, unsigned ub);
202 /* uint64_t lsx_filelength(sox_format_t * ft); Temporarily Moved to sox.h. */
203 off_t lsx_tell(sox_format_t * ft);
204 void lsx_clearerr(sox_format_t * ft);
205 void lsx_rewind(sox_format_t * ft);
206 
207 int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample);
208 
209 void lsx_fail_errno(sox_format_t *, int, const char *, ...)
210 #ifdef __GNUC__
211 __attribute__ ((format (printf, 3, 4)));
212 #else
213 ;
214 #endif
215 
216 typedef struct sox_formats_globals { /* Global parameters (for formats) */
217   sox_globals_t * global_info;
218 } sox_formats_globals;
219 
220 
221 
222 /*------------------------------ File Handlers -------------------------------*/
223 
224 int lsx_check_read_params(sox_format_t * ft, unsigned channels,
225     sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
226     uint64_t num_samples, sox_bool check_length);
227 #define LSX_FORMAT_HANDLER(name) \
228 sox_format_handler_t const * lsx_##name##_format_fn(void); \
229 sox_format_handler_t const * lsx_##name##_format_fn(void)
230 #define div_bits(size, bits) ((uint64_t)(size) * 8 / bits)
231 
232 /* Raw I/O */
233 int lsx_rawstartread(sox_format_t * ft);
234 size_t lsx_rawread(sox_format_t * ft, sox_sample_t *buf, size_t nsamp);
235 int lsx_rawstopread(sox_format_t * ft);
236 int lsx_rawstartwrite(sox_format_t * ft);
237 size_t lsx_rawwrite(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp);
238 int lsx_rawseek(sox_format_t * ft, uint64_t offset);
239 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);
240 #define lsx_rawstartread(ft) lsx_rawstart(ft, sox_false, sox_false, sox_false, SOX_ENCODING_UNKNOWN, 0)
241 #define lsx_rawstartwrite lsx_rawstartread
242 #define lsx_rawstopread NULL
243 #define lsx_rawstopwrite NULL
244 
245 extern sox_format_handler_t const * lsx_sndfile_format_fn(void);
246 
247 char * lsx_cat_comments(sox_comments_t comments);
248 
249 /*--------------------------------- Effects ----------------------------------*/
250 
251 int lsx_flow_copy(sox_effect_t * effp, const sox_sample_t * ibuf,
252     sox_sample_t * obuf, size_t * isamp, size_t * osamp);
253 int lsx_usage(sox_effect_t * effp);
254 char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n);
255 #define EFFECT(f) extern sox_effect_handler_t const * lsx_##f##_effect_fn(void);
256 #include "effects.h"
257 #undef EFFECT
258 
259 #define NUMERIC_PARAMETER(name, min, max) { \
260   char * end_ptr; \
261   double d; \
262   if (argc == 0) break; \
263   d = strtod(*argv, &end_ptr); \
264   if (end_ptr != *argv) { \
265     if (d < min || d > max || *end_ptr != '\0') {\
266       lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
267       return lsx_usage(effp); \
268     } \
269     p->name = d; \
270     --argc, ++argv; \
271   } \
272 }
273 
274 #define TEXTUAL_PARAMETER(name, enum_table) { \
275   lsx_enum_item const * e; \
276   if (argc == 0) break; \
277   e = lsx_find_enum_text(*argv, enum_table, 0); \
278   if (e != NULL) { \
279     p->name = e->value; \
280     --argc, ++argv; \
281   } \
282 }
283 
284 #define GETOPT_LOCAL_NUMERIC(state, ch, name, min, max) case ch:{ \
285   char * end_ptr; \
286   double d = strtod(state.arg, &end_ptr); \
287   if (end_ptr == state.arg || d < min || d > max || *end_ptr != '\0') {\
288     lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
289     return lsx_usage(effp); \
290   } \
291   name = d; \
292   break; \
293 }
294 #define GETOPT_NUMERIC(state, ch, name, min, max) GETOPT_LOCAL_NUMERIC(state, ch, p->name, min, max)
295 
296 int lsx_effect_set_imin(sox_effect_t * effp, size_t imin);
297 
298 int lsx_effects_init(void);
299 int lsx_effects_quit(void);
300 
301 /*--------------------------------- Dynamic Library ----------------------------------*/
302 
303 #if defined(HAVE_WIN32_LTDL_H)
304     #include "win32-ltdl.h"
305     #define HAVE_LIBLTDL 1
306     typedef lt_dlhandle lsx_dlhandle;
307 #elif defined(HAVE_LIBLTDL)
308     #include <ltdl.h>
309     typedef lt_dlhandle lsx_dlhandle;
310 #else
311     struct lsx_dlhandle_tag;
312     typedef struct lsx_dlhandle_tag *lsx_dlhandle;
313 #endif
314 
315 typedef void (*lsx_dlptr)(void);
316 
317 typedef struct lsx_dlfunction_info
318 {
319     const char* name;
320     lsx_dlptr static_func;
321     lsx_dlptr stub_func;
322 } lsx_dlfunction_info;
323 
324 int lsx_open_dllibrary(
325     int show_error_on_failure,
326     const char* library_description,
327     const char * const library_names[],
328     const lsx_dlfunction_info func_infos[],
329     lsx_dlptr selected_funcs[],
330     lsx_dlhandle* pdl);
331 
332 void lsx_close_dllibrary(
333     lsx_dlhandle dl);
334 
335 #define LSX_DLENTRIES_APPLY__(entries, f, x) entries(f, x)
336 
337 #define LSX_DLENTRY_TO_PTR__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
338     func_return (*func_ptr) func_args;
339 
340 #define LSX_DLENTRIES_TO_FUNCTIONS__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
341     func_return func_name func_args;
342 
343 /* LSX_DLENTRIES_TO_PTRS: Given an ENTRIES macro and the name of the dlhandle
344    variable, declares the corresponding function pointer variables and the
345    dlhandle variable. */
346 #define LSX_DLENTRIES_TO_PTRS(entries, dlhandle) \
347     LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRY_TO_PTR__, 0) \
348     lsx_dlhandle dlhandle
349 
350 /* LSX_DLENTRIES_TO_FUNCTIONS: Given an ENTRIES macro, declares the corresponding
351    functions. */
352 #define LSX_DLENTRIES_TO_FUNCTIONS(entries) \
353     LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRIES_TO_FUNCTIONS__, 0)
354 
355 #define LSX_DLLIBRARY_OPEN1__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
356     { #func_name, (lsx_dlptr)(static_func), (lsx_dlptr)(stub_func) },
357 
358 #define LSX_DLLIBRARY_OPEN2__(ptr_container, func_return, func_name, func_args, static_func, stub_func, func_ptr) \
359     (ptr_container)->func_ptr = (func_return (*)func_args)lsx_dlfunction_open_library_funcs[lsx_dlfunction_open_library_index++];
360 
361 /* LSX_DLLIBRARY_OPEN: Input an ENTRIES macro, the library's description,
362    a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }),
363    the name of the dlhandle variable, the name of the structure that contains
364    the function pointer and dlhandle variables, and the name of the variable in
365    which the result of the lsx_open_dllibrary call should be stored. This will
366    call lsx_open_dllibrary and copy the resulting function pointers into the
367    structure members. If the library cannot be opened, show a failure message. */
368 #define LSX_DLLIBRARY_OPEN(ptr_container, dlhandle, entries, library_description, library_names, return_var) \
369     LSX_DLLIBRARY_TRYOPEN(1, ptr_container, dlhandle, entries, library_description, library_names, return_var)
370 
371 /* LSX_DLLIBRARY_TRYOPEN: Input an ENTRIES macro, the library's description,
372    a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }),
373    the name of the dlhandle variable, the name of the structure that contains
374    the function pointer and dlhandle variables, and the name of the variable in
375    which the result of the lsx_open_dllibrary call should be stored. This will
376    call lsx_open_dllibrary and copy the resulting function pointers into the
377    structure members. If the library cannot be opened, show a report or a failure
378    message, depending on whether error_on_failure is non-zero. */
379 #define LSX_DLLIBRARY_TRYOPEN(error_on_failure, ptr_container, dlhandle, entries, library_description, library_names, return_var) \
380     do { \
381       lsx_dlfunction_info lsx_dlfunction_open_library_infos[] = { \
382         LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN1__, 0) \
383         {NULL,NULL,NULL} }; \
384       int lsx_dlfunction_open_library_index = 0; \
385       lsx_dlptr lsx_dlfunction_open_library_funcs[sizeof(lsx_dlfunction_open_library_infos)/sizeof(lsx_dlfunction_open_library_infos[0])]; \
386       (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); \
387       LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN2__, ptr_container) \
388     } while(0)
389 
390 #define LSX_DLLIBRARY_CLOSE(ptr_container, dlhandle) \
391     lsx_close_dllibrary((ptr_container)->dlhandle)
392 
393   /* LSX_DLENTRY_STATIC: For use in creating an ENTRIES macro. func is
394      expected to be available at link time. If not present, link will fail. */
395 #define LSX_DLENTRY_STATIC(f,x, ret, func, args)  f(x, ret, func, args, func, NULL, func)
396 
397   /* LSX_DLENTRY_DYNAMIC: For use in creating an ENTRIES macro. func need
398      not be available at link time (and if present, the link time version will
399      not be used). func will be loaded via dlsym. If this function is not
400      found in the shared library, the shared library will not be used. */
401 #define LSX_DLENTRY_DYNAMIC(f,x, ret, func, args) f(x, ret, func, args, NULL, NULL, func)
402 
403   /* LSX_DLENTRY_STUB: For use in creating an ENTRIES macro. func need not
404      be available at link time (and if present, the link time version will not
405      be used). If using DL_LAME, the func may be loaded via dlopen/dlsym, but
406      if not found, the shared library will still be used if all of the
407      non-stub functions are found. If the function is not found via dlsym (or
408      if we are not loading any shared libraries), the stub will be used. This
409      assumes that the name of the stub function is the name of the function +
410      "_stub". */
411 #define LSX_DLENTRY_STUB(f,x, ret, func, args)    f(x, ret, func, args, NULL, func##_stub, func)
412 
413   /* LSX_DLFUNC_IS_STUB: returns true if the named function is a do-nothing
414      stub. Assumes that the name of the stub function is the name of the
415      function + "_stub". */
416 #define LSX_DLFUNC_IS_STUB(ptr_container, func) ((ptr_container)->func == func##_stub)
417 
418 #endif
419