michael@0: /* Copyright (C) 2007 Jean-Marc Valin michael@0: michael@0: File: speex_resampler.h michael@0: Resampling code michael@0: michael@0: The design goals of this code are: michael@0: - Very fast algorithm michael@0: - Low memory requirement michael@0: - Good *perceptual* quality (and not best SNR) michael@0: michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions are michael@0: met: michael@0: michael@0: 1. Redistributions of source code must retain the above copyright notice, michael@0: this list of conditions and the following disclaimer. michael@0: michael@0: 2. Redistributions in binary form must reproduce the above copyright michael@0: notice, this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: michael@0: 3. The name of the author may not be used to endorse or promote products michael@0: derived from this software without specific prior written permission. michael@0: michael@0: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR michael@0: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES michael@0: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE michael@0: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, michael@0: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES michael@0: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR michael@0: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) michael@0: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, michael@0: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN michael@0: ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE michael@0: POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: michael@0: michael@0: #ifndef SPEEX_RESAMPLER_H michael@0: #define SPEEX_RESAMPLER_H michael@0: michael@0: #ifdef OUTSIDE_SPEEX michael@0: michael@0: /********* WARNING: MENTAL SANITY ENDS HERE *************/ michael@0: michael@0: /* If the resampler is defined outside of Speex, we change the symbol names so that michael@0: there won't be any clash if linking with Speex later on. */ michael@0: michael@0: /* #define RANDOM_PREFIX your software name here */ michael@0: #ifndef RANDOM_PREFIX michael@0: #error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes" michael@0: #endif michael@0: michael@0: #define CAT_PREFIX2(a,b) a ## b michael@0: #define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) michael@0: michael@0: #define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) michael@0: #define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) michael@0: #define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) michael@0: #define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float) michael@0: #define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int) michael@0: #define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float) michael@0: #define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int) michael@0: #define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate) michael@0: #define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate) michael@0: #define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac) michael@0: #define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio) michael@0: #define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality) michael@0: #define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) michael@0: #define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) michael@0: #define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) michael@0: #define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) michael@0: #define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) michael@0: #define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency) michael@0: #define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency) michael@0: #define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) michael@0: #define speex_resampler_set_skip_frac_num CAT_PREFIX(RANDOM_PREFIX,_resampler_set_skip_frac_num) michael@0: #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) michael@0: #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) michael@0: michael@0: #define spx_int16_t short michael@0: #define spx_int32_t int michael@0: #define spx_uint16_t unsigned short michael@0: #define spx_uint32_t unsigned int michael@0: michael@0: #else /* OUTSIDE_SPEEX */ michael@0: michael@0: #ifdef _BUILD_SPEEX michael@0: # include "speex_types.h" michael@0: #else michael@0: # include michael@0: #endif michael@0: michael@0: #endif /* OUTSIDE_SPEEX */ michael@0: michael@0: #ifdef __cplusplus michael@0: extern "C" { michael@0: #endif michael@0: michael@0: #define SPEEX_RESAMPLER_QUALITY_MAX 10 michael@0: #define SPEEX_RESAMPLER_QUALITY_MIN 0 michael@0: #define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 michael@0: #define SPEEX_RESAMPLER_QUALITY_VOIP 3 michael@0: #define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 michael@0: michael@0: enum { michael@0: RESAMPLER_ERR_SUCCESS = 0, michael@0: RESAMPLER_ERR_ALLOC_FAILED = 1, michael@0: RESAMPLER_ERR_BAD_STATE = 2, michael@0: RESAMPLER_ERR_INVALID_ARG = 3, michael@0: RESAMPLER_ERR_PTR_OVERLAP = 4, michael@0: michael@0: RESAMPLER_ERR_MAX_ERROR michael@0: }; michael@0: michael@0: struct SpeexResamplerState_; michael@0: typedef struct SpeexResamplerState_ SpeexResamplerState; michael@0: michael@0: /** Create a new resampler with integer input and output rates. michael@0: * @param nb_channels Number of channels to be processed michael@0: * @param in_rate Input sampling rate (integer number of Hz). michael@0: * @param out_rate Output sampling rate (integer number of Hz). michael@0: * @param quality Resampling quality between 0 and 10, where 0 has poor quality michael@0: * and 10 has very high quality. michael@0: * @return Newly created resampler state michael@0: * @retval NULL Error: not enough memory michael@0: */ michael@0: SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, michael@0: spx_uint32_t in_rate, michael@0: spx_uint32_t out_rate, michael@0: int quality, michael@0: int *err); michael@0: michael@0: /** Create a new resampler with fractional input/output rates. The sampling michael@0: * rate ratio is an arbitrary rational number with both the numerator and michael@0: * denominator being 32-bit integers. michael@0: * @param nb_channels Number of channels to be processed michael@0: * @param ratio_num Numerator of the sampling rate ratio michael@0: * @param ratio_den Denominator of the sampling rate ratio michael@0: * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). michael@0: * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). michael@0: * @param quality Resampling quality between 0 and 10, where 0 has poor quality michael@0: * and 10 has very high quality. michael@0: * @return Newly created resampler state michael@0: * @retval NULL Error: not enough memory michael@0: */ michael@0: SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, michael@0: spx_uint32_t ratio_num, michael@0: spx_uint32_t ratio_den, michael@0: spx_uint32_t in_rate, michael@0: spx_uint32_t out_rate, michael@0: int quality, michael@0: int *err); michael@0: michael@0: /** Destroy a resampler state. michael@0: * @param st Resampler state michael@0: */ michael@0: void speex_resampler_destroy(SpeexResamplerState *st); michael@0: michael@0: /** Resample a float array. The input and output buffers must *not* overlap. michael@0: * @param st Resampler state michael@0: * @param channel_index Index of the channel to process for the multi-channel michael@0: * base (0 otherwise) michael@0: * @param in Input buffer michael@0: * @param in_len Number of input samples in the input buffer. Returns the michael@0: * number of samples processed michael@0: * @param out Output buffer michael@0: * @param out_len Size of the output buffer. Returns the number of samples written michael@0: */ michael@0: int speex_resampler_process_float(SpeexResamplerState *st, michael@0: spx_uint32_t channel_index, michael@0: const float *in, michael@0: spx_uint32_t *in_len, michael@0: float *out, michael@0: spx_uint32_t *out_len); michael@0: michael@0: /** Resample an int array. The input and output buffers must *not* overlap. michael@0: * @param st Resampler state michael@0: * @param channel_index Index of the channel to process for the multi-channel michael@0: * base (0 otherwise) michael@0: * @param in Input buffer michael@0: * @param in_len Number of input samples in the input buffer. Returns the number michael@0: * of samples processed michael@0: * @param out Output buffer michael@0: * @param out_len Size of the output buffer. Returns the number of samples written michael@0: */ michael@0: int speex_resampler_process_int(SpeexResamplerState *st, michael@0: spx_uint32_t channel_index, michael@0: const spx_int16_t *in, michael@0: spx_uint32_t *in_len, michael@0: spx_int16_t *out, michael@0: spx_uint32_t *out_len); michael@0: michael@0: /** Resample an interleaved float array. The input and output buffers must *not* overlap. michael@0: * @param st Resampler state michael@0: * @param in Input buffer michael@0: * @param in_len Number of input samples in the input buffer. Returns the number michael@0: * of samples processed. This is all per-channel. michael@0: * @param out Output buffer michael@0: * @param out_len Size of the output buffer. Returns the number of samples written. michael@0: * This is all per-channel. michael@0: */ michael@0: int speex_resampler_process_interleaved_float(SpeexResamplerState *st, michael@0: const float *in, michael@0: spx_uint32_t *in_len, michael@0: float *out, michael@0: spx_uint32_t *out_len); michael@0: michael@0: /** Resample an interleaved int array. The input and output buffers must *not* overlap. michael@0: * @param st Resampler state michael@0: * @param in Input buffer michael@0: * @param in_len Number of input samples in the input buffer. Returns the number michael@0: * of samples processed. This is all per-channel. michael@0: * @param out Output buffer michael@0: * @param out_len Size of the output buffer. Returns the number of samples written. michael@0: * This is all per-channel. michael@0: */ michael@0: int speex_resampler_process_interleaved_int(SpeexResamplerState *st, michael@0: const spx_int16_t *in, michael@0: spx_uint32_t *in_len, michael@0: spx_int16_t *out, michael@0: spx_uint32_t *out_len); michael@0: michael@0: /** Set (change) the input/output sampling rates (integer value). michael@0: * @param st Resampler state michael@0: * @param in_rate Input sampling rate (integer number of Hz). michael@0: * @param out_rate Output sampling rate (integer number of Hz). michael@0: */ michael@0: int speex_resampler_set_rate(SpeexResamplerState *st, michael@0: spx_uint32_t in_rate, michael@0: spx_uint32_t out_rate); michael@0: michael@0: /** Get the current input/output sampling rates (integer value). michael@0: * @param st Resampler state michael@0: * @param in_rate Input sampling rate (integer number of Hz) copied. michael@0: * @param out_rate Output sampling rate (integer number of Hz) copied. michael@0: */ michael@0: void speex_resampler_get_rate(SpeexResamplerState *st, michael@0: spx_uint32_t *in_rate, michael@0: spx_uint32_t *out_rate); michael@0: michael@0: /** Set (change) the input/output sampling rates and resampling ratio michael@0: * (fractional values in Hz supported). michael@0: * @param st Resampler state michael@0: * @param ratio_num Numerator of the sampling rate ratio michael@0: * @param ratio_den Denominator of the sampling rate ratio michael@0: * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). michael@0: * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). michael@0: */ michael@0: int speex_resampler_set_rate_frac(SpeexResamplerState *st, michael@0: spx_uint32_t ratio_num, michael@0: spx_uint32_t ratio_den, michael@0: spx_uint32_t in_rate, michael@0: spx_uint32_t out_rate); michael@0: michael@0: /** Get the current resampling ratio. This will be reduced to the least michael@0: * common denominator. michael@0: * @param st Resampler state michael@0: * @param ratio_num Numerator of the sampling rate ratio copied michael@0: * @param ratio_den Denominator of the sampling rate ratio copied michael@0: */ michael@0: void speex_resampler_get_ratio(SpeexResamplerState *st, michael@0: spx_uint32_t *ratio_num, michael@0: spx_uint32_t *ratio_den); michael@0: michael@0: /** Set (change) the conversion quality. michael@0: * @param st Resampler state michael@0: * @param quality Resampling quality between 0 and 10, where 0 has poor michael@0: * quality and 10 has very high quality. michael@0: */ michael@0: int speex_resampler_set_quality(SpeexResamplerState *st, michael@0: int quality); michael@0: michael@0: /** Get the conversion quality. michael@0: * @param st Resampler state michael@0: * @param quality Resampling quality between 0 and 10, where 0 has poor michael@0: * quality and 10 has very high quality. michael@0: */ michael@0: void speex_resampler_get_quality(SpeexResamplerState *st, michael@0: int *quality); michael@0: michael@0: /** Set (change) the input stride. michael@0: * @param st Resampler state michael@0: * @param stride Input stride michael@0: */ michael@0: void speex_resampler_set_input_stride(SpeexResamplerState *st, michael@0: spx_uint32_t stride); michael@0: michael@0: /** Get the input stride. michael@0: * @param st Resampler state michael@0: * @param stride Input stride copied michael@0: */ michael@0: void speex_resampler_get_input_stride(SpeexResamplerState *st, michael@0: spx_uint32_t *stride); michael@0: michael@0: /** Set (change) the output stride. michael@0: * @param st Resampler state michael@0: * @param stride Output stride michael@0: */ michael@0: void speex_resampler_set_output_stride(SpeexResamplerState *st, michael@0: spx_uint32_t stride); michael@0: michael@0: /** Get the output stride. michael@0: * @param st Resampler state copied michael@0: * @param stride Output stride michael@0: */ michael@0: void speex_resampler_get_output_stride(SpeexResamplerState *st, michael@0: spx_uint32_t *stride); michael@0: michael@0: /** Get the latency introduced by the resampler measured in input samples. michael@0: * @param st Resampler state michael@0: */ michael@0: int speex_resampler_get_input_latency(SpeexResamplerState *st); michael@0: michael@0: /** Get the latency introduced by the resampler measured in output samples. michael@0: * @param st Resampler state michael@0: */ michael@0: int speex_resampler_get_output_latency(SpeexResamplerState *st); michael@0: michael@0: /** Make sure that the first samples to go out of the resamplers don't have michael@0: * leading zeros. This is only useful before starting to use a newly created michael@0: * resampler. It is recommended to use that when resampling an audio file, as michael@0: * it will generate a file with the same length. For real-time processing, michael@0: * it is probably easier not to use this call (so that the output duration michael@0: * is the same for the first frame). michael@0: * @param st Resampler state michael@0: */ michael@0: int speex_resampler_skip_zeros(SpeexResamplerState *st); michael@0: michael@0: /** Set the numerator in a fraction determining the advance through input michael@0: * samples before writing any output samples. The denominator of the fraction michael@0: * is the value returned from speex_resampler_get_ratio() in ratio_den. This michael@0: * is only useful before starting to use a newly created or reset resampler. michael@0: * If the first input sample is interpreted as the signal at time michael@0: * input_latency*in_rate, then the first output sample represents the signal michael@0: * at the time frac_num/ratio_num*out_rate. michael@0: * This is intended for careful alignment of output sample points wrt input michael@0: * sample points. Large values are not an efficient offset into the in buffer. michael@0: * @param st Resampler state michael@0: * @param skip_frac_num Numerator of the offset fraction, michael@0: * between 0 and ratio_den-1. michael@0: */ michael@0: int speex_resampler_set_skip_frac_num(SpeexResamplerState *st, michael@0: spx_uint32_t skip_frac_num); michael@0: michael@0: /** Reset a resampler so a new (unrelated) stream can be processed. michael@0: * @param st Resampler state michael@0: */ michael@0: int speex_resampler_reset_mem(SpeexResamplerState *st); michael@0: michael@0: /** Returns the English meaning for an error code michael@0: * @param err Error code michael@0: * @return English string michael@0: */ michael@0: const char *speex_resampler_strerror(int err); michael@0: michael@0: #ifdef __cplusplus michael@0: } michael@0: #endif michael@0: michael@0: #endif