/*
	syn123: some audio signal synthesis and format conversion

	copyright 2017-2023 by the mpg123 project,
	free software under the terms of the LGPL 2.1
	see COPYING and AUTHORS files in distribution or http://mpg123.org

	initially written by Thomas Orgis

	Consider defining SYN123_PORTABLE_API to limit the definitions to
	a safer subset without some problematic features (mainly off_t usage).
*/

#ifndef SYN123_H
#define SYN123_H

/** \file syn123.h The header file for the libsyn123 library. */

/* Common audio encoding specification. */
#include "fmt123.h"

/** A macro to check at compile time which set of API functions to expect.
 * This must be incremented at least each time a new symbol is added
 * to the header.
 */
#define SYN123_API_VERSION 2
/** library patch level at client build time */
#define SYN123_PATCHLEVEL  3

#ifndef MPG123_EXPORT
/** Defines needed for MS Visual Studio(tm) DLL builds.
 * Every public function must be prefixed with MPG123_EXPORT. When building 
 * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible
 * for clients and includes it in the import library which is created together
 * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which
 * imports the functions from the DLL. 
 */
#ifdef BUILD_MPG123_DLL
/* The dll exports. */
#define MPG123_EXPORT __declspec(dllexport)
#else
#ifdef LINK_MPG123_DLL
/* The exe imports. */
#define MPG123_EXPORT __declspec(dllimport)
#else
/* Nothing on normal/UNIX builds */
#define MPG123_EXPORT
#endif
#endif
#endif

/** Support the restrict keyword for handed-in pointers. Defined to
    'restrict' if available.
 */
#ifndef MPG123_RESTRICT
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define MPG123_RESTRICT restrict
#else
#define MPG123_RESTRICT
#endif
#endif

// for off_t and ssize_t
#ifndef SYN123_PORTABLE_API
#include <sys/types.h>
#endif

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/** \defgroup syn123_api syn123 library API
 *  I wanted to create some test signals in different encodings for testing
 *  libout123. Also, they shall serve to verify the decoding of libmpg123
 *  in automated testing. Then, the awful drop-sample resampling inside the
 *  latter needed replacement. As digital filtering is part of the resampler
 *  dance, a chain of those can also be configured and applied. I hope I can
 *  avoid adding yet more functionality. It's a little utility library to
 *  accompany libmpg123 and libout123, OK?
 *
 *  This is what libsyn123 offers:
 *
 *  - signal generation (mix of differing wave shapes, noise, a simulated
 *    Geiger counter for fun)
 *  - format conversion and channel mixing and amplification, with hard and
 *    soft clipping, also optional dithering
 *  - near-zero-latency good-enough quite-fast resampling
 *  - applying digital filters with user-provided coefficients
 *
 *  The usage model for signal generation is this:
 *
 *  1. Create handle with desired output format.
 *  2. Set up synthesis mode with parameters.
 *  3. Repeatedly extract buffers with PCM samples.
 *
 *  If your hardware is slow on floating point operations, you may benefit
 *  from the period buffer in the handle that only needs actual computation
 *  once in the setup function. The frequencies of a wave mix may be fudged
 *  a bit to make for a configured period size.
 *
 *  The usage model for resampling is this:
 *
 *  1. Create handle with any format or re-use a signal generation handle.
 *  2. Set up resampling (rate ratio, channels, dirty mode).
 *  3. Use predictor functions to work out matching sizes of input and
 *     output buffers.
 *  4. Call the resampler on chunks of input, immediately producing matching
 *     chunks of output.
 *
 *  The resampler works on 32 bit float, exclusively. This is what is required
 *  and appropriate for the provided quality.
 *
 *  The usage model for filtering is this:
 *
 *  1. Create or re-use a handle.
 *  2. Set up the filter chain for single or double precision floating point.
 *  3. Apply the filter to chunks of input in succession.
 *
 *  Computations are generally done in floating point, either 32 bit or 64
 *  bit (single or double precision). The functions for encoding conversion,
 *  (de-)interleaving, and interleaved mixing can work without a handle and
 *  only use the buffers you hand in. Some support using a syn123 handle to
 *  provide the temporary buffers for encoding conversion on the fly to apply
 *  flotating-point processing to integer encodings.
 *
 *  Only the functions that are able to return a success code do check
 *  arguments for obvious trouble like NULL pointers. You are supposed to
 *  act responsibly when calling.
 *
 *  The size of buffers is either counted in bytes or samples, which,
 *  depending on the context, refer to individual PCM samples or to what is
 *  more strictly called a frame (one sample for each channel counted
 *  together).
 @{
 */

/** Opaque structure for the libsyn123 handle.
 *
 *  Simple context-free API functions do not need a handle, while
 *  others require it. Those that require it want it as first argument.
 *  Functions taking a handle as last argument after others make optional
 *  use of it (if non-NULL) to enable advanced functionality like
 *  on-the-fly encoding conversion that needs temporary storage.
 */
struct syn123_struct;
/** Typedef shortcut as preferrend name for the handle type. */
typedef struct syn123_struct syn123_handle;

/** Get version of the mpg123 distribution this library build came with.
 * (optional means non-NULL)
 * \param major optional address to store major version number
 * \param minor optional address to store minor version number
 * \param patch optional address to store patchlevel version number
 * \return full version string (like "1.2.3-beta4 (experimental)")
 */
MPG123_EXPORT
const char *syn123_distversion(unsigned int *major, unsigned int *minor, unsigned int *patch);

/** Get API version of library build.
 * \param patch optional address to store patchlevel
 * \return API version of library
 */
MPG123_EXPORT
unsigned int syn123_libversion(unsigned int *patch);

/** Functions that return an integer success code either return
 *  SYN123_OK if everything went fine, or one of the other detailed
 *  error codes.
 */
enum syn123_error
{
	SYN123_OK = 0   /**< no error */
,	SYN123_BAD_HANDLE /**< bad handle given (NULL) */
,	SYN123_BAD_FMT  /**< bad format (rate/channels) */
,	SYN123_BAD_ENC  /**< bad encoding given */
,	SYN123_BAD_CONV /**< unsupported conversion */
,	SYN123_BAD_SIZE /**< buffer size bad (too small) */
,	SYN123_BAD_BUF  /**< bad buffer pointer (NULL) */
,	SYN123_BAD_CHOP /**< byte buffer not cut at sample boundaries */
,	SYN123_DOOM     /**< Disaster, Out Of Memory. */
,	SYN123_WEIRD    /**< An internal error that should never occur. */
,	SYN123_BAD_FREQ /**< Invalid wave frequency given. */
,	SYN123_BAD_SWEEP /**< Invalid sweep curve given. */
,	SYN123_OVERFLOW  /**< Some fatal (integer) overflow that prevents proper operation. */
,	SYN123_NO_DATA   /**< Not enough data to do something. */
,	SYN123_BAD_DATA  /**< Data present, but not usable. */
};

/** Give a short phrase explaining an error code.
 *  \param errcode the code returned by an API function
 *  \return error phrase
 */
const char* syn123_strerror(int errcode);

/** Create new handle with specified output format.
 *  \param rate sampling rate
 *  \param channels channel count (duplicated mono channels)
 *  \param encoding sample encoding (see enum mpg123_enc_enum)
 *  \param maxbuf maximum buffer size in bytes to allow for caching periodic
 *    signals. When this is given, it is attempted to fit any configured signal
 *    into this buffer in the hope it will work being played periodically. Maybe
 *    there will be tricks with non-periodic signals.
 *    A buffer size of zero turns off buffering and signals are always generated
 *    during extraction.
 *  \param err address to store error code, non-NULL if you care
 *  \return Pointer to allocated handle structure or NULL on error.
 */
MPG123_EXPORT
syn123_handle* syn123_new( long rate, int channels, int encoding
,	size_t maxbuf, int *err );

/** Delete a handle.
 *  \param sh the handle to delete
 */
MPG123_EXPORT
void syn123_del(syn123_handle *sh);

/** Enable/disable dithering for conversions.
 *
 *  The default is no dither for conversions to integer encodings. You can
 *  enable dithering after handle creation, or disable it, as you wish.
 *  Enabling the dither resets the random number generator seed to the provided
 *  value or an internal default if the provided value is zero. The dither noise
 *  is unfiltered with triangular distribution (TPDF), as a sensible common
 *  choice. No further filtering of questionable benefit.
 *
 *  \param sh handle to work on
 *  \param dither Disable (0) or enable (1, actually nonzero) dithering.
 *    Positive values > 1 may trigger differing dither modes in future, but not
 *    now.
 *  \param seed optional address to read the initial seed value from (if non-zero)
 *    and to write the current value to
 */
MPG123_EXPORT
int syn123_dither(syn123_handle *sh, int dither, unsigned long *seed);

/** Extract desired amount of data from the generator.
 *  \param sh handle
 *  \param dst destination buffer
 *  \param dst_bytes number of bytes to extract
 *  \return actual number of extracted bytes
 *  (might differ if dst_bytes is no multiple of the PCM frame size)
 */
MPG123_EXPORT
size_t syn123_read(syn123_handle *sh, void *dst, size_t dst_bytes);

/** Wave types */
enum syn123_wave_id
{
	SYN123_WAVE_INVALID = -1 /**< invalid wave pattern */
,	SYN123_WAVE_FLAT = 0 /**< flat line, silence */
,	SYN123_WAVE_SINE     /**< sinusodial wave*/
,	SYN123_WAVE_SQUARE   /**< square wave */
,	SYN123_WAVE_TRIANGLE /**< triangle wave */
,	SYN123_WAVE_SAWTOOTH /**< sawtooth wave */
,	SYN123_WAVE_GAUSS    /**< Gaussian bell shape */
,	SYN123_WAVE_PULSE    /**< pulse shape, x^2 exp(-A x^2)/S */
,	SYN123_WAVE_SHOT     /**< shot (sharper pulse), x^2 exp(-A x)/S
	* (different values for A and S) */
,	SYN123_WAVE_LIMIT /**< valid IDs below that. A newer release of
	* the library might support more. */
};

/** Setup periodic wave generator.
 *  This sets up a series of oscillators with differing wave shapes.
 *  They are multiplied/scaled with each other instead of mixed
 *  in a sum of signals. It's more fun this way to generate interesting
 *  sounds. If you want to mix differing streams with differing volumes,
 *  channel balance and phase shifts, just create multiple single-channel
 *  generators with a convenient format (float encoding comes to mind)
 *  and mix to your heart's desire. You can then still use this library
 *  to get your channel buffers interleaved and converted to something
 *  your output device likes.
 *
 *  You can ensure strict periodicity without possible shifts in phases
 *  due to floating point rounding errors with the buffered variant.
 *  That may adjust your chosen frequencies to be able to keep the limit
 *  on buffer size, but the resulting data is then strictly periodic
 *  without any further computations that may introduce timing errors.
 *  Apart from possibly saving computing time via the precomputed table,
 *  this is the reason to pre-mix multiple waves into a common buffer at
 *  all.
 *
 *  The adjustments of the wave frequencies also include limiting them
 *  between some minimal value and the Nyquist frequency. Without the
 *  buffer, you can happily choose waves that are not resolved at all
 *  by the sampling rate and get the nasty results. Things get nasty
 *  inside the buffer, too, when you approach the Nyquist limit, but that
 *  is life (and mathematics).
 *
 *  The default wave is a 440 Hz sine without phase offset. If any setting
 *  is missing, the default is taken from that.
 *
 *  \param sh handle
 *  \param count number of waves (if zero, one default wave is configured)
 *  \param id array of wave IDs (enum syn123_wave_id), may be NULL
 *  \param freq array of wave frequencies, may be NULL
 *     Your provided frequencies are overwritten with the actual
 *     values if the periodic buffer is chosen.
 *  \param phase array of wave phases, may be NULL
 *  \param backwards array of true (non-zero) or false (zero), indicating
      whether the wave is being inverted in time, may be NULL
 *  \param period address to store the size of the period buffer
 *    in samples (zero if not using the buffer), ignored if NULL
 *  \return success code
 */
MPG123_EXPORT
int syn123_setup_waves( syn123_handle* sh, size_t count
,	int *id, double *freq, double *phase, int* backwards
,	size_t *period );

/** Query current wave generator setup and state.
 *
 *  This lets you extract the setup of the wave generator and
 *  the current phases to be able to re-create it and continue
 *  seamlessly, or maybe intentionally in some tweaked form with
 *  slight phase or frequency shifts.
 *
 *  You only need to set target pointers to non-NULL where you
 *  want the corresponding values extracted. You need to have
 *  the storage prepared for the correct wave count. A common
 *  mode of usage might be to make a first call to only query
 *  the count, allocate storage, then a do a second call for the
 *  wave data.
 *
 *  \param sh handle
 *  \param count address to store number of waves
 *  \param id storage for array of wave IDs
 *  \param freq storage for array of wave frequencies
 *  \param phase storage for array of wave phases
 *  \param backwards storage for array of true (non-zero) or false (zero),
 *    indicating whether the wave is being inverted in time
 *  \param period address to store the size of the period buffer
 *    in samples (zero if not using the buffer)
 *  \return success code
 */
MPG123_EXPORT
int syn123_query_waves( syn123_handle* sh, size_t *count
,	int *id, double *freq, double *phase, int* backwards
,	size_t *period );

/** Return the name of the indicated wave pattern.
 *  \param id The numerical ID of the wave pattern
 *    (out of enum syn123_wave_id).
 *  \return The name string, guaranteed to be non-NULL.
 *    Invalid codes yield the string "???".
 */
MPG123_EXPORT
const char* syn123_wave_name(int id);

/** Return the wave pattern id given a name string.
 *  \param name The name string.
 *  \return The numerical id (out of enum syn123_wave_id).
 *  
 */
MPG123_EXPORT
int syn123_wave_id(const char *name);

/** Types of frequency sweeps.
 *  There are no functions mapping those to/from strings,
 *  as this list is supposed to be fixed and small.
 *  There are only so many types of sweeps that make sense.
 */
enum syn123_sweep_id
{
	SYN123_SWEEP_LIN = 0 /**< linear frequency change */
,	SYN123_SWEEP_QUAD    /**< quadratic frequency change */
,	SYN123_SWEEP_EXP     /**< exponential (octave per time unit) */
,	SYN123_SWEEP_LIMIT   /**< valid IDs less than that */
};

/** Frequency sweep generator.
 *  This generates a sweep from one frequency to another with one
 *  of the available wave shapes over a given time.
 *  While you can just extract your single sweep by exactly reading
 *  the requestet duration, the generator is set up to run the sweep
 *  a bit longer until the beginning phase is reached again
 *  (one sample before that, of course). That way, reasonably smooth 
 *  periodic playback from the buffer is possible without that nasty jump.
 *  Still, a large freqency difference will result in an audible pop,
 *  but at least that is not whole spectrum due to a phase jump.
 *  \param sh handle
 *  \param wave_id wave ID (enum syn123_wave_id)
 *  \param f1 pointer to beginning frequency in Hz (>= 1e-4, please,
 *    a value <= 0 being replaced by the standard frequency and stored for you)
 *  \param f2 ending frequency in Hz (>= 1e-4, please,
 *    in case of exponential sweep: f2-f1 >= 1e-4, too,
 *    a value <= 0 being replaced by the standard frequency and stored for you)
 *  \param sweep_id choice of sweep curve (enum syn123_sweep_id)
 *  \param smooth enable the periodic smoothing, if sensible
 *    (extending signal beyond the sweep to avoid phase jumps, a continuing
 *    starting at given start phase, not the returned endphase)
 *  \param duration duration of sweep in samples (> 1, please)
 *    This theoretically should be an off_t relating to the size of a
 *    file you produce, but off_t in API headers causes headaches.
 *    A 32 bit size_t still gives you over 24 hours of sweeping with 44100 kHz
 *    rate. On top of that, you can use the returned endphase to chop
 *    your monster sweep into pieces.
 *  \param phase initial phase of the sweep
 *  \param backwards invert the waveform in time if true
 *  \param endphase address to store the normal phase that would
 *    smoothly continue the signal without the period correction
 *    (You can create a following sweep that continues smoothly to a new
 *    target frequency by handing in this endphase as initial phase. Combine
 *    that with phases of constant tone and you could simulate a Theremin
 *    player by approximating the reaction to hand movements via sweeps.)
 *  \param period address to store the periodic sample count, usually
 *    being a bit bigger than the duration for getting the phase
 *    back down; does not imply use of the internal period buffer
 *  \param buffer_period address to store the period count only if the
 *    period buffer is actually in use
 */
MPG123_EXPORT
int syn123_setup_sweep( syn123_handle* sh
,	int wave_id, double phase, int backwards
,	int sweep_id, double *f1, double *f2, int smooth, size_t duration
,	double *endphase, size_t *period, size_t *buffer_period );

/** Set up pink noise generator.
 *  This employs the Gardner/McCartney method to the approximate
 *  the real thing. The number of rows in the tree pattern is tunable.
 *  The result is pink noise with around 2.5 dB/octave. Do not expect
 *  more than 32 bits of randomness (or anything;-).
 *  \param sh handle
 *  \param rows rows for the generator algorithm
 *    It maxes out at 30 rows. Below 1 chooses a default.
 *  \param seed a 32 bit seed value for the pseudo-random number generator
 *  \param period optional address to store the size of the enforced period
 *    (zero for endlessly freshly generated signal)
 *  \return success code
 */
MPG123_EXPORT
int syn123_setup_pink( syn123_handle *sh, int rows, unsigned long seed
,	size_t *period );

/** Set up white noise generator.
 *  A simple white noise source using some cheap pseudo RNG. Do not
 *  expect more than 32 bits of randomness (or anything;-).
 *  \param sh handle
 *  \param seed a 32 bit seed value for the pseudo-random number generator
 *  \param period optional address to store the size of the
 *    enforced period (zero for endlessly freshly generated signal)
 */
MPG123_EXPORT
int syn123_setup_white(syn123_handle *sh, unsigned long seed, size_t *period);

/** Set up Geiger counter simulator.
 *  This models a speaker that is triggered by the pulses from
 *  the Geiger-Mueller counter. That creepy ticking sound.
 *  \param sh handle
 *  \param activity average events per second
 *  \param seed a 32 bit seed value for the pseudo-random number generator
 *  \param period optional address to store the size of the enforced period
 *    (zero for endlessly freshly generated signal)
 *  \return success code
 */
MPG123_EXPORT
int syn123_setup_geiger( syn123_handle *sh, double activity
,	unsigned long seed, size_t *period );

/** Set up silence.
 *  This goes back to the vanilla state.
 *  \return success code
 */
MPG123_EXPORT
int syn123_setup_silence(syn123_handle *sh);

/** Convert between supported encodings.
 *  The buffers must not overlap.
 *  Note that syn123 converts -1.0 to -127 for 8 bit signed (and analogous for
 *  other encodings), but still clips asymmetrically at -128 as that is the
 *  range of the type. If you do explicit clipping using syn123_clip(),
 *  the resulting range will be symmetrical inside [-1.0:1.0] and hence
 *  only down to -127 for 8 bit signed encoding.
 *  The conversions only work directly either from anything to double/float or
 *  from double/float to anything. This process is wrapped in the routine if
 *  a handle is provided, using the fixed mixing buffer in that. Clipping
 *  is only handled for floating point to integer conversions. Also, NaN
 *  is set to zero on conversion and counted as clipped.
 *  The ulaw and alaw conversions use Sun's reference implementation of the
 *  G711 standard (differing from libmpg123's big lookup table).
 *
 *  \param dst destination buffer
 *  \param dst_enc destination encoding (enum mpg123_enc_enum)
 *  \param dst_size size of destination buffer in bytes
 *  \param src source buffer
 *  \param src_enc source encoding
 *  \param src_bytes source buffer size in bytes
 *  \param dst_bytes optional address to store the written byte count to
 *  \param clipped optional address to store number of clipped samples to
 *  \param sh an optional syn123_handle which enables arbitrary encoding
 *    conversions by utilizing the contained buffer as intermediate storage,
 *    can be NULL, disabling any conversion not involving floating point
 *    input or output
 *  \return success code
 */
MPG123_EXPORT
int syn123_conv( void * MPG123_RESTRICT dst, int dst_enc, size_t dst_size
,	void * MPG123_RESTRICT src, int src_enc, size_t src_bytes
,	size_t *dst_bytes, size_t *clipped, syn123_handle * sh );

/** The range of decibel values handled by syn123 goes from
 *  -SYN123_DB_LIMIT to +SYN123_DB_LIMIT
 *  This value ensures that a resulting linear volume can still
 *  be expressed using single-precision float.
 *  The resulting amplitude from -500 dB is still small enough
 *  to drive a 32 bit integer sample value orders of magnitude below
 *  1, so it is effectively a zero. Note that physical volume controls
 *  typically give a range as small as 60 dB. You might want to present
 *  a tighter range to the user than +/- 500 dB!
 */
#define SYN123_DB_LIMIT 500

/** Convert decibels to linear volume (amplitude factor).
 *  This just returns pow(10, db/20) in the supported range.
 *  The dB value is limited according to SYN123_DB_LIMIT, with
 *  NaN being put at the lower end of the range. Better silent
 *  than insanely loud.
 *  \param db relative volume in dB
 *  \return linear volume factor
 */
MPG123_EXPORT double syn123_db2lin(double db);

/** Convert linear volume (amplitude factor) to decibels.
 *  This just returns 20*log10(volume) in the supported range.
 *  The returned value is limited according to SYN123_DB_LIMIT, with
 *  NaN being put at the lower end of the range. Better silent
 *  than insanely loud.
 *  \param volume linear volume factor
 *  \return relative volume in dB
 */
MPG123_EXPORT double syn123_lin2db(double volume);

/** Amplify given buffer.
 *  This multiplies all samples by the given floating point value
 *  (possibly converting to/from floating point on the fly, if a
 *  handle with the included working buffer is given).
 *  Also an offset correction is provided.
 *
 *  \param buf the buffer to work on
 *  \param encoding the sample encoding
 *  \param samples number of samples
 *  \param volume linear volume factor (use syn123_db2lin() for
 *    applying a change in dB)
 *  \param offset offset to add to the sample values before
 *    multiplication
 *  \param clipped optional address to store number of clipped samples to
 *  \param sh optional handle to enable work on non-float
 *    encodings
 *  \return success code (e.g. bad encoding without handle)
 */
MPG123_EXPORT
int syn123_amp( void* buf, int encoding, size_t samples
,	double volume, double offset,	size_t *clipped, syn123_handle *sh );

/** Clip samples in buffer to default range.
 *  This only does anything with floating point encoding, but you can always
 *  call it without damage as a no-op on other encodings. After this, the
 *  samples are guaranteed to be in the range [-1,+1]. NaNs are mapped
 *  to zero (and counted as clipped), so they will still sound bad.
 *  If you want to hard clip to a smaller range, use syn123_soft_clip() with
 *  a width of zero.
 *  \param buf buffer to work on
 *  \param encoding sample encoding
 *  \param samples total number of samples
 *  \return number of clipped samples
 */
MPG123_EXPORT
size_t syn123_clip(void *buf, int encoding, size_t samples);

/** Soft clipping / cheap limiting.
 *  This limits the samples above the threshold of limit-width with a
 *  smooth curve, dampening the high-frequency content of the clipping.
 *  This is no proper frequency filter, but just an independent function on
 *  each sample value, also ignorant of the channel count. This can
 *  directly work on float encodings and does nothing on others unless
 *  a handle is provided for on-line conversion.
 *  \param buf buffer to work on
 *  \param encoding sample encoding
 *  \param samples total number of samples
 *  \param limit the limit to clip to (normally 1 for full scale)
 *  \param width smoothing range
 *  \param sh optional handle to work on non-float encodings
 *  \return number of clipped samples
 */
MPG123_EXPORT
size_t syn123_soft_clip( void *buf, int encoding, size_t samples
,	double limit, double width, syn123_handle *sh );

/** Interleave given number of channels into one stream.
 *  A rather trivial functionality, here for completeness. As the
 *  algorithm is agnostic to what is actually stored as a "sample",
 *  the parameter types are so generic that you could use these
 *  functions to arrange huge structs (hence samplesize as size_t)
 *  or whatever. If that makes sense is up to you.
 *  The buffers shall not overlap!
 *  \param dst destination buffer
 *  \param src source buffer array (one per channel)
 *  \param channels channel count
 *  \param samplesize size of one sample
 *  \param samplecount count of samples per channel
 */
MPG123_EXPORT
void syn123_interleave( void * MPG123_RESTRICT dst, void** MPG123_RESTRICT src
,	int channels, size_t samplesize, size_t samplecount );

/** Deinterleave given number of channels out of one stream.
 *  A rather trivial functionality, here for completeness. As the
 *  algorithm is agnostic to what is actually stored as a "sample",
 *  the parameter types are so generic that you could use these
 *  functions to arrange huge structs (hence samplesize as size_t)
 *  or whatever. If that makes sense is up to you.
 *  The buffers must not overlap!
 *  \param dst destination buffer array (one per channel)
 *  \param src source buffer
 *  \param channels channel count
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples per channel
 */
MPG123_EXPORT
void syn123_deinterleave( void ** MPG123_RESTRICT dst, void * MPG123_RESTRICT src
,	int channels, size_t samplesize, size_t samplecount );

/** Simply copies mono samples into an interleaved stream.
 *  This might be implemented by a call to syn123_interleave(), it might
 *  be optimized to something different. You could have fun measuring that.
 *  \param dst destination buffer
 *  \param src source buffer
 *  \param channels channel count
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples per channel
 */
MPG123_EXPORT
void syn123_mono2many( void * MPG123_RESTRICT dst, void * MPG123_RESTRICT src
, int channels, size_t samplesize, size_t samplecount );

/** A little helper/reminder on how interleaved format works:
 *  Produce the offset of the given sample for the given channel.
 */
#define SYN123_IOFF(sample, channel, channels) ((sample)*(channels)+(channel))

/** Specify floating point encoding to use for preserving precision in
 *  intermediate computations for given source and destination encoding.
 *  This should return either MPG123_ENC_FLOAT_32 or MPG123_ENC_FLOAT_64,
 *  unless an uncertain future adds things like 16 bit fp ...
 *  This is what syn123_conv() and syn123_mix() will use internally if
 *  intermediate conversion is necessary.
 *  Note that 64 bit floating point material will be mixed in 32 bit if the
 *  destination encoding does not need more precision.
 *  \param src_enc source/input encoding
 *  \param dst_enc destination/output encoding
 *  \return encoding value, zero if none can be chosen (invalid parameters)
 */
MPG123_EXPORT
int syn123_mixenc(int src_enc, int dst_enc);

/** Mix n input channels on top of m output channels.
 *  This takes an interleaved input stream and mixes its channels
 *  into the output stream given a channel matrix (m,n) where
 *  each of the m rows contains the n volume factors (weights)
 *  to apply when summing the samples from the n input channels.
 *  Sample values are added to what is already present unless
 *  initial silence is explicitly requested.
 *  This works directly with identical floating point encodings. It
 *  may have some optimization to work faster with mono or stereo on
 *  either side and slower generic code for arbitrary channel counts.
 *  You can use syn123_conv() to convert from/to input/output encodings
 *  or provide a syn123_handle to do it on the fly.
 *  There are no optimizations for special cases of mixing factors, so
 *  you should always be able to predict the number of floating point
 *  operations being executed.
 *  For fun, you could give the same problem to a BLAS implementation
 *  of your choice and compare the performance;-)
 *  \param dst destination buffer
 *  \param dst_enc output sample encoding, must be MPG123_ENC_FLOAT_32 or
 *   MPG123_ENC_FLOAT_64 unless a syn123_handle is provided
 *  \param dst_channels destination channel count (m)
 *  \param src source buffer
 *  \param src_enc input sample encoding, must be MPG123_ENC_FLOAT_32 or
 *   MPG123_ENC_FLOAT_64 unless a syn123_handle is provided
 *  \param src_channels source channel count (n)
 *  \param mixmatrix mixing factors ((m,n) matrix), same encoding as
 *    the audio data
 *  \param samples count of samples (PCM frames) to work on
 *  \param silence Set to non-zero value to intialize the output
 *    to a silent signal before adding the input.
 *  \param clipped optional address to store number of clipped samples to
 *    (in case of mixing to an integer encoding)
 *  \param sh an optional syn123_handle which enables work on non-float
 *    encodings by utilizing the contained buffer as intermediate storage,
 *    converting to/from float transparently; Note that this may limit
 *    the amount of channels depending on the fixed internal buffer space.
 *    As long as you have up to 128 channels, you should not worry.
 *  \return success code (e.g. bad encoding, channel counts ...)
 */
MPG123_EXPORT
int syn123_mix( void * MPG123_RESTRICT dst, int dst_enc, int dst_channels
,	void * MPG123_RESTRICT src, int src_enc, int src_channels
,	const double * mixmatrix
,	size_t samples, int silence, size_t *clipped, syn123_handle *sh );

/** Set up a generic digital filter.
 *
 *  This takes a filter order N and coefficient set to prepare
 *  the internal state of a digital filter defined by the transfer
 *  function
 *  \f[
 *             
 *    H(z) = \frac
 *            {b_0 + b_1 z^{-1} + ... + b_N z^{-N}}
 *            {1 + a_1 z^{-1} + ... + a_N z^{-N}}
 *  \f]
 *  It is your task to come up with fun values for the coefficients
 *  b_n and a_n to implement various FIR and IIR filters.
 *
 *  Since it is easy to do and useful, this configures not only a single
 *  filter but a chain of them. If you do configure a chain, the choice
 *  of mixenc and channels must match. No conversion between filters.
 *
 *  \param sh mandatory handle
 *  \param append if true, append a filter to the chain, fresh chain otherwise
 *  \param order filter order N (filter length minus one)
 *  \param b nominator coefficients, starting with b_0 (order+1 elements)
 *  \param a denominator coefficients, starting with a_0=1 (order+1 elements).
 *    It is an error to provide a sequence that does not start with 1.
 *    For a non-recursive (FIR) filter, you can set all following
 *    values from a_1 on to zero or choose to provide a NULL pointer.
 *  \param mixenc either MPG123_ENC_FLOAT_32 or MPG123_ENC_FLOAT_64 for
 *    computation in single or double precision, can be zero to refer to
 *    the value demanded by an already present filter
 *  \param channels number of channels in the audio signal, can be zero
 *    to refer to the value demanded by an already present filter
 *  \param init_firstval If non-zero, initialize the filter history with
 *    a constant stream of the first encountered sample instead of zero.
 *  \return success code
 */
MPG123_EXPORT
int syn123_setup_filter( syn123_handle *sh
,	int append, unsigned int order, double *b, double *a
,	int mixenc, int channels, int init_firstval );

/** init_firstval is the effective setting (extreme coefficients may remove the distinction) */

MPG123_EXPORT
int syn123_query_filter( syn123_handle *sh, size_t position
,	size_t *count, unsigned int *order, double *b, double *a
,	int *mixenc, int *channels, int *init_firstval );

/** drop the n last filters */
MPG123_EXPORT
void syn123_drop_filter(syn123_handle *sh, size_t count);

/** Apply a prepared digital filter.
 * 
 *  This applies the filter prepared by syn123_setup_filter to yur
 *  provided buffer in single or double precision float.
 *  Handing in a non-float encoding is an error. You are supposed
 *  to convert and clip before/after applying the filters.
 *
 *  If you got no filters configured, this always succeeds and
 *  does nothing.
 *
 *  \param sh handle
 *  \param buf audio data to work on (channel count matching what
 *     was given to mpg123_setup_filter())
 *  \param encoding audio encoding
 *  \param samples count of samples (PCM frames) in the buffer
 *  \return success code
 */
MPG123_EXPORT
int syn123_filter( syn123_handle *sh
,	void* buf, int encoding, size_t samples );

/** Set up the resampler.
 *
 *  This works independently of the signal generators. You can combine
 *  syn123_setup_resample() with syn123_setup_geiger(), for example.
 *
 *  People can get worked up a lot about differing algorithms for resampling,
 *  while many folks can actually bear the simple drop/repeat method and most
 *  probably do not bother about the distortions from linear resampling.
 *  A testament to this is that in the 18 years of me maintaining mpg123, I
 *  got bugged about the missing dithering and on subtle bias in shuffling
 *  a playlist, but people seem to insist on using the NtoM resampoler inside
 *  libmpg123, despite me warning about its horrible consequences for audio
 *  quality. It is a plain drop-sample implementation. The only good things to
 *  say about it is that it is cheap and is embedded with the sample-accurate
 *  decoder so that you do not have to worry about offsets in terms of input
 *  and output samples.
 *
 *  Anyhow, this is my take on a reasonably good and efficient resampler that is
 *  neither the best-sounding, nor the fastest in terms of CPU time, but gets
 *  by without significant latency. It needs far less computation than usual
 *  high-quality windowed-sinc resampling (libsamplerate), but cannot beat
 *  libsoxr with its FFT-based approach. The less stringent dirty mode (using
 *  only a 72 dB lowpass filter, in practice still close to CD-DA quality)
 *  comes quite close, though.
 *
 *  The selling point is that it produces output samples as soon as you start
 *  feeding, without any buffering of future samples to fill a window for the
 *  FIR filter or the Fourier transform. It employs IIR filters for low-passing,
 *  possibly in multiple stages for decimation, and optimized interpolation
 *  formulas using up to 6 points. These formulas, based on research by
 *  Olli Niemitalo using using Differential Evolution, are what enables a
 *  dynamic range of 108 dB, well above 16 bit CD-DA quality. Simple
 *  cubic splines after low-passing distort up to around -40 dB in my tests.
 *
 *  There is some effective signal delay well below 10 samples. The impulse
 *  response is about 3 samples late, so this is well inside the realm of
 *  (nonlinear) phase shift. The phase distortion looks bad on paper but does
 *  not matter much in the intended domain of application: the final change in
 *  sampling rate before playback on audio hardware, the last filter that is
 *  applied before the sound hits the speakers (or all the other filters
 *  implemented in your audio harware, that you can choose to be ignorant
 *  about). Use better resamplers for mixing in the studio. Use better
 *  resamplers for converting files on disk. For live playback, consider this
 *  one because it is good enough, fast enough, cheap enough.
 *
 *  Note that if you call this function repeatedly, the internal history
 *  is only cleared if you change anything besides the sampling rates. If
 *  only the rates change, the state of the resampler is kept to enable
 *  you to continue on prior data. This means you can vary the resampling
 *  ratio during operation, somewhat smoothly depending on your buffer size.
 *
 *  Also note that even on identical input and output rates, the resampler
 *  will apply the full filtering as for any ratio close to that, including
 *  oversampling. No special shortcuts.
 *
 *  A returned error guarantees that the internal resampler setup has
 *  been cleared (frees a little bit of memory). You can provide zero
 *  inrate, outrate, and channel count at the same time to that effect
 *  without an error message being produced (but still SYN123_BAD_FMT
 *  being returned).
 *
 *  \param sh mandatory handle
 *  \param inrate input sample rate (nominator of ratio)
 *  \param outrate output sample rate (denominator of ratio)
 *  \param channels number of interleaved channels
 *  \param dirty Enable (!= 0) the dirty mode for even more 'good enough'
 *  resampling with less computing time. Offers -72 dB low pass attentuation,
 *  worst-case distortion around that, too, and 85% worst-case bandwidth.
 *  With this set to zero, the normal mode is used, offering at least 108 dB
 *  dynamic range and worst-case bandwidth above 84%.
 *  \param smooth Enable (!=0) extra code smoothing the resampler response to
 *  on-the-fly changes of sampling rate ratio. This involves keeping
 *  some per-stage history to bootstrap additional decimation filters and the
 *  changed final lowpass/interpolation.
 *  \return success code
 */
MPG123_EXPORT
int syn123_setup_resample( syn123_handle *sh, long inrate, long outrate
,	int channels, int dirty, int smooth );

/** Return the maximum allowed value for sample rates given to the resampler.
 *
 *  Not every possible value of the underlying data type is a valid sample
 *  rate for the resampler. It needs some headroom for computations. This
 *  function returns the maximal rate you can specify. For 32-bit long, this
 *  will be above 1e9, for 64-bit long above 4e18. The minimum is 1, of course.
 *  So, with 32 bit, you can speed up/down by a factor of one million if you
 *  want to keep 0.1% precision in the rates.
 *
 *  \return upper sample rate limit
 */
MPG123_EXPORT
long syn123_resample_maxrate(void);

/** Give upper limit for output sample count from the resampler.
 *
 *  Since there is some rounding involved, the exact number of output samples
 *  from the resampler, being given a certain amount of input samples, can
 *  vary (one more or less than expected). This function is here to give you
 *  a safe output buffer size given a certain input buffer size. If you intend
 *  to vary the output rate for a fixed input rate, you may compute the output
 *  buffer size for the largest intended output rate and use that throughout.
 *  The same applies to the input sample count.
 *  A return value of zero indicates an error (zero, negative, or too large
 *  rate given) unless the given input sample count is also zero.
 *  The resampler only produces output when given new input.
 *  \param inrate input sample rate
 *  \param outrate output sample rate
 *  \param ins input sample count for one buffer
 *  \return number of maximum output samples for one buffer, or zero
 *     if no sensible value exists
 */
MPG123_EXPORT
size_t syn123_resample_count(long inrate, long outrate, size_t ins);

/** Return the amount of input samples needed to recreate resample filter state.
 *
 *  This returns a number of input samples that should fill the internal
 *  filter states good enough for output being close to that produced from
 *  the full input since the beginning. Since recursive filters are employed,
 *  there is no exact number that recreates a state apart from the full sequence
 *  that created it the first time.  This number here shall be more than the
 *  non-recursive history, but not by a huge factor. For extreme cases, this
 *  value may be saturated at SIZE_MAX and thus smaller than what is demanded
 *  by the above definition. It is assumed that you define a maximal practical
 *  size of history to consider for your application, anyway.
 *
 *  \param inrate input sample rate
 *  \param outrate output sample rate
 *  \param dirty switch for dirty resampling mode (see syn123_setup_resample())
 *  \return number of input samples to fill history, zero on error
 */
MPG123_EXPORT
size_t syn123_resample_history(long inrate, long outrate, int dirty);

/** Compute the minimal input sample count needed for given output sample count.
 *
 *  The reverse of syn123_resample_count(), in a way. This gives you the
 *  minimum amount of input samples to guarantee at least the desired amount
 *  of output samples. Once you got that, ensure to call syn123_resample_count()
 *  to get a safe buffer size for that amount of input and prepare accordingly.
 *  With this approach, you can ensure that you get your realtime output device
 *  buffer filled with each loop run fetching a bit of input, at the expense
 *  of handling some additional buffering for the returned sample counts above
 *  the minimum.
 *
 *  \param input_rate input sample rate
 *  \param output_rate output sample rate
 *  \param outs desired minimal output sample count for one input buffer
 *  \return number of minimal input samples in one buffer, or zero if no
 *    sensible value exists (invalid input parameters, or zero outs)
 */
MPG123_EXPORT
size_t syn123_resample_incount(long input_rate, long output_rate, size_t outs);

/** Compute the input sample count needed for close to given output sample
 *  count, but never more.
 *
 *  Call this to get a safe fixed count of input samples to make best use
 *  of a preallocated output buffer, filling it as much as safely possible.
 *  This can also be achieved by calling syn123_resample_incount() and reducing
 *  the value until syn123_resample_count() fits into your buffer.
 *
 *  \param input_rate input sample rate
 *  \param output_rate output sample rate
 *  \param outs desired output sample count for one input buffer
 *  \return number of input samples in one buffer, or zero if no
 *    sensible value exists (invalid input parameters, or zero outs)
 */
MPG123_EXPORT
size_t syn123_resample_fillcount(long input_rate, long output_rate, size_t outs);


/** Compute the maximum number of input samples for a resampling buffer.
 *
 *  Upsampling means that you will get more output samples than input samples.
 *  This larger number still needs to fit into the data type for sample
 *  counts. So please don't feed more than the value returned here.
 *
 *  \param input_rate input sample rate
 *  \param output_rate output sample rate
 *  \return maximum safe input sample count
 */
MPG123_EXPORT
size_t syn123_resample_maxincount(long input_rate, long output_rate);

/** Give exact output sample count for feeding given input now.
 *
 *  This gives you the exact number of samples you will get returned
 *  when feeding the resampler the given additional input samples now,
 *  given the current resampler state contained in the handle.
 *
 *  On error, zero is returned and the error code is set to a nonzero
 *  syn123 error code.
 *
 *  \param sh syn123 handle
 *  \param ins input sample count
 *  \param err location to store error code
 *  \return output sample count
 */
MPG123_EXPORT
size_t syn123_resample_out(syn123_handle *sh, size_t ins, int *err);

/** Give minimum input sample count needed now for given output.
 *
 *  This give you the minimal number of input samples needed right
 *  now to yield at least the specified amount of output samples.
 *  Since one input sample can result in several output sampels in one
 *  go, you have to check using syn123_resample_out() how many
 *  output samples to really expect.
 *
 *  On error, zero is returned and the error code is set to a nonzero
 *  syn123 error code.
 *
 *  \param sh syn123 handle
 *  \param outs output sample count
 *  \param err location to store error code
 *  \return minimal input sample count
 */
MPG123_EXPORT
size_t syn123_resample_in(syn123_handle *sh, size_t outs, int *err);

/** Give exact output sample count for total input sample count.
 *
 *  Use this to determine the total length of your output stream
 *  given the length of the input stream. The computation is exact.
 *  But: It is only valid for a constant sampling rate ratio. If you
 *  play with that during runtime, you need to figure out your output
 *  offset yourself.
 *
 *  \param inrate input sample rate
 *  \param outrate output sample rate
 *  \param ins input sample count for the whole stream
 *  \return number of output samples or -1 if the computation fails
 *    (bad/too large sampling rates, integer overflow)
 */
MPG123_EXPORT
int64_t syn123_resample_total64(long inrate, long outrate, int64_t ins);

/** Give minimum input sample count for total output sample count.
 *
 *  You need to feed at least that amount of input samples to get
 *  the desired amount of output samples from the resampler. Depending
 *  on the resampling ratio, you may in fact get more than the desired
 *  amount (one input sample being worth multiple output samples during
 *  upsampling) so make sure to call syn123_resample_total() to get
 *  the exact number of samples you need to prepare for.
 *  Again, the output offset is only meaninful for a constant sampling
 *  rate ratio.
 *
 *  \param inrate input sample rate
 *  \param outrate output sample rate
 *  \param outs output sample count for the whole stream
 *  \return number of input samples or -1 if the computation fails
 *    (bad/too large sampling rates, integer overflow)
 */
MPG123_EXPORT
int64_t syn123_resample_intotal64(long inrate, long outrate, int64_t outs);

/** Resample input buffer to output buffer.
 *
 *  This executes the resampling configured by syn123_setup_resample(). The
 *  input and output encoding is fixed at single-precision float
 *  (MPG123_ENC_FLOAT_32) and multiple channels are interleaved. There
 *  is no implicit conversion of other encodings since the fixed internal
 *  buffers for that may not fit your chosen extreme resampling ratios. Also,
 *  dealing with double precision does not make sense with the mathematical
 *  limitations of the employed filters.
 *
 *  You are responsible for having your buffers prepared with the correct sizes.
 *  Use syn123_resample_count() to ensure that you are prepared for the correct
 *  number of output samples given your input sample count.
 *
 *  Also, ensuring a minimal number of input samples using
 *  syn123_resample_incount() helps to identify an error situation where zero
 *  samples are returned (which would be valid for low input sample count).
 *  The only error apart from handing in an invalid/unprepared handle is
 *  a too large number of input samples. Check syn123_resample_maxincount().
 *
 *  \param sh handle with prepared resampling method
 *    If this is NULL or if the resampler has not been initialized before, the
 *    function returns zero instead of crashing randomly.
 *  \param dst destination buffer
 *  \param src source buffer
 *  \param samples input samples (PCM frames) in source buffer
 *  \return number of output samples (PCM frames)
 */
MPG123_EXPORT
size_t syn123_resample( syn123_handle *sh,
	float * MPG123_RESTRICT dst, float * MPG123_RESTRICT src, size_t samples );

/** Swap byte order between little/big endian.
 *  \param buf buffer to work on
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples
 */
MPG123_EXPORT
void syn123_swap_bytes(void* buf, size_t samplesize, size_t samplecount);

/* Wrappers over the above to convert to/from syn123's native byte order
   from/to little or big endian. */

/** Convert from host order to little endian.
 *  \param buf buffer to work on
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples
 */
MPG123_EXPORT
void syn123_host2le(void *buf, size_t samplesize, size_t samplecount);

/** Convert from host order to big endian.
 *  \param buf buffer to work on
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples
 */
MPG123_EXPORT
void syn123_host2be(void *buf, size_t samplesize, size_t samplecount);

/** Convert from little endian to host order.
 *  \param buf buffer to work on
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples
 */
MPG123_EXPORT
void syn123_le2host(void *buf, size_t samplesize, size_t samplecount);

/** Convert from big endian to host order.
 *  \param buf buffer to work on
 *  \param samplesize size of one sample (see MPG123_SAMPLESIZE)
 *  \param samplecount count of samples
 */
MPG123_EXPORT
void syn123_be2host(void *buf, size_t samplesize, size_t samplecount);

// You are invited to defined SYN123_PORTABLE_API to avoid seeing shape-shifting off_t
// anywhere, also to avoid using non-standard types like ssize_t.
#if !defined(SYN123_PORTABLE_API) && !defined(SYN123_NO_LARGEFUNC)

/** A little hack to help MSVC not having ssize_t, duplicated in internal header. */
#ifdef _MSC_VER
#include <stddef.h>
typedef ptrdiff_t syn123_ssize_t;
#else
typedef ssize_t syn123_ssize_t;
#endif

/** Give exact output sample count for feeding given input now.
 *
 *  Old variant of syn123_resample_out() that (ab)uses ssize_t.
 *
 *  \deprecated Use syn123_resample_out() instead.
 *    The return of errors (integer overflow in
 *    calculation)is broken, as both the error codes and the valid results
 *    are positive integers. I screwed up.
 *
 *  \param sh syn123 handle
 *  \param ins input sample count
 *  \return output sample count or error code, hard to distinguish
 */
MPG123_EXPORT
syn123_ssize_t syn123_resample_expect(syn123_handle *sh, size_t ins);

/** Give minimum input sample count needed now for given output.
 *
 *  Old variant of syn123_resample_in() that (ab)uses ssize_t.
 *
 *  \deprecated Use syn123_resample_in() instead.
 *    The return of errors (integer overflow in
 *    calculation)is broken, as both the error codes and the valid results
 *    are positive integers. I screwed up.
 *
 *  \param sh syn123 handle
 *  \param outs output sample count
 *  \return minimal input sample count or error code, hard to distinguish
 */
MPG123_EXPORT
syn123_ssize_t syn123_resample_inexpect(syn123_handle *sh, size_t outs);

/* Lightweight large file hackery to enable worry-reduced use of off_t.
   Depending on the size of off_t in your client build, the corresponding
   library function needs to be chosen. */

#if defined(_FILE_OFFSET_BITS) && !defined(MPG123_NO_LARGENAME)
#  if _FILE_OFFSET_BITS+0 == 32
#    define syn123_resample_total   syn123_resample_total_32
#    define syn123_resample_intotal syn123_resample_intotal_32
#  elif _FILE_OFFSET_BITS+0 == 64
#    define syn123_resample_total   syn123_resample_total_64
#    define syn123_resample_intotal syn123_resample_intotal_64
#  else
#    error "Unpredicted _FILE_OFFSET_BITS value."
#  endif
#endif

/** Give exact output sample count for total input sample count.
 *
 *  This is syn123_resample_total64() with shape-shifting off_t,
 *  possibly renamed by macro. For type safety, use the former.
 *
 *  \deprecated Use syn123_resample_total64() instead.
 *
 *  \param inrate input sample rate
 *  \param outrate output sample rate
 *  \param ins input sample count for the whole stream
 *  \return number of output samples or -1 if the computation fails
 *    (bad/too large sampling rates, integer overflow)
 */
MPG123_EXPORT
off_t syn123_resample_total(long inrate, long outrate, off_t ins);

/** Give minimum input sample count for total output sample count.
 *
 *  This is syn123_resample_intotal64() with shape-shifting off_t,
 *  possibly renamed by macro. For type safety, use the former.
 *
 *  \deprecated Use syn123_resample_intotal64() instead.
 *
 *  \param inrate input sample rate
 *  \param outrate output sample rate
 *  \param outs output sample count for the whole stream
 *  \return number of input samples or -1 if the computation fails
 *    (bad/too large sampling rates, integer overflow)
 */
MPG123_EXPORT
off_t syn123_resample_intotal(long inrate, long outrate, off_t outs);

#endif

/** @} */

#ifdef __cplusplus
}
#endif

#endif
