Intégration de libsoxr pour le rééchantillonnage audio
This commit is contained in:
23
C/share/doc/libsoxr/LICENCE
Normal file
23
C/share/doc/libsoxr/LICENCE
Normal file
@@ -0,0 +1,23 @@
|
||||
SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Notes
|
||||
|
||||
1. Re software in the `examples' directory: works that are not resampling
|
||||
examples but are based on the given examples -- for example, applications using
|
||||
the library -- shall not be considered to be derivative works of the examples.
|
||||
|
||||
2. If building with pffft.c, see the licence embedded in that file.
|
||||
46
C/share/doc/libsoxr/NEWS
Normal file
46
C/share/doc/libsoxr/NEWS
Normal file
@@ -0,0 +1,46 @@
|
||||
Version 0.1.3 (2018-02-24)
|
||||
* SIMD enhancements: SSE, AVX, Neon.
|
||||
* Improve support for clang, ARM, and cross-compilation.
|
||||
* Provide env. var. override of runtime parameters.
|
||||
* Build fix re cmake variables AVCODEC_INCLUDE_DIRS & AVUTIL_INCLUDE_DIRS.
|
||||
* Build options WITH_SINGLE_PRECISION, WITH_DOUBLE_PRECISION & WITH_SIMD have
|
||||
been removed; replacement options are detailed in INSTALL, `Resampling
|
||||
engines'.
|
||||
|
||||
Version 0.1.2 (2015-09-05)
|
||||
* Fix conversion failure when I/O types differ but I/O rates don't.
|
||||
* Fix #defines for interpolation order selection.
|
||||
* Fix ineffectual SOXR_MINIMUM_PHASE and SOXR_INTERMEDIATE_PHASE in
|
||||
soxr_quality_spec recipe.
|
||||
* Fix soxr_delay() returning a negative number after end-of-input has been
|
||||
indicated.
|
||||
* Fix crash when using soxr_process() after calling soxr_clear().
|
||||
* Be more POSIX compliant w.r.t. errno in the examples; fixes erroneous
|
||||
reporting of errors on FreeBSD.
|
||||
* Quality improvement for variable-rate.
|
||||
* Various fixes/improvements to build/tests/documentation.
|
||||
|
||||
Version 0.1.1 (2013-03-03)
|
||||
* Minor fixes/improvements to build/tests.
|
||||
* Fix crash (e.g. with k3b) when null error pointer passed to src_create (lsr
|
||||
bindings only).
|
||||
* Fix broken resampling in many cases with SIMD and anti_aliasing_pc < 100.
|
||||
* For clarity, renamed and slightly changed usage of three parameters in
|
||||
soxr_quality_spec_t (ABI compatible, API incompatible). An application not
|
||||
setting these parameters directly need make no change; otherwise, changes
|
||||
should be made per the following example (as shown, compatibility with both
|
||||
old/new APIs is maintained). See also the comments on these parameters in
|
||||
soxr.h. N.B. ABI compatibility with the 0.1.0 API may be removed in a
|
||||
future release.
|
||||
#if !defined SOXR_VERSION /* Deprecated, 0.1.0 API */
|
||||
q_spec.phase = minimum_phase? 0 : 50;
|
||||
q_spec.bw_pc = cutoff * 100;
|
||||
q_spec.anti_aliasing_pc = anti_aliasing * 100;
|
||||
#else /* 0.1.1 API */ Explanation:
|
||||
q_spec.phase_response = minimum_phase? 0 : 50; Renamed.
|
||||
q_spec.passband_end = cutoff; Renamed, no longer %.
|
||||
q_spec.stopband_begin = 2 - anti_aliasing; Renamed, no longer %, no
|
||||
#endif longer mirrored in Fs.
|
||||
|
||||
Version 0.1.0 (2013-01-19)
|
||||
* First public release.
|
||||
53
C/share/doc/libsoxr/README
Normal file
53
C/share/doc/libsoxr/README
Normal file
@@ -0,0 +1,53 @@
|
||||
SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||
|
||||
The SoX Resampler library `libsoxr' performs one-dimensional sample-rate
|
||||
conversion -- it may be used, for example, to resample PCM-encoded audio.
|
||||
For higher-dimensional resampling, such as for visual-image processing, you
|
||||
should look elsewhere.
|
||||
|
||||
It aims to give fast¹ and very high quality² results for any constant
|
||||
(rational or irrational) resampling ratio. Phase-response, preserved
|
||||
bandwidth, aliasing, and rejection level parameters are all configurable;
|
||||
alternatively, simple `preset' configurations may be selected. A
|
||||
variable-rate resampling mode of operation is also included.
|
||||
|
||||
The resampler is currently available either as part of `libsox' (the audio
|
||||
file-format and effect library), or stand-alone as `libsoxr' (this package).
|
||||
The interfaces to libsox and libsoxr are slightly different, with that of
|
||||
libsoxr designed specifically for resampling. An application requiring
|
||||
support for other effects, or for reading-from or writing-to audio files or
|
||||
devices, should use libsox (or other libraries such as libsndfile or
|
||||
libavformat).
|
||||
|
||||
Libsoxr provides a simple API that allows interfacing using the most
|
||||
commonly-used sample formats and buffering schemes: sample-formats may be
|
||||
either floating-point or integer, and multiple channels either interleaved
|
||||
or split in separate buffers. The API is documented in the header file
|
||||
`soxr.h', together with sample code found in the 'examples' directory.
|
||||
|
||||
For compatibility with the popular `libsamplerate' library, the header file
|
||||
`soxr-lsr.h' is provided and may be used as an alternative API.³ Note
|
||||
however, that libsoxr does not provide a full emulation of libsamplerate
|
||||
and that using this approach, only a sub-set of libsoxr's features are
|
||||
available.
|
||||
|
||||
The design was inspired by Laurent De Soras' paper `The Quest For The
|
||||
Perfect Resampler', http://ldesoras.free.fr/doc/articles/resampler-en.pdf;
|
||||
in essence, it combines Julius O. Smith's `Bandlimited Interpolation'
|
||||
technique (https://ccrma.stanford.edu/~jos/resample/resample.pdf) with FFT-
|
||||
based over-sampling.
|
||||
|
||||
Note that for real-time resampling, libsoxr may have a higher latency
|
||||
than non-FFT based resamplers. For example, when using the `High Quality'
|
||||
configuration to resample between 44100Hz and 48000Hz, the latency is
|
||||
around 1000 output samples, i.e. roughly 20ms (though passband and FFT-
|
||||
size configuration parameters may be used to reduce this figure).
|
||||
|
||||
For build and installation instructions, see the file `INSTALL'; for
|
||||
copyright and licensing information, see the file `LICENCE'.
|
||||
|
||||
For support and new versions, see https://soxr.sourceforge.net
|
||||
________
|
||||
¹ For example, multi-channel resampling can utilise multiple CPU-cores.
|
||||
² Bit-perfect within practical occupied-bandwidth limits.
|
||||
³ For details of that API, see http://www.mega-nerd.com/SRC/api.html.
|
||||
50
C/share/doc/libsoxr/examples/1-single-block.c
Normal file
50
C/share/doc/libsoxr/examples/1-single-block.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Example 1: `One-shot' resample a single block of data in memory.
|
||||
*
|
||||
* N.B. See example 2 for how to resample a stream (of blocks).
|
||||
*
|
||||
* Optional arguments are: INPUT-RATE OUTPUT-RATE
|
||||
*
|
||||
* With the default arguments, the output should produce lines similar to the
|
||||
* following:
|
||||
*
|
||||
* 0.00 0.71 1.00 0.71 -0.00 -0.71 -1.00 -0.71
|
||||
*
|
||||
* Gibbs effect may be seen at the ends of the resampled signal; this is because
|
||||
* unlike a `real-world' signal, the synthetic input signal is not band-limited.
|
||||
*/
|
||||
|
||||
#include <soxr.h>
|
||||
#include "examples-common.h"
|
||||
|
||||
const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */
|
||||
0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1,
|
||||
0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1};
|
||||
|
||||
int main(int argc, char const * arg[])
|
||||
{
|
||||
double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */
|
||||
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
|
||||
|
||||
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */
|
||||
float * out = malloc(sizeof(*out) * olen); /* Allocate output buffer. */
|
||||
size_t odone;
|
||||
|
||||
soxr_error_t error = soxr_oneshot(irate, orate, 1, /* Rates and # of chans. */
|
||||
in, AL(in), NULL, /* Input. */
|
||||
out, olen, &odone, /* Output. */
|
||||
NULL, NULL, NULL); /* Default configuration.*/
|
||||
|
||||
unsigned i = 0; /* Print out the resampled data, */
|
||||
while (i++ < odone)
|
||||
printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == odone]);
|
||||
printf("%-26s %s\n", arg[0], soxr_strerror(error)); /* and reported result. */
|
||||
|
||||
if (argc > 3) /* Library version check: */
|
||||
printf("runtime=%s API="SOXR_THIS_VERSION_STR"\n", soxr_version());
|
||||
|
||||
free(out); /* Tidy up. */
|
||||
return !!error;
|
||||
}
|
||||
40
C/share/doc/libsoxr/examples/1a-lsr.c
Normal file
40
C/share/doc/libsoxr/examples/1a-lsr.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Example 1a: Variant of example 1 using libsamplerate-like bindings. */
|
||||
|
||||
#include <soxr-lsr.h>
|
||||
#include "examples-common.h"
|
||||
|
||||
float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */
|
||||
0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1,
|
||||
0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1};
|
||||
|
||||
int main(int argc, char const * arg[])
|
||||
{
|
||||
double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */
|
||||
double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */
|
||||
|
||||
size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */
|
||||
float * out = (float *)malloc(sizeof(*out) * olen); /* Allocate output buf. */
|
||||
|
||||
int error, i = 0;
|
||||
SRC_DATA data;
|
||||
|
||||
data.data_in = in;
|
||||
data.data_out = out;
|
||||
data.input_frames = AL(in);
|
||||
data.output_frames = (int)olen;
|
||||
data.src_ratio = orate / irate;
|
||||
error = src_simple(&data, SRC_SINC_FASTEST, 1);
|
||||
|
||||
while (i++ < data.output_frames_gen) /* Print out the resampled data, */
|
||||
printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == data.output_frames_gen]);
|
||||
printf("%-26s %s\n", arg[0], src_strerror(error)); /* and reported result. */
|
||||
|
||||
if (argc > 3) /* Library version check: */
|
||||
printf("runtime=%s\n", src_get_version());
|
||||
|
||||
free(out); /* Tidy up. */
|
||||
return !!error;
|
||||
}
|
||||
78
C/share/doc/libsoxr/examples/2-stream.C
Normal file
78
C/share/doc/libsoxr/examples/2-stream.C
Normal file
@@ -0,0 +1,78 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Example 2: resample a raw, single-channel, floating-point data stream from
|
||||
* stdin to stdout.
|
||||
*
|
||||
* The application uses the single function `soxr_process' for both input and
|
||||
* output to/from the resampler; compared to the `input function' approach
|
||||
* (illustrated in example 3) this requires that the application implements
|
||||
* more logic, but one less function.
|
||||
*
|
||||
* Arguments are: INPUT-RATE OUTPUT-RATE
|
||||
*/
|
||||
|
||||
#include <soxr.h>
|
||||
#include "examples-common.h"
|
||||
|
||||
int main(int argc, char const * arg[])
|
||||
{
|
||||
double const irate = argc > 1? atof(arg[1]) : 96000.;
|
||||
double const orate = argc > 2? atof(arg[2]) : 44100.;
|
||||
|
||||
/* Allocate resampling input and output buffers in proportion to the input
|
||||
* and output rates: */
|
||||
#define buf_total_len 15000 /* In samples. */
|
||||
size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5);
|
||||
size_t const ilen = buf_total_len - olen;
|
||||
size_t const osize = sizeof(float), isize = osize;
|
||||
void * obuf = malloc(osize * olen);
|
||||
void * ibuf = malloc(isize * ilen);
|
||||
|
||||
size_t odone, written, need_input = 1;
|
||||
soxr_error_t error;
|
||||
|
||||
/* Create a stream resampler: */
|
||||
soxr_t soxr = soxr_create(
|
||||
irate, orate, 1, /* Input rate, output rate, # of channels. */
|
||||
&error, /* To report any error during creation. */
|
||||
NULL, NULL, NULL); /* Use configuration defaults.*/
|
||||
|
||||
if (!error) { /* If all is well, run the resampler: */
|
||||
USE_STD_STDIO;
|
||||
/* Resample in blocks: */
|
||||
do {
|
||||
size_t ilen1 = 0;
|
||||
|
||||
if (need_input) {
|
||||
|
||||
/* Read one block into the buffer, ready to be resampled: */
|
||||
ilen1 = fread(ibuf, isize, ilen, stdin);
|
||||
|
||||
if (!ilen1) { /* If the is no (more) input data available, */
|
||||
free(ibuf); /* set ibuf to NULL, to indicate end-of-input */
|
||||
ibuf = NULL; /* to the resampler. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy data from the input buffer into the resampler, and resample
|
||||
* to produce as much output as is possible to the given output buffer: */
|
||||
error = soxr_process(soxr, ibuf, ilen1, NULL, obuf, olen, &odone);
|
||||
|
||||
written = fwrite(obuf, osize, odone, stdout); /* Consume output.*/
|
||||
|
||||
/* If the actual amount of data output is less than that requested, and
|
||||
* we have not already reached the end of the input data, then supply some
|
||||
* more input next time round the loop: */
|
||||
need_input = odone < olen && ibuf;
|
||||
|
||||
} while (!error && (need_input || written));
|
||||
}
|
||||
/* Tidy up: */
|
||||
soxr_delete(soxr);
|
||||
free(obuf), free(ibuf);
|
||||
/* Diagnostics: */
|
||||
fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error),
|
||||
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error");
|
||||
return !!error;
|
||||
}
|
||||
114
C/share/doc/libsoxr/examples/3-options-input-fn.c
Normal file
114
C/share/doc/libsoxr/examples/3-options-input-fn.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Example 3: extends example 2 with multiple channels, multiple datatypes,
|
||||
* and other options.
|
||||
*
|
||||
* The application provides an input function, called on demand by libsoxr, in
|
||||
* response to calls to soxr_output(); compared to the `process' approach
|
||||
* (illustrated in example 2) this requires that the application implements
|
||||
* less logic, but one more function.
|
||||
*
|
||||
* The 11 arguments (which are optional, from last to first) are:
|
||||
* INPUT-RATE As example 2
|
||||
* OUTPUT-RATE Ditto
|
||||
* NUM-CHANNELS Number of interleaved channels
|
||||
* IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16
|
||||
* OUT-DATATYPE# Ditto; or 11 for un-dithered int16
|
||||
* Q-RECIPE Quality recipe (in hex) See soxr.h
|
||||
* Q-FLAGS Quality flags (in hex) See soxr.h
|
||||
* PASSBAND-END %
|
||||
* STOPBAND-BEGIN %
|
||||
* PHASE-RESPONSE [0,100]
|
||||
* USE-THREADS 1 to use multi-threading (where available)
|
||||
*/
|
||||
|
||||
#include <soxr.h>
|
||||
#include "examples-common.h"
|
||||
|
||||
typedef struct {void * ibuf; size_t isize;} input_context_t;
|
||||
|
||||
static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len)
|
||||
{
|
||||
/* Read one block into the buffer, ready to be input to the resampler: */
|
||||
len = fread(p->ibuf, p->isize, len, stdin); /* Actual len read may be less. */
|
||||
|
||||
/* Inform the resampler of the data's whereabouts (which could be anywhere, in
|
||||
* a freshly malloc'd buffer, for example): */
|
||||
*buf = (!len && ferror(stdin))? NULL : p->ibuf; /* NULL if error occurred. */
|
||||
|
||||
return len; /* # of samples per channel to input. */
|
||||
}
|
||||
|
||||
int main(int n, char const * arg[])
|
||||
{
|
||||
char const * const arg0 = n? --n, *arg++ : "", * engine = "";
|
||||
double const irate = n? --n, atof(*arg++) : 96000.;
|
||||
double const orate = n? --n, atof(*arg++) : 44100.;
|
||||
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
|
||||
soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
||||
unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
||||
unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ;
|
||||
unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0;
|
||||
double const passband_end = n? --n, atof(*arg++) : 0;
|
||||
double const stopband_begin = n? --n, atof(*arg++) : 0;
|
||||
double const phase_response = n? --n, atof(*arg++) : -1;
|
||||
int const use_threads = n? --n, atoi(*arg++) : 1;
|
||||
soxr_datatype_t const otype = ospec & 3;
|
||||
|
||||
soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags);
|
||||
soxr_io_spec_t io_spec = soxr_io_spec(itype, otype);
|
||||
soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads);
|
||||
|
||||
/* Allocate resampling input and output buffers in proportion to the input
|
||||
* and output rates: */
|
||||
#define buf_total_len 15000 /* In samples per channel. */
|
||||
size_t const osize = soxr_datatype_size(otype) * chans;
|
||||
size_t const isize = soxr_datatype_size(itype) * chans;
|
||||
size_t const olen0= (size_t)(orate * buf_total_len / (irate + orate) + .5);
|
||||
size_t const olen = min(max(olen0, 1), buf_total_len - 1);
|
||||
size_t const ilen = buf_total_len - olen;
|
||||
void * const obuf = malloc(osize * olen);
|
||||
void * const ibuf = malloc(isize * ilen);
|
||||
|
||||
input_context_t icontext;
|
||||
size_t odone, clips = 0;
|
||||
soxr_error_t error;
|
||||
soxr_t soxr;
|
||||
|
||||
/* Overrides (if given): */
|
||||
if (passband_end > 0) q_spec.passband_end = passband_end / 100;
|
||||
if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100;
|
||||
if (phase_response >=0) q_spec.phase_response = phase_response;
|
||||
io_spec.flags = ospec & ~7u;
|
||||
|
||||
/* Create a stream resampler: */
|
||||
soxr = soxr_create(
|
||||
irate, orate, chans, /* Input rate, output rate, # of channels. */
|
||||
&error, /* To report any error during creation. */
|
||||
&io_spec, &q_spec, &runtime_spec);
|
||||
|
||||
if (!error) { /* Register input_fn with the resampler: */
|
||||
icontext.ibuf = ibuf, icontext.isize = isize;
|
||||
error = soxr_set_input_fn(soxr, (soxr_input_fn_t)input_fn, &icontext, ilen);
|
||||
}
|
||||
|
||||
if (!error) { /* If all is well, run the resampler: */
|
||||
engine = soxr_engine(soxr);
|
||||
USE_STD_STDIO;
|
||||
/* Resample in blocks: */
|
||||
do odone = soxr_output(soxr, obuf, olen);
|
||||
while (fwrite(obuf, osize, odone, stdout)); /* Consume output. */
|
||||
|
||||
error = soxr_error(soxr); /* Check if any soxr error occurred. */
|
||||
clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */
|
||||
}
|
||||
/* Tidy up: */
|
||||
soxr_delete(soxr);
|
||||
free(obuf), free(ibuf);
|
||||
/* Diagnostics: */
|
||||
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%s)\n",
|
||||
arg0, soxr_strerror(error), (long unsigned)clips,
|
||||
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine);
|
||||
return !!error;
|
||||
}
|
||||
161
C/share/doc/libsoxr/examples/4-split-channels.c
Normal file
161
C/share/doc/libsoxr/examples/4-split-channels.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels.
|
||||
*
|
||||
* Note that, for convenience of the demonstration, split-channel data is
|
||||
* made available by deinterleaving data sourced from and sent to
|
||||
* interleaved file-streams; this adds a lot of code to the example that,
|
||||
* for purposes of understanding how to use split-channels, may safely be
|
||||
* ignored. In a real application, the channel-data might never be
|
||||
* interleaved; for example, the split-channel data output from the
|
||||
* resampler might be sent directly to digital-to-analogue converters.
|
||||
*
|
||||
* Note also (not shown in the examples) that split/interleaved channels may
|
||||
* be used for input and output independently.
|
||||
*
|
||||
* Arguments are as example 3.
|
||||
*/
|
||||
|
||||
#include <soxr.h>
|
||||
#include "examples-common.h"
|
||||
|
||||
|
||||
|
||||
#define DEINTERLEAVE(T) do { \
|
||||
unsigned i; \
|
||||
size_t j; \
|
||||
T * const * dest = (T * const *)dest0; \
|
||||
T const * src = src0; \
|
||||
if (ch == 1) memcpy(dest[0], src, n * sizeof(dest[0][0])); \
|
||||
else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = *src++; \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
static void deinterleave(soxr_datatype_t data_type,
|
||||
void * const * dest0,
|
||||
void const * src0,
|
||||
size_t n, unsigned ch)
|
||||
{
|
||||
switch (data_type & 3) {
|
||||
case SOXR_FLOAT32: DEINTERLEAVE(float);
|
||||
case SOXR_FLOAT64: DEINTERLEAVE(double);
|
||||
case SOXR_INT32 : DEINTERLEAVE(int32_t);
|
||||
case SOXR_INT16 : DEINTERLEAVE(int16_t);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
#define INTERLEAVE(T) do { \
|
||||
unsigned i; \
|
||||
size_t j; \
|
||||
T * dest = dest0; \
|
||||
T const * const * src = (T const * const *)src0; \
|
||||
if (ch == 1) memcpy(dest, src[0], n * sizeof(dest[0])); \
|
||||
else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = src[i][j]; \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
static void interleave(soxr_datatype_t data_type, void * dest0,
|
||||
void * const * src0, size_t n, unsigned ch)
|
||||
{
|
||||
switch (data_type & 3) {
|
||||
case SOXR_FLOAT32: INTERLEAVE(float);
|
||||
case SOXR_FLOAT64: INTERLEAVE(double);
|
||||
case SOXR_INT32 : INTERLEAVE(int32_t);
|
||||
case SOXR_INT16 : INTERLEAVE(int16_t);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int n, char const * arg[])
|
||||
{
|
||||
char const * const arg0 = n? --n, *arg++ : "";
|
||||
double const irate = n? --n, atof(*arg++) : 96000.;
|
||||
double const orate = n? --n, atof(*arg++) : 44100.;
|
||||
unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1;
|
||||
soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
||||
unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0;
|
||||
unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ;
|
||||
unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0;
|
||||
double const passband_end = n? --n, atof(*arg++) : 0;
|
||||
double const stopband_begin = n? --n, atof(*arg++) : 0;
|
||||
double const phase_response = n? --n, atof(*arg++) : -1;
|
||||
int const use_threads = n? --n, atoi(*arg++) : 1;
|
||||
soxr_datatype_t const otype = ospec & 3;
|
||||
|
||||
soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags);
|
||||
soxr_io_spec_t io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT);
|
||||
soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads);
|
||||
|
||||
/* Allocate resampling input and output buffers in proportion to the input
|
||||
* and output rates: */
|
||||
#define buf_total_len 15000 /* In samples per channel. */
|
||||
size_t const osize = soxr_datatype_size(otype) * chans;
|
||||
size_t const isize = soxr_datatype_size(itype) * chans;
|
||||
size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5);
|
||||
size_t const ilen = buf_total_len - olen;
|
||||
|
||||
/* For split channels: */
|
||||
void * * const obuf_ptrs = malloc(sizeof(void *) * chans);
|
||||
void * * ibuf_ptrs = malloc(sizeof(void *) * chans);
|
||||
char * const obufs = malloc(osize * olen), * optr = obufs;
|
||||
char * const ibufs = malloc(isize * ilen), * iptr = ibufs;
|
||||
|
||||
/* For interleaved channels: */
|
||||
char * const obuf = malloc(osize * olen);
|
||||
char * const ibuf = malloc(isize * ilen);
|
||||
|
||||
size_t odone, written, need_input = 1, clips = 0;
|
||||
soxr_error_t error;
|
||||
soxr_t soxr;
|
||||
unsigned i;
|
||||
|
||||
/* Overrides (if given): */
|
||||
if (passband_end > 0) q_spec.passband_end = passband_end / 100;
|
||||
if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100;
|
||||
if (phase_response >=0) q_spec.phase_response = phase_response;
|
||||
io_spec.flags = ospec & ~7u;
|
||||
|
||||
soxr = soxr_create(
|
||||
irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec);
|
||||
|
||||
for (i = 0; i < chans; ++i) {
|
||||
ibuf_ptrs[i] = iptr;
|
||||
obuf_ptrs[i] = optr;
|
||||
iptr += ilen * soxr_datatype_size(itype);
|
||||
optr += olen * soxr_datatype_size(otype);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
USE_STD_STDIO;
|
||||
|
||||
do {
|
||||
size_t ilen1 = 0;
|
||||
|
||||
if (need_input) {
|
||||
if (!(ilen1 = fread(ibuf, isize, ilen, stdin)))
|
||||
free(ibuf_ptrs), ibuf_ptrs = 0; /* If none available, don't retry. */
|
||||
else deinterleave(itype, ibuf_ptrs, ibuf, ilen1, chans);
|
||||
}
|
||||
|
||||
error = soxr_process(soxr, ibuf_ptrs, ilen1, NULL, obuf_ptrs, olen, &odone);
|
||||
interleave(otype, obuf, obuf_ptrs, odone, chans); /* Consume output... */
|
||||
written = fwrite(obuf, osize, odone, stdout);
|
||||
|
||||
need_input = odone < olen && ibuf_ptrs;
|
||||
|
||||
} while (!error && (need_input || written));
|
||||
|
||||
clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */
|
||||
}
|
||||
/* Tidy up: */
|
||||
soxr_delete(soxr);
|
||||
free(obuf), free(ibuf), free(obufs), free(ibufs);
|
||||
free(obuf_ptrs), free(ibuf_ptrs);
|
||||
/* Diagnostics: */
|
||||
fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n",
|
||||
arg0, soxr_strerror(error), (long unsigned)clips,
|
||||
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error");
|
||||
return !!error;
|
||||
}
|
||||
93
C/share/doc/libsoxr/examples/5-variable-rate.c
Normal file
93
C/share/doc/libsoxr/examples/5-variable-rate.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Example 5: Variable-rate resampling. A test signal (held in a buffer) is
|
||||
* resampled over a wide range of octaves. Resampled data is sent to stdout as
|
||||
* raw, float32 samples. Choices of 2 test-signals and of 2 ways of varying
|
||||
* the sample-rate are combined in a command-line option:
|
||||
*
|
||||
* Usage: ./5-variable-rate [0|1|2|3]
|
||||
*/
|
||||
|
||||
#include <soxr.h>
|
||||
#include "examples-common.h"
|
||||
|
||||
#define OCTAVES 5 /* Resampling range. ± */
|
||||
#define OLEN 16 /* Output length in seconds. */
|
||||
#define FS 44100 /* Output sampling rate in Hz. */
|
||||
|
||||
/* For output pos in [0,1], returns an ioratio in the 2^±OCTAVES range: */
|
||||
static double ioratio(double pos, int fm)
|
||||
{
|
||||
if (fm) /* fm: non-0 for a fast-changing ioratio, 0 for a slow sweep. */
|
||||
pos = .5 - cos(pos * 2 * M_PI) * .4 + sin(pos * OLEN * 20 * M_PI) * .05;
|
||||
return pow(2, 2 * OCTAVES * pos - OCTAVES);
|
||||
}
|
||||
|
||||
int main(int argc, char *arg[])
|
||||
{
|
||||
int opt = argc <= 1? 2 : (atoi(arg[1]) & 3), saw = opt & 1, fm = opt & 2;
|
||||
float ibuf[10 << OCTAVES], obuf[AL(ibuf)];
|
||||
int i, wl = 2 << OCTAVES;
|
||||
size_t ilen = AL(ibuf), need_input = 1, written;
|
||||
size_t odone, total_odone, total_olen = OLEN * FS;
|
||||
size_t olen1 = fm? 10 : AL(obuf); /* Small block-len if fast-changing ratio */
|
||||
soxr_error_t error;
|
||||
|
||||
/* When creating a var-rate resampler, q_spec must be set as follows: */
|
||||
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR);
|
||||
|
||||
/* The ratio of the given input rate and output rates must equate to the
|
||||
* maximum I/O ratio that will be used: */
|
||||
soxr_t soxr = soxr_create(1 << OCTAVES, 1, 1, &error, NULL, &q_spec, NULL);
|
||||
|
||||
if (!error) {
|
||||
USE_STD_STDIO;
|
||||
|
||||
/* Generate input signal, sine or saw, with wave-length = wl: */
|
||||
for (i = 0; i < (int)ilen; ++i)
|
||||
ibuf[i] = (float)(saw? (i%wl)/(wl-1.)-.5 : .9 * sin(2 * M_PI * i / wl));
|
||||
|
||||
/* Set the initial resampling ratio (N.B. 3rd parameter = 0): */
|
||||
soxr_set_io_ratio(soxr, ioratio(0, fm), 0);
|
||||
|
||||
/* Resample in blocks of size olen1: */
|
||||
for (total_odone = 0; !error && total_odone < total_olen;) {
|
||||
|
||||
/* The last block might be shorter: */
|
||||
size_t block_len = min(olen1, total_olen - total_odone);
|
||||
|
||||
/* Determine the position in [0,1] of the end of the current block: */
|
||||
double pos = (double)(total_odone + block_len) / (double)total_olen;
|
||||
|
||||
/* Calculate an ioratio for this position and instruct the resampler to
|
||||
* move smoothly to the new value, over the course of outputting the next
|
||||
* 'block_len' samples (or give 0 for an instant change instead): */
|
||||
soxr_set_io_ratio(soxr, ioratio(pos, fm), block_len);
|
||||
|
||||
/* Output the block of samples, supplying input samples as needed: */
|
||||
do {
|
||||
size_t len = need_input? ilen : 0;
|
||||
error = soxr_process(soxr, ibuf, len, NULL, obuf, block_len, &odone);
|
||||
written = fwrite(obuf, sizeof(float), odone, stdout);
|
||||
|
||||
/* Update counters for the current block and for the total length: */
|
||||
block_len -= odone;
|
||||
total_odone += odone;
|
||||
|
||||
/* If soxr_process did not provide the complete block, we must call it
|
||||
* again, supplying more input samples: */
|
||||
need_input = block_len != 0;
|
||||
|
||||
} while (need_input && !error && written == odone);
|
||||
|
||||
/* Now that the block for the current ioratio is complete, go back
|
||||
* round the main `for' loop in order to process the next block. */
|
||||
}
|
||||
soxr_delete(soxr);
|
||||
}
|
||||
/* Diagnostics: */
|
||||
fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error),
|
||||
ferror(stdin) || ferror(stdout)? strerror(errno) : "no error");
|
||||
return !!error;
|
||||
}
|
||||
20
C/share/doc/libsoxr/examples/README
Normal file
20
C/share/doc/libsoxr/examples/README
Normal file
@@ -0,0 +1,20 @@
|
||||
SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net
|
||||
|
||||
These simple examples show the different ways that an application may
|
||||
interface with soxr. Note that real-world applications may also have to
|
||||
deal with file-formats, codecs, (more sophisticated) dithering, etc., which
|
||||
are not covered here.
|
||||
|
||||
With the library installed, the examples may be built using commands similar
|
||||
to the following. On unix-like systems:
|
||||
|
||||
cc 1-single-block.c -lsoxr
|
||||
cc 1a-lsr.c -lsoxr-lsr
|
||||
|
||||
or, with MSVC on MS-Windows:
|
||||
|
||||
cl 1-single-block.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr.lib"
|
||||
cl 1a-lsr.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr-lsr.lib"
|
||||
|
||||
IDEs may hide such commands behind configuration screens and build menus --
|
||||
where applicable, consult your IDE's user-manual.
|
||||
47
C/share/doc/libsoxr/examples/examples-common.h
Normal file
47
C/share/doc/libsoxr/examples/examples-common.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net
|
||||
* Licence for this file: LGPL v2.1 See LICENCE for details. */
|
||||
|
||||
/* Common includes etc. for the examples. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Work-around for broken file-I/O on MS-Windows: */
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \
|
||||
_setmode(_fileno(stdin ), _O_BINARY)
|
||||
#else
|
||||
#define USE_STD_STDIO
|
||||
#endif
|
||||
|
||||
#undef int16_t
|
||||
#define int16_t short
|
||||
|
||||
#undef int32_t
|
||||
#if LONG_MAX > 2147483647L
|
||||
#define int32_t int
|
||||
#elif LONG_MAX < 2147483647L
|
||||
#error this programme requires that 'long int' has at least 32-bits
|
||||
#else
|
||||
#define int32_t long
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#define min(x,y) ((x)<(y)?(x):(y))
|
||||
|
||||
#undef max
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
#undef AL
|
||||
#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */
|
||||
|
||||
#undef M_PI /* Sometimes missing, so ensure that it is defined: */
|
||||
#define M_PI 3.14159265358979323846
|
||||
Reference in New Issue
Block a user