Cog/ThirdParty/mpg123/include/mpg123/syn123.h
Christopher Snowhill e400fafa5d Dependencies: Updated mpg123 to 1.32.10
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2025-01-10 14:37:59 -08:00

1211 lines
52 KiB
C

/*
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