From 7bd8f386be9d5449307087eb845d1d35d96f1e40 Mon Sep 17 00:00:00 2001 From: slicer Date: Tue, 22 Dec 2009 20:01:56 +0100 Subject: Split libspeex and libspeexdsp --- Makefile.am | 2 +- configure.ac | 9 +- include/speex/Makefile.am | 4 +- include/speex/speex_buffer.h | 72 -- include/speex/speex_echo.h | 174 --- include/speex/speex_jitter.h | 201 ---- include/speex/speex_preprocess.h | 223 ---- include/speex/speex_resampler.h | 344 ------ libspeex/Makefile.am | 46 +- libspeex/echo_diagnostic.m | 72 -- libspeex/jitter.c | 843 -------------- libspeex/mdf.c | 1285 --------------------- libspeex/preprocess.c | 1215 -------------------- libspeex/pseudofloat.h | 379 ------- libspeex/resample.c | 1137 ------------------- libspeex/resample_sse.h | 128 --- libspeex/scal.c | 293 ----- libspeex/testdenoise.c | 44 - libspeex/testecho.c | 53 - libspeex/testjitter.c | 75 -- libspeex/testresample.c | 86 -- speexdsp.pc.in | 15 - src/Makefile.am | 15 +- src/speexenc.c | 18 +- win32/Makefile.am | 2 +- win32/VS2003/Makefile.am | 2 +- win32/VS2003/libspeexdsp/Makefile.am | 8 - win32/VS2003/libspeexdsp/libspeexdsp.vcproj | 345 ------ win32/VS2005/Makefile.am | 2 +- win32/VS2005/libspeexdsp/Makefile.am | 8 - win32/VS2005/libspeexdsp/libspeexdsp.vcproj | 1628 --------------------------- win32/VS2008/Makefile.am | 2 +- win32/VS2008/libspeexdsp/Makefile.am | 8 - win32/VS2008/libspeexdsp/libspeexdsp.vcproj | 474 -------- win32/libspeex/Makefile.am | 2 +- win32/libspeex/libspeexdsp.dsp | 228 ---- win32/libspeex/libspeexdsp_dynamic.dsp | 237 ---- win32/libspeexdsp.def | 76 -- 38 files changed, 49 insertions(+), 9706 deletions(-) delete mode 100644 include/speex/speex_buffer.h delete mode 100644 include/speex/speex_echo.h delete mode 100644 include/speex/speex_jitter.h delete mode 100644 include/speex/speex_preprocess.h delete mode 100644 include/speex/speex_resampler.h delete mode 100644 libspeex/echo_diagnostic.m delete mode 100644 libspeex/jitter.c delete mode 100644 libspeex/mdf.c delete mode 100644 libspeex/preprocess.c delete mode 100644 libspeex/pseudofloat.h delete mode 100644 libspeex/resample.c delete mode 100644 libspeex/resample_sse.h delete mode 100755 libspeex/scal.c delete mode 100644 libspeex/testdenoise.c delete mode 100644 libspeex/testecho.c delete mode 100644 libspeex/testjitter.c delete mode 100644 libspeex/testresample.c delete mode 100644 speexdsp.pc.in delete mode 100644 win32/VS2003/libspeexdsp/Makefile.am delete mode 100755 win32/VS2003/libspeexdsp/libspeexdsp.vcproj delete mode 100644 win32/VS2005/libspeexdsp/Makefile.am delete mode 100755 win32/VS2005/libspeexdsp/libspeexdsp.vcproj delete mode 100644 win32/VS2008/libspeexdsp/Makefile.am delete mode 100755 win32/VS2008/libspeexdsp/libspeexdsp.vcproj delete mode 100755 win32/libspeex/libspeexdsp.dsp delete mode 100755 win32/libspeex/libspeexdsp_dynamic.dsp delete mode 100755 win32/libspeexdsp.def diff --git a/Makefile.am b/Makefile.am index 4b99faf..5908efb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ m4datadir = $(datadir)/aclocal m4data_DATA = speex.m4 pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = speex.pc speexdsp.pc +pkgconfig_DATA = speex.pc EXTRA_DIST = Speex.spec Speex.spec.in Speex.kdevelop speex.m4 speex.pc.in README.blackfin README.symbian README.TI-DSP diff --git a/configure.ac b/configure.ac index 3179521..0ddf398 100644 --- a/configure.ac +++ b/configure.ac @@ -204,7 +204,7 @@ AC_ARG_ENABLE(ti-c55x, [ --enable-ti-c55x Enable support for TI C55X DSP AC_DEFINE([TI_C55X], , [Enable support for TI C55X DSP]) fi]) -AC_ARG_ENABLE(vorbis-psy, [ --enable-psy Enable the Vorbis psy model], +AC_ARG_ENABLE(vorbis-psy, [ --enable-vorbis-psy Enable the Vorbis psy model], [if test "$enableval" = yes; then vorbis_psy=yes; AC_DEFINE([VORBIS_PSYCHO], , [Enable support for the Vorbis psy model]) @@ -249,6 +249,8 @@ AC_SUBST(FFT_PKGCONFIG) AM_CONDITIONAL(BUILD_VORBIS_PSY, [test "x$vorbis_psy" = "xyes"]) +PKG_CHECK_MODULES([SPEEXDSP], [speexdsp], [AC_DEFINE([USE_SPEEXDSP], [], [Use SpeexDSP library])], [speexdsp_failed=yes]) + AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) @@ -285,22 +287,19 @@ AC_SUBST(SIZE32) AC_DEFINE([_BUILD_SPEEX], [], [Defined only when Speex itself is build built]) AC_OUTPUT([Makefile libspeex/Makefile src/Makefile doc/Makefile Speex.spec - include/Makefile include/speex/Makefile speex.pc speexdsp.pc + include/Makefile include/speex/Makefile speex.pc win32/Makefile win32/libspeex/Makefile win32/speexenc/Makefile win32/speexdec/Makefile symbian/Makefile win32/VS2003/Makefile win32/VS2003/tests/Makefile win32/VS2003/libspeex/Makefile - win32/VS2003/libspeexdsp/Makefile win32/VS2003/speexdec/Makefile win32/VS2003/speexenc/Makefile win32/VS2005/Makefile win32/VS2005/libspeex/Makefile win32/VS2005/speexdec/Makefile win32/VS2005/speexenc/Makefile - win32/VS2005/libspeexdsp/Makefile win32/VS2005/tests/Makefile - win32/VS2008/libspeexdsp/Makefile win32/VS2008/Makefile win32/VS2008/speexdec/Makefile win32/VS2008/tests/Makefile diff --git a/include/speex/Makefile.am b/include/speex/Makefile.am index 2ae34f9..dff69d6 100644 --- a/include/speex/Makefile.am +++ b/include/speex/Makefile.am @@ -3,7 +3,7 @@ nodist_pkginclude_HEADERS = speex_config_types.h -pkginclude_HEADERS = speex.h speex_bits.h speex_buffer.h speex_callbacks.h \ - speex_echo.h speex_header.h speex_jitter.h speex_preprocess.h speex_resampler.h \ +pkginclude_HEADERS = speex.h speex_bits.h speex_callbacks.h \ + speex_header.h \ speex_stereo.h speex_types.h diff --git a/include/speex/speex_buffer.h b/include/speex/speex_buffer.h deleted file mode 100644 index 59632b3..0000000 --- a/include/speex/speex_buffer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2007 Jean-Marc Valin - - File: speex_buffer.h - This is a very simple ring buffer implementation. It is not thread-safe - so you need to do your own locking. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef SPEEX_BUFFER_H -#define SPEEX_BUFFER_H - -#ifdef _BUILD_SPEEX -# include "speex_types.h" -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -struct SpeexBuffer_; -typedef struct SpeexBuffer_ SpeexBuffer; - -SpeexBuffer *speex_buffer_init(int size); - -void speex_buffer_destroy(SpeexBuffer *st); - -int speex_buffer_write(SpeexBuffer *st, void *data, int len); - -int speex_buffer_writezeros(SpeexBuffer *st, int len); - -int speex_buffer_read(SpeexBuffer *st, void *data, int len); - -int speex_buffer_get_available(SpeexBuffer *st); - -int speex_buffer_resize(SpeexBuffer *st, int len); - -#ifdef __cplusplus -} -#endif - -#endif - - - - diff --git a/include/speex/speex_echo.h b/include/speex/speex_echo.h deleted file mode 100644 index c01688b..0000000 --- a/include/speex/speex_echo.h +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) Jean-Marc Valin */ -/** - @file speex_echo.h - @brief Echo cancellation -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef SPEEX_ECHO_H -#define SPEEX_ECHO_H -/** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller - * This is the acoustic echo canceller module. - * @{ - */ -#ifdef _BUILD_SPEEX -# include "speex_types.h" -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** Obtain frame size used by the AEC */ -#define SPEEX_ECHO_GET_FRAME_SIZE 3 - -/** Set sampling rate */ -#define SPEEX_ECHO_SET_SAMPLING_RATE 24 -/** Get sampling rate */ -#define SPEEX_ECHO_GET_SAMPLING_RATE 25 - -/* Can't set window sizes */ -/** Get size of impulse response (int32) */ -#define SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE 27 - -/* Can't set window content */ -/** Get impulse response (int32[]) */ -#define SPEEX_ECHO_GET_IMPULSE_RESPONSE 29 - -/** Internal echo canceller state. Should never be accessed directly. */ -struct SpeexEchoState_; - -/** @class SpeexEchoState - * This holds the state of the echo canceller. You need one per channel. -*/ - -/** Internal echo canceller state. Should never be accessed directly. */ -typedef struct SpeexEchoState_ SpeexEchoState; - -/** Creates a new echo canceller state - * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) - * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) - * @return Newly-created echo canceller state - */ -SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length); - -/** Creates a new multi-channel echo canceller state - * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) - * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) - * @param nb_mic Number of microphone channels - * @param nb_speakers Number of speaker channels - * @return Newly-created echo canceller state - */ -SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers); - -/** Destroys an echo canceller state - * @param st Echo canceller state -*/ -void speex_echo_state_destroy(SpeexEchoState *st); - -/** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added - * to playback in this form) - * - * @param st Echo canceller state - * @param rec Signal from the microphone (near end + far end echo) - * @param play Signal played to the speaker (received from far end) - * @param out Returns near-end signal with echo removed - */ -void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); - -/** Performs echo cancellation a frame (deprecated) */ -void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out, spx_int32_t *Yout); - -/** Perform echo cancellation using internal playback buffer, which is delayed by two frames - * to account for the delay introduced by most soundcards (but it could be off!) - * @param st Echo canceller state - * @param rec Signal from the microphone (near end + far end echo) - * @param out Returns near-end signal with echo removed -*/ -void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out); - -/** Let the echo canceller know that a frame was just queued to the soundcard - * @param st Echo canceller state - * @param play Signal played to the speaker (received from far end) -*/ -void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play); - -/** Reset the echo canceller to its original state - * @param st Echo canceller state - */ -void speex_echo_state_reset(SpeexEchoState *st); - -/** Used like the ioctl function to control the echo canceller parameters - * - * @param st Echo canceller state - * @param request ioctl-type request (one of the SPEEX_ECHO_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown - */ -int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr); - - - -struct SpeexDecorrState_; - -typedef struct SpeexDecorrState_ SpeexDecorrState; - - -/** Create a state for the channel decorrelation algorithm - This is useful for multi-channel echo cancellation only - * @param rate Sampling rate - * @param channels Number of channels (it's a bit pointless if you don't have at least 2) - * @param frame_size Size of the frame to process at ones (counting samples *per* channel) -*/ -SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size); - -/** Remove correlation between the channels by modifying the phase and possibly - adding noise in a way that is not (or little) perceptible. - * @param st Decorrelator state - * @param in Input audio in interleaved format - * @param out Result of the decorrelation (out *may* alias in) - * @param strength How much alteration of the audio to apply from 0 to 100. -*/ -void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength); - -/** Destroy a Decorrelation state - * @param st State to destroy -*/ -void speex_decorrelate_destroy(SpeexDecorrState *st); - - -#ifdef __cplusplus -} -#endif - - -/** @}*/ -#endif diff --git a/include/speex/speex_jitter.h b/include/speex/speex_jitter.h deleted file mode 100644 index 977916b..0000000 --- a/include/speex/speex_jitter.h +++ /dev/null @@ -1,201 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file speex_jitter.h - @brief Adaptive jitter buffer for Speex -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SPEEX_JITTER_H -#define SPEEX_JITTER_H -/** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer - * This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size - * to maintain good quality and low latency. - * @{ - */ - -#ifdef _BUILD_SPEEX -# include "speex_types.h" -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** Generic adaptive jitter buffer state */ -struct JitterBuffer_; - -/** Generic adaptive jitter buffer state */ -typedef struct JitterBuffer_ JitterBuffer; - -/** Definition of an incoming packet */ -typedef struct _JitterBufferPacket JitterBufferPacket; - -/** Definition of an incoming packet */ -struct _JitterBufferPacket { - char *data; /**< Data bytes contained in the packet */ - spx_uint32_t len; /**< Length of the packet in bytes */ - spx_uint32_t timestamp; /**< Timestamp for the packet */ - spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */ - spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */ - spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */ -}; - -/** Packet has been retrieved */ -#define JITTER_BUFFER_OK 0 -/** Packet is lost or is late */ -#define JITTER_BUFFER_MISSING 1 -/** A "fake" packet is meant to be inserted here to increase buffering */ -#define JITTER_BUFFER_INSERTION 2 -/** There was an error in the jitter buffer */ -#define JITTER_BUFFER_INTERNAL_ERROR -1 -/** Invalid argument */ -#define JITTER_BUFFER_BAD_ARGUMENT -2 - - -/** Set minimum amount of extra buffering required (margin) */ -#define JITTER_BUFFER_SET_MARGIN 0 -/** Get minimum amount of extra buffering required (margin) */ -#define JITTER_BUFFER_GET_MARGIN 1 -/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */ - -/** Get the amount of available packets currently buffered */ -#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3 -/** Included because of an early misspelling (will remove in next release) */ -#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3 - -/** Assign a function to destroy unused packet. When setting that, the jitter - buffer no longer copies packet data. */ -#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4 -/** */ -#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5 - -/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */ -#define JITTER_BUFFER_SET_DELAY_STEP 6 -/** */ -#define JITTER_BUFFER_GET_DELAY_STEP 7 - -/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */ -#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8 -#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9 - -/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss - should be half of that or less. */ -#define JITTER_BUFFER_SET_MAX_LATE_RATE 10 -#define JITTER_BUFFER_GET_MAX_LATE_RATE 11 - -/** Equivalent cost of one percent late packet in timestamp units */ -#define JITTER_BUFFER_SET_LATE_COST 12 -#define JITTER_BUFFER_GET_LATE_COST 13 - - -/** Initialises jitter buffer - * - * @param step_size Starting value for the size of concleanment packets and delay - adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP - and JITTER_BUFFER_GET_CONCEALMENT_SIZE. - * @return Newly created jitter buffer state - */ -JitterBuffer *jitter_buffer_init(int step_size); - -/** Restores jitter buffer to its original state - * - * @param jitter Jitter buffer state - */ -void jitter_buffer_reset(JitterBuffer *jitter); - -/** Destroys jitter buffer - * - * @param jitter Jitter buffer state - */ -void jitter_buffer_destroy(JitterBuffer *jitter); - -/** Put one packet into the jitter buffer - * - * @param jitter Jitter buffer state - * @param packet Incoming packet -*/ -void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet); - -/** Get one packet from the jitter buffer - * - * @param jitter Jitter buffer state - * @param packet Returned packet - * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee) - * @param current_timestamp Timestamp for the returned packet -*/ -int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset); - -/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp. - * This is mainly useful for media where a single "frame" can be split into several packets. - * - * @param jitter Jitter buffer state - * @param packet Returned packet - */ -int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet); - -/** Get pointer timestamp of jitter buffer - * - * @param jitter Jitter buffer state -*/ -int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter); - -/** Advance by one tick - * - * @param jitter Jitter buffer state -*/ -void jitter_buffer_tick(JitterBuffer *jitter); - -/** Telling the jitter buffer about the remaining data in the application buffer - * @param jitter Jitter buffer state - * @param rem Amount of data buffered by the application (timestamp units) - */ -void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem); - -/** Used like the ioctl function to control the jitter buffer parameters - * - * @param jitter Jitter buffer state - * @param request ioctl-type request (one of the JITTER_BUFFER_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown -*/ -int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr); - -int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset); - -/* @} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/speex/speex_preprocess.h b/include/speex/speex_preprocess.h deleted file mode 100644 index 2730595..0000000 --- a/include/speex/speex_preprocess.h +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (C) 2003 Epic Games - Written by Jean-Marc Valin */ -/** - * @file speex_preprocess.h - * @brief Speex preprocessor. The preprocess can do noise suppression, - * residual echo suppression (after using the echo canceller), automatic - * gain control (AGC) and voice activity detection (VAD). -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef SPEEX_PREPROCESS_H -#define SPEEX_PREPROCESS_H -/** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor - * This is the Speex preprocessor. The preprocess can do noise suppression, - * residual echo suppression (after using the echo canceller), automatic - * gain control (AGC) and voice activity detection (VAD). - * @{ - */ - -#ifdef _BUILD_SPEEX -# include "speex_types.h" -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** State of the preprocessor (one per channel). Should never be accessed directly. */ -struct SpeexPreprocessState_; - -/** State of the preprocessor (one per channel). Should never be accessed directly. */ -typedef struct SpeexPreprocessState_ SpeexPreprocessState; - - -/** Creates a new preprocessing state. You MUST create one state per channel processed. - * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms). Must be - * the same value as that used for the echo canceller for residual echo cancellation to work. - * @param sampling_rate Sampling rate used for the input. - * @return Newly created preprocessor state -*/ -SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate); - -/** Destroys a preprocessor state - * @param st Preprocessor state to destroy -*/ -void speex_preprocess_state_destroy(SpeexPreprocessState *st); - -/** Preprocess a frame - * @param st Preprocessor state - * @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init(). - * @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on. -*/ -int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x); - -/** Preprocess a frame (deprecated, use speex_preprocess_run() instead)*/ -int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo); - -/** Update preprocessor state, but do not compute the output - * @param st Preprocessor state - * @param x Audio sample vector (in only). Must be same size as specified in speex_preprocess_state_init(). -*/ -void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x); - -/** Used like the ioctl function to control the preprocessor parameters - * @param st Preprocessor state - * @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros) - * @param ptr Data exchanged to-from function - * @return 0 if no error, -1 if request in unknown -*/ -int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr); - - - -/** Set preprocessor denoiser state */ -#define SPEEX_PREPROCESS_SET_DENOISE 0 -/** Get preprocessor denoiser state */ -#define SPEEX_PREPROCESS_GET_DENOISE 1 - -/** Set preprocessor Automatic Gain Control state */ -#define SPEEX_PREPROCESS_SET_AGC 2 -/** Get preprocessor Automatic Gain Control state */ -#define SPEEX_PREPROCESS_GET_AGC 3 - -/** Set preprocessor Voice Activity Detection state */ -#define SPEEX_PREPROCESS_SET_VAD 4 -/** Get preprocessor Voice Activity Detection state */ -#define SPEEX_PREPROCESS_GET_VAD 5 - -/** Set preprocessor Automatic Gain Control level (float) */ -#define SPEEX_PREPROCESS_SET_AGC_LEVEL 6 -/** Get preprocessor Automatic Gain Control level (float) */ -#define SPEEX_PREPROCESS_GET_AGC_LEVEL 7 - -/** Set preprocessor dereverb state */ -#define SPEEX_PREPROCESS_SET_DEREVERB 8 -/** Get preprocessor dereverb state */ -#define SPEEX_PREPROCESS_GET_DEREVERB 9 - -/** Set preprocessor dereverb level */ -#define SPEEX_PREPROCESS_SET_DEREVERB_LEVEL 10 -/** Get preprocessor dereverb level */ -#define SPEEX_PREPROCESS_GET_DEREVERB_LEVEL 11 - -/** Set preprocessor dereverb decay */ -#define SPEEX_PREPROCESS_SET_DEREVERB_DECAY 12 -/** Get preprocessor dereverb decay */ -#define SPEEX_PREPROCESS_GET_DEREVERB_DECAY 13 - -/** Set probability required for the VAD to go from silence to voice */ -#define SPEEX_PREPROCESS_SET_PROB_START 14 -/** Get probability required for the VAD to go from silence to voice */ -#define SPEEX_PREPROCESS_GET_PROB_START 15 - -/** Set probability required for the VAD to stay in the voice state (integer percent) */ -#define SPEEX_PREPROCESS_SET_PROB_CONTINUE 16 -/** Get probability required for the VAD to stay in the voice state (integer percent) */ -#define SPEEX_PREPROCESS_GET_PROB_CONTINUE 17 - -/** Set maximum attenuation of the noise in dB (negative number) */ -#define SPEEX_PREPROCESS_SET_NOISE_SUPPRESS 18 -/** Get maximum attenuation of the noise in dB (negative number) */ -#define SPEEX_PREPROCESS_GET_NOISE_SUPPRESS 19 - -/** Set maximum attenuation of the residual echo in dB (negative number) */ -#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS 20 -/** Get maximum attenuation of the residual echo in dB (negative number) */ -#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS 21 - -/** Set maximum attenuation of the residual echo in dB when near end is active (negative number) */ -#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE 22 -/** Get maximum attenuation of the residual echo in dB when near end is active (negative number) */ -#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE 23 - -/** Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL for no residual echo suppression) */ -#define SPEEX_PREPROCESS_SET_ECHO_STATE 24 -/** Get the corresponding echo canceller state */ -#define SPEEX_PREPROCESS_GET_ECHO_STATE 25 - -/** Set maximal gain increase in dB/second (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_INCREMENT 26 - -/** Get maximal gain increase in dB/second (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_INCREMENT 27 - -/** Set maximal gain decrease in dB/second (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_DECREMENT 28 - -/** Get maximal gain decrease in dB/second (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_DECREMENT 29 - -/** Set maximal gain in dB (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 30 - -/** Get maximal gain in dB (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31 - -/* Can't set loudness */ -/** Get loudness */ -#define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33 - -/* Can't set gain */ -/** Get current gain (int32 percent) */ -#define SPEEX_PREPROCESS_GET_AGC_GAIN 35 - -/* Can't set spectrum size */ -/** Get spectrum size for power spectrum (int32) */ -#define SPEEX_PREPROCESS_GET_PSD_SIZE 37 - -/* Can't set power spectrum */ -/** Get power spectrum (int32[] of squared values) */ -#define SPEEX_PREPROCESS_GET_PSD 39 - -/* Can't set noise size */ -/** Get spectrum size for noise estimate (int32) */ -#define SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE 41 - -/* Can't set noise estimate */ -/** Get noise estimate (int32[] of squared values) */ -#define SPEEX_PREPROCESS_GET_NOISE_PSD 43 - -/* Can't set speech probability */ -/** Get speech probability in last frame (int32). */ -#define SPEEX_PREPROCESS_GET_PROB 45 - -/** Set preprocessor Automatic Gain Control level (int32) */ -#define SPEEX_PREPROCESS_SET_AGC_TARGET 46 -/** Get preprocessor Automatic Gain Control level (int32) */ -#define SPEEX_PREPROCESS_GET_AGC_TARGET 47 - -#ifdef __cplusplus -} -#endif - -/** @}*/ -#endif diff --git a/include/speex/speex_resampler.h b/include/speex/speex_resampler.h deleted file mode 100644 index 4d5913f..0000000 --- a/include/speex/speex_resampler.h +++ /dev/null @@ -1,344 +0,0 @@ -/* Copyright (C) 2007 Jean-Marc Valin - - File: speex_resampler.h - Resampling code - - The design goals of this code are: - - Very fast algorithm - - Low memory requirement - - Good *perceptual* quality (and not best SNR) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef SPEEX_RESAMPLER_H -#define SPEEX_RESAMPLER_H - -#ifdef OUTSIDE_SPEEX - -/********* WARNING: MENTAL SANITY ENDS HERE *************/ - -/* If the resampler is defined outside of Speex, we change the symbol names so that - there won't be any clash if linking with Speex later on. */ - -/* #define RANDOM_PREFIX your software name here */ -#ifndef RANDOM_PREFIX -#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes" -#endif - -#define CAT_PREFIX2(a,b) a ## b -#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) - -#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) -#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) -#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) -#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float) -#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int) -#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float) -#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int) -#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate) -#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate) -#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac) -#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio) -#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality) -#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) -#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) -#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) -#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) -#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) -#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency) -#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency) -#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) -#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) -#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) - -#define spx_int16_t short -#define spx_int32_t int -#define spx_uint16_t unsigned short -#define spx_uint32_t unsigned int - -#else /* OUTSIDE_SPEEX */ - -#ifdef _BUILD_SPEEX -# include "speex_types.h" -#else -# include -#endif - -#endif /* OUTSIDE_SPEEX */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SPEEX_RESAMPLER_QUALITY_MAX 10 -#define SPEEX_RESAMPLER_QUALITY_MIN 0 -#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 -#define SPEEX_RESAMPLER_QUALITY_VOIP 3 -#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 - -enum { - RESAMPLER_ERR_SUCCESS = 0, - RESAMPLER_ERR_ALLOC_FAILED = 1, - RESAMPLER_ERR_BAD_STATE = 2, - RESAMPLER_ERR_INVALID_ARG = 3, - RESAMPLER_ERR_PTR_OVERLAP = 4, - - RESAMPLER_ERR_MAX_ERROR -}; - -struct SpeexResamplerState_; -typedef struct SpeexResamplerState_ SpeexResamplerState; - -/** Create a new resampler with integer input and output rates. - * @param nb_channels Number of channels to be processed - * @param in_rate Input sampling rate (integer number of Hz). - * @param out_rate Output sampling rate (integer number of Hz). - * @param quality Resampling quality between 0 and 10, where 0 has poor quality - * and 10 has very high quality. - * @return Newly created resampler state - * @retval NULL Error: not enough memory - */ -SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, - spx_uint32_t in_rate, - spx_uint32_t out_rate, - int quality, - int *err); - -/** Create a new resampler with fractional input/output rates. The sampling - * rate ratio is an arbitrary rational number with both the numerator and - * denominator being 32-bit integers. - * @param nb_channels Number of channels to be processed - * @param ratio_num Numerator of the sampling rate ratio - * @param ratio_den Denominator of the sampling rate ratio - * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). - * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). - * @param quality Resampling quality between 0 and 10, where 0 has poor quality - * and 10 has very high quality. - * @return Newly created resampler state - * @retval NULL Error: not enough memory - */ -SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, - spx_uint32_t ratio_num, - spx_uint32_t ratio_den, - spx_uint32_t in_rate, - spx_uint32_t out_rate, - int quality, - int *err); - -/** Destroy a resampler state. - * @param st Resampler state - */ -void speex_resampler_destroy(SpeexResamplerState *st); - -/** Resample a float array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param channel_index Index of the channel to process for the multi-channel - * base (0 otherwise) - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the - * number of samples processed - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written - */ -int speex_resampler_process_float(SpeexResamplerState *st, - spx_uint32_t channel_index, - const float *in, - spx_uint32_t *in_len, - float *out, - spx_uint32_t *out_len); - -/** Resample an int array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param channel_index Index of the channel to process for the multi-channel - * base (0 otherwise) - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the number - * of samples processed - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written - */ -int speex_resampler_process_int(SpeexResamplerState *st, - spx_uint32_t channel_index, - const spx_int16_t *in, - spx_uint32_t *in_len, - spx_int16_t *out, - spx_uint32_t *out_len); - -/** Resample an interleaved float array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the number - * of samples processed. This is all per-channel. - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written. - * This is all per-channel. - */ -int speex_resampler_process_interleaved_float(SpeexResamplerState *st, - const float *in, - spx_uint32_t *in_len, - float *out, - spx_uint32_t *out_len); - -/** Resample an interleaved int array. The input and output buffers must *not* overlap. - * @param st Resampler state - * @param in Input buffer - * @param in_len Number of input samples in the input buffer. Returns the number - * of samples processed. This is all per-channel. - * @param out Output buffer - * @param out_len Size of the output buffer. Returns the number of samples written. - * This is all per-channel. - */ -int speex_resampler_process_interleaved_int(SpeexResamplerState *st, - const spx_int16_t *in, - spx_uint32_t *in_len, - spx_int16_t *out, - spx_uint32_t *out_len); - -/** Set (change) the input/output sampling rates (integer value). - * @param st Resampler state - * @param in_rate Input sampling rate (integer number of Hz). - * @param out_rate Output sampling rate (integer number of Hz). - */ -int speex_resampler_set_rate(SpeexResamplerState *st, - spx_uint32_t in_rate, - spx_uint32_t out_rate); - -/** Get the current input/output sampling rates (integer value). - * @param st Resampler state - * @param in_rate Input sampling rate (integer number of Hz) copied. - * @param out_rate Output sampling rate (integer number of Hz) copied. - */ -void speex_resampler_get_rate(SpeexResamplerState *st, - spx_uint32_t *in_rate, - spx_uint32_t *out_rate); - -/** Set (change) the input/output sampling rates and resampling ratio - * (fractional values in Hz supported). - * @param st Resampler state - * @param ratio_num Numerator of the sampling rate ratio - * @param ratio_den Denominator of the sampling rate ratio - * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). - * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). - */ -int speex_resampler_set_rate_frac(SpeexResamplerState *st, - spx_uint32_t ratio_num, - spx_uint32_t ratio_den, - spx_uint32_t in_rate, - spx_uint32_t out_rate); - -/** Get the current resampling ratio. This will be reduced to the least - * common denominator. - * @param st Resampler state - * @param ratio_num Numerator of the sampling rate ratio copied - * @param ratio_den Denominator of the sampling rate ratio copied - */ -void speex_resampler_get_ratio(SpeexResamplerState *st, - spx_uint32_t *ratio_num, - spx_uint32_t *ratio_den); - -/** Set (change) the conversion quality. - * @param st Resampler state - * @param quality Resampling quality between 0 and 10, where 0 has poor - * quality and 10 has very high quality. - */ -int speex_resampler_set_quality(SpeexResamplerState *st, - int quality); - -/** Get the conversion quality. - * @param st Resampler state - * @param quality Resampling quality between 0 and 10, where 0 has poor - * quality and 10 has very high quality. - */ -void speex_resampler_get_quality(SpeexResamplerState *st, - int *quality); - -/** Set (change) the input stride. - * @param st Resampler state - * @param stride Input stride - */ -void speex_resampler_set_input_stride(SpeexResamplerState *st, - spx_uint32_t stride); - -/** Get the input stride. - * @param st Resampler state - * @param stride Input stride copied - */ -void speex_resampler_get_input_stride(SpeexResamplerState *st, - spx_uint32_t *stride); - -/** Set (change) the output stride. - * @param st Resampler state - * @param stride Output stride - */ -void speex_resampler_set_output_stride(SpeexResamplerState *st, - spx_uint32_t stride); - -/** Get the output stride. - * @param st Resampler state copied - * @param stride Output stride - */ -void speex_resampler_get_output_stride(SpeexResamplerState *st, - spx_uint32_t *stride); - -/** Get the latency introduced by the resampler measured in input samples. - * @param st Resampler state - */ -int speex_resampler_get_input_latency(SpeexResamplerState *st); - -/** Get the latency introduced by the resampler measured in output samples. - * @param st Resampler state - */ -int speex_resampler_get_output_latency(SpeexResamplerState *st); - -/** Make sure that the first samples to go out of the resamplers don't have - * leading zeros. This is only useful before starting to use a newly created - * resampler. It is recommended to use that when resampling an audio file, as - * it will generate a file with the same length. For real-time processing, - * it is probably easier not to use this call (so that the output duration - * is the same for the first frame). - * @param st Resampler state - */ -int speex_resampler_skip_zeros(SpeexResamplerState *st); - -/** Reset a resampler so a new (unrelated) stream can be processed. - * @param st Resampler state - */ -int speex_resampler_reset_mem(SpeexResamplerState *st); - -/** Returns the English meaning for an error code - * @param err Error code - * @return English string - */ -const char *speex_resampler_strerror(int err); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libspeex/Makefile.am b/libspeex/Makefile.am index 6eef924..8ccad98 100644 --- a/libspeex/Makefile.am +++ b/libspeex/Makefile.am @@ -2,38 +2,33 @@ #AUTOMAKE_OPTIONS = no-dependencies if BUILD_VORBIS_PSY - VPSY_LIB=libspeexdsp.la VPSY_SOURCE=vorbis_psy.c +if BUILD_KISS_FFT + FFTSRC=kiss_fft.c _kiss_fft_guts.h kiss_fft.h kiss_fftr.c kiss_fftr.h +else +if BUILD_SMALLFT + FFTSRC=smallft.c +else + FFTSRC= +endif +endif else - VPSY_LIB= VPSY_SOURCE= + FFTSRC= endif -EXTRA_DIST=echo_diagnostic.m - INCLUDES = -I$(top_builddir)/include -I$(top_builddir) @OGG_CFLAGS@ @FFT_CFLAGS@ -lib_LTLIBRARIES = libspeex.la libspeexdsp.la +lib_LTLIBRARIES = libspeex.la # Sources for compilation in the library -libspeex_la_SOURCES = $(VPSY_SOURCE) cb_search.c exc_10_32_table.c exc_8_128_table.c \ +libspeex_la_SOURCES = $(VPSY_SOURCE) $(FFTSRC) cb_search.c exc_10_32_table.c exc_8_128_table.c \ filters.c gain_table.c hexc_table.c high_lsp_tables.c lsp.c \ ltp.c speex.c stereo.c vbr.c vq.c bits.c exc_10_16_table.c \ exc_20_32_table.c exc_5_256_table.c exc_5_64_table.c gain_table_lbr.c hexc_10_32_table.c \ lpc.c lsp_tables_nb.c modes.c modes_wb.c nb_celp.c quant_lsp.c sb_celp.c \ speex_callbacks.c speex_header.c window.c -if BUILD_KISS_FFT - FFTSRC=kiss_fft.c _kiss_fft_guts.h kiss_fft.h kiss_fftr.c kiss_fftr.h -else -if BUILD_SMALLFT - FFTSRC=smallft.c -else - FFTSRC= -endif -endif - -libspeexdsp_la_SOURCES = preprocess.c jitter.c mdf.c fftwrap.c filterbank.c resample.c buffer.c scal.c $(FFTSRC) noinst_HEADERS = arch.h bfin.h cb_search_arm4.h cb_search_bfin.h cb_search_sse.h \ filters.h filters_arm4.h filters_bfin.h filters_sse.h fixed_arm4.h \ @@ -41,22 +36,15 @@ noinst_HEADERS = arch.h bfin.h cb_search_arm4.h cb_search_bfin.h cb_search_s ltp_sse.h math_approx.h misc_bfin.h nb_celp.h quant_lsp.h sb_celp.h \ stack_alloc.h vbr.h vq.h vq_arm4.h vq_bfin.h vq_sse.h cb_search.h fftwrap.h \ filterbank.h fixed_generic.h lsp.h lsp_bfin.h ltp_bfin.h modes.h os_support.h \ - pseudofloat.h quant_lsp_bfin.h smallft.h vorbis_psy.h resample_sse.h + quant_lsp_bfin.h smallft.h vorbis_psy.h libspeex_la_LDFLAGS = -no-undefined -version-info @SPEEX_LT_CURRENT@:@SPEEX_LT_REVISION@:@SPEEX_LT_AGE@ -libspeexdsp_la_LDFLAGS = -no-undefined -version-info @SPEEX_LT_CURRENT@:@SPEEX_LT_REVISION@:@SPEEX_LT_AGE@ -noinst_PROGRAMS = testenc testenc_wb testenc_uwb testdenoise testecho testjitter +noinst_PROGRAMS = testenc testenc_wb testenc_uwb testenc_SOURCES = testenc.c -testenc_LDADD = libspeex.la $(VPSY_LIB) +testenc_LDADD = libspeex.la testenc_wb_SOURCES = testenc_wb.c -testenc_wb_LDADD = libspeex.la $(VPSY_LIB) +testenc_wb_LDADD = libspeex.la testenc_uwb_SOURCES = testenc_uwb.c -testenc_uwb_LDADD = libspeex.la $(VPSY_LIB) -testdenoise_SOURCES = testdenoise.c -testdenoise_LDADD = libspeexdsp.la @FFT_LIBS@ -testecho_SOURCES = testecho.c -testecho_LDADD = libspeexdsp.la @FFT_LIBS@ -testjitter_SOURCES = testjitter.c -testjitter_LDADD = libspeexdsp.la @FFT_LIBS@ +testenc_uwb_LDADD = libspeex.la diff --git a/libspeex/echo_diagnostic.m b/libspeex/echo_diagnostic.m deleted file mode 100644 index aebf390..0000000 --- a/libspeex/echo_diagnostic.m +++ /dev/null @@ -1,72 +0,0 @@ -% Attempts to diagnose AEC problems from recorded samples -% -% out = echo_diagnostic(rec_file, play_file, out_file, tail_length) -% -% Computes the full matrix inversion to cancel echo from the -% recording 'rec_file' using the far end signal 'play_file' using -% a filter length of 'tail_length'. The output is saved to 'out_file'. -function out = echo_diagnostic(rec_file, play_file, out_file, tail_length) - -F=fopen(rec_file,'rb'); -rec=fread(F,Inf,'short'); -fclose (F); -F=fopen(play_file,'rb'); -play=fread(F,Inf,'short'); -fclose (F); - -rec = [rec; zeros(1024,1)]; -play = [play; zeros(1024,1)]; - -N = length(rec); -corr = real(ifft(fft(rec).*conj(fft(play)))); -acorr = real(ifft(fft(play).*conj(fft(play)))); - -[a,b] = max(corr); - -if b > N/2 - b = b-N; -end -printf ("Far end to near end delay is %d samples\n", b); -if (b > .3*tail_length) - printf ('This is too much delay, try delaying the far-end signal a bit\n'); -else if (b < 0) - printf ('You have a negative delay, the echo canceller has no chance to cancel anything!\n'); - else - printf ('Delay looks OK.\n'); - end - end -end -N2 = round(N/2); -corr1 = real(ifft(fft(rec(1:N2)).*conj(fft(play(1:N2))))); -corr2 = real(ifft(fft(rec(N2+1:end)).*conj(fft(play(N2+1:end))))); - -[a,b1] = max(corr1); -if b1 > N2/2 - b1 = b1-N2; -end -[a,b2] = max(corr2); -if b2 > N2/2 - b2 = b2-N2; -end -drift = (b1-b2)/N2; -printf ('Drift estimate is %f%% (%d samples)\n', 100*drift, b1-b2); -if abs(b1-b2) < 10 - printf ('A drift of a few (+-10) samples is normal.\n'); -else - if abs(b1-b2) < 30 - printf ('There may be (not sure) excessive clock drift. Is the capture and playback done on the same soundcard?\n'); - else - printf ('Your clock is drifting! No way the AEC will be able to do anything with that. Most likely, you''re doing capture and playback from two different cards.\n'); - end - end -end -acorr(1) = .001+1.00001*acorr(1); -AtA = toeplitz(acorr(1:tail_length)); -bb = corr(1:tail_length); -h = AtA\bb; - -out = (rec - filter(h, 1, play)); - -F=fopen(out_file,'w'); -fwrite(F,out,'short'); -fclose (F); diff --git a/libspeex/jitter.c b/libspeex/jitter.c deleted file mode 100644 index 68240f1..0000000 --- a/libspeex/jitter.c +++ /dev/null @@ -1,843 +0,0 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: speex_jitter.h - - Adaptive jitter buffer for Speex - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -/* -TODO: -- Add short-term estimate -- Defensive programming - + warn when last returned < last desired (begative buffering) - + warn if update_delay not called between get() and tick() or is called twice in a row -- Linked list structure for holding the packets instead of the current fixed-size array - + return memory to a pool - + allow pre-allocation of the pool - + optional max number of elements -- Statistics - + drift - + loss - + late - + jitter - + buffering delay -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#include "arch.h" -#include "../include/speex/speex.h" -#include "../include/speex/speex_bits.h" -#include "../include/speex/speex_jitter.h" -#include "os_support.h" - -#ifndef NULL -#define NULL 0 -#endif - -#define SPEEX_JITTER_MAX_BUFFER_SIZE 200 /**< Maximum number of packets in jitter buffer */ - -#define TSUB(a,b) ((spx_int32_t)((a)-(b))) - -#define GT32(a,b) (((spx_int32_t)((a)-(b)))>0) -#define GE32(a,b) (((spx_int32_t)((a)-(b)))>=0) -#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0) -#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0) - -#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) - -#define MAX_TIMINGS 40 -#define MAX_BUFFERS 3 -#define TOP_DELAY 40 - -/** Buffer that keeps the time of arrival of the latest packets */ -struct TimingBuffer { - int filled; /**< Number of entries occupied in "timing" and "counts"*/ - int curr_count; /**< Number of packet timings we got (including those we discarded) */ - spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ - spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */ -}; - -static void tb_init(struct TimingBuffer *tb) -{ - tb->filled = 0; - tb->curr_count = 0; -} - -/* Add the timing of a new packet to the TimingBuffer */ -static void tb_add(struct TimingBuffer *tb, spx_int16_t timing) -{ - int pos; - /* Discard packet that won't make it into the list because they're too early */ - if (tb->filled >= MAX_TIMINGS && timing >= tb->timing[tb->filled-1]) - { - tb->curr_count++; - return; - } - - /* Find where the timing info goes in the sorted list */ - pos = 0; - /* FIXME: Do bisection instead of linear search */ - while (posfilled && timing >= tb->timing[pos]) - { - pos++; - } - - speex_assert(pos <= tb->filled && pos < MAX_TIMINGS); - - /* Shift everything so we can perform the insertion */ - if (pos < tb->filled) - { - int move_size = tb->filled-pos; - if (tb->filled == MAX_TIMINGS) - move_size -= 1; - SPEEX_MOVE(&tb->timing[pos+1], &tb->timing[pos], move_size); - SPEEX_MOVE(&tb->counts[pos+1], &tb->counts[pos], move_size); - } - /* Insert */ - tb->timing[pos] = timing; - tb->counts[pos] = tb->curr_count; - - tb->curr_count++; - if (tb->filledfilled++; -} - - - -/** Jitter buffer structure */ -struct JitterBuffer_ { - spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */ - spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */ - spx_uint32_t next_stop; /**< Estimated time the next get() will be called */ - - spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/ - - JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */ - spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */ - - void (*destroy) (void *); /**< Callback for destroying a packet */ - - spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */ - spx_int32_t concealment_size; /**< Size of the packet loss concealment "units" */ - int reset_state; /**< True if state was just reset */ - int buffer_margin; /**< How many frames we want to keep in the buffer (lower bound) */ - int late_cutoff; /**< How late must a packet be for it not to be considered at all */ - int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */ - int auto_adjust; /**< Whether to automatically adjust the delay at any time */ - - struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */ - struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */ - int window_size; /**< Total window over which the late frames are counted */ - int subwindow_size; /**< Sub-window size for faster computation */ - int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */ - int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */ - int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */ - - int lost_count; /**< Number of consecutive lost packets */ -}; - -/** Based on available data, this computes the optimal delay for the jitter buffer. - The optimised function is in timestamp units and is: - cost = delay + late_factor*[number of frames that would be late if we used that delay] - @param tb Array of buffers - @param late_factor Equivalent cost of a late frame (in timestamp units) - */ -static spx_int16_t compute_opt_delay(JitterBuffer *jitter) -{ - int i; - spx_int16_t opt=0; - spx_int32_t best_cost=0x7fffffff; - int late = 0; - int pos[MAX_BUFFERS]; - int tot_count; - float late_factor; - int penalty_taken = 0; - int best = 0; - int worst = 0; - spx_int32_t deltaT; - struct TimingBuffer *tb; - - tb = jitter->_tb; - - /* Number of packet timings we have received (including those we didn't keep) */ - tot_count = 0; - for (i=0;ilatency_tradeoff != 0) - late_factor = jitter->latency_tradeoff * 100.0f / tot_count; - else - late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count; - - /*fprintf(stderr, "late_factor = %f\n", late_factor);*/ - for (i=0;idelay_step); - pos[next]++; - - /* Actual cost function that tells us how bad using this delay would be */ - cost = -latest + late_factor*late; - /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/ - if (cost < best_cost) - { - best_cost = cost; - opt = latest; - } - } else { - break; - } - - /* For the next timing we will consider, there will be one more late packet to count */ - late++; - /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */ - if (latest >= 0 && !penalty_taken) - { - penalty_taken = 1; - late+=4; - } - } - - deltaT = best-worst; - /* This is a default "automatic latency tradeoff" when none is provided */ - jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY; - /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/ - - /* FIXME: Compute a short-term estimate too and combine with the long-term one */ - - /* Prevents reducing the buffer size when we haven't really had much data */ - if (tot_count < TOP_DELAY && opt > 0) - return 0; - return opt; -} - - -/** Initialise jitter buffer */ -EXPORT JitterBuffer *jitter_buffer_init(int step_size) -{ - JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); - if (jitter) - { - int i; - spx_int32_t tmp; - for (i=0;ipackets[i].data=NULL; - jitter->delay_step = step_size; - jitter->concealment_size = step_size; - /*FIXME: Should this be 0 or 1?*/ - jitter->buffer_margin = 0; - jitter->late_cutoff = 50; - jitter->destroy = NULL; - jitter->latency_tradeoff = 0; - jitter->auto_adjust = 1; - tmp = 4; - jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MAX_LATE_RATE, &tmp); - jitter_buffer_reset(jitter); - } - return jitter; -} - -/** Reset jitter buffer */ -EXPORT void jitter_buffer_reset(JitterBuffer *jitter) -{ - int i; - for (i=0;ipackets[i].data) - { - if (jitter->destroy) - jitter->destroy(jitter->packets[i].data); - else - speex_free(jitter->packets[i].data); - jitter->packets[i].data = NULL; - } - } - /* Timestamp is actually undefined at this point */ - jitter->pointer_timestamp = 0; - jitter->next_stop = 0; - jitter->reset_state = 1; - jitter->lost_count = 0; - jitter->buffered = 0; - jitter->auto_tradeoff = 32000; - - for (i=0;i_tb[i]); - jitter->timeBuffers[i] = &jitter->_tb[i]; - } - /*fprintf (stderr, "reset\n");*/ -} - -/** Destroy jitter buffer */ -EXPORT void jitter_buffer_destroy(JitterBuffer *jitter) -{ - jitter_buffer_reset(jitter); - speex_free(jitter); -} - -/** Take the following timing into consideration for future calculations */ -static void update_timings(JitterBuffer *jitter, spx_int32_t timing) -{ - if (timing < -32767) - timing = -32767; - if (timing > 32767) - timing = 32767; - /* If the current sub-window is full, perform a rotation and discard oldest sub-widow */ - if (jitter->timeBuffers[0]->curr_count >= jitter->subwindow_size) - { - int i; - /*fprintf(stderr, "Rotate buffer\n");*/ - struct TimingBuffer *tmp = jitter->timeBuffers[MAX_BUFFERS-1]; - for (i=MAX_BUFFERS-1;i>=1;i--) - jitter->timeBuffers[i] = jitter->timeBuffers[i-1]; - jitter->timeBuffers[0] = tmp; - tb_init(jitter->timeBuffers[0]); - } - tb_add(jitter->timeBuffers[0], timing); -} - -/** Compensate all timings when we do an adjustment of the buffering */ -static void shift_timings(JitterBuffer *jitter, spx_int16_t amount) -{ - int i, j; - for (i=0;itimeBuffers[i]->filled;j++) - jitter->timeBuffers[i]->timing[j] += amount; - } -} - - -/** Put one packet into the jitter buffer */ -EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) -{ - int i,j; - int late; - /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ - - /* Cleanup buffer (remove old packets that weren't played) */ - if (!jitter->reset_state) - { - for (i=0;ipackets[i].data && LE32(jitter->packets[i].timestamp + jitter->packets[i].span, jitter->pointer_timestamp)) - { - /*fprintf (stderr, "cleaned (not played)\n");*/ - if (jitter->destroy) - jitter->destroy(jitter->packets[i].data); - else - speex_free(jitter->packets[i].data); - jitter->packets[i].data = NULL; - } - } - } - - /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/ - /* Check if packet is late (could still be useful though) */ - if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) - { - update_timings(jitter, ((spx_int32_t)packet->timestamp) - ((spx_int32_t)jitter->next_stop) - jitter->buffer_margin); - late = 1; - } else { - late = 0; - } - - /* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is - * used to resync. */ - if (jitter->lost_count>20) - { - jitter_buffer_reset(jitter); - } - - /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */ - if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp)) - { - - /*Find an empty slot in the buffer*/ - for (i=0;ipackets[i].data==NULL) - break; - } - - /*No place left in the buffer, need to make room for it by discarding the oldest packet */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - int earliest=jitter->packets[0].timestamp; - i=0; - for (j=1;jpackets[i].data || LT32(jitter->packets[j].timestamp,earliest)) - { - earliest = jitter->packets[j].timestamp; - i=j; - } - } - if (jitter->destroy) - jitter->destroy(jitter->packets[i].data); - else - speex_free(jitter->packets[i].data); - jitter->packets[i].data=NULL; - /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/ - } - - /* Copy packet in buffer */ - if (jitter->destroy) - { - jitter->packets[i].data = packet->data; - } else { - jitter->packets[i].data=(char*)speex_alloc(packet->len); - for (j=0;jlen;j++) - jitter->packets[i].data[j]=packet->data[j]; - } - jitter->packets[i].timestamp=packet->timestamp; - jitter->packets[i].span=packet->span; - jitter->packets[i].len=packet->len; - jitter->packets[i].sequence=packet->sequence; - jitter->packets[i].user_data=packet->user_data; - if (jitter->reset_state || late) - jitter->arrival[i] = 0; - else - jitter->arrival[i] = jitter->next_stop; - } - - -} - -/** Get one packet from the jitter buffer */ -EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) -{ - int i; - unsigned int j; - int incomplete = 0; - spx_int16_t opt; - - if (start_offset != NULL) - *start_offset = 0; - - /* Syncing on the first call */ - if (jitter->reset_state) - { - int found = 0; - /* Find the oldest packet */ - spx_uint32_t oldest=0; - for (i=0;ipackets[i].data && (!found || LT32(jitter->packets[i].timestamp,oldest))) - { - oldest = jitter->packets[i].timestamp; - found = 1; - } - } - if (found) - { - jitter->reset_state=0; - jitter->pointer_timestamp = oldest; - jitter->next_stop = oldest; - } else { - packet->timestamp = 0; - packet->span = jitter->interp_requested; - return JITTER_BUFFER_MISSING; - } - } - - - jitter->last_returned_timestamp = jitter->pointer_timestamp; - - if (jitter->interp_requested != 0) - { - packet->timestamp = jitter->pointer_timestamp; - packet->span = jitter->interp_requested; - - /* Increment the pointer because it got decremented in the delay update */ - jitter->pointer_timestamp += jitter->interp_requested; - packet->len = 0; - /*fprintf (stderr, "Deferred interpolate\n");*/ - - jitter->interp_requested = 0; - - jitter->buffered = packet->span - desired_span; - - return JITTER_BUFFER_INSERTION; - } - - /* Searching for the packet that fits best */ - - /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ - for (i=0;ipackets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) - break; - } - - /* If no match, try for an "older" packet that still spans (fully) the current chunk */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - for (i=0;ipackets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) - break; - } - } - - /* If still no match, try for an "older" packet that spans part of the current chunk */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - for (i=0;ipackets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GT32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp)) - break; - } - } - - /* If still no match, try for earliest packet possible */ - if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) - { - int found = 0; - spx_uint32_t best_time=0; - int best_span=0; - int besti=0; - for (i=0;ipackets[i].data && LT32(jitter->packets[i].timestamp,jitter->pointer_timestamp+desired_span) && GE32(jitter->packets[i].timestamp,jitter->pointer_timestamp)) - { - if (!found || LT32(jitter->packets[i].timestamp,best_time) || (jitter->packets[i].timestamp==best_time && GT32(jitter->packets[i].span,best_span))) - { - best_time = jitter->packets[i].timestamp; - best_span = jitter->packets[i].span; - besti = i; - found = 1; - } - } - } - if (found) - { - i=besti; - incomplete = 1; - /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/ - } - } - - /* If we find something */ - if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) - { - spx_int32_t offset; - - /* We (obviously) haven't lost this packet */ - jitter->lost_count = 0; - - /* In this case, 0 isn't as a valid timestamp */ - if (jitter->arrival[i] != 0) - { - update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin); - } - - - /* Copy packet */ - if (jitter->destroy) - { - packet->data = jitter->packets[i].data; - packet->len = jitter->packets[i].len; - } else { - if (jitter->packets[i].len > packet->len) - { - speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len); - } else { - packet->len = jitter->packets[i].len; - } - for (j=0;jlen;j++) - packet->data[j] = jitter->packets[i].data[j]; - /* Remove packet */ - speex_free(jitter->packets[i].data); - } - jitter->packets[i].data = NULL; - /* Set timestamp and span (if requested) */ - offset = (spx_int32_t)jitter->packets[i].timestamp-(spx_int32_t)jitter->pointer_timestamp; - if (start_offset != NULL) - *start_offset = offset; - else if (offset != 0) - speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset); - - packet->timestamp = jitter->packets[i].timestamp; - jitter->last_returned_timestamp = packet->timestamp; - - packet->span = jitter->packets[i].span; - packet->sequence = jitter->packets[i].sequence; - packet->user_data = jitter->packets[i].user_data; - /* Point to the end of the current packet */ - jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span; - - jitter->buffered = packet->span - desired_span; - - if (start_offset != NULL) - jitter->buffered += *start_offset; - - return JITTER_BUFFER_OK; - } - - - /* If we haven't found anything worth returning */ - - /*fprintf (stderr, "not found\n");*/ - jitter->lost_count++; - /*fprintf (stderr, "m");*/ - /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/ - - opt = compute_opt_delay(jitter); - - /* Should we force an increase in the buffer or just do normal interpolation? */ - if (opt < 0) - { - /* Need to increase buffering */ - - /* Shift histogram to compensate */ - shift_timings(jitter, -opt); - - packet->timestamp = jitter->pointer_timestamp; - packet->span = -opt; - /* Don't move the pointer_timestamp forward */ - packet->len = 0; - - jitter->buffered = packet->span - desired_span; - return JITTER_BUFFER_INSERTION; - /*jitter->pointer_timestamp -= jitter->delay_step;*/ - /*fprintf (stderr, "Forced to interpolate\n");*/ - } else { - /* Normal packet loss */ - packet->timestamp = jitter->pointer_timestamp; - - desired_span = ROUND_DOWN(desired_span, jitter->concealment_size); - packet->span = desired_span; - jitter->pointer_timestamp += desired_span; - packet->len = 0; - - jitter->buffered = packet->span - desired_span; - return JITTER_BUFFER_MISSING; - /*fprintf (stderr, "Normal loss\n");*/ - } - - -} - -EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) -{ - int i, j; - for (i=0;ipackets[i].data && jitter->packets[i].timestamp==jitter->last_returned_timestamp) - break; - } - if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) - { - /* Copy packet */ - packet->len = jitter->packets[i].len; - if (jitter->destroy) - { - packet->data = jitter->packets[i].data; - } else { - for (j=0;jlen;j++) - packet->data[j] = jitter->packets[i].data[j]; - /* Remove packet */ - speex_free(jitter->packets[i].data); - } - jitter->packets[i].data = NULL; - packet->timestamp = jitter->packets[i].timestamp; - packet->span = jitter->packets[i].span; - packet->sequence = jitter->packets[i].sequence; - packet->user_data = jitter->packets[i].user_data; - return JITTER_BUFFER_OK; - } else { - packet->data = NULL; - packet->len = 0; - packet->span = 0; - return JITTER_BUFFER_MISSING; - } -} - -/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ -static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) -{ - spx_int16_t opt = compute_opt_delay(jitter); - /*fprintf(stderr, "opt adjustment is %d ", opt);*/ - - if (opt < 0) - { - shift_timings(jitter, -opt); - - jitter->pointer_timestamp += opt; - jitter->interp_requested = -opt; - /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/ - } else if (opt > 0) - { - shift_timings(jitter, -opt); - jitter->pointer_timestamp += opt; - /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/ - } - - return opt; -} - -/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ -EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) -{ - /* If the programmer calls jitter_buffer_update_delay() directly, - automatically disable auto-adjustment */ - jitter->auto_adjust = 0; - - return _jitter_buffer_update_delay(jitter, packet, start_offset); -} - -/** Get pointer timestamp of jitter buffer */ -EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) -{ - return jitter->pointer_timestamp; -} - -EXPORT void jitter_buffer_tick(JitterBuffer *jitter) -{ - /* Automatically-adjust the buffering delay if requested */ - if (jitter->auto_adjust) - _jitter_buffer_update_delay(jitter, NULL, NULL); - - if (jitter->buffered >= 0) - { - jitter->next_stop = jitter->pointer_timestamp - jitter->buffered; - } else { - jitter->next_stop = jitter->pointer_timestamp; - speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); - } - jitter->buffered = 0; -} - -EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) -{ - /* Automatically-adjust the buffering delay if requested */ - if (jitter->auto_adjust) - _jitter_buffer_update_delay(jitter, NULL, NULL); - - if (jitter->buffered < 0) - speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); - jitter->next_stop = jitter->pointer_timestamp - rem; -} - - -/* Used like the ioctl function to control the jitter buffer parameters */ -EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) -{ - int count, i; - switch(request) - { - case JITTER_BUFFER_SET_MARGIN: - jitter->buffer_margin = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_MARGIN: - *(spx_int32_t*)ptr = jitter->buffer_margin; - break; - case JITTER_BUFFER_GET_AVALIABLE_COUNT: - count = 0; - for (i=0;ipackets[i].data && LE32(jitter->pointer_timestamp, jitter->packets[i].timestamp)) - { - count++; - } - } - *(spx_int32_t*)ptr = count; - break; - case JITTER_BUFFER_SET_DESTROY_CALLBACK: - jitter->destroy = (void (*) (void *))ptr; - break; - case JITTER_BUFFER_GET_DESTROY_CALLBACK: - *(void (**) (void *))ptr = jitter->destroy; - break; - case JITTER_BUFFER_SET_DELAY_STEP: - jitter->delay_step = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_DELAY_STEP: - *(spx_int32_t*)ptr = jitter->delay_step; - break; - case JITTER_BUFFER_SET_CONCEALMENT_SIZE: - jitter->concealment_size = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_CONCEALMENT_SIZE: - *(spx_int32_t*)ptr = jitter->concealment_size; - break; - case JITTER_BUFFER_SET_MAX_LATE_RATE: - jitter->max_late_rate = *(spx_int32_t*)ptr; - jitter->window_size = 100*TOP_DELAY/jitter->max_late_rate; - jitter->subwindow_size = jitter->window_size/MAX_BUFFERS; - break; - case JITTER_BUFFER_GET_MAX_LATE_RATE: - *(spx_int32_t*)ptr = jitter->max_late_rate; - break; - case JITTER_BUFFER_SET_LATE_COST: - jitter->latency_tradeoff = *(spx_int32_t*)ptr; - break; - case JITTER_BUFFER_GET_LATE_COST: - *(spx_int32_t*)ptr = jitter->latency_tradeoff; - break; - default: - speex_warning_int("Unknown jitter_buffer_ctl request: ", request); - return -1; - } - return 0; -} - diff --git a/libspeex/mdf.c b/libspeex/mdf.c deleted file mode 100644 index 8a5c031..0000000 --- a/libspeex/mdf.c +++ /dev/null @@ -1,1285 +0,0 @@ -/* Copyright (C) 2003-2008 Jean-Marc Valin - - File: mdf.c - Echo canceller based on the MDF algorithm (see below) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - The echo canceller is based on the MDF algorithm described in: - - J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, - IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, - February 1990. - - We use the Alternatively Updated MDF (AUMDF) variant. Robustness to - double-talk is achieved using a variable learning rate as described in: - - Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo - Cancellation With Double-Talk. IEEE Transactions on Audio, - Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007. - http://people.xiph.org/~jm/papers/valin_taslp2006.pdf - - There is no explicit double-talk detection, but a continuous variation - in the learning rate based on residual echo, double-talk and background - noise. - - About the fixed-point version: - All the signals are represented with 16-bit words. The filter weights - are represented with 32-bit words, but only the top 16 bits are used - in most cases. The lower 16 bits are completely unreliable (due to the - fact that the update is done only on the top bits), but help in the - adaptation -- probably by removing a "threshold effect" due to - quantization (rounding going to zero) when the gradient is small. - - Another kludge that seems to work good: when performing the weight - update, we only move half the way toward the "goal" this seems to - reduce the effect of quantization noise in the update phase. This - can be seen as applying a gradient descent on a "soft constraint" - instead of having a hard constraint. - -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "arch.h" -#include "../include/speex/speex_echo.h" -#include "fftwrap.h" -#include "pseudofloat.h" -#include "math_approx.h" -#include "os_support.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#ifdef FIXED_POINT -#define WEIGHT_SHIFT 11 -#define NORMALIZE_SCALEDOWN 5 -#define NORMALIZE_SCALEUP 3 -#else -#define WEIGHT_SHIFT 0 -#endif - -#ifdef FIXED_POINT -#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) -#else -#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) -#endif - -/* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk - and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */ -#define TWO_PATH - -#ifdef FIXED_POINT -static const spx_float_t MIN_LEAK = {20972, -22}; - -/* Constants for the two-path filter */ -static const spx_float_t VAR1_SMOOTH = {23593, -16}; -static const spx_float_t VAR2_SMOOTH = {23675, -15}; -static const spx_float_t VAR1_UPDATE = {16384, -15}; -static const spx_float_t VAR2_UPDATE = {16384, -16}; -static const spx_float_t VAR_BACKTRACK = {16384, -12}; -#define TOP16(x) ((x)>>16) - -#else - -static const spx_float_t MIN_LEAK = .005f; - -/* Constants for the two-path filter */ -static const spx_float_t VAR1_SMOOTH = .36f; -static const spx_float_t VAR2_SMOOTH = .7225f; -static const spx_float_t VAR1_UPDATE = .5f; -static const spx_float_t VAR2_UPDATE = .25f; -static const spx_float_t VAR_BACKTRACK = 4.f; -#define TOP16(x) (x) -#endif - - -#define PLAYBACK_DELAY 2 - -void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len); - - -/** Speex echo cancellation state. */ -struct SpeexEchoState_ { - int frame_size; /**< Number of samples processed each time */ - int window_size; - int M; - int cancel_count; - int adapted; - int saturated; - int screwed_up; - int C; /** Number of input channels (microphones) */ - int K; /** Number of output channels (loudspeakers) */ - spx_int32_t sampling_rate; - spx_word16_t spec_average; - spx_word16_t beta0; - spx_word16_t beta_max; - spx_word32_t sum_adapt; - spx_word16_t leak_estimate; - - spx_word16_t *e; /* scratch */ - spx_word16_t *x; /* Far-end input buffer (2N) */ - spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */ - spx_word16_t *input; /* scratch */ - spx_word16_t *y; /* scratch */ - spx_word16_t *last_y; - spx_word16_t *Y; /* scratch */ - spx_word16_t *E; - spx_word32_t *PHI; /* scratch */ - spx_word32_t *W; /* (Background) filter weights */ -#ifdef TWO_PATH - spx_word16_t *foreground; /* Foreground filter weights */ - spx_word32_t Davg1; /* 1st recursive average of the residual power difference */ - spx_word32_t Davg2; /* 2nd recursive average of the residual power difference */ - spx_float_t Dvar1; /* Estimated variance of 1st estimator */ - spx_float_t Dvar2; /* Estimated variance of 2nd estimator */ -#endif - spx_word32_t *power; /* Power of the far-end signal */ - spx_float_t *power_1;/* Inverse power of far-end */ - spx_word16_t *wtmp; /* scratch */ -#ifdef FIXED_POINT - spx_word16_t *wtmp2; /* scratch */ -#endif - spx_word32_t *Rf; /* scratch */ - spx_word32_t *Yf; /* scratch */ - spx_word32_t *Xf; /* scratch */ - spx_word32_t *Eh; - spx_word32_t *Yh; - spx_float_t Pey; - spx_float_t Pyy; - spx_word16_t *window; - spx_word16_t *prop; - void *fft_table; - spx_word16_t *memX, *memD, *memE; - spx_word16_t preemph; - spx_word16_t notch_radius; - spx_mem_t *notch_mem; - - /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ - spx_int16_t *play_buf; - int play_buf_pos; - int play_buf_started; -}; - -static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride) -{ - int i; - spx_word16_t den2; -#ifdef FIXED_POINT - den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius)); -#else - den2 = radius*radius + .7*(1-radius)*(1-radius); -#endif - /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ - for (i=0;i>= 1; - while(len--) - { - spx_word32_t part=0; - part = MAC16_16(part,*x++,*y++); - part = MAC16_16(part,*x++,*y++); - /* HINT: If you had a 40-bit accumulator, you could shift only at the end */ - sum = ADD32(sum,SHR32(part,6)); - } - return sum; -} - -/** Compute power spectrum of a half-complex (packed) vector */ -static inline void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N) -{ - int i, j; - ps[0]=MULT16_16(X[0],X[0]); - for (i=1,j=1;i max_sum) - max_sum = prop[i]; - } - for (i=0;i -static FILE *rFile=NULL, *pFile=NULL, *oFile=NULL; - -static void dump_audio(const spx_int16_t *rec, const spx_int16_t *play, const spx_int16_t *out, int len) -{ - if (!(rFile && pFile && oFile)) - { - speex_fatal("Dump files not open"); - } - fwrite(rec, sizeof(spx_int16_t), len, rFile); - fwrite(play, sizeof(spx_int16_t), len, pFile); - fwrite(out, sizeof(spx_int16_t), len, oFile); -} -#endif - -/** Creates a new echo canceller state */ -EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) -{ - return speex_echo_state_init_mc(frame_size, filter_length, 1, 1); -} - -EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers) -{ - int i,N,M, C, K; - SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState)); - - st->K = nb_speakers; - st->C = nb_mic; - C=st->C; - K=st->K; -#ifdef DUMP_ECHO_CANCEL_DATA - if (rFile || pFile || oFile) - speex_fatal("Opening dump files twice"); - rFile = fopen("aec_rec.sw", "wb"); - pFile = fopen("aec_play.sw", "wb"); - oFile = fopen("aec_out.sw", "wb"); -#endif - - st->frame_size = frame_size; - st->window_size = 2*frame_size; - N = st->window_size; - M = st->M = (filter_length+st->frame_size-1)/frame_size; - st->cancel_count=0; - st->sum_adapt = 0; - st->saturated = 0; - st->screwed_up = 0; - /* This is the default sampling rate */ - st->sampling_rate = 8000; - st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); -#ifdef FIXED_POINT - st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); - st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); -#else - st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; - st->beta_max = (.5f*st->frame_size)/st->sampling_rate; -#endif - st->leak_estimate = 0; - - st->fft_table = spx_fft_init(N); - - st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t)); - st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t)); - st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); - - st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t)); - st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); - st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t)); -#ifdef TWO_PATH - st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t)); -#endif - st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t)); - st->power_1 = (spx_float_t*)speex_alloc((frame_size+1)*sizeof(spx_float_t)); - st->window = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); - st->prop = (spx_word16_t*)speex_alloc(M*sizeof(spx_word16_t)); - st->wtmp = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); -#ifdef FIXED_POINT - st->wtmp2 = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); - for (i=0;i>1;i++) - { - st->window[i] = (16383-SHL16(spx_cos(DIV32_16(MULT16_16(25736,i<<1),N)),1)); - st->window[N-i-1] = st->window[i]; - } -#else - for (i=0;iwindow[i] = .5-.5*cos(2*M_PI*i/N); -#endif - for (i=0;i<=st->frame_size;i++) - st->power_1[i] = FLOAT_ONE; - for (i=0;iW[i] = 0; - { - spx_word32_t sum = 0; - /* Ratio of ~10 between adaptation rate of first and last block */ - spx_word16_t decay = SHR32(spx_exp(NEG16(DIV32_16(QCONST16(2.4,11),M))),1); - st->prop[0] = QCONST16(.7, 15); - sum = EXTEND32(st->prop[0]); - for (i=1;iprop[i] = MULT16_16_Q15(st->prop[i-1], decay); - sum = ADD32(sum, EXTEND32(st->prop[i])); - } - for (i=M-1;i>=0;i--) - { - st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum); - } - } - - st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t)); - st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); - st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); - st->preemph = QCONST16(.9,15); - if (st->sampling_rate<12000) - st->notch_radius = QCONST16(.9, 15); - else if (st->sampling_rate<24000) - st->notch_radius = QCONST16(.982, 15); - else - st->notch_radius = QCONST16(.992, 15); - - st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t)); - st->adapted = 0; - st->Pey = st->Pyy = FLOAT_ONE; - -#ifdef TWO_PATH - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; -#endif - - st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); - st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; - st->play_buf_started = 0; - - return st; -} - -/** Resets echo canceller state */ -EXPORT void speex_echo_state_reset(SpeexEchoState *st) -{ - int i, M, N, C, K; - st->cancel_count=0; - st->screwed_up = 0; - N = st->window_size; - M = st->M; - C=st->C; - K=st->K; - for (i=0;iW[i] = 0; -#ifdef TWO_PATH - for (i=0;iforeground[i] = 0; -#endif - for (i=0;iX[i] = 0; - for (i=0;i<=st->frame_size;i++) - { - st->power[i] = 0; - st->power_1[i] = FLOAT_ONE; - st->Eh[i] = 0; - st->Yh[i] = 0; - } - for (i=0;iframe_size;i++) - { - st->last_y[i] = 0; - } - for (i=0;iE[i] = 0; - } - for (i=0;ix[i] = 0; - } - for (i=0;i<2*C;i++) - st->notch_mem[i] = 0; - for (i=0;imemD[i]=st->memE[i]=0; - for (i=0;imemX[i]=0; - - st->saturated = 0; - st->adapted = 0; - st->sum_adapt = 0; - st->Pey = st->Pyy = FLOAT_ONE; -#ifdef TWO_PATH - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; -#endif - for (i=0;i<3*st->frame_size;i++) - st->play_buf[i] = 0; - st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; - st->play_buf_started = 0; - -} - -/** Destroys an echo canceller state */ -EXPORT void speex_echo_state_destroy(SpeexEchoState *st) -{ - spx_fft_destroy(st->fft_table); - - speex_free(st->e); - speex_free(st->x); - speex_free(st->input); - speex_free(st->y); - speex_free(st->last_y); - speex_free(st->Yf); - speex_free(st->Rf); - speex_free(st->Xf); - speex_free(st->Yh); - speex_free(st->Eh); - - speex_free(st->X); - speex_free(st->Y); - speex_free(st->E); - speex_free(st->W); -#ifdef TWO_PATH - speex_free(st->foreground); -#endif - speex_free(st->PHI); - speex_free(st->power); - speex_free(st->power_1); - speex_free(st->window); - speex_free(st->prop); - speex_free(st->wtmp); -#ifdef FIXED_POINT - speex_free(st->wtmp2); -#endif - speex_free(st->memX); - speex_free(st->memD); - speex_free(st->memE); - speex_free(st->notch_mem); - - speex_free(st->play_buf); - speex_free(st); - -#ifdef DUMP_ECHO_CANCEL_DATA - fclose(rFile); - fclose(pFile); - fclose(oFile); - rFile = pFile = oFile = NULL; -#endif -} - -EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) -{ - int i; - /*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/ - st->play_buf_started = 1; - if (st->play_buf_pos>=st->frame_size) - { - speex_echo_cancellation(st, rec, st->play_buf, out); - st->play_buf_pos -= st->frame_size; - for (i=0;iplay_buf_pos;i++) - st->play_buf[i] = st->play_buf[i+st->frame_size]; - } else { - speex_warning("No playback frame available (your application is buggy and/or got xruns)"); - if (st->play_buf_pos!=0) - { - speex_warning("internal playback buffer corruption?"); - st->play_buf_pos = 0; - } - for (i=0;iframe_size;i++) - out[i] = rec[i]; - } -} - -EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) -{ - /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/ - if (!st->play_buf_started) - { - speex_warning("discarded first playback frame"); - return; - } - if (st->play_buf_pos<=PLAYBACK_DELAY*st->frame_size) - { - int i; - for (i=0;iframe_size;i++) - st->play_buf[st->play_buf_pos+i] = play[i]; - st->play_buf_pos += st->frame_size; - if (st->play_buf_pos <= (PLAYBACK_DELAY-1)*st->frame_size) - { - speex_warning("Auto-filling the buffer (your application is buggy and/or got xruns)"); - for (i=0;iframe_size;i++) - st->play_buf[st->play_buf_pos+i] = play[i]; - st->play_buf_pos += st->frame_size; - } - } else { - speex_warning("Had to discard a playback frame (your application is buggy and/or got xruns)"); - } -} - -/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */ -EXPORT void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) -{ - speex_echo_cancellation(st, in, far_end, out); -} - -/** Performs echo cancellation on a frame */ -EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) -{ - int i,j, chan, speak; - int N,M, C, K; - spx_word32_t Syy,See,Sxx,Sdd, Sff; -#ifdef TWO_PATH - spx_word32_t Dbf; - int update_foreground; -#endif - spx_word32_t Sey; - spx_word16_t ss, ss_1; - spx_float_t Pey = FLOAT_ONE, Pyy=FLOAT_ONE; - spx_float_t alpha, alpha_1; - spx_word16_t RER; - spx_word32_t tmp32; - - N = st->window_size; - M = st->M; - C = st->C; - K = st->K; - - st->cancel_count++; -#ifdef FIXED_POINT - ss=DIV32_16(11469,M); - ss_1 = SUB16(32767,ss); -#else - ss=.35/M; - ss_1 = 1-ss; -#endif - - for (chan = 0; chan < C; chan++) - { - /* Apply a notch filter to make sure DC doesn't end up causing problems */ - filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C); - /* Copy input data to buffer and apply pre-emphasis */ - /* Copy input data to buffer */ - for (i=0;iframe_size;i++) - { - spx_word32_t tmp32; - /* FIXME: This core has changed a bit, need to merge properly */ - tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan]))); -#ifdef FIXED_POINT - if (tmp32 > 32767) - { - tmp32 = 32767; - if (st->saturated == 0) - st->saturated = 1; - } - if (tmp32 < -32767) - { - tmp32 = -32767; - if (st->saturated == 0) - st->saturated = 1; - } -#endif - st->memD[chan] = st->input[chan*st->frame_size+i]; - st->input[chan*st->frame_size+i] = EXTRACT16(tmp32); - } - } - - for (speak = 0; speak < K; speak++) - { - for (i=0;iframe_size;i++) - { - spx_word32_t tmp32; - st->x[speak*N+i] = st->x[speak*N+i+st->frame_size]; - tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak]))); -#ifdef FIXED_POINT - /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */ - if (tmp32 > 32767) - { - tmp32 = 32767; - st->saturated = M+1; - } - if (tmp32 < -32767) - { - tmp32 = -32767; - st->saturated = M+1; - } -#endif - st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32); - st->memX[speak] = far_end[i*K+speak]; - } - } - - for (speak = 0; speak < K; speak++) - { - /* Shift memory: this could be optimized eventually*/ - for (j=M-1;j>=0;j--) - { - for (i=0;iX[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i]; - } - /* Convert x (echo input) to frequency domain */ - spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]); - } - - Sxx = 0; - for (speak = 0; speak < K; speak++) - { - Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); - power_spectrum_accum(st->X+speak*N, st->Xf, N); - } - - Sff = 0; - for (chan = 0; chan < C; chan++) - { -#ifdef TWO_PATH - /* Compute foreground filter */ - spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K); - spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N); - for (i=0;iframe_size;i++) - st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]); - Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); -#endif - } - - /* Adjust proportional adaption rate */ - /* FIXME: Adjust that for C, K*/ - if (st->adapted) - mdf_adjust_prop (st->W, N, M, C*K, st->prop); - /* Compute weight gradient */ - if (st->saturated == 0) - { - for (chan = 0; chan < C; chan++) - { - for (speak = 0; speak < K; speak++) - { - for (j=M-1;j>=0;j--) - { - weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N*K+speak*N], st->E+chan*N, st->PHI, N); - for (i=0;iW[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i]; - } - } - } - } else { - st->saturated--; - } - - /* FIXME: MC conversion required */ - /* Update weight to prevent circular convolution (MDF / AUMDF) */ - for (chan = 0; chan < C; chan++) - { - for (speak = 0; speak < K; speak++) - { - for (j=0;jcancel_count%(M-1) == j-1) - { -#ifdef FIXED_POINT - for (i=0;iwtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16)); - spx_ifft(st->fft_table, st->wtmp2, st->wtmp); - for (i=0;iframe_size;i++) - { - st->wtmp[i]=0; - } - for (i=st->frame_size;iwtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); - } - spx_fft(st->fft_table, st->wtmp, st->wtmp2); - /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ - for (i=0;iW[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); -#else - spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp); - for (i=st->frame_size;iwtmp[i]=0; - } - spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]); -#endif - } - } - } - } - - /* So we can use power_spectrum_accum */ - for (i=0;i<=st->frame_size;i++) - st->Rf[i] = st->Yf[i] = st->Xf[i] = 0; - - Dbf = 0; - See = 0; -#ifdef TWO_PATH - /* Difference in response, this is used to estimate the variance of our residual power estimate */ - for (chan = 0; chan < C; chan++) - { - spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K); - spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N); - for (i=0;iframe_size;i++) - st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]); - Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); - for (i=0;iframe_size;i++) - st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); - See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); - } -#endif - -#ifndef TWO_PATH - Sff = See; -#endif - -#ifdef TWO_PATH - /* Logic for updating the foreground filter */ - - /* For two time windows, compute the mean of the energy difference, as well as the variance */ - st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See))); - st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See))); - st->Dvar1 = FLOAT_ADD(FLOAT_MULT(VAR1_SMOOTH, st->Dvar1), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff), MULT16_32_Q15(QCONST16(.4f,15),Dbf))); - st->Dvar2 = FLOAT_ADD(FLOAT_MULT(VAR2_SMOOTH, st->Dvar2), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff), MULT16_32_Q15(QCONST16(.15f,15),Dbf))); - - /* Equivalent float code: - st->Davg1 = .6*st->Davg1 + .4*(Sff-See); - st->Davg2 = .85*st->Davg2 + .15*(Sff-See); - st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf; - st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf; - */ - - update_foreground = 0; - /* Check if we have a statistically significant reduction in the residual echo */ - /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */ - if (FLOAT_GT(FLOAT_MUL32U(SUB32(Sff,See),ABS32(SUB32(Sff,See))), FLOAT_MUL32U(Sff,Dbf))) - update_foreground = 1; - else if (FLOAT_GT(FLOAT_MUL32U(st->Davg1, ABS32(st->Davg1)), FLOAT_MULT(VAR1_UPDATE,(st->Dvar1)))) - update_foreground = 1; - else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2)))) - update_foreground = 1; - - /* Do we update? */ - if (update_foreground) - { - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; - /* Copy background filter to foreground filter */ - for (i=0;iforeground[i] = EXTRACT16(PSHR32(st->W[i],16)); - /* Apply a smooth transition so as to not introduce blocking artifacts */ - for (chan = 0; chan < C; chan++) - for (i=0;iframe_size;i++) - st->e[chan*N+i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[chan*N+i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[chan*N+i+st->frame_size]); - } else { - int reset_background=0; - /* Otherwise, check if the background filter is significantly worse */ - if (FLOAT_GT(FLOAT_MUL32U(NEG32(SUB32(Sff,See)),ABS32(SUB32(Sff,See))), FLOAT_MULT(VAR_BACKTRACK,FLOAT_MUL32U(Sff,Dbf)))) - reset_background = 1; - if (FLOAT_GT(FLOAT_MUL32U(NEG32(st->Davg1), ABS32(st->Davg1)), FLOAT_MULT(VAR_BACKTRACK,st->Dvar1))) - reset_background = 1; - if (FLOAT_GT(FLOAT_MUL32U(NEG32(st->Davg2), ABS32(st->Davg2)), FLOAT_MULT(VAR_BACKTRACK,st->Dvar2))) - reset_background = 1; - if (reset_background) - { - /* Copy foreground filter to background filter */ - for (i=0;iW[i] = SHL32(EXTEND32(st->foreground[i]),16); - /* We also need to copy the output so as to get correct adaptation */ - for (chan = 0; chan < C; chan++) - { - for (i=0;iframe_size;i++) - st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size]; - for (i=0;iframe_size;i++) - st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); - } - See = Sff; - st->Davg1 = st->Davg2 = 0; - st->Dvar1 = st->Dvar2 = FLOAT_ZERO; - } - } -#endif - - Sey = Syy = Sdd = 0; - for (chan = 0; chan < C; chan++) - { - /* Compute error signal (for the output with de-emphasis) */ - for (i=0;iframe_size;i++) - { - spx_word32_t tmp_out; -#ifdef TWO_PATH - tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size])); -#else - tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size])); -#endif - tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan]))); - /* This is an arbitrary test for saturation in the microphone signal */ - if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000) - { - if (st->saturated == 0) - st->saturated = 1; - } - out[i*C+chan] = WORD2INT(tmp_out); - st->memE[chan] = tmp_out; - } - -#ifdef DUMP_ECHO_CANCEL_DATA - dump_audio(in, far_end, out, st->frame_size); -#endif - - /* Compute error signal (filter update version) */ - for (i=0;iframe_size;i++) - { - st->e[chan*N+i+st->frame_size] = st->e[chan*N+i]; - st->e[chan*N+i] = 0; - } - - /* Compute a bunch of correlations */ - /* FIXME: bad merge */ - Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); - Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); - Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size); - - /* Convert error to frequency domain */ - spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N); - for (i=0;iframe_size;i++) - st->y[i+chan*N] = 0; - spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N); - - /* Compute power spectrum of echo (X), error (E) and filter response (Y) */ - power_spectrum_accum(st->E+chan*N, st->Rf, N); - power_spectrum_accum(st->Y+chan*N, st->Yf, N); - - } - - /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/ - - /* Do some sanity check */ - if (!(Syy>=0 && Sxx>=0 && See >= 0) -#ifndef FIXED_POINT - || !(Sff < N*1e9 && Syy < N*1e9 && Sxx < N*1e9) -#endif - ) - { - /* Things have gone really bad */ - st->screwed_up += 50; - for (i=0;iframe_size*C;i++) - out[i] = 0; - } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6))) - { - /* AEC seems to add lots of echo instead of removing it, let's see if it will improve */ - st->screwed_up++; - } else { - /* Everything's fine */ - st->screwed_up=0; - } - if (st->screwed_up>=50) - { - speex_warning("The echo canceller started acting funny and got slapped (reset). It swears it will behave now."); - speex_echo_state_reset(st); - return; - } - - /* Add a small noise floor to make sure not to have problems when dividing */ - See = MAX32(See, SHR32(MULT16_16(N, 100),6)); - - for (speak = 0; speak < K; speak++) - { - Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); - power_spectrum_accum(st->X+speak*N, st->Xf, N); - } - - - /* Smooth far end energy estimate over time */ - for (j=0;j<=st->frame_size;j++) - st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]); - - /* Compute filtered spectra and (cross-)correlations */ - for (j=st->frame_size;j>=0;j--) - { - spx_float_t Eh, Yh; - Eh = PSEUDOFLOAT(st->Rf[j] - st->Eh[j]); - Yh = PSEUDOFLOAT(st->Yf[j] - st->Yh[j]); - Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh)); - Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh)); -#ifdef FIXED_POINT - st->Eh[j] = MAC16_32_Q15(MULT16_32_Q15(SUB16(32767,st->spec_average),st->Eh[j]), st->spec_average, st->Rf[j]); - st->Yh[j] = MAC16_32_Q15(MULT16_32_Q15(SUB16(32767,st->spec_average),st->Yh[j]), st->spec_average, st->Yf[j]); -#else - st->Eh[j] = (1-st->spec_average)*st->Eh[j] + st->spec_average*st->Rf[j]; - st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j]; -#endif - } - - Pyy = FLOAT_SQRT(Pyy); - Pey = FLOAT_DIVU(Pey,Pyy); - - /* Compute correlation updatete rate */ - tmp32 = MULT16_32_Q15(st->beta0,Syy); - if (tmp32 > MULT16_32_Q15(st->beta_max,See)) - tmp32 = MULT16_32_Q15(st->beta_max,See); - alpha = FLOAT_DIV32(tmp32, See); - alpha_1 = FLOAT_SUB(FLOAT_ONE, alpha); - /* Update correlations (recursive average) */ - st->Pey = FLOAT_ADD(FLOAT_MULT(alpha_1,st->Pey) , FLOAT_MULT(alpha,Pey)); - st->Pyy = FLOAT_ADD(FLOAT_MULT(alpha_1,st->Pyy) , FLOAT_MULT(alpha,Pyy)); - if (FLOAT_LT(st->Pyy, FLOAT_ONE)) - st->Pyy = FLOAT_ONE; - /* We don't really hope to get better than 33 dB (MIN_LEAK-3dB) attenuation anyway */ - if (FLOAT_LT(st->Pey, FLOAT_MULT(MIN_LEAK,st->Pyy))) - st->Pey = FLOAT_MULT(MIN_LEAK,st->Pyy); - if (FLOAT_GT(st->Pey, st->Pyy)) - st->Pey = st->Pyy; - /* leak_estimate is the linear regression result */ - st->leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(st->Pey, st->Pyy),14)); - /* This looks like a stupid bug, but it's right (because we convert from Q14 to Q15) */ - if (st->leak_estimate > 16383) - st->leak_estimate = 32767; - else - st->leak_estimate = SHL16(st->leak_estimate,1); - /*printf ("%f\n", st->leak_estimate);*/ - - /* Compute Residual to Error Ratio */ -#ifdef FIXED_POINT - tmp32 = MULT16_32_Q15(st->leak_estimate,Syy); - tmp32 = ADD32(SHR32(Sxx,13), ADD32(tmp32, SHL32(tmp32,1))); - /* Check for y in e (lower bound on RER) */ - { - spx_float_t bound = PSEUDOFLOAT(Sey); - bound = FLOAT_DIVU(FLOAT_MULT(bound, bound), PSEUDOFLOAT(ADD32(1,Syy))); - if (FLOAT_GT(bound, PSEUDOFLOAT(See))) - tmp32 = See; - else if (tmp32 < FLOAT_EXTRACT32(bound)) - tmp32 = FLOAT_EXTRACT32(bound); - } - if (tmp32 > SHR32(See,1)) - tmp32 = SHR32(See,1); - RER = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32,See),15)); -#else - RER = (.0001*Sxx + 3.*MULT16_32_Q15(st->leak_estimate,Syy)) / See; - /* Check for y in e (lower bound on RER) */ - if (RER < Sey*Sey/(1+See*Syy)) - RER = Sey*Sey/(1+See*Syy); - if (RER > .5) - RER = .5; -#endif - - /* We consider that the filter has had minimal adaptation if the following is true*/ - if (!st->adapted && st->sum_adapt > SHL32(EXTEND32(M),15) && MULT16_32_Q15(st->leak_estimate,Syy) > MULT16_32_Q15(QCONST16(.03f,15),Syy)) - { - st->adapted = 1; - } - - if (st->adapted) - { - /* Normal learning rate calculation once we're past the minimal adaptation phase */ - for (i=0;i<=st->frame_size;i++) - { - spx_word32_t r, e; - /* Compute frequency-domain adaptation mask */ - r = MULT16_32_Q15(st->leak_estimate,SHL32(st->Yf[i],3)); - e = SHL32(st->Rf[i],3)+1; -#ifdef FIXED_POINT - if (r>SHR32(e,1)) - r = SHR32(e,1); -#else - if (r>.5*e) - r = .5*e; -#endif - r = MULT16_32_Q15(QCONST16(.7,15),r) + MULT16_32_Q15(QCONST16(.3,15),(spx_word32_t)(MULT16_32_Q15(RER,e))); - /*st->power_1[i] = adapt_rate*r/(e*(1+st->power[i]));*/ - st->power_1[i] = FLOAT_SHL(FLOAT_DIV32_FLOAT(r,FLOAT_MUL32U(e,st->power[i]+10)),WEIGHT_SHIFT+16); - } - } else { - /* Temporary adaption rate if filter is not yet adapted enough */ - spx_word16_t adapt_rate=0; - - if (Sxx > SHR32(MULT16_16(N, 1000),6)) - { - tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx); -#ifdef FIXED_POINT - if (tmp32 > SHR32(See,2)) - tmp32 = SHR32(See,2); -#else - if (tmp32 > .25*See) - tmp32 = .25*See; -#endif - adapt_rate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32, See),15)); - } - for (i=0;i<=st->frame_size;i++) - st->power_1[i] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(st->power[i],10)),WEIGHT_SHIFT+1); - - - /* How much have we adapted so far? */ - st->sum_adapt = ADD32(st->sum_adapt,adapt_rate); - } - - /* FIXME: MC conversion required */ - for (i=0;iframe_size;i++) - st->last_y[i] = st->last_y[st->frame_size+i]; - if (st->adapted) - { - /* If the filter is adapted, take the filtered echo */ - for (i=0;iframe_size;i++) - st->last_y[st->frame_size+i] = in[i]-out[i]; - } else { - /* If filter isn't adapted yet, all we can do is take the far end signal directly */ - /* moved earlier: for (i=0;ilast_y[i] = st->x[i];*/ - } - -} - -/* Compute spectrum of estimated echo for use in an echo post-filter */ -void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, int len) -{ - int i; - spx_word16_t leak2; - int N; - - N = st->window_size; - - /* Apply hanning window (should pre-compute it)*/ - for (i=0;iy[i] = MULT16_16_Q15(st->window[i],st->last_y[i]); - - /* Compute power spectrum of the echo */ - spx_fft(st->fft_table, st->y, st->Y); - power_spectrum(st->Y, residual_echo, N); - -#ifdef FIXED_POINT - if (st->leak_estimate > 16383) - leak2 = 32767; - else - leak2 = SHL16(st->leak_estimate, 1); -#else - if (st->leak_estimate>.5) - leak2 = 1; - else - leak2 = 2*st->leak_estimate; -#endif - /* Estimate residual echo */ - for (i=0;i<=st->frame_size;i++) - residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]); - -} - -EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) -{ - switch(request) - { - - case SPEEX_ECHO_GET_FRAME_SIZE: - (*(int*)ptr) = st->frame_size; - break; - case SPEEX_ECHO_SET_SAMPLING_RATE: - st->sampling_rate = (*(int*)ptr); - st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); -#ifdef FIXED_POINT - st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); - st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); -#else - st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; - st->beta_max = (.5f*st->frame_size)/st->sampling_rate; -#endif - if (st->sampling_rate<12000) - st->notch_radius = QCONST16(.9, 15); - else if (st->sampling_rate<24000) - st->notch_radius = QCONST16(.982, 15); - else - st->notch_radius = QCONST16(.992, 15); - break; - case SPEEX_ECHO_GET_SAMPLING_RATE: - (*(int*)ptr) = st->sampling_rate; - break; - case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE: - /*FIXME: Implement this for multiple channels */ - *((spx_int32_t *)ptr) = st->M * st->frame_size; - break; - case SPEEX_ECHO_GET_IMPULSE_RESPONSE: - { - int M = st->M, N = st->window_size, n = st->frame_size, i, j; - spx_int32_t *filt = (spx_int32_t *) ptr; - for(j=0;jwtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN)); - spx_ifft(st->fft_table, st->wtmp2, st->wtmp); -#else - spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); -#endif - for(i=0;iwtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN); - } - } - break; - default: - speex_warning_int("Unknown speex_echo_ctl request: ", request); - return -1; - } - return 0; -} diff --git a/libspeex/preprocess.c b/libspeex/preprocess.c deleted file mode 100644 index 3920a76..0000000 --- a/libspeex/preprocess.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin) - Copyright (C) 2004-2006 Epic Games - - File: preprocess.c - Preprocessor with denoising based on the algorithm by Ephraim and Malah - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* - Recommended papers: - - Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error - short-time spectral amplitude estimator". IEEE Transactions on Acoustics, - Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984. - - Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error - log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and - Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985. - - I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments". - Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001. - - Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic - approach to combined acoustic echo cancellation and noise reduction". IEEE - Transactions on Speech and Audio Processing, 2002. - - J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation - of simultaneous non-stationary sources". In Proceedings IEEE International - Conference on Acoustics, Speech, and Signal Processing, 2004. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "../include/speex/speex_preprocess.h" -#include "../include/speex/speex_echo.h" -#include "arch.h" -#include "fftwrap.h" -#include "filterbank.h" -#include "math_approx.h" -#include "os_support.h" - -#define LOUDNESS_EXP 5.f -#define AMP_SCALE .001f -#define AMP_SCALE_1 1000.f - -#define NB_BANDS 24 - -#define SPEECH_PROB_START_DEFAULT QCONST16(0.35f,15) -#define SPEECH_PROB_CONTINUE_DEFAULT QCONST16(0.20f,15) -#define NOISE_SUPPRESS_DEFAULT -15 -#define ECHO_SUPPRESS_DEFAULT -40 -#define ECHO_SUPPRESS_ACTIVE_DEFAULT -15 - -#ifndef NULL -#define NULL 0 -#endif - -#define SQR(x) ((x)*(x)) -#define SQR16(x) (MULT16_16((x),(x))) -#define SQR16_Q15(x) (MULT16_16_Q15((x),(x))) - -#ifdef FIXED_POINT -static inline spx_word16_t DIV32_16_Q8(spx_word32_t a, spx_word32_t b) -{ - if (SHR32(a,7) >= b) - { - return 32767; - } else { - if (b>=QCONST32(1,23)) - { - a = SHR32(a,8); - b = SHR32(b,8); - } - if (b>=QCONST32(1,19)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - if (b>=QCONST32(1,15)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - a = SHL32(a,8); - return PDIV32_16(a,b); - } - -} -static inline spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b) -{ - if (SHR32(a,15) >= b) - { - return 32767; - } else { - if (b>=QCONST32(1,23)) - { - a = SHR32(a,8); - b = SHR32(b,8); - } - if (b>=QCONST32(1,19)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - if (b>=QCONST32(1,15)) - { - a = SHR32(a,4); - b = SHR32(b,4); - } - a = SHL32(a,15)-a; - return DIV32_16(a,b); - } -} -#define SNR_SCALING 256.f -#define SNR_SCALING_1 0.0039062f -#define SNR_SHIFT 8 - -#define FRAC_SCALING 32767.f -#define FRAC_SCALING_1 3.0518e-05 -#define FRAC_SHIFT 1 - -#define EXPIN_SCALING 2048.f -#define EXPIN_SCALING_1 0.00048828f -#define EXPIN_SHIFT 11 -#define EXPOUT_SCALING_1 1.5259e-05 - -#define NOISE_SHIFT 7 - -#else - -#define DIV32_16_Q8(a,b) ((a)/(b)) -#define DIV32_16_Q15(a,b) ((a)/(b)) -#define SNR_SCALING 1.f -#define SNR_SCALING_1 1.f -#define SNR_SHIFT 0 -#define FRAC_SCALING 1.f -#define FRAC_SCALING_1 1.f -#define FRAC_SHIFT 0 -#define NOISE_SHIFT 0 - -#define EXPIN_SCALING 1.f -#define EXPIN_SCALING_1 1.f -#define EXPOUT_SCALING_1 1.f - -#endif - -/** Speex pre-processor state. */ -struct SpeexPreprocessState_ { - /* Basic info */ - int frame_size; /**< Number of samples processed each time */ - int ps_size; /**< Number of points in the power spectrum */ - int sampling_rate; /**< Sampling rate of the input/output */ - int nbands; - FilterBank *bank; - - /* Parameters */ - int denoise_enabled; - int vad_enabled; - int dereverb_enabled; - spx_word16_t reverb_decay; - spx_word16_t reverb_level; - spx_word16_t speech_prob_start; - spx_word16_t speech_prob_continue; - int noise_suppress; - int echo_suppress; - int echo_suppress_active; - SpeexEchoState *echo_state; - - spx_word16_t speech_prob; /**< Probability last frame was speech */ - - /* DSP-related arrays */ - spx_word16_t *frame; /**< Processing frame (2*ps_size) */ - spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */ - spx_word32_t *ps; /**< Current power spectrum */ - spx_word16_t *gain2; /**< Adjusted gains */ - spx_word16_t *gain_floor; /**< Minimum gain allowed */ - spx_word16_t *window; /**< Analysis/Synthesis window */ - spx_word32_t *noise; /**< Noise estimate */ - spx_word32_t *reverb_estimate; /**< Estimate of reverb energy */ - spx_word32_t *old_ps; /**< Power spectrum for last frame */ - spx_word16_t *gain; /**< Ephraim Malah gain */ - spx_word16_t *prior; /**< A-priori SNR */ - spx_word16_t *post; /**< A-posteriori SNR */ - - spx_word32_t *S; /**< Smoothed power spectrum */ - spx_word32_t *Smin; /**< See Cohen paper */ - spx_word32_t *Stmp; /**< See Cohen paper */ - int *update_prob; /**< Probability of speech presence for noise update */ - - spx_word16_t *zeta; /**< Smoothed a priori SNR */ - spx_word32_t *echo_noise; - spx_word32_t *residual_echo; - - /* Misc */ - spx_word16_t *inbuf; /**< Input buffer (overlapped analysis) */ - spx_word16_t *outbuf; /**< Output buffer (for overlap and add) */ - - /* AGC stuff, only for floating point for now */ -#ifndef FIXED_POINT - int agc_enabled; - float agc_level; - float loudness_accum; - float *loudness_weight; /**< Perceptual loudness curve */ - float loudness; /**< Loudness estimate */ - float agc_gain; /**< Current AGC gain */ - float max_gain; /**< Maximum gain allowed */ - float max_increase_step; /**< Maximum increase in gain from one frame to another */ - float max_decrease_step; /**< Maximum decrease in gain from one frame to another */ - float prev_loudness; /**< Loudness of previous frame */ - float init_max; /**< Current gain limit during initialisation */ -#endif - int nb_adapt; /**< Number of frames used for adaptation so far */ - int was_speech; - int min_count; /**< Number of frames processed so far */ - void *fft_lookup; /**< Lookup table for the FFT */ -#ifdef FIXED_POINT - int frame_shift; -#endif -}; - - -static void conj_window(spx_word16_t *w, int len) -{ - int i; - for (i=0;i19) - return ADD32(EXTEND32(Q15_ONE),EXTEND32(DIV32_16(QCONST32(.1296,23), SHR32(xx,EXPIN_SHIFT-SNR_SHIFT)))); - frac = SHL32(xx-SHL32(ind,10),5); - return SHL32(DIV32_16(PSHR32(MULT16_16(Q15_ONE-frac,table[ind]) + MULT16_16(frac,table[ind+1]),7),(spx_sqrt(SHL32(xx,15)+6711))),7); -} - -static inline spx_word16_t qcurve(spx_word16_t x) -{ - x = MAX16(x, 1); - return DIV32_16(SHL32(EXTEND32(32767),9),ADD16(512,MULT16_16_Q15(QCONST16(.60f,15),DIV32_16(32767,x)))); -} - -/* Compute the gain floor based on different floors for the background noise and residual echo */ -static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len) -{ - int i; - - if (noise_suppress > effective_echo_suppress) - { - spx_word16_t noise_gain, gain_ratio; - noise_gain = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(0.11513,11),noise_suppress)),1))); - gain_ratio = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(.2302585f,11),effective_echo_suppress-noise_suppress)),1))); - - /* gain_floor = sqrt [ (noise*noise_floor + echo*echo_floor) / (noise+echo) ] */ - for (i=0;i19) - return FRAC_SCALING*(1+.1296/x); - frac = 2*x-integer; - return FRAC_SCALING*((1-frac)*table[ind] + frac*table[ind+1])/sqrt(x+.0001f); -} - -static inline spx_word16_t qcurve(spx_word16_t x) -{ - return 1.f/(1.f+.15f/(SNR_SCALING_1*x)); -} - -static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len) -{ - int i; - float echo_floor; - float noise_floor; - - noise_floor = exp(.2302585f*noise_suppress); - echo_floor = exp(.2302585f*effective_echo_suppress); - - /* Compute the gain floor based on different floors for the background noise and residual echo */ - for (i=0;iframe_size = frame_size; - - /* Round ps_size down to the nearest power of two */ -#if 0 - i=1; - st->ps_size = st->frame_size; - while(1) - { - if (st->ps_size & ~i) - { - st->ps_size &= ~i; - i<<=1; - } else { - break; - } - } - - - if (st->ps_size < 3*st->frame_size/4) - st->ps_size = st->ps_size * 3 / 2; -#else - st->ps_size = st->frame_size; -#endif - - N = st->ps_size; - N3 = 2*N - st->frame_size; - N4 = st->frame_size - N3; - - st->sampling_rate = sampling_rate; - st->denoise_enabled = 1; - st->vad_enabled = 0; - st->dereverb_enabled = 0; - st->reverb_decay = 0; - st->reverb_level = 0; - st->noise_suppress = NOISE_SUPPRESS_DEFAULT; - st->echo_suppress = ECHO_SUPPRESS_DEFAULT; - st->echo_suppress_active = ECHO_SUPPRESS_ACTIVE_DEFAULT; - - st->speech_prob_start = SPEECH_PROB_START_DEFAULT; - st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT; - - st->echo_state = NULL; - - st->nbands = NB_BANDS; - M = st->nbands; - st->bank = filterbank_new(M, sampling_rate, N, 1); - - st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); - st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); - st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); - - st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->residual_echo = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->reverb_estimate = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->old_ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); - st->prior = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->post = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->gain = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); - - st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); - st->update_prob = (int*)speex_alloc(N*sizeof(int)); - - st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); - st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); - - conj_window(st->window, 2*N3); - for (i=2*N3;i<2*st->ps_size;i++) - st->window[i]=Q15_ONE; - - if (N4>0) - { - for (i=N3-1;i>=0;i--) - { - st->window[i+N3+N4]=st->window[i+N3]; - st->window[i+N3]=1; - } - } - for (i=0;inoise[i]=QCONST32(1.f,NOISE_SHIFT); - st->reverb_estimate[i]=0; - st->old_ps[i]=1; - st->gain[i]=Q15_ONE; - st->post[i]=SHL16(1, SNR_SHIFT); - st->prior[i]=SHL16(1, SNR_SHIFT); - } - - for (i=0;iupdate_prob[i] = 1; - for (i=0;iinbuf[i]=0; - st->outbuf[i]=0; - } -#ifndef FIXED_POINT - st->agc_enabled = 0; - st->agc_level = 8000; - st->loudness_weight = (float*)speex_alloc(N*sizeof(float)); - for (i=0;iloudness_weight[i] = .5f*(1.f/(1.f+ff/8000.f))+1.f*exp(-.5f*(ff-3800.f)*(ff-3800.f)/9e5f);*/ - st->loudness_weight[i] = .35f-.35f*ff/16000.f+.73f*exp(-.5f*(ff-3800)*(ff-3800)/9e5f); - if (st->loudness_weight[i]<.01f) - st->loudness_weight[i]=.01f; - st->loudness_weight[i] *= st->loudness_weight[i]; - } - /*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/ - st->loudness = 1e-15; - st->agc_gain = 1; - st->max_gain = 30; - st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate); - st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate); - st->prev_loudness = 1; - st->init_max = 1; -#endif - st->was_speech = 0; - - st->fft_lookup = spx_fft_init(2*N); - - st->nb_adapt=0; - st->min_count=0; - return st; -} - -EXPORT void speex_preprocess_state_destroy(SpeexPreprocessState *st) -{ - speex_free(st->frame); - speex_free(st->ft); - speex_free(st->ps); - speex_free(st->gain2); - speex_free(st->gain_floor); - speex_free(st->window); - speex_free(st->noise); - speex_free(st->reverb_estimate); - speex_free(st->old_ps); - speex_free(st->gain); - speex_free(st->prior); - speex_free(st->post); -#ifndef FIXED_POINT - speex_free(st->loudness_weight); -#endif - speex_free(st->echo_noise); - speex_free(st->residual_echo); - - speex_free(st->S); - speex_free(st->Smin); - speex_free(st->Stmp); - speex_free(st->update_prob); - speex_free(st->zeta); - - speex_free(st->inbuf); - speex_free(st->outbuf); - - spx_fft_destroy(st->fft_lookup); - filterbank_destroy(st->bank); - speex_free(st); -} - -/* FIXME: The AGC doesn't work yet with fixed-point*/ -#ifndef FIXED_POINT -static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx_word16_t *ft) -{ - int i; - int N = st->ps_size; - float target_gain; - float loudness=1.f; - float rate; - - for (i=2;ips[i]* st->loudness_weight[i]; - } - loudness=sqrt(loudness); - /*if (loudness < 2*pow(st->loudness, 1.0/LOUDNESS_EXP) && - loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/ - if (Pframe>.3f) - { - /*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/ - rate = .03*Pframe*Pframe; - st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP); - st->loudness_accum = (1-rate)*st->loudness_accum + rate; - if (st->init_max < st->max_gain && st->nb_adapt > 20) - st->init_max *= 1.f + .1f*Pframe*Pframe; - } - /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/ - - target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP); - - if ((Pframe>.5 && st->nb_adapt > 20) || target_gain < st->agc_gain) - { - if (target_gain > st->max_increase_step*st->agc_gain) - target_gain = st->max_increase_step*st->agc_gain; - if (target_gain < st->max_decrease_step*st->agc_gain && loudness < 10*st->prev_loudness) - target_gain = st->max_decrease_step*st->agc_gain; - if (target_gain > st->max_gain) - target_gain = st->max_gain; - if (target_gain > st->init_max) - target_gain = st->init_max; - - st->agc_gain = target_gain; - } - /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/ - - for (i=0;i<2*N;i++) - ft[i] *= st->agc_gain; - st->prev_loudness = loudness; -} -#endif - -static void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x) -{ - int i; - int N = st->ps_size; - int N3 = 2*N - st->frame_size; - int N4 = st->frame_size - N3; - spx_word32_t *ps=st->ps; - - /* 'Build' input frame */ - for (i=0;iframe[i]=st->inbuf[i]; - for (i=0;iframe_size;i++) - st->frame[N3+i]=x[i]; - - /* Update inbuf */ - for (i=0;iinbuf[i]=x[N4+i]; - - /* Windowing */ - for (i=0;i<2*N;i++) - st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]); - -#ifdef FIXED_POINT - { - spx_word16_t max_val=0; - for (i=0;i<2*N;i++) - max_val = MAX16(max_val, ABS16(st->frame[i])); - st->frame_shift = 14-spx_ilog2(EXTEND32(max_val)); - for (i=0;i<2*N;i++) - st->frame[i] = SHL16(st->frame[i], st->frame_shift); - } -#endif - - /* Perform FFT */ - spx_fft(st->fft_lookup, st->frame, st->ft); - - /* Power spectrum */ - ps[0]=MULT16_16(st->ft[0],st->ft[0]); - for (i=1;ift[2*i-1],st->ft[2*i-1]) + MULT16_16(st->ft[2*i],st->ft[2*i]); - for (i=0;ips[i] = PSHR32(st->ps[i], 2*st->frame_shift); - - filterbank_compute_bank32(st->bank, ps, ps+N); -} - -static void update_noise_prob(SpeexPreprocessState *st) -{ - int i; - int min_range; - int N = st->ps_size; - - for (i=1;iS[i] = MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1]) - + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]); - st->S[0] = MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]); - st->S[N-1] = MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]); - - if (st->nb_adapt==1) - { - for (i=0;iSmin[i] = st->Stmp[i] = 0; - } - - if (st->nb_adapt < 100) - min_range = 15; - else if (st->nb_adapt < 1000) - min_range = 50; - else if (st->nb_adapt < 10000) - min_range = 150; - else - min_range = 300; - if (st->min_count > min_range) - { - st->min_count = 0; - for (i=0;iSmin[i] = MIN32(st->Stmp[i], st->S[i]); - st->Stmp[i] = st->S[i]; - } - } else { - for (i=0;iSmin[i] = MIN32(st->Smin[i], st->S[i]); - st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]); - } - } - for (i=0;iS[i]) > st->Smin[i]) - st->update_prob[i] = 1; - else - st->update_prob[i] = 0; - /*fprintf (stderr, "%f ", st->S[i]/st->Smin[i]);*/ - /*fprintf (stderr, "%f ", st->update_prob[i]);*/ - } - -} - -#define NOISE_OVERCOMPENS 1. - -void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len); - -EXPORT int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo) -{ - return speex_preprocess_run(st, x); -} - -EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x) -{ - int i; - int M; - int N = st->ps_size; - int N3 = 2*N - st->frame_size; - int N4 = st->frame_size - N3; - spx_word32_t *ps=st->ps; - spx_word32_t Zframe; - spx_word16_t Pframe; - spx_word16_t beta, beta_1; - spx_word16_t effective_echo_suppress; - - st->nb_adapt++; - if (st->nb_adapt>20000) - st->nb_adapt = 20000; - st->min_count++; - - beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt)); - beta_1 = Q15_ONE-beta; - M = st->nbands; - /* Deal with residual echo if provided */ - if (st->echo_state) - { - speex_echo_get_residual(st->echo_state, st->residual_echo, N); -#ifndef FIXED_POINT - /* If there are NaNs or ridiculous values, it'll show up in the DC and we just reset everything to zero */ - if (!(st->residual_echo[0] >=0 && st->residual_echo[0]residual_echo[i] = 0; - } -#endif - for (i=0;iecho_noise[i] = MAX32(MULT16_32_Q15(QCONST16(.6f,15),st->echo_noise[i]), st->residual_echo[i]); - filterbank_compute_bank32(st->bank, st->echo_noise, st->echo_noise+N); - } else { - for (i=0;iecho_noise[i] = 0; - } - preprocess_analysis(st, x); - - update_noise_prob(st); - - /* Noise estimation always updated for the 10 first frames */ - /*if (st->nb_adapt<10) - { - for (i=1;iupdate_prob[i] = 0; - } - */ - - /* Update the noise estimate for the frequencies where it can be */ - for (i=0;iupdate_prob[i] || st->ps[i] < PSHR32(st->noise[i], NOISE_SHIFT)) - st->noise[i] = MAX32(EXTEND32(0),MULT16_32_Q15(beta_1,st->noise[i]) + MULT16_32_Q15(beta,SHL32(st->ps[i],NOISE_SHIFT))); - } - filterbank_compute_bank32(st->bank, st->noise, st->noise+N); - - /* Special case for first frame */ - if (st->nb_adapt==1) - for (i=0;iold_ps[i] = ps[i]; - - /* Compute a posteriori SNR */ - for (i=0;inoise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]); - - /* A posteriori SNR = ps/noise - 1*/ - st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT)); - st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT)); - - /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */ - gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise)))); - - /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */ - st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15)); - st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT)); - } - - /*print_vec(st->post, N+M, "");*/ - - /* Recursive average of the a priori SNR. A bit smoothed for the psd components */ - st->zeta[0] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[0]), MULT16_16(QCONST16(.3f,15),st->prior[0])),15); - for (i=1;izeta[i] = PSHR32(ADD32(ADD32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.15f,15),st->prior[i])), - MULT16_16(QCONST16(.075f,15),st->prior[i-1])), MULT16_16(QCONST16(.075f,15),st->prior[i+1])),15); - for (i=N-1;izeta[i] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.3f,15),st->prior[i])),15); - - /* Speech probability of presence for the entire frame is based on the average filterbank a priori SNR */ - Zframe = 0; - for (i=N;izeta[i])); - Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands))); - - effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15)); - - compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M); - - /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale) - Technically this is actually wrong because the EM gaim assumes a slightly different probability - distribution */ - for (i=N;iprior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); - theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); - - MM = hypergeom_gain(theta); - /* Gain with bound */ - st->gain[i] = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM))); - /* Save old Bark power spectrum */ - st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]); - - P1 = QCONST16(.199f,15)+MULT16_16_Q15(QCONST16(.8f,15),qcurve (st->zeta[i])); - q = Q15_ONE-MULT16_16_Q15(Pframe,P1); -#ifdef FIXED_POINT - theta = MIN32(theta, EXTEND32(32767)); -/*Q8*/tmp = MULT16_16_Q15((SHL32(1,SNR_SHIFT)+st->prior[i]),EXTRACT16(MIN32(Q15ONE,SHR32(spx_exp(-EXTRACT16(theta)),1)))); - tmp = MIN16(QCONST16(3.,SNR_SHIFT), tmp); /* Prevent overflows in the next line*/ -/*Q8*/tmp = EXTRACT16(PSHR32(MULT16_16(PDIV32_16(SHL32(EXTEND32(q),8),(Q15_ONE-q)),tmp),8)); - st->gain2[i]=DIV32_16(SHL32(EXTEND32(32767),SNR_SHIFT), ADD16(256,tmp)); -#else - st->gain2[i]=1/(1.f + (q/(1.f-q))*(1+st->prior[i])*exp(-theta)); -#endif - } - /* Convert the EM gains and speech prob to linear frequency */ - filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); - filterbank_compute_psd16(st->bank,st->gain+N, st->gain); - - /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */ - if (1) - { - filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor); - - /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */ - for (i=0;iprior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); - theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); - - /* Optimal estimator for loudness domain */ - MM = hypergeom_gain(theta); - /* EM gain with bound */ - g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM))); - /* Interpolated speech probability of presence */ - p = st->gain2[i]; - - /* Constrain the gain to be close to the Bark scale gain */ - if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i]) - g = MULT16_16(3,st->gain[i]); - st->gain[i] = g; - - /* Save old power spectrum */ - st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]); - - /* Apply gain floor */ - if (st->gain[i] < st->gain_floor[i]) - st->gain[i] = st->gain_floor[i]; - - /* Exponential decay model for reverberation (unused) */ - /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/ - - /* Take into account speech probability of presence (loudness domain MMSE estimator) */ - /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */ - tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); - st->gain2[i]=SQR16_Q15(tmp); - - /* Use this if you want a log-domain MMSE estimator instead */ - /*st->gain2[i] = pow(st->gain[i], p) * pow(st->gain_floor[i],1.f-p);*/ - } - } else { - for (i=N;igain2[i]; - st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]); - tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); - st->gain2[i]=SQR16_Q15(tmp); - } - filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); - } - - /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */ - if (!st->denoise_enabled) - { - for (i=0;igain2[i]=Q15_ONE; - } - - /* Apply computed gain */ - for (i=1;ift[2*i-1] = MULT16_16_P15(st->gain2[i],st->ft[2*i-1]); - st->ft[2*i] = MULT16_16_P15(st->gain2[i],st->ft[2*i]); - } - st->ft[0] = MULT16_16_P15(st->gain2[0],st->ft[0]); - st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]); - - /*FIXME: This *will* not work for fixed-point */ -#ifndef FIXED_POINT - if (st->agc_enabled) - speex_compute_agc(st, Pframe, st->ft); -#endif - - /* Inverse FFT with 1/N scaling */ - spx_ifft(st->fft_lookup, st->ft, st->frame); - /* Scale back to original (lower) amplitude */ - for (i=0;i<2*N;i++) - st->frame[i] = PSHR16(st->frame[i], st->frame_shift); - - /*FIXME: This *will* not work for fixed-point */ -#ifndef FIXED_POINT - if (st->agc_enabled) - { - float max_sample=0; - for (i=0;i<2*N;i++) - if (fabs(st->frame[i])>max_sample) - max_sample = fabs(st->frame[i]); - if (max_sample>28000.f) - { - float damp = 28000.f/max_sample; - for (i=0;i<2*N;i++) - st->frame[i] *= damp; - } - } -#endif - - /* Synthesis window (for WOLA) */ - for (i=0;i<2*N;i++) - st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]); - - /* Perform overlap and add */ - for (i=0;ioutbuf[i] + st->frame[i]; - for (i=0;iframe[N3+i]; - - /* Update outbuf */ - for (i=0;ioutbuf[i] = st->frame[st->frame_size+i]; - - /* FIXME: This VAD is a kludge */ - st->speech_prob = Pframe; - if (st->vad_enabled) - { - if (st->speech_prob > st->speech_prob_start || (st->was_speech && st->speech_prob > st->speech_prob_continue)) - { - st->was_speech=1; - return 1; - } else - { - st->was_speech=0; - return 0; - } - } else { - return 1; - } -} - -EXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x) -{ - int i; - int N = st->ps_size; - int N3 = 2*N - st->frame_size; - int M; - spx_word32_t *ps=st->ps; - - M = st->nbands; - st->min_count++; - - preprocess_analysis(st, x); - - update_noise_prob(st); - - for (i=1;iupdate_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT)) - { - st->noise[i] = MULT16_32_Q15(QCONST16(.95f,15),st->noise[i]) + MULT16_32_Q15(QCONST16(.05f,15),SHL32(st->ps[i],NOISE_SHIFT)); - } - } - - for (i=0;ioutbuf[i] = MULT16_16_Q15(x[st->frame_size-N3+i],st->window[st->frame_size+i]); - - /* Save old power spectrum */ - for (i=0;iold_ps[i] = ps[i]; - - for (i=0;ireverb_estimate[i] = MULT16_32_Q15(st->reverb_decay, st->reverb_estimate[i]); -} - - -EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr) -{ - int i; - SpeexPreprocessState *st; - st=(SpeexPreprocessState*)state; - switch(request) - { - case SPEEX_PREPROCESS_SET_DENOISE: - st->denoise_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_DENOISE: - (*(spx_int32_t*)ptr) = st->denoise_enabled; - break; -#ifndef FIXED_POINT - case SPEEX_PREPROCESS_SET_AGC: - st->agc_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_AGC: - (*(spx_int32_t*)ptr) = st->agc_enabled; - break; -#ifndef DISABLE_FLOAT_API - case SPEEX_PREPROCESS_SET_AGC_LEVEL: - st->agc_level = (*(float*)ptr); - if (st->agc_level<1) - st->agc_level=1; - if (st->agc_level>32768) - st->agc_level=32768; - break; - case SPEEX_PREPROCESS_GET_AGC_LEVEL: - (*(float*)ptr) = st->agc_level; - break; -#endif /* #ifndef DISABLE_FLOAT_API */ - case SPEEX_PREPROCESS_SET_AGC_INCREMENT: - st->max_increase_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate); - break; - case SPEEX_PREPROCESS_GET_AGC_INCREMENT: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_increase_step)*st->sampling_rate/st->frame_size); - break; - case SPEEX_PREPROCESS_SET_AGC_DECREMENT: - st->max_decrease_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate); - break; - case SPEEX_PREPROCESS_GET_AGC_DECREMENT: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_decrease_step)*st->sampling_rate/st->frame_size); - break; - case SPEEX_PREPROCESS_SET_AGC_MAX_GAIN: - st->max_gain = exp(0.11513f * (*(spx_int32_t*)ptr)); - break; - case SPEEX_PREPROCESS_GET_AGC_MAX_GAIN: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_gain)); - break; -#endif - case SPEEX_PREPROCESS_SET_VAD: - speex_warning("The VAD has been replaced by a hack pending a complete rewrite"); - st->vad_enabled = (*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_VAD: - (*(spx_int32_t*)ptr) = st->vad_enabled; - break; - - case SPEEX_PREPROCESS_SET_DEREVERB: - st->dereverb_enabled = (*(spx_int32_t*)ptr); - for (i=0;ips_size;i++) - st->reverb_estimate[i]=0; - break; - case SPEEX_PREPROCESS_GET_DEREVERB: - (*(spx_int32_t*)ptr) = st->dereverb_enabled; - break; - - case SPEEX_PREPROCESS_SET_DEREVERB_LEVEL: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*st->reverb_level = (*(float*)ptr);*/ - break; - case SPEEX_PREPROCESS_GET_DEREVERB_LEVEL: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*(*(float*)ptr) = st->reverb_level;*/ - break; - - case SPEEX_PREPROCESS_SET_DEREVERB_DECAY: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*st->reverb_decay = (*(float*)ptr);*/ - break; - case SPEEX_PREPROCESS_GET_DEREVERB_DECAY: - /* FIXME: Re-enable when de-reverberation is actually enabled again */ - /*(*(float*)ptr) = st->reverb_decay;*/ - break; - - case SPEEX_PREPROCESS_SET_PROB_START: - *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr)); - st->speech_prob_start = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100); - break; - case SPEEX_PREPROCESS_GET_PROB_START: - (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_start, 100); - break; - - case SPEEX_PREPROCESS_SET_PROB_CONTINUE: - *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr)); - st->speech_prob_continue = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100); - break; - case SPEEX_PREPROCESS_GET_PROB_CONTINUE: - (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_continue, 100); - break; - - case SPEEX_PREPROCESS_SET_NOISE_SUPPRESS: - st->noise_suppress = -ABS(*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_NOISE_SUPPRESS: - (*(spx_int32_t*)ptr) = st->noise_suppress; - break; - case SPEEX_PREPROCESS_SET_ECHO_SUPPRESS: - st->echo_suppress = -ABS(*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_ECHO_SUPPRESS: - (*(spx_int32_t*)ptr) = st->echo_suppress; - break; - case SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE: - st->echo_suppress_active = -ABS(*(spx_int32_t*)ptr); - break; - case SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE: - (*(spx_int32_t*)ptr) = st->echo_suppress_active; - break; - case SPEEX_PREPROCESS_SET_ECHO_STATE: - st->echo_state = (SpeexEchoState*)ptr; - break; - case SPEEX_PREPROCESS_GET_ECHO_STATE: - (*(SpeexEchoState**)ptr) = (SpeexEchoState*)st->echo_state; - break; -#ifndef FIXED_POINT - case SPEEX_PREPROCESS_GET_AGC_LOUDNESS: - (*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP); - break; - case SPEEX_PREPROCESS_GET_AGC_GAIN: - (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->agc_gain)); - break; -#endif - case SPEEX_PREPROCESS_GET_PSD_SIZE: - case SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE: - (*(spx_int32_t*)ptr) = st->ps_size; - break; - case SPEEX_PREPROCESS_GET_PSD: - for(i=0;ips_size;i++) - ((spx_int32_t *)ptr)[i] = (spx_int32_t) st->ps[i]; - break; - case SPEEX_PREPROCESS_GET_NOISE_PSD: - for(i=0;ips_size;i++) - ((spx_int32_t *)ptr)[i] = (spx_int32_t) PSHR32(st->noise[i], NOISE_SHIFT); - break; - case SPEEX_PREPROCESS_GET_PROB: - (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob, 100); - break; -#ifndef FIXED_POINT - case SPEEX_PREPROCESS_SET_AGC_TARGET: - st->agc_level = (*(spx_int32_t*)ptr); - if (st->agc_level<1) - st->agc_level=1; - if (st->agc_level>32768) - st->agc_level=32768; - break; - case SPEEX_PREPROCESS_GET_AGC_TARGET: - (*(spx_int32_t*)ptr) = st->agc_level; - break; -#endif - default: - speex_warning_int("Unknown speex_preprocess_ctl request: ", request); - return -1; - } - return 0; -} - -#ifdef FIXED_DEBUG -long long spx_mips=0; -#endif - diff --git a/libspeex/pseudofloat.h b/libspeex/pseudofloat.h deleted file mode 100644 index fa841a0..0000000 --- a/libspeex/pseudofloat.h +++ /dev/null @@ -1,379 +0,0 @@ -/* Copyright (C) 2005 Jean-Marc Valin */ -/** - @file pseudofloat.h - @brief Pseudo-floating point - * This header file provides a lightweight floating point type for - * use on fixed-point platforms when a large dynamic range is - * required. The new type is not compatible with the 32-bit IEEE format, - * it is not even remotely as accurate as 32-bit floats, and is not - * even guaranteed to produce even remotely correct results for code - * other than Speex. It makes all kinds of shortcuts that are acceptable - * for Speex, but may not be acceptable for your application. You're - * quite welcome to reuse this code and improve it, but don't assume - * it works out of the box. Most likely, it doesn't. - */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef PSEUDOFLOAT_H -#define PSEUDOFLOAT_H - -#include "arch.h" -#include "os_support.h" -#include "math_approx.h" -#include - -#ifdef FIXED_POINT - -typedef struct { - spx_int16_t m; - spx_int16_t e; -} spx_float_t; - -static const spx_float_t FLOAT_ZERO = {0,0}; -static const spx_float_t FLOAT_ONE = {16384,-14}; -static const spx_float_t FLOAT_HALF = {16384,-15}; - -#define MIN(a,b) ((a)<(b)?(a):(b)) -static inline spx_float_t PSEUDOFLOAT(spx_int32_t x) -{ - int e=0; - int sign=0; - if (x<0) - { - sign = 1; - x = -x; - } - if (x==0) - { - spx_float_t r = {0,0}; - return r; - } - e = spx_ilog2(ABS32(x))-14; - x = VSHR32(x, e); - if (sign) - { - spx_float_t r; - r.m = -x; - r.e = e; - return r; - } - else - { - spx_float_t r; - r.m = x; - r.e = e; - return r; - } -} - - -static inline spx_float_t FLOAT_ADD(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - if (a.m==0) - return b; - else if (b.m==0) - return a; - if ((a).e > (b).e) - { - r.m = ((a).m>>1) + ((b).m>>MIN(15,(a).e-(b).e+1)); - r.e = (a).e+1; - } - else - { - r.m = ((b).m>>1) + ((a).m>>MIN(15,(b).e-(a).e+1)); - r.e = (b).e+1; - } - if (r.m>0) - { - if (r.m<16384) - { - r.m<<=1; - r.e-=1; - } - } else { - if (r.m>-16384) - { - r.m<<=1; - r.e-=1; - } - } - /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/ - return r; -} - -static inline spx_float_t FLOAT_SUB(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - if (a.m==0) - return b; - else if (b.m==0) - return a; - if ((a).e > (b).e) - { - r.m = ((a).m>>1) - ((b).m>>MIN(15,(a).e-(b).e+1)); - r.e = (a).e+1; - } - else - { - r.m = ((a).m>>MIN(15,(b).e-(a).e+1)) - ((b).m>>1); - r.e = (b).e+1; - } - if (r.m>0) - { - if (r.m<16384) - { - r.m<<=1; - r.e-=1; - } - } else { - if (r.m>-16384) - { - r.m<<=1; - r.e-=1; - } - } - /*printf ("%f + %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/ - return r; -} - -static inline int FLOAT_LT(spx_float_t a, spx_float_t b) -{ - if (a.m==0) - return b.m>0; - else if (b.m==0) - return a.m<0; - if ((a).e > (b).e) - return ((a).m>>1) < ((b).m>>MIN(15,(a).e-(b).e+1)); - else - return ((b).m>>1) > ((a).m>>MIN(15,(b).e-(a).e+1)); - -} - -static inline int FLOAT_GT(spx_float_t a, spx_float_t b) -{ - return FLOAT_LT(b,a); -} - -static inline spx_float_t FLOAT_MULT(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15); - r.e = (a).e+(b).e+15; - if (r.m>0) - { - if (r.m<16384) - { - r.m<<=1; - r.e-=1; - } - } else { - if (r.m>-16384) - { - r.m<<=1; - r.e-=1; - } - } - /*printf ("%f * %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/ - return r; -} - -static inline spx_float_t FLOAT_AMULT(spx_float_t a, spx_float_t b) -{ - spx_float_t r; - r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15); - r.e = (a).e+(b).e+15; - return r; -} - - -static inline spx_float_t FLOAT_SHL(spx_float_t a, int b) -{ - spx_float_t r; - r.m = a.m; - r.e = a.e+b; - return r; -} - -static inline spx_int16_t FLOAT_EXTRACT16(spx_float_t a) -{ - if (a.e<0) - return EXTRACT16((EXTEND32(a.m)+(EXTEND32(1)<<(-a.e-1)))>>-a.e); - else - return a.m<>-a.e; - else - return EXTEND32(a.m)<=SHL32(EXTEND32(b.m-1),15)) - { - a >>= 1; - e++; - } - r.m = DIV32_16(a,b.m); - r.e = e-b.e; - return r; -} - - -/* Do NOT attempt to divide by a negative number */ -static inline spx_float_t FLOAT_DIV32(spx_word32_t a, spx_word32_t b) -{ - int e0=0,e=0; - spx_float_t r; - if (a==0) - { - return FLOAT_ZERO; - } - if (b>32767) - { - e0 = spx_ilog2(b)-14; - b = VSHR32(b, e0); - e0 = -e0; - } - e = spx_ilog2(ABS32(a))-spx_ilog2(b-1)-15; - a = VSHR32(a, e); - if (ABS32(a)>=SHL32(EXTEND32(b-1),15)) - { - a >>= 1; - e++; - } - e += e0; - r.m = DIV32_16(a,b); - r.e = e; - return r; -} - -/* Do NOT attempt to divide by a negative number */ -static inline spx_float_t FLOAT_DIVU(spx_float_t a, spx_float_t b) -{ - int e=0; - spx_int32_t num; - spx_float_t r; - if (b.m<=0) - { - speex_warning_int("Attempted to divide by", b.m); - return FLOAT_ONE; - } - num = a.m; - a.m = ABS16(a.m); - while (a.m >= b.m) - { - e++; - a.m >>= 1; - } - num = num << (15-e); - r.m = DIV32_16(num,b.m); - r.e = a.e-b.e-15+e; - return r; -} - -static inline spx_float_t FLOAT_SQRT(spx_float_t a) -{ - spx_float_t r; - spx_int32_t m; - m = SHL32(EXTEND32(a.m), 14); - r.e = a.e - 14; - if (r.e & 1) - { - r.e -= 1; - m <<= 1; - } - r.e >>= 1; - r.m = spx_sqrt(m); - return r; -} - -#else - -#define spx_float_t float -#define FLOAT_ZERO 0.f -#define FLOAT_ONE 1.f -#define FLOAT_HALF 0.5f -#define PSEUDOFLOAT(x) (x) -#define FLOAT_MULT(a,b) ((a)*(b)) -#define FLOAT_AMULT(a,b) ((a)*(b)) -#define FLOAT_MUL32(a,b) ((a)*(b)) -#define FLOAT_DIV32(a,b) ((a)/(b)) -#define FLOAT_EXTRACT16(a) (a) -#define FLOAT_EXTRACT32(a) (a) -#define FLOAT_ADD(a,b) ((a)+(b)) -#define FLOAT_SUB(a,b) ((a)-(b)) -#define REALFLOAT(x) (x) -#define FLOAT_DIV32_FLOAT(a,b) ((a)/(b)) -#define FLOAT_MUL32U(a,b) ((a)*(b)) -#define FLOAT_SHL(a,b) (a) -#define FLOAT_LT(a,b) ((a)<(b)) -#define FLOAT_GT(a,b) ((a)>(b)) -#define FLOAT_DIVU(a,b) ((a)/(b)) -#define FLOAT_SQRT(a) (spx_sqrt(a)) - -#endif - -#endif diff --git a/libspeex/resample.c b/libspeex/resample.c deleted file mode 100644 index 7b5a308..0000000 --- a/libspeex/resample.c +++ /dev/null @@ -1,1137 +0,0 @@ -/* Copyright (C) 2007-2008 Jean-Marc Valin - Copyright (C) 2008 Thorvald Natvig - - File: resample.c - Arbitrary resampling code - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - The design goals of this code are: - - Very fast algorithm - - SIMD-friendly algorithm - - Low memory requirement - - Good *perceptual* quality (and not best SNR) - - Warning: This resampler is relatively new. Although I think I got rid of - all the major bugs and I don't expect the API to change anymore, there - may be something I've missed. So use with caution. - - This algorithm is based on this original resampling algorithm: - Smith, Julius O. Digital Audio Resampling Home Page - Center for Computer Research in Music and Acoustics (CCRMA), - Stanford University, 2007. - Web published at http://www-ccrma.stanford.edu/~jos/resample/. - - There is one main difference, though. This resampler uses cubic - interpolation instead of linear interpolation in the above paper. This - makes the table much smaller and makes it possible to compute that table - on a per-stream basis. In turn, being able to tweak the table for each - stream makes it possible to both reduce complexity on simple ratios - (e.g. 2/3), and get rid of the rounding operations in the inner loop. - The latter both reduces CPU time and makes the algorithm more SIMD-friendly. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef OUTSIDE_SPEEX -#include -static void *speex_alloc (int size) {return calloc(size,1);} -static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} -static void speex_free (void *ptr) {free(ptr);} -#include "speex_resampler.h" -#include "arch.h" -#else /* OUTSIDE_SPEEX */ - -#include "../include/speex/speex_resampler.h" -#include "arch.h" -#include "os_support.h" -#endif /* OUTSIDE_SPEEX */ - -#include "stack_alloc.h" -#include - -#ifndef M_PI -#define M_PI 3.14159263 -#endif - -#ifdef FIXED_POINT -#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) -#else -#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) -#endif - -#define IMAX(a,b) ((a) > (b) ? (a) : (b)) -#define IMIN(a,b) ((a) < (b) ? (a) : (b)) - -#ifndef NULL -#define NULL 0 -#endif - -#ifdef _USE_SSE -#include "resample_sse.h" -#endif - -/* Numer of elements to allocate on the stack */ -#ifdef VAR_ARRAYS -#define FIXED_STACK_ALLOC 8192 -#else -#define FIXED_STACK_ALLOC 1024 -#endif - -typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); - -struct SpeexResamplerState_ { - spx_uint32_t in_rate; - spx_uint32_t out_rate; - spx_uint32_t num_rate; - spx_uint32_t den_rate; - - int quality; - spx_uint32_t nb_channels; - spx_uint32_t filt_len; - spx_uint32_t mem_alloc_size; - spx_uint32_t buffer_size; - int int_advance; - int frac_advance; - float cutoff; - spx_uint32_t oversample; - int initialised; - int started; - - /* These are per-channel */ - spx_int32_t *last_sample; - spx_uint32_t *samp_frac_num; - spx_uint32_t *magic_samples; - - spx_word16_t *mem; - spx_word16_t *sinc_table; - spx_uint32_t sinc_table_length; - resampler_basic_func resampler_ptr; - - int in_stride; - int out_stride; -} ; - -static double kaiser12_table[68] = { - 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, - 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, - 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, - 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, - 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, - 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, - 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, - 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, - 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, - 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, - 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, - 0.00001000, 0.00000000}; -/* -static double kaiser12_table[36] = { - 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, - 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, - 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, - 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, - 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, - 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; -*/ -static double kaiser10_table[36] = { - 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, - 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, - 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, - 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, - 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, - 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; - -static double kaiser8_table[36] = { - 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, - 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, - 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, - 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, - 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, - 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; - -static double kaiser6_table[36] = { - 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, - 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, - 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, - 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, - 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, - 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000}; - -struct FuncDef { - double *table; - int oversample; -}; - -static struct FuncDef _KAISER12 = {kaiser12_table, 64}; -#define KAISER12 (&_KAISER12) -/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; -#define KAISER12 (&_KAISER12)*/ -static struct FuncDef _KAISER10 = {kaiser10_table, 32}; -#define KAISER10 (&_KAISER10) -static struct FuncDef _KAISER8 = {kaiser8_table, 32}; -#define KAISER8 (&_KAISER8) -static struct FuncDef _KAISER6 = {kaiser6_table, 32}; -#define KAISER6 (&_KAISER6) - -struct QualityMapping { - int base_length; - int oversample; - float downsample_bandwidth; - float upsample_bandwidth; - struct FuncDef *window_func; -}; - - -/* This table maps conversion quality to internal parameters. There are two - reasons that explain why the up-sampling bandwidth is larger than the - down-sampling bandwidth: - 1) When up-sampling, we can assume that the spectrum is already attenuated - close to the Nyquist rate (from an A/D or a previous resampling filter) - 2) Any aliasing that occurs very close to the Nyquist rate will be masked - by the sinusoids/noise just below the Nyquist rate (guaranteed only for - up-sampling). -*/ -static const struct QualityMapping quality_map[11] = { - { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */ - { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */ - { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ - { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ - { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ - { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ - { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ - {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ - {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ - {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ - {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ -}; -/*8,24,40,56,80,104,128,160,200,256,320*/ -static double compute_func(float x, struct FuncDef *func) -{ - float y, frac; - double interp[4]; - int ind; - y = x*func->oversample; - ind = (int)floor(y); - frac = (y-ind); - /* CSE with handle the repeated powers */ - interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac); - interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac); - /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ - interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); - /* Just to make sure we don't have rounding problems */ - interp[1] = 1.f-interp[3]-interp[2]-interp[0]; - - /*sum = frac*accum[1] + (1-frac)*accum[2];*/ - return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; -} - -#if 0 -#include -int main(int argc, char **argv) -{ - int i; - for (i=0;i<256;i++) - { - printf ("%f\n", compute_func(i/256., KAISER12)); - } - return 0; -} -#endif - -#ifdef FIXED_POINT -/* The slow way of computing a sinc for the table. Should improve that some day */ -static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) -{ - /*fprintf (stderr, "%f ", x);*/ - float xx = x * cutoff; - if (fabs(x)<1e-6f) - return WORD2INT(32768.*cutoff); - else if (fabs(x) > .5f*N) - return 0; - /*FIXME: Can it really be any slower than this? */ - return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func)); -} -#else -/* The slow way of computing a sinc for the table. Should improve that some day */ -static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) -{ - /*fprintf (stderr, "%f ", x);*/ - float xx = x * cutoff; - if (fabs(x)<1e-6) - return cutoff; - else if (fabs(x) > .5*N) - return 0; - /*FIXME: Can it really be any slower than this? */ - return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func); -} -#endif - -#ifdef FIXED_POINT -static void cubic_coef(spx_word16_t x, spx_word16_t interp[4]) -{ - /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation - but I know it's MMSE-optimal on a sinc */ - spx_word16_t x2, x3; - x2 = MULT16_16_P15(x, x); - x3 = MULT16_16_P15(x, x2); - interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15); - interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1)); - interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); - /* Just to make sure we don't have rounding problems */ - interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; - if (interp[2]<32767) - interp[2]+=1; -} -#else -static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) -{ - /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation - but I know it's MMSE-optimal on a sinc */ - interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; - interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; - /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ - interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; - /* Just to make sure we don't have rounding problems */ - interp[2] = 1.-interp[0]-interp[1]-interp[3]; -} -#endif - -static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const spx_word16_t *sinc_table = st->sinc_table; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - spx_word32_t sum; - int j; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; - const spx_word16_t *iptr = & in[last_sample]; - -#ifndef OVERRIDE_INNER_PRODUCT_SINGLE - sum = 0; - for(j=0;j= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} - -#ifdef FIXED_POINT -#else -/* This is the same as the previous function, except with a double-precision accumulator */ -static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const spx_word16_t *sinc_table = st->sinc_table; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - double sum; - int j; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; - const spx_word16_t *iptr = & in[last_sample]; - -#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE - double accum[4] = {0,0,0,0}; - - for(j=0;j= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} -#endif - -static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - int j; - spx_word32_t sum; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *iptr = & in[last_sample]; - - const int offset = samp_frac_num*st->oversample/st->den_rate; -#ifdef FIXED_POINT - const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); -#else - const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; -#endif - spx_word16_t interp[4]; - - -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE - spx_word32_t accum[4] = {0,0,0,0}; - - for(j=0;jsinc_table[4+(j+1)*st->oversample-offset-2]); - accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); - accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); - accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); - } - - cubic_coef(frac, interp); - sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); -#else - cubic_coef(frac, interp); - sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); -#endif - - out[out_stride * out_sample++] = SATURATE32(PSHR32(sum, 14), 32767); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} - -#ifdef FIXED_POINT -#else -/* This is the same as the previous function, except with a double-precision accumulator */ -static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - const int N = st->filt_len; - int out_sample = 0; - int last_sample = st->last_sample[channel_index]; - spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - int j; - spx_word32_t sum; - - while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) - { - const spx_word16_t *iptr = & in[last_sample]; - - const int offset = samp_frac_num*st->oversample/st->den_rate; -#ifdef FIXED_POINT - const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); -#else - const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; -#endif - spx_word16_t interp[4]; - - -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE - double accum[4] = {0,0,0,0}; - - for(j=0;jsinc_table[4+(j+1)*st->oversample-offset-2]); - accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); - accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); - accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); - } - - cubic_coef(frac, interp); - sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]); -#else - cubic_coef(frac, interp); - sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); -#endif - - out[out_stride * out_sample++] = PSHR32(sum,15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) - { - samp_frac_num -= den_rate; - last_sample++; - } - } - - st->last_sample[channel_index] = last_sample; - st->samp_frac_num[channel_index] = samp_frac_num; - return out_sample; -} -#endif - -static void update_filter(SpeexResamplerState *st) -{ - spx_uint32_t old_length; - - old_length = st->filt_len; - st->oversample = quality_map[st->quality].oversample; - st->filt_len = quality_map[st->quality].base_length; - - if (st->num_rate > st->den_rate) - { - /* down-sampling */ - st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; - /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ - st->filt_len = st->filt_len*st->num_rate / st->den_rate; - /* Round down to make sure we have a multiple of 4 */ - st->filt_len &= (~0x3); - if (2*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (4*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (8*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (16*st->den_rate < st->num_rate) - st->oversample >>= 1; - if (st->oversample < 1) - st->oversample = 1; - } else { - /* up-sampling */ - st->cutoff = quality_map[st->quality].upsample_bandwidth; - } - - /* Choose the resampling type that requires the least amount of memory */ - if (st->den_rate <= st->oversample) - { - spx_uint32_t i; - if (!st->sinc_table) - st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); - else if (st->sinc_table_length < st->filt_len*st->den_rate) - { - st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t)); - st->sinc_table_length = st->filt_len*st->den_rate; - } - for (i=0;iden_rate;i++) - { - spx_int32_t j; - for (j=0;jfilt_len;j++) - { - st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func); - } - } -#ifdef FIXED_POINT - st->resampler_ptr = resampler_basic_direct_single; -#else - if (st->quality>8) - st->resampler_ptr = resampler_basic_direct_double; - else - st->resampler_ptr = resampler_basic_direct_single; -#endif - /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ - } else { - spx_int32_t i; - if (!st->sinc_table) - st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); - else if (st->sinc_table_length < st->filt_len*st->oversample+8) - { - st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); - st->sinc_table_length = st->filt_len*st->oversample+8; - } - for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) - st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); -#ifdef FIXED_POINT - st->resampler_ptr = resampler_basic_interpolate_single; -#else - if (st->quality>8) - st->resampler_ptr = resampler_basic_interpolate_double; - else - st->resampler_ptr = resampler_basic_interpolate_single; -#endif - /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ - } - st->int_advance = st->num_rate/st->den_rate; - st->frac_advance = st->num_rate%st->den_rate; - - - /* Here's the place where we update the filter memory to take into account - the change in filter length. It's probably the messiest part of the code - due to handling of lots of corner cases. */ - if (!st->mem) - { - spx_uint32_t i; - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - for (i=0;inb_channels*st->mem_alloc_size;i++) - st->mem[i] = 0; - /*speex_warning("init filter");*/ - } else if (!st->started) - { - spx_uint32_t i; - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - for (i=0;inb_channels*st->mem_alloc_size;i++) - st->mem[i] = 0; - /*speex_warning("reinit filter");*/ - } else if (st->filt_len > old_length) - { - spx_int32_t i; - /* Increase the filter length */ - /*speex_warning("increase filter size");*/ - int old_alloc_size = st->mem_alloc_size; - if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) - { - st->mem_alloc_size = st->filt_len-1 + st->buffer_size; - st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); - } - for (i=st->nb_channels-1;i>=0;i--) - { - spx_int32_t j; - spx_uint32_t olen = old_length; - /*if (st->magic_samples[i])*/ - { - /* Try and remove the magic samples as if nothing had happened */ - - /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ - olen = old_length + 2*st->magic_samples[i]; - for (j=old_length-2+st->magic_samples[i];j>=0;j--) - st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; - for (j=0;jmagic_samples[i];j++) - st->mem[i*st->mem_alloc_size+j] = 0; - st->magic_samples[i] = 0; - } - if (st->filt_len > olen) - { - /* If the new filter length is still bigger than the "augmented" length */ - /* Copy data going backward */ - for (j=0;jmem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; - /* Then put zeros for lack of anything better */ - for (;jfilt_len-1;j++) - st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; - /* Adjust last_sample */ - st->last_sample[i] += (st->filt_len - olen)/2; - } else { - /* Put back some of the magic! */ - st->magic_samples[i] = (olen - st->filt_len)/2; - for (j=0;jfilt_len-1+st->magic_samples[i];j++) - st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; - } - } - } else if (st->filt_len < old_length) - { - spx_uint32_t i; - /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" - samples so they can be used directly as input the next time(s) */ - for (i=0;inb_channels;i++) - { - spx_uint32_t j; - spx_uint32_t old_magic = st->magic_samples[i]; - st->magic_samples[i] = (old_length - st->filt_len)/2; - /* We must copy some of the memory that's no longer used */ - /* Copy data going backward */ - for (j=0;jfilt_len-1+st->magic_samples[i]+old_magic;j++) - st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; - st->magic_samples[i] += old_magic; - } - } - -} - -EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) -{ - return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); -} - -EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) -{ - spx_uint32_t i; - SpeexResamplerState *st; - if (quality > 10 || quality < 0) - { - if (err) - *err = RESAMPLER_ERR_INVALID_ARG; - return NULL; - } - st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); - st->initialised = 0; - st->started = 0; - st->in_rate = 0; - st->out_rate = 0; - st->num_rate = 0; - st->den_rate = 0; - st->quality = -1; - st->sinc_table_length = 0; - st->mem_alloc_size = 0; - st->filt_len = 0; - st->mem = 0; - st->resampler_ptr = 0; - - st->cutoff = 1.f; - st->nb_channels = nb_channels; - st->in_stride = 1; - st->out_stride = 1; - -#ifdef FIXED_POINT - st->buffer_size = 160; -#else - st->buffer_size = 160; -#endif - - /* Per channel data */ - st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); - st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); - st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); - for (i=0;ilast_sample[i] = 0; - st->magic_samples[i] = 0; - st->samp_frac_num[i] = 0; - } - - speex_resampler_set_quality(st, quality); - speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); - - - update_filter(st); - - st->initialised = 1; - if (err) - *err = RESAMPLER_ERR_SUCCESS; - - return st; -} - -EXPORT void speex_resampler_destroy(SpeexResamplerState *st) -{ - speex_free(st->mem); - speex_free(st->sinc_table); - speex_free(st->last_sample); - speex_free(st->magic_samples); - speex_free(st->samp_frac_num); - speex_free(st); -} - -static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) -{ - int j=0; - const int N = st->filt_len; - int out_sample = 0; - spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; - spx_uint32_t ilen; - - st->started = 1; - - /* Call the right resampler through the function ptr */ - out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); - - if (st->last_sample[channel_index] < (spx_int32_t)*in_len) - *in_len = st->last_sample[channel_index]; - *out_len = out_sample; - st->last_sample[channel_index] -= *in_len; - - ilen = *in_len; - - for(j=0;jmagic_samples[channel_index]; - spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; - const int N = st->filt_len; - - speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); - - st->magic_samples[channel_index] -= tmp_in_len; - - /* If we couldn't process all "magic" input samples, save the rest for next time */ - if (st->magic_samples[channel_index]) - { - spx_uint32_t i; - for (i=0;imagic_samples[channel_index];i++) - mem[N-1+i]=mem[N-1+i+tmp_in_len]; - } - *out += out_len*st->out_stride; - return out_len; -} - -#ifdef FIXED_POINT -EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) -#else -EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) -#endif -{ - int j; - spx_uint32_t ilen = *in_len; - spx_uint32_t olen = *out_len; - spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; - const int filt_offs = st->filt_len - 1; - const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; - const int istride = st->in_stride; - - if (st->magic_samples[channel_index]) - olen -= speex_resampler_magic(st, channel_index, &out, olen); - if (! st->magic_samples[channel_index]) { - while (ilen && olen) { - spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; - spx_uint32_t ochunk = olen; - - if (in) { - for(j=0;jout_stride; - if (in) - in += ichunk * istride; - } - } - *in_len -= ilen; - *out_len -= olen; - return RESAMPLER_ERR_SUCCESS; -} - -#ifdef FIXED_POINT -EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) -#else -EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) -#endif -{ - int j; - const int istride_save = st->in_stride; - const int ostride_save = st->out_stride; - spx_uint32_t ilen = *in_len; - spx_uint32_t olen = *out_len; - spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; - const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); -#ifdef VAR_ARRAYS - const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; - VARDECL(spx_word16_t *ystack); - ALLOC(ystack, ylen, spx_word16_t); -#else - const unsigned int ylen = FIXED_STACK_ALLOC; - spx_word16_t ystack[FIXED_STACK_ALLOC]; -#endif - - st->out_stride = 1; - - while (ilen && olen) { - spx_word16_t *y = ystack; - spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; - spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; - spx_uint32_t omagic = 0; - - if (st->magic_samples[channel_index]) { - omagic = speex_resampler_magic(st, channel_index, &y, ochunk); - ochunk -= omagic; - olen -= omagic; - } - if (! st->magic_samples[channel_index]) { - if (in) { - for(j=0;jfilt_len-1]=WORD2INT(in[j*istride_save]); -#else - x[j+st->filt_len-1]=in[j*istride_save]; -#endif - } else { - for(j=0;jfilt_len-1]=0; - } - - speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk); - } else { - ichunk = 0; - ochunk = 0; - } - - for (j=0;jout_stride = ostride_save; - *in_len -= ilen; - *out_len -= olen; - - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) -{ - spx_uint32_t i; - int istride_save, ostride_save; - spx_uint32_t bak_len = *out_len; - istride_save = st->in_stride; - ostride_save = st->out_stride; - st->in_stride = st->out_stride = st->nb_channels; - for (i=0;inb_channels;i++) - { - *out_len = bak_len; - if (in != NULL) - speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); - else - speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len); - } - st->in_stride = istride_save; - st->out_stride = ostride_save; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) -{ - spx_uint32_t i; - int istride_save, ostride_save; - spx_uint32_t bak_len = *out_len; - istride_save = st->in_stride; - ostride_save = st->out_stride; - st->in_stride = st->out_stride = st->nb_channels; - for (i=0;inb_channels;i++) - { - *out_len = bak_len; - if (in != NULL) - speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); - else - speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len); - } - st->in_stride = istride_save; - st->out_stride = ostride_save; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) -{ - return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); -} - -EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) -{ - *in_rate = st->in_rate; - *out_rate = st->out_rate; -} - -EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) -{ - spx_uint32_t fact; - spx_uint32_t old_den; - spx_uint32_t i; - if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) - return RESAMPLER_ERR_SUCCESS; - - old_den = st->den_rate; - st->in_rate = in_rate; - st->out_rate = out_rate; - st->num_rate = ratio_num; - st->den_rate = ratio_den; - /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ - for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) - { - while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) - { - st->num_rate /= fact; - st->den_rate /= fact; - } - } - - if (old_den > 0) - { - for (i=0;inb_channels;i++) - { - st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; - /* Safety net */ - if (st->samp_frac_num[i] >= st->den_rate) - st->samp_frac_num[i] = st->den_rate-1; - } - } - - if (st->initialised) - update_filter(st); - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) -{ - *ratio_num = st->num_rate; - *ratio_den = st->den_rate; -} - -EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality) -{ - if (quality > 10 || quality < 0) - return RESAMPLER_ERR_INVALID_ARG; - if (st->quality == quality) - return RESAMPLER_ERR_SUCCESS; - st->quality = quality; - if (st->initialised) - update_filter(st); - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) -{ - *quality = st->quality; -} - -EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) -{ - st->in_stride = stride; -} - -EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) -{ - *stride = st->in_stride; -} - -EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) -{ - st->out_stride = stride; -} - -EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) -{ - *stride = st->out_stride; -} - -EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st) -{ - return st->filt_len / 2; -} - -EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st) -{ - return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate; -} - -EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st) -{ - spx_uint32_t i; - for (i=0;inb_channels;i++) - st->last_sample[i] = st->filt_len/2; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st) -{ - spx_uint32_t i; - for (i=0;inb_channels*(st->filt_len-1);i++) - st->mem[i] = 0; - return RESAMPLER_ERR_SUCCESS; -} - -EXPORT const char *speex_resampler_strerror(int err) -{ - switch (err) - { - case RESAMPLER_ERR_SUCCESS: - return "Success."; - case RESAMPLER_ERR_ALLOC_FAILED: - return "Memory allocation failed."; - case RESAMPLER_ERR_BAD_STATE: - return "Bad resampler state."; - case RESAMPLER_ERR_INVALID_ARG: - return "Invalid argument."; - case RESAMPLER_ERR_PTR_OVERLAP: - return "Input and output buffers overlap."; - default: - return "Unknown error. Bad error code or strange version mismatch."; - } -} diff --git a/libspeex/resample_sse.h b/libspeex/resample_sse.h deleted file mode 100644 index 64be8a1..0000000 --- a/libspeex/resample_sse.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2007-2008 Jean-Marc Valin - * Copyright (C) 2008 Thorvald Natvig - */ -/** - @file resample_sse.h - @brief Resampler functions (SSE version) -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include - -#define OVERRIDE_INNER_PRODUCT_SINGLE -static inline float inner_product_single(const float *a, const float *b, unsigned int len) -{ - int i; - float ret; - __m128 sum = _mm_setzero_ps(); - for (i=0;i -#define OVERRIDE_INNER_PRODUCT_DOUBLE - -static inline double inner_product_double(const float *a, const float *b, unsigned int len) -{ - int i; - double ret; - __m128d sum = _mm_setzero_pd(); - __m128 t; - for (i=0;i -#include - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#define ALLPASS_ORDER 20 - -struct SpeexDecorrState_ { - int rate; - int channels; - int frame_size; -#ifdef VORBIS_PSYCHO - VorbisPsy *psy; - struct drft_lookup lookup; - float *wola_mem; - float *curve; -#endif - float *vorbis_win; - int seed; - float *y; - - /* Per-channel stuff */ - float *buff; - float (*ring)[ALLPASS_ORDER]; - int *ringID; - int *order; - float *alpha; -}; - - - -EXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size) -{ - int i, ch; - SpeexDecorrState *st = speex_alloc(sizeof(SpeexDecorrState)); - st->rate = rate; - st->channels = channels; - st->frame_size = frame_size; -#ifdef VORBIS_PSYCHO - st->psy = vorbis_psy_init(rate, 2*frame_size); - spx_drft_init(&st->lookup, 2*frame_size); - st->wola_mem = speex_alloc(frame_size*sizeof(float)); - st->curve = speex_alloc(frame_size*sizeof(float)); -#endif - st->y = speex_alloc(frame_size*sizeof(float)); - - st->buff = speex_alloc(channels*2*frame_size*sizeof(float)); - st->ringID = speex_alloc(channels*sizeof(int)); - st->order = speex_alloc(channels*sizeof(int)); - st->alpha = speex_alloc(channels*sizeof(float)); - st->ring = speex_alloc(channels*ALLPASS_ORDER*sizeof(float)); - - /*FIXME: The +20 is there only as a kludge for ALL_PASS_OLA*/ - st->vorbis_win = speex_alloc((2*frame_size+20)*sizeof(float)); - for (i=0;i<2*frame_size;i++) - st->vorbis_win[i] = sin(.5*M_PI* sin(M_PI*i/(2*frame_size))*sin(M_PI*i/(2*frame_size)) ); - st->seed = rand(); - - for (ch=0;chring[ch][i] = 0; - st->ringID[ch] = 0; - st->alpha[ch] = 0; - st->order[ch] = 10; - } - return st; -} - -static float uni_rand(int *seed) -{ - const unsigned int jflone = 0x3f800000; - const unsigned int jflmsk = 0x007fffff; - union {int i; float f;} ran; - *seed = 1664525 * *seed + 1013904223; - ran.i = jflone | (jflmsk & *seed); - ran.f -= 1.5; - return 2*ran.f; -} - -static unsigned int irand(int *seed) -{ - *seed = 1664525 * *seed + 1013904223; - return ((unsigned int)*seed)>>16; -} - - -EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength) -{ - int ch; - float amount; - - if (strength<0) - strength = 0; - if (strength>100) - strength = 100; - - amount = .01*strength; - for (ch=0;chchannels;ch++) - { - int i; - int N=2*st->frame_size; - float beta, beta2; - float *x; - float max_alpha = 0; - - float *buff; - float *ring; - int ringID; - int order; - float alpha; - - buff = st->buff+ch*2*st->frame_size; - ring = st->ring[ch]; - ringID = st->ringID[ch]; - order = st->order[ch]; - alpha = st->alpha[ch]; - - for (i=0;iframe_size;i++) - buff[i] = buff[i+st->frame_size]; - for (i=0;iframe_size;i++) - buff[i+st->frame_size] = in[i*st->channels+ch]; - - x = buff+st->frame_size; - beta = 1.-.3*amount*amount; - if (amount>1) - beta = 1-sqrt(.4*amount); - else - beta = 1-0.63246*amount; - if (beta<0) - beta = 0; - - beta2 = beta; - for (i=0;iframe_size;i++) - { - st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order] - + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i] - - alpha*(ring[ringID] - - beta*ring[ringID+1>=order?0:ringID+1]); - ring[ringID++]=st->y[i]; - st->y[i] *= st->vorbis_win[st->frame_size+i]; - if (ringID>=order) - ringID=0; - } - order = order+(irand(&st->seed)%3)-1; - if (order < 5) - order = 5; - if (order > 10) - order = 10; - /*order = 5+(irand(&st->seed)%6);*/ - max_alpha = pow(.96+.04*(amount-1),order); - if (max_alpha > .98/(1.+beta2)) - max_alpha = .98/(1.+beta2); - - alpha = alpha + .4*uni_rand(&st->seed); - if (alpha > max_alpha) - alpha = max_alpha; - if (alpha < -max_alpha) - alpha = -max_alpha; - for (i=0;iframe_size;i++) - { - float tmp = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order] - + x[i-ALLPASS_ORDER]*st->vorbis_win[i] - - alpha*(ring[ringID] - - beta*ring[ringID+1>=order?0:ringID+1]); - ring[ringID++]=tmp; - tmp *= st->vorbis_win[i]; - if (ringID>=order) - ringID=0; - st->y[i] += tmp; - } - -#ifdef VORBIS_PSYCHO - float frame[N]; - float scale = 1./N; - for (i=0;i<2*st->frame_size;i++) - frame[i] = buff[i]; - //float coef = .5*0.78130; - float coef = M_PI*0.075063 * 0.93763 * amount * .8 * 0.707; - compute_curve(st->psy, buff, st->curve); - for (i=1;iframe_size;i++) - { - float x1,x2; - float gain; - do { - x1 = uni_rand(&st->seed); - x2 = uni_rand(&st->seed); - } while (x1*x1+x2*x2 > 1.); - gain = coef*sqrt(.1+st->curve[i]); - frame[2*i-1] = gain*x1; - frame[2*i] = gain*x2; - } - frame[0] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[0]); - frame[2*st->frame_size-1] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[st->frame_size-1]); - spx_drft_backward(&st->lookup,frame); - for (i=0;i<2*st->frame_size;i++) - frame[i] *= st->vorbis_win[i]; -#endif - - for (i=0;iframe_size;i++) - { -#ifdef VORBIS_PSYCHO - float tmp = st->y[i] + frame[i] + st->wola_mem[i]; - st->wola_mem[i] = frame[i+st->frame_size]; -#else - float tmp = st->y[i]; -#endif - if (tmp>32767) - tmp = 32767; - if (tmp < -32767) - tmp = -32767; - out[i*st->channels+ch] = tmp; - } - - st->ringID[ch] = ringID; - st->order[ch] = order; - st->alpha[ch] = alpha; - - } -} - -EXPORT void speex_decorrelate_destroy(SpeexDecorrState *st) -{ -#ifdef VORBIS_PSYCHO - vorbis_psy_destroy(st->psy); - speex_free(st->wola_mem); - speex_free(st->curve); -#endif - speex_free(st->buff); - speex_free(st->ring); - speex_free(st->ringID); - speex_free(st->alpha); - speex_free(st->vorbis_win); - speex_free(st->order); - speex_free(st->y); - speex_free(st); -} diff --git a/libspeex/testdenoise.c b/libspeex/testdenoise.c deleted file mode 100644 index 9c5398b..0000000 --- a/libspeex/testdenoise.c +++ /dev/null @@ -1,44 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../include/speex/speex_preprocess.h" -#include - -#define NN 160 - -int main() -{ - short in[NN]; - int i; - SpeexPreprocessState *st; - int count=0; - float f; - - st = speex_preprocess_state_init(NN, 8000); - i=1; - speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i); - i=0; - speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i); - i=8000; - speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i); - i=0; - speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i); - f=.0; - speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f); - f=.0; - speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f); - while (1) - { - int vad; - fread(in, sizeof(short), NN, stdin); - if (feof(stdin)) - break; - vad = speex_preprocess_run(st, in); - /*fprintf (stderr, "%d\n", vad);*/ - fwrite(in, sizeof(short), NN, stdout); - count++; - } - speex_preprocess_state_destroy(st); - return 0; -} diff --git a/libspeex/testecho.c b/libspeex/testecho.c deleted file mode 100644 index 2eedfac..0000000 --- a/libspeex/testecho.c +++ /dev/null @@ -1,53 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include "../include/speex/speex_echo.h" -#include "../include/speex/speex_preprocess.h" - - -#define NN 128 -#define TAIL 1024 - -int main(int argc, char **argv) -{ - FILE *echo_fd, *ref_fd, *e_fd; - short echo_buf[NN], ref_buf[NN], e_buf[NN]; - SpeexEchoState *st; - SpeexPreprocessState *den; - int sampleRate = 8000; - - if (argc != 4) - { - fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n"); - exit(1); - } - echo_fd = fopen(argv[2], "rb"); - ref_fd = fopen(argv[1], "rb"); - e_fd = fopen(argv[3], "wb"); - - st = speex_echo_state_init(NN, TAIL); - den = speex_preprocess_state_init(NN, sampleRate); - speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); - speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st); - - while (!feof(ref_fd) && !feof(echo_fd)) - { - fread(ref_buf, sizeof(short), NN, ref_fd); - fread(echo_buf, sizeof(short), NN, echo_fd); - speex_echo_cancellation(st, ref_buf, echo_buf, e_buf); - speex_preprocess_run(den, e_buf); - fwrite(e_buf, sizeof(short), NN, e_fd); - } - speex_echo_state_destroy(st); - speex_preprocess_state_destroy(den); - fclose(e_fd); - fclose(echo_fd); - fclose(ref_fd); - return 0; -} diff --git a/libspeex/testjitter.c b/libspeex/testjitter.c deleted file mode 100644 index c4894fb..0000000 --- a/libspeex/testjitter.c +++ /dev/null @@ -1,75 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../include/speex/speex_jitter.h" -#include - -union jbpdata { - unsigned int idx; - unsigned char data[4]; -}; - -void synthIn(JitterBufferPacket *in, int idx, int span) { - union jbpdata d; - d.idx = idx; - - in->data = d.data; - in->len = sizeof(d); - in->timestamp = idx * 10; - in->span = span * 10; - in->sequence = idx; - in->user_data = 0; -} - -void jitterFill(JitterBuffer *jb) { - char buffer[65536]; - JitterBufferPacket in, out; - int i; - - out.data = buffer; - - jitter_buffer_reset(jb); - - for(i=0;i<100;++i) { - synthIn(&in, i, 1); - jitter_buffer_put(jb, &in); - - out.len = 65536; - if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) { - printf("Fill test failed iteration %d\n", i); - } - if (out.timestamp != i * 10) { - printf("Fill test expected %d got %d\n", i*10, out.timestamp); - } - jitter_buffer_tick(jb); - } -} - -int main() -{ - char buffer[65536]; - JitterBufferPacket in, out; - int i; - - JitterBuffer *jb = jitter_buffer_init(10); - - out.data = buffer; - - /* Frozen sender case */ - jitterFill(jb); - for(i=0;i<100;++i) { - out.len = 65536; - jitter_buffer_get(jb, &out, 10, NULL); - jitter_buffer_tick(jb); - } - synthIn(&in, 100, 1); - jitter_buffer_put(jb, &in); - out.len = 65536; - if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) { - printf("Failed frozen sender resynchronize\n"); - } else { - printf("Frozen sender: Jitter %d\n", out.timestamp - 100*10); - } - return 0; -} diff --git a/libspeex/testresample.c b/libspeex/testresample.c deleted file mode 100644 index 8e16dc7..0000000 --- a/libspeex/testresample.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2007 Jean-Marc Valin - - File: testresample.c - Testing the resampling code - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "../include/speex/speex_resampler.h" -#include -#include - -#define NN 256 - -int main() -{ - spx_uint32_t i; - short *in; - short *out; - float *fin, *fout; - int count = 0; - SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 10, NULL); - speex_resampler_set_rate(st, 96000, 44100); - speex_resampler_skip_zeros(st); - - in = malloc(NN*sizeof(short)); - out = malloc(2*NN*sizeof(short)); - fin = malloc(NN*sizeof(float)); - fout = malloc(2*NN*sizeof(float)); - while (1) - { - spx_uint32_t in_len; - spx_uint32_t out_len; - fread(in, sizeof(short), NN, stdin); - if (feof(stdin)) - break; - for (i=0;i +#endif #if defined WIN32 || defined _WIN32 /* We need the following two to set stdout to binary */ @@ -225,8 +227,10 @@ void usage() printf (" --dtx Enable file-based discontinuous transmission (DTX)\n"); printf (" --comp n Set encoding complexity (0-10), default 3\n"); printf (" --nframes n Number of frames per Ogg packet (1-10), default 1\n"); +#ifdef USE_SPEEXDSP printf (" --denoise Denoise the input before encoding\n"); printf (" --agc Apply adaptive gain control (AGC) before encoding\n"); +#endif printf (" --no-highpass Disable the encoder's built-in high-pass filter\n"); printf (" --skeleton Outputs ogg skeleton metadata (may cause incompatibilities)\n"); printf (" --comment Add the given string as an extra comment. This may be\n"); @@ -288,8 +292,10 @@ int main(int argc, char **argv) {"bitrate", required_argument, NULL, 0}, {"nframes", required_argument, NULL, 0}, {"comp", required_argument, NULL, 0}, +#ifdef USE_SPEEXDSP {"denoise", no_argument, NULL, 0}, {"agc", no_argument, NULL, 0}, +#endif {"no-highpass", no_argument, NULL, 0}, {"skeleton",no_argument,NULL, 0}, {"help", no_argument, NULL, 0}, @@ -336,8 +342,10 @@ int main(int argc, char **argv) char first_bytes[12]; int wave_input=0; spx_int32_t tmp; +#ifdef USE_SPEEXDSP SpeexPreprocessState *preprocess = NULL; int denoise_enabled=0, agc_enabled=0; +#endif int highpass_enabled=1; int output_rate=0; spx_int32_t lookahead = 0; @@ -409,12 +417,14 @@ int main(int argc, char **argv) } else if (strcmp(long_options[option_index].name,"comp")==0) { complexity = atoi (optarg); +#ifdef USE_SPEEXDSP } else if (strcmp(long_options[option_index].name,"denoise")==0) { denoise_enabled=1; } else if (strcmp(long_options[option_index].name,"agc")==0) { agc_enabled=1; +#endif } else if (strcmp(long_options[option_index].name,"no-highpass")==0) { highpass_enabled=0; @@ -716,6 +726,7 @@ int main(int argc, char **argv) speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); +#ifdef USE_SPEEXDSP if (denoise_enabled || agc_enabled) { preprocess = speex_preprocess_state_init(frame_size, rate); @@ -723,7 +734,7 @@ int main(int argc, char **argv) speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &agc_enabled); lookahead += frame_size; } - +#endif /* first packet should be the skeleton header. */ if (with_skeleton) { @@ -826,9 +837,10 @@ int main(int argc, char **argv) if (chan==2) speex_encode_stereo_int(input, frame_size, &bits); +#ifdef USE_SPEEXDSP if (preprocess) speex_preprocess(preprocess, input, NULL); - +#endif speex_encode_int(st, input, &bits); nb_encoded += frame_size; diff --git a/win32/Makefile.am b/win32/Makefile.am index 8cee7fb..9ab5387 100644 --- a/win32/Makefile.am +++ b/win32/Makefile.am @@ -5,4 +5,4 @@ SUBDIRS = libspeex speexenc speexdec VS2003 VS2005 VS2008 -EXTRA_DIST = speex.iss config.h libspeex.def libspeexdsp.def +EXTRA_DIST = speex.iss config.h libspeex.def diff --git a/win32/VS2003/Makefile.am b/win32/VS2003/Makefile.am index 15479c3..3fec6aa 100644 --- a/win32/VS2003/Makefile.am +++ b/win32/VS2003/Makefile.am @@ -3,6 +3,6 @@ # Disable automatic dependency tracking if using other tools than gcc and gmake #AUTOMAKE_OPTIONS = no-dependencies -SUBDIRS = libspeex libspeexdsp speexenc speexdec tests +SUBDIRS = libspeex speexenc speexdec tests EXTRA_DIST = libspeex.sln diff --git a/win32/VS2003/libspeexdsp/Makefile.am b/win32/VS2003/libspeexdsp/Makefile.am deleted file mode 100644 index 796fefc..0000000 --- a/win32/VS2003/libspeexdsp/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -## Process this file with automake to produce Makefile.in. -*-Makefile-*- - -# Disable automatic dependency tracking if using other tools than gcc and gmake -#AUTOMAKE_OPTIONS = no-dependencies - -EXTRA_DIST = libspeexdsp.vcproj - - diff --git a/win32/VS2003/libspeexdsp/libspeexdsp.vcproj b/win32/VS2003/libspeexdsp/libspeexdsp.vcproj deleted file mode 100755 index 1fc21ad..0000000 --- a/win32/VS2003/libspeexdsp/libspeexdsp.vcproj +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/VS2005/Makefile.am b/win32/VS2005/Makefile.am index 15479c3..3fec6aa 100644 --- a/win32/VS2005/Makefile.am +++ b/win32/VS2005/Makefile.am @@ -3,6 +3,6 @@ # Disable automatic dependency tracking if using other tools than gcc and gmake #AUTOMAKE_OPTIONS = no-dependencies -SUBDIRS = libspeex libspeexdsp speexenc speexdec tests +SUBDIRS = libspeex speexenc speexdec tests EXTRA_DIST = libspeex.sln diff --git a/win32/VS2005/libspeexdsp/Makefile.am b/win32/VS2005/libspeexdsp/Makefile.am deleted file mode 100644 index 796fefc..0000000 --- a/win32/VS2005/libspeexdsp/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -## Process this file with automake to produce Makefile.in. -*-Makefile-*- - -# Disable automatic dependency tracking if using other tools than gcc and gmake -#AUTOMAKE_OPTIONS = no-dependencies - -EXTRA_DIST = libspeexdsp.vcproj - - diff --git a/win32/VS2005/libspeexdsp/libspeexdsp.vcproj b/win32/VS2005/libspeexdsp/libspeexdsp.vcproj deleted file mode 100755 index 2d22d6a..0000000 --- a/win32/VS2005/libspeexdsp/libspeexdsp.vcproj +++ /dev/null @@ -1,1628 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/VS2008/Makefile.am b/win32/VS2008/Makefile.am index 15479c3..3fec6aa 100644 --- a/win32/VS2008/Makefile.am +++ b/win32/VS2008/Makefile.am @@ -3,6 +3,6 @@ # Disable automatic dependency tracking if using other tools than gcc and gmake #AUTOMAKE_OPTIONS = no-dependencies -SUBDIRS = libspeex libspeexdsp speexenc speexdec tests +SUBDIRS = libspeex speexenc speexdec tests EXTRA_DIST = libspeex.sln diff --git a/win32/VS2008/libspeexdsp/Makefile.am b/win32/VS2008/libspeexdsp/Makefile.am deleted file mode 100644 index 796fefc..0000000 --- a/win32/VS2008/libspeexdsp/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -## Process this file with automake to produce Makefile.in. -*-Makefile-*- - -# Disable automatic dependency tracking if using other tools than gcc and gmake -#AUTOMAKE_OPTIONS = no-dependencies - -EXTRA_DIST = libspeexdsp.vcproj - - diff --git a/win32/VS2008/libspeexdsp/libspeexdsp.vcproj b/win32/VS2008/libspeexdsp/libspeexdsp.vcproj deleted file mode 100755 index 5904b94..0000000 --- a/win32/VS2008/libspeexdsp/libspeexdsp.vcproj +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/libspeex/Makefile.am b/win32/libspeex/Makefile.am index 9cf4e85..4d95004 100644 --- a/win32/libspeex/Makefile.am +++ b/win32/libspeex/Makefile.am @@ -3,4 +3,4 @@ # Disable automatic dependency tracking if using other tools than gcc and gmake #AUTOMAKE_OPTIONS = no-dependencies -EXTRA_DIST = libspeex.dsw libspeex.dsp libspeex_dynamic.dsp libspeexdsp.dsp libspeexdsp_dynamic.dsp +EXTRA_DIST = libspeex.dsw libspeex.dsp libspeex_dynamic.dsp diff --git a/win32/libspeex/libspeexdsp.dsp b/win32/libspeex/libspeexdsp.dsp deleted file mode 100755 index 6accbd8..0000000 --- a/win32/libspeex/libspeexdsp.dsp +++ /dev/null @@ -1,228 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libspeexdsp" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=libspeexdsp - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libspeexdsp.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libspeexdsp.mak" CFG="libspeexdsp - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libspeexdsp - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libspeexdsp - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libspeexdsp - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -F90=df.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W1 /GX- /O2 /I "../../include" /I "../" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "HAVE_CONFIG_H" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x419 /d "NDEBUG" -# ADD RSC /l 0x809 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\..\lib\libspeexdsp.lib" - -!ELSEIF "$(CFG)" == "libspeexdsp - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "libspeexdsp___Win32_Debug" -# PROP BASE Intermediate_Dir "libspeexdsp___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "libspeexdsp___Win32_Debug" -# PROP Intermediate_Dir "libspeexdsp___Win32_Debug" -# PROP Target_Dir "" -F90=df.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm- /GX- /Zi /Od /I "../../include" /I "../" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "HAVE_CONFIG_H" /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x419 /d "_DEBUG" -# ADD RSC /l 0x809 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\..\lib\libspeexdsp.lib" - -!ENDIF - -# Begin Target - -# Name "libspeexdsp - Win32 Release" -# Name "libspeexdsp - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\libspeex\buffer.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fftwrap.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\filterbank.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\jitter.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fft.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fftr.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\mdf.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\preprocess.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\resample.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\scal.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\smallft.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\libspeex\_kiss_fft_guts.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\arch.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fftwrap.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\filterbank.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fixed_debug.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fixed_generic.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fft.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fftr.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\math_approx.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\os_support.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\pseudofloat.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\smallft.h -# End Source File -# End Group -# Begin Group "Public Header Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\include\speex\speex.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_bits.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_buffer.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_echo.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_jitter.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_preprocess.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_resampler.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_types.h -# End Source File -# End Group -# Begin Source File - -SOURCE=..\config.h -# End Source File -# End Target -# End Project diff --git a/win32/libspeex/libspeexdsp_dynamic.dsp b/win32/libspeex/libspeexdsp_dynamic.dsp deleted file mode 100755 index ac40b38..0000000 --- a/win32/libspeex/libspeexdsp_dynamic.dsp +++ /dev/null @@ -1,237 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libspeexdsp_dynamic" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=libspeexdsp_dynamic - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libspeexdsp_dynamic.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libspeexdsp_dynamic.mak" CFG="libspeexdsp_dynamic - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libspeexdsp_dynamic - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "libspeexdsp_dynamic - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libspeexdsp_dynamic - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "libspeexdsp_dynamic___Win32_Release" -# PROP BASE Intermediate_Dir "libspeexdsp_dynamic___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Dynamic_Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSPEEX_DYNAMIC_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HAVE_CONFIG_H" /FD /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\bin\libspeexdsp.dll" /implib:"..\..\lib\libspeexdsp.lib" - -!ELSEIF "$(CFG)" == "libspeexdsp_dynamic - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "libspeexdsp_dynamic___Win32_Debug" -# PROP BASE Intermediate_Dir "libspeexdsp_dynamic___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Dynamic_Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSPEEX_DYNAMIC_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "../" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HAVE_CONFIG_H" /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\bin\libspeexdsp.dll" /implib:"..\..\lib\libspeexdsp.lib" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "libspeexdsp_dynamic - Win32 Release" -# Name "libspeexdsp_dynamic - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\libspeex\buffer.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fftwrap.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\filterbank.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\jitter.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fft.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fftr.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\mdf.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\preprocess.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\resample.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\scal.c -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\smallft.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\libspeex\_kiss_fft_guts.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\arch.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fftwrap.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\filterbank.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fixed_debug.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\fixed_generic.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fft.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\kiss_fftr.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\math_approx.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\os_support.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\pseudofloat.h -# End Source File -# Begin Source File - -SOURCE=..\..\libspeex\smallft.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_buffer.h -# End Source File -# End Group -# Begin Group "Public Header Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\include\speex\speex.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_bits.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_echo.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_jitter.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_preprocess.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_resampler.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\speex\speex_types.h -# End Source File -# End Group -# Begin Source File - -SOURCE=..\config.h -# End Source File -# Begin Source File - -SOURCE=..\libspeexdsp.def -# End Source File -# End Target -# End Project diff --git a/win32/libspeexdsp.def b/win32/libspeexdsp.def deleted file mode 100755 index 45fc69d..0000000 --- a/win32/libspeexdsp.def +++ /dev/null @@ -1,76 +0,0 @@ -LIBRARY libspeexdsp -EXPORTS - - -; -; speex_buffer.h -; -speex_buffer_init -speex_buffer_destroy -speex_buffer_write -speex_buffer_writezeros -speex_buffer_read -speex_buffer_get_available -speex_buffer_resize - -; -; speex_echo.h -; -speex_echo_state_init -speex_echo_state_init_mc -speex_echo_state_destroy -speex_echo_cancellation -speex_echo_cancel -speex_echo_capture -speex_echo_playback -speex_echo_state_reset -speex_echo_ctl -speex_decorrelate_new -speex_decorrelate -speex_decorrelate_destroy - -; -; speex_jitter.h -; -jitter_buffer_init -jitter_buffer_reset -jitter_buffer_destroy -jitter_buffer_put -jitter_buffer_get -jitter_buffer_get_pointer_timestamp -jitter_buffer_tick -jitter_buffer_update_delay - -; -; speex_preprocess.h -; -speex_preprocess_state_init -speex_preprocess_state_destroy -speex_preprocess_run -speex_preprocess -speex_preprocess_estimate_update -speex_preprocess_ctl - -; -; speex_resampler.h -; -speex_resampler_init -speex_resampler_init_frac -speex_resampler_destroy -speex_resampler_process_float -speex_resampler_process_int -speex_resampler_process_interleaved_float -speex_resampler_process_interleaved_int -speex_resampler_set_rate -speex_resampler_get_rate -speex_resampler_set_rate_frac -speex_resampler_get_ratio -speex_resampler_set_quality -speex_resampler_get_quality -speex_resampler_set_input_stride -speex_resampler_get_input_stride -speex_resampler_set_output_stride -speex_resampler_get_output_stride -speex_resampler_skip_zeros -speex_resampler_reset_mem -speex_resampler_strerror -- cgit v1.2.3