diff --git a/external/speex/CMakeLists.txt b/external/speex/CMakeLists.txt index 951d3e2..4d8c6c9 100644 --- a/external/speex/CMakeLists.txt +++ b/external/speex/CMakeLists.txt @@ -2,7 +2,19 @@ # Project Definition #------------------------------------------------------------------------------- -project("Speex") +project( "Speex" + VERSION "1.2.1" + DESCRIPTION "Speex voice codec" + HOMEPAGE_URL "https://gitlab.xiph.org/xiph/speex" + LANGUAGES "C" +) + +#------------------------------------------------------------------------------- +# Options +#------------------------------------------------------------------------------- + +option(SPEEX_ENABLE_VORBIS_PSY "Enable Vorbis psychoacoustic model" OFF) +option(SPEEX_USE_KISS_FFT "Use KISS Fast Fourier Transform (otherwise OggVorbis)" OFF) #------------------------------------------------------------------------------- # Target Definition @@ -22,12 +34,18 @@ target_sources("${TARGET_NAME}" PUBLIC "include/speex/speex_bits.h" "include/speex/speex_callbacks.h" + "include/speex/speex_config_types.h" "include/speex/speex_header.h" "include/speex/speex_stereo.h" + "include/speex/speex_types.h" "include/speex/speex.h" PRIVATE + "src/arch.h" + "src/bfin.h" "src/bits.c" + "src/cb_search_bfin.h" + "src/cb_search_sse.h" "src/cb_search.c" "src/cb_search.h" "src/exc_10_16_table.c" @@ -36,42 +54,73 @@ target_sources("${TARGET_NAME}" "src/exc_5_256_table.c" "src/exc_5_64_table.c" "src/exc_8_128_table.c" + "src/fftwrap.h" + "src/filters_bfin.h" "src/filters_sse.h" "src/filters.c" "src/filters.h" + "src/fixed_bfin.h" + "src/fixed_debug.h" + "src/fixed_generic.h" "src/gain_table_lbr.c" "src/gain_table.c" "src/hexc_10_32_table.c" "src/hexc_table.c" "src/high_lsp_tables.c" + "src/lpc_bfin.h" "src/lpc.c" "src/lpc.h" + "src/lsp_bfin.h" "src/lsp_tables_nb.c" "src/lsp.c" "src/lsp.h" + "src/ltp_bfin.h" "src/ltp_sse.h" "src/ltp.c" "src/ltp.h" - "src/math_approx.c" "src/math_approx.h" - "src/misc.c" - "src/misc.h" + "src/misc_bfin.h" + "src/modes_wb.c" "src/modes.c" "src/modes.h" "src/nb_celp.c" "src/nb_celp.h" + "src/os_support.h" + "src/quant_lsp_bfin.h" "src/quant_lsp.c" "src/quant_lsp.h" "src/sb_celp.c" "src/sb_celp.h" "src/speex_callbacks.c" "src/speex_header.c" + "src/speex.c" "src/stack_alloc.h" "src/stereo.c" "src/vbr.c" "src/vbr.h" + "src/vq_bfin.h" + "src/vq_sse.h" "src/vq.c" "src/vq.h" + "src/window.c" + + $<$: + "src/_kiss_fft_guts.h" + "src/kiss_fft.c" + "src/kiss_fft.h" + "src/kiss_fftr.c" + "src/kiss_fftr.h" + > + + $<$>: + "src/smallft.c" + "src/smallft.h" + > + + $<$: + "src/vorbis_psy.c" + "src/vorbis_psy.h" + > ) #------------------------------------------------------------------------------- @@ -86,11 +135,70 @@ target_include_directories("${TARGET_NAME}" "${PROJECT_SOURCE_DIR}/include/speex" ) +#------------------------------------------------------------------------------- +# Compile Definitions +#------------------------------------------------------------------------------- + +target_compile_definitions("${TARGET_NAME}" + PRIVATE + _USE_SSE + FLOATING_POINT + + SPEEX_MAJOR_VERSION=${PROJECT_VERSION_MAJOR} + SPEEX_MINOR_VERSION=${PROJECT_VERSION_MINOR} + SPEEX_MICRO_VERSION=${PROJECT_VERSION_PATCH} + SPEEX_VERSION="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" + SPEEX_EXTRA_VERSION="" + + $<$: + _USE_SSE2 + _USE_MATH_DEFINES + alloca=_alloca + inline=__inline + EXPORT= + > + + $<$>: + HAVE_ALLOCA_H + HAVE_GETOPT_H + USE_ALLOCA + VAR_ARRAYS + EXPORT=__attribute__\(\(visibility\(\"default\"\)\)\) + > + + $<$:VORBIS_PSYCHO> + $,USE_KISS_FFT,USE_SMALLFT> +) + #------------------------------------------------------------------------------- # Compile Options #------------------------------------------------------------------------------- target_compile_options("${TARGET_NAME}" PRIVATE - $,/W0,-w> + -UARM4_ASM + -UARM5E_ASM + -UBFIN_ASM + -UDISABLE_FLOAT_API + -UDISABLE_VBR + -UENABLE_VALGRIND + -UFIXED_POINT_DEBUG + + $<$: + -UHAVE_GETOPT_H + -UUSE_ALLOCA + > + + $,/W0,-w> +) + +#------------------------------------------------------------------------------- +# Link Libraries +#------------------------------------------------------------------------------- + +target_link_libraries("${TARGET_NAME}" + PUBLIC + $<$>: + "m" + > ) diff --git a/external/speex/include/speex/speex.h b/external/speex/include/speex/speex.h index cafd0cd..34919e2 100644 --- a/external/speex/include/speex/speex.h +++ b/external/speex/include/speex/speex.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin*/ +/* Copyright (C) 2002-2006 Jean-Marc Valin*/ /** @file speex.h @brief Describes the different modes of the codec @@ -7,18 +7,18 @@ 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 @@ -35,7 +35,12 @@ #ifndef SPEEX_H #define SPEEX_H +/** @defgroup Codec Speex encoder and decoder + * This is the Speex codec itself. + * @{ + */ +#include "speex_types.h" #include "speex_bits.h" #ifdef __cplusplus @@ -56,7 +61,7 @@ extern "C" { /** Set quality value */ #define SPEEX_SET_QUALITY 4 /** Get current quality setting */ -#define SPEEX_GET_QUALITY 5 +/* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */ /** Set sub-mode to use */ #define SPEEX_SET_MODE 6 @@ -93,10 +98,10 @@ extern "C" { /** Get current bit-rate used by the encoder or decoder */ #define SPEEX_GET_BITRATE 19 -/**Define a handler function for in-band Speex request*/ +/** Define a handler function for in-band Speex request*/ #define SPEEX_SET_HANDLER 20 -/**Define a handler function for in-band user-defined request*/ +/** Define a handler function for in-band user-defined request*/ #define SPEEX_SET_USER_HANDLER 22 /** Set sampling rate used in bit-rate computation */ @@ -126,16 +131,34 @@ extern "C" { /** Get DTX status (1 for on, 0 for off) */ #define SPEEX_GET_DTX 35 +/** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */ +#define SPEEX_SET_SUBMODE_ENCODING 36 +/** Get submode encoding in each frame */ +#define SPEEX_GET_SUBMODE_ENCODING 37 -/* Used internally, not to be used in applications */ -/** Used internally*/ -#define SPEEX_GET_PI_GAIN 100 -/** Used internally*/ -#define SPEEX_GET_EXC 101 -/** Used internally*/ -#define SPEEX_GET_INNOV 102 -/** Used internally*/ -#define SPEEX_GET_DTX_STATUS 103 +/*#define SPEEX_SET_LOOKAHEAD 38*/ +/** Returns the lookahead used by Speex separately for an encoder and a decoder. + * Sum encoder and decoder lookahead values to get the total codec lookahead. */ +#define SPEEX_GET_LOOKAHEAD 39 + +/** Sets tuning for packet-loss concealment (expected loss rate) */ +#define SPEEX_SET_PLC_TUNING 40 +/** Gets tuning for PLC */ +#define SPEEX_GET_PLC_TUNING 41 + +/** Sets the max bit-rate allowed in VBR mode */ +#define SPEEX_SET_VBR_MAX_BITRATE 42 +/** Gets the max bit-rate allowed in VBR mode */ +#define SPEEX_GET_VBR_MAX_BITRATE 43 + +/** Turn on/off input/output high-pass filtering */ +#define SPEEX_SET_HIGHPASS 44 +/** Get status of input/output high-pass filtering */ +#define SPEEX_GET_HIGHPASS 45 + +/** Get "activity level" of the last decoded frame, i.e. + how much damage we cause if we remove the frame */ +#define SPEEX_GET_ACTIVITY 47 /* Preserving compatibility:*/ @@ -145,6 +168,8 @@ extern "C" { #define SPEEX_GET_PF 1 + + /* Values allowed for mode queries */ /** Query the frame size of a mode */ #define SPEEX_MODE_FRAME_SIZE 0 @@ -153,52 +178,84 @@ extern "C" { #define SPEEX_SUBMODE_BITS_PER_FRAME 1 + +/** Get major Speex version */ +#define SPEEX_LIB_GET_MAJOR_VERSION 1 +/** Get minor Speex version */ +#define SPEEX_LIB_GET_MINOR_VERSION 3 +/** Get micro Speex version */ +#define SPEEX_LIB_GET_MICRO_VERSION 5 +/** Get extra Speex version */ +#define SPEEX_LIB_GET_EXTRA_VERSION 7 +/** Get Speex version string */ +#define SPEEX_LIB_GET_VERSION_STRING 9 + +/*#define SPEEX_LIB_SET_ALLOC_FUNC 10 +#define SPEEX_LIB_GET_ALLOC_FUNC 11 +#define SPEEX_LIB_SET_FREE_FUNC 12 +#define SPEEX_LIB_GET_FREE_FUNC 13 + +#define SPEEX_LIB_SET_WARNING_FUNC 14 +#define SPEEX_LIB_GET_WARNING_FUNC 15 +#define SPEEX_LIB_SET_ERROR_FUNC 16 +#define SPEEX_LIB_GET_ERROR_FUNC 17 +*/ + /** Number of defined modes in Speex */ #define SPEEX_NB_MODES 3 +/** modeID for the defined narrowband mode */ +#define SPEEX_MODEID_NB 0 + +/** modeID for the defined wideband mode */ +#define SPEEX_MODEID_WB 1 + +/** modeID for the defined ultra-wideband mode */ +#define SPEEX_MODEID_UWB 2 + struct SpeexMode; /* Prototypes for mode function pointers */ /** Encoder state initialization function */ -typedef void *(*encoder_init_func)(struct SpeexMode *mode); +typedef void *(*encoder_init_func)(const struct SpeexMode *mode); /** Encoder state destruction function */ typedef void (*encoder_destroy_func)(void *st); /** Main encoding function */ -typedef int (*encode_func)(void *state, float *in, SpeexBits *bits); +typedef int (*encode_func)(void *state, void *in, SpeexBits *bits); /** Function for controlling the encoder options */ typedef int (*encoder_ctl_func)(void *state, int request, void *ptr); /** Decoder state initialization function */ -typedef void *(*decoder_init_func)(struct SpeexMode *mode); +typedef void *(*decoder_init_func)(const struct SpeexMode *mode); /** Decoder state destruction function */ typedef void (*decoder_destroy_func)(void *st); /** Main decoding function */ -typedef int (*decode_func)(void *state, SpeexBits *bits, float *out); +typedef int (*decode_func)(void *state, SpeexBits *bits, void *out); /** Function for controlling the decoder options */ typedef int (*decoder_ctl_func)(void *state, int request, void *ptr); /** Query function for a mode */ -typedef int (*mode_query_func)(void *mode, int request, void *ptr); +typedef int (*mode_query_func)(const void *mode, int request, void *ptr); -/** Struct defining a Speex mode */ +/** Struct defining a Speex mode */ typedef struct SpeexMode { /** Pointer to the low-level mode data */ - void *mode; + const void *mode; /** Pointer to the mode query function */ mode_query_func query; - + /** The name of the mode (you should not rely on this to identify the mode)*/ - char *modeName; + const char *modeName; /**ID of the mode*/ int modeID; @@ -234,47 +291,59 @@ typedef struct SpeexMode { } SpeexMode; /** - * Returns a handle to a newly created Speex encoder state structure. For now, - * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes - * may be added. Note that for now if you have more than one channels to + * Returns a handle to a newly created Speex encoder state structure. For now, + * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes + * may be added. Note that for now if you have more than one channels to * encode, you need one state per channel. * - * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) - * @return A newly created encoder + * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) + * @return A newly created encoder state or NULL if state allocation fails */ -void *speex_encoder_init(SpeexMode *mode); +void *speex_encoder_init(const SpeexMode *mode); -/** Frees all resources associated to an existing Speex encoder state. +/** Frees all resources associated to an existing Speex encoder state. * @param state Encoder state to be destroyed */ void speex_encoder_destroy(void *state); /** Uses an existing encoder state to encode one frame of speech pointed to by "in". The encoded bit-stream is saved in "bits". @param state Encoder state - @param in Frame that will be encoded with a +-2^16 range + @param in Frame that will be encoded with a +-2^15 range. This data MAY be + overwritten by the encoder and should be considered uninitialised + after the call. @param bits Bit-stream where the data will be written + @return 0 if frame needs not be transmitted (DTX only), 1 otherwise */ int speex_encode(void *state, float *in, SpeexBits *bits); +/** Uses an existing encoder state to encode one frame of speech pointed to by + "in". The encoded bit-stream is saved in "bits". + @param state Encoder state + @param in Frame that will be encoded with a +-2^15 range + @param bits Bit-stream where the data will be written + @return 0 if frame needs not be transmitted (DTX only), 1 otherwise + */ +int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits); + /** Used like the ioctl function to control the encoder parameters * * @param state Encoder state * @param request ioctl-type request (one of the SPEEX_* macros) * @param ptr Data exchanged to-from function - * @return 0 if frame needs not be transmitted (DTX only), 1 otherwise + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter */ int speex_encoder_ctl(void *state, int request, void *ptr); -/** Returns a handle to a newly created decoder state structure. For now, +/** Returns a handle to a newly created decoder state structure. For now, * the mode argument can be &nb_mode or &wb_mode . In the future, more modes * may be added. Note that for now if you have more than one channels to * decode, you need one state per channel. * * @param mode Speex mode (one of speex_nb_mode or speex_wb_mode) - * @return A newly created decoder state - */ -void *speex_decoder_init(SpeexMode *mode); + * @return A newly created decoder state or NULL if state allocation fails + */ +void *speex_decoder_init(const SpeexMode *mode); /** Frees all resources associated to an existing decoder state. * @@ -288,16 +357,26 @@ void speex_decoder_destroy(void *state); * @param state Decoder state * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) * @param out Where to write the decoded frame - * @return return status (0 for no error, -1 for end of stream, -2 other) + * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) */ int speex_decode(void *state, SpeexBits *bits, float *out); +/** Uses an existing decoder state to decode one frame of speech from + * bit-stream bits. The output speech is saved written to out. + * + * @param state Decoder state + * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) + * @param out Where to write the decoded frame + * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) + */ +int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out); + /** Used like the ioctl function to control the encoder parameters * * @param state Decoder state * @param request ioctl-type request (one of the SPEEX_* macros) * @param ptr Data exchanged to-from function - * @return 0 for no error, 1 if a terminator is reached, 2 for another error + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter */ int speex_decoder_ctl(void *state, int request, void *ptr); @@ -307,25 +386,40 @@ int speex_decoder_ctl(void *state, int request, void *ptr); * @param mode Speex mode * @param request ioctl-type request (one of the SPEEX_* macros) * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter */ -int speex_mode_query(SpeexMode *mode, int request, void *ptr); +int speex_mode_query(const SpeexMode *mode, int request, void *ptr); +/** Functions for controlling the behavior of libspeex + * @param request ioctl-type request (one of the SPEEX_LIB_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_lib_ctl(int request, void *ptr); /** Default narrowband mode */ -extern SpeexMode speex_nb_mode; +extern const SpeexMode speex_nb_mode; /** Default wideband mode */ -extern SpeexMode speex_wb_mode; +extern const SpeexMode speex_wb_mode; /** Default "ultra-wideband" mode */ -extern SpeexMode speex_uwb_mode; +extern const SpeexMode speex_uwb_mode; /** List of all modes available */ -extern SpeexMode *speex_mode_list[SPEEX_NB_MODES]; +extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES]; + +/** Obtain one of the modes available */ +const SpeexMode * speex_lib_get_mode (int mode); + +#ifndef _WIN32 +/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */ +#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode)) +#endif #ifdef __cplusplus } #endif - +/** @}*/ #endif diff --git a/external/speex/include/speex/speex_bits.h b/external/speex/include/speex/speex_bits.h index b41fdad..f98b826 100644 --- a/external/speex/include/speex/speex_bits.h +++ b/external/speex/include/speex/speex_bits.h @@ -7,18 +7,18 @@ 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 @@ -35,21 +35,23 @@ #ifndef BITS_H #define BITS_H +/** @defgroup SpeexBits SpeexBits: Bit-stream manipulations + * This is the structure that holds the bit-stream when encoding or decoding + * with Speex. It allows some manipulations as well. + * @{ + */ #ifdef __cplusplus extern "C" { #endif -/** Maximum size of the bit-stream (for fixed-size allocation) */ -#define MAX_BYTES_PER_FRAME 2000 - /** Bit-packing data structure representing (part of) a bit-stream. */ typedef struct SpeexBits { - char *bytes; /**< "raw" data */ + char *chars; /**< "raw" data */ int nbBits; /**< Total number of bits stored in the stream*/ - int bytePtr; /**< Position of the byte "cursor" */ - int bitPtr; /**< Position of the bit "cursor" within the current byte */ - int owner; /**< Does the struct "own" the "raw" buffer (member "bytes") */ + int charPtr; /**< Position of the byte "cursor" */ + int bitPtr; /**< Position of the bit "cursor" within the current char */ + int owner; /**< Does the struct "own" the "raw" buffer (member "chars") */ int overflow;/**< Set to one if we try to read past the valid data */ int buf_size;/**< Allocated size for buffer */ int reserved1; /**< Reserved for future use */ @@ -62,6 +64,9 @@ void speex_bits_init(SpeexBits *bits); /** Initializes SpeexBits struct using a pre-allocated buffer*/ void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size); +/** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */ +void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size); + /** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/ void speex_bits_destroy(SpeexBits *bits); @@ -72,16 +77,23 @@ void speex_bits_reset(SpeexBits *bits); void speex_bits_rewind(SpeexBits *bits); /** Initializes the bit-stream from the data in an area of memory */ -void speex_bits_read_from(SpeexBits *bits, char *bytes, int len); +void speex_bits_read_from(SpeexBits *bits, const char *bytes, int len); /** Append bytes to the bit-stream + * * @param bits Bit-stream to operate on * @param bytes pointer to the bytes what will be appended * @param len Number of bytes of append */ -void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len); +void speex_bits_read_whole_bytes(SpeexBits *bits, const char *bytes, int len); -/** Write the content of a bit-stream to an area of memory */ +/** Write the content of a bit-stream to an area of memory + * + * @param bits Bit-stream to operate on + * @param bytes Memory location where to write the bits + * @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer) + * @return Number of bytes written to the "bytes" buffer +*/ int speex_bits_write(SpeexBits *bits, char *bytes, int max_len); /** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */ @@ -117,17 +129,23 @@ unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits); */ int speex_bits_nbytes(SpeexBits *bits); -/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position */ +/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to look for + * @return Value of the bits peeked, interpreted as unsigned + */ unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits); /** Get the value of the next bit in the stream, without modifying the - * "cursor" position - * + * "cursor" position + * * @param bits Bit-stream to operate on + * @return Value of the bit peeked (one bit only) */ int speex_bits_peek(SpeexBits *bits); -/** Advances the position of the "bit cursor" in the stream +/** Advances the position of the "bit cursor" in the stream * * @param bits Bit-stream to operate on * @param n Number of bits to advance @@ -137,11 +155,12 @@ void speex_bits_advance(SpeexBits *bits, int n); /** Returns the number of bits remaining to be read in a stream * * @param bits Bit-stream to operate on + * @return Number of bits that can still be read from the stream */ int speex_bits_remaining(SpeexBits *bits); -/** Insert a terminator so that the data can be sent as a packet while auto-detecting - * the number of frames in each packet +/** Insert a terminator so that the data can be sent as a packet while auto-detecting + * the number of frames in each packet * * @param bits Bit-stream to operate on */ @@ -151,4 +170,5 @@ void speex_bits_insert_terminator(SpeexBits *bits); } #endif +/* @} */ #endif diff --git a/external/speex/include/speex/speex_callbacks.h b/external/speex/include/speex/speex_callbacks.h index f6334f2..3928c34 100644 --- a/external/speex/include/speex/speex_callbacks.h +++ b/external/speex/include/speex/speex_callbacks.h @@ -7,18 +7,18 @@ 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 @@ -35,6 +35,9 @@ #ifndef SPEEX_CALLBACKS_H #define SPEEX_CALLBACKS_H +/** @defgroup SpeexCallbacks Various definitions for Speex callbacks supported by the decoder. + * @{ + */ #include "speex.h" @@ -110,13 +113,16 @@ int speex_default_user_handler(SpeexBits *bits, void *state, void *data); - +/** Standard handler for low mode request (change low mode, no questions asked) */ int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data); +/** Standard handler for VBR request (Set VBR, no questions asked) */ int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data); +/** Standard handler for enhancer request (Turn enhancer on/off, no questions asked) */ int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data); +/** Standard handler for VBR quality request (Set VBR quality, no questions asked) */ int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data); @@ -124,5 +130,5 @@ int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *da } #endif - +/** @} */ #endif diff --git a/external/speex/include/speex/speex_config_types.h b/external/speex/include/speex/speex_config_types.h new file mode 100644 index 0000000..ca1f5a3 --- /dev/null +++ b/external/speex/include/speex/speex_config_types.h @@ -0,0 +1,12 @@ +#ifndef __SPEEX_TYPES_H__ +#define __SPEEX_TYPES_H__ + +#include + +typedef int16_t spx_int16_t; +typedef uint16_t spx_uint16_t; +typedef int32_t spx_int32_t; +typedef uint32_t spx_uint32_t; + +#endif + diff --git a/external/speex/include/speex/speex_header.h b/external/speex/include/speex/speex_header.h index 8ded911..ffe8c47 100644 --- a/external/speex/include/speex/speex_header.h +++ b/external/speex/include/speex/speex_header.h @@ -7,18 +7,18 @@ 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 @@ -36,6 +36,12 @@ #ifndef SPEEX_HEADER_H #define SPEEX_HEADER_H +/** @defgroup SpeexHeader SpeexHeader: Makes it easy to write/parse an Ogg/Speex header + * This is the Speex header for the Ogg encapsulation. You don't need that if you just use RTP. + * @{ + */ + +#include "speex_types.h" #ifdef __cplusplus extern "C" { @@ -43,30 +49,33 @@ extern "C" { struct SpeexMode; +/** Length of the Speex header identifier */ +#define SPEEX_HEADER_STRING_LENGTH 8 + /** Maximum number of characters for encoding the Speex version number in the header */ #define SPEEX_HEADER_VERSION_LENGTH 20 /** Speex header info for file-based formats */ typedef struct SpeexHeader { - char speex_string[8]; /**< Identifies a Speex bit-stream, always set to "Speex " */ + char speex_string[SPEEX_HEADER_STRING_LENGTH]; /**< Identifies a Speex bit-stream, always set to "Speex " */ char speex_version[SPEEX_HEADER_VERSION_LENGTH]; /**< Speex version */ - int speex_version_id; /**< Version for Speex (for checking compatibility) */ - int header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ - int rate; /**< Sampling rate used */ - int mode; /**< Mode used (0 for narrowband, 1 for wideband) */ - int mode_bitstream_version; /**< Version ID of the bit-stream */ - int nb_channels; /**< Number of channels encoded */ - int bitrate; /**< Bit-rate used */ - int frame_size; /**< Size of frames */ - int vbr; /**< 1 for a VBR encoding, 0 otherwise */ - int frames_per_packet; /**< Number of frames stored per Ogg packet */ - int extra_headers; /**< Number of additional headers after the comments */ - int reserved1; /**< Reserved for future use, must be zero */ - int reserved2; /**< Reserved for future use, must be zero */ + spx_int32_t speex_version_id; /**< Version for Speex (for checking compatibility) */ + spx_int32_t header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + spx_int32_t rate; /**< Sampling rate used */ + spx_int32_t mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + spx_int32_t mode_bitstream_version; /**< Version ID of the bit-stream */ + spx_int32_t nb_channels; /**< Number of channels encoded */ + spx_int32_t bitrate; /**< Bit-rate used */ + spx_int32_t frame_size; /**< Size of frames */ + spx_int32_t vbr; /**< 1 for a VBR encoding, 0 otherwise */ + spx_int32_t frames_per_packet; /**< Number of frames stored per Ogg packet */ + spx_int32_t extra_headers; /**< Number of additional headers after the comments */ + spx_int32_t reserved1; /**< Reserved for future use, must be zero */ + spx_int32_t reserved2; /**< Reserved for future use, must be zero */ } SpeexHeader; /** Initializes a SpeexHeader using basic information */ -void speex_init_header(SpeexHeader *header, int rate, int nb_channels, struct SpeexMode *m); +void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const struct SpeexMode *m); /** Creates the header packet from the header itself (mostly involves endianness conversion) */ char *speex_header_to_packet(SpeexHeader *header, int *size); @@ -74,9 +83,12 @@ char *speex_header_to_packet(SpeexHeader *header, int *size); /** Creates a SpeexHeader from a packet */ SpeexHeader *speex_packet_to_header(char *packet, int size); +/** Frees the memory allocated by either speex_header_to_packet() or speex_packet_to_header() */ +void speex_header_free(void *ptr); + #ifdef __cplusplus } #endif - +/** @} */ #endif diff --git a/external/speex/include/speex/speex_stereo.h b/external/speex/include/speex/speex_stereo.h index 3fbeb91..12af2bb 100644 --- a/external/speex/include/speex/speex_stereo.h +++ b/external/speex/include/speex/speex_stereo.h @@ -7,18 +7,18 @@ 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 @@ -34,10 +34,20 @@ #ifndef STEREO_H #define STEREO_H +/** @defgroup SpeexStereoState SpeexStereoState: Handling Speex stereo files + * This describes the Speex intensity stereo encoding/decoding + * @{ + */ +#include "speex_types.h" #include "speex_bits.h" -/** State used for decoding (intensity) stereo information */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** If you access any of these fields directly, I'll personally come and bite you */ typedef struct SpeexStereoState { float balance; /**< Left/right balance info */ float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ @@ -47,16 +57,36 @@ typedef struct SpeexStereoState { float reserved2; /**< Reserved for future use */ } SpeexStereoState; -/** Initialization value for a stereo state */ -#define SPEEX_STEREO_STATE_INIT {1,.5,1,1} +/** Deprecated. Use speex_stereo_state_init() instead. */ +#define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} + +/** Initialise/create a stereo stereo state */ +SpeexStereoState *speex_stereo_state_init(void); + +/** Reset/re-initialise an already allocated stereo state */ +void speex_stereo_state_reset(SpeexStereoState *stereo); + +/** Destroy a stereo stereo state */ +void speex_stereo_state_destroy(SpeexStereoState *stereo); /** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); +/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ +void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits); + /** Transforms a mono frame into a stereo frame using intensity stereo info */ void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo); +/** Transforms a mono frame into a stereo frame using intensity stereo info */ +void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo); + /** Callback handler for intensity stereo info */ int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data); +#ifdef __cplusplus +} +#endif + +/** @} */ #endif diff --git a/external/speex/include/speex/speex_types.h b/external/speex/include/speex/speex_types.h new file mode 100644 index 0000000..bdc6329 --- /dev/null +++ b/external/speex/include/speex/speex_types.h @@ -0,0 +1,126 @@ +/* speex_types.h taken from libogg */ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ + + ********************************************************************/ +/** + @file speex_types.h + @brief Speex types +*/ +#ifndef _SPEEX_TYPES_H +#define _SPEEX_TYPES_H + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t spx_int32_t; + typedef _G_uint32_t spx_uint32_t; + typedef _G_int16_t spx_int16_t; + typedef _G_uint16_t spx_uint16_t; +# elif defined(__MINGW32__) + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; +# elif defined(__MWERKS__) + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; +# else + /* MSVC/Borland */ + typedef __int32 spx_int32_t; + typedef unsigned __int32 spx_uint32_t; + typedef __int16 spx_int16_t; + typedef unsigned __int16 spx_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 spx_int16_t; + typedef UInt16 spx_uint16_t; + typedef SInt32 spx_int32_t; + typedef UInt32 spx_uint32_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short spx_int16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int spx_int32_t; + typedef unsigned spx_uint32_t; + typedef short spx_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef signed int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef long spx_int32_t; + typedef unsigned long spx_uint32_t; + +#elif defined(CONFIG_TI_C6X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#else + +#include "speex_config_types.h" + +#endif + +#endif /* _SPEEX_TYPES_H */ diff --git a/external/speex/src/_kiss_fft_guts.h b/external/speex/src/_kiss_fft_guts.h new file mode 100644 index 0000000..f5f2a5f --- /dev/null +++ b/external/speex/src/_kiss_fft_guts.h @@ -0,0 +1,160 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +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 author nor the names of any 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 COPYRIGHT OWNER 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. +*/ + +#define MIN(a,b) ((a)<(b) ? (a):(b)) +#define MAX(a,b) ((a)>(b) ? (a):(b)) + +/* kiss_fft.h + defines kiss_fft_scalar as either short or a float type + and defines + typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ +#include "kiss_fft.h" +#include "math_approx.h" + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ +#ifdef FIXED_POINT +#include "arch.h" +# define FRACBITS 15 +# define SAMPPROD spx_int32_t +#define SAMP_MAX 32767 + +#define SAMP_MIN -SAMP_MAX + +#if defined(CHECK_OVERFLOW) +# define CHECK_OVERFLOW_OP(a,op,b) \ + if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ + fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } +#endif + + +# define smul(a,b) ( (SAMPPROD)(a)*(b) ) +# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) + +# define S_MUL(a,b) sround( smul(a,b) ) + +# define C_MUL(m,a,b) \ + do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ + (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) + +# define C_MUL4(m,a,b) \ + do{ (m).r = PSHR32( smul((a).r,(b).r) - smul((a).i,(b).i),17 ); \ + (m).i = PSHR32( smul((a).r,(b).i) + smul((a).i,(b).r),17 ); }while(0) + +# define DIVSCALAR(x,k) \ + (x) = sround( smul( x, SAMP_MAX/k ) ) + +# define C_FIXDIV(c,div) \ + do { DIVSCALAR( (c).r , div); \ + DIVSCALAR( (c).i , div); }while (0) + +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r = sround( smul( (c).r , s ) ) ;\ + (c).i = sround( smul( (c).i , s ) ) ; }while(0) + +#else /* not FIXED_POINT*/ + +# define S_MUL(a,b) ( (a)*(b) ) +#define C_MUL(m,a,b) \ + do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ + (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) + +#define C_MUL4(m,a,b) C_MUL(m,a,b) + +# define C_FIXDIV(c,div) /* NOOP */ +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r *= (s);\ + (c).i *= (s); }while(0) +#endif + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) + + +#ifdef FIXED_POINT +# define KISS_FFT_COS(phase) floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase)))) +# define KISS_FFT_SIN(phase) floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase)))) +# define HALF_OF(x) ((x)>>1) +#elif defined(USE_SIMD) +# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) +# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) +# define HALF_OF(x) ((x)*_mm_set1_ps(.5)) +#else +# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) +# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) +# define HALF_OF(x) ((x)*.5) +#endif + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_COS(phase);\ + (x)->i = KISS_FFT_SIN(phase);\ + }while(0) +#define kf_cexp2(x,phase) \ + do{ \ + (x)->r = spx_cos_norm((phase));\ + (x)->i = spx_cos_norm((phase)-32768);\ +}while(0) + + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/external/speex/src/arch.h b/external/speex/src/arch.h new file mode 100644 index 0000000..20f6eaa --- /dev/null +++ b/external/speex/src/arch.h @@ -0,0 +1,236 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file arch.h + @brief Various architecture definitions 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 ARCH_H +#define ARCH_H + +#ifndef SPEEX_VERSION +#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */ +#define SPEEX_MINOR_VERSION 2 /**< Minor Speex version. */ +#define SPEEX_MICRO_VERSION 1 /**< Micro Speex version. */ +#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */ +#define SPEEX_VERSION "speex-1.2.1" /**< Speex version string. */ +#endif + +/* A couple test to catch stupid option combinations */ +#ifdef FIXED_POINT + +#ifdef FLOATING_POINT +#error You cannot compile as floating point and fixed point at the same time +#endif +#ifdef _USE_SSE +#error SSE is only for floating-point +#endif +#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM)) +#error Make up your mind. What CPU do you have? +#endif +#ifdef VORBIS_PSYCHO +#error Vorbis-psy model currently not implemented in fixed-point +#endif + +#else + +#ifndef FLOATING_POINT +#error You now need to define either FIXED_POINT or FLOATING_POINT +#endif +#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM) +#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions? +#endif +#ifdef FIXED_POINT_DEBUG +#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?" +#endif + + +#endif + +#include "speex/speex_types.h" + +#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ +#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ +#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ +#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */ +#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ + +#ifdef FIXED_POINT + +typedef spx_int16_t spx_word16_t; +typedef spx_int32_t spx_word32_t; +typedef spx_word32_t spx_mem_t; +typedef spx_word16_t spx_coef_t; +typedef spx_word16_t spx_lsp_t; +typedef spx_word32_t spx_sig_t; + +#define Q15ONE 32767 + +#define LPC_SCALING 8192 +#define SIG_SCALING 16384 +#define LSP_SCALING 8192. +#define GAMMA_SCALING 32768. +#define GAIN_SCALING 64 +#define GAIN_SCALING_1 0.015625 + +#define LPC_SHIFT 13 +#define LSP_SHIFT 13 +#define SIG_SHIFT 14 +#define GAIN_SHIFT 6 + +#define EPSILON 1 +#define VERY_SMALL 0 +#define VERY_LARGE32 ((spx_word32_t)2147483647) +#define VERY_LARGE16 ((spx_word16_t)32767) +#define Q15_ONE ((spx_word16_t)32767) + + +#ifdef FIXED_DEBUG +#include "fixed_debug.h" +#else + +#include "fixed_generic.h" + +#ifdef ARM5E_ASM +#include "fixed_arm5e.h" +#elif defined (ARM4_ASM) +#include "fixed_arm4.h" +#elif defined (BFIN_ASM) +#include "fixed_bfin.h" +#endif + +#endif + + +#else + +typedef float spx_mem_t; +typedef float spx_coef_t; +typedef float spx_lsp_t; +typedef float spx_sig_t; +typedef float spx_word16_t; +typedef float spx_word32_t; + +#define Q15ONE 1.0f +#define LPC_SCALING 1.f +#define SIG_SCALING 1.f +#define LSP_SCALING 1.f +#define GAMMA_SCALING 1.f +#define GAIN_SCALING 1.f +#define GAIN_SCALING_1 1.f + + +#define EPSILON 1e-15f +#define VERY_SMALL 1e-15f +#define VERY_LARGE32 1e15f +#define VERY_LARGE16 1e15f +#define Q15_ONE ((spx_word16_t)1.f) + +#define QCONST16(x,bits) (x) +#define QCONST32(x,bits) (x) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) (x) +#define EXTEND32(x) (x) +#define SHR16(a,shift) (a) +#define SHL16(a,shift) (a) +#define SHR32(a,shift) (a) +#define SHL32(a,shift) (a) +#define PSHR16(a,shift) (a) +#define PSHR32(a,shift) (a) +#define VSHR32(a,shift) (a) +#define SATURATE16(x,a) (x) +#define SATURATE32(x,a) (x) + +#define PSHR(a,shift) (a) +#define SHR(a,shift) (a) +#define SHL(a,shift) (a) +#define SATURATE(x,a) (x) + +#define ADD16(a,b) ((a)+(b)) +#define SUB16(a,b) ((a)-(b)) +#define ADD32(a,b) ((a)+(b)) +#define SUB32(a,b) ((a)-(b)) +#define MULT16_16_16(a,b) ((a)*(b)) +#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b)) +#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b)) + +#define MULT16_32_Q13(a,b) ((a)*(b)) +#define MULT16_32_Q14(a,b) ((a)*(b)) +#define MULT16_32_Q15(a,b) ((a)*(b)) +#define MULT16_32_P15(a,b) ((a)*(b)) + +#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) + +#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b)) +#define MAC16_16_P13(c,a,b) ((c)+(a)*(b)) +#define MULT16_16_Q11_32(a,b) ((a)*(b)) +#define MULT16_16_Q13(a,b) ((a)*(b)) +#define MULT16_16_Q14(a,b) ((a)*(b)) +#define MULT16_16_Q15(a,b) ((a)*(b)) +#define MULT16_16_P15(a,b) ((a)*(b)) +#define MULT16_16_P13(a,b) ((a)*(b)) +#define MULT16_16_P14(a,b) ((a)*(b)) + +#define DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) +#define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) +#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) +#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) + + +#endif + + +#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + +/* 2 on TI C5x DSP */ +#define BYTES_PER_CHAR 2 +#define BITS_PER_CHAR 16 +#define LOG2_BITS_PER_CHAR 4 + +#else + +#define BYTES_PER_CHAR 1 +#define BITS_PER_CHAR 8 +#define LOG2_BITS_PER_CHAR 3 + +#endif + + + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + + +#endif diff --git a/external/speex/src/bfin.h b/external/speex/src/bfin.h new file mode 100644 index 0000000..b934cf2 --- /dev/null +++ b/external/speex/src/bfin.h @@ -0,0 +1,15 @@ +/* Common Blackfin assembly defines + * + * Copyright (C) 2005-2009 Analog Devices + */ + +#if __GNUC__ <= 3 +/* GCC-3.4 and older did not use hardware loops and thus did not have + * register constraints for declaring clobbers. + */ +# define BFIN_HWLOOP0_REGS +# define BFIN_HWLOOP1_REGS +#else +# define BFIN_HWLOOP0_REGS , "LB0", "LT0", "LC0" +# define BFIN_HWLOOP1_REGS , "LB1", "LT1", "LC1" +#endif diff --git a/external/speex/src/bits.c b/external/speex/src/bits.c index 68285e0..4f457af 100644 --- a/external/speex/src/bits.c +++ b/external/speex/src/bits.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: speex_bits.c Handles bit packing/unpacking @@ -6,18 +6,18 @@ 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 @@ -32,184 +32,215 @@ */ -#include "speex_bits.h" -#include "misc.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -void speex_bits_init(SpeexBits *bits) +#include "speex/speex_bits.h" +#include "arch.h" +#include "os_support.h" + +/* Maximum size of the bit-stream (for fixed-size allocation) */ +#ifndef MAX_CHARS_PER_FRAME +#define MAX_CHARS_PER_FRAME (2000/BYTES_PER_CHAR) +#endif + +EXPORT void speex_bits_init(SpeexBits *bits) { - int i; - bits->bytes = (char*)speex_alloc(MAX_BYTES_PER_FRAME); - bits->buf_size = MAX_BYTES_PER_FRAME; + bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME); + if (!bits->chars) + return; + + bits->buf_size = MAX_CHARS_PER_FRAME; - for (i=0;ibuf_size;i++) - bits->bytes[i]=0; - bits->nbBits=0; - bits->bytePtr=0; - bits->bitPtr=0; bits->owner=1; - bits->overflow=0; + + speex_bits_reset(bits); } -void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) +EXPORT void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) { - int i; - bits->bytes = (char*)buff; + bits->chars = (char*)buff; bits->buf_size = buf_size; - for (i=0;ibytes[i]=0; - bits->nbBits=0; - bits->bytePtr=0; - bits->bitPtr=0; bits->owner=0; - bits->overflow=0; + + speex_bits_reset(bits); } -void speex_bits_destroy(SpeexBits *bits) +EXPORT void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size) +{ + bits->chars = (char*)buff; + bits->buf_size = buf_size; + + bits->owner=0; + + bits->nbBits=buf_size<charPtr=0; + bits->bitPtr=0; + bits->overflow=0; + +} + +EXPORT void speex_bits_destroy(SpeexBits *bits) { if (bits->owner) - speex_free(bits->bytes); + speex_free(bits->chars); /* Will do something once the allocation is dynamic */ } -void speex_bits_reset(SpeexBits *bits) +EXPORT void speex_bits_reset(SpeexBits *bits) { - int i; - for (i=0;ibuf_size;i++) - bits->bytes[i]=0; + /* We only need to clear the first byte now */ + bits->chars[0]=0; bits->nbBits=0; - bits->bytePtr=0; + bits->charPtr=0; bits->bitPtr=0; bits->overflow=0; } -void speex_bits_rewind(SpeexBits *bits) +EXPORT void speex_bits_rewind(SpeexBits *bits) { - bits->bytePtr=0; + bits->charPtr=0; bits->bitPtr=0; bits->overflow=0; } -void speex_bits_read_from(SpeexBits *bits, char *bytes, int len) +EXPORT void speex_bits_read_from(SpeexBits *bits, const char *chars, int len) { int i; - if (len > bits->buf_size) + int nchars = len / BYTES_PER_CHAR; + if (nchars > bits->buf_size) { - speex_warning_int("Packet if larger than allocated buffer: ", len); + speex_notify("Packet is larger than allocated buffer"); if (bits->owner) { - char *tmp = (char*)speex_realloc(bits->bytes, len); + char *tmp = (char*)speex_realloc(bits->chars, nchars); if (tmp) { - bits->buf_size=len; - bits->bytes=tmp; + bits->buf_size=nchars; + bits->chars=tmp; } else { - len=bits->buf_size; + nchars=bits->buf_size; speex_warning("Could not resize input buffer: truncating input"); } } else { - speex_warning("Do not own input buffer: truncating input"); - len=bits->buf_size; + speex_warning("Do not own input buffer: truncating oversize input"); + nchars=bits->buf_size; } } - for (i=0;ibytes[i]=bytes[i]; - bits->nbBits=len<<3; - bits->bytePtr=0; +#if (BYTES_PER_CHAR==2) +/* Swap bytes to proper endian order (could be done externally) */ +#define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8)) +#else +#define HTOLS(A) (A) +#endif + for (i=0;ichars[i]=HTOLS(chars[i]); + + bits->nbBits=nchars<charPtr=0; bits->bitPtr=0; bits->overflow=0; } static void speex_bits_flush(SpeexBits *bits) { - int i; - if (bits->bytePtr>0) - { - for (i=bits->bytePtr;i<((bits->nbBits+7)>>3);i++) - bits->bytes[i-bits->bytePtr]=bits->bytes[i]; - } - bits->nbBits -= bits->bytePtr<<3; - bits->bytePtr=0; + int nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); + if (bits->charPtr>0) + SPEEX_MOVE(bits->chars, &bits->chars[bits->charPtr], nchars-bits->charPtr); + bits->nbBits -= bits->charPtr<charPtr=0; } -void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len) +EXPORT void speex_bits_read_whole_bytes(SpeexBits *bits, const char *chars, int nbytes) { int i,pos; + int nchars = nbytes/BYTES_PER_CHAR; - if ((bits->nbBits>>3)+len+1 > bits->buf_size) + if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size) { - speex_warning_int("Packet if larger than allocated buffer: ", len); + /* Packet is larger than allocated buffer */ if (bits->owner) { - char *tmp = (char*)speex_realloc(bits->bytes, (bits->nbBits>>3)+len+1); + char *tmp = (char*)speex_realloc(bits->chars, (bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1); if (tmp) { - bits->buf_size=(bits->nbBits>>3)+len+1; - bits->bytes=tmp; + bits->buf_size=(bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1; + bits->chars=tmp; } else { - len=bits->buf_size-(bits->nbBits>>3)-1; - speex_warning("Could not resize input buffer: truncating input"); + nchars=bits->buf_size-(bits->nbBits>>LOG2_BITS_PER_CHAR)-1; + speex_warning("Could not resize input buffer: truncating oversize input"); } } else { - speex_warning("Do not own input buffer: truncating input"); - len=bits->buf_size; + speex_warning("Do not own input buffer: truncating oversize input"); + nchars=bits->buf_size; } } speex_bits_flush(bits); - pos=bits->nbBits>>3; - for (i=0;ibytes[pos+i]=bytes[i]; - bits->nbBits+=len<<3; + pos=bits->nbBits>>LOG2_BITS_PER_CHAR; + for (i=0;ichars[pos+i]=HTOLS(chars[i]); + bits->nbBits+=nchars< ((bits->nbBits+7)>>3)) - max_len = ((bits->nbBits+7)>>3); - for (i=0;ibytes[i]; - return max_len; + int max_nchars = max_nbytes/BYTES_PER_CHAR; + int charPtr, bitPtr, nbBits; + + /* Insert terminator, but save the data so we can put it back after */ + bitPtr=bits->bitPtr; + charPtr=bits->charPtr; + nbBits=bits->nbBits; + speex_bits_insert_terminator(bits); + bits->bitPtr=bitPtr; + bits->charPtr=charPtr; + bits->nbBits=nbBits; + + if (max_nchars > ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)) + max_nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); + + for (i=0;ichars[i]); + return max_nchars*BYTES_PER_CHAR; } -int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len) +EXPORT int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes) { + int max_nchars = max_nbytes/BYTES_PER_CHAR; int i; - if (max_len > ((bits->nbBits)>>3)) - max_len = ((bits->nbBits)>>3); - for (i=0;ibytes[i]; - + if (max_nchars > ((bits->nbBits)>>LOG2_BITS_PER_CHAR)) + max_nchars = ((bits->nbBits)>>LOG2_BITS_PER_CHAR); + for (i=0;ichars[i]); + if (bits->bitPtr>0) - bits->bytes[0]=bits->bytes[max_len]; + bits->chars[0]=bits->chars[max_nchars]; else - bits->bytes[0]=0; - for (i=1;i<((bits->nbBits)>>3)+1;i++) - bits->bytes[i]=0; - bits->bytePtr=0; - bits->nbBits &= 7; - return max_len; + bits->chars[0]=0; + bits->charPtr=0; + bits->nbBits &= (BITS_PER_CHAR-1); + return max_nchars*BYTES_PER_CHAR; } - -void speex_bits_pack(SpeexBits *bits, int data, int nbBits) +EXPORT void speex_bits_pack(SpeexBits *bits, int data, int nbBits) { - int i; unsigned int d=data; - if (bits->bytePtr+((nbBits+bits->bitPtr)>>3) >= bits->buf_size) + if (bits->charPtr+((nbBits+bits->bitPtr)>>LOG2_BITS_PER_CHAR) >= bits->buf_size) { - speex_warning("Buffer too small to pack bits"); + speex_notify("Buffer too small to pack bits"); if (bits->owner) { - char *tmp = (char*)speex_realloc(bits->bytes, ((bits->buf_size+5)*3)>>1); + int new_nchars = ((bits->buf_size+5)*3)>>1; + char *tmp = (char*)speex_realloc(bits->chars, new_nchars); if (tmp) { - for (i=bits->buf_size;i<(((bits->buf_size+5)*3)>>1);i++) - tmp[i]=0; - bits->buf_size=((bits->buf_size+5)*3)>>1; - bits->bytes=tmp; + bits->buf_size=new_nchars; + bits->chars=tmp; } else { speex_warning("Could not resize input buffer: not packing"); return; @@ -224,129 +255,118 @@ void speex_bits_pack(SpeexBits *bits, int data, int nbBits) { int bit; bit = (d>>(nbBits-1))&1; - bits->bytes[bits->bytePtr] |= bit<<(7-bits->bitPtr); + bits->chars[bits->charPtr] |= bit<<(BITS_PER_CHAR-1-bits->bitPtr); bits->bitPtr++; - if (bits->bitPtr==8) + if (bits->bitPtr==BITS_PER_CHAR) { bits->bitPtr=0; - bits->bytePtr++; + bits->charPtr++; + bits->chars[bits->charPtr] = 0; } bits->nbBits++; nbBits--; } } -int speex_bits_unpack_signed(SpeexBits *bits, int nbBits) +EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits) { unsigned int d=speex_bits_unpack_unsigned(bits,nbBits); /* If number is negative */ if (d>>(nbBits-1)) { - d |= (-1)<bytePtr<<3)+bits->bitPtr+nbBits>bits->nbBits) + if ((bits->charPtr<bitPtr+nbBits>bits->nbBits) bits->overflow=1; if (bits->overflow) return 0; while(nbBits) { d<<=1; - d |= (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1; + d |= (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1; bits->bitPtr++; - if (bits->bitPtr==8) + if (bits->bitPtr==BITS_PER_CHAR) { bits->bitPtr=0; - bits->bytePtr++; + bits->charPtr++; } nbBits--; } return d; } -unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) +EXPORT unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) { unsigned int d=0; - int bitPtr, bytePtr; - char *bytes; + int bitPtr, charPtr; + char *chars; - if ((bits->bytePtr<<3)+bits->bitPtr+nbBits>bits->nbBits) + if ((bits->charPtr<bitPtr+nbBits>bits->nbBits) bits->overflow=1; if (bits->overflow) return 0; bitPtr=bits->bitPtr; - bytePtr=bits->bytePtr; - bytes = bits->bytes; + charPtr=bits->charPtr; + chars = bits->chars; while(nbBits) { d<<=1; - d |= (bytes[bytePtr]>>(7-bitPtr))&1; + d |= (chars[charPtr]>>(BITS_PER_CHAR-1 - bitPtr))&1; bitPtr++; - if (bitPtr==8) + if (bitPtr==BITS_PER_CHAR) { bitPtr=0; - bytePtr++; + charPtr++; } nbBits--; } return d; } -int speex_bits_peek(SpeexBits *bits) +EXPORT int speex_bits_peek(SpeexBits *bits) { - if ((bits->bytePtr<<3)+bits->bitPtr+1>bits->nbBits) + if ((bits->charPtr<bitPtr+1>bits->nbBits) bits->overflow=1; if (bits->overflow) return 0; - return (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1; + return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1; } -void speex_bits_advance(SpeexBits *bits, int n) +EXPORT void speex_bits_advance(SpeexBits *bits, int n) { - int nbytes, nbits; - - if ((bits->bytePtr<<3)+bits->bitPtr+n>bits->nbBits) + if (((bits->charPtr<bitPtr+n>bits->nbBits) || bits->overflow){ bits->overflow=1; - if (bits->overflow) return; - - nbytes = n >> 3; - nbits = n & 7; - - bits->bytePtr += nbytes; - bits->bitPtr += nbits; - - if (bits->bitPtr>7) - { - bits->bitPtr-=8; - bits->bytePtr++; - } + } + bits->charPtr += (bits->bitPtr+n) >> LOG2_BITS_PER_CHAR; /* divide by BITS_PER_CHAR */ + bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */ } -int speex_bits_remaining(SpeexBits *bits) +EXPORT int speex_bits_remaining(SpeexBits *bits) { if (bits->overflow) return -1; else - return bits->nbBits-((bits->bytePtr<<3)+bits->bitPtr); + return bits->nbBits-((bits->charPtr<bitPtr); } -int speex_bits_nbytes(SpeexBits *bits) +EXPORT int speex_bits_nbytes(SpeexBits *bits) { - return ((bits->nbBits+7)>>3); + return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); } -void speex_bits_insert_terminator(SpeexBits *bits) +EXPORT void speex_bits_insert_terminator(SpeexBits *bits) { - if (bits->bitPtr<7) + if (bits->bitPtr) speex_bits_pack(bits, 0, 1); - while (bits->bitPtr<7) + while (bits->bitPtr) speex_bits_pack(bits, 1, 1); } diff --git a/external/speex/src/cb_search.c b/external/speex/src/cb_search.c index 785bb49..9271a57 100644 --- a/external/speex/src/cb_search.c +++ b/external/speex/src/cb_search.c @@ -1,21 +1,21 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002-2006 Jean-Marc Valin File: cb_search.c 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 @@ -29,235 +29,433 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "cb_search.h" #include "filters.h" #include "stack_alloc.h" #include "vq.h" -#include "misc.h" +#include "arch.h" +#include "math_approx.h" +#include "os_support.h" -void split_cb_search_shape_sign( -float target[], /* target vector */ -float ak[], /* LPCs for this subframe */ -float awk1[], /* Weighted LPCs for this subframe */ -float awk2[], /* Weighted LPCs for this subframe */ -void *par, /* Codebook/search parameters*/ +#ifdef _USE_SSE +#include "cb_search_sse.h" +#elif defined(ARM4_ASM) || defined(ARM5E_ASM) +#include "cb_search_arm4.h" +#elif defined(BFIN_ASM) +#include "cb_search_bfin.h" +#endif + +#ifndef DISABLE_ENCODER + +#ifndef OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK +static void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack) +{ + int i, j, k; + VARDECL(spx_word16_t *shape); + ALLOC(shape, subvect_size, spx_word16_t); + for (i=0;i10) - N=10; - - ot=PUSH(stack, N, float*); - nt=PUSH(stack, N, float*); - oind=PUSH(stack, N, int*); - nind=PUSH(stack, N, int*); - - params = (split_cb_params *) par; + params = (const split_cb_params *) par; subvect_size = params->subvect_size; nb_subvect = params->nb_subvect; shape_cb_size = 1<shape_bits; shape_cb = params->shape_cb; have_sign = params->have_sign; - resp = PUSH(stack, shape_cb_size*subvect_size, float); - t = PUSH(stack, nsf, float); - e = PUSH(stack, nsf, float); - r2 = PUSH(stack, nsf, float); - E = PUSH(stack, shape_cb_size, float); - ind = PUSH(stack, nb_subvect, int); + ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t); +#ifdef _USE_SSE + ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128); + ALLOC(E, shape_cb_size>>2, __m128); +#else + resp2 = resp; + ALLOC(E, shape_cb_size, spx_word32_t); +#endif + ALLOC(t, nsf, spx_word16_t); + ALLOC(e, nsf, spx_sig_t); - tmp = PUSH(stack, 2*N*nsf, float); - for (i=0;ishape_bits+have_sign); + + { + int rind; + spx_word16_t *res; + spx_word16_t sign=1; + rind = best_index; + if (rind>=shape_cb_size) + { + sign=-1; + rind-=shape_cb_size; + } + res = resp+rind*subvect_size; + if (sign>0) + for (m=0;m=shape_cb_size) + { + sign=-1; + rind-=shape_cb_size; + } + + q=subvect_size-m; +#ifdef FIXED_POINT + g=sign*shape_cb[rind*subvect_size+m]; +#else + g=sign*0.03125*shape_cb[rind*subvect_size+m]; +#endif + target_update(t+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1)); + } } - best_index = PUSH(stack, N, int); - best_dist = PUSH(stack, N, float); - ndist = PUSH(stack, N, float); - odist = PUSH(stack, N, float); - - itmp = PUSH(stack, 2*N*nb_subvect, int); + /* Update excitation */ + /* FIXME: We could update the excitation directly above */ + for (j=0;j10) + N=10; + /* Complexity isn't as important for the codebooks as it is for the pitch */ + N=(2*N)/3; + if (N<1) + N=1; + if (N==1) + { + split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,update_target); + return; + } + ALLOC(ot2, N, spx_word16_t*); + ALLOC(nt2, N, spx_word16_t*); + ALLOC(oind, N, int*); + ALLOC(nind, N, int*); + + params = (const split_cb_params *) par; + subvect_size = params->subvect_size; + nb_subvect = params->nb_subvect; + shape_cb_size = 1<shape_bits; + shape_cb = params->shape_cb; + have_sign = params->have_sign; + ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t); +#ifdef _USE_SSE + ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128); + ALLOC(E, shape_cb_size>>2, __m128); +#else + resp2 = resp; + ALLOC(E, shape_cb_size, spx_word32_t); +#endif + ALLOC(t, nsf, spx_word16_t); + ALLOC(e, nsf, spx_sig_t); + ALLOC(ind, nb_subvect, int); + + ALLOC(tmp, 2*N*nsf, spx_word16_t); for (i=0;i=shape_cb_size) - { - sign=-1; - rind-=shape_cb_size; - } - res = resp+rind*subvect_size; - if (sign>0) - for (m=0;m=shape_cb_size) - { - sign=-1; - rind-=shape_cb_size; - } - - g=sign*0.03125*shape_cb[rind*subvect_size+m]; - q=subvect_size-m; - for (n=subvect_size*(i+1);nm;n--) { - for (q=(i+1)*subvect_size;q=shape_cb_size) + { + sign=-1; + rind-=shape_cb_size; + } + + q=subvect_size-m; +#ifdef FIXED_POINT + g=sign*shape_cb[rind*subvect_size+m]; +#else + g=sign*0.03125*shape_cb[rind*subvect_size+m]; +#endif + target_update(nt[j]+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1)); + } + + for (q=0;qshape_bits+have_sign); } - + /* Put everything back together */ for (i=0;i=shape_cb_size) { sign=-1; rind-=shape_cb_size; } - +#ifdef FIXED_POINT + if (sign==1) + { + for (j=0;jsubvect_size; nb_subvect = params->nb_subvect; - shape_cb_size = 1<shape_bits; + shape_cb = params->shape_cb; have_sign = params->have_sign; - ind = PUSH(stack, nb_subvect, int); - signs = PUSH(stack, nb_subvect, int); + ALLOC(ind, nb_subvect, int); + ALLOC(signs, nb_subvect, int); /* Decode codewords and gains */ for (i=0;i>>= 13;\n\t" + "A1 += R0.L*R0.L (IS);\n\t" + "W[P3++] = R0;\n\t" + "P0 += 1;\n\t" + "P2 += 2;\n\t" + "LOOP_END outer%=;\n\t" + "P4 = %4;\n\t" + "R1 = A1;\n\t" + "[P4] = R1;\n\t" + : + : "m" (subvect_size), "m" (shape_cb), "m" (r), "m" (resp), "m" (E) + : "A0", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "I0", "I1", "L0", + "L1", "A0", "A1", "memory", "ASTAT" BFIN_HWLOOP0_REGS BFIN_HWLOOP1_REGS + ); + shape_cb += subvect_size; + resp += subvect_size; + E++; + } +} + +#define OVERRIDE_TARGET_UPDATE +static inline void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len) +{ + if (!len) + return; + __asm__ __volatile__ + ( + "I0 = %0;\n\t" + "I1 = %1;\n\t" + "L0 = 0;\n\t" + "L1 = 0;\n\t" + "R2 = 4096;\n\t" + "LOOP tupdate%= LC0 = %3;\n\t" + "LOOP_BEGIN tupdate%=;\n\t" + "R0.L = W[I0] || R1.L = W[I1++];\n\t" + "R1 = (A1 = R1.L*%2.L) (IS);\n\t" + "R1 = R1 + R2;\n\t" + "R1 >>>= 13;\n\t" + "R0.L = R0.L - R1.L;\n\t" + "W[I0++] = R0.L;\n\t" + "LOOP_END tupdate%=;\n\t" + : + : "a" (t), "a" (r), "d" (g), "a" (len) + : "R0", "R1", "R2", "A1", "I0", "I1", "L0", "L1", "ASTAT" BFIN_HWLOOP0_REGS + ); +} diff --git a/external/speex/src/cb_search_sse.h b/external/speex/src/cb_search_sse.h new file mode 100644 index 0000000..286326a --- /dev/null +++ b/external/speex/src/cb_search_sse.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2004 Jean-Marc Valin */ +/** + @file cb_search_sse.h + @brief Fixed codebook 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 + +static inline void _spx_mm_getr_ps (__m128 U, float *__Z, float *__Y, float *__X, float *__W) +{ + union { + float __a[4]; + __m128 __v; + } __u; + + __u.__v = U; + + *__Z = __u.__a[0]; + *__Y = __u.__a[1]; + *__X = __u.__a[2]; + *__W = __u.__a[3]; + +} + +#define OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK +static void compute_weighted_codebook(const signed char *shape_cb, const spx_sig_t *_r, float *resp, __m128 *resp2, __m128 *E, int shape_cb_size, int subvect_size, char *stack) +{ + int i, j, k; + __m128 resj, EE; + VARDECL(__m128 *r); + VARDECL(__m128 *shape); + ALLOC(r, subvect_size, __m128); + ALLOC(shape, subvect_size, __m128); + for(j=0;j>2] = EE; + } +} diff --git a/external/speex/src/exc_10_16_table.c b/external/speex/src/exc_10_16_table.c index 322ef38..f75ba30 100644 --- a/external/speex/src/exc_10_16_table.c +++ b/external/speex/src/exc_10_16_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: exc_10_16_table.c Codebook for excitation in narrowband CELP mode (3200 bps) 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 @@ -31,7 +31,7 @@ */ -signed char exc_10_16_table[160] = { +const signed char exc_10_16_table[160] = { 22,39,14,44,11,35,-2,23,-4,6, 46,-28,13,-27,-23,12,4,20,-5,9, 37,-18,-23,23,0,9,-6,-20,4,-1, diff --git a/external/speex/src/exc_10_32_table.c b/external/speex/src/exc_10_32_table.c index 75a8cb0..89425f0 100644 --- a/external/speex/src/exc_10_32_table.c +++ b/external/speex/src/exc_10_32_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: exc_10_32_table.c Codebook for excitation in narrowband CELP mode (4000 bps) 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 @@ -31,7 +31,7 @@ */ -signed char exc_10_32_table[320] = { +const signed char exc_10_32_table[320] = { 7,17,17,27,25,22,12,4,-3,0, 28,-36,39,-24,-15,3,-9,15,-5,10, 31,-28,11,31,-21,9,-11,-11,-2,-7, diff --git a/external/speex/src/exc_20_32_table.c b/external/speex/src/exc_20_32_table.c index 76b0c94..f7b3032 100644 --- a/external/speex/src/exc_20_32_table.c +++ b/external/speex/src/exc_20_32_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: exc_20_32_table.c Codebook for excitation in narrowband CELP mode (2000 bps) 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 @@ -31,7 +31,7 @@ */ -signed char exc_20_32_table[640] = { +const signed char exc_20_32_table[640] = { 12,32,25,46,36,33,9,14,-3,6,1,-8,0,-10,-5,-7,-7,-7,-5,-5, 31,-27,24,-32,-4,10,-11,21,-3,19,23,-9,22,24,-10,-1,-10,-13,-7,-11, 42,-33,31,19,-8,0,-10,-16,1,-21,-17,10,-8,14,8,4,11,-2,5,-2, diff --git a/external/speex/src/exc_5_256_table.c b/external/speex/src/exc_5_256_table.c index 1ceb2d4..169b628 100644 --- a/external/speex/src/exc_5_256_table.c +++ b/external/speex/src/exc_5_256_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: exc_5_256_table.c Codebook for excitation in narrowband CELP mode (12800 bps) 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 @@ -31,7 +31,7 @@ */ -signed char exc_5_256_table[1280] = { +const signed char exc_5_256_table[1280] = { -8,-37,5,-43,5, 73,61,39,12,-3, -61,-32,2,42,30, diff --git a/external/speex/src/exc_5_64_table.c b/external/speex/src/exc_5_64_table.c index ec08abf..6d2ae2b 100644 --- a/external/speex/src/exc_5_64_table.c +++ b/external/speex/src/exc_5_64_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: exc_5_64_table.c Codebook for excitation in narrowband CELP mode (9600 bps) 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 @@ -31,7 +31,7 @@ */ -signed char exc_5_64_table[320]={ +const signed char exc_5_64_table[320]={ 1,5,-15,49,-66, -48,-4,50,-44,7, 37,16,-18,25,-26, diff --git a/external/speex/src/exc_8_128_table.c b/external/speex/src/exc_8_128_table.c index e812a8d..fd05890 100644 --- a/external/speex/src/exc_8_128_table.c +++ b/external/speex/src/exc_8_128_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: exc_8_128_table.c Codebook for excitation in narrowband CELP mode (7000 bps) 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 @@ -31,7 +31,7 @@ */ -signed char exc_8_128_table[1024] = { +const signed char exc_8_128_table[1024] = { -14,9,13,-32,2,-10,31,-10, -8,-8,6,-4,-1,10,-64,23, 6,20,13,6,8,-22,16,34, diff --git a/external/speex/src/fftwrap.c b/external/speex/src/fftwrap.c new file mode 100644 index 0000000..4573479 --- /dev/null +++ b/external/speex/src/fftwrap.c @@ -0,0 +1,448 @@ +/* Copyright (C) 2005-2006 Jean-Marc Valin + File: fftwrap.c + + Wrapper for various FFTs + + 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "arch.h" +#include "os_support.h" + +#define MAX_FFT_SIZE 2048 + +#ifdef FIXED_POINT +static int maximize_range(spx_word16_t *in, spx_word16_t *out, spx_word16_t bound, int len) +{ + int i, shift; + spx_word16_t max_val = 0; + for (i=0;imax_val) + max_val = in[i]; + if (-in[i]>max_val) + max_val = -in[i]; + } + shift=0; + while (max_val <= (bound>>1) && max_val != 0) + { + max_val <<= 1; + shift++; + } + for (i=0;i + +void *spx_fft_init(int size) +{ + struct drft_lookup *table; + table = speex_alloc(sizeof(struct drft_lookup)); + spx_drft_init((struct drft_lookup *)table, size); + return (void*)table; +} + +void spx_fft_destroy(void *table) +{ + spx_drft_clear(table); + speex_free(table); +} + +void spx_fft(void *table, float *in, float *out) +{ + if (in==out) + { + int i; + float scale = 1./((struct drft_lookup *)table)->n; + speex_warning("FFT should not be done in-place"); + for (i=0;i<((struct drft_lookup *)table)->n;i++) + out[i] = scale*in[i]; + } else { + int i; + float scale = 1./((struct drft_lookup *)table)->n; + for (i=0;i<((struct drft_lookup *)table)->n;i++) + out[i] = scale*in[i]; + } + spx_drft_forward((struct drft_lookup *)table, out); +} + +void spx_ifft(void *table, float *in, float *out) +{ + if (in==out) + { + speex_warning("FFT should not be done in-place"); + } else { + int i; + for (i=0;i<((struct drft_lookup *)table)->n;i++) + out[i] = in[i]; + } + spx_drft_backward((struct drft_lookup *)table, out); +} + +#elif defined(USE_INTEL_MKL) +#include + +struct mkl_config { + DFTI_DESCRIPTOR_HANDLE desc; + int N; +}; + +void *spx_fft_init(int size) +{ + struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config)); + table->N = size; + DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size); + DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT); + DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE); + DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size); + DftiCommitDescriptor(table->desc); + return table; +} + +void spx_fft_destroy(void *table) +{ + struct mkl_config *t = (struct mkl_config *) table; + DftiFreeDescriptor(t->desc); + speex_free(table); +} + +void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + struct mkl_config *t = (struct mkl_config *) table; + DftiComputeForward(t->desc, in, out); +} + +void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + struct mkl_config *t = (struct mkl_config *) table; + DftiComputeBackward(t->desc, in, out); +} + +#elif defined(USE_INTEL_IPP) + +#include + +struct ipp_fft_config +{ + IppsDFTSpec_R_32f *dftSpec; + Ipp8u *buffer; +}; + +void *spx_fft_init(int size) +{ + int bufferSize = 0; + int hint; + struct ipp_fft_config *table; + + table = (struct ipp_fft_config *)speex_alloc(sizeof(struct ipp_fft_config)); + + /* there appears to be no performance difference between ippAlgHintFast and + ippAlgHintAccurate when using the with the floating point version + of the fft. */ + hint = ippAlgHintAccurate; + + ippsDFTInitAlloc_R_32f(&table->dftSpec, size, IPP_FFT_DIV_FWD_BY_N, hint); + + ippsDFTGetBufSize_R_32f(table->dftSpec, &bufferSize); + table->buffer = ippsMalloc_8u(bufferSize); + + return table; +} + +void spx_fft_destroy(void *table) +{ + struct ipp_fft_config *t = (struct ipp_fft_config *)table; + ippsFree(t->buffer); + ippsDFTFree_R_32f(t->dftSpec); + speex_free(t); +} + +void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + struct ipp_fft_config *t = (struct ipp_fft_config *)table; + ippsDFTFwd_RToPack_32f(in, out, t->dftSpec, t->buffer); +} + +void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + struct ipp_fft_config *t = (struct ipp_fft_config *)table; + ippsDFTInv_PackToR_32f(in, out, t->dftSpec, t->buffer); +} + +#elif defined(USE_GPL_FFTW3) + +#include + +struct fftw_config { + float *in; + float *out; + fftwf_plan fft; + fftwf_plan ifft; + int N; +}; + +void *spx_fft_init(int size) +{ + struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config)); + table->in = fftwf_malloc(sizeof(float) * (size+2)); + table->out = fftwf_malloc(sizeof(float) * (size+2)); + + table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT); + table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT); + + table->N = size; + return table; +} + +void spx_fft_destroy(void *table) +{ + struct fftw_config *t = (struct fftw_config *) table; + fftwf_destroy_plan(t->fft); + fftwf_destroy_plan(t->ifft); + fftwf_free(t->in); + fftwf_free(t->out); + speex_free(table); +} + + +void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + int i; + struct fftw_config *t = (struct fftw_config *) table; + const int N = t->N; + float *iptr = t->in; + float *optr = t->out; + const float m = 1.0 / N; + for(i=0;ifft); + + out[0] = optr[0]; + for(i=1;iN; + float *iptr = t->in; + float *optr = t->out; + + iptr[0] = in[0]; + iptr[1] = 0.0f; + for(i=1;iifft); + + for(i=0;iforward = kiss_fftr_alloc(size,0,NULL,NULL); + table->backward = kiss_fftr_alloc(size,1,NULL,NULL); + table->N = size; + return table; +} + +void spx_fft_destroy(void *table) +{ + struct kiss_config *t = (struct kiss_config *)table; + kiss_fftr_free(t->forward); + kiss_fftr_free(t->backward); + speex_free(table); +} + +#ifdef FIXED_POINT + +void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + int shift; + struct kiss_config *t = (struct kiss_config *)table; + shift = maximize_range(in, in, 32000, t->N); + kiss_fftr2(t->forward, in, out); + renorm_range(in, in, shift, t->N); + renorm_range(out, out, shift, t->N); +} + +#else + +void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + int i; + float scale; + struct kiss_config *t = (struct kiss_config *)table; + scale = 1./t->N; + kiss_fftr2(t->forward, in, out); + for (i=0;iN;i++) + out[i] *= scale; +} +#endif + +void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) +{ + struct kiss_config *t = (struct kiss_config *)table; + kiss_fftri2(t->backward, in, out); +} + + +#else + +#error No other FFT implemented + +#endif + + +#ifdef FIXED_POINT +/*#include "smallft.h"*/ + + +void spx_fft_float(void *table, float *in, float *out) +{ + int i; +#ifdef USE_SMALLFT + int N = ((struct drft_lookup *)table)->n; +#elif defined(USE_KISS_FFT) + int N = ((struct kiss_config *)table)->N; +#else +#endif +#ifdef VAR_ARRAYS + spx_word16_t _in[N]; + spx_word16_t _out[N]; +#else + spx_word16_t _in[MAX_FFT_SIZE]; + spx_word16_t _out[MAX_FFT_SIZE]; +#endif + for (i=0;iN); + scale = 1./((struct kiss_config *)table)->N; + for (i=0;i<((struct kiss_config *)table)->N;i++) + out[i] = scale*in[i]; + spx_drft_forward(&t, out); + spx_drft_clear(&t); + } +#endif +} + +void spx_ifft_float(void *table, float *in, float *out) +{ + int i; +#ifdef USE_SMALLFT + int N = ((struct drft_lookup *)table)->n; +#elif defined(USE_KISS_FFT) + int N = ((struct kiss_config *)table)->N; +#else +#endif +#ifdef VAR_ARRAYS + spx_word16_t _in[N]; + spx_word16_t _out[N]; +#else + spx_word16_t _in[MAX_FFT_SIZE]; + spx_word16_t _out[MAX_FFT_SIZE]; +#endif + for (i=0;iN); + for (i=0;i<((struct kiss_config *)table)->N;i++) + out[i] = in[i]; + spx_drft_backward(&t, out); + spx_drft_clear(&t); + } +#endif +} + +#else + +void spx_fft_float(void *table, float *in, float *out) +{ + spx_fft(table, in, out); +} +void spx_ifft_float(void *table, float *in, float *out) +{ + spx_ifft(table, in, out); +} + +#endif diff --git a/external/speex/src/misc.h b/external/speex/src/fftwrap.h similarity index 51% rename from external/speex/src/misc.h rename to external/speex/src/fftwrap.h index d128da8..2c07425 100644 --- a/external/speex/src/misc.h +++ b/external/speex/src/fftwrap.h @@ -1,24 +1,23 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ -/** - @file misc.h - @brief Various compatibility routines for Speex -*/ -/* +/* Copyright (C) 2005 Jean-Marc Valin + File: fftwrap.h + + Wrapper for various FFTs + 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 @@ -30,54 +29,30 @@ 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 MISC_H -#define MISC_H +#ifndef FFTWRAP_H +#define FFTWRAP_H -#ifndef VERSION -#define VERSION "speex-1.0" -#endif +#include "arch.h" -/*Disable some warnings on VC++*/ -#ifdef _MSC_VER -#pragma warning(disable : 4244) -#pragma warning(disable : 4305) -#endif +/** Compute tables for an FFT */ +void *spx_fft_init(int size); -#ifndef RELEASE -void print_vec(float *vec, int len, char *name); -#endif +/** Destroy tables for an FFT */ +void spx_fft_destroy(void *table); -unsigned int be_int(unsigned int i); -unsigned int le_int(unsigned int i); +/** Forward (real to half-complex) transform */ +void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out); +/** Backward (half-complex to real) transform */ +void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out); -unsigned short be_short(unsigned short s); -unsigned short le_short(unsigned short s); +/** Forward (real to half-complex) transform of float data */ +void spx_fft_float(void *table, float *in, float *out); -/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free */ -void *speex_alloc (int size); - -/** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, speex_alloc and speex_free */ -void *speex_realloc (void *ptr, int size); - -/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_alloc */ -void speex_free (void *ptr); - -/** Speex wrapper for mem_move */ -void *speex_move (void *dest, void *src, int n); - -void speex_error(char *str); - -void speex_warning(char *str); - -void speex_warning_int(char *str, int val); - -void speex_rand_vec(float std, float *data, int len); - -float speex_rand(float std); - -void _speex_putc(int ch, void *file); +/** Backward (half-complex to real) transform of float data */ +void spx_ifft_float(void *table, float *in, float *out); #endif diff --git a/external/speex/src/filters.c b/external/speex/src/filters.c index 943678d..5e1e45e 100644 --- a/external/speex/src/filters.c +++ b/external/speex/src/filters.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002-2006 Jean-Marc Valin File: filters.c Various analysis/synthesis filters @@ -30,263 +30,807 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "filters.h" #include "stack_alloc.h" +#include "arch.h" +#include "math_approx.h" +#include "ltp.h" #include - -void bw_lpc(float gamma, float *lpc_in, float *lpc_out, int order) -{ - int i; - float tmp=1; - for (i=0;i=min_val && vec[i] <= max_val)) + { + if (vec[i] < min_val) + vec[i] = min_val; + else if (vec[i] > max_val) + vec[i] = max_val; + else /* Has to be NaN */ + vec[i] = 0; + } + } +} -void iir_mem2(float *x, float *den, float *y, int N, int ord, float *mem) +void highpass(const spx_word16_t *x, spx_word16_t *y, int len, int filtID, spx_mem_t *mem) +{ + int i; +#ifdef FIXED_POINT + const spx_word16_t Pcoef[5][3] = {{16384, -31313, 14991}, {16384, -31569, 15249}, {16384, -31677, 15328}, {16384, -32313, 15947}, {16384, -22446, 6537}}; + const spx_word16_t Zcoef[5][3] = {{15672, -31344, 15672}, {15802, -31601, 15802}, {15847, -31694, 15847}, {16162, -32322, 16162}, {14418, -28836, 14418}}; +#else + const spx_word16_t Pcoef[5][3] = {{1.00000f, -1.91120f, 0.91498f}, {1.00000f, -1.92683f, 0.93071f}, {1.00000f, -1.93338f, 0.93553f}, {1.00000f, -1.97226f, 0.97332f}, {1.00000f, -1.37000f, 0.39900f}}; + const spx_word16_t Zcoef[5][3] = {{0.95654f, -1.91309f, 0.95654f}, {0.96446f, -1.92879f, 0.96446f}, {0.96723f, -1.93445f, 0.96723f}, {0.98645f, -1.97277f, 0.98645f}, {0.88000f, -1.76000f, 0.88000f}}; +#endif + const spx_word16_t *den, *num; + if (filtID>4) + filtID=4; + + den = Pcoef[filtID]; num = Zcoef[filtID]; + /*return;*/ + for (i=0;i SHL32(EXTEND32(SIG_SCALING), 8)) + { + spx_word16_t scale_1; + scale = PSHR32(scale, SIG_SHIFT); + scale_1 = EXTRACT16(PDIV32_16(SHL32(EXTEND32(SIG_SCALING),7),scale)); + for (i=0;i SHR32(EXTEND32(SIG_SCALING), 2)) { + spx_word16_t scale_1; + scale = PSHR32(scale, SIG_SHIFT-5); + scale_1 = DIV32_16(SHL32(EXTEND32(SIG_SCALING),3),scale); + for (i=0;i max_val) + max_val = tmp; + } + + sig_shift=0; + while (max_val>16383) + { + sig_shift++; + max_val >>= 1; + } + + for (i=0;i max_val) + max_val = tmp; + } + if (max_val>16383) + { + spx_word32_t sum=0; + for (i=0;i= max_val) + max_val = tmp; + } + + sig_shift=0; + while (max_val>max_scale) + { + sig_shift++; + max_val >>= 1; + } + + for (i=0;i>1; for (i=0;i>1; + N2 = N>>1; + ALLOC(xx1, M2+N2, spx_word16_t); + ALLOC(xx2, M2+N2, spx_word16_t); - for (i = 0; i < N; i += 4) { - float y0, y1, y2, y3; - float x0; + for (i = 0; i < N2; i++) + xx1[i] = x1[N2-1-i]; + for (i = 0; i < M2; i++) + xx1[N2+i] = mem1[2*i+1]; + for (i = 0; i < N2; i++) + xx2[i] = x2[N2-1-i]; + for (i = 0; i < M2; i++) + xx2[N2+i] = mem2[2*i+1]; - y0 = y1 = y2 = y3 = 0.f; - x0 = xx[N-4-i]; + for (i = 0; i < N2; i += 2) { + spx_sig_t y0, y1, y2, y3; + spx_word16_t x10, x20; - for (j = 0; j < M; j += 4) { - float x1; - float a0, a1; + y0 = y1 = y2 = y3 = 0; + x10 = xx1[N2-2-i]; + x20 = xx2[N2-2-i]; - a0 = a[j]; - a1 = a[j+1]; - x1 = xx[N-2+j-i]; + for (j = 0; j < M2; j += 2) { + spx_word16_t x11, x21; + spx_word16_t a0, a1; - y0 += a0 * x1; - y1 += a1 * x1; - y2 += a0 * x0; - y3 += a1 * x0; + a0 = a[2*j]; + a1 = a[2*j+1]; + x11 = xx1[N2-1+j-i]; + x21 = xx2[N2-1+j-i]; - a0 = a[j+2]; - a1 = a[j+3]; - x0 = xx[N+j-i]; +#ifdef FIXED_POINT + /* We multiply twice by the same coef to avoid overflows */ + y0 = MAC16_16(MAC16_16(y0, a0, x11), NEG16(a0), x21); + y1 = MAC16_16(MAC16_16(y1, a1, x11), a1, x21); + y2 = MAC16_16(MAC16_16(y2, a0, x10), NEG16(a0), x20); + y3 = MAC16_16(MAC16_16(y3, a1, x10), a1, x20); +#else + y0 = ADD32(y0,MULT16_16(a0, x11-x21)); + y1 = ADD32(y1,MULT16_16(a1, x11+x21)); + y2 = ADD32(y2,MULT16_16(a0, x10-x20)); + y3 = ADD32(y3,MULT16_16(a1, x10+x20)); +#endif + a0 = a[2*j+2]; + a1 = a[2*j+3]; + x10 = xx1[N2+j-i]; + x20 = xx2[N2+j-i]; - y0 += a0 * x0; - y1 += a1 * x0; - y2 += a0 * x1; - y3 += a1 * x1; +#ifdef FIXED_POINT + /* We multiply twice by the same coef to avoid overflows */ + y0 = MAC16_16(MAC16_16(y0, a0, x10), NEG16(a0), x20); + y1 = MAC16_16(MAC16_16(y1, a1, x10), a1, x20); + y2 = MAC16_16(MAC16_16(y2, a0, x11), NEG16(a0), x21); + y3 = MAC16_16(MAC16_16(y3, a1, x11), a1, x21); +#else + y0 = ADD32(y0,MULT16_16(a0, x10-x20)); + y1 = ADD32(y1,MULT16_16(a1, x10+x20)); + y2 = ADD32(y2,MULT16_16(a0, x11-x21)); + y3 = ADD32(y3,MULT16_16(a1, x11+x21)); +#endif } - y[i] = y0; - y[i+1] = y1; - y[i+2] = y2; - y[i+3] = y3; +#ifdef FIXED_POINT + y[2*i] = EXTRACT16(SATURATE32(PSHR32(y0,15),32767)); + y[2*i+1] = EXTRACT16(SATURATE32(PSHR32(y1,15),32767)); + y[2*i+2] = EXTRACT16(SATURATE32(PSHR32(y2,15),32767)); + y[2*i+3] = EXTRACT16(SATURATE32(PSHR32(y3,15),32767)); +#else + /* Normalize up explicitly if we're in float */ + y[2*i] = 2.f*y0; + y[2*i+1] = 2.f*y1; + y[2*i+2] = 2.f*y2; + y[2*i+3] = 2.f*y3; +#endif } - for (i = 0; i < M - 1; i += 2) - mem[i+1] = xx[i]; + for (i = 0; i < M2; i++) + mem1[2*i+1] = xx1[i]; + for (i = 0; i < M2; i++) + mem2[2*i+1] = xx2[i]; } +#endif /* DISABLE_WIDEBAND */ -void comp_filter_mem_init (CombFilterMem *mem) +#ifndef DISABLE_DECODER + +#ifdef FIXED_POINT +#if 0 +const spx_word16_t shift_filt[3][7] = {{-33, 1043, -4551, 19959, 19959, -4551, 1043}, + {-98, 1133, -4425, 29179, 8895, -2328, 444}, + {444, -2328, 8895, 29179, -4425, 1133, -98}}; +#else +const spx_word16_t shift_filt[3][7] = {{-390, 1540, -4993, 20123, 20123, -4993, 1540}, + {-1064, 2817, -6694, 31589, 6837, -990, -209}, + {-209, -990, 6837, 31589, -6694, 2817, -1064}}; +#endif +#else +#if 0 +const float shift_filt[3][7] = {{-9.9369e-04, 3.1831e-02, -1.3889e-01, 6.0910e-01, 6.0910e-01, -1.3889e-01, 3.1831e-02}, + {-0.0029937, 0.0345613, -0.1350474, 0.8904793, 0.2714479, -0.0710304, 0.0135403}, + {0.0135403, -0.0710304, 0.2714479, 0.8904793, -0.1350474, 0.0345613, -0.0029937}}; +#else +const float shift_filt[3][7] = {{-0.011915f, 0.046995f, -0.152373f, 0.614108f, 0.614108f, -0.152373f, 0.046995f}, + {-0.0324855f, 0.0859768f, -0.2042986f, 0.9640297f, 0.2086420f, -0.0302054f, -0.0063646f}, + {-0.0063646f, -0.0302054f, 0.2086420f, 0.9640297f, -0.2042986f, 0.0859768f, -0.0324855f}}; +#endif +#endif + +static int interp_pitch( +spx_word16_t *exc, /*decoded excitation*/ +spx_word16_t *interp, /*decoded excitation*/ +int pitch, /*pitch period*/ +int len +) { - mem->last_pitch=0; - mem->last_pitch_gain[0]=mem->last_pitch_gain[1]=mem->last_pitch_gain[2]=0; - mem->smooth_gain=1; + int i,j,k; + spx_word32_t corr[4][7]; + spx_word32_t maxcorr; + int maxi, maxj; + for (i=0;i<7;i++) + { + corr[0][i] = inner_prod(exc, exc-pitch-3+i, len); + } + for (i=0;i<3;i++) + { + for (j=0;j<7;j++) + { + int i1, i2; + spx_word32_t tmp=0; + i1 = 3-j; + if (i1<0) + i1 = 0; + i2 = 10-j; + if (i2>7) + i2 = 7; + for (k=i1;k maxcorr) + { + maxcorr = corr[i][j]; + maxi=i; + maxj=j; + } + } + } + for (i=0;i0) + { + for (k=0;k<7;k++) + { + tmp += MULT16_16(exc[i-(pitch-maxj+3)+k-3],shift_filt[maxi-1][k]); + } + } else { + tmp = SHL32(exc[i-(pitch-maxj+3)],15); + } + interp[i] = PSHR32(tmp,15); + } + return pitch-maxj+3; } -void comb_filter_( -float *exc, /*decoded excitation*/ -float *new_exc, /*enhanced excitation*/ -float *ak, /*LPC filter coefs*/ +void multicomb( +spx_word16_t *exc, /*decoded excitation*/ +spx_word16_t *new_exc, /*enhanced excitation*/ +spx_coef_t *ak, /*LPC filter coefs*/ int p, /*LPC order*/ int nsf, /*sub-frame size*/ int pitch, /*pitch period*/ -float *pitch_gain, /*pitch gain (3-tap)*/ -float comb_gain, /*gain of comb filter*/ -CombFilterMem *mem +int max_pitch, +spx_word16_t comb_gain, /*gain of comb filter*/ +char *stack ) { int i; - float exc_energy=0, new_exc_energy=0; - float gain; - float step; - float fact; - /*Compute excitation energy prior to enhancement*/ - for (i=0;ilast_pitch_gain[0] + mem->last_pitch_gain[1] + mem->last_pitch_gain[2]); - if (g>1.3) - comb_gain*=1.3/g; - if (g<.5) - comb_gain*=2*g; +#ifdef FIXED_POINT + if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],19661)) && +#else + if ((nol_pitch_coef[i]>.6*nol_pitch_coef[0]) && +#endif + (ABS(2*nol_pitch[i]-corr_pitch)<=2 || ABS(3*nol_pitch[i]-corr_pitch)<=3 || + ABS(4*nol_pitch[i]-corr_pitch)<=4 || ABS(5*nol_pitch[i]-corr_pitch)<=5)) + { + corr_pitch = nol_pitch[i]; + } } - step = 1.0/nsf; - fact=0; - /*Apply pitch comb-filter (filter out noise between pitch harmonics)*/ +#else + corr_pitch = pitch; +#endif + + ALLOC(iexc, 2*nsf, spx_word16_t); + + interp_pitch(exc, iexc, corr_pitch, 80); + if (corr_pitch>max_pitch) + interp_pitch(exc, iexc+nsf, 2*corr_pitch, 80); + else + interp_pitch(exc, iexc+nsf, -corr_pitch, 80); + +#ifdef FIXED_POINT for (i=0;ilast_pitch_gain[0]*exc[i-mem->last_pitch+1] + - mem->last_pitch_gain[1]*exc[i-mem->last_pitch] + - mem->last_pitch_gain[2]*exc[i-mem->last_pitch-1] - ); + if (ABS16(exc[i])>16383) + { + scaledown = 1; + break; + } } - - mem->last_pitch_gain[0] = pitch_gain[0]; - mem->last_pitch_gain[1] = pitch_gain[1]; - mem->last_pitch_gain[2] = pitch_gain[2]; - mem->last_pitch = pitch; - - /*Gain after enhancement*/ - for (i=0;i1) - gain=1; - - for (i=0;ismooth_gain = .96*mem->smooth_gain + .04*gain; - new_exc[i] *= mem->smooth_gain; + for (i=0;i MULT16_16(iexc0_mag,exc_mag)) + pgain1 = QCONST16(1., 14); + else + pgain1 = PDIV32_16(SHL32(PDIV32(corr0, exc_mag),14),iexc0_mag); + if (corr1 > MULT16_16(iexc1_mag,exc_mag)) + pgain2 = QCONST16(1., 14); + else + pgain2 = PDIV32_16(SHL32(PDIV32(corr1, exc_mag),14),iexc1_mag); + gg1 = PDIV32_16(SHL32(EXTEND32(exc_mag),8), iexc0_mag); + gg2 = PDIV32_16(SHL32(EXTEND32(exc_mag),8), iexc1_mag); + if (comb_gain>0) + { +#ifdef FIXED_POINT + c1 = (MULT16_16_Q15(QCONST16(.4,15),comb_gain)+QCONST16(.07,15)); + c2 = QCONST16(.5,15)+MULT16_16_Q14(QCONST16(1.72,14),(c1-QCONST16(.07,15))); +#else + c1 = .4*comb_gain+.07; + c2 = .5+1.72*(c1-.07); +#endif + } else + { + c1=c2=0; + } +#ifdef FIXED_POINT + g1 = 32767 - MULT16_16_Q13(MULT16_16_Q15(c2, pgain1),pgain1); + g2 = 32767 - MULT16_16_Q13(MULT16_16_Q15(c2, pgain2),pgain2); +#else + g1 = 1-c2*pgain1*pgain1; + g2 = 1-c2*pgain2*pgain2; +#endif + if (g1max_pitch) + { + gain0 = MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q14(g1,gg1)); + gain1 = MULT16_16_Q15(QCONST16(.3,15),MULT16_16_Q14(g2,gg2)); + } else { + gain0 = MULT16_16_Q15(QCONST16(.6,15),MULT16_16_Q14(g1,gg1)); + gain1 = MULT16_16_Q15(QCONST16(.6,15),MULT16_16_Q14(g2,gg2)); + } + for (i=0;i new_ener) + old_ener = new_ener; + ngain = PDIV32_16(SHL32(EXTEND32(old_ener),14),new_ener); + + for (i=0;imax_scale) + { + sig_shift++; + max_val >>= 1; + } + + __asm__ __volatile__ ( + ".normalize16loop%=: \n" + + "\tldr %4, [%0], #4 \n" + "\tldr %5, [%0], #4 \n" + "\tmov %4, %4, asr %3 \n" + "\tstrh %4, [%1], #2 \n" + "\tldr %4, [%0], #4 \n" + "\tmov %5, %5, asr %3 \n" + "\tstrh %5, [%1], #2 \n" + "\tldr %5, [%0], #4 \n" + "\tmov %4, %4, asr %3 \n" + "\tstrh %4, [%1], #2 \n" + "\tsubs %2, %2, #1 \n" + "\tmov %5, %5, asr %3 \n" + "\tstrh %5, [%1], #2 \n" + + "\tbgt .normalize16loop%=\n" + : "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4), + "=r" (dead5), "=r" (dead6) + : "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift) + : "cc", "memory"); + return sig_shift; +} + diff --git a/external/speex/src/filters_bfin.h b/external/speex/src/filters_bfin.h new file mode 100644 index 0000000..a9bc0d2 --- /dev/null +++ b/external/speex/src/filters_bfin.h @@ -0,0 +1,520 @@ +/* Copyright (C) 2005 Analog Devices */ +/** + @file filters_bfin.h + @brief Various analysis/synthesis filters (Blackfin 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 "bfin.h" + +#define OVERRIDE_NORMALIZE16 +int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int len) +{ + spx_sig_t max_val=1; + int sig_shift; + __asm__ + ( + "%0 = 0;\n\t" + "I0 = %1;\n\t" + "L0 = 0;\n\t" + "R1 = [I0++];\n\t" + "LOOP norm_max%= LC0 = %2;\n\t" + "LOOP_BEGIN norm_max%=;\n\t" + "R2 = ABS R1 || R1 = [I0++];\n\t" + "%0 = MAX(%0, R2);\n\t" + "LOOP_END norm_max%=;\n\t" + : "=&d" (max_val) + : "a" (x), "a" (len) + : "R1", "R2", "ASTAT" BFIN_HWLOOP0_REGS + ); + + sig_shift=0; + while (max_val>max_scale) + { + sig_shift++; + max_val >>= 1; + } + + __asm__ __volatile__ + ( + "I0 = %0;\n\t" + "L0 = 0;\n\t" + "P1 = %1;\n\t" + "R0 = [I0++];\n\t" + "LOOP norm_shift%= LC0 = %3;\n\t" + "LOOP_BEGIN norm_shift%=;\n\t" + "R1 = ASHIFT R0 by %2.L || R0 = [I0++];\n\t" + "W[P1++] = R1;\n\t" + "LOOP_END norm_shift%=;\n\t" + "R1 = ASHIFT R0 by %2.L;\n\t" + "W[P1++] = R1;\n\t" + : : "a" (x), "a" (y), "d" (-sig_shift), "a" (len-1) + : "I0", "L0", "P1", "R0", "R1", "memory", "ASTAT" BFIN_HWLOOP0_REGS + ); + return sig_shift; +} + + + +#define OVERRIDE_FILTER_MEM16 +void filter_mem16(const spx_word16_t *_x, const spx_coef_t *num, const spx_coef_t *den, spx_word16_t *_y, int N, int ord, spx_mem_t *mem, char *stack) +{ + VARDECL(spx_word32_t *xy2); + VARDECL(spx_word32_t *numden_a); + spx_word32_t *xy; + spx_word16_t *numden; + int i; + + ALLOC(xy2, (N+1), spx_word32_t); + ALLOC(numden_a, (2*ord+2), spx_word32_t); + xy = xy2+1; + numden = (spx_word16_t*) numden_a; + + for (i=0;i>> 13;\n\t" + "W[%0] = R3.L;\n\t" + "R0 <<= 1;\n\t" + "R1 = R1 + R0;\n\t" + "R1 >>>= 13;\n\t" + "W[%1] = R1.L;\n\t" + "LOOP_END samples%=;\n\t" + : "=a" (ytmp2), "=a" (y) + : "a" (awk2), "a" (ak), "d" (ord), "m" (N), "0" (ytmp2), "1" (y) + : "A0", "A1", "R0", "R1", "R2", "R3", "I0", "I1", "I2", "I3", "L0", "L1", "L2", "L3", + "ASTAT" BFIN_HWLOOP0_REGS BFIN_HWLOOP1_REGS + ); +} + + + +#if 0 /* Equivalent C function for filter_mem2 and compute_impulse_response */ +#define min(a,b) ((a)<(b) ? (a):(b)) + +void compute_impulse_response(const spx_coef_t *ak, const spx_coef_t *awk1, const spx_coef_t *awk2, spx_word16_t *y, int N, int ord, char *stack) +{ + int i,j; + VARDECL(spx_word16_t *ytmp); + ALLOC(ytmp, N, spx_word16_t); + + y[0] = LPC_SCALING; + for (i=0;i + +void filter_mem16_10(const float *x, const float *_num, const float *_den, float *y, int N, int ord, float *_mem) { - float __num[20], __den[20], __mem[20]; - float *num, *den, *mem; + __m128 num[3], den[3], mem[3]; + int i; - num = (float*)(((int)(__num+4))&0xfffffff0)-1; - den = (float*)(((int)(__den+4))&0xfffffff0)-1; - mem = (float*)(((int)(__mem+4))&0xfffffff0)-1; - for (i=0;i<=10;i++) - num[i]=den[i]=0; - for (i=0;i<10;i++) - mem[i]=0; - - for (i=0;i>1; + __asm__ ( + "P0 = 15;\n\t" + "R0 = %1;\n\t" + "R1 = %2;\n\t" + //"R0 = R0 + R1;\n\t" + "R0 <<= 1;\n\t" + "DIVS (R0, R1);\n\t" + "LOOP divide%= LC0 = P0;\n\t" + "LOOP_BEGIN divide%=;\n\t" + "DIVQ (R0, R1);\n\t" + "LOOP_END divide%=;\n\t" + "R0 = R0.L;\n\t" + "%0 = R0;\n\t" + : "=m" (res) + : "m" (a), "m" (bb) + : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); + return res; +} + +#undef DIV32_16 +static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word16_t b) +{ + spx_word32_t res, bb; + bb = b; + /* Make the roundinf consistent with the C version + (do we need to do that?)*/ + if (a<0) + a += (b-1); + __asm__ ( + "P0 = 15;\n\t" + "R0 = %1;\n\t" + "R1 = %2;\n\t" + "R0 <<= 1;\n\t" + "DIVS (R0, R1);\n\t" + "LOOP divide%= LC0 = P0;\n\t" + "LOOP_BEGIN divide%=;\n\t" + "DIVQ (R0, R1);\n\t" + "LOOP_END divide%=;\n\t" + "R0 = R0.L;\n\t" + "%0 = R0;\n\t" + : "=m" (res) + : "m" (a), "m" (bb) + : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); + return res; +} + +#undef MAX16 +static inline spx_word16_t MAX16(spx_word16_t a, spx_word16_t b) +{ + spx_word32_t res; + __asm__ ( + "%1 = %1.L (X);\n\t" + "%2 = %2.L (X);\n\t" + "%0 = MAX(%1,%2);" + : "=d" (res) + : "%d" (a), "d" (b) + : "ASTAT" + ); + return res; +} + +#undef MULT16_32_Q15 +static inline spx_word32_t MULT16_32_Q15(spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "A1 = %2.L*%1.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %2.L*%1.H) ;\n\t" + : "=&W" (res), "=&d" (b) + : "d" (a), "1" (b) + : "A1", "ASTAT" + ); + return res; +} + +#undef MAC16_32_Q15 +static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "A1 = %2.L*%1.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %2.L*%1.H);\n\t" + "%0 = %0 + %4;\n\t" + : "=&W" (res), "=&d" (b) + : "d" (a), "1" (b), "d" (c) + : "A1", "ASTAT" + ); + return res; +} + +#undef MULT16_32_Q14 +static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "%2 <<= 1;\n\t" + "A1 = %1.L*%2.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %1.L*%2.H);\n\t" + : "=W" (res), "=d" (a), "=d" (b) + : "1" (a), "2" (b) + : "A1", "ASTAT" + ); + return res; +} + +#undef MAC16_32_Q14 +static inline spx_word32_t MAC16_32_Q14(spx_word32_t c, spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "%1 <<= 1;\n\t" + "A1 = %2.L*%1.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %2.L*%1.H);\n\t" + "%0 = %0 + %4;\n\t" + : "=&W" (res), "=&d" (b) + : "d" (a), "1" (b), "d" (c) + : "A1", "ASTAT" + ); + return res; +} + +#endif diff --git a/external/speex/src/fixed_debug.h b/external/speex/src/fixed_debug.h new file mode 100644 index 0000000..756138b --- /dev/null +++ b/external/speex/src/fixed_debug.h @@ -0,0 +1,484 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file fixed_debug.h + @brief Fixed-point operations with debugging +*/ +/* + 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 FIXED_DEBUG_H +#define FIXED_DEBUG_H + +#include + +extern long long spx_mips; +#define MIPS_INC spx_mips++, + +#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) +#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) + + +#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) +#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) + +static inline short NEG16(int x) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "NEG16: input is not short: %d\n", (int)x); + } + res = -x; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "NEG16: output is not short: %d\n", (int)res); + spx_mips++; + return res; +} +static inline int NEG32(long long x) +{ + long long res; + if (!VERIFY_INT(x)) + { + fprintf (stderr, "NEG16: input is not int: %d\n", (int)x); + } + res = -x; + if (!VERIFY_INT(res)) + fprintf (stderr, "NEG16: output is not int: %d\n", (int)res); + spx_mips++; + return res; +} + +#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__) +static inline short _EXTRACT16(int x, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line); + } + res = x; + spx_mips++; + return res; +} + +#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__) +static inline int _EXTEND32(int x, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line); + } + res = x; + spx_mips++; + return res; +} + +#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) +static inline short _SHR16(int a, int shift, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line); + } + res = a>>shift; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line); + spx_mips++; + return res; +} +#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) +static inline short _SHL16(int a, int shift, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line); + } + res = (int)((unsigned)a<>shift; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "SHR32: output is not int: %d\n", (int)res); + } + spx_mips++; + return res; +} +static inline int SHL32(long long a, int shift) +{ + long long res; + if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift); + } + res = (long long)((unsigned long long)a<>1))),shift)) +#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift)) +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) + +#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) +#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + +//#define SHR(a,shift) ((a) >> (shift)) +//#define SHL(a,shift) ((a) << (shift)) + +#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) +static inline short _ADD16(int a, int b, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); + } + res = a+b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line); + } + spx_mips++; + return res; +} + +#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) +static inline short _SUB16(int a, int b, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); + } + res = a-b; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line); + spx_mips++; + return res; +} + +#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) +static inline int _ADD32(long long a, long long b, char *file, int line) +{ + long long res; + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line); + } + res = a+b; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line); + } + spx_mips++; + return res; +} + +static inline int SUB32(long long a, long long b) +{ + long long res; + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b); + } + res = a-b; + if (!VERIFY_INT(res)) + fprintf (stderr, "SUB32: output is not int: %d\n", (int)res); + spx_mips++; + return res; +} + +#define ADD64(a,b) (MIPS_INC(a)+(b)) + +/* result fits in 16 bits */ +static inline short MULT16_16_16(int a, int b) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b); + } + res = a*b; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res); + spx_mips++; + return res; +} + +#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) +static inline int _MULT16_16(int a, int b, char *file, int line) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); + } + res = ((long long)a)*b; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line); + spx_mips++; + return res; +} + +#define MAC16_16(c,a,b) (spx_mips--,ADD32((c),MULT16_16((a),(b)))) +#define MAC16_16_Q11(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))) +#define MAC16_16_Q13(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))) +#define MAC16_16_P13(c,a,b) (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))) + + +#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__) +static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); + } + if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); + res = (((long long)a)*(long long)b) >> Q; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line); + spx_mips+=5; + return res; +} + +static inline int MULT16_32_PX(int a, long long b, int Q) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b); + } + if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b); + res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<>1))>> Q; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res); + spx_mips+=5; + return res; +} + + +#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13) +#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14) +#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15) +#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15) +#define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b))) + +static inline int SATURATE(int a, int b) +{ + if (a>b) + a=b; + if (a<-b) + a = -b; + return a; +} + +static inline int MULT16_16_Q11_32(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 11; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res); + spx_mips+=3; + return res; +} +static inline short MULT16_16_Q13(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 13; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=3; + return res; +} +static inline short MULT16_16_Q14(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 14; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res); + spx_mips+=3; + return res; +} +static inline short MULT16_16_Q15(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 15; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res); + } + spx_mips+=3; + return res; +} + +static inline short MULT16_16_P13(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res += 4096; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res); + res >>= 13; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=4; + return res; +} +static inline short MULT16_16_P14(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res += 8192; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res); + res >>= 14; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=4; + return res; +} +static inline short MULT16_16_P15(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res += 16384; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res); + res >>= 15; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=4; + return res; +} + +#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) + +static inline int _DIV32_16(long long a, long long b, char *file, int line) +{ + long long res; + if (b==0) + { + fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); + return 0; + } + if (!VERIFY_INT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line); + } + res = a/b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line); + if (res>32767) + res = 32767; + if (res<-32768) + res = -32768; + } + spx_mips+=20; + return res; +} + +#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) +static inline int _DIV32(long long a, long long b, char *file, int line) +{ + long long res; + if (b==0) + { + fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); + return 0; + } + + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line); + } + res = a/b; + if (!VERIFY_INT(res)) + fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line); + spx_mips+=36; + return res; +} +#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b) +#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b) + +#endif diff --git a/external/speex/src/fixed_generic.h b/external/speex/src/fixed_generic.h new file mode 100644 index 0000000..8ae5e4d --- /dev/null +++ b/external/speex/src/fixed_generic.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file fixed_generic.h + @brief Generic fixed-point operations +*/ +/* + 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 FIXED_GENERIC_H +#define FIXED_GENERIC_H + +#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) +#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) ((spx_word16_t)(x)) +#define EXTEND32(x) ((spx_word32_t)(x)) +#define SHR16(a,shift) ((a) >> (shift)) +#define SHL16(a,shift) ((spx_int16_t)((spx_uint16_t)(a) << (shift))) +#define SHR32(a,shift) ((a) >> (shift)) +#define SHL32(a,shift) ((spx_int32_t)((spx_uint32_t)(a) << (shift))) +#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) +#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) +#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) +#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + +#define SHR(a,shift) ((a) >> (shift)) +#define SHL(a,shift) ((spx_int32_t)((spx_uint32_t)(a) << (shift))) +#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + + +#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) +#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) +#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) +#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) + + +/* result fits in 16 bits */ +#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) + +/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ +#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) + +#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) +#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) +#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14)) + +#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) +#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) +#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) + + +#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) +#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13))) +#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13))) + +#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) +#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) +#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) +#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) + +#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) +#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) +#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) + +#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) + +#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) +#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) +#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) +#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) + +#endif diff --git a/external/speex/src/gain_table.c b/external/speex/src/gain_table.c index b1a2a7d..63dc6e7 100644 --- a/external/speex/src/gain_table.c +++ b/external/speex/src/gain_table.c @@ -1,13 +1,13 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: gain_table.c Codebook for 3-tap pitch prediction gain (128 entries) - + 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. + 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 @@ -29,132 +29,132 @@ POSSIBILITY OF SUCH DAMAGE. */ -signed char gain_cdbk_nb[384] = { --32,-32,-32, --28,-67,-5, --42,-6,-32, --57,-10,-54, --16,27,-41, -19,-19,-40, --45,24,-21, --8,-14,-18, -1,14,-58, --18,-88,-39, --38,21,-18, --19,20,-43, -10,17,-48, --52,-58,-13, --44,-1,-11, --12,-11,-34, -14,0,-46, --37,-35,-34, --25,44,-30, -6,-4,-63, --31,43,-41, --23,30,-43, --43,26,-14, --33,1,-13, --13,18,-37, --46,-73,-45, --36,24,-25, --36,-11,-20, --25,12,-18, --36,-69,-59, --45,6,8, --22,-14,-24, --1,13,-44, --39,-48,-26, --32,31,-37, --33,15,-46, --24,30,-36, --41,31,-23, --50,22,-4, --22,2,-21, --17,30,-34, --7,-60,-28, --38,42,-28, --44,-11,21, --16,8,-44, --39,-55,-43, --11,-35,26, --9,0,-34, --8,121,-81, -7,-16,-22, --37,33,-31, --27,-7,-36, --34,70,-57, --37,-11,-48, --40,17,-1, --33,6,-6, --9,0,-20, --21,69,-33, --29,33,-31, --55,12,-1, --33,27,-22, --50,-33,-47, --50,54,51, --1,-5,-44, --4,22,-40, --39,-66,-25, --33,1,-26, --24,-23,-25, --11,21,-45, --25,-45,-19, --43,105,-16, -5,-21,1, --16,11,-33, --13,-99,-4, --37,33,-15, --25,37,-63, --36,24,-31, --53,-56,-38, --41,-4,4, --33,13,-30, -49,52,-94, --5,-30,-15, -1,38,-40, --23,12,-36, --17,40,-47, --37,-41,-39, --49,34,0, --18,-7,-4, --16,17,-27, -30,5,-62, -4,48,-68, --43,11,-11, --18,19,-15, --23,-62,-39, --42,10,-2, --21,-13,-13, --9,13,-47, --23,-62,-24, --44,60,-21, --18,-3,-52, --22,22,-36, --75,57,16, --19,3,10, --29,23,-38, --5,-62,-51, --51,40,-18, --42,13,-24, --34,14,-20, --56,-75,-26, --26,32,15, --26,17,-29, --7,28,-52, --12,-30,5, --5,-48,-5, -2,2,-43, -21,16,16, --25,-45,-32, --43,18,-10, -9,0,-1, --1,7,-30, -19,-48,-4, --28,25,-29, --22,0,-31, --32,17,-10, --64,-41,-62, --52,15,16, --30,-22,-32, --7,9,-38}; +const signed char gain_cdbk_nb[512] = { +-32, -32, -32, 0, +-28, -67, -5, 33, +-42, -6, -32, 18, +-57, -10, -54, 35, +-16, 27, -41, 42, +19, -19, -40, 36, +-45, 24, -21, 40, +-8, -14, -18, 28, +1, 14, -58, 53, +-18, -88, -39, 39, +-38, 21, -18, 37, +-19, 20, -43, 38, +10, 17, -48, 54, +-52, -58, -13, 33, +-44, -1, -11, 32, +-12, -11, -34, 22, +14, 0, -46, 46, +-37, -35, -34, 5, +-25, 44, -30, 43, +6, -4, -63, 49, +-31, 43, -41, 43, +-23, 30, -43, 41, +-43, 26, -14, 44, +-33, 1, -13, 27, +-13, 18, -37, 37, +-46, -73, -45, 34, +-36, 24, -25, 34, +-36, -11, -20, 19, +-25, 12, -18, 33, +-36, -69, -59, 34, +-45, 6, 8, 46, +-22, -14, -24, 18, +-1, 13, -44, 44, +-39, -48, -26, 15, +-32, 31, -37, 34, +-33, 15, -46, 31, +-24, 30, -36, 37, +-41, 31, -23, 41, +-50, 22, -4, 50, +-22, 2, -21, 28, +-17, 30, -34, 40, +-7, -60, -28, 29, +-38, 42, -28, 42, +-44, -11, 21, 43, +-16, 8, -44, 34, +-39, -55, -43, 21, +-11, -35, 26, 41, +-9, 0, -34, 29, +-8, 121, -81, 113, +7, -16, -22, 33, +-37, 33, -31, 36, +-27, -7, -36, 17, +-34, 70, -57, 65, +-37, -11, -48, 21, +-40, 17, -1, 44, +-33, 6, -6, 33, +-9, 0, -20, 34, +-21, 69, -33, 57, +-29, 33, -31, 35, +-55, 12, -1, 49, +-33, 27, -22, 35, +-50, -33, -47, 17, +-50, 54, 51, 94, +-1, -5, -44, 35, +-4, 22, -40, 45, +-39, -66, -25, 24, +-33, 1, -26, 20, +-24, -23, -25, 12, +-11, 21, -45, 44, +-25, -45, -19, 17, +-43, 105, -16, 82, +5, -21, 1, 41, +-16, 11, -33, 30, +-13, -99, -4, 57, +-37, 33, -15, 44, +-25, 37, -63, 54, +-36, 24, -31, 31, +-53, -56, -38, 26, +-41, -4, 4, 37, +-33, 13, -30, 24, +49, 52, -94, 114, +-5, -30, -15, 23, +1, 38, -40, 56, +-23, 12, -36, 29, +-17, 40, -47, 51, +-37, -41, -39, 11, +-49, 34, 0, 58, +-18, -7, -4, 34, +-16, 17, -27, 35, +30, 5, -62, 65, +4, 48, -68, 76, +-43, 11, -11, 38, +-18, 19, -15, 41, +-23, -62, -39, 23, +-42, 10, -2, 41, +-21, -13, -13, 25, +-9, 13, -47, 42, +-23, -62, -24, 24, +-44, 60, -21, 58, +-18, -3, -52, 32, +-22, 22, -36, 34, +-75, 57, 16, 90, +-19, 3, 10, 45, +-29, 23, -38, 32, +-5, -62, -51, 38, +-51, 40, -18, 53, +-42, 13, -24, 32, +-34, 14, -20, 30, +-56, -75, -26, 37, +-26, 32, 15, 59, +-26, 17, -29, 29, +-7, 28, -52, 53, +-12, -30, 5, 30, +-5, -48, -5, 35, +2, 2, -43, 40, +21, 16, 16, 75, +-25, -45, -32, 10, +-43, 18, -10, 42, +9, 0, -1, 52, +-1, 7, -30, 36, +19, -48, -4, 48, +-28, 25, -29, 32, +-22, 0, -31, 22, +-32, 17, -10, 36, +-64, -41, -62, 36, +-52, 15, 16, 58, +-30, -22, -32, 6, +-7, 9, -38, 36}; diff --git a/external/speex/src/gain_table_lbr.c b/external/speex/src/gain_table_lbr.c index 1d6291a..be464f3 100644 --- a/external/speex/src/gain_table_lbr.c +++ b/external/speex/src/gain_table_lbr.c @@ -1,13 +1,13 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: gain_table_lbr.c Codebook for 3-tap pitch prediction gain (32 entries) - + 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. + 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 @@ -29,36 +29,36 @@ POSSIBILITY OF SUCH DAMAGE. */ -signed char gain_cdbk_lbr[96] = { --32,-32,-32, --31,-58,-16, --41,-24,-43, --56,-22,-55, --13,33,-41, --4,-39,-9, --41,15,-12, --8,-15,-12, -1,2,-44, --22,-66,-42, --38,28,-23, --21,14,-37, -0,21,-50, --53,-71,-27, --37,-1,-19, --19,-5,-28, -6,65,-44, --33,-48,-33, --40,57,-14, --17,4,-45, --31,38,-33, --23,28,-40, --43,29,-12, --34,13,-23, --16,15,-27, --14,-82,-15, --31,25,-32, --21,5,-5, --47,-63,-51, --46,12,3, --28,-17,-29, --10,14,-40}; +const signed char gain_cdbk_lbr[128] = { +-32, -32, -32, 0, +-31, -58, -16, 22, +-41, -24, -43, 14, +-56, -22, -55, 29, +-13, 33, -41, 47, +-4, -39, -9, 29, +-41, 15, -12, 38, +-8, -15, -12, 31, +1, 2, -44, 40, +-22, -66, -42, 27, +-38, 28, -23, 38, +-21, 14, -37, 31, +0, 21, -50, 52, +-53, -71, -27, 33, +-37, -1, -19, 25, +-19, -5, -28, 22, +6, 65, -44, 74, +-33, -48, -33, 9, +-40, 57, -14, 58, +-17, 4, -45, 32, +-31, 38, -33, 36, +-23, 28, -40, 39, +-43, 29, -12, 46, +-34, 13, -23, 28, +-16, 15, -27, 34, +-14, -82, -15, 43, +-31, 25, -32, 29, +-21, 5, -5, 38, +-47, -63, -51, 33, +-46, 12, 3, 47, +-28, -17, -29, 11, +-10, 14, -40, 38}; diff --git a/external/speex/src/hexc_10_32_table.c b/external/speex/src/hexc_10_32_table.c index 39ff1f9..1c7f285 100644 --- a/external/speex/src/hexc_10_32_table.c +++ b/external/speex/src/hexc_10_32_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: hexc_10_32_table.c Codebook for high-band excitation in SB-CELP mode (4000 bps) 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 @@ -30,37 +30,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -signed char hexc_10_32_table[320] = { --3, -2, -1, 0, -4, 5, 35, -40, -9, 13, --44, 5, -27, -1, -7, 6, -11, 7, -8, 7, -19, -14, 15, -4, 9, -10, 10, -8, 10, -9, --1, 1, 0, 0, 2, 5, -18, 22, -53, 50, -1, -23, 50, -36, 15, 3, -13, 14, -10, 6, -1, 5, -3, 4, -2, 5, -32, 25, 5, -2, --1, -4, 1, 11, -29, 26, -6, -15, 30, -18, -0, 15, -17, 40, -41, 3, 9, -2, -2, 3, --3, -1, -5, 2, 21, -6, -16, -21, 23, 2, -60, 15, 16, -16, -9, 14, 9, -1, 7, -9, -0, 1, 1, 0, -1, -6, 17, -28, 54, -45, --1, 1, -1, -6, -6, 2, 11, 26, -29, -2, -46, -21, 34, 12, -23, 32, -23, 16, -10, 3, -66, 19, -20, 24, 7, 11, -3, 0, -3, -1, --50, -46, 2, -18, -3, 4, -1, -2, 3, -3, --19, 41, -36, 9, 11, -24, 21, -16, 9, -3, --25, -3, 10, 18, -9, -2, -5, -1, -5, 6, --4, -3, 2, -26, 21, -19, 35, -15, 7, -13, -17, -19, 39, -43, 48, -31, 16, -9, 7, -2, --5, 3, -4, 9, -19, 27, -55, 63, -35, 10, -26, -44, -2, 9, 4, 1, -6, 8, -9, 5, --8, -1, -3, -16, 45, -42, 5, 15, -16, 10, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, --16, 24, -55, 47, -38, 27, -19, 7, -3, 1, -16, 27, 20, -19, 18, 5, -7, 1, -5, 2, --6, 8, -22, 0, -3, -3, 8, -1, 7, -8, -1, -3, 5, 0, 17, -48, 58, -52, 29, -7, --2, 3, -10, 6, -26, 58, -31, 1, -6, 3, -93, -29, 39, 3, 17, 5, 6, -1, -1, -1, -27, 13, 10, 19, -7, -34, 12, 10, -4, 9, --76, 9, 8, -28, -2, -11, 2, -1, 3, 1, --83, 38, -39, 4, -16, -6, -2, -5, 5, -2, +const signed char hexc_10_32_table[320] = { +-3, -2, -1, 0, -4, 5, 35, -40, -9, 13, +-44, 5, -27, -1, -7, 6, -11, 7, -8, 7, +19, -14, 15, -4, 9, -10, 10, -8, 10, -9, +-1, 1, 0, 0, 2, 5, -18, 22, -53, 50, +1, -23, 50, -36, 15, 3, -13, 14, -10, 6, +1, 5, -3, 4, -2, 5, -32, 25, 5, -2, +-1, -4, 1, 11, -29, 26, -6, -15, 30, -18, +0, 15, -17, 40, -41, 3, 9, -2, -2, 3, +-3, -1, -5, 2, 21, -6, -16, -21, 23, 2, +60, 15, 16, -16, -9, 14, 9, -1, 7, -9, +0, 1, 1, 0, -1, -6, 17, -28, 54, -45, +-1, 1, -1, -6, -6, 2, 11, 26, -29, -2, +46, -21, 34, 12, -23, 32, -23, 16, -10, 3, +66, 19, -20, 24, 7, 11, -3, 0, -3, -1, +-50, -46, 2, -18, -3, 4, -1, -2, 3, -3, +-19, 41, -36, 9, 11, -24, 21, -16, 9, -3, +-25, -3, 10, 18, -9, -2, -5, -1, -5, 6, +-4, -3, 2, -26, 21, -19, 35, -15, 7, -13, +17, -19, 39, -43, 48, -31, 16, -9, 7, -2, +-5, 3, -4, 9, -19, 27, -55, 63, -35, 10, +26, -44, -2, 9, 4, 1, -6, 8, -9, 5, +-8, -1, -3, -16, 45, -42, 5, 15, -16, 10, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +-16, 24, -55, 47, -38, 27, -19, 7, -3, 1, +16, 27, 20, -19, 18, 5, -7, 1, -5, 2, +-6, 8, -22, 0, -3, -3, 8, -1, 7, -8, +1, -3, 5, 0, 17, -48, 58, -52, 29, -7, +-2, 3, -10, 6, -26, 58, -31, 1, -6, 3, +93, -29, 39, 3, 17, 5, 6, -1, -1, -1, +27, 13, 10, 19, -7, -34, 12, 10, -4, 9, +-76, 9, 8, -28, -2, -11, 2, -1, 3, 1, +-83, 38, -39, 4, -16, -6, -2, -5, 5, -2, }; diff --git a/external/speex/src/hexc_table.c b/external/speex/src/hexc_table.c index d7b2f51..6e36069 100644 --- a/external/speex/src/hexc_table.c +++ b/external/speex/src/hexc_table.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: hexc_table.c Codebook for high-band excitation in SB-CELP mode (8000 bps with sign) 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 @@ -30,133 +30,133 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -signed char hexc_table[1024] = { --24, 21, -20, 5, -5, -7, 14, -10, -2, -27, 16, -20, 0, -32, 26, 19, -8, -11, -41, 31, 28, -27, -32, 34, -42, 34, -17, 22, -10, 13, -29, 18, --12, -26, -24, 11, 22, 5, -5, -5, -54, -68, -43, 57, -25, 24, 4, 4, -26, -8, -12, -17, 54, 30, -45, 1, -10, -15, 18, -41, 11, 68, -67, 37, --16, -24, -16, 38, -22, 6, -29, 30, -66, -27, 5, 7, -16, 13, 2, -12, --7, -3, -20, 36, 4, -28, 9, 3, -32, 48, 26, 39, 3, 0, 7, -21, --13, 5, -82, -7, 73, -20, 34, -9, --5, 1, -1, 10, -5, -10, -1, 9, -1, -9, 10, 0, -14, 11, -1, -2, --1, 11, 20, 96, -81, -22, -12, -9, --58, 9, 24, -30, 26, -35, 27, -12, -13, -18, 56, -59, 15, -7, 23, -15, --1, 6, -25, 14, -22, -20, 47, -11, -16, 2, 38, -23, -19, -30, -9, 40, --11, 5, 4, -6, 8, 26, -21, -11, -131, 4, 1, 6, -9, 2, -7, -2, --3, 7, -5, 10, -19, 7, -106, 91, --3, 9, -4, 21, -8, 26, -80, 8, -1, -2, -10, -17, -17, -27, 32, 71, -6, -29, 11, -23, 54, -38, 29, -22, -39, 87, -31, -12, -20, 3, -2, -2, -2, 20, 0, -1, -35, 27, 9, -6, --12, 3, -12, -6, 13, 1, 14, -22, --59, -15, -17, -25, 13, -7, 7, 3, -0, 1, -7, 6, -3, 61, -37, -23, --23, -29, 38, -31, 27, 1, -8, 2, --27, 23, -26, 36, -34, 5, 24, -24, --6, 7, 3, -59, 78, -62, 44, -16, -1, 6, 0, 17, 8, 45, 0, -110, -6, 14, -2, 32, -77, -56, 62, -3, -3, -13, 4, -16, 102, -15, -36, -1, -9, -113, 6, 23, 0, 9, 9, 5, --8, -1, -14, 5, -12, 121, -53, -27, --8, -9, 22, -13, 3, 2, -3, 1, --2, -71, 95, 38, -19, 15, -16, -5, -71, 10, 2, -32, -13, -5, 15, -1, --2, -14, -85, 30, 29, 6, 3, 2, -0, 0, 0, 0, 0, 0, 0, 0, -2, -65, -56, -9, 18, 18, 23, -14, --2, 0, 12, -29, 26, -12, 1, 2, --12, -64, 90, -6, 4, 1, 5, -5, --110, -3, -31, 22, -29, 9, 0, 8, --40, -5, 21, -5, -5, 13, 10, -18, -40, 1, 35, -20, 30, -28, 11, -6, -19, 7, 14, 18, -64, 9, -6, 16, -51, 68, 8, 16, 12, -8, 0, -9, -20, -22, 25, 7, -4, -13, 41, -35, -93, -18, -54, 11, -1, 1, -9, 4, --66, 66, -31, 20, -22, 25, -23, 11, -10, 9, 19, 15, 11, -5, -31, -10, --23, -28, -6, -6, -3, -4, 5, 3, --28, 22, -11, -42, 25, -25, -16, 41, -34, 47, -6, 2, 42, -19, -22, 5, --39, 32, 6, -35, 22, 17, -30, 8, --26, -11, -11, 3, -12, 33, 33, -37, -21, -1, 6, -4, 3, 0, -5, 5, -12, -12, 57, 27, -61, -3, 20, -17, -2, 0, 4, 0, -2, -33, -58, 81, --23, 39, -10, -5, 2, 6, -7, 5, -4, -3, -2, -13, -23, -72, 107, 15, --5, 0, -7, -3, -6, 5, -4, 15, -47, 12, -31, 25, -16, 8, 22, -25, --62, -56, -18, 14, 28, 12, 2, -11, -74, -66, 41, -20, -7, 16, -20, 16, --8, 0, -16, 4, -19, 92, 12, -59, --14, -39, 49, -25, -16, 23, -27, 19, --3, -33, 19, 85, -29, 6, -7, -10, -16, -7, -12, 1, -6, 2, 4, -2, -64, 10, -25, 41, -2, -31, 15, 0, -110, 50, 69, 35, 28, 19, -10, 2, --43, -49, -56, -15, -16, 10, 3, 12, --1, -8, 1, 26, -12, -1, 7, -11, --27, 41, 25, 1, -11, -18, 22, -7, --1, -47, -8, 23, -3, -17, -7, 18, --125, 59, -5, 3, 18, 1, 2, 3, -27, -35, 65, -53, 50, -46, 37, -21, --28, 7, 14, -37, -5, -5, 12, 5, --8, 78, -19, 21, -6, -16, 8, -7, -5, 2, 7, 2, 10, -6, 12, -60, -44, 11, -36, -32, 31, 0, 2, -2, -2, 1, -3, 7, -10, 17, -21, 10, -6, -2, 19, -2, 59, -38, -86, 38, -8, -41, -30, -45, -33, 7, 15, 28, -29, -7, 24, -40, 7, 7, 5, -2, -9, 24, -23, -18, 6, -29, 30, 2, -28, 49, -11, -46, 10, 43, -13, -9, --1, -3, -7, -7, -17, -6, 97, -33, --21, 3, 5, 1, 12, -43, -8, 28, -7, -43, -7, 17, -20, 19, -1, 2, --13, 9, 54, 34, 9, -28, -11, -9, --17, 110, -59, 44, -26, 0, 3, -12, --47, 73, -34, -43, 38, -33, 16, -5, --46, -4, -6, -2, -25, 19, -29, 28, --13, 5, 14, 27, -40, -43, 4, 32, --13, -2, -35, -4, 112, -42, 9, -12, -37, -28, 17, 14, -19, 35, -39, 23, -3, -14, -1, -57, -5, 94, -9, 3, --39, 5, 30, -10, -32, 42, -13, -14, --97, -63, 30, -9, 1, -7, 12, 5, -20, 17, -9, -36, -30, 25, 47, -9, --15, 12, -22, 98, -8, -50, 15, -27, -21, -16, -11, 2, 12, -10, 10, -3, -33, 36, -96, 0, -17, 31, -9, 9, -3, -20, 13, -11, 8, -4, 10, -10, -9, 1, 112, -70, -27, 5, -21, 2, --57, -3, -29, 10, 19, -21, 21, -10, --66, -3, 91, -35, 30, -12, 0, -7, -59, -28, 26, 2, 14, -18, 1, 1, -11, 17, 20, -54, -59, 27, 4, 29, -32, 5, 19, 12, -4, 1, 7, -10, -5, -2, 10, 0, 23, -5, 28, -104, -46, 11, 16, 3, 29, 1, -8, -14, -1, 7, -50, 88, -62, 26, 8, -17, --14, 50, 0, 32, -12, -3, -27, 18, --8, -5, 8, 3, -20, -11, 37, -12, -9, 33, 46, -101, -1, -4, 1, 6, --1, 28, -42, -15, 16, 5, -1, -2, --55, 85, 38, -9, -4, 11, -2, -9, --6, 3, -20, -10, -77, 89, 24, -3, --104, -57, -26, -31, -20, -6, -9, 14, -20, -23, 46, -15, -31, 28, 1, -15, --2, 6, -2, 31, 45, -76, 23, -25, +const signed char hexc_table[1024] = { +-24, 21, -20, 5, -5, -7, 14, -10, +2, -27, 16, -20, 0, -32, 26, 19, +8, -11, -41, 31, 28, -27, -32, 34, +42, 34, -17, 22, -10, 13, -29, 18, +-12, -26, -24, 11, 22, 5, -5, -5, +54, -68, -43, 57, -25, 24, 4, 4, +26, -8, -12, -17, 54, 30, -45, 1, +10, -15, 18, -41, 11, 68, -67, 37, +-16, -24, -16, 38, -22, 6, -29, 30, +66, -27, 5, 7, -16, 13, 2, -12, +-7, -3, -20, 36, 4, -28, 9, 3, +32, 48, 26, 39, 3, 0, 7, -21, +-13, 5, -82, -7, 73, -20, 34, -9, +-5, 1, -1, 10, -5, -10, -1, 9, +1, -9, 10, 0, -14, 11, -1, -2, +-1, 11, 20, 96, -81, -22, -12, -9, +-58, 9, 24, -30, 26, -35, 27, -12, +13, -18, 56, -59, 15, -7, 23, -15, +-1, 6, -25, 14, -22, -20, 47, -11, +16, 2, 38, -23, -19, -30, -9, 40, +-11, 5, 4, -6, 8, 26, -21, -11, +127, 4, 1, 6, -9, 2, -7, -2, +-3, 7, -5, 10, -19, 7, -106, 91, +-3, 9, -4, 21, -8, 26, -80, 8, +1, -2, -10, -17, -17, -27, 32, 71, +6, -29, 11, -23, 54, -38, 29, -22, +39, 87, -31, -12, -20, 3, -2, -2, +2, 20, 0, -1, -35, 27, 9, -6, +-12, 3, -12, -6, 13, 1, 14, -22, +-59, -15, -17, -25, 13, -7, 7, 3, +0, 1, -7, 6, -3, 61, -37, -23, +-23, -29, 38, -31, 27, 1, -8, 2, +-27, 23, -26, 36, -34, 5, 24, -24, +-6, 7, 3, -59, 78, -62, 44, -16, +1, 6, 0, 17, 8, 45, 0, -110, +6, 14, -2, 32, -77, -56, 62, -3, +3, -13, 4, -16, 102, -15, -36, -1, +9, -113, 6, 23, 0, 9, 9, 5, +-8, -1, -14, 5, -12, 121, -53, -27, +-8, -9, 22, -13, 3, 2, -3, 1, +-2, -71, 95, 38, -19, 15, -16, -5, +71, 10, 2, -32, -13, -5, 15, -1, +-2, -14, -85, 30, 29, 6, 3, 2, +0, 0, 0, 0, 0, 0, 0, 0, +2, -65, -56, -9, 18, 18, 23, -14, +-2, 0, 12, -29, 26, -12, 1, 2, +-12, -64, 90, -6, 4, 1, 5, -5, +-110, -3, -31, 22, -29, 9, 0, 8, +-40, -5, 21, -5, -5, 13, 10, -18, +40, 1, 35, -20, 30, -28, 11, -6, +19, 7, 14, 18, -64, 9, -6, 16, +51, 68, 8, 16, 12, -8, 0, -9, +20, -22, 25, 7, -4, -13, 41, -35, +93, -18, -54, 11, -1, 1, -9, 4, +-66, 66, -31, 20, -22, 25, -23, 11, +10, 9, 19, 15, 11, -5, -31, -10, +-23, -28, -6, -6, -3, -4, 5, 3, +-28, 22, -11, -42, 25, -25, -16, 41, +34, 47, -6, 2, 42, -19, -22, 5, +-39, 32, 6, -35, 22, 17, -30, 8, +-26, -11, -11, 3, -12, 33, 33, -37, +21, -1, 6, -4, 3, 0, -5, 5, +12, -12, 57, 27, -61, -3, 20, -17, +2, 0, 4, 0, -2, -33, -58, 81, +-23, 39, -10, -5, 2, 6, -7, 5, +4, -3, -2, -13, -23, -72, 107, 15, +-5, 0, -7, -3, -6, 5, -4, 15, +47, 12, -31, 25, -16, 8, 22, -25, +-62, -56, -18, 14, 28, 12, 2, -11, +74, -66, 41, -20, -7, 16, -20, 16, +-8, 0, -16, 4, -19, 92, 12, -59, +-14, -39, 49, -25, -16, 23, -27, 19, +-3, -33, 19, 85, -29, 6, -7, -10, +16, -7, -12, 1, -6, 2, 4, -2, +64, 10, -25, 41, -2, -31, 15, 0, +110, 50, 69, 35, 28, 19, -10, 2, +-43, -49, -56, -15, -16, 10, 3, 12, +-1, -8, 1, 26, -12, -1, 7, -11, +-27, 41, 25, 1, -11, -18, 22, -7, +-1, -47, -8, 23, -3, -17, -7, 18, +-125, 59, -5, 3, 18, 1, 2, 3, +27, -35, 65, -53, 50, -46, 37, -21, +-28, 7, 14, -37, -5, -5, 12, 5, +-8, 78, -19, 21, -6, -16, 8, -7, +5, 2, 7, 2, 10, -6, 12, -60, +44, 11, -36, -32, 31, 0, 2, -2, +2, 1, -3, 7, -10, 17, -21, 10, +6, -2, 19, -2, 59, -38, -86, 38, +8, -41, -30, -45, -33, 7, 15, 28, +29, -7, 24, -40, 7, 7, 5, -2, +9, 24, -23, -18, 6, -29, 30, 2, +28, 49, -11, -46, 10, 43, -13, -9, +-1, -3, -7, -7, -17, -6, 97, -33, +-21, 3, 5, 1, 12, -43, -8, 28, +7, -43, -7, 17, -20, 19, -1, 2, +-13, 9, 54, 34, 9, -28, -11, -9, +-17, 110, -59, 44, -26, 0, 3, -12, +-47, 73, -34, -43, 38, -33, 16, -5, +-46, -4, -6, -2, -25, 19, -29, 28, +-13, 5, 14, 27, -40, -43, 4, 32, +-13, -2, -35, -4, 112, -42, 9, -12, +37, -28, 17, 14, -19, 35, -39, 23, +3, -14, -1, -57, -5, 94, -9, 3, +-39, 5, 30, -10, -32, 42, -13, -14, +-97, -63, 30, -9, 1, -7, 12, 5, +20, 17, -9, -36, -30, 25, 47, -9, +-15, 12, -22, 98, -8, -50, 15, -27, +21, -16, -11, 2, 12, -10, 10, -3, +33, 36, -96, 0, -17, 31, -9, 9, +3, -20, 13, -11, 8, -4, 10, -10, +9, 1, 112, -70, -27, 5, -21, 2, +-57, -3, -29, 10, 19, -21, 21, -10, +-66, -3, 91, -35, 30, -12, 0, -7, +59, -28, 26, 2, 14, -18, 1, 1, +11, 17, 20, -54, -59, 27, 4, 29, +32, 5, 19, 12, -4, 1, 7, -10, +5, -2, 10, 0, 23, -5, 28, -104, +46, 11, 16, 3, 29, 1, -8, -14, +1, 7, -50, 88, -62, 26, 8, -17, +-14, 50, 0, 32, -12, -3, -27, 18, +-8, -5, 8, 3, -20, -11, 37, -12, +9, 33, 46, -101, -1, -4, 1, 6, +-1, 28, -42, -15, 16, 5, -1, -2, +-55, 85, 38, -9, -4, 11, -2, -9, +-6, 3, -20, -10, -77, 89, 24, -3, +-104, -57, -26, -31, -20, -6, -9, 14, +20, -23, 46, -15, -31, 28, 1, -15, +-2, 6, -2, 31, 45, -76, 23, -25, }; diff --git a/external/speex/src/high_lsp_tables.c b/external/speex/src/high_lsp_tables.c index 90bea7a..732c8b5 100644 --- a/external/speex/src/high_lsp_tables.c +++ b/external/speex/src/high_lsp_tables.c @@ -1,13 +1,13 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: high_lsp_tables.c Codebooks for high-band LSPs in SB-CELP mode - + 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. + 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 @@ -28,8 +28,8 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -signed char high_lsp_cdbk[512]={ + +const signed char high_lsp_cdbk[512]={ 39,12,-14,-20,-29,-61,-67,-76, -32,-71,-67,68,77,46,34,5, -13,-48,-46,-72,-81,-84,-60,-58, @@ -96,7 +96,7 @@ signed char high_lsp_cdbk[512]={ -42,-74,-48,21,-4,70,52,10}; -signed char high_lsp_cdbk2[512]={ +const signed char high_lsp_cdbk2[512]={ -36,-62,6,-9,-10,-14,-56,23, 1,-26,23,-48,-17,12,8,-7, 23,29,-36,-28,-6,-29,-17,-5, diff --git a/external/speex/src/kiss_fft.c b/external/speex/src/kiss_fft.c new file mode 100644 index 0000000..8dc9345 --- /dev/null +++ b/external/speex/src/kiss_fft.c @@ -0,0 +1,523 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding +Copyright (c) 2005-2007, Jean-Marc Valin + +All rights reserved. + +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 author nor the names of any 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 COPYRIGHT OWNER 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. +*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "_kiss_fft_guts.h" +#include "arch.h" +#include "os_support.h" + +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also declares the kf_ internal functions. + */ + +static void kf_bfly2( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m, + int N, + int mm + ) +{ + kiss_fft_cpx * Fout2; + kiss_fft_cpx * tw1; + kiss_fft_cpx t; + if (!st->inverse) { + int i,j; + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for(j=0;jr , tw1->r),MULT16_16(Fout2->i , tw1->i)), 1); + ti = SHR32(ADD32(MULT16_16(Fout2->i , tw1->r),MULT16_16(Fout2->r , tw1->i)), 1); + tw1 += fstride; + Fout2->r = PSHR32(SUB32(SHL32(EXTEND32(Fout->r), 14), tr), 15); + Fout2->i = PSHR32(SUB32(SHL32(EXTEND32(Fout->i), 14), ti), 15); + Fout->r = PSHR32(ADD32(SHL32(EXTEND32(Fout->r), 14), tr), 15); + Fout->i = PSHR32(ADD32(SHL32(EXTEND32(Fout->i), 14), ti), 15); + ++Fout2; + ++Fout; + } + } + } else { + int i,j; + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for(j=0;jinverse) + { + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for (j=0;jtwiddles; + for (j=0;jr = PSHR16(Fout->r, 2); + Fout->i = PSHR16(Fout->i, 2); + C_SUB( scratch[5] , *Fout, scratch[1] ); + C_ADDTO(*Fout, scratch[1]); + C_ADD( scratch[3] , scratch[0] , scratch[2] ); + C_SUB( scratch[4] , scratch[0] , scratch[2] ); + Fout[m2].r = PSHR16(Fout[m2].r, 2); + Fout[m2].i = PSHR16(Fout[m2].i, 2); + C_SUB( Fout[m2], *Fout, scratch[3] ); + tw1 += fstride; + tw2 += fstride*2; + tw3 += fstride*3; + C_ADDTO( *Fout , scratch[3] ); + + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + ++Fout; + } + } + } +} + +static void kf_bfly3( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + size_t m + ) +{ + size_t k=m; + const size_t m2 = 2*m; + kiss_fft_cpx *tw1,*tw2; + kiss_fft_cpx scratch[5]; + kiss_fft_cpx epi3; + epi3 = st->twiddles[fstride*m]; + + tw1=tw2=st->twiddles; + + do{ + if (!st->inverse) { + C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); + } + + C_MUL(scratch[1],Fout[m] , *tw1); + C_MUL(scratch[2],Fout[m2] , *tw2); + + C_ADD(scratch[3],scratch[1],scratch[2]); + C_SUB(scratch[0],scratch[1],scratch[2]); + tw1 += fstride; + tw2 += fstride*2; + + Fout[m].r = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); + + C_MULBYSCALAR( scratch[0] , epi3.i ); + + C_ADDTO(*Fout,scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + }while(--k); +} + +static void kf_bfly5( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m + ) +{ + kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; + int u; + kiss_fft_cpx scratch[13]; + kiss_fft_cpx * twiddles = st->twiddles; + kiss_fft_cpx *tw; + kiss_fft_cpx ya,yb; + ya = twiddles[fstride*m]; + yb = twiddles[fstride*2*m]; + + Fout0=Fout; + Fout1=Fout0+m; + Fout2=Fout0+2*m; + Fout3=Fout0+3*m; + Fout4=Fout0+4*m; + + tw=st->twiddles; + for ( u=0; uinverse) { + C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5); + } + scratch[0] = *Fout0; + + C_MUL(scratch[1] ,*Fout1, tw[u*fstride]); + C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]); + C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]); + C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]); + + C_ADD( scratch[7],scratch[1],scratch[4]); + C_SUB( scratch[10],scratch[1],scratch[4]); + C_ADD( scratch[8],scratch[2],scratch[3]); + C_SUB( scratch[9],scratch[2],scratch[3]); + + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); + + scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); + scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); + + C_SUB(*Fout1,scratch[5],scratch[6]); + C_ADD(*Fout4,scratch[5],scratch[6]); + + scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); + scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); + + C_ADD(*Fout2,scratch[11],scratch[12]); + C_SUB(*Fout3,scratch[11],scratch[12]); + + ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void kf_bfly_generic( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m, + int p + ) +{ + int u,k,q1,q; + kiss_fft_cpx * twiddles = st->twiddles; + kiss_fft_cpx t; + kiss_fft_cpx scratchbuf[17]; + int Norig = st->nfft; + + /*CHECKBUF(scratchbuf,nscratchbuf,p);*/ + if (p>17) + speex_fatal("KissFFT: max radix supported is 17"); + + for ( u=0; uinverse) { + C_FIXDIV(scratchbuf[q1],p); + } + k += m; + } + + k=u; + for ( q1=0 ; q1

=Norig) twidx-=Norig; + C_MUL(t,scratchbuf[q] , twiddles[twidx] ); + C_ADDTO( Fout[ k ] ,t); + } + k += m; + } + } +} + +static +void kf_shuffle( + kiss_fft_cpx * Fout, + const kiss_fft_cpx * f, + const size_t fstride, + int in_stride, + int * factors, + const kiss_fft_cfg st + ) +{ + const int p=*factors++; /* the radix */ + const int m=*factors++; /* stage's fft length/p */ + + /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/ + if (m==1) + { + int j; + for (j=0;j32000 || (spx_int32_t)p*(spx_int32_t)p > n) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) +{ + kiss_fft_cfg st=NULL; + size_t memneeded = sizeof(struct kiss_fft_state) + + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ + + if ( lenmem==NULL ) { + st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); + }else{ + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_cfg)mem; + *lenmem = memneeded; + } + if (st) { + int i; + st->nfft=nfft; + st->inverse = inverse_fft; +#ifdef FIXED_POINT + for (i=0;iinverse) + phase = -phase; + kf_cexp2(st->twiddles+i, DIV32(SHL32(phase,17),nfft)); + } +#else + for (i=0;iinverse) + phase *= -1; + kf_cexp(st->twiddles+i, phase ); + } +#endif + kf_factor(nfft,st->factors); + } + return st; +} + + + + +void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride) +{ + if (fin == fout) + { + speex_fatal("In-place FFT not supported"); + /*CHECKBUF(tmpbuf,ntmpbuf,st->nfft); + kf_work(tmpbuf,fin,1,in_stride, st->factors,st); + SPEEX_MOVE(fout,tmpbuf,st->nfft);*/ + } else { + kf_shuffle( fout, fin, 1,in_stride, st->factors,st); + kf_work( fout, fin, 1,in_stride, st->factors,st, 1, in_stride, 1); + } +} + +void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) +{ + kiss_fft_stride(cfg,fin,fout,1); +} + diff --git a/external/speex/src/kiss_fft.h b/external/speex/src/kiss_fft.h new file mode 100644 index 0000000..bb19ead --- /dev/null +++ b/external/speex/src/kiss_fft.h @@ -0,0 +1,108 @@ +#ifndef KISS_FFT_H +#define KISS_FFT_H + +#include +#include +#include "arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#ifdef USE_SIMD +# include +# define kiss_fft_scalar __m128 +#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) +#else +#define KISS_FFT_MALLOC speex_alloc +#endif + + +#ifdef FIXED_POINT +#include "arch.h" +# define kiss_fft_scalar spx_int16_t +#else +# ifndef kiss_fft_scalar +/* default is float */ +# define kiss_fft_scalar float +# endif +#endif + +typedef struct { + kiss_fft_scalar r; + kiss_fft_scalar i; +}kiss_fft_cpx; + +typedef struct kiss_fft_state* kiss_fft_cfg; + +/* + * kiss_fft_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth sample. + * */ +void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); + +/* If kiss_fft_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_free speex_free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_cleanup(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/speex/src/kiss_fftr.c b/external/speex/src/kiss_fftr.c new file mode 100644 index 0000000..827e0b1 --- /dev/null +++ b/external/speex/src/kiss_fftr.c @@ -0,0 +1,297 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +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 author nor the names of any 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 COPYRIGHT OWNER 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "os_support.h" +#include "kiss_fftr.h" +#include "_kiss_fft_guts.h" + +struct kiss_fftr_state{ + kiss_fft_cfg substate; + kiss_fft_cpx * tmpbuf; + kiss_fft_cpx * super_twiddles; +#ifdef USE_SIMD + long pad; +#endif +}; + +kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) +{ + int i; + kiss_fftr_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + speex_warning("Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 2); + + if (lenmem == NULL) { + st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ + st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); + +#ifdef FIXED_POINT + for (i=0;i>1); + if (!inverse_fft) + phase = -phase; + kf_cexp2(st->super_twiddles+i, DIV32(SHL32(phase,16),nfft)); + } +#else + for (i=0;isuper_twiddles+i, phase ); + } +#endif + return st; +} + +void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k,ncfft; + kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; + + if ( st->substate->inverse) { + speex_fatal("kiss fft usage error: improper alloc\n"); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag*/ + kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV(tdc,2); + CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); + CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for ( k=1;k <= ncfft/2 ; ++k ) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft-k].r; + fpnk.i = - st->tmpbuf[ncfft-k].i; + C_FIXDIV(fpk,2); + C_FIXDIV(fpnk,2); + + C_ADD( f1k, fpk , fpnk ); + C_SUB( f2k, fpk , fpnk ); + C_MUL( tw , f2k , st->super_twiddles[k]); + + freqdata[k].r = HALF_OF(f1k.r + tw.r); + freqdata[k].i = HALF_OF(f1k.i + tw.i); + freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); + freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); + } +} + +void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata, kiss_fft_scalar *timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + speex_fatal("kiss fft usage error: improper alloc\n"); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + /*C_FIXDIV(st->tmpbuf[0],2);*/ + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_cpx fk, fnkc, fek, fok, tmp; + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + /*C_FIXDIV( fk , 2 ); + C_FIXDIV( fnkc , 2 );*/ + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); +} + +void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k,ncfft; + kiss_fft_cpx f2k,tdc; + spx_word32_t f1kr, f1ki, twr, twi; + + if ( st->substate->inverse) { + speex_fatal("kiss fft usage error: improper alloc\n"); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag*/ + kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV(tdc,2); + CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); + CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); + freqdata[0] = tdc.r + tdc.i; + freqdata[2*ncfft-1] = tdc.r - tdc.i; + + for ( k=1;k <= ncfft/2 ; ++k ) + { + /*fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft-k].r; + fpnk.i = - st->tmpbuf[ncfft-k].i; + C_FIXDIV(fpk,2); + C_FIXDIV(fpnk,2); + + C_ADD( f1k, fpk , fpnk ); + C_SUB( f2k, fpk , fpnk ); + + C_MUL( tw , f2k , st->super_twiddles[k]); + + freqdata[2*k-1] = HALF_OF(f1k.r + tw.r); + freqdata[2*k] = HALF_OF(f1k.i + tw.i); + freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r); + freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i); + */ + + /*f1k.r = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); + f1k.i = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); + f2k.r = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); + f2k.i = SHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); + + C_MUL( tw , f2k , st->super_twiddles[k]); + + freqdata[2*k-1] = HALF_OF(f1k.r + tw.r); + freqdata[2*k] = HALF_OF(f1k.i + tw.i); + freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r); + freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i); + */ + f2k.r = SHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1); + f2k.i = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1); + + f1kr = SHL32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),13); + f1ki = SHL32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),13); + + twr = SHR32(SUB32(MULT16_16(f2k.r,st->super_twiddles[k].r),MULT16_16(f2k.i,st->super_twiddles[k].i)), 1); + twi = SHR32(ADD32(MULT16_16(f2k.i,st->super_twiddles[k].r),MULT16_16(f2k.r,st->super_twiddles[k].i)), 1); + +#ifdef FIXED_POINT + freqdata[2*k-1] = PSHR32(f1kr + twr, 15); + freqdata[2*k] = PSHR32(f1ki + twi, 15); + freqdata[2*(ncfft-k)-1] = PSHR32(f1kr - twr, 15); + freqdata[2*(ncfft-k)] = PSHR32(twi - f1ki, 15); +#else + freqdata[2*k-1] = .5f*(f1kr + twr); + freqdata[2*k] = .5f*(f1ki + twi); + freqdata[2*(ncfft-k)-1] = .5f*(f1kr - twr); + freqdata[2*(ncfft-k)] = .5f*(twi - f1ki); + +#endif + } +} + +void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata,kiss_fft_scalar *timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + speex_fatal ("kiss fft usage error: improper alloc\n"); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0] + freqdata[2*ncfft-1]; + st->tmpbuf[0].i = freqdata[0] - freqdata[2*ncfft-1]; + /*C_FIXDIV(st->tmpbuf[0],2);*/ + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_cpx fk, fnkc, fek, fok, tmp; + fk.r = freqdata[2*k-1]; + fk.i = freqdata[2*k]; + fnkc.r = freqdata[2*(ncfft - k)-1]; + fnkc.i = -freqdata[2*(ncfft - k)]; + /*C_FIXDIV( fk , 2 ); + C_FIXDIV( fnkc , 2 );*/ + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); +} diff --git a/external/speex/src/kiss_fftr.h b/external/speex/src/kiss_fftr.h new file mode 100644 index 0000000..8cfeda1 --- /dev/null +++ b/external/speex/src/kiss_fftr.h @@ -0,0 +1,51 @@ +#ifndef KISS_FTR_H +#define KISS_FTR_H + +#include "kiss_fft.h" +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_state *kiss_fftr_cfg; + + +kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata); + +void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); + +void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata, kiss_fft_scalar *timedata); + +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_free speex_free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/speex/src/lpc.c b/external/speex/src/lpc.c index 9aec141..fca4d9e 100644 --- a/external/speex/src/lpc.c +++ b/external/speex/src/lpc.c @@ -17,25 +17,25 @@ Carsten Bormann - Code slightly modified by Jean-Marc Valin + Code modified by Jean-Marc Valin Speex License: 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 @@ -49,9 +49,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifndef DISABLE_ENCODER -/* LPC- and Reflection Coefficients +#include "lpc.h" + +#ifdef BFIN_ASM +#include "lpc_bfin.h" +#endif + +/* LPC analysis * * The next two functions calculate linear prediction coefficients * and/or the related reflection coefficients from the first P_MAX+1 @@ -61,45 +71,103 @@ /* Invented by N. Levinson in 1947, modified by J. Durbin in 1959. */ -#include "lpc.h" - -float /* returns minimum mean square error */ -wld( - float * lpc, /* [0...p-1] LPC coefficients */ - const float * ac, /* in: [0...p] autocorrelation values */ - float * ref, /* out: [0...p-1] reflection coef's */ - int p - ) +/* returns minimum mean square error */ +spx_word32_t _spx_lpc( +spx_coef_t *lpc, /* out: [0...p-1] LPC coefficients */ +const spx_word16_t *ac, /* in: [0...p] autocorrelation values */ +int p +) { - int i, j; float r, error = ac[0]; - - if (ac[0] == 0) { - for (i = 0; i < p; i++) ref[i] = 0; return 0; } + int i, j; + spx_word16_t r; + spx_word16_t error = ac[0]; for (i = 0; i < p; i++) { - /* Sum up this iteration's reflection coefficient. - */ - r = -ac[i + 1]; - for (j = 0; j < i; j++) r -= lpc[j] * ac[i - j]; - ref[i] = r /= error; - - /* Update LPC coefficients and total error. - */ + /* Sum up this iteration's reflection coefficient */ + spx_word32_t rr = NEG32(SHL32(EXTEND32(ac[i + 1]),13)); + for (j = 0; j < i; j++) + rr = SUB32(rr,MULT16_16(lpc[j],ac[i - j])); +#ifdef FIXED_POINT + r = DIV32_16(rr+PSHR32(error,1),ADD16(error,8)); +#else + r = rr/(error+.003*ac[0]); +#endif + /* Update LPC coefficients and total error */ lpc[i] = r; - for (j = 0; j < i/2; j++) { - float tmp = lpc[j]; - lpc[j] += r * lpc[i-1-j]; - lpc[i-1-j] += r * tmp; + for (j = 0; j < (i+1)>>1; j++) + { + spx_word16_t tmp1, tmp2; + /* It could be that j == i-1-j, in which case, we're updating the same value twice, which is OK */ + tmp1 = lpc[j]; + tmp2 = lpc[i-1-j]; + lpc[j] = MAC16_16_P13(tmp1,r,tmp2); + lpc[i-1-j] = MAC16_16_P13(tmp2,r,tmp1); } - if (i % 2) lpc[j] += lpc[j] * r; - error *= 1.0 - r * r; + error = SUB16(error,MULT16_16_Q13(r,MULT16_16_Q13(error,r))); } return error; } +#ifdef FIXED_POINT + +/* Compute the autocorrelation + * ,--, + * ac(i) = > x(n) * x(n-i) for all n + * `--' + * for lags between 0 and lag-1, and x == 0 outside 0...n-1 + */ + +#ifndef OVERRIDE_SPEEX_AUTOCORR +void _spx_autocorr( +const spx_word16_t *x, /* in: [0...n-1] samples x */ +spx_word16_t *ac, /* out: [0...lag-1] ac values */ +int lag, +int n +) +{ + spx_word32_t d; + int i, j; + spx_word32_t ac0=1; + int shift, ac_shift; + + for (j=0;j x(n) * x(n-i) for all n @@ -107,13 +175,24 @@ wld( * for lags between 0 and lag-1, and x == 0 outside 0...n-1 */ void _spx_autocorr( - const float * x, /* in: [0...n-1] samples x */ - float *ac, /* out: [0...lag-1] ac values */ - int lag, int n) +const spx_word16_t *x, /* in: [0...n-1] samples x */ +float *ac, /* out: [0...lag-1] ac values */ +int lag, +int n +) { - float d; int i; - while (lag--) { - for (i = lag, d = 0; i < n; i++) d += x[i] * x[i-lag]; + float d; + int i; + while (lag--) + { + for (i = lag, d = 0; i < n; i++) + d += x[i] * x[i-lag]; ac[lag] = d; } + ac[0] += 10; } + +#endif + + +#endif /* DISABLE_ENCODER */ diff --git a/external/speex/src/lpc.h b/external/speex/src/lpc.h index e3f70b5..8885471 100644 --- a/external/speex/src/lpc.h +++ b/external/speex/src/lpc.h @@ -1,22 +1,24 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: lpc.h - Functions for LPC (Linear Prediction Coefficients) analysis - +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file lpc.h + @brief Functions for LPC (Linear Prediction Coefficients) analysis +*/ +/* 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 @@ -33,16 +35,17 @@ #ifndef LPC_H #define LPC_H +#include "arch.h" + void _spx_autocorr( - const float * x, /* in: [0...n-1] samples x */ - float *ac, /* out: [0...lag-1] ac values */ + const spx_word16_t * x, /* in: [0...n-1] samples x */ + spx_word16_t *ac, /* out: [0...lag-1] ac values */ int lag, int n); -float /* returns minimum mean square error */ -wld( - float * lpc, /* [0...p-1] LPC coefficients */ - const float * ac, /* in: [0...p] autocorrelation values */ - float * ref, /* out: [0...p-1] reflection coef's */ +spx_word32_t /* returns minimum mean square error */ +_spx_lpc( + spx_coef_t * lpc, /* [0...p-1] LPC coefficients */ + const spx_word16_t * ac, /* in: [0...p] autocorrelation values */ int p ); diff --git a/external/speex/src/lpc_bfin.h b/external/speex/src/lpc_bfin.h new file mode 100644 index 0000000..d2e0406 --- /dev/null +++ b/external/speex/src/lpc_bfin.h @@ -0,0 +1,134 @@ +/* Copyright (C) 2005 Analog Devices */ +/** + @file lpc_bfin.h + @author Jean-Marc Valin + @brief Functions for LPC (Linear Prediction Coefficients) analysis (Blackfin 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 "bfin.h" + +#define OVERRIDE_SPEEX_AUTOCORR +void _spx_autocorr( +const spx_word16_t *x, /* in: [0...n-1] samples x */ +spx_word16_t *ac, /* out: [0...lag-1] ac values */ +int lag, +int n + ) +{ + spx_word32_t d; + const spx_word16_t *xs; + int i, j; + spx_word32_t ac0=1; + spx_word32_t ac32[11], *ac32top; + int shift, ac_shift; + ac32top = ac32+lag-1; + int lag_1, N_lag; + int nshift; + lag_1 = lag-1; + N_lag = n-lag_1; + for (j=0;j> 1;\n\t" + "LOOP_BEGIN pitch%=;\n\t" + "I1 = P0;\n\t" + "A1 = A0 = 0;\n\t" + "R1 = [I1++];\n\t" + "LOOP inner_prod%= LC1 = P3 >> 1;\n\t" + "LOOP_BEGIN inner_prod%=;\n\t" + "A1 += R0.L*R1.H, A0 += R0.L*R1.L (IS) || R1.L = W[I1++];\n\t" + "A1 += R0.H*R1.L, A0 += R0.H*R1.H (IS) || R1.H = W[I1++] || R0 = [I0++];\n\t" + "LOOP_END inner_prod%=;\n\t" + "A0 = ASHIFT A0 by R4.L;\n\t" + "A1 = ASHIFT A1 by R4.L;\n\t" + + "R2 = A0, R3 = A1;\n\t" + "[P1--] = R2;\n\t" + "[P1--] = R3;\n\t" + "P0 += 4;\n\t" + "LOOP_END pitch%=;\n\t" + : : "m" (xs), "m" (x), "m" (ac32top), "m" (N_lag), "m" (lag_1), "m" (nshift) + : "A0", "A1", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "R3", "R4", "I0", "I1", "L0", "L1", "B0", "B1", "memory", + "ASTAT" BFIN_HWLOOP0_REGS BFIN_HWLOOP1_REGS + ); + d=0; + for (j=0;j #include "lsp.h" #include "stack_alloc.h" - +#include "math_approx.h" #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ @@ -56,63 +96,128 @@ Modified by Jean-Marc Valin #define NULL 0 #endif +#ifdef FIXED_POINT + +#define FREQ_SCALE 16384 + +/*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/ +#define ANGLE2X(a) (SHL16(spx_cos(a),2)) + +/*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/ +#define X2ANGLE(x) (spx_acos(x)) + +#ifdef BFIN_ASM +#include "lsp_bfin.h" +#endif + +#else + +/*#define C1 0.99940307 +#define C2 -0.49558072 +#define C3 0.03679168*/ + +#define FREQ_SCALE 1. +#define ANGLE2X(a) (spx_cos(a)) +#define X2ANGLE(x) (acos(x)) + +#endif + +#ifndef DISABLE_ENCODER + /*---------------------------------------------------------------------------*\ - FUNCTION....: cheb_poly_eva() + FUNCTION....: cheb_poly_eva() - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 + AUTHOR......: David Rowe + DATE CREATED: 24/2/93 - This function evaluates a series of Chebyshev polynomials + This function evaluates a series of Chebyshev polynomials \*---------------------------------------------------------------------------*/ +#ifdef FIXED_POINT - -static float cheb_poly_eva(float *coef,float x,int m,char *stack) -/* float coef[] coefficients of the polynomial to be evaluated */ -/* float x the point where polynomial is to be evaluated */ -/* int m order of the polynomial */ +#ifndef OVERRIDE_CHEB_POLY_EVA +static inline spx_word32_t cheb_poly_eva( + spx_word16_t *coef, /* P or Q coefs in Q13 format */ + spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */ + int m, /* LPC order/2 */ + char *stack +) { int i; - float *T,sum; - int m2=m>>1; + spx_word16_t b0, b1; + spx_word32_t sum; - /* Allocate memory for Chebyshev series formulation */ - T=PUSH(stack, m2+1, float); + /*Prevents overflows*/ + if (x>16383) + x = 16383; + if (x<-16383) + x = -16383; /* Initialise values */ - T[0]=1; - T[1]=x; + b1=16384; + b0=x; - /* Evaluate Chebyshev series formulation using iterative approach */ - /* Evaluate polynomial and return value also free memory space */ - sum = coef[m2] + coef[m2-1]*x; - x *= 2; - for(i=2;i<=m2;i++) + /* Evaluate Chebyshev series formulation using an iterative approach */ + sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x))); + for(i=2;i<=m;i++) { - T[i] = x*T[i-1] - T[i-2]; - sum += coef[m2-i] * T[i]; + spx_word16_t tmp=b0; + b0 = SUB16(MULT16_16_Q13(x,b0), b1); + b1 = tmp; + sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0))); } - + return sum; } +#endif +#else + +static float cheb_poly_eva(spx_word32_t *coef, spx_word16_t x, int m, char *stack) +{ + int k; + float b0, b1, tmp; + + /* Initial conditions */ + b0=0; /* b_(m+1) */ + b1=0; /* b_(m+2) */ + + x*=2; + + /* Calculate the b_(k) */ + for(k=m;k>0;k--) + { + tmp=b0; /* tmp holds the previous value of b0 */ + b0=x*b0-b1+coef[m-k]; /* b0 holds its new value based on b0 and b1 */ + b1=tmp; /* b1 holds the previous value of b0 */ + } + + return(-b1+.5*x*b0+coef[m]); +} +#endif /*---------------------------------------------------------------------------*\ - FUNCTION....: lpc_to_lsp() + FUNCTION....: lpc_to_lsp() - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 + AUTHOR......: David Rowe + DATE CREATED: 24/2/93 This function converts LPC coefficients to LSP coefficients. \*---------------------------------------------------------------------------*/ +#ifdef FIXED_POINT +#define SIGN_CHANGE(a,b) ((((a)^(b))&0x80000000)||(b==0)) +#else +#define SIGN_CHANGE(a,b) (((a)*(b))<0.0) +#endif -int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) + +int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack) /* float *a lpc coefficients */ /* int lpcrdr order of LPC coefficients (10) */ /* float *freq LSP frequencies in the x domain */ @@ -121,27 +226,25 @@ int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) { - - float psuml,psumr,psumm,temp_xr,xl,xr,xm=0; - float temp_psumr/*,temp_qsumr*/; - int i,j,m,flag,k; - float *Q; /* ptrs for memory allocation */ - float *P; - float *px; /* ptrs of respective P'(z) & Q'(z) */ - float *qx; - float *p; - float *q; - float *pt; /* ptr used for cheb_poly_eval() + spx_word16_t temp_xr,xl,xr,xm=0; + spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/; + int i,j,m,k; + VARDECL(spx_word32_t *Q); /* ptrs for memory allocation */ + VARDECL(spx_word32_t *P); + VARDECL(spx_word16_t *Q16); /* ptrs for memory allocation */ + VARDECL(spx_word16_t *P16); + spx_word32_t *px; /* ptrs of respective P'(z) & Q'(z) */ + spx_word32_t *qx; + spx_word32_t *p; + spx_word32_t *q; + spx_word16_t *pt; /* ptr used for cheb_poly_eval() whether P' or Q' */ int roots=0; /* DR 8/2/94: number of roots found */ - flag = 1; /* program is searching for a root when, - 1 else has found one */ m = lpcrdr/2; /* order of P'(z) & Q'(z) polynomials */ - /* Allocate memory space for polynomials */ - Q = PUSH(stack, (m+1), float); - P = PUSH(stack, (m+1), float); + ALLOC(Q, (m+1), spx_word32_t); + ALLOC(P, (m+1), spx_word32_t); /* determine P'(z)'s and Q'(z)'s coefficients where P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */ @@ -150,47 +253,90 @@ int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) qx = Q; p = px; q = qx; - *px++ = 1.0; - *qx++ = 1.0; - for(i=1;i<=m;i++){ - *px++ = a[i]+a[lpcrdr+1-i]-*p++; - *qx++ = a[i]-a[lpcrdr+1-i]+*q++; + +#ifdef FIXED_POINT + *px++ = LPC_SCALING; + *qx++ = LPC_SCALING; + for(i=0;i=32768) + speex_warning_int("px", *px); + if (fabs(*qx)>=32768) + speex_warning_int("qx", *qx);*/ + *px = PSHR32(*px,2); + *qx = PSHR32(*qx,2); + px++; + qx++; + } + /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */ + P[m] = PSHR32(P[m],3); + Q[m] = PSHR32(Q[m],3); +#else + *px++ = LPC_SCALING; + *qx++ = LPC_SCALING; + for(i=0;i= -1.0)){ - float dd; + psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl */ + + while(xr >= -FREQ_SCALE){ + spx_word16_t dd; /* Modified by JMV to provide smaller steps around x=+-1 */ - dd=(delta*(1-.9*xl*xl)); +#ifdef FIXED_POINT + dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000))); + if (psuml<512 && psuml>-512) + dd = PSHR16(dd,1); +#else + dd=delta*(1-.9*xl*xl); if (fabs(psuml)<.2) dd *= .5; - - xr = xl - dd; /* interval spacing */ - psumr = cheb_poly_eva(pt,xr,lpcrdr,stack);/* poly(xl-delta_x) */ +#endif + xr = SUB16(xl, dd); /* interval spacing */ + psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x) */ temp_psumr = psumr; temp_xr = xr; @@ -203,27 +349,33 @@ int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) between xm and xr else set interval between xl and xr and repeat till root is located within the specified limits */ - if((psumr*psuml)<0.0){ + if(SIGN_CHANGE(psumr,psuml)) + { roots++; psumm=psuml; for(k=0;k<=nb;k++){ - xm = (xl+xr)/2; /* bisect the interval */ - psumm=cheb_poly_eva(pt,xm,lpcrdr,stack); - if(psumm*psuml>0.){ +#ifdef FIXED_POINT + xm = ADD16(PSHR16(xl,1),PSHR16(xr,1)); /* bisect the interval */ +#else + xm = .5*(xl+xr); /* bisect the interval */ +#endif + psumm=cheb_poly_eva(pt,xm,m,stack); + /*if(psumm*psuml>0.)*/ + if(!SIGN_CHANGE(psumm,psuml)) + { psuml=psumm; xl=xm; - } - else{ + } else { psumr=psumm; xr=xm; } } /* once zero is found, reset initial interval to xr */ - freq[j] = (xm); + freq[j] = X2ANGLE(xm); xl = xm; - flag = 0; /* reset flag for next search */ + break; } else{ psuml=temp_psumr; @@ -234,7 +386,7 @@ int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) return(roots); } - +#endif /* DISABLE_ENCODER */ /*---------------------------------------------------------------------------*\ FUNCTION....: lsp_to_lpc() @@ -242,13 +394,132 @@ int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) AUTHOR......: David Rowe DATE CREATED: 24/2/93 - lsp_to_lpc: This function converts LSP coefficients to LPC - coefficients. + Converts LSP coefficients to LPC coefficients. \*---------------------------------------------------------------------------*/ +#ifdef FIXED_POINT -void lsp_to_lpc(float *freq,float *ak,int lpcrdr, char *stack) +void lsp_to_lpc(const spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack) +/* float *freq array of LSP frequencies in the x domain */ +/* float *ak array of LPC coefficients */ +/* int lpcrdr order of LPC coefficients */ +{ + int i,j; + spx_word32_t xout1,xout2,xin; + spx_word32_t mult, a; + VARDECL(spx_word16_t *freqn); + VARDECL(spx_word32_t **xp); + VARDECL(spx_word32_t *xpmem); + VARDECL(spx_word32_t **xq); + VARDECL(spx_word32_t *xqmem); + int m = lpcrdr>>1; + + /* + + Reconstruct P(z) and Q(z) by cascading second order polynomials + in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency. + In the time domain this is: + + y(n) = x(n) - 2cos(w)x(n-1) + x(n-2) + + This is what the ALLOCS below are trying to do: + + int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP + int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP + + These matrices store the output of each stage on each row. The + final (m-th) row has the output of the final (m-th) cascaded + 2nd order filter. The first row is the impulse input to the + system (not written as it is known). + + The version below takes advantage of the fact that a lot of the + outputs are zero or known, for example if we put an inpulse + into the first section the "clock" it 10 times only the first 3 + outputs samples are non-zero (it's an FIR filter). + */ + + ALLOC(xp, (m+1), spx_word32_t*); + ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t); + + ALLOC(xq, (m+1), spx_word32_t*); + ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t); + + for(i=0; i<=m; i++) { + xp[i] = xpmem + i*(lpcrdr+1+2); + xq[i] = xqmem + i*(lpcrdr+1+2); + } + + /* work out 2cos terms in Q14 */ + + ALLOC(freqn, lpcrdr, spx_word16_t); + for (i=0;i 32767) a = 32767; + ak[j-1] = (short)a; + + } + +} + +#else + +void lsp_to_lpc(const spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack) /* float *freq array of LSP frequencies in the x domain */ /* float *ak array of LPC coefficients */ /* int lpcrdr order of LPC coefficients */ @@ -257,11 +528,12 @@ void lsp_to_lpc(float *freq,float *ak,int lpcrdr, char *stack) { int i,j; float xout1,xout2,xin1,xin2; - float *Wp; + VARDECL(float *Wp); float *pw,*n1,*n2,*n3,*n4=NULL; - int m = lpcrdr/2; + VARDECL(float *x_freq); + int m = lpcrdr>>1; - Wp = PUSH(stack, 4*m+2, float); + ALLOC(Wp, 4*m+2, float); pw = Wp; /* initialise contents of array */ @@ -276,6 +548,10 @@ void lsp_to_lpc(float *freq,float *ak,int lpcrdr, char *stack) xin1 = 1.0; xin2 = 1.0; + ALLOC(x_freq, lpcrdr, float); + for (i=0;i0) + ak[j-1] = (xout1 + xout2)*0.5f; *(n4+1) = xin1; *(n4+2) = xin2; @@ -307,22 +584,58 @@ void lsp_to_lpc(float *freq,float *ak,int lpcrdr, char *stack) } } +#endif -/*Added by JMV - Makes sure the LSPs are stable*/ -void lsp_enforce_margin(float *lsp, int len, float margin) + +#ifdef FIXED_POINT + + +void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *lsp, int len, int subframe, int nb_subframes, spx_word16_t margin) { int i; - if (lsp[0]M_PI-margin) - lsp[len-1]=M_PI-margin; + spx_word16_t m = margin; + spx_word16_t m2 = 25736-margin; + spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); + spx_word16_t tmp2 = 16384-tmp; + for (i=0;im2) + lsp[len-1]=m2; for (i=1;ilsp[i+1]-margin) - lsp[i]= .5* (lsp[i] + lsp[i+1]-margin); + if (lsp[i]>lsp[i+1]-m) + lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); } } + +#else + + +void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *lsp, int len, int subframe, int nb_subframes, spx_word16_t margin) +{ + int i; + float tmp = (1.0f + subframe)/nb_subframes; + for (i=0;iLSP_SCALING*(M_PI-margin)) + lsp[len-1]=LSP_SCALING*(M_PI-margin); + for (i=1;ilsp[i+1]-LSP_SCALING*margin) + lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin); + } +} + +#endif diff --git a/external/speex/src/lsp.h b/external/speex/src/lsp.h index 2540495..fed49bc 100644 --- a/external/speex/src/lsp.h +++ b/external/speex/src/lsp.h @@ -14,23 +14,27 @@ Modified by Jean-Marc Valin unit circle. \*---------------------------------------------------------------------------*/ +/** + @file lsp.h + @brief Line Spectral Pair (LSP) functions. +*/ /* Speex License: 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 @@ -47,11 +51,12 @@ Modified by Jean-Marc Valin #ifndef __AK2LSPD__ #define __AK2LSPD__ -int lpc_to_lsp (float *a, int lpcrdr, float *freq, int nb, float delta, char *stack); -void lsp_to_lpc(float *freq, float *ak, int lpcrdr, char *stack); +#include "arch.h" + +int lpc_to_lsp (spx_coef_t *a, int lpcrdr, spx_lsp_t *freq, int nb, spx_word16_t delta, char *stack); +void lsp_to_lpc(const spx_lsp_t *freq, spx_coef_t *ak, int lpcrdr, char *stack); /*Added by JMV*/ -void lsp_enforce_margin(float *lsp, int len, float margin); - +void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes, spx_word16_t margin); #endif /* __AK2LSPD__ */ diff --git a/external/speex/src/lsp_bfin.h b/external/speex/src/lsp_bfin.h new file mode 100644 index 0000000..4f91d52 --- /dev/null +++ b/external/speex/src/lsp_bfin.h @@ -0,0 +1,89 @@ +/* Copyright (C) 2006 David Rowe */ +/** + @file lsp_bfin.h + @author David Rowe + @brief LSP routines optimised for the Blackfin +*/ +/* + 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. +*/ + +#define OVERRIDE_CHEB_POLY_EVA +#ifdef OVERRIDE_CHEB_POLY_EVA +static inline spx_word32_t cheb_poly_eva( + spx_word16_t *coef, /* P or Q coefs in Q13 format */ + spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */ + int m, /* LPC order/2 */ + char *stack +) +{ + spx_word32_t sum; + + __asm__ __volatile__ + ( + "P0 = %2;\n\t" /* P0: coef[m], coef[m-1],..., coef[0] */ + "R4 = 8192;\n\t" /* R4: rounding constant */ + "R2 = %1;\n\t" /* R2: x */ + + "R5 = -16383;\n\t" + "R2 = MAX(R2,R5);\n\t" + "R5 = 16383;\n\t" + "R2 = MIN(R2,R5);\n\t" + + "R3 = W[P0--] (X);\n\t" /* R3: sum */ + "R5 = W[P0--] (X);\n\t" + "R5 = R5.L * R2.L (IS);\n\t" + "R5 = R5 + R4;\n\t" + "R5 >>>= 14;\n\t" + "R3 = R3 + R5;\n\t" + + "R0 = R2;\n\t" /* R0: b0 */ + "R1 = 16384;\n\t" /* R1: b1 */ + "LOOP cpe%= LC0 = %3;\n\t" + "LOOP_BEGIN cpe%=;\n\t" + "P1 = R0;\n\t" + "R0 = R2.L * R0.L (IS) || R5 = W[P0--] (X);\n\t" + "R0 >>>= 13;\n\t" + "R0 = R0 - R1;\n\t" + "R1 = P1;\n\t" + "R5 = R5.L * R0.L (IS);\n\t" + "R5 = R5 + R4;\n\t" + "R5 >>>= 14;\n\t" + "R3 = R3 + R5;\n\t" + "LOOP_END cpe%=;\n\t" + "%0 = R3;\n\t" + : "=&d" (sum) + : "a" (x), "a" (&coef[m]), "a" (m-1) + : "R0", "R1", "R3", "R2", "R4", "R5", "P0", "P1", "ASTAT" BFIN_HWLOOP0_REGS + ); + return sum; +} +#endif + + + diff --git a/external/speex/src/lsp_tables_nb.c b/external/speex/src/lsp_tables_nb.c index a68ce99..8015b9a 100644 --- a/external/speex/src/lsp_tables_nb.c +++ b/external/speex/src/lsp_tables_nb.c @@ -1,13 +1,13 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: lsp_tables_nb.c Codebooks for LSPs in narrowband CELP mode - + 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. + 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 @@ -29,7 +29,7 @@ POSSIBILITY OF SUCH DAMAGE. */ -signed char cdbk_nb[640]={ +const signed char cdbk_nb[640]={ 30,19,38,34,40,32,46,43,58,43, 5,-18,-25,-40,-33,-55,-52,20,34,28, -20,-63,-97,-92,61,53,47,49,53,75, @@ -95,7 +95,7 @@ signed char cdbk_nb[640]={ -6,-41,-67,6,-2,-9,19,2,85,74, -22,-67,-84,-71,-50,3,11,-9,2,62}; -signed char cdbk_nb_low1[320]={ +const signed char cdbk_nb_low1[320]={ -34,-52,-15,45,2, 23,21,52,24,-33, -9,-1,9,-44,-41, @@ -161,7 +161,7 @@ signed char cdbk_nb_low1[320]={ 13,20,20,-19,-22, -2,-8,2,51,-51}; -signed char cdbk_nb_low2[320]={ +const signed char cdbk_nb_low2[320]={ -6,53,-21,-24,4, 26,17,-4,-37,25, 17,-36,-13,31,3, @@ -227,7 +227,7 @@ signed char cdbk_nb_low2[320]={ -23,-29,-16,1,-3, -8,-10,31,64,-65}; -signed char cdbk_nb_high1[320]={ +const signed char cdbk_nb_high1[320]={ -26,-8,29,21,4, 19,-39,33,-7,-36, 56,54,48,40,29, @@ -293,7 +293,7 @@ signed char cdbk_nb_high1[320]={ 29,17,8,-29,-39, -69,18,15,-15,-5}; -signed char cdbk_nb_high2[320]={ +const signed char cdbk_nb_high2[320]={ 11,47,16,-9,-46, -32,26,-64,34,-5, 38,-7,47,20,2, diff --git a/external/speex/src/ltp.c b/external/speex/src/ltp.c index 90142bd..347a9db 100644 --- a/external/speex/src/ltp.c +++ b/external/speex/src/ltp.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002-2006 Jean-Marc Valin File: ltp.c Long-Term Prediction functions 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 @@ -30,195 +30,430 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "ltp.h" #include "stack_alloc.h" #include "filters.h" -#include "speex_bits.h" +#include "math_approx.h" +#include "os_support.h" + +#ifndef NULL +#define NULL 0 +#endif + #ifdef _USE_SSE #include "ltp_sse.h" -#else -static float inner_prod(float *x, float *y, int len) +#elif defined (ARM4_ASM) || defined(ARM5E_ASM) +#include "ltp_arm4.h" +#elif defined (BFIN_ASM) +#include "ltp_bfin.h" +#endif + +#ifndef OVERRIDE_INNER_PROD +spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) { - int i; - float sum1=0,sum2=0,sum3=0,sum4=0; - for (i=0;i>= 2; + while(len--) { - sum1 += x[i]*y[i]; - sum2 += x[i+1]*y[i+1]; - sum3 += x[i+2]*y[i+2]; - sum4 += x[i+3]*y[i+3]; - i+=4; + spx_word32_t part=0; + part = MAC16_16(part,*x++,*y++); + part = MAC16_16(part,*x++,*y++); + 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 sum1+sum2+sum3+sum4; + return sum; } #endif -/*Original, non-optimized version*/ -/*static float inner_prod(float *x, float *y, int len) +#ifndef DISABLE_ENCODER + +#ifndef OVERRIDE_PITCH_XCORR +#if 0 /* HINT: Enable this for machines with enough registers (i.e. not x86) */ +static void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) +{ + int i,j; + for (i=0;ibest_score[N-1]) + if (ABS16(sw[i])>16383) { - float g1, g; - g1 = corr[i-start]/(energy[i-start]+10); - g = sqrt(g1*corr[i-start]/(e0+10)); - if (g>g1) - g=g1; - if (g<0) - g=0; - for (j=0;jMULT16_16(best_score[N-1],ADD16(1,ener16[i-start]))) + { + /* We can safely put it last and then check */ + best_score[N-1]=tmp; + best_ener[N-1]=ener16[i-start]+1; + pitch[N-1]=i; + /* Check if it comes in front of others */ + for (j=0;j best_score[j]) + if (MULT16_16(tmp,best_ener[j])>MULT16_16(best_score[j],ADD16(1,ener16[i-start]))) { for (k=N-1;k>j;k--) { best_score[k]=best_score[k-1]; + best_ener[k]=best_ener[k-1]; pitch[k]=pitch[k-1]; - gain[k] = gain[k-1]; } - best_score[j]=score[i-start]; + best_score[j]=tmp; + best_ener[j]=ener16[i-start]+1; pitch[j]=i; - gain[j]=g; break; } } } } + /* Compute open-loop gain if necessary */ + if (gain) + { + for (j=0;jbest_sum && gain_sum<=max_gain) { + best_sum=sum; + best_cdbk=i; + } + } + + return best_cdbk; +} +#endif /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ -float pitch_gain_search_3tap( -float target[], /* Target vector */ -float ak[], /* LPCs for this subframe */ -float awk1[], /* Weighted LPCs #1 for this subframe */ -float awk2[], /* Weighted LPCs #2 for this subframe */ -float exc[], /* Excitation */ -void *par, +static spx_word32_t pitch_gain_search_3tap( +const spx_word16_t target[], /* Target vector */ +const spx_coef_t ak[], /* LPCs for this subframe */ +const spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ +const spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ +spx_sig_t exc[], /* Excitation */ +const signed char *gain_cdbk, +int gain_cdbk_size, int pitch, /* Pitch value */ int p, /* Number of LPC coeffs */ int nsf, /* Number of samples in subframe */ SpeexBits *bits, char *stack, -float *exc2, -float *r, -int *cdbk_index +const spx_word16_t *exc2, +const spx_word16_t *r, +spx_word16_t *new_target, +int *cdbk_index, +int plc_tuning, +spx_word32_t cumul_gain, +int scaledown ) { int i,j; - float *tmp, *tmp2; - float *x[3]; - float *e[3]; - float corr[3]; - float A[3][3]; - float gain[3]; - int gain_cdbk_size; - signed char *gain_cdbk; - float err1,err2; + VARDECL(spx_word16_t *tmp1); + VARDECL(spx_word16_t *e); + spx_word16_t *x[3]; + spx_word32_t corr[3]; + spx_word32_t A[3][3]; + spx_word16_t gain[3]; + spx_word32_t err; + spx_word16_t max_gain=128; + int best_cdbk=0; - ltp_params *params; - params = (ltp_params*) par; - gain_cdbk=params->gain_cdbk; - gain_cdbk_size=1<gain_bits; - tmp = PUSH(stack, 3*nsf, float); - tmp2 = PUSH(stack, 3*nsf, float); + ALLOC(tmp1, 3*nsf, spx_word16_t); + ALLOC(e, nsf, spx_word16_t); - x[0]=tmp; - x[1]=tmp+nsf; - x[2]=tmp+2*nsf; + if (cumul_gain > 262144) + max_gain = 31; + + x[0]=tmp1; + x[1]=tmp1+nsf; + x[2]=tmp1+2*nsf; + + for (j=0;j=0;i--) { - int pp=pitch+1-i; - for (j=0;j0) + bound = pp; + for (j=0;j0) + bound = pp+pitch; + for (;j=0;i--) + { + spx_word16_t e0=exc2[-pitch-1+i]; +#ifdef FIXED_POINT + /* Scale excitation down if needed (avoiding overflow) */ + if (scaledown) + e0 = SHR16(e0,1); +#endif + x[i][0]=MULT16_16_Q14(r[0], e0); + for (j=0;j30) + plc_tuning=30; +#ifdef FIXED_POINT + C[0] = SHL32(C[0],1); + C[1] = SHL32(C[1],1); + C[2] = SHL32(C[2],1); + C[3] = SHL32(C[3],1); + C[4] = SHL32(C[4],1); + C[5] = SHL32(C[5],1); + C[6] = MAC16_32_Q15(C[6],MULT16_16_16(plc_tuning,655),C[6]); + C[7] = MAC16_32_Q15(C[7],MULT16_16_16(plc_tuning,655),C[7]); + C[8] = MAC16_32_Q15(C[8],MULT16_16_16(plc_tuning,655),C[8]); + normalize16(C, C16, 32767, 9); +#else + C[6]*=.5*(1+.02*plc_tuning); + C[7]*=.5*(1+.02*plc_tuning); + C[8]*=.5*(1+.02*plc_tuning); +#endif - /* If 1, force "safe" pitch values to handle packet loss better */ - if (0) { - float tot = fabs((float)ptr[1]); - if (ptr[0]>0) - tot+=ptr[0]; - if (ptr[2]>0) - tot+=ptr[2]; - if (tot>1) - continue; - } - - if (sum>best_sum || i==0) - { - best_sum=sum; - best_cdbk=i; - } - } - gain[0] = 0.015625*gain_cdbk[best_cdbk*3] + .5; - gain[1] = 0.015625*gain_cdbk[best_cdbk*3+1]+ .5; - gain[2] = 0.015625*gain_cdbk[best_cdbk*3+2]+ .5; + best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain); +#ifdef FIXED_POINT + gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4]); + gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+1]); + gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+2]); + /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/ +#else + gain[0] = 0.015625*gain_cdbk[best_cdbk*4] + .5; + gain[1] = 0.015625*gain_cdbk[best_cdbk*4+1]+ .5; + gain[2] = 0.015625*gain_cdbk[best_cdbk*4+2]+ .5; +#endif *cdbk_index=best_cdbk; } - - for (i=0;ipp) + tmp1=pp; + for (j=0;jpp+pitch) + tmp3=pp+pitch; + for (j=tmp1;jgain_bits; + gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset; N=complexity; if (N>10) N=10; + if (N<1) + N=1; - nbest=PUSH(stack, N, int); - gains = PUSH(stack, N, float); - params = (ltp_params*) par; + ALLOC(nbest, N, int); + params = (const ltp_params*) par; - if (N==0 || endpitch_bits); speex_bits_pack(bits, 0, params->gain_bits); - for (i=0;i16383) + { + scaledown=1; + break; + } + } + for (i=-end;i<0;i++) + { + if (ABS16(exc2[i])>16383) + { + scaledown=1; + break; + } + } +#endif if (N>end-start+1) N=end-start+1; - open_loop_nbest_pitch(sw, start, end, nsf, nbest, gains, N, stack); + if (end != start) + open_loop_nbest_pitch(sw, start, end, nsf, nbest, NULL, N, stack); + else + nbest[0] = start; + + ALLOC(best_exc, nsf, spx_sig_t); + ALLOC(new_target, nsf, spx_word16_t); + ALLOC(best_target, nsf, spx_word16_t); + for (i=0;ipitch_bits); speex_bits_pack(bits, best_gain_index, params->gain_bits); +#ifdef FIXED_POINT + *cumul_gain = MULT16_32_Q13(SHL16(params->gain_cdbk[4*best_gain_index+3],8), MAX32(1024,*cumul_gain)); +#else + *cumul_gain = 0.03125*MAX32(1024,*cumul_gain)*params->gain_cdbk[4*best_gain_index+3]; +#endif + /*printf ("%f\n", cumul_gain);*/ /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/ - for (i=0;igain_cdbk; + spx_word16_t gain[3]; + const signed char *gain_cdbk; + int gain_cdbk_size; + const ltp_params *params; + + params = (const ltp_params*) par; + gain_cdbk_size = 1<gain_bits; + gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset; pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits); pitch += start; gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits); /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/ - gain[0] = 0.015625*gain_cdbk[gain_index*3]+.5; - gain[1] = 0.015625*gain_cdbk[gain_index*3+1]+.5; - gain[2] = 0.015625*gain_cdbk[gain_index*3+2]+.5; +#ifdef FIXED_POINT + gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4]); + gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+1]); + gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+2]); +#else + gain[0] = 0.015625*gain_cdbk[gain_index*4]+.5; + gain[1] = 0.015625*gain_cdbk[gain_index*4+1]+.5; + gain[2] = 0.015625*gain_cdbk[gain_index*4+2]+.5; +#endif if (count_lost && pitch > subframe_offset) { - float gain_sum; - + spx_word16_t gain_sum; if (1) { - float tmp = count_lost < 4 ? last_pitch_gain : 0.4 * last_pitch_gain; +#ifdef FIXED_POINT + spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain,1); + if (tmp>62) + tmp=62; +#else + spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain; if (tmp>.95) tmp=.95; - gain_sum = fabs(gain[1]); - if (gain[0]>0) - gain_sum += gain[0]; - else - gain_sum -= .5*gain[0]; - if (gain[2]>0) - gain_sum += gain[2]; - else - gain_sum -= .5*gain[2]; - if (gain_sum > tmp) { - float fact = tmp/gain_sum; - for (i=0;i<3;i++) - gain[i]*=fact; +#endif + gain_sum = gain_3tap_to_1tap(gain); - } + if (gain_sum > tmp) + { + spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp),14),gain_sum); + for (i=0;i<3;i++) + gain[i]=MULT16_16_Q14(fact,gain[i]); + } } - if (0) { - gain_sum = fabs(gain[0])+fabs(gain[1])+fabs(gain[2]); - if (gain_sum>.95) { - float fact = .95/gain_sum; - for (i=0;i<3;i++) - gain[i]*=fact; - } - } } *pitch_val = pitch; - /**gain_val = gain[0]+gain[1]+gain[2];*/ gain_val[0]=gain[0]; gain_val[1]=gain[1]; gain_val[2]=gain[2]; - + gain[0] = SHL16(gain[0],7); + gain[1] = SHL16(gain[1],7); + gain[2] = SHL16(gain[2],7); + SPEEX_MEMSET(exc_out, 0, nsf); + for (i=0;i<3;i++) { - float *e[3]; - float *tmp2; - tmp2=PUSH(stack, 3*nsf, float); - e[0]=tmp2; - e[1]=tmp2+nsf; - e[2]=tmp2+2*nsf; - - for (i=0;i<3;i++) - { - int j; - int pp=pitch+1-i; -#if 0 - for (j=0;jpp) - tmp1=pp; - for (j=0;jpp+pitch) - tmp3=pp+pitch; - for (j=tmp1;jpp) + tmp1=pp; + for (j=0;jpp+pitch) + tmp3=pp+pitch; + for (j=tmp1;j63) + pitch_coef=63; +#else if (pitch_coef>.99) pitch_coef=.99; - for (i=0;i63) + pitch_coef=63; +#else if (pitch_coef>.99) pitch_coef=.99; +#endif for (i=0;i0 ? g[0] : -SHR16(g[0],1)) + (g[2]>0 ? g[2] : -SHR16(g[2],1))) +#else +#define gain_3tap_to_1tap(g) (ABS(g[1]) + (g[0]>0 ? g[0] : -.5*g[0]) + (g[2]>0 ? g[2] : -.5*g[2])) +#endif -void open_loop_nbest_pitch(float *sw, int start, int end, int len, int *pitch, float *gain, int N, char *stack); +spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len); + +void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack); /** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ int pitch_search_3tap( -float target[], /* Target vector */ -float *sw, -float ak[], /* LPCs for this subframe */ -float awk1[], /* Weighted LPCs #1 for this subframe */ -float awk2[], /* Weighted LPCs #2 for this subframe */ -float exc[], /* Overlapping codebook */ -void *par, +spx_word16_t target[], /* Target vector */ +spx_word16_t *sw, +spx_coef_t ak[], /* LPCs for this subframe */ +spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ +spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ +spx_sig_t exc[], /* Overlapping codebook */ +const void *par, int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ -float pitch_coef, /* Voicing (pitch) coefficient */ +spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ int p, /* Number of LPC coeffs */ int nsf, /* Number of samples in subframe */ SpeexBits *bits, char *stack, -float *exc2, -float *r, -int complexity +spx_word16_t *exc2, +spx_word16_t *r, +int complexity, +int cdbk_offset, +int plc_tuning, +spx_word32_t *cumul_gain ); /*Unquantize adaptive codebook and update pitch contribution*/ void pitch_unquant_3tap( -float exc[], /* Excitation */ +spx_word16_t exc[], /* Input excitation */ +spx_word32_t exc_out[], /* Output excitation */ int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ -float pitch_coef, /* Voicing (pitch) coefficient */ -void *par, +spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ +const void *par, int nsf, /* Number of samples in subframe */ int *pitch_val, -float *gain_val, +spx_word16_t *gain_val, SpeexBits *bits, char *stack, int lost, int subframe_offset, -float last_pitch_gain +spx_word16_t last_pitch_gain, +int cdbk_offset ); -float pitch_gain_search_3tap( -float target[], /* Target vector */ -float ak[], /* LPCs for this subframe */ -float awk1[], /* Weighted LPCs #1 for this subframe */ -float awk2[], /* Weighted LPCs #2 for this subframe */ -float exc[], /* Excitation */ -void *par, -int pitch, /* Pitch value */ -int p, /* Number of LPC coeffs */ -int nsf, /* Number of samples in subframe */ -SpeexBits *bits, -char *stack, -float *exc2, -float *r, -int *cdbk_index -); - - /** Forced pitch delay and gain */ int forced_pitch_quant( -float target[], /* Target vector */ -float *sw, -float ak[], /* LPCs for this subframe */ -float awk1[], /* Weighted LPCs #1 for this subframe */ -float awk2[], /* Weighted LPCs #2 for this subframe */ -float exc[], /* Excitation */ -void *par, +spx_word16_t target[], /* Target vector */ +spx_word16_t *sw, +spx_coef_t ak[], /* LPCs for this subframe */ +spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ +spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ +spx_sig_t exc[], /* Excitation */ +const void *par, int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ -float pitch_coef, /* Voicing (pitch) coefficient */ +spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ int p, /* Number of LPC coeffs */ int nsf, /* Number of samples in subframe */ SpeexBits *bits, char *stack, -float *exc2, -float *r, -int complexity +spx_word16_t *exc2, +spx_word16_t *r, +int complexity, +int cdbk_offset, +int plc_tuning, +spx_word32_t *cumul_gain ); /** Unquantize forced pitch delay and gain */ void forced_pitch_unquant( -float exc[], /* Excitation */ +spx_word16_t exc[], /* Input excitation */ +spx_word32_t exc_out[], /* Output excitation */ int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ -float pitch_coef, /* Voicing (pitch) coefficient */ -void *par, +spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ +const void *par, int nsf, /* Number of samples in subframe */ int *pitch_val, -float *gain_val, +spx_word16_t *gain_val, SpeexBits *bits, char *stack, int lost, int subframe_offset, -float last_pitch_gain +spx_word16_t last_pitch_gain, +int cdbk_offset ); + +#endif /* LTP_H */ diff --git a/external/speex/src/ltp_arm4.h b/external/speex/src/ltp_arm4.h new file mode 100644 index 0000000..18be0d1 --- /dev/null +++ b/external/speex/src/ltp_arm4.h @@ -0,0 +1,187 @@ +/* Copyright (C) 2004 Jean-Marc Valin */ +/** + @file ltp_arm4.h + @brief Long-Term Prediction functions (ARM4 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. +*/ + +#define OVERRIDE_INNER_PROD +spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) +{ + spx_word32_t sum1=0,sum2=0; + spx_word16_t *deadx, *deady; + int deadlen, dead1, dead2, dead3, dead4, dead5, dead6; + __asm__ __volatile__ ( + "\tldrsh %5, [%0], #2 \n" + "\tldrsh %6, [%1], #2 \n" + ".inner_prod_loop%=:\n" + "\tsub %7, %7, %7\n" + "\tsub %10, %10, %10\n" + + "\tldrsh %8, [%0], #2 \n" + "\tldrsh %9, [%1], #2 \n" + "\tmla %7, %5, %6, %7\n" + "\tldrsh %5, [%0], #2 \n" + "\tldrsh %6, [%1], #2 \n" + "\tmla %10, %8, %9, %10\n" + "\tldrsh %8, [%0], #2 \n" + "\tldrsh %9, [%1], #2 \n" + "\tmla %7, %5, %6, %7\n" + "\tldrsh %5, [%0], #2 \n" + "\tldrsh %6, [%1], #2 \n" + "\tmla %10, %8, %9, %10\n" + + "\tldrsh %8, [%0], #2 \n" + "\tldrsh %9, [%1], #2 \n" + "\tmla %7, %5, %6, %7\n" + "\tldrsh %5, [%0], #2 \n" + "\tldrsh %6, [%1], #2 \n" + "\tmla %10, %8, %9, %10\n" + "\tldrsh %8, [%0], #2 \n" + "\tldrsh %9, [%1], #2 \n" + "\tmla %7, %5, %6, %7\n" + "\tldrsh %5, [%0], #2 \n" + "\tldrsh %6, [%1], #2 \n" + "\tmla %10, %8, %9, %10\n" + + "\tsubs %4, %4, #1\n" + "\tadd %2, %2, %7, asr #5\n" + "\tadd %3, %3, %10, asr #5\n" + "\tbne .inner_prod_loop%=\n" + : "=r" (deadx), "=r" (deady), "+r" (sum1), "+r" (sum2), + "=r" (deadlen), "=r" (dead1), "=r" (dead2), "=r" (dead3), + "=r" (dead4), "=r" (dead5), "=r" (dead6) + : "0" (x), "1" (y), "4" (len>>3) + : "cc" + ); + return (sum1+sum2)>>1; +} + +#define OVERRIDE_PITCH_XCORR +void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) +{ + int i,j; + for (i=0;i>> 6;\n\t" + "R0 = A0;\n\t" + "%0 = R0;\n\t" + : "=m" (sum) + : "m" (x), "m" (y), "d" (len-1) + : "P0", "P1", "P2", "R0", "R1", "A0", "I0", "I1", "L0", "L1", "R3", "ASTAT" BFIN_HWLOOP0_REGS + ); + return sum; +} + +#define OVERRIDE_PITCH_XCORR +void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) +{ + corr += nb_pitch - 1; + __asm__ __volatile__ ( + "P2 = %0;\n\t" + "I0 = P2;\n\t" /* x in I0 */ + "B0 = P2;\n\t" /* x in B0 */ + "R0 = %3;\n\t" /* len in R0 */ + "P3 = %3;\n\t" + "P3 += -2;\n\t" /* len in R0 */ + "P4 = %4;\n\t" /* nb_pitch in R0 */ + "R1 = R0 << 1;\n\t" /* number of bytes in x */ + "L0 = R1;\n\t" + "P0 = %1;\n\t" + + "P1 = %2;\n\t" + "B1 = P1;\n\t" + "L1 = 0;\n\t" /*Disable looping on I1*/ + + "r0 = [I0++];\n\t" + "LOOP pitch%= LC0 = P4 >> 1;\n\t" + "LOOP_BEGIN pitch%=;\n\t" + "I1 = P0;\n\t" + "A1 = A0 = 0;\n\t" + "R1 = [I1++];\n\t" + "LOOP inner_prod%= LC1 = P3 >> 1;\n\t" + "LOOP_BEGIN inner_prod%=;\n\t" + "A1 += R0.L*R1.H, A0 += R0.L*R1.L (IS) || R1.L = W[I1++];\n\t" + "A1 += R0.H*R1.L, A0 += R0.H*R1.H (IS) || R1.H = W[I1++] || R0 = [I0++];\n\t" + "LOOP_END inner_prod%=;\n\t" + "A1 += R0.L*R1.H, A0 += R0.L*R1.L (IS) || R1.L = W[I1++];\n\t" + "A1 += R0.H*R1.L, A0 += R0.H*R1.H (IS) || R0 = [I0++];\n\t" + "A0 = A0 >>> 6;\n\t" + "A1 = A1 >>> 6;\n\t" + "R2 = A0, R3 = A1;\n\t" + "[P1--] = r2;\n\t" + "[P1--] = r3;\n\t" + "P0 += 4;\n\t" + "LOOP_END pitch%=;\n\t" + "L0 = 0;\n\t" + : : "m" (_x), "m" (_y), "m" (corr), "m" (len), "m" (nb_pitch) + : "A0", "A1", "P0", "P1", "P2", "P3", "P4", "R0", "R1", "R2", "R3", "I0", "I1", "L0", "L1", "B0", "B1", "memory", + "ASTAT" BFIN_HWLOOP0_REGS BFIN_HWLOOP1_REGS + ); +} + +#define OVERRIDE_COMPUTE_PITCH_ERROR +static inline spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g, spx_word16_t pitch_control) +{ + spx_word32_t sum; + __asm__ __volatile__ + ( + "A0 = 0;\n\t" + + "R0 = W[%1++];\n\t" + "R1.L = %2.L*%5.L (IS);\n\t" + "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %3.L*%5.L (IS);\n\t" + "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %4.L*%5.L (IS);\n\t" + "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %2.L*%3.L (IS);\n\t" + "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %4.L*%3.L (IS);\n\t" + "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %4.L*%2.L (IS);\n\t" + "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %2.L*%2.L (IS);\n\t" + "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %3.L*%3.L (IS);\n\t" + "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t" + + "R1.L = %4.L*%4.L (IS);\n\t" + "A0 -= R1.L*R0.L (IS);\n\t" + + "%0 = A0;\n\t" + : "=&D" (sum), "=a" (C) + : "d" (g[0]), "d" (g[1]), "d" (g[2]), "d" (pitch_control), "1" (C) + : "R0", "R1", "R2", "A0", "ASTAT" + ); + return sum; +} + +#define OVERRIDE_OPEN_LOOP_NBEST_PITCH +#ifdef OVERRIDE_OPEN_LOOP_NBEST_PITCH +void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack) +{ + int i,j,k; + VARDECL(spx_word32_t *best_score); + VARDECL(spx_word32_t *best_ener); + spx_word32_t e0; + VARDECL(spx_word32_t *corr); + VARDECL(spx_word32_t *energy); + + ALLOC(best_score, N, spx_word32_t); + ALLOC(best_ener, N, spx_word32_t); + ALLOC(corr, end-start+1, spx_word32_t); + ALLOC(energy, end-start+2, spx_word32_t); + + for (i=0;i>>= 6;\n\t" +" R1 = R1 + R2;\n\t" +" R0 >>>= 6;\n\t" +" R1 = R1 - R0;\n\t" +" R2 = MAX(R1,R3);\n\t" +"eu2: [P0++] = R2;\n\t" + : : "d" (energy), "d" (&sw[-start-1]), "d" (&sw[-start+len-1]), + "a" (end-start) + : "P0", "I1", "I2", "R0", "R1", "R2", "R3", "ASTAT" BFIN_HWLOOP1_REGS + ); + + pitch_xcorr(sw, sw-end, corr, len, end-start+1, stack); + + /* FIXME: Fixed-point and floating-point code should be merged */ + { + VARDECL(spx_word16_t *corr16); + VARDECL(spx_word16_t *ener16); + ALLOC(corr16, end-start+1, spx_word16_t); + ALLOC(ener16, end-start+1, spx_word16_t); + /* Normalize to 180 so we can square it and it still fits in 16 bits */ + normalize16(corr, corr16, 180, end-start+1); + normalize16(energy, ener16, 180, end-start+1); + + if (N == 1) { + /* optimised asm to handle N==1 case */ + __asm__ __volatile__ + ( +" I0 = %1;\n\t" /* I0: corr16[] */ +" L0 = 0;\n\t" +" I1 = %2;\n\t" /* I1: energy */ +" L1 = 0;\n\t" +" R2 = -1;\n\t" /* R2: best score */ +" R3 = 0;\n\t" /* R3: best energy */ +" P0 = %4;\n\t" /* P0: best pitch */ +" P1 = %4;\n\t" /* P1: counter */ +" LSETUP (sl1, sl2) LC1 = %3;\n\t" +"sl1: R0.L = W [I0++] || R1.L = W [I1++];\n\t" +" R0 = R0.L * R0.L (IS);\n\t" +" R1 += 1;\n\t" +" R4 = R0.L * R3.L;\n\t" +" R5 = R2.L * R1.L;\n\t" +" cc = R5 < R4;\n\t" +" if cc R2 = R0;\n\t" +" if cc R3 = R1;\n\t" +" if cc P0 = P1;\n\t" +"sl2: P1 += 1;\n\t" +" %0 = P0;\n\t" + : "=&d" (pitch[0]) + : "a" (corr16), "a" (ener16), "a" (end+1-start), "d" (start) + : "P0", "P1", "I0", "I1", "R0", "R1", "R2", "R3", "R4", "R5", + "ASTAT", "CC" BFIN_HWLOOP1_REGS + ); + + } + else { + for (i=start;i<=end;i++) + { + spx_word16_t tmp = MULT16_16_16(corr16[i-start],corr16[i-start]); + /* Instead of dividing the tmp by the energy, we multiply on the other side */ + if (MULT16_16(tmp,best_ener[N-1])>MULT16_16(best_score[N-1],ADD16(1,ener16[i-start]))) + { + /* We can safely put it last and then check */ + best_score[N-1]=tmp; + best_ener[N-1]=ener16[i-start]+1; + pitch[N-1]=i; + /* Check if it comes in front of others */ + for (j=0;jMULT16_16(best_score[j],ADD16(1,ener16[i-start]))) + { + for (k=N-1;k>j;k--) + { + best_score[k]=best_score[k-1]; + best_ener[k]=best_ener[k-1]; + pitch[k]=pitch[k-1]; + } + best_score[j]=tmp; + best_ener[j]=ener16[i-start]+1; + pitch[j]=i; + break; + } + } + } + } + } + } + + /* Compute open-loop gain */ + if (gain) + { + for (j=0;jbest_sum && gain_sum<=max_gain) ------ (1) + + if (sum>best_sum && !(gain_sum>max_gain)) ------ (2) + + if (max_gain<=gain_sum) { ------ (3) + sum = -VERY_LARGE32; + } + if (best_sum<=sum) + + The blackin cc instructions are all of the form: + + cc = x < y (or cc = x <= y) +*/ +" R1 = B0\n\t" +" R2 = %5\n\t" +" R3 = %6\n\t" +" cc = R2 <= R1;\n\t" +" if cc R0 = R3;\n\t" +" cc = %0 <= R0;\n\t" +" if cc %0 = R0;\n\t" +" if cc %1 = P1;\n\t" + +"pgs2: P1 += 1;\n\t" + + : "=&d" (best_sum), "=&d" (best_cdbk) + : "a" (gain_cdbk), "a" (C16), "a" (gain_cdbk_size), "a" (max_gain), + "b" (-VERY_LARGE32) + : "R0", "R1", "R2", "R3", "R4", "P0", + "P1", "I1", "L1", "A0", "B0", "CC", "ASTAT" BFIN_HWLOOP1_REGS + ); + + return best_cdbk; +} +#endif + diff --git a/external/speex/src/ltp_sse.h b/external/speex/src/ltp_sse.h index c8d484a..3260008 100644 --- a/external/speex/src/ltp_sse.h +++ b/external/speex/src/ltp_sse.h @@ -1,22 +1,24 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: ltp.c - Lont-Term Prediction functions - +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file ltp_sse.h + @brief Long-Term Prediction 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 @@ -30,66 +32,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include -static float inner_prod(float *a, float *b, int len) +#define OVERRIDE_INNER_PROD +float inner_prod(const float *a, const float *b, int len) { - float sum; - __asm__ __volatile__ ( - "\tpush %%eax\n" - "\tpush %%edi\n" - "\tpush %%ecx\n" - "\txorps %%xmm3, %%xmm3\n" - "\txorps %%xmm4, %%xmm4\n" - - "\tsub $20, %%ecx\n" - -".mul20_loop%=:\n" - - "\tmovups (%%eax), %%xmm0\n" - "\tmovups (%%edi), %%xmm1\n" - "\tmulps %%xmm0, %%xmm1\n" - - "\tmovups 16(%%eax), %%xmm5\n" - "\tmovups 16(%%edi), %%xmm6\n" - "\tmulps %%xmm5, %%xmm6\n" - "\taddps %%xmm1, %%xmm3\n" - - "\tmovups 32(%%eax), %%xmm0\n" - "\tmovups 32(%%edi), %%xmm1\n" - "\tmulps %%xmm0, %%xmm1\n" - "\taddps %%xmm6, %%xmm4\n" - - "\tmovups 48(%%eax), %%xmm5\n" - "\tmovups 48(%%edi), %%xmm6\n" - "\tmulps %%xmm5, %%xmm6\n" - "\taddps %%xmm1, %%xmm3\n" - - "\tmovups 64(%%eax), %%xmm0\n" - "\tmovups 64(%%edi), %%xmm1\n" - "\tmulps %%xmm0, %%xmm1\n" - "\taddps %%xmm6, %%xmm4\n" - "\taddps %%xmm1, %%xmm3\n" - - - "\tadd $80, %%eax\n" - "\tadd $80, %%edi\n" - - "\tsub $20, %%ecx\n" - - "\tjae .mul20_loop%=\n" - - "\taddps %%xmm4, %%xmm3\n" - - "\tmovhlps %%xmm3, %%xmm4\n" - "\taddps %%xmm4, %%xmm3\n" - "\tmovaps %%xmm3, %%xmm4\n" - "\tshufps $0x55, %%xmm4, %%xmm4\n" - "\taddss %%xmm4, %%xmm3\n" - "\tmovss %%xmm3, (%%edx)\n" - - "\tpop %%ecx\n" - "\tpop %%edi\n" - "\tpop %%eax\n" - : : "a" (a), "D" (b), "c" (len), "d" (&sum) : "memory"); - return sum; + int i; + float ret; + __m128 sum = _mm_setzero_ps(); + for (i=0;i<(len>>2);i+=2) + { + sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+0), _mm_loadu_ps(b+0))); + sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+4), _mm_loadu_ps(b+4))); + a += 8; + b += 8; + } + sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); + sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); + _mm_store_ss(&ret, sum); + return ret; +} + +#define OVERRIDE_PITCH_XCORR +void pitch_xcorr(const float *_x, const float *_y, float *corr, int len, int nb_pitch, char *stack) +{ + int i, offset; + VARDECL(__m128 *x); + VARDECL(__m128 *y); + int N, L; + N = len>>2; + L = nb_pitch>>2; + ALLOC(x, N, __m128); + ALLOC(y, N+L, __m128); + for (i=0;i -#include "math_approx.h" - -#ifdef SLOW_TRIG - -float cos_sin[102] = { - 1.00000000, 0.00000000, - 0.99804751, 0.06245932, - 0.99219767, 0.12467473, - 0.98247331, 0.18640330, - 0.96891242, 0.24740396, - 0.95156795, 0.30743851, - 0.93050762, 0.36627253, - 0.90581368, 0.42367626, - 0.87758256, 0.47942554, - 0.84592450, 0.53330267, - 0.81096312, 0.58509727, - 0.77283495, 0.63460708, - 0.73168887, 0.68163876, - 0.68768556, 0.72600866, - 0.64099686, 0.76754350, - 0.59180508, 0.80608111, - 0.54030231, 0.84147098, - 0.48668967, 0.87357494, - 0.43117652, 0.90226759, - 0.37397963, 0.92743692, - 0.31532236, 0.94898462, - 0.25543377, 0.96682656, - 0.19454771, 0.98089306, - 0.13290194, 0.99112919, - 0.07073720, 0.99749499, - 0.00829623, 0.99996559, - -0.05417714, 0.99853134, - -0.11643894, 0.99319785, - -0.17824606, 0.98398595, - -0.23935712, 0.97093160, - -0.29953351, 0.95408578, - -0.35854022, 0.93351428, - -0.41614684, 0.90929743, - -0.47212841, 0.88152979, - -0.52626633, 0.85031979, - -0.57834920, 0.81578931, - -0.62817362, 0.77807320, - -0.67554504, 0.73731872, - -0.72027847, 0.69368503, - -0.76219923, 0.64734252, - -0.80114362, 0.59847214, - -0.83695955, 0.54726475, - -0.86950718, 0.49392030, - -0.89865940, 0.43864710, - -0.92430238, 0.38166099, - -0.94633597, 0.32318451, - -0.96467415, 0.26344599, - -0.97924529, 0.20267873, - -0.98999250, 0.14112001, - -0.99687381, 0.07901022, - -0.99986235, 0.01659189 -}; - -float speex_cos(float x) -{ - int ind; - float delta; - ind = (int)floor(x*16+.5); - delta = x-0.062500*ind; - ind <<= 1; - return cos_sin[ind] - delta*(cos_sin[ind+1] + - .5*delta*(cos_sin[ind] - - .3333333*delta*cos_sin[ind+1])); -} - -#endif - diff --git a/external/speex/src/math_approx.h b/external/speex/src/math_approx.h index c917ffd..a01349c 100644 --- a/external/speex/src/math_approx.h +++ b/external/speex/src/math_approx.h @@ -1,22 +1,24 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: math_approx.c - Various math approximation functions for Speex - +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file math_approx.h + @brief Various math approximation functions 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 @@ -33,7 +35,298 @@ #ifndef MATH_APPROX_H #define MATH_APPROX_H -float speex_cos(float x); +#include "arch.h" + +#ifndef FIXED_POINT + +#define spx_sqrt sqrt +#define spx_acos acos +#define spx_exp exp +#define spx_cos_norm(x) (cos((.5f*M_PI)*(x))) +#define spx_atan atan + +/** Generate a pseudo-random number */ +static inline spx_word16_t speex_rand(spx_word16_t std, spx_uint32_t *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 3.4642*std*ran.f; +} + + +#endif + + +static inline spx_int16_t spx_ilog2(spx_uint32_t x) +{ + int r=0; + if (x>=(spx_int32_t)65536) + { + x >>= 16; + r += 16; + } + if (x>=256) + { + x >>= 8; + r += 8; + } + if (x>=16) + { + x >>= 4; + r += 4; + } + if (x>=4) + { + x >>= 2; + r += 2; + } + if (x>=2) + { + r += 1; + } + return r; +} + +static inline spx_int16_t spx_ilog4(spx_uint32_t x) +{ + int r=0; + if (x>=(spx_int32_t)65536) + { + x >>= 16; + r += 8; + } + if (x>=256) + { + x >>= 8; + r += 4; + } + if (x>=16) + { + x >>= 4; + r += 2; + } + if (x>=4) + { + r += 1; + } + return r; +} + +#ifdef FIXED_POINT + +/** Generate a pseudo-random number */ +static inline spx_word16_t speex_rand(spx_word16_t std, spx_uint32_t *seed) +{ + spx_word32_t res; + *seed = 1664525 * *seed + 1013904223; + res = MULT16_16(EXTRACT16(SHR32(*seed,16)),std); + return EXTRACT16(PSHR32(SUB32(res, SHR32(res, 3)),14)); +} + +/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */ +/*#define C0 3634 +#define C1 21173 +#define C2 -12627 +#define C3 4215*/ + +/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */ +#define C0 3634 +#define C1 21173 +#define C2 -12627 +#define C3 4204 + +static inline spx_word16_t spx_sqrt(spx_word32_t x) +{ + int k; + spx_word32_t rt; + k = spx_ilog4(x)-6; + x = VSHR32(x, (int)((unsigned)k<<1)); + rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3))))))); + rt = VSHR32(rt,7-k); + return rt; +} + +/* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */ + + +#define A1 16469 +#define A2 2242 +#define A3 1486 + +static inline spx_word16_t spx_acos(spx_word16_t x) +{ + int s=0; + spx_word16_t ret; + spx_word16_t sq; + if (x<0) + { + s=1; + x = NEG16(x); + } + x = SUB16(16384,x); + + x = x >> 1; + sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3)))))); + ret = spx_sqrt(SHL32(EXTEND32(sq),13)); + + /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/ + if (s) + ret = SUB16(25736,ret); + return ret; +} + + +#define K1 8192 +#define K2 -4096 +#define K3 340 +#define K4 -10 + +static inline spx_word16_t spx_cos(spx_word16_t x) +{ + spx_word16_t x2; + + if (x<12868) + { + x2 = MULT16_16_P13(x,x); + return ADD32(K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2)))))); + } else { + x = SUB16(25736,x); + x2 = MULT16_16_P13(x,x); + return SUB32(-K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2)))))); + } +} + +#define L1 32767 +#define L2 -7651 +#define L3 8277 +#define L4 -626 + +static inline spx_word16_t _spx_cos_pi_2(spx_word16_t x) +{ + spx_word16_t x2; + + x2 = MULT16_16_P15(x,x); + return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2)))))))); +} + +static inline spx_word16_t spx_cos_norm(spx_word32_t x) +{ + x = x&0x0001ffff; + if (x>SHL32(EXTEND32(1), 16)) + x = SUB32(SHL32(EXTEND32(1), 17),x); + if (x&0x00007fff) + { + if (x14) + return 0x7fffffff; + else if (integer < -15) + return 0; + frac = SHL16(x-SHL16(integer,11),3); + frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2 , MULT16_16_Q14(D3,frac)))))); + return VSHR32(EXTEND32(frac), -integer-2); +} + +/* Input in Q11 format, output in Q16 */ +static inline spx_word32_t spx_exp(spx_word16_t x) +{ + if (x>21290) + return 0x7fffffff; + else if (x<-21290) + return 0; + else + return spx_exp2(MULT16_16_P14(23637,x)); +} +#define M1 32767 +#define M2 -21 +#define M3 -11943 +#define M4 4936 + +static inline spx_word16_t spx_atan01(spx_word16_t x) +{ + return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x))))))); +} + +#undef M1 +#undef M2 +#undef M3 +#undef M4 + +/* Input in Q15, output in Q14 */ +static inline spx_word16_t spx_atan(spx_word32_t x) +{ + if (x <= 32767) + { + return SHR16(spx_atan01(x),1); + } else { + int e = spx_ilog2(x); + if (e>=29) + return 25736; + x = DIV32_16(SHL32(EXTEND32(32767),29-e), EXTRACT16(SHR32(x, e-14))); + return SUB16(25736, SHR16(spx_atan01(x),1)); + } +} +#else + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + +#define C1 0.9999932946f +#define C2 -0.4999124376f +#define C3 0.0414877472f +#define C4 -0.0012712095f + + +#define SPX_PI_2 1.5707963268 +static inline spx_word16_t spx_cos(spx_word16_t x) +{ + if (x -#include -#include - -#ifndef RELEASE -void print_vec(float *vec, int len, char *name) -{ - int i; - printf ("%s ", name); - for (i=0;i>24; - ret += (i>>8)&0x0000ff00; - ret += (i<<8)&0x00ff0000; - ret += (i<<24); -#endif - return ret; -} - -unsigned int le_int(unsigned int i) -{ - unsigned int ret=i; -#ifdef WORDS_BIGENDIAN - ret = i>>24; - ret += (i>>8)&0x0000ff00; - ret += (i<<8)&0x00ff0000; - ret += (i<<24); -#endif - return ret; -} - -unsigned short be_short(unsigned short s) -{ - unsigned short ret=s; -#ifndef WORDS_BIGENDIAN - ret = s>>8; - ret += s<<8; -#endif - return ret; -} - -unsigned short le_short(unsigned short s) -{ - unsigned short ret=s; -#ifdef WORDS_BIGENDIAN - ret = s>>8; - ret += s<<8; -#endif - return ret; -} - -void *speex_alloc (int size) -{ - return calloc(size,1); -} - -void *speex_realloc (void *ptr, int size) -{ - return realloc(ptr, size); -} - -void speex_free (void *ptr) -{ - free(ptr); -} - -void *speex_move (void *dest, void *src, int n) -{ - return memmove(dest,src,n); -} - -void speex_error(char *str) -{ - fprintf (stderr, "Fatal error: %s\n", str); - exit(1); -} - -void speex_warning(char *str) -{ - fprintf (stderr, "warning: %s\n", str); -} - -void speex_warning_int(char *str, int val) -{ - fprintf (stderr, "warning: %s %d\n", str, val); -} - -void speex_rand_vec(float std, float *data, int len) -{ - int i; - for (i=0;i>2)-1), "0" (src), "1" (dest) + : "R0", "I0", "L0", "memory" BFIN_HWLOOP0_REGS + ); + return dest; +} diff --git a/external/speex/src/modes.c b/external/speex/src/modes.c index b525872..88e431a 100644 --- a/external/speex/src/modes.c +++ b/external/speex/src/modes.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002-2006 Jean-Marc Valin File: modes.c Describes the different modes of the codec @@ -6,18 +6,18 @@ 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 @@ -32,6 +32,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "modes.h" #include "ltp.h" #include "quant_lsp.h" @@ -39,59 +43,82 @@ #include "sb_celp.h" #include "nb_celp.h" #include "vbr.h" -#include "misc.h" +#include "arch.h" +#include #ifndef NULL #define NULL 0 #endif -SpeexMode *speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode}; +#ifdef DISABLE_ENCODER +#define nb_encoder_init NULL +#define nb_encoder_destroy NULL +#define nb_encode NULL +#define nb_encoder_ctl NULL + +#define split_cb_search_shape_sign NULL +#define noise_codebook_quant NULL +#define pitch_search_3tap NULL +#define forced_pitch_quant NULL +#define lsp_quant_nb NULL +#define lsp_quant_lbr NULL +#endif /* DISABLE_ENCODER */ + +#ifdef DISABLE_DECODER +#define nb_decoder_init NULL +#define nb_decoder_destroy NULL +#define nb_decode NULL +#define nb_decoder_ctl NULL + +#define noise_codebook_unquant NULL +#define split_cb_shape_sign_unquant NULL +#define lsp_unquant_nb NULL +#define lsp_unquant_lbr NULL +#define pitch_unquant_3tap NULL +#define forced_pitch_unquant NULL +#endif /* DISABLE_DECODER */ /* Extern declarations for all codebooks we use here */ -extern signed char gain_cdbk_nb[]; -extern signed char gain_cdbk_lbr[]; -extern signed char hexc_table[]; -extern signed char exc_5_256_table[]; -extern signed char exc_5_64_table[]; -extern signed char exc_8_128_table[]; -extern signed char exc_10_32_table[]; -extern signed char exc_10_16_table[]; -extern signed char exc_20_32_table[]; -extern signed char hexc_10_32_table[]; +extern const signed char gain_cdbk_nb[]; +extern const signed char gain_cdbk_lbr[]; +extern const signed char exc_5_256_table[]; +extern const signed char exc_5_64_table[]; +extern const signed char exc_8_128_table[]; +extern const signed char exc_10_32_table[]; +extern const signed char exc_10_16_table[]; +extern const signed char exc_20_32_table[]; -static int nb_mode_query(void *mode, int request, void *ptr); -static int wb_mode_query(void *mode, int request, void *ptr); /* Parameters for Long-Term Prediction (LTP)*/ -static ltp_params ltp_params_nb = { +static const ltp_params ltp_params_nb = { gain_cdbk_nb, 7, 7 }; /* Parameters for Long-Term Prediction (LTP)*/ -static ltp_params ltp_params_vlbr = { +static const ltp_params ltp_params_vlbr = { gain_cdbk_lbr, 5, 0 }; /* Parameters for Long-Term Prediction (LTP)*/ -static ltp_params ltp_params_lbr = { +static const ltp_params ltp_params_lbr = { gain_cdbk_lbr, 5, 7 }; /* Parameters for Long-Term Prediction (LTP)*/ -static ltp_params ltp_params_med = { +static const ltp_params ltp_params_med = { gain_cdbk_lbr, 5, 7 }; /* Split-VQ innovation parameters for very low bit-rate narrowband */ -static split_cb_params split_cb_nb_vlbr = { +static const split_cb_params split_cb_nb_vlbr = { 10, /*subvect_size*/ 4, /*nb_subvect*/ exc_10_16_table, /*shape_cb*/ @@ -100,7 +127,7 @@ static split_cb_params split_cb_nb_vlbr = { }; /* Split-VQ innovation parameters for very low bit-rate narrowband */ -static split_cb_params split_cb_nb_ulbr = { +static const split_cb_params split_cb_nb_ulbr = { 20, /*subvect_size*/ 2, /*nb_subvect*/ exc_20_32_table, /*shape_cb*/ @@ -109,7 +136,7 @@ static split_cb_params split_cb_nb_ulbr = { }; /* Split-VQ innovation parameters for low bit-rate narrowband */ -static split_cb_params split_cb_nb_lbr = { +static const split_cb_params split_cb_nb_lbr = { 10, /*subvect_size*/ 4, /*nb_subvect*/ exc_10_32_table, /*shape_cb*/ @@ -119,7 +146,7 @@ static split_cb_params split_cb_nb_lbr = { /* Split-VQ innovation parameters narrowband */ -static split_cb_params split_cb_nb = { +static const split_cb_params split_cb_nb = { 5, /*subvect_size*/ 8, /*nb_subvect*/ exc_5_64_table, /*shape_cb*/ @@ -128,7 +155,7 @@ static split_cb_params split_cb_nb = { }; /* Split-VQ innovation parameters narrowband */ -static split_cb_params split_cb_nb_med = { +static const split_cb_params split_cb_nb_med = { 8, /*subvect_size*/ 5, /*nb_subvect*/ exc_8_128_table, /*shape_cb*/ @@ -137,7 +164,7 @@ static split_cb_params split_cb_nb_med = { }; /* Split-VQ innovation for low-band wideband */ -static split_cb_params split_cb_sb = { +static const split_cb_params split_cb_sb = { 5, /*subvect_size*/ 8, /*nb_subvect*/ exc_5_256_table, /*shape_cb*/ @@ -145,27 +172,10 @@ static split_cb_params split_cb_sb = { 0, }; -/* Split-VQ innovation for high-band wideband */ -static split_cb_params split_cb_high = { - 8, /*subvect_size*/ - 5, /*nb_subvect*/ - hexc_table, /*shape_cb*/ - 7, /*shape_bits*/ - 1, -}; -/* Split-VQ innovation for high-band wideband */ -static split_cb_params split_cb_high_lbr = { - 10, /*subvect_size*/ - 4, /*nb_subvect*/ - hexc_10_32_table, /*shape_cb*/ - 5, /*shape_bits*/ - 0, -}; - /* 2150 bps "vocoder-like" mode for comfort noise */ -static SpeexSubmode nb_submode1 = { +static const SpeexSubmode nb_submode1 = { 0, 1, 0, @@ -181,12 +191,12 @@ static SpeexSubmode nb_submode1 = { noise_codebook_quant, noise_codebook_unquant, NULL, - .7, .7, -1, + -1, 43 }; /* 3.95 kbps very low bit-rate mode */ -static SpeexSubmode nb_submode8 = { +static const SpeexSubmode nb_submode8 = { 0, 1, 0, @@ -202,13 +212,12 @@ static SpeexSubmode nb_submode8 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_nb_ulbr, - - 0.7, 0.5, .65, + QCONST16(.5,15), 79 }; /* 5.95 kbps very low bit-rate mode */ -static SpeexSubmode nb_submode2 = { +static const SpeexSubmode nb_submode2 = { 0, 0, 0, @@ -224,13 +233,12 @@ static SpeexSubmode nb_submode2 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_nb_vlbr, - - 0.7, 0.5, .55, + QCONST16(.6,15), 119 }; /* 8 kbps low bit-rate mode */ -static SpeexSubmode nb_submode3 = { +static const SpeexSubmode nb_submode3 = { -1, 0, 1, @@ -246,13 +254,12 @@ static SpeexSubmode nb_submode3 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_nb_lbr, - - 0.7, 0.55, .45, + QCONST16(.55,15), 160 }; /* 11 kbps medium bit-rate mode */ -static SpeexSubmode nb_submode4 = { +static const SpeexSubmode nb_submode4 = { -1, 0, 1, @@ -268,13 +275,12 @@ static SpeexSubmode nb_submode4 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_nb_med, - - 0.7, 0.63, .35, + QCONST16(.45,15), 220 }; /* 15 kbps high bit-rate mode */ -static SpeexSubmode nb_submode5 = { +static const SpeexSubmode nb_submode5 = { -1, 0, 3, @@ -290,13 +296,12 @@ static SpeexSubmode nb_submode5 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_nb, - - 0.7, 0.65, .25, + QCONST16(.25,15), 300 }; /* 18.2 high bit-rate mode */ -static SpeexSubmode nb_submode6 = { +static const SpeexSubmode nb_submode6 = { -1, 0, 3, @@ -312,13 +317,12 @@ static SpeexSubmode nb_submode6 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_sb, - - 0.68, 0.65, .1, + QCONST16(.15,15), 364 }; /* 24.6 kbps high bit-rate mode */ -static SpeexSubmode nb_submode7 = { +static const SpeexSubmode nb_submode7 = { -1, 0, 3, @@ -334,25 +338,21 @@ static SpeexSubmode nb_submode7 = { split_cb_search_shape_sign, split_cb_shape_sign_unquant, &split_cb_nb, - - 0.65, 0.65, -1, + QCONST16(.05,15), 492 }; /* Default mode for narrowband */ -static SpeexNBMode nb_mode = { - 160, /*frameSize*/ - 40, /*subframeSize*/ - 10, /*lpcSize*/ - 640, /*bufSize*/ - 17, /*pitchStart*/ - 144, /*pitchEnd*/ - 0.9, /*gamma1*/ - 0.6, /*gamma2*/ - .01, /*lag_factor*/ - 1.0001, /*lpc_floor*/ - 0.0, /*preemph*/ +static const SpeexNBMode nb_mode = { + NB_FRAME_SIZE, /*frameSize*/ + NB_SUBFRAME_SIZE, /*subframeSize*/ + NB_ORDER, /*lpcSize*/ + NB_PITCH_START, /*pitchStart*/ + NB_PITCH_END, /*pitchEnd*/ + QCONST16(0.92,15), /* gamma1 */ + QCONST16(0.6,15), /* gamma2 */ + QCONST16(.0002,15), /*lpc_floor*/ {NULL, &nb_submode1, &nb_submode2, &nb_submode3, &nb_submode4, &nb_submode5, &nb_submode6, &nb_submode7, &nb_submode8, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, 5, @@ -361,290 +361,30 @@ static SpeexNBMode nb_mode = { /* Default mode for narrowband */ -SpeexMode speex_nb_mode = { +EXPORT const SpeexMode speex_nb_mode = { &nb_mode, nb_mode_query, "narrowband", 0, 4, - &nb_encoder_init, - &nb_encoder_destroy, - &nb_encode, - &nb_decoder_init, - &nb_decoder_destroy, - &nb_decode, - &nb_encoder_ctl, - &nb_decoder_ctl, -}; - - -/* Wideband part */ - -static SpeexSubmode wb_submode1 = { - 0, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*No innovation quantization*/ - NULL, - NULL, - NULL, - - .75, .75, -1, - 36 -}; - - -static SpeexSubmode wb_submode2 = { - 0, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_high_lbr, - - .85, .6, -1, - 112 -}; - - -static SpeexSubmode wb_submode3 = { - 0, - 0, - 1, - 0, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_high, - - .75, .7, -1, - 192 -}; - -static SpeexSubmode wb_submode4 = { - 0, - 0, - 1, - 1, - /*LSP quantization*/ - lsp_quant_high, - lsp_unquant_high, - /*Pitch quantization*/ - NULL, - NULL, - NULL, - /*Innovation quantization*/ - split_cb_search_shape_sign, - split_cb_shape_sign_unquant, - &split_cb_high, - - .75, .75, -1, - 352 -}; - - -/* Split-band wideband CELP mode*/ -static SpeexSBMode sb_wb_mode = { - &speex_nb_mode, - 160, /*frameSize*/ - 40, /*subframeSize*/ - 8, /*lpcSize*/ - 640, /*bufSize*/ - .9, /*gamma1*/ - 0.6, /*gamma2*/ - .002, /*lag_factor*/ - 1.0001, /*lpc_floor*/ - 0.0, /*preemph*/ - 0.9, - {NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL}, - 3, - {1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7}, - {1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4}, - vbr_hb_thresh, - 5 -}; - - -SpeexMode speex_wb_mode = { - &sb_wb_mode, - wb_mode_query, - "wideband (sub-band CELP)", - 1, - 4, - &sb_encoder_init, - &sb_encoder_destroy, - &sb_encode, - &sb_decoder_init, - &sb_decoder_destroy, - &sb_decode, - &sb_encoder_ctl, - &sb_decoder_ctl, + nb_encoder_init, + nb_encoder_destroy, + nb_encode, + nb_decoder_init, + nb_decoder_destroy, + nb_decode, + nb_encoder_ctl, + nb_decoder_ctl, }; -/* "Ultra-wideband" mode stuff */ - - - -/* Split-band "ultra-wideband" (32 kbps) CELP mode*/ -static SpeexSBMode sb_uwb_mode = { - &speex_wb_mode, - 320, /*frameSize*/ - 80, /*subframeSize*/ - 8, /*lpcSize*/ - 1280, /*bufSize*/ - .9, /*gamma1*/ - 0.6, /*gamma2*/ - .002, /*lag_factor*/ - 1.0001, /*lpc_floor*/ - 0.0, /*preemph*/ - 0.7, - {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL}, - 1, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - vbr_uhb_thresh, - 2 -}; - - -SpeexMode speex_uwb_mode = { - &sb_uwb_mode, - wb_mode_query, - "ultra-wideband (sub-band CELP)", - 2, - 4, - &sb_encoder_init, - &sb_encoder_destroy, - &sb_encode, - &sb_decoder_init, - &sb_decoder_destroy, - &sb_decode, - &sb_encoder_ctl, - &sb_decoder_ctl, -}; - - - - -void *speex_encoder_init(SpeexMode *mode) -{ - return mode->enc_init(mode); -} - -void *speex_decoder_init(SpeexMode *mode) -{ - return mode->dec_init(mode); -} - -void speex_encoder_destroy(void *state) -{ - (*((SpeexMode**)state))->enc_destroy(state); -} - -int speex_encode(void *state, float *in, SpeexBits *bits) -{ - return (*((SpeexMode**)state))->enc(state, in, bits); -} - -void speex_decoder_destroy(void *state) -{ - (*((SpeexMode**)state))->dec_destroy(state); -} - -int speex_decode(void *state, SpeexBits *bits, float *out) -{ - return (*((SpeexMode**)state))->dec(state, bits, out); -} - - -int speex_encoder_ctl(void *state, int request, void *ptr) -{ - return (*((SpeexMode**)state))->enc_ctl(state, request, ptr); -} - -int speex_decoder_ctl(void *state, int request, void *ptr) -{ - return (*((SpeexMode**)state))->dec_ctl(state, request, ptr); -} - - - -static int nb_mode_query(void *mode, int request, void *ptr) -{ - SpeexNBMode *m = (SpeexNBMode*)mode; - - switch (request) - { - case SPEEX_MODE_FRAME_SIZE: - *((int*)ptr)=m->frameSize; - break; - case SPEEX_SUBMODE_BITS_PER_FRAME: - if (*((int*)ptr)==0) - *((int*)ptr) = NB_SUBMODE_BITS+1; - else if (m->submodes[*((int*)ptr)]==NULL) - *((int*)ptr) = -1; - else - *((int*)ptr) = m->submodes[*((int*)ptr)]->bits_per_frame; - break; - default: - speex_warning_int("Unknown nb_mode_query request: ", request); - return -1; - } - return 0; -} - -static int wb_mode_query(void *mode, int request, void *ptr) -{ - SpeexSBMode *m = (SpeexSBMode*)mode; - - switch (request) - { - case SPEEX_MODE_FRAME_SIZE: - *((int*)ptr)=2*m->frameSize; - break; - case SPEEX_SUBMODE_BITS_PER_FRAME: - if (*((int*)ptr)==0) - *((int*)ptr) = SB_SUBMODE_BITS+1; - else if (m->submodes[*((int*)ptr)]==NULL) - *((int*)ptr) = -1; - else - *((int*)ptr) = m->submodes[*((int*)ptr)]->bits_per_frame; - break; - default: - speex_warning_int("Unknown wb_mode_query request: ", request); - return -1; - } - return 0; -} - - -int speex_mode_query(SpeexMode *mode, int request, void *ptr) +EXPORT int speex_mode_query(const SpeexMode *mode, int request, void *ptr) { return mode->query(mode->mode, request, ptr); } + +#ifdef FIXED_DEBUG +long long spx_mips=0; +#endif + diff --git a/external/speex/src/modes.h b/external/speex/src/modes.h index 0a94357..2d5adc4 100644 --- a/external/speex/src/modes.h +++ b/external/speex/src/modes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ +/* Copyright (C) 2002-2006 Jean-Marc Valin */ /** @file modes.h @brief Describes the different modes of the codec @@ -7,18 +7,18 @@ 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 @@ -36,9 +36,8 @@ #ifndef MODES_H #define MODES_H -#include "speex.h" -#include "speex_bits.h" - +#include "speex/speex.h" +#include "arch.h" #define NB_SUBMODES 16 #define NB_SUBMODE_BITS 4 @@ -46,32 +45,49 @@ #define SB_SUBMODES 8 #define SB_SUBMODE_BITS 3 +/* Used internally, NOT TO BE USED in applications */ +/** Used internally*/ +#define SPEEX_GET_PI_GAIN 100 +/** Used internally*/ +#define SPEEX_GET_EXC 101 +/** Used internally*/ +#define SPEEX_GET_INNOV 102 +/** Used internally*/ +#define SPEEX_GET_DTX_STATUS 103 +/** Used internally*/ +#define SPEEX_SET_INNOVATION_SAVE 104 +/** Used internally*/ +#define SPEEX_SET_WIDEBAND 105 + +/** Used internally*/ +#define SPEEX_GET_STACK 106 + /** Quantizes LSPs */ -typedef void (*lsp_quant_func)(float *, float *, int, SpeexBits *); +typedef void (*lsp_quant_func)(spx_lsp_t *, spx_lsp_t *, int, SpeexBits *); /** Decodes quantized LSPs */ -typedef void (*lsp_unquant_func)(float *, int, SpeexBits *); +typedef void (*lsp_unquant_func)(spx_lsp_t *, int, SpeexBits *); /** Long-term predictor quantization */ -typedef int (*ltp_quant_func)(float *, float *, float *, float *, - float *, float *, void *, int, int, float, - int, int, SpeexBits*, char *, float *, float *, int); +typedef int (*ltp_quant_func)(spx_word16_t *, spx_word16_t *, spx_coef_t *, spx_coef_t *, + spx_coef_t *, spx_sig_t *, const void *, int, int, spx_word16_t, + int, int, SpeexBits*, char *, spx_word16_t *, spx_word16_t *, int, int, int, spx_word32_t *); /** Long-term un-quantize */ -typedef void (*ltp_unquant_func)(float *, int, int, float, void *, int, int *, - float *, SpeexBits*, char*, int, int, float); +typedef void (*ltp_unquant_func)(spx_word16_t *, spx_word32_t *, int, int, spx_word16_t, const void *, int, int *, + spx_word16_t *, SpeexBits*, char*, int, int, spx_word16_t, int); /** Innovation quantization function */ -typedef void (*innovation_quant_func)(float *, float *, float *, float *, void *, int, int, - float *, float *, SpeexBits *, char *, int); +typedef void (*innovation_quant_func)(spx_word16_t *, spx_coef_t *, spx_coef_t *, spx_coef_t *, const void *, int, int, + spx_sig_t *, spx_word16_t *, SpeexBits *, char *, int, int); /** Innovation unquantization function */ -typedef void (*innovation_unquant_func)(float *, void *, int, SpeexBits*, char *); +typedef void (*innovation_unquant_func)(spx_sig_t *, const void *, int, SpeexBits*, char *, spx_uint32_t *); -/** Description of a Speex sub-mode (wither narrowband or wideband */ +/** Description of a Speex sub-mode (either narrowband or wideband) */ typedef struct SpeexSubmode { int lbr_pitch; /**< Set to -1 for "normal" modes, otherwise encode pitch using a global pitch and allowing a +- lbr_pitch variation (for low not-rates)*/ int forced_pitch_gain; /**< Use the same (forced) pitch gain for all sub-frames */ @@ -81,20 +97,17 @@ typedef struct SpeexSubmode { lsp_quant_func lsp_quant; /**< LSP quantization function */ lsp_unquant_func lsp_unquant; /**< LSP unquantization function */ - /*Lont-term predictor functions*/ + /*Long-term predictor functions*/ ltp_quant_func ltp_quant; /**< Long-term predictor (pitch) quantizer */ ltp_unquant_func ltp_unquant; /**< Long-term predictor (pitch) un-quantizer */ - void *ltp_params; /**< Pitch parameters (options) */ + const void *ltp_params; /**< Pitch parameters (options) */ /*Quantization of innovation*/ innovation_quant_func innovation_quant; /**< Innovation quantization */ innovation_unquant_func innovation_unquant; /**< Innovation un-quantization */ - void *innovation_params; /**< Innovation quantization parameters*/ + const void *innovation_params; /**< Innovation quantization parameters*/ - /*Synthesis filter enhancement*/ - float lpc_enh_k1; /**< Enhancer constant */ - float lpc_enh_k2; /**< Enhancer constant */ - float comb_gain; /**< Gain of enhancer comb filter */ + spx_word16_t comb_gain; /**< Gain of enhancer comb filter */ int bits_per_frame; /**< Number of bits per frame after encoding*/ } SpeexSubmode; @@ -104,17 +117,14 @@ typedef struct SpeexNBMode { int frameSize; /**< Size of frames used for encoding */ int subframeSize; /**< Size of sub-frames used for encoding */ int lpcSize; /**< Order of LPC filter */ - int bufSize; /**< Size of signal buffer to use in encoder */ int pitchStart; /**< Smallest pitch value allowed */ int pitchEnd; /**< Largest pitch value allowed */ - float gamma1; /**< Perceptual filter parameter #1 */ - float gamma2; /**< Perceptual filter parameter #2 */ - float lag_factor; /**< Lag-windowing parameter */ - float lpc_floor; /**< Noise floor for LPC analysis */ - float preemph; /**< Pre-emphasis */ + spx_word16_t gamma1; /**< Perceptual filter parameter #1 */ + spx_word16_t gamma2; /**< Perceptual filter parameter #2 */ + spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */ - SpeexSubmode *submodes[NB_SUBMODES]; /**< Sub-mode data for the mode */ + const SpeexSubmode *submodes[NB_SUBMODES]; /**< Sub-mode data for the mode */ int defaultSubmode; /**< Default sub-mode to use when encoding */ int quality_map[11]; /**< Mode corresponding to each quality setting */ } SpeexNBMode; @@ -122,25 +132,29 @@ typedef struct SpeexNBMode { /** Struct defining the encoding/decoding mode for SB-CELP (wideband) */ typedef struct SpeexSBMode { - SpeexMode *nb_mode; /**< Embedded narrowband mode */ + const SpeexMode *nb_mode; /**< Embedded narrowband mode */ int frameSize; /**< Size of frames used for encoding */ int subframeSize; /**< Size of sub-frames used for encoding */ int lpcSize; /**< Order of LPC filter */ - int bufSize; /**< Signal buffer size in encoder */ - float gamma1; /**< Perceptual filter parameter #1 */ - float gamma2; /**< Perceptual filter parameter #1 */ - float lag_factor; /**< Lag-windowing parameter */ - float lpc_floor; /**< Noise floor for LPC analysis */ - float preemph; /**< Pre-emphasis */ - float folding_gain; + spx_word16_t gamma1; /**< Perceptual filter parameter #1 */ + spx_word16_t gamma2; /**< Perceptual filter parameter #1 */ + spx_word16_t lpc_floor; /**< Noise floor for LPC analysis */ + spx_word16_t folding_gain; - SpeexSubmode *submodes[SB_SUBMODES]; /**< Sub-mode data for the mode */ + const SpeexSubmode *submodes[SB_SUBMODES]; /**< Sub-mode data for the mode */ int defaultSubmode; /**< Default sub-mode to use when encoding */ int low_quality_map[11]; /**< Mode corresponding to each quality setting */ int quality_map[11]; /**< Mode corresponding to each quality setting */ - float (*vbr_thresh)[11]; +#ifndef DISABLE_VBR + const float (*vbr_thresh)[11]; +#endif int nb_modes; } SpeexSBMode; +int speex_encode_native(void *state, spx_word16_t *in, SpeexBits *bits); +int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out); + +int nb_mode_query(const void *mode, int request, void *ptr); +int wb_mode_query(const void *mode, int request, void *ptr); #endif diff --git a/external/speex/src/modes_wb.c b/external/speex/src/modes_wb.c new file mode 100644 index 0000000..aef5fdf --- /dev/null +++ b/external/speex/src/modes_wb.c @@ -0,0 +1,322 @@ +/* Copyright (C) 2002-2007 Jean-Marc Valin + File: modes.c + + Describes the wideband modes of the codec + + 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "modes.h" +#include "ltp.h" +#include "quant_lsp.h" +#include "cb_search.h" +#include "sb_celp.h" +#include "nb_celp.h" +#include "vbr.h" +#include "arch.h" +#include +#include "os_support.h" + + +#ifndef NULL +#define NULL 0 +#endif + +#if defined(DISABLE_ENCODER) || defined(DISABLE_WIDEBAND) +#define split_cb_search_shape_sign NULL +#define noise_codebook_quant NULL +#define pitch_search_3tap NULL +#define forced_pitch_quant NULL +#define sb_encoder_init NULL +#define sb_encoder_destroy NULL +#define sb_encode NULL +#define sb_encoder_ctl NULL +#define lsp_quant_high NULL +#endif /* DISABLE_ENCODER */ + +#if defined(DISABLE_DECODER) || defined(DISABLE_WIDEBAND) +#define noise_codebook_unquant NULL +#define split_cb_shape_sign_unquant NULL +#define lsp_unquant_high NULL +#define sb_decoder_init NULL +#define sb_decoder_destroy NULL +#define sb_decode NULL +#define sb_decoder_ctl NULL +#endif /* DISABLE_DECODER */ + +EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode}; + +extern const signed char hexc_table[]; +extern const signed char hexc_10_32_table[]; + +#ifndef DISABLE_WIDEBAND + +/* Split-VQ innovation for high-band wideband */ +static const split_cb_params split_cb_high = { + 8, /*subvect_size*/ + 5, /*nb_subvect*/ + hexc_table, /*shape_cb*/ + 7, /*shape_bits*/ + 1, +}; + + +/* Split-VQ innovation for high-band wideband */ +static const split_cb_params split_cb_high_lbr = { + 10, /*subvect_size*/ + 4, /*nb_subvect*/ + hexc_10_32_table, /*shape_cb*/ + 5, /*shape_bits*/ + 0, +}; + +#endif + + +static const SpeexSubmode wb_submode1 = { + 0, + 0, + 1, + 0, + /*LSP quantization*/ + lsp_quant_high, + lsp_unquant_high, + /*Pitch quantization*/ + NULL, + NULL, + NULL, + /*No innovation quantization*/ + NULL, + NULL, + NULL, + -1, + 36 +}; + + +static const SpeexSubmode wb_submode2 = { + 0, + 0, + 1, + 0, + /*LSP quantization*/ + lsp_quant_high, + lsp_unquant_high, + /*Pitch quantization*/ + NULL, + NULL, + NULL, + /*Innovation quantization*/ + split_cb_search_shape_sign, + split_cb_shape_sign_unquant, +#ifdef DISABLE_WIDEBAND + NULL, +#else + &split_cb_high_lbr, +#endif + -1, + 112 +}; + + +static const SpeexSubmode wb_submode3 = { + 0, + 0, + 1, + 0, + /*LSP quantization*/ + lsp_quant_high, + lsp_unquant_high, + /*Pitch quantization*/ + NULL, + NULL, + NULL, + /*Innovation quantization*/ + split_cb_search_shape_sign, + split_cb_shape_sign_unquant, +#ifdef DISABLE_WIDEBAND + NULL, +#else + &split_cb_high, +#endif + -1, + 192 +}; + +static const SpeexSubmode wb_submode4 = { + 0, + 0, + 1, + 1, + /*LSP quantization*/ + lsp_quant_high, + lsp_unquant_high, + /*Pitch quantization*/ + NULL, + NULL, + NULL, + /*Innovation quantization*/ + split_cb_search_shape_sign, + split_cb_shape_sign_unquant, +#ifdef DISABLE_WIDEBAND + NULL, +#else + &split_cb_high, +#endif + -1, + 352 +}; + + +/* Split-band wideband CELP mode*/ +static const SpeexSBMode sb_wb_mode = { + &speex_nb_mode, + 160, /*frameSize*/ + 40, /*subframeSize*/ + 8, /*lpcSize*/ +#ifdef FIXED_POINT + 29491, 19661, /* gamma1, gamma2 */ +#else + 0.9, 0.6, /* gamma1, gamma2 */ +#endif + QCONST16(.0002,15), /*lpc_floor*/ + QCONST16(0.9f,15), + {NULL, &wb_submode1, &wb_submode2, &wb_submode3, &wb_submode4, NULL, NULL, NULL}, + 3, + {1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7}, + {1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4}, +#ifndef DISABLE_VBR + vbr_hb_thresh, +#endif + 5 +}; + + +EXPORT const SpeexMode speex_wb_mode = { + &sb_wb_mode, + wb_mode_query, + "wideband (sub-band CELP)", + 1, + 4, + sb_encoder_init, + sb_encoder_destroy, + sb_encode, + sb_decoder_init, + sb_decoder_destroy, + sb_decode, + sb_encoder_ctl, + sb_decoder_ctl, +}; + + + +/* "Ultra-wideband" mode stuff */ + + + +/* Split-band "ultra-wideband" (32 kbps) CELP mode*/ +static const SpeexSBMode sb_uwb_mode = { + &speex_wb_mode, + 320, /*frameSize*/ + 80, /*subframeSize*/ + 8, /*lpcSize*/ +#ifdef FIXED_POINT + 29491, 19661, /* gamma1, gamma2 */ +#else + 0.9, 0.6, /* gamma1, gamma2 */ +#endif + QCONST16(.0002,15), /*lpc_floor*/ + QCONST16(0.7f,15), + {NULL, &wb_submode1, NULL, NULL, NULL, NULL, NULL, NULL}, + 1, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, +#ifndef DISABLE_VBR + vbr_uhb_thresh, +#endif + 2 +}; + +int wb_mode_query(const void *mode, int request, void *ptr) +{ + const SpeexSBMode *m = (const SpeexSBMode*)mode; + + switch (request) + { + case SPEEX_MODE_FRAME_SIZE: + *((int*)ptr)=2*m->frameSize; + break; + case SPEEX_SUBMODE_BITS_PER_FRAME: + if (*((int*)ptr)==0) + *((int*)ptr) = SB_SUBMODE_BITS+1; + else if (m->submodes[*((int*)ptr)]==NULL) + *((int*)ptr) = -1; + else + *((int*)ptr) = m->submodes[*((int*)ptr)]->bits_per_frame; + break; + default: + speex_warning_int("Unknown wb_mode_query request: ", request); + return -1; + } + return 0; +} + + +EXPORT const SpeexMode speex_uwb_mode = { + &sb_uwb_mode, + wb_mode_query, + "ultra-wideband (sub-band CELP)", + 2, + 4, + sb_encoder_init, + sb_encoder_destroy, + sb_encode, + sb_decoder_init, + sb_decoder_destroy, + sb_decode, + sb_encoder_ctl, + sb_decoder_ctl, +}; + +/* We have defined speex_lib_get_mode() as a macro in speex.h */ +#undef speex_lib_get_mode + +EXPORT const SpeexMode * speex_lib_get_mode (int mode) +{ + if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL; + + return speex_mode_list[mode]; +} + + + diff --git a/external/speex/src/nb_celp.c b/external/speex/src/nb_celp.c index 63920fc..6f4f0ad 100644 --- a/external/speex/src/nb_celp.c +++ b/external/speex/src/nb_celp.c @@ -1,21 +1,21 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002-2006 Jean-Marc Valin File: nb_celp.c 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 @@ -29,6 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "nb_celp.h" #include "lpc.h" @@ -39,18 +43,13 @@ #include "filters.h" #include "stack_alloc.h" #include "vq.h" -#include "speex_bits.h" #include "vbr.h" -#include "misc.h" -#include "speex_callbacks.h" - -#ifdef SLOW_TRIG +#include "arch.h" #include "math_approx.h" -#define cos speex_cos -#endif +#include "os_support.h" -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ +#ifdef VORBIS_PSYCHO +#include "vorbis_psy.h" #endif #ifndef NULL @@ -59,122 +58,115 @@ #define SUBMODE(x) st->submodes[st->submodeID]->x -float exc_gain_quant_scal3[8]={-2.794750, -1.810660, -1.169850, -0.848119, -0.587190, -0.329818, -0.063266, 0.282826}; +/* Default size for the encoder and decoder stack (can be changed at compile time). + This does not apply when using variable-size arrays or alloca. */ +#ifndef NB_ENC_STACK +#define NB_ENC_STACK (8000*sizeof(spx_sig_t)) +#endif -float exc_gain_quant_scal1[2]={-0.35, 0.05}; +#ifndef NB_DEC_STACK +#define NB_DEC_STACK (4000*sizeof(spx_sig_t)) +#endif -#define sqr(x) ((x)*(x)) -void *nb_encoder_init(SpeexMode *m) +#ifdef FIXED_POINT +static const spx_word32_t ol_gain_table[32]={18900, 25150, 33468, 44536, 59265, 78865, 104946, 139653, 185838, 247297, 329081, 437913, 582736, 775454, 1031906, 1373169, 1827293, 2431601, 3235761, 4305867, 5729870, 7624808, 10146425, 13501971, 17967238, 23909222, 31816294, 42338330, 56340132, 74972501, 99766822, 132760927}; +static const spx_word16_t exc_gain_quant_scal3_bound[7]={1841, 3883, 6051, 8062, 10444, 13580, 18560}; +static const spx_word16_t exc_gain_quant_scal3[8]={1002, 2680, 5086, 7016, 9108, 11781, 15380, 21740}; +static const spx_word16_t exc_gain_quant_scal1_bound[1]={14385}; +static const spx_word16_t exc_gain_quant_scal1[2]={11546, 17224}; + +#define LSP_MARGIN 16 +#define LSP_DELTA1 6553 +#define LSP_DELTA2 1638 + +#else + +static const float exc_gain_quant_scal3_bound[7]={0.112338f, 0.236980f, 0.369316f, 0.492054f, 0.637471f, 0.828874f, 1.132784f}; +static const float exc_gain_quant_scal3[8]={0.061130f, 0.163546f, 0.310413f, 0.428220f, 0.555887f, 0.719055f, 0.938694f, 1.326874f}; +static const float exc_gain_quant_scal1_bound[1]={0.87798f}; +static const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f}; + +#define LSP_MARGIN .002f +#define LSP_DELTA1 .2f +#define LSP_DELTA2 .05f + +#endif + +extern const spx_word16_t lag_window[]; +extern const spx_word16_t lpc_window[]; + +#ifndef DISABLE_ENCODER +void *nb_encoder_init(const SpeexMode *m) { EncState *st; - SpeexNBMode *mode; + const SpeexNBMode *mode; int i; - mode=(SpeexNBMode *)m->mode; - st = (EncState*)speex_alloc(sizeof(EncState)+8000*sizeof(float)); + mode=(const SpeexNBMode *)m->mode; + st = (EncState*)speex_alloc(sizeof(EncState)); if (!st) return NULL; +#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) + st->stack = NULL; +#else + st->stack = (char*)speex_alloc_scratch(NB_ENC_STACK); +#endif - st->stack = ((char*)st) + sizeof(EncState); - st->mode=m; - st->frameSize = mode->frameSize; - st->windowSize = st->frameSize*3/2; - st->nbSubframes=mode->frameSize/mode->subframeSize; - st->subframeSize=mode->subframeSize; - st->lpcSize = mode->lpcSize; - st->bufSize = mode->bufSize; st->gamma1=mode->gamma1; st->gamma2=mode->gamma2; - st->min_pitch=mode->pitchStart; - st->max_pitch=mode->pitchEnd; - st->lag_factor=mode->lag_factor; st->lpc_floor = mode->lpc_floor; - st->preemph = mode->preemph; - + st->submodes=mode->submodes; st->submodeID=st->submodeSelect=mode->defaultSubmode; - st->pre_mem=0; - st->pre_mem2=0; st->bounded_pitch = 1; - /* Allocating input buffer */ - st->inBuf = PUSH(st->stack, st->bufSize, float); - st->frame = st->inBuf + st->bufSize - st->windowSize; - /* Allocating excitation buffer */ - st->excBuf = PUSH(st->stack, st->bufSize, float); - st->exc = st->excBuf + st->bufSize - st->windowSize; - st->swBuf = PUSH(st->stack, st->bufSize, float); - st->sw = st->swBuf + st->bufSize - st->windowSize; + st->encode_submode = 1; - st->exc2Buf = PUSH(st->stack, st->bufSize, float); - st->exc2 = st->exc2Buf + st->bufSize - st->windowSize; +#ifdef VORBIS_PSYCHO + st->psy = vorbis_psy_init(8000, 256); + st->curve = (float*)speex_alloc(128*sizeof(float)); + st->old_curve = (float*)speex_alloc(128*sizeof(float)); + st->psy_window = (float*)speex_alloc(256*sizeof(float)); +#endif - st->innov = PUSH(st->stack, st->frameSize, float); + st->cumul_gain = 1024; + + st->window= lpc_window; - /* Asymmetric "pseudo-Hamming" window */ - { - int part1, part2; - part1 = st->subframeSize*7/2; - part2 = st->subframeSize*5/2; - st->window = PUSH(st->stack, st->windowSize, float); - for (i=0;iwindow[i]=.54-.46*cos(M_PI*i/part1); - for (i=0;iwindow[part1+i]=.54+.46*cos(M_PI*i/part2); - } /* Create the window for autocorrelation (lag-windowing) */ - st->lagWindow = PUSH(st->stack, st->lpcSize+1, float); - for (i=0;ilpcSize+1;i++) - st->lagWindow[i]=exp(-.5*sqr(2*M_PI*st->lag_factor*i)); + st->lagWindow = lag_window; - st->autocorr = PUSH(st->stack, st->lpcSize+1, float); - - st->buf2 = PUSH(st->stack, st->windowSize, float); - - st->lpc = PUSH(st->stack, st->lpcSize+1, float); - st->interp_lpc = PUSH(st->stack, st->lpcSize+1, float); - st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, float); - st->bw_lpc1 = PUSH(st->stack, st->lpcSize+1, float); - st->bw_lpc2 = PUSH(st->stack, st->lpcSize+1, float); - - st->lsp = PUSH(st->stack, st->lpcSize, float); - st->qlsp = PUSH(st->stack, st->lpcSize, float); - st->old_lsp = PUSH(st->stack, st->lpcSize, float); - st->old_qlsp = PUSH(st->stack, st->lpcSize, float); - st->interp_lsp = PUSH(st->stack, st->lpcSize, float); - st->interp_qlsp = PUSH(st->stack, st->lpcSize, float); - st->rc = PUSH(st->stack, st->lpcSize, float); st->first = 1; - for (i=0;ilpcSize;i++) - { - st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); - } + for (i=0;iold_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), NB_ORDER+1); - st->mem_sp = PUSH(st->stack, st->lpcSize, float); - st->mem_sw = PUSH(st->stack, st->lpcSize, float); - st->mem_sw_whole = PUSH(st->stack, st->lpcSize, float); - st->mem_exc = PUSH(st->stack, st->lpcSize, float); + st->innov_rms_save = NULL; - st->pi_gain = PUSH(st->stack, st->nbSubframes, float); - - st->pitch = PUSH(st->stack, st->nbSubframes, int); - - st->vbr = PUSHS(st->stack, VBRState); - vbr_init(st->vbr); +#ifndef DISABLE_VBR + vbr_init(&st->vbr); st->vbr_quality = 8; st->vbr_enabled = 0; + st->vbr_max = 0; st->vad_enabled = 0; st->dtx_enabled = 0; + st->dtx_count=0; st->abr_enabled = 0; st->abr_drift = 0; + st->abr_drift2 = 0; +#endif /* #ifndef DISABLE_VBR */ + st->plc_tuning = 2; st->complexity=2; st->sampling_rate=8000; - st->dtx_count=0; + st->isWideband = 0; + st->highpass_enabled = 1; +#ifdef ENABLE_VALGRIND + VALGRIND_MAKE_MEM_DEFINED(st, NB_ENC_STACK); +#endif return st; } @@ -182,130 +174,361 @@ void nb_encoder_destroy(void *state) { EncState *st=(EncState *)state; /* Free all allocated memory */ +#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) + speex_free_scratch(st->stack); +#endif - vbr_destroy(st->vbr); +#ifndef DISABLE_VBR + vbr_destroy(&st->vbr); +#endif /* #ifndef DISABLE_VBR */ + +#ifdef VORBIS_PSYCHO + vorbis_psy_destroy(st->psy); + speex_free (st->curve); + speex_free (st->old_curve); + speex_free (st->psy_window); +#endif /*Free state memory... should be last*/ speex_free(st); } -int nb_encode(void *state, float *in, SpeexBits *bits) + +int nb_encoder_ctl(void *state, int request, void *ptr) +{ + EncState *st; + st=(EncState*)state; + switch(request) + { + case SPEEX_GET_FRAME_SIZE: + (*(spx_int32_t*)ptr) = NB_FRAME_SIZE; + break; + case SPEEX_SET_LOW_MODE: + case SPEEX_SET_MODE: + st->submodeSelect = st->submodeID = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_LOW_MODE: + case SPEEX_GET_MODE: + (*(spx_int32_t*)ptr) = st->submodeID; + break; +#ifndef DISABLE_VBR + case SPEEX_SET_VBR: + st->vbr_enabled = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_VBR: + (*(spx_int32_t*)ptr) = st->vbr_enabled; + break; + case SPEEX_SET_VAD: + st->vad_enabled = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_VAD: + (*(spx_int32_t*)ptr) = st->vad_enabled; + break; + case SPEEX_SET_DTX: + st->dtx_enabled = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_DTX: + (*(spx_int32_t*)ptr) = st->dtx_enabled; + break; + case SPEEX_SET_ABR: + st->abr_enabled = (*(spx_int32_t*)ptr); + st->vbr_enabled = st->abr_enabled!=0; + if (st->vbr_enabled) + { + spx_int32_t i=10; + spx_int32_t rate, target; + float vbr_qual; + target = (*(spx_int32_t*)ptr); + while (i>=0) + { + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); + speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); + if (rate <= target) + break; + i--; + } + vbr_qual=i; + if (vbr_qual<0) + vbr_qual=0; + speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); + st->abr_count=0; + st->abr_drift=0; + st->abr_drift2=0; + } + + break; + case SPEEX_GET_ABR: + (*(spx_int32_t*)ptr) = st->abr_enabled; + break; +#endif /* #ifndef DISABLE_VBR */ +#if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) + case SPEEX_SET_VBR_QUALITY: + st->vbr_quality = (*(float*)ptr); + break; + case SPEEX_GET_VBR_QUALITY: + (*(float*)ptr) = st->vbr_quality; + break; +#endif /* !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */ + case SPEEX_SET_QUALITY: + { + int quality = (*(spx_int32_t*)ptr); + if (quality < 0) + quality = 0; + if (quality > 10) + quality = 10; + st->submodeSelect = st->submodeID = ((const SpeexNBMode*)(st->mode->mode))->quality_map[quality]; + } + break; + case SPEEX_SET_COMPLEXITY: + st->complexity = (*(spx_int32_t*)ptr); + if (st->complexity<0) + st->complexity=0; + break; + case SPEEX_GET_COMPLEXITY: + (*(spx_int32_t*)ptr) = st->complexity; + break; + case SPEEX_SET_BITRATE: + { + spx_int32_t i=10; + spx_int32_t rate, target; + target = (*(spx_int32_t*)ptr); + while (i>=0) + { + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); + speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); + if (rate <= target) + break; + i--; + } + } + break; + case SPEEX_GET_BITRATE: + if (st->submodes[st->submodeID]) + (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/NB_FRAME_SIZE; + else + (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/NB_FRAME_SIZE; + break; + case SPEEX_SET_SAMPLING_RATE: + st->sampling_rate = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_SAMPLING_RATE: + (*(spx_int32_t*)ptr)=st->sampling_rate; + break; + case SPEEX_RESET_STATE: + { + int i; + st->bounded_pitch = 1; + st->first = 1; + for (i=0;iold_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), NB_ORDER+1); + for (i=0;imem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0; + for (i=0;iexcBuf[i]=st->swBuf[i]=0; + for (i=0;iwinBuf[i]=0; + } + break; + case SPEEX_SET_SUBMODE_ENCODING: + st->encode_submode = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_SUBMODE_ENCODING: + (*(spx_int32_t*)ptr) = st->encode_submode; + break; + case SPEEX_GET_LOOKAHEAD: + (*(spx_int32_t*)ptr)=(NB_WINDOW_SIZE-NB_FRAME_SIZE); + break; + case SPEEX_SET_PLC_TUNING: + st->plc_tuning = (*(spx_int32_t*)ptr); + if (st->plc_tuning>100) + st->plc_tuning=100; + break; + case SPEEX_GET_PLC_TUNING: + (*(spx_int32_t*)ptr)=(st->plc_tuning); + break; +#ifndef DISABLE_VBR + case SPEEX_SET_VBR_MAX_BITRATE: + st->vbr_max = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_VBR_MAX_BITRATE: + (*(spx_int32_t*)ptr) = st->vbr_max; + break; +#endif /* #ifndef DISABLE_VBR */ + case SPEEX_SET_HIGHPASS: + st->highpass_enabled = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_HIGHPASS: + (*(spx_int32_t*)ptr) = st->highpass_enabled; + break; + + /* This is all internal stuff past this point */ + case SPEEX_GET_PI_GAIN: + { + int i; + spx_word32_t *g = (spx_word32_t*)ptr; + for (i=0;ipi_gain[i]; + } + break; + case SPEEX_GET_EXC: + { + int i; + for (i=0;iexc+i*NB_SUBFRAME_SIZE, NB_SUBFRAME_SIZE); + } + break; +#ifndef DISABLE_VBR + case SPEEX_GET_RELATIVE_QUALITY: + (*(float*)ptr)=st->relative_quality; + break; +#endif /* #ifndef DISABLE_VBR */ + case SPEEX_SET_INNOVATION_SAVE: + st->innov_rms_save = (spx_word16_t*)ptr; + break; + case SPEEX_SET_WIDEBAND: + st->isWideband = *((spx_int32_t*)ptr); + break; + case SPEEX_GET_STACK: + *((char**)ptr) = st->stack; + break; + default: + speex_warning_int("Unknown nb_ctl request: ", request); + return -1; + } + return 0; +} + + +int nb_encode(void *state, void *vin, SpeexBits *bits) { EncState *st; int i, sub, roots; int ol_pitch; - float ol_pitch_coef; - float ol_gain; - float *res, *target, *mem; + spx_word16_t ol_pitch_coef; + spx_word32_t ol_gain; + VARDECL(spx_word16_t *target); + VARDECL(spx_sig_t *innov); + VARDECL(spx_word32_t *exc32); + VARDECL(spx_mem_t *mem); + VARDECL(spx_coef_t *bw_lpc1); + VARDECL(spx_coef_t *bw_lpc2); + VARDECL(spx_coef_t *lpc); + VARDECL(spx_lsp_t *lsp); + VARDECL(spx_lsp_t *qlsp); + VARDECL(spx_lsp_t *interp_lsp); + VARDECL(spx_lsp_t *interp_qlsp); + VARDECL(spx_coef_t *interp_lpc); + VARDECL(spx_coef_t *interp_qlpc); char *stack; - float *syn_resp; - float lsp_dist=0; - float *orig; + VARDECL(spx_word16_t *syn_resp); + + spx_word32_t ener=0; + spx_word16_t fine_gain; + spx_word16_t *in = (spx_word16_t*)vin; st=(EncState *)state; stack=st->stack; - /* Copy new data in input buffer */ - speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - st->inBuf[st->bufSize-st->frameSize] = in[0] - st->preemph*st->pre_mem; - for (i=1;iframeSize;i++) - st->inBuf[st->bufSize-st->frameSize+i] = in[i] - st->preemph*in[i-1]; - st->pre_mem = in[st->frameSize-1]; + ALLOC(lpc, NB_ORDER, spx_coef_t); + ALLOC(bw_lpc1, NB_ORDER, spx_coef_t); + ALLOC(bw_lpc2, NB_ORDER, spx_coef_t); + ALLOC(lsp, NB_ORDER, spx_lsp_t); + ALLOC(qlsp, NB_ORDER, spx_lsp_t); + ALLOC(interp_lsp, NB_ORDER, spx_lsp_t); + ALLOC(interp_qlsp, NB_ORDER, spx_lsp_t); + ALLOC(interp_lpc, NB_ORDER, spx_coef_t); + ALLOC(interp_qlpc, NB_ORDER, spx_coef_t); + st->exc = st->excBuf + NB_PITCH_END + 2; + st->sw = st->swBuf + NB_PITCH_END + 2; /* Move signals 1 frame towards the past */ - speex_move(st->exc2Buf, st->exc2Buf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - speex_move(st->swBuf, st->swBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); + SPEEX_MOVE(st->excBuf, st->excBuf+NB_FRAME_SIZE, NB_PITCH_END+2); + SPEEX_MOVE(st->swBuf, st->swBuf+NB_FRAME_SIZE, NB_PITCH_END+2); + if (st->highpass_enabled) + highpass(in, in, NB_FRAME_SIZE, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS_NARROWBAND)|HIGHPASS_INPUT, st->mem_hp); - /* Window for analysis */ - for (i=0;iwindowSize;i++) - st->buf2[i] = st->frame[i] * st->window[i]; - - /* Compute auto-correlation */ - _spx_autocorr(st->buf2, st->autocorr, st->lpcSize+1, st->windowSize); - - st->autocorr[0] += 10; /* prevents NANs */ - st->autocorr[0] *= st->lpc_floor; /* Noise floor in auto-correlation domain */ - - /* Lag windowing: equivalent to filtering in the power-spectrum domain */ - for (i=0;ilpcSize+1;i++) - st->autocorr[i] *= st->lagWindow[i]; - - /* Levinson-Durbin */ - wld(st->lpc+1, st->autocorr, st->rc, st->lpcSize); - st->lpc[0]=1; - - /* LPC to LSPs (x-domain) transform */ - roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, 0.2, stack); - /* Check if we found all the roots */ - if (roots==st->lpcSize) { - /* LSP x-domain to angle domain*/ - for (i=0;ilpcSize;i++) - st->lsp[i] = acos(st->lsp[i]); - } else { - /* Search again if we can afford it */ - if (st->complexity>1) - roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, 0.05, stack); - if (roots==st->lpcSize) + VARDECL(spx_word16_t *w_sig); + VARDECL(spx_word16_t *autocorr); + ALLOC(w_sig, NB_WINDOW_SIZE, spx_word16_t); + ALLOC(autocorr, NB_ORDER+1, spx_word16_t); + /* Window for analysis */ + for (i=0;iwinBuf[i],st->window[i]); + for (;iwindow[i]); + /* Compute auto-correlation */ + _spx_autocorr(w_sig, autocorr, NB_ORDER+1, NB_WINDOW_SIZE); + autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */ + + /* Lag windowing: equivalent to filtering in the power-spectrum domain */ + for (i=0;ilagWindow[i]); + autocorr[0] = ADD16(autocorr[0],1); + + /* Levinson-Durbin */ + _spx_lpc(lpc, autocorr, NB_ORDER); + /* LPC to LSPs (x-domain) transform */ + roots=lpc_to_lsp (lpc, NB_ORDER, lsp, 10, LSP_DELTA1, stack); + /* Check if we found all the roots */ + if (roots!=NB_ORDER) { - /* LSP x-domain to angle domain*/ - for (i=0;ilpcSize;i++) - st->lsp[i] = acos(st->lsp[i]); - } else { /*If we can't find all LSP's, do some damage control and use previous filter*/ - for (i=0;ilpcSize;i++) + for (i=0;ilsp[i]=st->old_lsp[i]; + lsp[i]=st->old_lsp[i]; } } } - lsp_dist=0; - for (i=0;ilpcSize;i++) - lsp_dist += (st->old_lsp[i] - st->lsp[i])*(st->old_lsp[i] - st->lsp[i]); + /* Whole frame analysis (open-loop estimation of pitch and excitation gain) */ { + int diff = NB_WINDOW_SIZE-NB_FRAME_SIZE; if (st->first) - for (i=0;ilpcSize;i++) - st->interp_lsp[i] = st->lsp[i]; + for (i=0;ilpcSize;i++) - st->interp_lsp[i] = .375*st->old_lsp[i] + .625*st->lsp[i]; - - lsp_enforce_margin(st->interp_lsp, st->lpcSize, .002); + lsp_interpolate(st->old_lsp, lsp, interp_lsp, NB_ORDER, NB_NB_SUBFRAMES, NB_NB_SUBFRAMES<<1, LSP_MARGIN); /* Compute interpolated LPCs (unquantized) for whole frame*/ - for (i=0;ilpcSize;i++) - st->interp_lsp[i] = cos(st->interp_lsp[i]); - lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack); + lsp_to_lpc(interp_lsp, interp_lpc, NB_ORDER,stack); /*Open-loop pitch*/ - if (!st->submodes[st->submodeID] || st->vbr_enabled || st->vad_enabled || SUBMODE(forced_pitch_gain) || - SUBMODE(lbr_pitch) != -1) + if (!st->submodes[st->submodeID] || (st->complexity>2 && SUBMODE(have_subframe_gain)<3) || SUBMODE(forced_pitch_gain) || SUBMODE(lbr_pitch) != -1 +#ifndef DISABLE_VBR + || st->vbr_enabled || st->vad_enabled +#endif + ) { int nol_pitch[6]; - float nol_pitch_coef[6]; - - bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize); - bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize); - - filter_mem2(st->frame, st->bw_lpc1, st->bw_lpc2, st->sw, st->frameSize, st->lpcSize, st->mem_sw_whole); + spx_word16_t nol_pitch_coef[6]; - open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize, + bw_lpc(QCONST16(0.9,15), interp_lpc, bw_lpc1, NB_ORDER); + bw_lpc(QCONST16(0.55,15), interp_lpc, bw_lpc2, NB_ORDER); + + SPEEX_COPY(st->sw, st->winBuf, diff); + SPEEX_COPY(st->sw+diff, in, NB_FRAME_SIZE-diff); + filter10(st->sw, bw_lpc1, bw_lpc2, st->sw, NB_FRAME_SIZE, st->mem_sw_whole, stack); + + open_loop_nbest_pitch(st->sw, NB_PITCH_START, NB_PITCH_END, NB_FRAME_SIZE, nol_pitch, nol_pitch_coef, 6, stack); ol_pitch=nol_pitch[0]; ol_pitch_coef = nol_pitch_coef[0]; /*Try to remove pitch multiples*/ for (i=1;i<6;i++) { - if ((nol_pitch_coef[i]>.85*ol_pitch_coef) && - (fabs(nol_pitch[i]-ol_pitch/2.0)<=1 || fabs(nol_pitch[i]-ol_pitch/3.0)<=1 || - fabs(nol_pitch[i]-ol_pitch/4.0)<=1 || fabs(nol_pitch[i]-ol_pitch/5.0)<=1)) +#ifdef FIXED_POINT + if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],27853)) && +#else + if ((nol_pitch_coef[i]>.85*nol_pitch_coef[0]) && +#endif + (ABS(2*nol_pitch[i]-ol_pitch)<=2 || ABS(3*nol_pitch[i]-ol_pitch)<=3 || + ABS(4*nol_pitch[i]-ol_pitch)<=4 || ABS(5*nol_pitch[i]-ol_pitch)<=5)) { /*ol_pitch_coef=nol_pitch_coef[i];*/ ol_pitch = nol_pitch[i]; @@ -314,25 +537,47 @@ int nb_encode(void *state, float *in, SpeexBits *bits) /*if (ol_pitch>50) ol_pitch/=2;*/ /*ol_pitch_coef = sqrt(ol_pitch_coef);*/ + } else { ol_pitch=0; ol_pitch_coef=0; } + /*Compute "real" excitation*/ - fir_mem2(st->frame, st->interp_lpc, st->exc, st->frameSize, st->lpcSize, st->mem_exc); + /*SPEEX_COPY(st->exc, st->winBuf, diff); + SPEEX_COPY(st->exc+diff, in, NB_FRAME_SIZE-diff);*/ + fir_mem16(st->winBuf, interp_lpc, st->exc, diff, NB_ORDER, st->mem_exc, stack); + fir_mem16(in, interp_lpc, st->exc+diff, NB_FRAME_SIZE-diff, NB_ORDER, st->mem_exc, stack); /* Compute open-loop excitation gain */ - ol_gain=0; - for (i=0;iframeSize;i++) - ol_gain += st->exc[i]*st->exc[i]; - - ol_gain=sqrt(1+ol_gain/st->frameSize); + { + spx_word16_t g = compute_rms16(st->exc, NB_FRAME_SIZE); + if (st->submodeID!=1 && ol_pitch>0) + ol_gain = MULT16_16(g, MULT16_16_Q14(QCONST16(1.1,14), + spx_sqrt(QCONST32(1.,28)-MULT16_32_Q15(QCONST16(.8,15),SHL32(MULT16_16(ol_pitch_coef,ol_pitch_coef),16))))); + else + ol_gain = SHL32(EXTEND32(g),SIG_SHIFT); + } } +#ifdef VORBIS_PSYCHO + SPEEX_MOVE(st->psy_window, st->psy_window+NB_FRAME_SIZE, 256-NB_FRAME_SIZE); + SPEEX_COPY(&st->psy_window[256-NB_FRAME_SIZE], in, NB_FRAME_SIZE); + compute_curve(st->psy, st->psy_window, st->curve); + /*print_vec(st->curve, 128, "curve");*/ + if (st->first) + SPEEX_COPY(st->old_curve, st->curve, 128); +#endif + /*VBR stuff*/ - if (st->vbr && (st->vbr_enabled||st->vad_enabled)) +#ifndef DISABLE_VBR + if (st->vbr_enabled||st->vad_enabled) { - + float lsp_dist=0; + for (i=0;iold_lsp[i] - lsp[i])*(st->old_lsp[i] - lsp[i]); + lsp_dist /= LSP_SCALING*LSP_SCALING; + if (st->abr_enabled) { float qual_change=0; @@ -352,12 +597,12 @@ int nb_encode(void *state, float *in, SpeexBits *bits) st->vbr_quality=0; } - st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, ol_pitch_coef); + st->relative_quality = vbr_analysis(&st->vbr, in, NB_FRAME_SIZE, ol_pitch, GAIN_SCALING_1*ol_pitch_coef); /*if (delta_qual<0)*/ /* delta_qual*=.1*(3+st->vbr_quality);*/ - if (st->vbr_enabled) + if (st->vbr_enabled) { - int mode; + spx_int32_t mode; int choice=0; float min_diff=100; mode = 8; @@ -370,7 +615,7 @@ int nb_encode(void *state, float *in, SpeexBits *bits) thresh = vbr_nb_thresh[mode][v1]; else thresh = (st->vbr_quality-v1)*vbr_nb_thresh[mode][v1+1] + (1+v1-st->vbr_quality)*vbr_nb_thresh[mode][v1]; - if (st->relative_quality > thresh && + if (st->relative_quality > thresh && st->relative_quality-threshvbr_max>0) + { + spx_int32_t rate; + speex_encoder_ctl(state, SPEEX_GET_BITRATE, &rate); + if (rate > st->vbr_max) + { + rate = st->vbr_max; + speex_encoder_ctl(state, SPEEX_SET_BITRATE, &rate); + } + } if (st->abr_enabled) { - int bitrate; + spx_int32_t bitrate; speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate); st->abr_drift+=(bitrate-st->abr_enabled); st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled); @@ -423,37 +678,38 @@ int nb_encode(void *state, float *in, SpeexBits *bits) } /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ st->submodeID=mode; - } + } } else { st->relative_quality = -1; } +#endif /* #ifndef DISABLE_VBR */ - /* First, transmit a zero for narrowband */ - speex_bits_pack(bits, 0, 1); + if (st->encode_submode) + { + /* First, transmit a zero for narrowband */ + speex_bits_pack(bits, 0, 1); - /* Transmit the sub-mode we use for this frame */ - speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS); + /* Transmit the sub-mode we use for this frame */ + speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS); + } /* If null mode (no transmission), just set a couple things to zero*/ if (st->submodes[st->submodeID] == NULL) { - for (i=0;iframeSize;i++) - st->exc[i]=st->exc2[i]=st->sw[i]=0; + for (i=0;iexc[i]=st->sw[i]=VERY_SMALL; - for (i=0;ilpcSize;i++) + for (i=0;imem_sw[i]=0; st->first=1; st->bounded_pitch = 1; - /* Final signal synthesis from excitation */ - iir_mem2(st->exc, st->interp_qlpc, st->frame, st->frameSize, st->lpcSize, st->mem_sp); - - in[0] = st->frame[0] + st->preemph*st->pre_mem2; - for (i=1;iframeSize;i++) - in[i]=st->frame[i] + st->preemph*in[i-1]; - st->pre_mem2=in[st->frameSize-1]; + SPEEX_COPY(st->winBuf, in+2*NB_FRAME_SIZE-NB_WINDOW_SIZE, NB_WINDOW_SIZE-NB_FRAME_SIZE); + /* Clear memory (no need to really compute it) */ + for (i=0;imem_sp[i] = 0; return 0; } @@ -461,162 +717,182 @@ int nb_encode(void *state, float *in, SpeexBits *bits) /* LSP Quantization */ if (st->first) { - for (i=0;ilpcSize;i++) - st->old_lsp[i] = st->lsp[i]; + for (i=0;iold_lsp[i] = lsp[i]; } /*Quantize LSPs*/ #if 1 /*0 for unquantized*/ - SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits); + SUBMODE(lsp_quant)(lsp, qlsp, NB_ORDER, bits); #else - for (i=0;ilpcSize;i++) - st->qlsp[i]=st->lsp[i]; + for (i=0;imin_pitch, 7); - } - + speex_bits_pack(bits, ol_pitch-NB_PITCH_START, 7); + } + if (SUBMODE(forced_pitch_gain)) { int quant; - quant = (int)floor(.5+15*ol_pitch_coef); + /* This just damps the pitch a bit, because it tends to be too aggressive when forced */ + ol_pitch_coef = MULT16_16_Q15(QCONST16(.9,15), ol_pitch_coef); +#ifdef FIXED_POINT + quant = PSHR16(MULT16_16_16(15, ol_pitch_coef),GAIN_SHIFT); +#else + quant = (int)floor(.5+15*ol_pitch_coef*GAIN_SCALING_1); +#endif if (quant>15) quant=15; if (quant<0) quant=0; speex_bits_pack(bits, quant, 4); - ol_pitch_coef=0.066667*quant; + ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT)); } - - + + /*Quantize and transmit open-loop excitation gain*/ +#ifdef FIXED_POINT { - int qe = (int)(floor(3.5*log(ol_gain))); + int qe = scal_quant32(ol_gain, ol_gain_table, 32); + /*ol_gain = exp(qe/3.5)*SIG_SCALING;*/ + ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]); + speex_bits_pack(bits, qe, 5); + } +#else + { + int qe = (int)(floor(.5+3.5*log(ol_gain*1.0/SIG_SCALING))); if (qe<0) qe=0; if (qe>31) qe=31; - ol_gain = exp(qe/3.5); + ol_gain = exp(qe/3.5)*SIG_SCALING; speex_bits_pack(bits, qe, 5); } +#endif + + /* Special case for first frame */ if (st->first) { - for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + for (i=0;iold_qlsp[i] = qlsp[i]; } - /* Filter response */ - res = PUSH(stack, st->subframeSize, float); /* Target signal */ - target = PUSH(stack, st->subframeSize, float); - syn_resp = PUSH(stack, st->subframeSize, float); - mem = PUSH(stack, st->lpcSize, float); - orig = PUSH(stack, st->frameSize, float); - for (i=0;iframeSize;i++) - orig[i]=st->frame[i]; + ALLOC(target, NB_SUBFRAME_SIZE, spx_word16_t); + ALLOC(innov, NB_SUBFRAME_SIZE, spx_sig_t); + ALLOC(exc32, NB_SUBFRAME_SIZE, spx_word32_t); + ALLOC(syn_resp, NB_SUBFRAME_SIZE, spx_word16_t); + ALLOC(mem, NB_ORDER, spx_mem_t); /* Loop on sub-frames */ - for (sub=0;subnbSubframes;sub++) + for (sub=0;subsubframeSize*sub; - /* Original signal */ - sp=st->frame+offset; + offset = NB_SUBFRAME_SIZE*sub; /* Excitation */ exc=st->exc+offset; /* Weighted signal */ sw=st->sw+offset; - exc2=st->exc2+offset; - - /* LSP interpolation (quantized and unquantized) */ - tmp = (1.0 + sub)/st->nbSubframes; - for (i=0;ilpcSize;i++) - st->interp_lsp[i] = (1-tmp)*st->old_lsp[i] + tmp*st->lsp[i]; - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i]; - - /* Make sure the filters are stable */ - lsp_enforce_margin(st->interp_lsp, st->lpcSize, .002); - lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002); + lsp_interpolate(st->old_lsp, lsp, interp_lsp, NB_ORDER, sub, NB_NB_SUBFRAMES, LSP_MARGIN); + lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, NB_ORDER, sub, NB_NB_SUBFRAMES, LSP_MARGIN); /* Compute interpolated LPCs (quantized and unquantized) */ - for (i=0;ilpcSize;i++) - st->interp_lsp[i] = cos(st->interp_lsp[i]); - lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack); + lsp_to_lpc(interp_lsp, interp_lpc, NB_ORDER,stack); - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = cos(st->interp_qlsp[i]); - lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack); + lsp_to_lpc(interp_qlsp, interp_qlpc, NB_ORDER, stack); /* Compute analysis filter gain at w=pi (for use in SB-CELP) */ - tmp=1; - st->pi_gain[sub]=0; - for (i=0;i<=st->lpcSize;i++) { - st->pi_gain[sub] += tmp*st->interp_qlpc[i]; - tmp = -tmp; + spx_word32_t pi_g=LPC_SCALING; + for (i=0;iinterp_qlpc[i] + st->interp_qlpc[i+1];*/ + pi_g = ADD32(pi_g, SUB32(EXTEND32(interp_qlpc[i+1]),EXTEND32(interp_qlpc[i]))); + } + st->pi_gain[sub] = pi_g; } +#ifdef VORBIS_PSYCHO + { + float curr_curve[128]; + float fact = ((float)sub+1.0f)/NB_NB_SUBFRAMES; + for (i=0;i<128;i++) + curr_curve[i] = (1.0f-fact)*st->old_curve[i] + fact*st->curve[i]; + curve_to_lpc(st->psy, curr_curve, bw_lpc1, bw_lpc2, 10); + } +#else /* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting */ - bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize); - if (st->gamma2>=0) - bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize); + bw_lpc(st->gamma1, interp_lpc, bw_lpc1, NB_ORDER); + bw_lpc(st->gamma2, interp_lpc, bw_lpc2, NB_ORDER); + /*print_vec(st->bw_lpc1, 10, "bw_lpc");*/ +#endif + + /*FIXME: This will break if we change the window size */ + speex_assert(NB_WINDOW_SIZE-NB_FRAME_SIZE == NB_SUBFRAME_SIZE); + if (sub==0) + inBuf = st->winBuf; else - { - st->bw_lpc2[0]=1; - st->bw_lpc2[1]=-st->preemph; - for (i=2;i<=st->lpcSize;i++) - st->bw_lpc2[i]=0; - } + inBuf = &in[((sub-1)*NB_SUBFRAME_SIZE)]; + for (i=0;isubframeSize;i++) - exc[i]=0; - exc[0]=1; - syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack); - - /* Reset excitation */ - for (i=0;isubframeSize;i++) - exc[i]=0; - for (i=0;isubframeSize;i++) - exc2[i]=0; + if (st->complexity==0) + response_bound >>= 1; + compute_impulse_response(interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, response_bound, NB_ORDER, stack); + for (i=response_bound;ilpcSize;i++) - mem[i]=st->mem_sp[i]; - iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem); - - for (i=0;ilpcSize;i++) - mem[i]=st->mem_sw[i]; - filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem); - + for (i=0;imem_sp[i],1); + for (i=0;imem_sw[i],1); + filter10(exc, st->bw_lpc1, st->bw_lpc2, exc, response_bound, mem, stack); + SPEEX_MEMSET(&exc[response_bound], 0, NB_SUBFRAME_SIZE-response_bound); +#else + iir_mem16(exc, interp_qlpc, exc, NB_SUBFRAME_SIZE, NB_ORDER, mem, stack); + for (i=0;imem_sw[i],1); + filter10(exc, bw_lpc1, bw_lpc2, exc, NB_SUBFRAME_SIZE, mem, stack); +#endif + /* Compute weighted signal */ - for (i=0;ilpcSize;i++) + for (i=0;imem_sw[i]; - filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem); - - /* Compute target signal */ - for (i=0;isubframeSize;i++) - target[i]=sw[i]-res[i]; + filter10(sw, bw_lpc1, bw_lpc2, sw, NB_SUBFRAME_SIZE, mem, stack); - for (i=0;isubframeSize;i++) - exc[i]=exc2[i]=0; + if (st->complexity==0) + for (i=0;imem_sw[i]=mem[i]; + /* Compute target signal (saturation prevents overflows on clipped input speech) */ + for (i=0;imem_exc2, stack); /* If we have a long-term predictor (otherwise, something's wrong) */ - if (SUBMODE(ltp_quant)) + speex_assert (SUBMODE(ltp_quant)); { int pit_min, pit_max; /* Long-term prediction */ @@ -627,178 +903,145 @@ int nb_encode(void *state, float *in, SpeexBits *bits) margin = SUBMODE(lbr_pitch); if (margin) { - if (ol_pitch < st->min_pitch+margin-1) - ol_pitch=st->min_pitch+margin-1; - if (ol_pitch > st->max_pitch-margin) - ol_pitch=st->max_pitch-margin; + if (ol_pitch < NB_PITCH_START+margin-1) + ol_pitch=NB_PITCH_START+margin-1; + if (ol_pitch > NB_PITCH_END-margin) + ol_pitch=NB_PITCH_END-margin; pit_min = ol_pitch-margin+1; pit_max = ol_pitch+margin; } else { pit_min=pit_max=ol_pitch; } } else { - pit_min = st->min_pitch; - pit_max = st->max_pitch; + pit_min = NB_PITCH_START; + pit_max = NB_PITCH_END; } - + /* Force pitch to use only the current frame if needed */ if (st->bounded_pitch && pit_max>offset) pit_max=offset; /* Perform pitch search */ - pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, - exc, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef, - st->lpcSize, st->subframeSize, bits, stack, - exc2, syn_resp, st->complexity); + pitch = SUBMODE(ltp_quant)(target, sw, interp_qlpc, bw_lpc1, bw_lpc2, + exc32, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef, + NB_ORDER, NB_SUBFRAME_SIZE, bits, stack, + exc, syn_resp, st->complexity, 0, st->plc_tuning, &st->cumul_gain); st->pitch[sub]=pitch; + } + /* Quantization of innovation */ + SPEEX_MEMSET(innov, 0, NB_SUBFRAME_SIZE); + + /* FIXME: Make sure this is safe from overflows (so far so good) */ + for (i=0;iinterp_qlpc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, stack); - for (i=0;isubframeSize;i++) - target[i]-=res[i]; + /*printf ("%f %f\n", ener, ol_gain);*/ + /* Normalize innovation */ + signal_div(target, target, ener, NB_SUBFRAME_SIZE); - /* Quantization of innovation */ + /* Quantize innovation */ + speex_assert (SUBMODE(innovation_quant)); { - float *innov; - float ener=0, ener_1; + /* Codebook search */ + SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2, + SUBMODE(innovation_params), NB_ORDER, NB_SUBFRAME_SIZE, + innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook)); - innov = st->innov+sub*st->subframeSize; - for (i=0;isubframeSize;i++) - innov[i]=0; - - residue_percep_zero(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, st->buf2, st->subframeSize, st->lpcSize, stack); - for (i=0;isubframeSize;i++) - ener+=st->buf2[i]*st->buf2[i]; - ener=sqrt(.1+ener/st->subframeSize); - /*for (i=0;isubframeSize;i++) - printf ("%f\n", st->buf2[i]/ener); - */ - - ener /= ol_gain; - - /* Calculate gain correction for the sub-frame (if any) */ - if (SUBMODE(have_subframe_gain)) - { - int qe; - ener=log(ener); - if (SUBMODE(have_subframe_gain)==3) - { - qe = vq_index(&ener, exc_gain_quant_scal3, 1, 8); - speex_bits_pack(bits, qe, 3); - ener=exc_gain_quant_scal3[qe]; - } else { - qe = vq_index(&ener, exc_gain_quant_scal1, 1, 2); - speex_bits_pack(bits, qe, 1); - ener=exc_gain_quant_scal1[qe]; - } - ener=exp(ener); - } else { - ener=1; - } - - ener*=ol_gain; - - /*printf ("%f %f\n", ener, ol_gain);*/ - - ener_1 = 1/ener; - - /* Normalize innovation */ - for (i=0;isubframeSize;i++) - target[i]*=ener_1; - - /* Quantize innovation */ - if (SUBMODE(innovation_quant)) - { - /* Codebook search */ - SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov, syn_resp, bits, stack, st->complexity); - - /* De-normalize innovation and update excitation */ - for (i=0;isubframeSize;i++) - innov[i]*=ener; - for (i=0;isubframeSize;i++) - exc[i] += innov[i]; - } else { - speex_error("No fixed codebook"); - } + /* De-normalize innovation and update excitation */ + signal_mul(innov, innov, ener, NB_SUBFRAME_SIZE); /* In some (rare) modes, we do a second search (more bits) to reduce noise even more */ if (SUBMODE(double_codebook)) { char *tmp_stack=stack; - float *innov2 = PUSH(tmp_stack, st->subframeSize, float); - for (i=0;isubframeSize;i++) - innov2[i]=0; - for (i=0;isubframeSize;i++) - target[i]*=2.2; - SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov2, syn_resp, bits, tmp_stack, st->complexity); - for (i=0;isubframeSize;i++) - innov2[i]*=ener*(1/2.2); - for (i=0;isubframeSize;i++) - exc[i] += innov2[i]; + VARDECL(spx_sig_t *innov2); + ALLOC(innov2, NB_SUBFRAME_SIZE, spx_sig_t); + SPEEX_MEMSET(innov2, 0, NB_SUBFRAME_SIZE); + for (i=0;icomplexity, 0); + signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener), NB_SUBFRAME_SIZE); + for (i=0;isubframeSize;i++) - target[i]*=ener; - + for (i=0;iinnov_rms_save) + st->innov_rms_save[sub] = compute_rms(innov, NB_SUBFRAME_SIZE); } - /*Keep the previous memory*/ - for (i=0;ilpcSize;i++) - mem[i]=st->mem_sp[i]; /* Final signal synthesis from excitation */ - iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp); + iir_mem16(exc, interp_qlpc, sw, NB_SUBFRAME_SIZE, NB_ORDER, st->mem_sp, stack); /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ - filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw); - for (i=0;isubframeSize;i++) - exc2[i]=exc[i]; + if (st->complexity!=0) + filter10(sw, bw_lpc1, bw_lpc2, sw, NB_SUBFRAME_SIZE, st->mem_sw, stack); + } /* Store the LSPs for interpolation in the next frame */ if (st->submodeID>=1) { - for (i=0;ilpcSize;i++) - st->old_lsp[i] = st->lsp[i]; - for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + for (i=0;iold_lsp[i] = lsp[i]; + for (i=0;iold_qlsp[i] = qlsp[i]; } +#ifdef VORBIS_PSYCHO + if (st->submodeID>=1) + SPEEX_COPY(st->old_curve, st->curve, 128); +#endif + if (st->submodeID==1) { +#ifndef DISABLE_VBR if (st->dtx_count) speex_bits_pack(bits, 15, 4); else +#endif speex_bits_pack(bits, 0, 4); } /* The next frame will not be the first (Duh!) */ st->first = 0; - - { - float ener=0, err=0; - float snr; - for (i=0;iframeSize;i++) - { - ener+=st->frame[i]*st->frame[i]; - err += (st->frame[i]-orig[i])*(st->frame[i]-orig[i]); - } - snr = 10*log10((ener+1)/(err+1)); - /*printf ("%f %f %f\n", snr, ener, err);*/ - } - - /* Replace input by synthesized speech */ - in[0] = st->frame[0] + st->preemph*st->pre_mem2; - for (i=1;iframeSize;i++) - in[i]=st->frame[i] + st->preemph*in[i-1]; - st->pre_mem2=in[st->frameSize-1]; + SPEEX_COPY(st->winBuf, in+2*NB_FRAME_SIZE-NB_WINDOW_SIZE, NB_WINDOW_SIZE-NB_FRAME_SIZE); if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0) st->bounded_pitch = 1; @@ -807,64 +1050,46 @@ int nb_encode(void *state, float *in, SpeexBits *bits) return 1; } +#endif /* DISABLE_ENCODER */ -void *nb_decoder_init(SpeexMode *m) +#ifndef DISABLE_DECODER +void *nb_decoder_init(const SpeexMode *m) { DecState *st; - SpeexNBMode *mode; + const SpeexNBMode *mode; int i; - mode=(SpeexNBMode*)m->mode; - st = (DecState *)speex_alloc(sizeof(DecState)+4000*sizeof(float)); + mode=(const SpeexNBMode*)m->mode; + st = (DecState *)speex_alloc(sizeof(DecState)); + if (!st) + return NULL; +#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) + st->stack = NULL; +#else + st->stack = (char*)speex_alloc_scratch(NB_DEC_STACK); +#endif + st->mode=m; - st->stack = ((char*)st) + sizeof(DecState); + + st->encode_submode = 1; st->first=1; /* Codec parameters, should eventually have several "modes"*/ - st->frameSize = mode->frameSize; - st->windowSize = st->frameSize*3/2; - st->nbSubframes=mode->frameSize/mode->subframeSize; - st->subframeSize=mode->subframeSize; - st->lpcSize = mode->lpcSize; - st->bufSize = mode->bufSize; - st->gamma1=mode->gamma1; - st->gamma2=mode->gamma2; - st->min_pitch=mode->pitchStart; - st->max_pitch=mode->pitchEnd; - st->preemph = mode->preemph; st->submodes=mode->submodes; st->submodeID=mode->defaultSubmode; - st->pre_mem=0; - st->lpc_enh_enabled=0; + st->lpc_enh_enabled=1; + SPEEX_MEMSET(st->excBuf, 0, NB_FRAME_SIZE + NB_PITCH_END); - st->inBuf = PUSH(st->stack, st->bufSize, float); - st->frame = st->inBuf + st->bufSize - st->windowSize; - st->excBuf = PUSH(st->stack, st->bufSize, float); - st->exc = st->excBuf + st->bufSize - st->windowSize; - for (i=0;ibufSize;i++) - st->inBuf[i]=0; - for (i=0;ibufSize;i++) - st->excBuf[i]=0; - st->innov = PUSH(st->stack, st->frameSize, float); - - st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, float); - st->qlsp = PUSH(st->stack, st->lpcSize, float); - st->old_qlsp = PUSH(st->stack, st->lpcSize, float); - st->interp_qlsp = PUSH(st->stack, st->lpcSize, float); - st->mem_sp = PUSH(st->stack, 5*st->lpcSize, float); - st->comb_mem = PUSHS(st->stack, CombFilterMem); - comp_filter_mem_init (st->comb_mem); - - st->pi_gain = PUSH(st->stack, st->nbSubframes, float); st->last_pitch = 40; st->count_lost=0; st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 0; st->pitch_gain_buf_idx = 0; + st->seed = 1000; st->sampling_rate=8000; st->last_ol_gain = 0; @@ -877,751 +1102,25 @@ void *nb_decoder_init(SpeexMode *m) st->voc_m1=st->voc_m2=st->voc_mean=0; st->voc_offset=0; st->dtx_enabled=0; + st->isWideband = 0; + st->highpass_enabled = 1; + +#ifdef ENABLE_VALGRIND + VALGRIND_MAKE_MEM_DEFINED(st, NB_DEC_STACK); +#endif return st; } void nb_decoder_destroy(void *state) { +#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) DecState *st; st=(DecState*)state; - - speex_free(state); -} -#define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a)))) - -static void nb_decode_lost(DecState *st, float *out, char *stack) -{ - int i, sub; - float *awk1, *awk2, *awk3; - float pitch_gain, fact, gain_med; - - fact = exp(-.04*st->count_lost*st->count_lost); - gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_gain_buf[2]); - if (gain_med < st->last_pitch_gain) - st->last_pitch_gain = gain_med; - - pitch_gain = st->last_pitch_gain; - if (pitch_gain>.95) - pitch_gain=.95; - - pitch_gain *= fact; - - /* Shift all buffers by one frame */ - speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - - awk1=PUSH(stack, (st->lpcSize+1), float); - awk2=PUSH(stack, (st->lpcSize+1), float); - awk3=PUSH(stack, (st->lpcSize+1), float); - - for (sub=0;subnbSubframes;sub++) - { - int offset; - float *sp, *exc; - /* Offset relative to start of frame */ - offset = st->subframeSize*sub; - /* Original signal */ - sp=st->frame+offset; - /* Excitation */ - exc=st->exc+offset; - /* Excitation after post-filter*/ - - /* Calculate perceptually enhanced LPC filter */ - if (st->lpc_enh_enabled) - { - float r=.9; - - float k1,k2,k3; - if (st->submodes[st->submodeID] != NULL) - { - k1=SUBMODE(lpc_enh_k1); - k2=SUBMODE(lpc_enh_k2); - } else { - k1=k2=.7; - } - k3=(1-(1-r*k1)/(1-r*k2))/r; - if (!st->lpc_enh_enabled) - { - k1=k2; - k3=0; - } - bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize); - bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize); - bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize); - } - - /* Make up a plausible excitation */ - /* THIS CAN BE IMPROVED */ - /*if (pitch_gain>.95) - pitch_gain=.95;*/ - { - float innov_gain=0; - for (i=0;iframeSize;i++) - innov_gain += st->innov[i]*st->innov[i]; - innov_gain=sqrt(innov_gain/st->frameSize); - for (i=0;isubframeSize;i++) - { -#if 0 - exc[i] = pitch_gain * exc[i - st->last_pitch] + fact*sqrt(1-pitch_gain)*st->innov[i+offset]; - /*Just so it give the same lost packets as with if 0*/ - /*rand();*/ -#else - /*exc[i]=pitch_gain*exc[i-st->last_pitch] + fact*st->innov[i+offset];*/ - exc[i]=pitch_gain*exc[i-st->last_pitch] + - fact*sqrt(1-pitch_gain)*speex_rand(innov_gain); + speex_free_scratch(st->stack); #endif - } - } - for (i=0;isubframeSize;i++) - sp[i]=exc[i]; - - /* Signal synthesis */ - if (st->lpc_enh_enabled) - { - filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize, - st->mem_sp+st->lpcSize); - filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp); - } else { - for (i=0;ilpcSize;i++) - st->mem_sp[st->lpcSize+i] = 0; - iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp); - } - } - out[0] = st->frame[0] + st->preemph*st->pre_mem; - for (i=1;iframeSize;i++) - out[i]=st->frame[i] + st->preemph*out[i-1]; - st->pre_mem=out[st->frameSize-1]; - - st->first = 0; - st->count_lost++; - st->pitch_gain_buf[st->pitch_gain_buf_idx++] = pitch_gain; - if (st->pitch_gain_buf_idx > 2) /* rollover */ - st->pitch_gain_buf_idx = 0; -} - -int nb_decode(void *state, SpeexBits *bits, float *out) -{ - DecState *st; - int i, sub; - int pitch; - float pitch_gain[3]; - float ol_gain=0; - int ol_pitch=0; - float ol_pitch_coef=0; - int best_pitch=40; - float best_pitch_gain=0; - int wideband; - int m; - char *stack; - float *awk1, *awk2, *awk3; - float pitch_average=0; - - st=(DecState*)state; - stack=st->stack; - - /* Check if we're in DTX mode*/ - if (!bits && st->dtx_enabled) - { - st->submodeID=0; - } else - { - /* If bits is NULL, consider the packet to be lost (what could we do anyway) */ - if (!bits) - { - nb_decode_lost(st, out, stack); - return 0; - } - - /* Search for next narrowband block (handle requests, skip wideband blocks) */ - do { - wideband = speex_bits_unpack_unsigned(bits, 1); - if (wideband) /* Skip wideband block (for compatibility) */ - { - int submode; - int advance; - advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); - speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance); - if (advance < 0) - { - speex_warning ("Invalid wideband mode encountered. Corrupted stream?"); - return -2; - } - advance -= (SB_SUBMODE_BITS+1); - speex_bits_advance(bits, advance); - wideband = speex_bits_unpack_unsigned(bits, 1); - if (wideband) - { - advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); - speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance); - if (advance < 0) - { - speex_warning ("Invalid wideband mode encountered: corrupted stream?"); - return -2; - } - advance -= (SB_SUBMODE_BITS+1); - speex_bits_advance(bits, advance); - wideband = speex_bits_unpack_unsigned(bits, 1); - if (wideband) - { - speex_warning ("More than to wideband layers found: corrupted stream?"); - return -2; - } - - } - } - - /* FIXME: Check for overflow */ - m = speex_bits_unpack_unsigned(bits, 4); - if (m==15) /* We found a terminator */ - { - return -1; - } else if (m==14) /* Speex in-band request */ - { - int ret = speex_inband_handler(bits, st->speex_callbacks, state); - if (ret) - return ret; - } else if (m==13) /* User in-band request */ - { - int ret = st->user_callback.func(bits, state, st->user_callback.data); - if (ret) - return ret; - } else if (m>8) /* Invalid mode */ - { - speex_warning("Invalid mode encountered: corrupted stream?"); - return -2; - } - - } while (m>8); - - /* Get the sub-mode that was used */ - st->submodeID = m; - - } - - /* Shift all buffers by one frame */ - speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float)); - - /* If null mode (no transmission), just set a couple things to zero*/ - if (st->submodes[st->submodeID] == NULL) - { - float *lpc; - lpc = PUSH(stack,11, float); - bw_lpc(.93, st->interp_qlpc, lpc, 10); - /*for (i=0;iframeSize;i++) - st->exc[i]=0;*/ - { - float innov_gain=0; - float pgain=st->last_pitch_gain; - if (pgain>.6) - pgain=.6; - for (i=0;iframeSize;i++) - innov_gain += st->innov[i]*st->innov[i]; - innov_gain=sqrt(innov_gain/st->frameSize); - for (i=0;iframeSize;i++) - st->exc[i]=0; - speex_rand_vec(innov_gain, st->exc, st->frameSize); - } - - - st->first=1; - - /* Final signal synthesis from excitation */ - iir_mem2(st->exc, lpc, st->frame, st->frameSize, st->lpcSize, st->mem_sp); - - out[0] = st->frame[0] + st->preemph*st->pre_mem; - for (i=1;iframeSize;i++) - out[i]=st->frame[i] + st->preemph*out[i-1]; - st->pre_mem=out[st->frameSize-1]; - st->count_lost=0; - return 0; - } - - /* Unquantize LSPs */ - SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits); - - /*Damp memory if a frame was lost and the LSP changed too much*/ - if (st->count_lost) - { - float lsp_dist=0, fact; - for (i=0;ilpcSize;i++) - lsp_dist += fabs(st->old_qlsp[i] - st->qlsp[i]); - fact = .6*exp(-.2*lsp_dist); - for (i=0;i<2*st->lpcSize;i++) - st->mem_sp[i] *= fact; - } - - - /* Handle first frame and lost-packet case */ - if (st->first || st->count_lost) - { - for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; - } - - /* Get open-loop pitch estimation for low bit-rate pitch coding */ - if (SUBMODE(lbr_pitch)!=-1) - { - ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7); - } - - if (SUBMODE(forced_pitch_gain)) - { - int quant; - quant = speex_bits_unpack_unsigned(bits, 4); - ol_pitch_coef=0.066667*quant; - } - - /* Get global excitation gain */ - { - int qe; - qe = speex_bits_unpack_unsigned(bits, 5); - ol_gain = exp(qe/3.5); - } - - awk1=PUSH(stack, st->lpcSize+1, float); - awk2=PUSH(stack, st->lpcSize+1, float); - awk3=PUSH(stack, st->lpcSize+1, float); - - if (st->submodeID==1) - { - int extra; - extra = speex_bits_unpack_unsigned(bits, 4); - - if (extra==15) - st->dtx_enabled=1; - else - st->dtx_enabled=0; - } - if (st->submodeID>1) - st->dtx_enabled=0; - - /*Loop on subframes */ - for (sub=0;subnbSubframes;sub++) - { - int offset; - float *sp, *exc, tmp; - - /* Offset relative to start of frame */ - offset = st->subframeSize*sub; - /* Original signal */ - sp=st->frame+offset; - /* Excitation */ - exc=st->exc+offset; - /* Excitation after post-filter*/ - - /* LSP interpolation (quantized and unquantized) */ - tmp = (1.0 + sub)/st->nbSubframes; - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i]; - - /* Make sure the LSP's are stable */ - lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002); - - - /* Compute interpolated LPCs (unquantized) */ - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = cos(st->interp_qlsp[i]); - lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack); - - /* Compute enhanced synthesis filter */ - if (st->lpc_enh_enabled) - { - float r=.9; - - float k1,k2,k3; - k1=SUBMODE(lpc_enh_k1); - k2=SUBMODE(lpc_enh_k2); - k3=(1-(1-r*k1)/(1-r*k2))/r; - if (!st->lpc_enh_enabled) - { - k1=k2; - k3=0; - } - bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize); - bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize); - bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize); - - } - - /* Compute analysis filter at w=pi */ - tmp=1; - st->pi_gain[sub]=0; - for (i=0;i<=st->lpcSize;i++) - { - st->pi_gain[sub] += tmp*st->interp_qlpc[i]; - tmp = -tmp; - } - - /* Reset excitation */ - for (i=0;isubframeSize;i++) - exc[i]=0; - - /*Adaptive codebook contribution*/ - if (SUBMODE(ltp_unquant)) - { - int pit_min, pit_max; - /* Handle pitch constraints if any */ - if (SUBMODE(lbr_pitch) != -1) - { - int margin; - margin = SUBMODE(lbr_pitch); - if (margin) - { -/* GT - need optimization? - if (ol_pitch < st->min_pitch+margin-1) - ol_pitch=st->min_pitch+margin-1; - if (ol_pitch > st->max_pitch-margin) - ol_pitch=st->max_pitch-margin; - pit_min = ol_pitch-margin+1; - pit_max = ol_pitch+margin; -*/ - pit_min = ol_pitch-margin+1; - if (pit_min < st->min_pitch) - pit_min = st->min_pitch; - pit_max = ol_pitch+margin; - if (pit_max > st->max_pitch) - pit_max = st->max_pitch; - } else { - pit_min = pit_max = ol_pitch; - } - } else { - pit_min = st->min_pitch; - pit_max = st->max_pitch; - } - - /* Pitch synthesis */ - SUBMODE(ltp_unquant)(exc, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params), - st->subframeSize, &pitch, &pitch_gain[0], bits, stack, st->count_lost, offset, st->last_pitch_gain); - - /* If we had lost frames, check energy of last received frame */ - if (st->count_lost && ol_gain < st->last_ol_gain) - { - float fact = ol_gain/(st->last_ol_gain+1); - for (i=0;isubframeSize;i++) - exc[i]*=fact; - } - - tmp = fabs(pitch_gain[0]+pitch_gain[1]+pitch_gain[2]); - tmp = fabs(pitch_gain[1]); - if (pitch_gain[0]>0) - tmp += pitch_gain[0]; - else - tmp -= .5*pitch_gain[0]; - if (pitch_gain[2]>0) - tmp += pitch_gain[2]; - else - tmp -= .5*pitch_gain[0]; - - - pitch_average += tmp; - if (tmp>best_pitch_gain) - { - best_pitch = pitch; - best_pitch_gain = tmp; - /* best_pitch_gain = tmp*.9; - if (best_pitch_gain>.85) - best_pitch_gain=.85;*/ - } - } else { - speex_error("No pitch prediction, what's wrong"); - } - - /* Unquantize the innovation */ - { - int q_energy; - float ener; - float *innov; - - innov = st->innov+sub*st->subframeSize; - for (i=0;isubframeSize;i++) - innov[i]=0; - - /* Decode sub-frame gain correction */ - if (SUBMODE(have_subframe_gain)==3) - { - q_energy = speex_bits_unpack_unsigned(bits, 3); - ener = ol_gain*exp(exc_gain_quant_scal3[q_energy]); - } else if (SUBMODE(have_subframe_gain)==1) - { - q_energy = speex_bits_unpack_unsigned(bits, 1); - ener = ol_gain*exp(exc_gain_quant_scal1[q_energy]); - } else { - ener = ol_gain; - } - - if (SUBMODE(innovation_unquant)) - { - /*Fixed codebook contribution*/ - SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), st->subframeSize, bits, stack); - } else { - speex_error("No fixed codebook"); - } - - /* De-normalize innovation and update excitation */ - for (i=0;isubframeSize;i++) - innov[i]*=ener; - - /*Vocoder mode*/ - if (st->submodeID==1) - { - float g=ol_pitch_coef; - - - for (i=0;isubframeSize;i++) - exc[i]=0; - while (st->voc_offsetsubframeSize) - { - if (st->voc_offset>=0) - exc[st->voc_offset]=sqrt(1.0*ol_pitch); - st->voc_offset+=ol_pitch; - } - st->voc_offset -= st->subframeSize; - - g=.5+2*(g-.6); - if (g<0) - g=0; - if (g>1) - g=1; - for (i=0;isubframeSize;i++) - { - float exci=exc[i]; - exc[i]=.8*g*exc[i]*ol_gain + .6*g*st->voc_m1*ol_gain + .5*g*innov[i] - .5*g*st->voc_m2 + (1-g)*innov[i]; - st->voc_m1 = exci; - st->voc_m2=innov[i]; - st->voc_mean = .95*st->voc_mean + .05*exc[i]; - exc[i]-=st->voc_mean; - } - } else { - for (i=0;isubframeSize;i++) - exc[i]+=innov[i]; - } - /* Decode second codebook (only for some modes) */ - if (SUBMODE(double_codebook)) - { - char *tmp_stack=stack; - float *innov2 = PUSH(tmp_stack, st->subframeSize, float); - for (i=0;isubframeSize;i++) - innov2[i]=0; - SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, bits, tmp_stack); - for (i=0;isubframeSize;i++) - innov2[i]*=ener*(1/2.2); - for (i=0;isubframeSize;i++) - exc[i] += innov2[i]; - } - - } - - for (i=0;isubframeSize;i++) - sp[i]=exc[i]; - - /* Signal synthesis */ - if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0) - comb_filter_(exc, sp, st->interp_qlpc, st->lpcSize, st->subframeSize, - pitch, pitch_gain, SUBMODE(comb_gain), st->comb_mem); - if (st->lpc_enh_enabled) - { - /* Use enhanced LPC filter */ - filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize, - st->mem_sp+st->lpcSize); - filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp); - } else { - /* Use regular filter */ - for (i=0;ilpcSize;i++) - st->mem_sp[st->lpcSize+i] = 0; - iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp); - } - } - - /*Copy output signal*/ - out[0] = st->frame[0] + st->preemph*st->pre_mem; - for (i=1;iframeSize;i++) - out[i]=st->frame[i] + st->preemph*out[i-1]; - st->pre_mem=out[st->frameSize-1]; - - - /* Store the LSPs for interpolation in the next frame */ - for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; - - /* The next frame will not be the first (Duh!) */ - st->first = 0; - st->count_lost=0; - st->last_pitch = best_pitch; - st->last_pitch_gain = .25*pitch_average; - st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain; - if (st->pitch_gain_buf_idx > 2) /* rollover */ - st->pitch_gain_buf_idx = 0; - - st->last_ol_gain = ol_gain; - - return 0; -} - -int nb_encoder_ctl(void *state, int request, void *ptr) -{ - EncState *st; - st=(EncState*)state; - switch(request) - { - case SPEEX_GET_FRAME_SIZE: - (*(int*)ptr) = st->frameSize; - break; - case SPEEX_SET_LOW_MODE: - case SPEEX_SET_MODE: - st->submodeSelect = st->submodeID = (*(int*)ptr); - break; - case SPEEX_GET_LOW_MODE: - case SPEEX_GET_MODE: - (*(int*)ptr) = st->submodeID; - break; - case SPEEX_SET_VBR: - st->vbr_enabled = (*(int*)ptr); - break; - case SPEEX_GET_VBR: - (*(int*)ptr) = st->vbr_enabled; - break; - case SPEEX_SET_VAD: - st->vad_enabled = (*(int*)ptr); - break; - case SPEEX_GET_VAD: - (*(int*)ptr) = st->vad_enabled; - break; - case SPEEX_SET_DTX: - st->dtx_enabled = (*(int*)ptr); - break; - case SPEEX_GET_DTX: - (*(int*)ptr) = st->dtx_enabled; - break; - case SPEEX_SET_ABR: - st->abr_enabled = (*(int*)ptr); - st->vbr_enabled = 1; - { - int i=10, rate, target; - float vbr_qual; - target = (*(int*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - vbr_qual=i; - if (vbr_qual<0) - vbr_qual=0; - speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); - st->abr_count=0; - st->abr_drift=0; - st->abr_drift2=0; - } - - break; - case SPEEX_GET_ABR: - (*(int*)ptr) = st->abr_enabled; - break; - case SPEEX_SET_VBR_QUALITY: - st->vbr_quality = (*(float*)ptr); - break; - case SPEEX_GET_VBR_QUALITY: - (*(float*)ptr) = st->vbr_quality; - break; - case SPEEX_SET_QUALITY: - { - int quality = (*(int*)ptr); - if (quality < 0) - quality = 0; - if (quality > 10) - quality = 10; - st->submodeSelect = st->submodeID = ((SpeexNBMode*)(st->mode->mode))->quality_map[quality]; - } - break; - case SPEEX_SET_COMPLEXITY: - st->complexity = (*(int*)ptr); - if (st->complexity<1) - st->complexity=1; - break; - case SPEEX_GET_COMPLEXITY: - (*(int*)ptr) = st->complexity; - break; - case SPEEX_SET_BITRATE: - { - int i=10, rate, target; - target = (*(int*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - } - break; - case SPEEX_GET_BITRATE: - if (st->submodes[st->submodeID]) - (*(int*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize; - else - (*(int*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize; - break; - case SPEEX_SET_SAMPLING_RATE: - st->sampling_rate = (*(int*)ptr); - break; - case SPEEX_GET_SAMPLING_RATE: - (*(int*)ptr)=st->sampling_rate; - break; - case SPEEX_RESET_STATE: - { - int i; - st->bounded_pitch = 1; - st->first = 1; - for (i=0;ilpcSize;i++) - st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); - for (i=0;ilpcSize;i++) - st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0; - for (i=0;ibufSize;i++) - st->excBuf[i]=st->swBuf[i]=st->inBuf[i]=st->exc2Buf[i]=0; - } - break; - case SPEEX_GET_PI_GAIN: - { - int i; - float *g = (float*)ptr; - for (i=0;inbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - float *e = (float*)ptr; - for (i=0;iframeSize;i++) - e[i]=st->exc[i]; - } - break; - case SPEEX_GET_INNOV: - { - int i; - float *e = (float*)ptr; - for (i=0;iframeSize;i++) - e[i]=st->innov[i]; - } - break; - case SPEEX_GET_RELATIVE_QUALITY: - (*(float*)ptr)=st->relative_quality; - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; + speex_free(state); } int nb_decoder_ctl(void *state, int request, void *ptr) @@ -1630,30 +1129,34 @@ int nb_decoder_ctl(void *state, int request, void *ptr) st=(DecState*)state; switch(request) { + case SPEEX_SET_LOW_MODE: + case SPEEX_SET_MODE: + st->submodeID = (*(spx_int32_t*)ptr); + break; case SPEEX_GET_LOW_MODE: case SPEEX_GET_MODE: - (*(int*)ptr) = st->submodeID; + (*(spx_int32_t*)ptr) = st->submodeID; break; case SPEEX_SET_ENH: - st->lpc_enh_enabled = *((int*)ptr); + st->lpc_enh_enabled = *((spx_int32_t*)ptr); break; case SPEEX_GET_ENH: - *((int*)ptr) = st->lpc_enh_enabled; + *((spx_int32_t*)ptr) = st->lpc_enh_enabled; break; case SPEEX_GET_FRAME_SIZE: - (*(int*)ptr) = st->frameSize; + (*(spx_int32_t*)ptr) = NB_FRAME_SIZE; break; case SPEEX_GET_BITRATE: if (st->submodes[st->submodeID]) - (*(int*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize; + (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/NB_FRAME_SIZE; else - (*(int*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize; + (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/NB_FRAME_SIZE; break; case SPEEX_SET_SAMPLING_RATE: - st->sampling_rate = (*(int*)ptr); + st->sampling_rate = (*(spx_int32_t*)ptr); break; case SPEEX_GET_SAMPLING_RATE: - (*(int*)ptr)=st->sampling_rate; + (*(spx_int32_t*)ptr)=st->sampling_rate; break; case SPEEX_SET_HANDLER: { @@ -1674,38 +1177,69 @@ int nb_decoder_ctl(void *state, int request, void *ptr) case SPEEX_RESET_STATE: { int i; - for (i=0;i<2*st->lpcSize;i++) + for (i=0;imem_sp[i]=0; - for (i=0;ibufSize;i++) - st->excBuf[i]=st->inBuf[i]=0; + for (i=0;iexcBuf[i]=0; } break; + case SPEEX_SET_SUBMODE_ENCODING: + st->encode_submode = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_SUBMODE_ENCODING: + (*(spx_int32_t*)ptr) = st->encode_submode; + break; + case SPEEX_GET_LOOKAHEAD: + (*(spx_int32_t*)ptr)=NB_SUBFRAME_SIZE; + break; + case SPEEX_SET_HIGHPASS: + st->highpass_enabled = (*(spx_int32_t*)ptr); + break; + case SPEEX_GET_HIGHPASS: + (*(spx_int32_t*)ptr) = st->highpass_enabled; + break; + /* FIXME: Convert to fixed-point and re-enable even when float API is disabled */ +#ifndef DISABLE_FLOAT_API + case SPEEX_GET_ACTIVITY: + { + float ret; + ret = log(st->level/st->min_level)/log(st->max_level/st->min_level); + if (ret>1) + ret = 1; + /* Done in a strange way to catch NaNs as well */ + if (!(ret > 0)) + ret = 0; + /*printf ("%f %f %f %f\n", st->level, st->min_level, st->max_level, ret);*/ + (*(spx_int32_t*)ptr) = (int)(100*ret); + } + break; +#endif case SPEEX_GET_PI_GAIN: { int i; - float *g = (float*)ptr; - for (i=0;inbSubframes;i++) + spx_word32_t *g = (spx_word32_t*)ptr; + for (i=0;ipi_gain[i]; } break; case SPEEX_GET_EXC: { int i; - float *e = (float*)ptr; - for (i=0;iframeSize;i++) - e[i]=st->exc[i]; - } - break; - case SPEEX_GET_INNOV: - { - int i; - float *e = (float*)ptr; - for (i=0;iframeSize;i++) - e[i]=st->innov[i]; + for (i=0;iexc+i*NB_SUBFRAME_SIZE, NB_SUBFRAME_SIZE); } break; case SPEEX_GET_DTX_STATUS: - *((int*)ptr) = st->dtx_enabled; + *((spx_int32_t*)ptr) = st->dtx_enabled; + break; + case SPEEX_SET_INNOVATION_SAVE: + st->innov_save = (spx_word16_t*)ptr; + break; + case SPEEX_SET_WIDEBAND: + st->isWideband = *((spx_int32_t*)ptr); + break; + case SPEEX_GET_STACK: + *((char**)ptr) = st->stack; break; default: speex_warning_int("Unknown nb_ctl request: ", request); @@ -1713,3 +1247,573 @@ int nb_decoder_ctl(void *state, int request, void *ptr) } return 0; } + + +#define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a)))) + +#ifdef FIXED_POINT +const spx_word16_t attenuation[10] = {32767, 31483, 27923, 22861, 17278, 12055, 7764, 4616, 2533, 1283}; +#else +const spx_word16_t attenuation[10] = {1., 0.961, 0.852, 0.698, 0.527, 0.368, 0.237, 0.141, 0.077, 0.039}; + +#endif + +static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack) +{ + int i; + int pitch_val; + spx_word16_t pitch_gain; + spx_word16_t fact; + spx_word16_t gain_med; + spx_word16_t innov_gain; + spx_word16_t noise_gain; + + st->exc = st->excBuf + 2*NB_PITCH_END + NB_SUBFRAME_SIZE + 6; + + if (st->count_lost<10) + fact = attenuation[st->count_lost]; + else + fact = 0; + + gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_gain_buf[2]); + if (gain_med < st->last_pitch_gain) + st->last_pitch_gain = gain_med; + +#ifdef FIXED_POINT + pitch_gain = st->last_pitch_gain; + if (pitch_gain>54) + pitch_gain = 54; + pitch_gain = SHL16(pitch_gain, 9); +#else + pitch_gain = GAIN_SCALING_1*st->last_pitch_gain; + if (pitch_gain>.85) + pitch_gain=.85; +#endif + pitch_gain = MULT16_16_Q15(fact,pitch_gain) + VERY_SMALL; + /* FIXME: This was rms of innovation (not exc) */ + innov_gain = compute_rms16(st->exc, NB_FRAME_SIZE); + noise_gain = MULT16_16_Q15(innov_gain, MULT16_16_Q15(fact, SUB16(Q15ONE,MULT16_16_Q15(pitch_gain,pitch_gain)))); + /* Shift all buffers by one frame */ + SPEEX_MOVE(st->excBuf, st->excBuf+NB_FRAME_SIZE, 2*NB_PITCH_END + NB_SUBFRAME_SIZE + 12); + + + pitch_val = st->last_pitch + SHR32((spx_int32_t)speex_rand(1+st->count_lost, &st->seed),SIG_SHIFT); + if (pitch_val > NB_PITCH_END) + pitch_val = NB_PITCH_END; + if (pitch_val < NB_PITCH_START) + pitch_val = NB_PITCH_START; + for (i=0;iexc[i]= MULT16_16_Q15(pitch_gain, (st->exc[i-pitch_val]+VERY_SMALL)) + + speex_rand(noise_gain, &st->seed); + } + + bw_lpc(QCONST16(.98,15), st->interp_qlpc, st->interp_qlpc, NB_ORDER); + iir_mem16(&st->exc[-NB_SUBFRAME_SIZE], st->interp_qlpc, out, NB_FRAME_SIZE, + NB_ORDER, st->mem_sp, stack); + highpass(out, out, NB_FRAME_SIZE, HIGHPASS_NARROWBAND|HIGHPASS_OUTPUT, st->mem_hp); + + st->first = 0; + st->count_lost++; + st->pitch_gain_buf[st->pitch_gain_buf_idx++] = PSHR16(pitch_gain,9); + if (st->pitch_gain_buf_idx > 2) /* rollover */ + st->pitch_gain_buf_idx = 0; +} + +/* Just so we don't need to carry the complete wideband mode information */ +static const int wb_skip_table[8] = {0, 36, 112, 192, 352, 0, 0, 0}; + +int nb_decode(void *state, SpeexBits *bits, void *vout) +{ + DecState *st; + int i, sub; + int pitch; + spx_word16_t pitch_gain[3]; + spx_word32_t ol_gain=0; + int ol_pitch=0; + spx_word16_t ol_pitch_coef=0; + int best_pitch=40; + spx_word16_t best_pitch_gain=0; + int wideband; + int m; + char *stack; + VARDECL(spx_sig_t *innov); + VARDECL(spx_word32_t *exc32); + VARDECL(spx_coef_t *ak); + VARDECL(spx_lsp_t *qlsp); + spx_word16_t pitch_average=0; + + spx_word16_t *out = (spx_word16_t*)vout; + VARDECL(spx_lsp_t *interp_qlsp); + + st=(DecState*)state; + stack=st->stack; + + st->exc = st->excBuf + 2*NB_PITCH_END + NB_SUBFRAME_SIZE + 6; + + /* Check if we're in DTX mode*/ + if (!bits && st->dtx_enabled) + { + st->submodeID=0; + } else + { + /* If bits is NULL, consider the packet to be lost (what could we do anyway) */ + if (!bits) + { + nb_decode_lost(st, out, stack); + return 0; + } + + if (st->encode_submode) + { + + /* Search for next narrowband block (handle requests, skip wideband blocks) */ + do { + if (speex_bits_remaining(bits)<5) + return -1; + wideband = speex_bits_unpack_unsigned(bits, 1); + if (wideband) /* Skip wideband block (for compatibility) */ + { + int submode; + int advance; + advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); + /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);*/ + advance = wb_skip_table[submode]; + if (advance < 0) + { + speex_notify("Invalid mode encountered. The stream is corrupted."); + return -2; + } + advance -= (SB_SUBMODE_BITS+1); + speex_bits_advance(bits, advance); + + if (speex_bits_remaining(bits)<5) + return -1; + wideband = speex_bits_unpack_unsigned(bits, 1); + if (wideband) + { + advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); + /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);*/ + advance = wb_skip_table[submode]; + if (advance < 0) + { + speex_notify("Invalid mode encountered. The stream is corrupted."); + return -2; + } + advance -= (SB_SUBMODE_BITS+1); + speex_bits_advance(bits, advance); + wideband = speex_bits_unpack_unsigned(bits, 1); + if (wideband) + { + speex_notify("More than two wideband layers found. The stream is corrupted."); + return -2; + } + + } + } + if (speex_bits_remaining(bits)<4) + return -1; + /* FIXME: Check for overflow */ + m = speex_bits_unpack_unsigned(bits, 4); + if (m==15) /* We found a terminator */ + { + return -1; + } else if (m==14) /* Speex in-band request */ + { + int ret = speex_inband_handler(bits, st->speex_callbacks, state); + if (ret) + return ret; + } else if (m==13) /* User in-band request */ + { + int ret = st->user_callback.func(bits, state, st->user_callback.data); + if (ret) + return ret; + } else if (m>8) /* Invalid mode */ + { + speex_notify("Invalid mode encountered. The stream is corrupted."); + return -2; + } + + } while (m>8); + + /* Get the sub-mode that was used */ + st->submodeID = m; + } + + } + + /* Shift all buffers by one frame */ + SPEEX_MOVE(st->excBuf, st->excBuf+NB_FRAME_SIZE, 2*NB_PITCH_END + NB_SUBFRAME_SIZE + 12); + + /* If null mode (no transmission), just set a couple things to zero*/ + if (st->submodes[st->submodeID] == NULL) + { + VARDECL(spx_coef_t *lpc); + ALLOC(lpc, NB_ORDER, spx_coef_t); + bw_lpc(QCONST16(0.93f,15), st->interp_qlpc, lpc, NB_ORDER); + { + spx_word16_t innov_gain=0; + /* FIXME: This was innov, not exc */ + innov_gain = compute_rms16(st->exc, NB_FRAME_SIZE); + for (i=0;iexc[i]=speex_rand(innov_gain, &st->seed); + } + + + st->first=1; + + /* Final signal synthesis from excitation */ + iir_mem16(st->exc, lpc, out, NB_FRAME_SIZE, NB_ORDER, st->mem_sp, stack); + + /* Normally this is written to later but since this is returning early, + avoid reading uninitialized memory in caller */ + if (st->innov_save) + SPEEX_MEMSET(st->innov_save, 0, NB_NB_SUBFRAMES*NB_SUBFRAME_SIZE); + + st->count_lost=0; + return 0; + } + + ALLOC(qlsp, NB_ORDER, spx_lsp_t); + + /* Unquantize LSPs */ + SUBMODE(lsp_unquant)(qlsp, NB_ORDER, bits); + + /*Damp memory if a frame was lost and the LSP changed too much*/ + if (st->count_lost) + { + spx_word16_t fact; + spx_word32_t lsp_dist=0; + for (i=0;iold_qlsp[i] - qlsp[i]))); +#ifdef FIXED_POINT + fact = SHR16(19661,SHR32(lsp_dist,LSP_SHIFT+2)); +#else + fact = .6*exp(-.2*lsp_dist); +#endif + for (i=0;imem_sp[i] = MULT16_32_Q15(fact,st->mem_sp[i]); + } + + + /* Handle first frame and lost-packet case */ + if (st->first || st->count_lost) + { + for (i=0;iold_qlsp[i] = qlsp[i]; + } + + /* Get open-loop pitch estimation for low bit-rate pitch coding */ + if (SUBMODE(lbr_pitch)!=-1) + { + ol_pitch = NB_PITCH_START+speex_bits_unpack_unsigned(bits, 7); + } + + if (SUBMODE(forced_pitch_gain)) + { + int quant; + quant = speex_bits_unpack_unsigned(bits, 4); + ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT)); + } + + /* Get global excitation gain */ + { + int qe; + qe = speex_bits_unpack_unsigned(bits, 5); +#ifdef FIXED_POINT + /* FIXME: Perhaps we could slightly lower the gain here when the output is going to saturate? */ + ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]); +#else + ol_gain = SIG_SCALING*exp(qe/3.5); +#endif + } + + ALLOC(ak, NB_ORDER, spx_coef_t); + ALLOC(innov, NB_SUBFRAME_SIZE, spx_sig_t); + ALLOC(exc32, NB_SUBFRAME_SIZE, spx_word32_t); + + if (st->submodeID==1) + { + int extra; + extra = speex_bits_unpack_unsigned(bits, 4); + + if (extra==15) + st->dtx_enabled=1; + else + st->dtx_enabled=0; + } + if (st->submodeID>1) + st->dtx_enabled=0; + + /*Loop on subframes */ + for (sub=0;subexc+offset; + /* Original signal */ + if (st->innov_save) + innov_save = st->innov_save+offset; + + + /* Reset excitation */ + SPEEX_MEMSET(exc, 0, NB_SUBFRAME_SIZE); + + /*Adaptive codebook contribution*/ + speex_assert (SUBMODE(ltp_unquant)); + { + int pit_min, pit_max; + /* Handle pitch constraints if any */ + if (SUBMODE(lbr_pitch) != -1) + { + int margin; + margin = SUBMODE(lbr_pitch); + if (margin) + { +/* GT - need optimization? + if (ol_pitch < NB_PITCH_START+margin-1) + ol_pitch=NB_PITCH_START+margin-1; + if (ol_pitch > NB_PITCH_END-margin) + ol_pitch=NB_PITCH_END-margin; + pit_min = ol_pitch-margin+1; + pit_max = ol_pitch+margin; +*/ + pit_min = ol_pitch-margin+1; + if (pit_min < NB_PITCH_START) + pit_min = NB_PITCH_START; + pit_max = ol_pitch+margin; + if (pit_max > NB_PITCH_END) + pit_max = NB_PITCH_END; + } else { + pit_min = pit_max = ol_pitch; + } + } else { + pit_min = NB_PITCH_START; + pit_max = NB_PITCH_END; + } + + + + SUBMODE(ltp_unquant)(exc, exc32, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params), + NB_SUBFRAME_SIZE, &pitch, &pitch_gain[0], bits, stack, + st->count_lost, offset, st->last_pitch_gain, 0); + + /* Ensuring that things aren't blowing up as would happen if e.g. an encoder is + crafting packets to make us produce NaNs and slow down the decoder (vague DoS threat). + We can probably be even more aggressive and limit to 15000 or so. */ + sanitize_values32(exc32, NEG32(QCONST32(32000,SIG_SHIFT-1)), QCONST32(32000,SIG_SHIFT-1), NB_SUBFRAME_SIZE); + + tmp = gain_3tap_to_1tap(pitch_gain); + + pitch_average += tmp; + if ((tmp>best_pitch_gain&&ABS(2*best_pitch-pitch)>=3&&ABS(3*best_pitch-pitch)>=4&&ABS(4*best_pitch-pitch)>=5) + || (tmp>MULT16_16_Q15(QCONST16(.6,15),best_pitch_gain)&&(ABS(best_pitch-2*pitch)<3||ABS(best_pitch-3*pitch)<4||ABS(best_pitch-4*pitch)<5)) + || (MULT16_16_Q15(QCONST16(.67,15),tmp)>best_pitch_gain&&(ABS(2*best_pitch-pitch)<3||ABS(3*best_pitch-pitch)<4||ABS(4*best_pitch-pitch)<5)) ) + { + best_pitch = pitch; + if (tmp > best_pitch_gain) + best_pitch_gain = tmp; + } + } + + /* Unquantize the innovation */ + { + int q_energy; + spx_word32_t ener; + + SPEEX_MEMSET(innov, 0, NB_SUBFRAME_SIZE); + + /* Decode sub-frame gain correction */ + if (SUBMODE(have_subframe_gain)==3) + { + q_energy = speex_bits_unpack_unsigned(bits, 3); + ener = MULT16_32_Q14(exc_gain_quant_scal3[q_energy],ol_gain); + } else if (SUBMODE(have_subframe_gain)==1) + { + q_energy = speex_bits_unpack_unsigned(bits, 1); + ener = MULT16_32_Q14(exc_gain_quant_scal1[q_energy],ol_gain); + } else { + ener = ol_gain; + } + + speex_assert (SUBMODE(innovation_unquant)); + { + /*Fixed codebook contribution*/ + SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), NB_SUBFRAME_SIZE, bits, stack, &st->seed); + /* De-normalize innovation and update excitation */ + + signal_mul(innov, innov, ener, NB_SUBFRAME_SIZE); + + /* Decode second codebook (only for some modes) */ + if (SUBMODE(double_codebook)) + { + char *tmp_stack=stack; + VARDECL(spx_sig_t *innov2); + ALLOC(innov2, NB_SUBFRAME_SIZE, spx_sig_t); + SPEEX_MEMSET(innov2, 0, NB_SUBFRAME_SIZE); + SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), NB_SUBFRAME_SIZE, bits, stack, &st->seed); + signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener), NB_SUBFRAME_SIZE); + for (i=0;isubmodeID==1) + { + spx_word16_t g=ol_pitch_coef; + g=MULT16_16_P14(QCONST16(1.5f,14),(g-QCONST16(.2f,6))); + if (g<0) + g=0; + if (g>GAIN_SCALING) + g=GAIN_SCALING; + + SPEEX_MEMSET(exc, 0, NB_SUBFRAME_SIZE); + while (st->voc_offsetvoc_offset]= g*sqrt(2*ol_pitch)*ol_gain; + Not quite sure why we need the factor of two in the sqrt */ + if (st->voc_offset>=0) + exc[st->voc_offset]=MULT16_16(spx_sqrt(MULT16_16_16(2,ol_pitch)),EXTRACT16(PSHR32(MULT16_16(g,PSHR32(ol_gain,SIG_SHIFT)),6))); + st->voc_offset+=ol_pitch; + } + st->voc_offset -= NB_SUBFRAME_SIZE; + + for (i=0;ivoc_m1)), + SUB16(MULT16_16_Q15(Q15_ONE-MULT16_16_16(QCONST16(.85f,9),g),EXTRACT16(PSHR32(innov[i],SIG_SHIFT))), + MULT16_16_Q15(MULT16_16_16(QCONST16(.15f,9),g),EXTRACT16(PSHR32(st->voc_m2,SIG_SHIFT))) + )); + st->voc_m1 = exci; + st->voc_m2=innov[i]; + st->voc_mean = EXTRACT16(PSHR32(ADD32(MULT16_16(QCONST16(.8f,15),st->voc_mean), MULT16_16(QCONST16(.2f,15),exc[i])), 15)); + exc[i]-=st->voc_mean; + } + } + + } + } + + ALLOC(interp_qlsp, NB_ORDER, spx_lsp_t); + + if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0 && !st->count_lost) + { + multicomb(st->exc-NB_SUBFRAME_SIZE, out, st->interp_qlpc, NB_ORDER, 2*NB_SUBFRAME_SIZE, best_pitch, 40, SUBMODE(comb_gain), stack); + multicomb(st->exc+NB_SUBFRAME_SIZE, out+2*NB_SUBFRAME_SIZE, st->interp_qlpc, NB_ORDER, 2*NB_SUBFRAME_SIZE, best_pitch, 40, SUBMODE(comb_gain), stack); + } else { + SPEEX_COPY(out, &st->exc[-NB_SUBFRAME_SIZE], NB_FRAME_SIZE); + } + + /* If the last packet was lost, re-scale the excitation to obtain the same energy as encoded in ol_gain */ + if (st->count_lost) + { + spx_word16_t exc_ener; + spx_word32_t gain32; + spx_word16_t gain; + exc_ener = compute_rms16 (st->exc, NB_FRAME_SIZE); + gain32 = PDIV32(ol_gain, ADD16(exc_ener,1)); +#ifdef FIXED_POINT + if (gain32 > 32767) + gain32 = 32767; + gain = EXTRACT16(gain32); +#else + if (gain32 > 2) + gain32=2; + gain = gain32; +#endif + for (i=0;iexc[i] = MULT16_16_Q14(gain, st->exc[i]); + out[i]=st->exc[i-NB_SUBFRAME_SIZE]; + } + } + + /*Loop on subframes */ + for (sub=0;subold_qlsp, qlsp, interp_qlsp, NB_ORDER, sub, NB_NB_SUBFRAMES, LSP_MARGIN); + + /* Compute interpolated LPCs (unquantized) */ + lsp_to_lpc(interp_qlsp, ak, NB_ORDER, stack); + + /* Compute analysis filter at w=pi */ + { + spx_word32_t pi_g=LPC_SCALING; + for (i=0;iinterp_qlpc[i] + st->interp_qlpc[i+1];*/ + pi_g = ADD32(pi_g, SUB32(EXTEND32(ak[i+1]),EXTEND32(ak[i]))); + } + st->pi_gain[sub] = pi_g; + } + + iir_mem16(sp, st->interp_qlpc, sp, NB_SUBFRAME_SIZE, NB_ORDER, + st->mem_sp, stack); + + for (i=0;iinterp_qlpc[i] = ak[i]; + + } + + if (st->highpass_enabled) + highpass(out, out, NB_FRAME_SIZE, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS_NARROWBAND)|HIGHPASS_OUTPUT, st->mem_hp); + /*for (i=0;iframe[i]);*/ + + /* Tracking output level */ + st->level = 1+PSHR32(ol_gain,SIG_SHIFT); + st->max_level = MAX16(MULT16_16_Q15(QCONST16(.99f,15), st->max_level), st->level); + st->min_level = MIN16(ADD16(1,MULT16_16_Q14(QCONST16(1.01f,14), st->min_level)), st->level); + if (st->max_level < st->min_level+1) + st->max_level = st->min_level+1; + /*printf ("%f %f %f %d\n", og, st->min_level, st->max_level, update);*/ + + /* Store the LSPs for interpolation in the next frame */ + for (i=0;iold_qlsp[i] = qlsp[i]; + + /* The next frame will not be the first (Duh!) */ + st->first = 0; + st->count_lost=0; + st->last_pitch = best_pitch; +#ifdef FIXED_POINT + st->last_pitch_gain = PSHR16(pitch_average,2); +#else + st->last_pitch_gain = .25*pitch_average; +#endif + st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain; + if (st->pitch_gain_buf_idx > 2) /* rollover */ + st->pitch_gain_buf_idx = 0; + + st->last_ol_gain = ol_gain; + + return 0; +} +#endif /* DISABLE_DECODER */ + diff --git a/external/speex/src/nb_celp.h b/external/speex/src/nb_celp.h index 7439f1c..8fe60ce 100644 --- a/external/speex/src/nb_celp.h +++ b/external/speex/src/nb_celp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ +/* Copyright (C) 2002-2006 Jean-Marc Valin */ /** @file nb_celp.h @brief Narrowband CELP encoder/decoder @@ -7,18 +7,18 @@ 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 @@ -37,160 +37,157 @@ #define NB_CELP_H #include "modes.h" -#include "speex_bits.h" -#include "speex_callbacks.h" +#include "speex/speex_callbacks.h" #include "vbr.h" #include "filters.h" +#ifdef VORBIS_PSYCHO +#include "vorbis_psy.h" +#endif + +#define NB_ORDER 10 +#define NB_FRAME_SIZE 160 +#define NB_SUBFRAME_SIZE 40 +#define NB_NB_SUBFRAMES 4 +#define NB_PITCH_START 17 +#define NB_PITCH_END 144 + +#define NB_WINDOW_SIZE (NB_FRAME_SIZE+NB_SUBFRAME_SIZE) +#define NB_EXCBUF (NB_FRAME_SIZE+NB_PITCH_END+2) +#define NB_DEC_BUFFER (NB_FRAME_SIZE+2*NB_PITCH_END+NB_SUBFRAME_SIZE+12) /**Structure representing the full state of the narrowband encoder*/ typedef struct EncState { - SpeexMode *mode; /**< Mode corresponding to the state */ - int first; /**< Is this the first frame? */ - int frameSize; /**< Size of frames */ - int subframeSize; /**< Size of sub-frames */ - int nbSubframes; /**< Number of sub-frames */ - int windowSize; /**< Analysis (LPC) window length */ - int lpcSize; /**< LPC order */ - int bufSize; /**< Buffer size */ - int min_pitch; /**< Minimum pitch value allowed */ - int max_pitch; /**< Maximum pitch value allowed */ + const SpeexMode *mode; /**< Mode corresponding to the state */ + int first; /**< Is this the first frame? */ - int safe_pitch; /**< Don't use too large values for pitch (in case we lose a packet) */ - int bounded_pitch; /**< Next frame should not rely on previous frames for pitch */ - int ol_pitch; /**< Open-loop pitch */ - int ol_voiced; /**< Open-loop voiced/non-voiced decision */ - int *pitch; - float gamma1; /**< Perceptual filter: A(z/gamma1) */ - float gamma2; /**< Perceptual filter: A(z/gamma2) */ - float lag_factor; /**< Lag windowing Gaussian width */ - float lpc_floor; /**< Noise floor multiplier for A[0] in LPC analysis*/ - float preemph; /**< Pre-emphasis: P(z) = 1 - a*z^-1*/ - float pre_mem; /**< 1-element memory for pre-emphasis */ - float pre_mem2; /**< 1-element memory for pre-emphasis */ - char *stack; /**< Pseudo-stack allocation for temporary memory */ - float *inBuf; /**< Input buffer (original signal) */ - float *frame; /**< Start of original frame */ - float *excBuf; /**< Excitation buffer */ - float *exc; /**< Start of excitation frame */ - float *exc2Buf; /**< "Pitch enhanced" excitation */ - float *exc2; /**< "Pitch enhanced" excitation */ - float *swBuf; /**< Weighted signal buffer */ - float *sw; /**< Start of weighted signal frame */ - float *innov; /**< Innovation for the frame */ - float *window; /**< Temporary (Hanning) window */ - float *buf2; /**< 2nd temporary buffer */ - float *autocorr; /**< auto-correlation */ - float *lagWindow; /**< Window applied to auto-correlation */ - float *lpc; /**< LPCs for current frame */ - float *lsp; /**< LSPs for current frame */ - float *qlsp; /**< Quantized LSPs for current frame */ - float *old_lsp; /**< LSPs for previous frame */ - float *old_qlsp; /**< Quantized LSPs for previous frame */ - float *interp_lsp; /**< Interpolated LSPs */ - float *interp_qlsp; /**< Interpolated quantized LSPs */ - float *interp_lpc; /**< Interpolated LPCs */ - float *interp_qlpc; /**< Interpolated quantized LPCs */ - float *bw_lpc1; /**< LPCs after bandwidth expansion by gamma1 for perceptual weighting*/ - float *bw_lpc2; /**< LPCs after bandwidth expansion by gamma2 for perceptual weighting*/ - float *rc; /**< Reflection coefficients */ - float *mem_sp; /**< Filter memory for signal synthesis */ - float *mem_sw; /**< Filter memory for perceptually-weighted signal */ - float *mem_sw_whole; /**< Filter memory for perceptually-weighted signal (whole frame)*/ - float *mem_exc; /**< Filter memory for excitation (whole frame) */ - float *pi_gain; /**< Gain of LPC filter at theta=pi (fe/2) */ + spx_word32_t cumul_gain; /**< Product of previously used pitch gains (Q10) */ + int bounded_pitch; /**< Next frame should not rely on previous frames for pitch */ + int ol_pitch; /**< Open-loop pitch */ + int ol_voiced; /**< Open-loop voiced/non-voiced decision */ + int pitch[NB_NB_SUBFRAMES]; - VBRState *vbr; /**< State of the VBR data */ - float vbr_quality; /**< Quality setting for VBR encoding */ - float relative_quality; /**< Relative quality that will be needed by VBR */ - int vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */ - int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */ - int dtx_enabled; /**< 1 for enabling DTX, 0 otherwise */ - int dtx_count; /**< Number of consecutive DTX frames */ - int abr_enabled; /**< ABR setting (in bps), 0 if off */ +#ifdef VORBIS_PSYCHO + VorbisPsy *psy; + float *psy_window; + float *curve; + float *old_curve; +#endif + + spx_word16_t gamma1; /**< Perceptual filter: A(z/gamma1) */ + spx_word16_t gamma2; /**< Perceptual filter: A(z/gamma2) */ + spx_word16_t lpc_floor; /**< Noise floor multiplier for A[0] in LPC analysis*/ + char *stack; /**< Pseudo-stack allocation for temporary memory */ + spx_word16_t winBuf[NB_WINDOW_SIZE-NB_FRAME_SIZE]; /**< Input buffer (original signal) */ + spx_word16_t excBuf[NB_EXCBUF]; /**< Excitation buffer */ + spx_word16_t *exc; /**< Start of excitation frame */ + spx_word16_t swBuf[NB_EXCBUF]; /**< Weighted signal buffer */ + spx_word16_t *sw; /**< Start of weighted signal frame */ + const spx_word16_t *window; /**< Temporary (Hanning) window */ + const spx_word16_t *lagWindow; /**< Window applied to auto-correlation */ + spx_lsp_t old_lsp[NB_ORDER]; /**< LSPs for previous frame */ + spx_lsp_t old_qlsp[NB_ORDER]; /**< Quantized LSPs for previous frame */ + spx_mem_t mem_sp[NB_ORDER]; /**< Filter memory for signal synthesis */ + spx_mem_t mem_sw[NB_ORDER]; /**< Filter memory for perceptually-weighted signal */ + spx_mem_t mem_sw_whole[NB_ORDER]; /**< Filter memory for perceptually-weighted signal (whole frame)*/ + spx_mem_t mem_exc[NB_ORDER]; /**< Filter memory for excitation (whole frame) */ + spx_mem_t mem_exc2[NB_ORDER]; /**< Filter memory for excitation (whole frame) */ + spx_mem_t mem_hp[2]; /**< High-pass filter memory */ + spx_word32_t pi_gain[NB_NB_SUBFRAMES]; /**< Gain of LPC filter at theta=pi (fe/2) */ + spx_word16_t *innov_rms_save; /**< If non-NULL, innovation RMS is copied here */ + +#ifndef DISABLE_VBR + VBRState vbr; /**< State of the VBR data */ + float vbr_quality; /**< Quality setting for VBR encoding */ + float relative_quality; /**< Relative quality that will be needed by VBR */ + spx_int32_t vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */ + spx_int32_t vbr_max; /**< Max bit-rate allowed in VBR mode */ + int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */ + int dtx_enabled; /**< 1 for enabling DTX, 0 otherwise */ + int dtx_count; /**< Number of consecutive DTX frames */ + spx_int32_t abr_enabled; /**< ABR setting (in bps), 0 if off */ float abr_drift; float abr_drift2; float abr_count; - int complexity; /**< Complexity setting (0-10 from least complex to most complex) */ - int sampling_rate; +#endif /* #ifndef DISABLE_VBR */ - SpeexSubmode **submodes; /**< Sub-mode data */ - int submodeID; /**< Activated sub-mode */ - int submodeSelect; /**< Mode chosen by the user (may differ from submodeID if VAD is on) */ + int complexity; /**< Complexity setting (0-10 from least complex to most complex) */ + spx_int32_t sampling_rate; + int plc_tuning; + int encode_submode; + const SpeexSubmode * const *submodes; /**< Sub-mode data */ + int submodeID; /**< Activated sub-mode */ + int submodeSelect; /**< Mode chosen by the user (may differ from submodeID if VAD is on) */ + int isWideband; /**< Is this used as part of the embedded wideband codec */ + int highpass_enabled; /**< Is the input filter enabled */ } EncState; /**Structure representing the full state of the narrowband decoder*/ typedef struct DecState { - SpeexMode *mode; /**< Mode corresponding to the state */ - int first; /**< Is this the first frame? */ - int count_lost; /**< Was the last frame lost? */ - int frameSize; /**< Size of frames */ - int subframeSize; /**< Size of sub-frames */ - int nbSubframes; /**< Number of sub-frames */ - int windowSize; /**< Analysis (LPC) window length */ - int lpcSize; /**< LPC order */ - int bufSize; /**< Buffer size */ - int min_pitch; /**< Minimum pitch value allowed */ - int max_pitch; /**< Maximum pitch value allowed */ - int sampling_rate; - float last_ol_gain; /**< Open-loop gain for previous frame */ + const SpeexMode *mode; /**< Mode corresponding to the state */ + int first; /**< Is this the first frame? */ + int count_lost; /**< Was the last frame lost? */ + spx_int32_t sampling_rate; + spx_word16_t last_ol_gain; /**< Open-loop gain for previous frame */ - float gamma1; /**< Perceptual filter: A(z/gamma1) */ - float gamma2; /**< Perceptual filter: A(z/gamma2) */ - float preemph; /**< Pre-emphasis: P(z) = 1 - a*z^-1*/ - float pre_mem; /**< 1-element memory for pre-emphasis */ - char *stack; /**< Pseudo-stack allocation for temporary memory */ - float *inBuf; /**< Input buffer (original signal) */ - float *frame; /**< Start of original frame */ - float *excBuf; /**< Excitation buffer */ - float *exc; /**< Start of excitation frame */ - float *innov; /**< Innovation for the frame */ - float *qlsp; /**< Quantized LSPs for current frame */ - float *old_qlsp; /**< Quantized LSPs for previous frame */ - float *interp_qlsp; /**< Interpolated quantized LSPs */ - float *interp_qlpc; /**< Interpolated quantized LPCs */ - float *mem_sp; /**< Filter memory for synthesis signal */ - float *pi_gain; /**< Gain of LPC filter at theta=pi (fe/2) */ - int last_pitch; /**< Pitch of last correctly decoded frame */ - float last_pitch_gain; /**< Pitch gain of last correctly decoded frame */ - float pitch_gain_buf[3]; /**< Pitch gain of last decoded frames */ - int pitch_gain_buf_idx; /**< Tail of the buffer */ + char *stack; /**< Pseudo-stack allocation for temporary memory */ + spx_word16_t excBuf[NB_DEC_BUFFER]; /**< Excitation buffer */ + spx_word16_t *exc; /**< Start of excitation frame */ + spx_lsp_t old_qlsp[NB_ORDER]; /**< Quantized LSPs for previous frame */ + spx_coef_t interp_qlpc[NB_ORDER]; /**< Interpolated quantized LPCs */ + spx_mem_t mem_sp[NB_ORDER]; /**< Filter memory for synthesis signal */ + spx_mem_t mem_hp[2]; /**< High-pass filter memory */ + spx_word32_t pi_gain[NB_NB_SUBFRAMES]; /**< Gain of LPC filter at theta=pi (fe/2) */ + spx_word16_t *innov_save; /** If non-NULL, innovation is copied here */ - SpeexSubmode **submodes; /**< Sub-mode data */ - int submodeID; /**< Activated sub-mode */ - int lpc_enh_enabled; /**< 1 when LPC enhancer is on, 0 otherwise */ - CombFilterMem *comb_mem; + spx_word16_t level; + spx_word16_t max_level; + spx_word16_t min_level; + + /* This is used in packet loss concealment */ + int last_pitch; /**< Pitch of last correctly decoded frame */ + spx_word16_t last_pitch_gain; /**< Pitch gain of last correctly decoded frame */ + spx_word16_t pitch_gain_buf[3]; /**< Pitch gain of last decoded frames */ + int pitch_gain_buf_idx; /**< Tail of the buffer */ + spx_uint32_t seed; /** Seed used for random number generation */ + + int encode_submode; + const SpeexSubmode * const *submodes; /**< Sub-mode data */ + int submodeID; /**< Activated sub-mode */ + int lpc_enh_enabled; /**< 1 when LPC enhancer is on, 0 otherwise */ SpeexCallback speex_callbacks[SPEEX_MAX_CALLBACKS]; SpeexCallback user_callback; /*Vocoder data*/ - float voc_m1; - float voc_m2; - float voc_mean; + spx_word16_t voc_m1; + spx_word32_t voc_m2; + spx_word16_t voc_mean; int voc_offset; int dtx_enabled; + int isWideband; /**< Is this used as part of the embedded wideband codec */ + int highpass_enabled; /**< Is the input filter enabled */ } DecState; /** Initializes encoder state*/ -void *nb_encoder_init(SpeexMode *m); +void *nb_encoder_init(const SpeexMode *m); /** De-allocates encoder state resources*/ void nb_encoder_destroy(void *state); /** Encodes one frame*/ -int nb_encode(void *state, float *in, SpeexBits *bits); +int nb_encode(void *state, void *in, SpeexBits *bits); /** Initializes decoder state*/ -void *nb_decoder_init(SpeexMode *m); +void *nb_decoder_init(const SpeexMode *m); /** De-allocates decoder state resources*/ void nb_decoder_destroy(void *state); /** Decodes one frame*/ -int nb_decode(void *state, SpeexBits *bits, float *out); +int nb_decode(void *state, SpeexBits *bits, void *out); /** ioctl-like function for controlling a narrowband encoder */ int nb_encoder_ctl(void *state, int request, void *ptr); diff --git a/external/speex/src/os_support.h b/external/speex/src/os_support.h new file mode 100644 index 0000000..0db31a6 --- /dev/null +++ b/external/speex/src/os_support.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: os_support.h + This is the (tiny) OS abstraction layer. Aside from math.h, this is the + only place where system headers are allowed. + + 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 OS_SUPPORT_H +#define OS_SUPPORT_H + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef OS_SUPPORT_CUSTOM +#include "os_support_custom.h" +#endif + +/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free + NOTE: speex_alloc needs to CLEAR THE MEMORY */ +#ifndef OVERRIDE_SPEEX_ALLOC +static inline void *speex_alloc (int size) +{ + /* WARNING: this is not equivalent to malloc(). If you want to use malloc() + or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise + you will experience strange bugs */ + return calloc(size,1); +} +#endif + +/** Same as speex_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ +#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH +static inline void *speex_alloc_scratch (int size) +{ + /* Scratch space doesn't need to be cleared */ + return calloc(size,1); +} +#endif + +/** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, speex_alloc and speex_free */ +#ifndef OVERRIDE_SPEEX_REALLOC +static inline void *speex_realloc (void *ptr, int size) +{ + return realloc(ptr, size); +} +#endif + +/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_alloc */ +#ifndef OVERRIDE_SPEEX_FREE +static inline void speex_free (void *ptr) +{ + free(ptr); +} +#endif + +/** Same as speex_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ +#ifndef OVERRIDE_SPEEX_FREE_SCRATCH +static inline void speex_free_scratch (void *ptr) +{ + free(ptr); +} +#endif + +/** Copy n elements from src to dst. The 0* term provides compile-time type checking */ +#ifndef OVERRIDE_SPEEX_COPY +#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#endif + +/** Copy n elements from src to dst, allowing overlapping regions. The 0* term + provides compile-time type checking */ +#ifndef OVERRIDE_SPEEX_MOVE +#define SPEEX_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#endif + +/** For n elements worth of memory, set every byte to the value of c, starting at address dst */ +#ifndef OVERRIDE_SPEEX_MEMSET +#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) +#endif + + +#ifndef OVERRIDE_SPEEX_FATAL +static inline void _speex_fatal(const char *str, const char *file, int line) +{ + fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); + exit(1); +} +#endif + +#ifndef OVERRIDE_SPEEX_WARNING +static inline void speex_warning(const char *str) +{ +#ifndef DISABLE_WARNINGS + fprintf (stderr, "warning: %s\n", str); +#endif +} +#endif + +#ifndef OVERRIDE_SPEEX_WARNING_INT +static inline void speex_warning_int(const char *str, int val) +{ +#ifndef DISABLE_WARNINGS + fprintf (stderr, "warning: %s %d\n", str, val); +#endif +} +#endif + +#ifndef OVERRIDE_SPEEX_NOTIFY +static inline void speex_notify(const char *str) +{ +#ifndef DISABLE_NOTIFICATIONS + fprintf (stderr, "notification: %s\n", str); +#endif +} +#endif + +#ifndef OVERRIDE_SPEEX_PUTC +/** Speex wrapper for putc */ +static inline void _speex_putc(int ch, void *file) +{ + FILE *f = (FILE *)file; + fprintf(f, "%c", ch); +} +#endif + +#define speex_fatal(str) _speex_fatal(str, __FILE__, __LINE__); +#define speex_assert(cond) {if (!(cond)) {speex_fatal("assertion failed: " #cond);}} + +#ifndef RELEASE +static inline void print_vec(float *vec, int len, char *name) +{ + int i; + printf ("%s ", name); + for (i=0;i +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif -extern int lsp_nb_vqid[64]; -static float quant_weight[MAX_LSP_SIZE]; +#include "arch.h" -/* Note: x is modified*/ -static int lsp_quant(float *x, signed char *cdbk, int nbVec, int nbDim) -{ - int i,j; - float dist, tmp; - float best_dist=0; - int best_id=0; - signed char *ptr=cdbk; - for (i=0;i tmp2 ? tmp1 : tmp2; - } - for (i=0;i tmp2 ? tmp1 : tmp2; - } + compute_quant_weights(qlsp, quant_weight, order); for (i=0;i tmp2 ? tmp1 : tmp2; - } + }*/ for (i=0;i>> 16;\n\t" +" R1 = (A1 += R2.L*R0.H) (IS);\n\t" +"4: R3 = R3 + R1;\n\t" + +" cc =R3<%0;\n\t" +" if cc %0=R3;\n\t" +" if cc %1=R5;\n\t" +"2: R5 += 1;\n\t" +" L0 = 0;\n\t" +" L1 = 0;\n\t" + : "=&d" (best_dist), "=&d" (best_id) + : "a" (x), "a" (weight), "b" (cdbk), "a" (nbVec), "a" (nbDim) + : "I0", "I1", "P2", "R0", "R1", "R2", "R3", "R5", "A1", + "L0", "L1", "B0", "B1", "CC", "ASTAT" BFIN_HWLOOP0_REGS BFIN_HWLOOP1_REGS + ); + + for (j=0;j #include "sb_celp.h" -#include "stdlib.h" #include "filters.h" #include "lpc.h" #include "lsp.h" @@ -41,183 +43,185 @@ #include "quant_lsp.h" #include "vq.h" #include "ltp.h" -#include "misc.h" +#include "arch.h" +#include "math_approx.h" +#include "os_support.h" -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ +#ifndef NULL +#define NULL 0 #endif -#define sqr(x) ((x)*(x)) +/* Default size for the encoder and decoder stack (can be changed at compile time). + This does not apply when using variable-size arrays or alloca. */ +#ifndef SB_ENC_STACK +#define SB_ENC_STACK (10000*sizeof(spx_sig_t)) +#endif + +#ifndef SB_DEC_STACK +#define SB_DEC_STACK (6000*sizeof(spx_sig_t)) +#endif + + +#ifndef DISABLE_WIDEBAND #define SUBMODE(x) st->submodes[st->submodeID]->x +#ifdef FIXED_POINT +static const spx_word16_t gc_quant_bound[16] = {125, 164, 215, 282, 370, 484, 635, 832, 1090, 1428, 1871, 2452, 3213, 4210, 5516, 7228}; +static const spx_word16_t fold_quant_bound[32] = { + 39, 44, 50, 57, 64, 73, 83, 94, + 106, 120, 136, 154, 175, 198, 225, 255, + 288, 327, 370, 420, 476, 539, 611, 692, + 784, 889, 1007, 1141, 1293, 1465, 1660, 1881}; +#define LSP_MARGIN 410 +#define LSP_DELTA1 6553 +#define LSP_DELTA2 1638 + +#else + +static const spx_word16_t gc_quant_bound[16] = { + 0.97979, 1.28384, 1.68223, 2.20426, 2.88829, 3.78458, 4.95900, 6.49787, + 8.51428, 11.15642, 14.61846, 19.15484, 25.09895, 32.88761, 43.09325, 56.46588}; +static const spx_word16_t fold_quant_bound[32] = { + 0.30498, 0.34559, 0.39161, 0.44375, 0.50283, 0.56979, 0.64565, 0.73162, + 0.82903, 0.93942, 1.06450, 1.20624, 1.36685, 1.54884, 1.75506, 1.98875, + 2.25355, 2.55360, 2.89361, 3.27889, 3.71547, 4.21018, 4.77076, 5.40598, + 6.12577, 6.94141, 7.86565, 8.91295, 10.09969, 11.44445, 12.96826, 14.69497}; + +#define LSP_MARGIN .05 +#define LSP_DELTA1 .2 +#define LSP_DELTA2 .05 + +#endif + #define QMF_ORDER 64 -static float h0[64] = { - 3.596189e-05, -0.0001123515, - -0.0001104587, 0.0002790277, - 0.0002298438, -0.0005953563, - -0.0003823631, 0.00113826, - 0.0005308539, -0.001986177, - -0.0006243724, 0.003235877, - 0.0005743159, -0.004989147, - -0.0002584767, 0.007367171, - -0.0004857935, -0.01050689, - 0.001894714, 0.01459396, - -0.004313674, -0.01994365, - 0.00828756, 0.02716055, - -0.01485397, -0.03764973, - 0.026447, 0.05543245, - -0.05095487, -0.09779096, - 0.1382363, 0.4600981, - 0.4600981, 0.1382363, - -0.09779096, -0.05095487, - 0.05543245, 0.026447, - -0.03764973, -0.01485397, - 0.02716055, 0.00828756, - -0.01994365, -0.004313674, - 0.01459396, 0.001894714, - -0.01050689, -0.0004857935, - 0.007367171, -0.0002584767, - -0.004989147, 0.0005743159, - 0.003235877, -0.0006243724, - -0.001986177, 0.0005308539, - 0.00113826, -0.0003823631, - -0.0005953563, 0.0002298438, - 0.0002790277, -0.0001104587, - -0.0001123515, 3.596189e-05 + +#ifdef FIXED_POINT +static const spx_word16_t h0[64] = {2, -7, -7, 18, 15, -39, -25, 75, 35, -130, -41, 212, 38, -327, -17, 483, -32, -689, 124, 956, -283, -1307, 543, 1780, -973, -2467, 1733, 3633, -3339, -6409, 9059, 30153, 30153, 9059, -6409, -3339, 3633, 1733, -2467, -973, 1780, 543, -1307, -283, 956, 124, -689, -32, 483, -17, -327, 38, 212, -41, -130, 35, 75, -25, -39, 15, 18, -7, -7, 2}; + +#else +static const float h0[64] = { + 3.596189e-05f, -0.0001123515f, + -0.0001104587f, 0.0002790277f, + 0.0002298438f, -0.0005953563f, + -0.0003823631f, 0.00113826f, + 0.0005308539f, -0.001986177f, + -0.0006243724f, 0.003235877f, + 0.0005743159f, -0.004989147f, + -0.0002584767f, 0.007367171f, + -0.0004857935f, -0.01050689f, + 0.001894714f, 0.01459396f, + -0.004313674f, -0.01994365f, + 0.00828756f, 0.02716055f, + -0.01485397f, -0.03764973f, + 0.026447f, 0.05543245f, + -0.05095487f, -0.09779096f, + 0.1382363f, 0.4600981f, + 0.4600981f, 0.1382363f, + -0.09779096f, -0.05095487f, + 0.05543245f, 0.026447f, + -0.03764973f, -0.01485397f, + 0.02716055f, 0.00828756f, + -0.01994365f, -0.004313674f, + 0.01459396f, 0.001894714f, + -0.01050689f, -0.0004857935f, + 0.007367171f, -0.0002584767f, + -0.004989147f, 0.0005743159f, + 0.003235877f, -0.0006243724f, + -0.001986177f, 0.0005308539f, + 0.00113826f, -0.0003823631f, + -0.0005953563f, 0.0002298438f, + 0.0002790277f, -0.0001104587f, + -0.0001123515f, 3.596189e-05f }; -static float h1[64] = { - 3.596189e-05, 0.0001123515, - -0.0001104587, -0.0002790277, - 0.0002298438, 0.0005953563, - -0.0003823631, -0.00113826, - 0.0005308539, 0.001986177, - -0.0006243724, -0.003235877, - 0.0005743159, 0.004989147, - -0.0002584767, -0.007367171, - -0.0004857935, 0.01050689, - 0.001894714, -0.01459396, - -0.004313674, 0.01994365, - 0.00828756, -0.02716055, - -0.01485397, 0.03764973, - 0.026447, -0.05543245, - -0.05095487, 0.09779096, - 0.1382363, -0.4600981, - 0.4600981, -0.1382363, - -0.09779096, 0.05095487, - 0.05543245, -0.026447, - -0.03764973, 0.01485397, - 0.02716055, -0.00828756, - -0.01994365, 0.004313674, - 0.01459396, -0.001894714, - -0.01050689, 0.0004857935, - 0.007367171, 0.0002584767, - -0.004989147, -0.0005743159, - 0.003235877, 0.0006243724, - -0.001986177, -0.0005308539, - 0.00113826, 0.0003823631, - -0.0005953563, -0.0002298438, - 0.0002790277, 0.0001104587, - -0.0001123515, -3.596189e-05 -}; +#endif -void *sb_encoder_init(SpeexMode *m) +extern const spx_word16_t lag_window[]; +extern const spx_word16_t lpc_window[]; + +#ifndef DISABLE_ENCODER +void *sb_encoder_init(const SpeexMode *m) { int i; + spx_int32_t tmp; SBEncState *st; - SpeexSBMode *mode; + const SpeexSBMode *mode; - st = (SBEncState*)speex_alloc(sizeof(SBEncState)+8000*sizeof(float)); + st = (SBEncState*)speex_alloc(sizeof(SBEncState)); + if (!st) + return NULL; st->mode = m; - mode = (SpeexSBMode*)m->mode; + mode = (const SpeexSBMode*)m->mode; - st->stack = ((char*)st) + sizeof(SBEncState); st->st_low = speex_encoder_init(mode->nb_mode); +#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) + st->stack = NULL; +#else + /*st->stack = (char*)speex_alloc_scratch(SB_ENC_STACK);*/ + speex_encoder_ctl(st->st_low, SPEEX_GET_STACK, &st->stack); +#endif + st->full_frame_size = 2*mode->frameSize; st->frame_size = mode->frameSize; st->subframeSize = mode->subframeSize; st->nbSubframes = mode->frameSize/mode->subframeSize; - st->windowSize = st->frame_size*3/2; + st->windowSize = st->frame_size+st->subframeSize; st->lpcSize=mode->lpcSize; - st->bufSize=mode->bufSize; + st->encode_submode = 1; st->submodes=mode->submodes; st->submodeSelect = st->submodeID=mode->defaultSubmode; - - i=9; - speex_encoder_ctl(st->st_low, SPEEX_SET_QUALITY, &i); - st->lag_factor = mode->lag_factor; + tmp=9; + speex_encoder_ctl(st->st_low, SPEEX_SET_QUALITY, &tmp); + tmp=1; + speex_encoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, &tmp); + st->lpc_floor = mode->lpc_floor; st->gamma1=mode->gamma1; st->gamma2=mode->gamma2; st->first=1; - st->x0d=PUSH(st->stack, st->frame_size, float); - st->x1d=PUSH(st->stack, st->frame_size, float); - st->high=PUSH(st->stack, st->full_frame_size, float); - st->y0=PUSH(st->stack, st->full_frame_size, float); - st->y1=PUSH(st->stack, st->full_frame_size, float); + st->high=(spx_word16_t*)speex_alloc((st->windowSize-st->frame_size)*sizeof(spx_word16_t)); - st->h0_mem=PUSH(st->stack, QMF_ORDER, float); - st->h1_mem=PUSH(st->stack, QMF_ORDER, float); - st->g0_mem=PUSH(st->stack, QMF_ORDER, float); - st->g1_mem=PUSH(st->stack, QMF_ORDER, float); + st->h0_mem=(spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); - st->buf=PUSH(st->stack, st->windowSize, float); - st->excBuf=PUSH(st->stack, st->bufSize, float); - st->exc = st->excBuf + st->bufSize - st->windowSize; + st->window= lpc_window; - st->res=PUSH(st->stack, st->frame_size, float); - st->sw=PUSH(st->stack, st->frame_size, float); - st->target=PUSH(st->stack, st->frame_size, float); - /*Asymmetric "pseudo-Hamming" window*/ - { - int part1, part2; - part1 = st->subframeSize*7/2; - part2 = st->subframeSize*5/2; - st->window = PUSH(st->stack, st->windowSize, float); - for (i=0;iwindow[i]=.54-.46*cos(M_PI*i/part1); - for (i=0;iwindow[part1+i]=.54+.46*cos(M_PI*i/part2); - } + st->lagWindow = lag_window; - st->lagWindow = PUSH(st->stack, st->lpcSize+1, float); - for (i=0;ilpcSize+1;i++) - st->lagWindow[i]=exp(-.5*sqr(2*M_PI*st->lag_factor*i)); + st->old_lsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); + st->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); + st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); + st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); + st->exc_rms = (spx_word16_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word16_t)); + st->innov_rms_save = NULL; - st->rc = PUSH(st->stack, st->lpcSize, float); - st->autocorr = PUSH(st->stack, st->lpcSize+1, float); - st->lpc = PUSH(st->stack, st->lpcSize+1, float); - st->bw_lpc1 = PUSH(st->stack, st->lpcSize+1, float); - st->bw_lpc2 = PUSH(st->stack, st->lpcSize+1, float); - st->lsp = PUSH(st->stack, st->lpcSize, float); - st->qlsp = PUSH(st->stack, st->lpcSize, float); - st->old_lsp = PUSH(st->stack, st->lpcSize, float); - st->old_qlsp = PUSH(st->stack, st->lpcSize, float); - st->interp_lsp = PUSH(st->stack, st->lpcSize, float); - st->interp_qlsp = PUSH(st->stack, st->lpcSize, float); - st->interp_lpc = PUSH(st->stack, st->lpcSize+1, float); - st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, float); - st->pi_gain = PUSH(st->stack, st->nbSubframes, float); + st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); + st->mem_sp2 = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); + st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); - st->mem_sp = PUSH(st->stack, st->lpcSize, float); - st->mem_sp2 = PUSH(st->stack, st->lpcSize, float); - st->mem_sw = PUSH(st->stack, st->lpcSize, float); + for (i=0;ilpcSize;i++) + st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1); +#ifndef DISABLE_VBR st->vbr_quality = 8; st->vbr_enabled = 0; + st->vbr_max = 0; + st->vbr_max_high = 20000; /* We just need a big value here */ st->vad_enabled = 0; st->abr_enabled = 0; st->relative_quality=0; +#endif /* #ifndef DISABLE_VBR */ st->complexity=2; - speex_decoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); + speex_encoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); st->sampling_rate*=2; - +#ifdef ENABLE_VALGRIND + VALGRIND_MAKE_MEM_DEFINED(st, (st->stack-(char*)st)); +#endif return st; } @@ -226,47 +230,350 @@ void sb_encoder_destroy(void *state) SBEncState *st=(SBEncState*)state; speex_encoder_destroy(st->st_low); +#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) + /*speex_free_scratch(st->stack);*/ +#endif + + speex_free(st->high); + + speex_free(st->h0_mem); + + speex_free(st->old_lsp); + speex_free(st->old_qlsp); + speex_free(st->interp_qlpc); + speex_free(st->pi_gain); + speex_free(st->exc_rms); + + speex_free(st->mem_sp); + speex_free(st->mem_sp2); + speex_free(st->mem_sw); + speex_free(st); } +int sb_encoder_ctl(void *state, int request, void *ptr) +{ + SBEncState *st; + st=(SBEncState*)state; + switch(request) + { + case SPEEX_GET_FRAME_SIZE: + (*(spx_int32_t*)ptr) = st->full_frame_size; + break; + case SPEEX_SET_HIGH_MODE: + st->submodeSelect = st->submodeID = (*(spx_int32_t*)ptr); + break; + case SPEEX_SET_LOW_MODE: + speex_encoder_ctl(st->st_low, SPEEX_SET_LOW_MODE, ptr); + break; + case SPEEX_SET_DTX: + speex_encoder_ctl(st->st_low, SPEEX_SET_DTX, ptr); + break; + case SPEEX_GET_DTX: + speex_encoder_ctl(st->st_low, SPEEX_GET_DTX, ptr); + break; + case SPEEX_GET_LOW_MODE: + speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, ptr); + break; + case SPEEX_SET_MODE: + speex_encoder_ctl(st, SPEEX_SET_QUALITY, ptr); + break; +#ifndef DISABLE_VBR + case SPEEX_SET_VBR: + st->vbr_enabled = (*(spx_int32_t*)ptr); + speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, ptr); + break; + case SPEEX_GET_VBR: + (*(spx_int32_t*)ptr) = st->vbr_enabled; + break; + case SPEEX_SET_VAD: + st->vad_enabled = (*(spx_int32_t*)ptr); + speex_encoder_ctl(st->st_low, SPEEX_SET_VAD, ptr); + break; + case SPEEX_GET_VAD: + (*(spx_int32_t*)ptr) = st->vad_enabled; + break; +#endif /* #ifndef DISABLE_VBR */ +#if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) + case SPEEX_SET_VBR_QUALITY: + { + spx_int32_t q; + float qual = (*(float*)ptr)+.6; + st->vbr_quality = (*(float*)ptr); + if (qual>10) + qual=10; + q=(int)floor(.5+*(float*)ptr); + if (q>10) + q=10; + speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_QUALITY, &qual); + speex_encoder_ctl(state, SPEEX_SET_QUALITY, &q); + break; + } + case SPEEX_GET_VBR_QUALITY: + (*(float*)ptr) = st->vbr_quality; + break; +#endif /* #if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */ +#ifndef DISABLE_VBR + case SPEEX_SET_ABR: + st->abr_enabled = (*(spx_int32_t*)ptr); + st->vbr_enabled = st->abr_enabled!=0; + speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, &st->vbr_enabled); + if (st->vbr_enabled) + { + spx_int32_t i=10, rate, target; + float vbr_qual; + target = (*(spx_int32_t*)ptr); + while (i>=0) + { + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); + speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); + if (rate <= target) + break; + i--; + } + vbr_qual=i; + if (vbr_qual<0) + vbr_qual=0; + speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); + st->abr_count=0; + st->abr_drift=0; + st->abr_drift2=0; + } -int sb_encode(void *state, float *in, SpeexBits *bits) + break; + case SPEEX_GET_ABR: + (*(spx_int32_t*)ptr) = st->abr_enabled; + break; +#endif /* #ifndef DISABLE_VBR */ + + case SPEEX_SET_QUALITY: + { + spx_int32_t nb_qual; + int quality = (*(spx_int32_t*)ptr); + if (quality < 0) + quality = 0; + if (quality > 10) + quality = 10; + st->submodeSelect = st->submodeID = ((const SpeexSBMode*)(st->mode->mode))->quality_map[quality]; + nb_qual = ((const SpeexSBMode*)(st->mode->mode))->low_quality_map[quality]; + speex_encoder_ctl(st->st_low, SPEEX_SET_MODE, &nb_qual); + } + break; + case SPEEX_SET_COMPLEXITY: + speex_encoder_ctl(st->st_low, SPEEX_SET_COMPLEXITY, ptr); + st->complexity = (*(spx_int32_t*)ptr); + if (st->complexity<1) + st->complexity=1; + break; + case SPEEX_GET_COMPLEXITY: + (*(spx_int32_t*)ptr) = st->complexity; + break; + case SPEEX_SET_BITRATE: + { + spx_int32_t i=10; + spx_int32_t rate, target; + target = (*(spx_int32_t*)ptr); + while (i>=0) + { + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); + speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); + if (rate <= target) + break; + i--; + } + } + break; + case SPEEX_GET_BITRATE: + speex_encoder_ctl(st->st_low, request, ptr); + /*fprintf (stderr, "before: %d\n", (*(int*)ptr));*/ + if (st->submodes[st->submodeID]) + (*(spx_int32_t*)ptr) += st->sampling_rate*SUBMODE(bits_per_frame)/st->full_frame_size; + else + (*(spx_int32_t*)ptr) += st->sampling_rate*(SB_SUBMODE_BITS+1)/st->full_frame_size; + /*fprintf (stderr, "after: %d\n", (*(int*)ptr));*/ + break; + case SPEEX_SET_SAMPLING_RATE: + { + spx_int32_t tmp=(*(spx_int32_t*)ptr); + st->sampling_rate = tmp; + tmp>>=1; + speex_encoder_ctl(st->st_low, SPEEX_SET_SAMPLING_RATE, &tmp); + } + break; + case SPEEX_GET_SAMPLING_RATE: + (*(spx_int32_t*)ptr)=st->sampling_rate; + break; + case SPEEX_RESET_STATE: + { + int i; + st->first = 1; + for (i=0;ilpcSize;i++) + st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1); + for (i=0;ilpcSize;i++) + st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0; + for (i=0;ih0_mem[i]=0; + } + break; + case SPEEX_SET_SUBMODE_ENCODING: + st->encode_submode = (*(spx_int32_t*)ptr); + speex_encoder_ctl(st->st_low, SPEEX_SET_SUBMODE_ENCODING, ptr); + break; + case SPEEX_GET_SUBMODE_ENCODING: + (*(spx_int32_t*)ptr) = st->encode_submode; + break; + case SPEEX_GET_LOOKAHEAD: + speex_encoder_ctl(st->st_low, SPEEX_GET_LOOKAHEAD, ptr); + (*(spx_int32_t*)ptr) = 2*(*(spx_int32_t*)ptr) + QMF_ORDER - 1; + break; + case SPEEX_SET_PLC_TUNING: + speex_encoder_ctl(st->st_low, SPEEX_SET_PLC_TUNING, ptr); + break; + case SPEEX_GET_PLC_TUNING: + speex_encoder_ctl(st->st_low, SPEEX_GET_PLC_TUNING, ptr); + break; +#ifndef DISABLE_VBR + case SPEEX_SET_VBR_MAX_BITRATE: + { + st->vbr_max = (*(spx_int32_t*)ptr); + if (SPEEX_SET_VBR_MAX_BITRATE<1) + { + speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_MAX_BITRATE, &st->vbr_max); + st->vbr_max_high = 17600; + } else { + spx_int32_t low_rate; + if (st->vbr_max >= 42200) + { + st->vbr_max_high = 17600; + } else if (st->vbr_max >= 27800) + { + st->vbr_max_high = 9600; + } else if (st->vbr_max > 20600) + { + st->vbr_max_high = 5600; + } else { + st->vbr_max_high = 1800; + } + if (st->subframeSize==80) + st->vbr_max_high = 1800; + low_rate = st->vbr_max - st->vbr_max_high; + speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_MAX_BITRATE, &low_rate); + } + } + break; + case SPEEX_GET_VBR_MAX_BITRATE: + (*(spx_int32_t*)ptr) = st->vbr_max; + break; +#endif /* #ifndef DISABLE_VBR */ + case SPEEX_SET_HIGHPASS: + speex_encoder_ctl(st->st_low, SPEEX_SET_HIGHPASS, ptr); + break; + case SPEEX_GET_HIGHPASS: + speex_encoder_ctl(st->st_low, SPEEX_GET_HIGHPASS, ptr); + break; + + + /* This is all internal stuff past this point */ + case SPEEX_GET_PI_GAIN: + { + int i; + spx_word32_t *g = (spx_word32_t*)ptr; + for (i=0;inbSubframes;i++) + g[i]=st->pi_gain[i]; + } + break; + case SPEEX_GET_EXC: + { + int i; + for (i=0;inbSubframes;i++) + ((spx_word16_t*)ptr)[i] = st->exc_rms[i]; + } + break; +#ifndef DISABLE_VBR + case SPEEX_GET_RELATIVE_QUALITY: + (*(float*)ptr)=st->relative_quality; + break; +#endif /* #ifndef DISABLE_VBR */ + case SPEEX_SET_INNOVATION_SAVE: + st->innov_rms_save = (spx_word16_t*)ptr; + break; + case SPEEX_SET_WIDEBAND: + speex_encoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, ptr); + break; + case SPEEX_GET_STACK: + *((char**)ptr) = st->stack; + break; + default: + speex_warning_int("Unknown nb_ctl request: ", request); + return -1; + } + return 0; +} + + +int sb_encode(void *state, void *vin, SpeexBits *bits) { SBEncState *st; int i, roots, sub; char *stack; - float *mem, *innov, *syn_resp; - float *low_pi_gain, *low_exc, *low_innov; - SpeexSBMode *mode; - int dtx; + VARDECL(spx_mem_t *mem); + VARDECL(spx_sig_t *innov); + VARDECL(spx_word16_t *target); + VARDECL(spx_word16_t *syn_resp); + VARDECL(spx_word32_t *low_pi_gain); + spx_word16_t *low; + spx_word16_t *high; + VARDECL(spx_word16_t *low_exc_rms); + VARDECL(spx_word16_t *low_innov_rms); + const SpeexSBMode *mode; + spx_int32_t dtx; + spx_word16_t *in = (spx_word16_t*)vin; + spx_word16_t e_low=0, e_high=0; + VARDECL(spx_coef_t *lpc); + VARDECL(spx_coef_t *interp_lpc); + VARDECL(spx_coef_t *bw_lpc1); + VARDECL(spx_coef_t *bw_lpc2); + VARDECL(spx_lsp_t *lsp); + VARDECL(spx_lsp_t *qlsp); + VARDECL(spx_lsp_t *interp_lsp); + VARDECL(spx_lsp_t *interp_qlsp); st = (SBEncState*)state; stack=st->stack; - mode = (SpeexSBMode*)(st->mode->mode); - - /* Compute the two sub-bands by filtering with h0 and h1*/ - qmf_decomp(in, h0, st->x0d, st->x1d, st->full_frame_size, QMF_ORDER, st->h0_mem, stack); - - /* Encode the narrowband part*/ - speex_encode(st->st_low, st->x0d, bits); + mode = (const SpeexSBMode*)(st->mode->mode); + low = in; + high = in+st->frame_size; /* High-band buffering / sync with low band */ - for (i=0;iwindowSize-st->frame_size;i++) - st->high[i] = st->high[st->frame_size+i]; - for (i=0;iframe_size;i++) - st->high[st->windowSize-st->frame_size+i]=st->x1d[i]; + /* Compute the two sub-bands by filtering with QMF h0*/ + qmf_decomp(in, h0, low, high, st->full_frame_size, QMF_ORDER, st->h0_mem, stack); - speex_move(st->excBuf, st->excBuf+st->frame_size, (st->bufSize-st->frame_size)*sizeof(float)); +#ifndef DISABLE_VBR + if (st->vbr_enabled || st->vad_enabled) + { + /* Need to compute things here before the signal is trashed by the encoder */ + /*FIXME: Are the two signals (low, high) in sync? */ + e_low = compute_rms16(low, st->frame_size); + e_high = compute_rms16(high, st->frame_size); + } +#endif /* #ifndef DISABLE_VBR */ + + ALLOC(low_innov_rms, st->nbSubframes, spx_word16_t); + speex_encoder_ctl(st->st_low, SPEEX_SET_INNOVATION_SAVE, low_innov_rms); + /* Encode the narrowband part*/ + speex_encode_native(st->st_low, low, bits); + + high = high - (st->windowSize-st->frame_size); + SPEEX_COPY(high, st->high, st->windowSize-st->frame_size); + SPEEX_COPY(st->high, &high[st->frame_size], st->windowSize-st->frame_size); - low_pi_gain = PUSH(stack, st->nbSubframes, float); - low_exc = PUSH(stack, st->frame_size, float); - low_innov = PUSH(stack, st->frame_size, float); + ALLOC(low_pi_gain, st->nbSubframes, spx_word32_t); + ALLOC(low_exc_rms, st->nbSubframes, spx_word16_t); speex_encoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain); - speex_encoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc); - speex_encoder_ctl(st->st_low, SPEEX_GET_INNOV, low_innov); - + speex_encoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc_rms); + speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, &dtx); if (dtx==0) @@ -274,45 +581,61 @@ int sb_encode(void *state, float *in, SpeexBits *bits) else dtx=0; - /* Start encoding the high-band */ - for (i=0;iwindowSize;i++) - st->buf[i] = st->high[i] * st->window[i]; + ALLOC(lpc, st->lpcSize, spx_coef_t); + ALLOC(interp_lpc, st->lpcSize, spx_coef_t); + ALLOC(bw_lpc1, st->lpcSize, spx_coef_t); + ALLOC(bw_lpc2, st->lpcSize, spx_coef_t); - /* Compute auto-correlation */ - _spx_autocorr(st->buf, st->autocorr, st->lpcSize+1, st->windowSize); + ALLOC(lsp, st->lpcSize, spx_lsp_t); + ALLOC(qlsp, st->lpcSize, spx_lsp_t); + ALLOC(interp_lsp, st->lpcSize, spx_lsp_t); + ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); - st->autocorr[0] += 1; /* prevents NANs */ - st->autocorr[0] *= st->lpc_floor; /* Noise floor in auto-correlation domain */ - /* Lag windowing: equivalent to filtering in the power-spectrum domain */ - for (i=0;ilpcSize+1;i++) - st->autocorr[i] *= st->lagWindow[i]; + { + VARDECL(spx_word16_t *autocorr); + VARDECL(spx_word16_t *w_sig); + ALLOC(autocorr, st->lpcSize+1, spx_word16_t); + ALLOC(w_sig, st->windowSize, spx_word16_t); + /* Window for analysis */ + /* FIXME: This is a kludge */ + if (st->subframeSize==80) + { + for (i=0;iwindowSize;i++) + w_sig[i] = EXTRACT16(SHR32(MULT16_16(high[i],st->window[i>>1]),SIG_SHIFT)); + } else { + for (i=0;iwindowSize;i++) + w_sig[i] = EXTRACT16(SHR32(MULT16_16(high[i],st->window[i]),SIG_SHIFT)); + } + /* Compute auto-correlation */ + _spx_autocorr(w_sig, autocorr, st->lpcSize+1, st->windowSize); + autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */ - /* Levinson-Durbin */ - wld(st->lpc+1, st->autocorr, st->rc, st->lpcSize); - st->lpc[0]=1; + /* Lag windowing: equivalent to filtering in the power-spectrum domain */ + for (i=0;ilpcSize+1;i++) + autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]); + + /* Levinson-Durbin */ + _spx_lpc(lpc, autocorr, st->lpcSize); + } /* LPC to LSPs (x-domain) transform */ - roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, 0.2, stack); + roots=lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA1, stack); if (roots!=st->lpcSize) { - roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, 0.02, stack); + roots = lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA2, stack); if (roots!=st->lpcSize) { /*If we can't find all LSP's, do some damage control and use a flat filter*/ for (i=0;ilpcSize;i++) { - st->lsp[i]=cos(M_PI*((float)(i+1))/(st->lpcSize+1)); + lsp[i]=st->old_lsp[i]; } } } - /* x-domain to angle domain*/ - for (i=0;ilpcSize;i++) - st->lsp[i] = acos(st->lsp[i]); - +#ifndef DISABLE_VBR /* VBR code */ if ((st->vbr_enabled || st->vad_enabled) && !dtx) { - float e_low=0, e_high=0; float ratio; if (st->abr_enabled) { @@ -334,21 +657,17 @@ int sb_encode(void *state, float *in, SpeexBits *bits) } - for (i=0;iframe_size;i++) - { - e_low += st->x0d[i]* st->x0d[i]; - e_high += st->high[i]* st->high[i]; - } - ratio = log((1+e_high)/(1+e_low)); + ratio = 2*log((1.f+e_high)/(1.f+e_low)); + speex_encoder_ctl(st->st_low, SPEEX_GET_RELATIVE_QUALITY, &st->relative_quality); if (ratio<-4) ratio=-4; if (ratio>2) ratio=2; /*if (ratio>-2)*/ - if (st->vbr_enabled) + if (st->vbr_enabled) { - int modeid; + spx_int32_t modeid; modeid = mode->nb_modes-1; st->relative_quality+=1.0*(ratio+2); if (st->relative_quality<-1) @@ -361,16 +680,16 @@ int sb_encode(void *state, float *in, SpeexBits *bits) if (v1==10) thresh = mode->vbr_thresh[modeid][v1]; else - thresh = (st->vbr_quality-v1) * mode->vbr_thresh[modeid][v1+1] + + thresh = (st->vbr_quality-v1) * mode->vbr_thresh[modeid][v1+1] + (1+v1-st->vbr_quality) * mode->vbr_thresh[modeid][v1]; - if (st->relative_quality >= thresh) + if (st->relative_quality >= thresh && st->sampling_rate*st->submodes[modeid]->bits_per_frame/st->full_frame_size <= st->vbr_max_high) break; modeid--; } speex_encoder_ctl(state, SPEEX_SET_HIGH_MODE, &modeid); if (st->abr_enabled) { - int bitrate; + spx_int32_t bitrate; speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate); st->abr_drift+=(bitrate-st->abr_enabled); st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled); @@ -390,35 +709,29 @@ int sb_encode(void *state, float *in, SpeexBits *bits) } /*fprintf (stderr, "%f %f\n", ratio, low_qual);*/ } +#endif /* #ifndef DISABLE_VBR */ - speex_bits_pack(bits, 1, 1); - if (dtx) - speex_bits_pack(bits, 0, SB_SUBMODE_BITS); - else - speex_bits_pack(bits, st->submodeID, SB_SUBMODE_BITS); + if (st->encode_submode) + { + speex_bits_pack(bits, 1, 1); + if (dtx) + speex_bits_pack(bits, 0, SB_SUBMODE_BITS); + else + speex_bits_pack(bits, st->submodeID, SB_SUBMODE_BITS); + } /* If null mode (no transmission), just set a couple things to zero*/ if (dtx || st->submodes[st->submodeID] == NULL) { for (i=0;iframe_size;i++) - st->exc[i]=st->sw[i]=0; + high[i]=VERY_SMALL; for (i=0;ilpcSize;i++) st->mem_sw[i]=0; st->first=1; /* Final signal synthesis from excitation */ - iir_mem2(st->exc, st->interp_qlpc, st->high, st->subframeSize, st->lpcSize, st->mem_sp); - -#ifndef RELEASE - - /* Reconstruct the original */ - fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack); - fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack); - - for (i=0;ifull_frame_size;i++) - in[i]=2*(st->y0[i]-st->y1[i]); -#endif + iir_mem16(high, st->interp_qlpc, high, st->frame_size, st->lpcSize, st->mem_sp, stack); if (dtx) return 0; @@ -428,279 +741,281 @@ int sb_encode(void *state, float *in, SpeexBits *bits) /* LSP quantization */ - SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits); + SUBMODE(lsp_quant)(lsp, qlsp, st->lpcSize, bits); if (st->first) { for (i=0;ilpcSize;i++) - st->old_lsp[i] = st->lsp[i]; + st->old_lsp[i] = lsp[i]; for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; } - - mem=PUSH(stack, st->lpcSize, float); - syn_resp=PUSH(stack, st->subframeSize, float); - innov = PUSH(stack, st->subframeSize, float); + + ALLOC(mem, st->lpcSize, spx_mem_t); + ALLOC(syn_resp, st->subframeSize, spx_word16_t); + ALLOC(innov, st->subframeSize, spx_sig_t); + ALLOC(target, st->subframeSize, spx_word16_t); for (sub=0;subnbSubframes;sub++) { - float *exc, *sp, *res, *target, *sw, tmp, filter_ratio; + VARDECL(spx_word16_t *exc); + VARDECL(spx_word16_t *res); + VARDECL(spx_word16_t *sw); + spx_word16_t *sp; + spx_word16_t filter_ratio; /*Q7*/ int offset; - float rl, rh, eh=0, el=0; - int fold; + spx_word32_t rl, rh; /*Q13*/ + spx_word16_t eh=0; offset = st->subframeSize*sub; - sp=st->high+offset; - exc=st->exc+offset; - res=st->res+offset; - target=st->target+offset; - sw=st->sw+offset; - + sp=high+offset; + ALLOC(exc, st->subframeSize, spx_word16_t); + ALLOC(res, st->subframeSize, spx_word16_t); + ALLOC(sw, st->subframeSize, spx_word16_t); + /* LSP interpolation (quantized and unquantized) */ - tmp = (1.0 + sub)/st->nbSubframes; - for (i=0;ilpcSize;i++) - st->interp_lsp[i] = (1-tmp)*st->old_lsp[i] + tmp*st->lsp[i]; - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i]; - - lsp_enforce_margin(st->interp_lsp, st->lpcSize, .05); - lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .05); + lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, sub, st->nbSubframes, LSP_MARGIN); + lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes, LSP_MARGIN); - /* Compute interpolated LPCs (quantized and unquantized) */ - for (i=0;ilpcSize;i++) - st->interp_lsp[i] = cos(st->interp_lsp[i]); - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = cos(st->interp_qlsp[i]); + lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); + lsp_to_lpc(interp_qlsp, st->interp_qlpc, st->lpcSize, stack); - lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack); - lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack); - - bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize); - bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize); + bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); + bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); /* Compute mid-band (4000 Hz for wideband) response of low-band and high-band filters */ - rl=rh=0; - tmp=1; - st->pi_gain[sub]=0; - for (i=0;i<=st->lpcSize;i++) + st->pi_gain[sub]=LPC_SCALING; + rh = LPC_SCALING; + for (i=0;ilpcSize;i+=2) { - rh += tmp*st->interp_qlpc[i]; - tmp = -tmp; - st->pi_gain[sub]+=st->interp_qlpc[i]; + rh += st->interp_qlpc[i+1] - st->interp_qlpc[i]; + st->pi_gain[sub] += st->interp_qlpc[i] + st->interp_qlpc[i+1]; } - rl = low_pi_gain[sub]; - rl=1/(fabs(rl)+.01); - rh=1/(fabs(rh)+.01); - /* Compute ratio, will help predict the gain */ - filter_ratio=fabs(.01+rh)/(.01+fabs(rl)); - fold = filter_ratio<5; - /*printf ("filter_ratio %f\n", filter_ratio);*/ - fold=0; + rl = low_pi_gain[sub]; +#ifdef FIXED_POINT + filter_ratio=EXTRACT16(SATURATE(PDIV32(SHL32(ADD32(rl,82),7),ADD32(82,rh)),32767)); +#else + filter_ratio=(rl+.01)/(rh+.01); +#endif /* Compute "real excitation" */ - fir_mem2(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2); + fir_mem16(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2, stack); /* Compute energy of low-band and high-band excitation */ - for (i=0;isubframeSize;i++) - eh+=sqr(exc[i]); + + eh = compute_rms16(exc, st->subframeSize); if (!SUBMODE(innovation_quant)) {/* 1 for spectral folding excitation, 0 for stochastic */ - float g; - /*speex_bits_pack(bits, 1, 1);*/ - for (i=0;isubframeSize;i++) - el+=sqr(low_innov[offset+i]); + spx_word32_t g; /*Q7*/ + spx_word16_t el; /*Q0*/ + el = low_innov_rms[sub]; /* Gain to use if we want to use the low-band excitation for high-band */ - g=eh/(.01+el); - g=sqrt(g); + g=PDIV32(MULT16_16(filter_ratio,eh),EXTEND32(ADD16(1,el))); + +#if 0 + { + char *tmp_stack=stack; + float *tmp_sig; + float g2; + ALLOC(tmp_sig, st->subframeSize, spx_sig_t); + for (i=0;ilpcSize;i++) + mem[i]=st->mem_sp[i]; + iir_mem2(st->low_innov+offset, st->interp_qlpc, tmp_sig, st->subframeSize, st->lpcSize, mem); + g2 = compute_rms(sp, st->subframeSize)/(.01+compute_rms(tmp_sig, st->subframeSize)); + /*fprintf (stderr, "gains: %f %f\n", g, g2);*/ + g = g2; + stack = tmp_stack; + } +#endif - g *= filter_ratio; /*print_vec(&g, 1, "gain factor");*/ /* Gain quantization */ { - int quant = (int) floor(.5 + 10 + 8.0 * log((g+.0001))); + int quant = scal_quant(g, fold_quant_bound, 32); /*speex_warning_int("tata", quant);*/ if (quant<0) quant=0; if (quant>31) quant=31; speex_bits_pack(bits, quant, 5); - g= .1*exp(quant/9.4); } - /*printf ("folding gain: %f\n", g);*/ - g /= filter_ratio; - - } else { - float gc, scale, scale_1; - - for (i=0;isubframeSize;i++) - el+=sqr(low_exc[offset+i]); - /*speex_bits_pack(bits, 0, 1);*/ - - gc = sqrt(1+eh)*filter_ratio/sqrt((1+el)*st->subframeSize); + if (st->innov_rms_save) { - int qgc = (int)floor(.5+3.7*(log(gc)+2)); - if (qgc<0) - qgc=0; - if (qgc>15) - qgc=15; - speex_bits_pack(bits, qgc, 4); - gc = exp((1/3.7)*qgc-2); + st->innov_rms_save[sub] = eh; } + st->exc_rms[sub] = eh; + } else { + spx_word16_t gc; /*Q7*/ + spx_word32_t scale; /*Q14*/ + spx_word16_t el; /*Q0*/ + el = low_exc_rms[sub]; /*Q0*/ + + gc = PDIV32_16(MULT16_16(filter_ratio,1+eh),1+el); + + /* This is a kludge that cleans up a historical bug */ + if (st->subframeSize==80) + gc = MULT16_16_P15(QCONST16(0.70711f,15),gc); + /*printf ("%f %f %f %f\n", el, eh, filter_ratio, gc);*/ + { + int qgc = scal_quant(gc, gc_quant_bound, 16); + speex_bits_pack(bits, qgc, 4); + gc = MULT16_16_Q15(QCONST16(0.87360,15),gc_quant_bound[qgc]); + } + if (st->subframeSize==80) + gc = MULT16_16_P14(QCONST16(1.4142f,14), gc); + + scale = SHL32(MULT16_16(PDIV32_16(SHL32(EXTEND32(gc),SIG_SHIFT-6),MAX16(EPSILON,filter_ratio)),(1+el)),6); + + compute_impulse_response(st->interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack); - scale = gc*sqrt(1+el)/filter_ratio; - scale_1 = 1/scale; - for (i=0;isubframeSize;i++) - exc[i]=0; - exc[0]=1; - syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack); - /* Reset excitation */ for (i=0;isubframeSize;i++) - exc[i]=0; - + res[i]=VERY_SMALL; + /* Compute zero response (ringing) of A(z/g1) / ( A(z/g2) * Aq(z) ) */ for (i=0;ilpcSize;i++) mem[i]=st->mem_sp[i]; - iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem); + iir_mem16(res, st->interp_qlpc, res, st->subframeSize, st->lpcSize, mem, stack); for (i=0;ilpcSize;i++) mem[i]=st->mem_sw[i]; - filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem); + filter_mem16(res, bw_lpc1, bw_lpc2, res, st->subframeSize, st->lpcSize, mem, stack); /* Compute weighted signal */ for (i=0;ilpcSize;i++) mem[i]=st->mem_sw[i]; - filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem); + filter_mem16(sp, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, mem, stack); /* Compute target signal */ for (i=0;isubframeSize;i++) - target[i]=sw[i]-res[i]; + target[i]=SUB16(sw[i],res[i]); - for (i=0;isubframeSize;i++) - exc[i]=0; + signal_div(target, target, scale, st->subframeSize); - - for (i=0;isubframeSize;i++) - target[i]*=scale_1; - /* Reset excitation */ - for (i=0;isubframeSize;i++) - innov[i]=0; + SPEEX_MEMSET(innov, 0, st->subframeSize); /*print_vec(target, st->subframeSize, "\ntarget");*/ - SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov, syn_resp, bits, stack, (st->complexity+1)>>1); + SUBMODE(innovation_quant)(target, st->interp_qlpc, bw_lpc1, bw_lpc2, + SUBMODE(innovation_params), st->lpcSize, st->subframeSize, + innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook)); /*print_vec(target, st->subframeSize, "after");*/ - for (i=0;isubframeSize;i++) - exc[i] += innov[i]*scale; + signal_mul(innov, innov, scale, st->subframeSize); if (SUBMODE(double_codebook)) { char *tmp_stack=stack; - float *innov2 = PUSH(tmp_stack, st->subframeSize, float); + VARDECL(spx_sig_t *innov2); + ALLOC(innov2, st->subframeSize, spx_sig_t); + SPEEX_MEMSET(innov2, 0, st->subframeSize); for (i=0;isubframeSize;i++) - innov2[i]=0; + target[i]=MULT16_16_P13(QCONST16(2.5f,13), target[i]); + + SUBMODE(innovation_quant)(target, st->interp_qlpc, bw_lpc1, bw_lpc2, + SUBMODE(innovation_params), st->lpcSize, st->subframeSize, + innov2, syn_resp, bits, stack, st->complexity, 0); + signal_mul(innov2, innov2, MULT16_32_P15(QCONST16(0.4f,15),scale), st->subframeSize); + for (i=0;isubframeSize;i++) - target[i]*=2.5; - SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, - SUBMODE(innovation_params), st->lpcSize, st->subframeSize, - innov2, syn_resp, bits, tmp_stack, (st->complexity+1)>>1); - for (i=0;isubframeSize;i++) - innov2[i]*=scale*(1/2.5); - for (i=0;isubframeSize;i++) - exc[i] += innov2[i]; + innov[i] = ADD32(innov[i],innov2[i]); + stack = tmp_stack; } + for (i=0;isubframeSize;i++) + exc[i] = PSHR32(innov[i],SIG_SHIFT); + + if (st->innov_rms_save) + { + st->innov_rms_save[sub] = MULT16_16_Q15(QCONST16(.70711f, 15), compute_rms(innov, st->subframeSize)); + } + st->exc_rms[sub] = compute_rms16(exc, st->subframeSize); + } - /*Keep the previous memory*/ - for (i=0;ilpcSize;i++) - mem[i]=st->mem_sp[i]; - /* Final signal synthesis from excitation */ - iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp); - - /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ - filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw); + + /*Keep the previous memory*/ + for (i=0;ilpcSize;i++) + mem[i]=st->mem_sp[i]; + /* Final signal synthesis from excitation */ + iir_mem16(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp, stack); + + /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ + filter_mem16(sp, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw, stack); } - -#ifndef RELEASE - - /* Reconstruct the original */ - fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack); - fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack); - - for (i=0;ifull_frame_size;i++) - in[i]=2*(st->y0[i]-st->y1[i]); -#endif for (i=0;ilpcSize;i++) - st->old_lsp[i] = st->lsp[i]; + st->old_lsp[i] = lsp[i]; for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; st->first=0; return 1; } +#endif /* DISABLE_ENCODER */ - - -void *sb_decoder_init(SpeexMode *m) +#ifndef DISABLE_DECODER +void *sb_decoder_init(const SpeexMode *m) { + spx_int32_t tmp; SBDecState *st; - SpeexSBMode *mode; - st = (SBDecState*)speex_alloc(sizeof(SBDecState)+6000*sizeof(float)); + const SpeexSBMode *mode; + st = (SBDecState*)speex_alloc(sizeof(SBDecState)); + if (!st) + return NULL; st->mode = m; - mode=(SpeexSBMode*)m->mode; - - st->stack = ((char*)st) + sizeof(SBDecState); - - + mode=(const SpeexSBMode*)m->mode; + st->encode_submode = 1; st->st_low = speex_decoder_init(mode->nb_mode); +#if defined(VAR_ARRAYS) || defined (USE_ALLOCA) + st->stack = NULL; +#else + /*st->stack = (char*)speex_alloc_scratch(SB_DEC_STACK);*/ + speex_decoder_ctl(st->st_low, SPEEX_GET_STACK, &st->stack); +#endif + st->full_frame_size = 2*mode->frameSize; st->frame_size = mode->frameSize; st->subframeSize = mode->subframeSize; st->nbSubframes = mode->frameSize/mode->subframeSize; - st->lpcSize=8; + st->lpcSize=mode->lpcSize; speex_decoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); st->sampling_rate*=2; + tmp=1; + speex_decoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, &tmp); st->submodes=mode->submodes; st->submodeID=mode->defaultSubmode; st->first=1; + st->g0_mem = (spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); + st->g1_mem = (spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t)); - st->x0d=PUSH(st->stack, st->frame_size, float); - st->x1d=PUSH(st->stack, st->frame_size, float); - st->high=PUSH(st->stack, st->full_frame_size, float); - st->y0=PUSH(st->stack, st->full_frame_size, float); - st->y1=PUSH(st->stack, st->full_frame_size, float); + st->excBuf = (spx_word16_t*)speex_alloc((st->subframeSize)*sizeof(spx_word16_t)); - st->h0_mem=PUSH(st->stack, QMF_ORDER, float); - st->h1_mem=PUSH(st->stack, QMF_ORDER, float); - st->g0_mem=PUSH(st->stack, QMF_ORDER, float); - st->g1_mem=PUSH(st->stack, QMF_ORDER, float); + st->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); + st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); - st->exc=PUSH(st->stack, st->frame_size, float); + st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t)); + st->exc_rms = (spx_word16_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word16_t)); + st->mem_sp = (spx_mem_t*)speex_alloc((2*st->lpcSize)*sizeof(spx_mem_t)); + + st->innov_save = NULL; - st->qlsp = PUSH(st->stack, st->lpcSize, float); - st->old_qlsp = PUSH(st->stack, st->lpcSize, float); - st->interp_qlsp = PUSH(st->stack, st->lpcSize, float); - st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, float); - st->pi_gain = PUSH(st->stack, st->nbSubframes, float); - st->mem_sp = PUSH(st->stack, 2*st->lpcSize, float); - st->lpc_enh_enabled=0; + st->seed = 1000; +#ifdef ENABLE_VALGRIND + VALGRIND_MAKE_MEM_DEFINED(st, (st->stack-(char*)st)); +#endif return st; } @@ -709,14 +1024,155 @@ void sb_decoder_destroy(void *state) SBDecState *st; st = (SBDecState*)state; speex_decoder_destroy(st->st_low); +#if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) + /*speex_free_scratch(st->stack);*/ +#endif + + speex_free(st->g0_mem); + speex_free(st->g1_mem); + speex_free(st->excBuf); + speex_free(st->old_qlsp); + speex_free(st->interp_qlpc); + speex_free(st->pi_gain); + speex_free(st->exc_rms); + speex_free(st->mem_sp); speex_free(state); } -static void sb_decode_lost(SBDecState *st, float *out, int dtx, char *stack) + + +int sb_decoder_ctl(void *state, int request, void *ptr) +{ + SBDecState *st; + st=(SBDecState*)state; + switch(request) + { + case SPEEX_SET_HIGH_MODE: + st->submodeID = (*(spx_int32_t*)ptr); + break; + case SPEEX_SET_LOW_MODE: + speex_decoder_ctl(st->st_low, SPEEX_SET_LOW_MODE, ptr); + break; + case SPEEX_GET_LOW_MODE: + speex_decoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, ptr); + break; + case SPEEX_GET_FRAME_SIZE: + (*(spx_int32_t*)ptr) = st->full_frame_size; + break; + case SPEEX_SET_ENH: + speex_decoder_ctl(st->st_low, request, ptr); + st->lpc_enh_enabled = *((spx_int32_t*)ptr); + break; + case SPEEX_GET_ENH: + *((spx_int32_t*)ptr) = st->lpc_enh_enabled; + break; + case SPEEX_SET_MODE: + case SPEEX_SET_QUALITY: + { + spx_int32_t nb_qual; + int quality = (*(spx_int32_t*)ptr); + if (quality < 0) + quality = 0; + if (quality > 10) + quality = 10; + st->submodeID = ((const SpeexSBMode*)(st->mode->mode))->quality_map[quality]; + nb_qual = ((const SpeexSBMode*)(st->mode->mode))->low_quality_map[quality]; + speex_decoder_ctl(st->st_low, SPEEX_SET_MODE, &nb_qual); + } + break; + case SPEEX_GET_BITRATE: + speex_decoder_ctl(st->st_low, request, ptr); + if (st->submodes[st->submodeID]) + (*(spx_int32_t*)ptr) += st->sampling_rate*SUBMODE(bits_per_frame)/st->full_frame_size; + else + (*(spx_int32_t*)ptr) += st->sampling_rate*(SB_SUBMODE_BITS+1)/st->full_frame_size; + break; + case SPEEX_SET_SAMPLING_RATE: + { + spx_int32_t tmp=(*(spx_int32_t*)ptr); + st->sampling_rate = tmp; + tmp>>=1; + speex_decoder_ctl(st->st_low, SPEEX_SET_SAMPLING_RATE, &tmp); + } + break; + case SPEEX_GET_SAMPLING_RATE: + (*(spx_int32_t*)ptr)=st->sampling_rate; + break; + case SPEEX_SET_HANDLER: + speex_decoder_ctl(st->st_low, SPEEX_SET_HANDLER, ptr); + break; + case SPEEX_SET_USER_HANDLER: + speex_decoder_ctl(st->st_low, SPEEX_SET_USER_HANDLER, ptr); + break; + case SPEEX_RESET_STATE: + { + int i; + for (i=0;i<2*st->lpcSize;i++) + st->mem_sp[i]=0; + for (i=0;ig0_mem[i]=st->g1_mem[i]=0; + st->last_ener=0; + } + break; + case SPEEX_SET_SUBMODE_ENCODING: + st->encode_submode = (*(spx_int32_t*)ptr); + speex_decoder_ctl(st->st_low, SPEEX_SET_SUBMODE_ENCODING, ptr); + break; + case SPEEX_GET_SUBMODE_ENCODING: + (*(spx_int32_t*)ptr) = st->encode_submode; + break; + case SPEEX_GET_LOOKAHEAD: + speex_decoder_ctl(st->st_low, SPEEX_GET_LOOKAHEAD, ptr); + (*(spx_int32_t*)ptr) = 2*(*(spx_int32_t*)ptr); + break; + case SPEEX_SET_HIGHPASS: + speex_decoder_ctl(st->st_low, SPEEX_SET_HIGHPASS, ptr); + break; + case SPEEX_GET_HIGHPASS: + speex_decoder_ctl(st->st_low, SPEEX_GET_HIGHPASS, ptr); + break; + case SPEEX_GET_ACTIVITY: + speex_decoder_ctl(st->st_low, SPEEX_GET_ACTIVITY, ptr); + break; + case SPEEX_GET_PI_GAIN: + { + int i; + spx_word32_t *g = (spx_word32_t*)ptr; + for (i=0;inbSubframes;i++) + g[i]=st->pi_gain[i]; + } + break; + case SPEEX_GET_EXC: + { + int i; + for (i=0;inbSubframes;i++) + ((spx_word16_t*)ptr)[i] = st->exc_rms[i]; + } + break; + case SPEEX_GET_DTX_STATUS: + speex_decoder_ctl(st->st_low, SPEEX_GET_DTX_STATUS, ptr); + break; + case SPEEX_SET_INNOVATION_SAVE: + st->innov_save = (spx_word16_t*)ptr; + break; + case SPEEX_SET_WIDEBAND: + speex_decoder_ctl(st->st_low, SPEEX_SET_WIDEBAND, ptr); + break; + case SPEEX_GET_STACK: + *((char**)ptr) = st->stack; + break; + default: + speex_warning_int("Unknown nb_ctl request: ", request); + return -1; + } + return 0; +} + + +static void sb_decode_lost(SBDecState *st, spx_word16_t *out, int dtx, char *stack) { int i; - float *awk1, *awk2, *awk3; int saved_modeid=0; if (dtx) @@ -724,75 +1180,26 @@ static void sb_decode_lost(SBDecState *st, float *out, int dtx, char *stack) saved_modeid=st->submodeID; st->submodeID=1; } else { - bw_lpc(0.99, st->interp_qlpc, st->interp_qlpc, st->lpcSize); + bw_lpc(QCONST16(0.99f,15), st->interp_qlpc, st->interp_qlpc, st->lpcSize); } st->first=1; - - awk1=PUSH(stack, st->lpcSize+1, float); - awk2=PUSH(stack, st->lpcSize+1, float); - awk3=PUSH(stack, st->lpcSize+1, float); - - if (st->lpc_enh_enabled) - { - float r=.9; - - float k1,k2,k3; - if (st->submodes[st->submodeID] != NULL) - { - k1=SUBMODE(lpc_enh_k1); - k2=SUBMODE(lpc_enh_k2); - } else { - k1=k2=.7; - } - k3=(1-(1-r*k1)/(1-r*k2))/r; - k3=k1-k2; - if (!st->lpc_enh_enabled) - { - k1=k2; - k3=0; - } - bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize); - bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize); - bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize); - /*fprintf (stderr, "%f %f %f\n", k1, k2, k3);*/ - } - - + + /* Final signal synthesis from excitation */ if (!dtx) { - for (i=0;iframe_size;i++) - st->exc[i] *= .9; + st->last_ener = MULT16_16_Q15(QCONST16(.9f,15),st->last_ener); } - for (i=0;iframe_size;i++) - st->high[i]=st->exc[i]; + out[i+st->frame_size] = speex_rand(st->last_ener, &st->seed); + + iir_mem16(out+st->frame_size, st->interp_qlpc, out+st->frame_size, st->frame_size, st->lpcSize, + st->mem_sp, stack); + - if (st->lpc_enh_enabled) - { - /* Use enhanced LPC filter */ - filter_mem2(st->high, awk2, awk1, st->high, st->frame_size, st->lpcSize, - st->mem_sp+st->lpcSize); - filter_mem2(st->high, awk3, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, - st->mem_sp); - } else { - /* Use regular filter */ - for (i=0;ilpcSize;i++) - st->mem_sp[st->lpcSize+i] = 0; - iir_mem2(st->high, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, - st->mem_sp); - } - - /*iir_mem2(st->exc, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, st->mem_sp);*/ - /* Reconstruct the original */ - fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack); - fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack); - - for (i=0;ifull_frame_size;i++) - out[i]=2*(st->y0[i]-st->y1[i]); - + qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); if (dtx) { st->submodeID=saved_modeid; @@ -801,24 +1208,32 @@ static void sb_decode_lost(SBDecState *st, float *out, int dtx, char *stack) return; } -int sb_decode(void *state, SpeexBits *bits, float *out) +int sb_decode(void *state, SpeexBits *bits, void *vout) { int i, sub; SBDecState *st; int wideband; int ret; char *stack; - float *low_pi_gain, *low_exc, *low_innov; - float *awk1, *awk2, *awk3; - int dtx; - SpeexSBMode *mode; + VARDECL(spx_word32_t *low_pi_gain); + VARDECL(spx_word16_t *low_exc_rms); + VARDECL(spx_coef_t *ak); + VARDECL(spx_lsp_t *qlsp); + VARDECL(spx_lsp_t *interp_qlsp); + spx_int32_t dtx; + const SpeexSBMode *mode; + spx_word16_t *out = (spx_word16_t*)vout; + spx_word16_t *low_innov_alias; + spx_word32_t exc_ener_sum = 0; st = (SBDecState*)state; stack=st->stack; - mode = (SpeexSBMode*)(st->mode->mode); + mode = (const SpeexSBMode*)(st->mode->mode); + low_innov_alias = out+st->frame_size; + speex_decoder_ctl(st->st_low, SPEEX_SET_INNOVATION_SAVE, low_innov_alias); /* Decode the low-band */ - ret = speex_decode(st->st_low, bits, st->x0d); + ret = speex_decode_native(st->st_low, bits, out); speex_decoder_ctl(st->st_low, SPEEX_GET_DTX_STATUS, &dtx); @@ -834,30 +1249,37 @@ int sb_decode(void *state, SpeexBits *bits, float *out) return 0; } - /*Check "wideband bit"*/ - if (speex_bits_remaining(bits)>0) - wideband = speex_bits_peek(bits); - else - wideband = 0; - if (wideband) + if (st->encode_submode) { - /*Regular wideband frame, read the submode*/ - wideband = speex_bits_unpack_unsigned(bits, 1); - st->submodeID = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); - } else - { - /*Was a narrowband frame, set "null submode"*/ - st->submodeID = 0; - } - if (st->submodeID != 0 && st->submodes[st->submodeID] == NULL) - { - speex_warning("Invalid mode encountered: corrupted stream?"); - return -2; + + /*Check "wideband bit"*/ + if (speex_bits_remaining(bits)>0) + wideband = speex_bits_peek(bits); + else + wideband = 0; + if (wideband) + { + /*Regular wideband frame, read the submode*/ + wideband = speex_bits_unpack_unsigned(bits, 1); + st->submodeID = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS); + } else + { + /*Was a narrowband frame, set "null submode"*/ + st->submodeID = 0; + } + if (st->submodeID != 0 && st->submodes[st->submodeID] == NULL) + { + speex_notify("Invalid mode encountered. The stream is corrupted."); + return -2; + } } /* If null mode (no transmission), just set a couple things to zero*/ if (st->submodes[st->submodeID] == NULL) { + if (st->innov_save) + SPEEX_MEMSET(st->innov_save, 0, st->full_frame_size); + if (dtx) { sb_decode_lost(st, out, 1, stack); @@ -865,469 +1287,158 @@ int sb_decode(void *state, SpeexBits *bits, float *out) } for (i=0;iframe_size;i++) - st->exc[i]=0; + out[st->frame_size+i]=VERY_SMALL; st->first=1; /* Final signal synthesis from excitation */ - iir_mem2(st->exc, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, st->mem_sp); + iir_mem16(out+st->frame_size, st->interp_qlpc, out+st->frame_size, st->frame_size, st->lpcSize, st->mem_sp, stack); - fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack); - fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack); - - for (i=0;ifull_frame_size;i++) - out[i]=2*(st->y0[i]-st->y1[i]); + qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); return 0; } - for (i=0;iframe_size;i++) - st->exc[i]=0; - - low_pi_gain = PUSH(stack, st->nbSubframes, float); - low_exc = PUSH(stack, st->frame_size, float); - low_innov = PUSH(stack, st->frame_size, float); + ALLOC(low_pi_gain, st->nbSubframes, spx_word32_t); + ALLOC(low_exc_rms, st->nbSubframes, spx_word16_t); speex_decoder_ctl(st->st_low, SPEEX_GET_PI_GAIN, low_pi_gain); - speex_decoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc); - speex_decoder_ctl(st->st_low, SPEEX_GET_INNOV, low_innov); + speex_decoder_ctl(st->st_low, SPEEX_GET_EXC, low_exc_rms); + + ALLOC(qlsp, st->lpcSize, spx_lsp_t); + ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); + SUBMODE(lsp_unquant)(qlsp, st->lpcSize, bits); - SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits); - if (st->first) { for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; } - - awk1=PUSH(stack, st->lpcSize+1, float); - awk2=PUSH(stack, st->lpcSize+1, float); - awk3=PUSH(stack, st->lpcSize+1, float); + + ALLOC(ak, st->lpcSize, spx_coef_t); for (sub=0;subnbSubframes;sub++) { - float *exc, *sp, tmp, filter_ratio, el=0; + VARDECL(spx_word32_t *exc); + spx_word16_t *innov_save=NULL; + spx_word16_t *sp; + spx_word16_t filter_ratio; + spx_word16_t el=0; int offset; - float rl=0,rh=0; - + spx_word32_t rl=0,rh=0; + offset = st->subframeSize*sub; - sp=st->high+offset; - exc=st->exc+offset; - - /* LSP interpolation */ - tmp = (1.0 + sub)/st->nbSubframes; - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i]; - - lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .05); - - /* LSPs to x-domain */ - for (i=0;ilpcSize;i++) - st->interp_qlsp[i] = cos(st->interp_qlsp[i]); - - /* LSP to LPC */ - lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack); - - - if (st->lpc_enh_enabled) + sp=out+st->frame_size+offset; + ALLOC(exc, st->subframeSize, spx_word32_t); + /* Pointer for saving innovation */ + if (st->innov_save) { - float r=.9; - - float k1,k2,k3; - k1=SUBMODE(lpc_enh_k1); - k2=SUBMODE(lpc_enh_k2); - k3=(1-(1-r*k1)/(1-r*k2))/r; - k3=k1-k2; - if (!st->lpc_enh_enabled) - { - k1=k2; - k3=0; - } - bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize); - bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize); - bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize); - /*fprintf (stderr, "%f %f %f\n", k1, k2, k3);*/ + innov_save = st->innov_save+2*offset; + SPEEX_MEMSET(innov_save, 0, 2*st->subframeSize); } + /* LSP interpolation */ + lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes, LSP_MARGIN); - /* Calculate reponse ratio between the low and high filter in the middle + /* LSP to LPC */ + lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack); + + /* Calculate response ratio between the low and high filter in the middle of the band (4000 Hz) */ - - tmp=1; - st->pi_gain[sub]=0; - for (i=0;i<=st->lpcSize;i++) + + st->pi_gain[sub]=LPC_SCALING; + rh = LPC_SCALING; + for (i=0;ilpcSize;i+=2) { - rh += tmp*st->interp_qlpc[i]; - tmp = -tmp; - st->pi_gain[sub]+=st->interp_qlpc[i]; + rh += ak[i+1] - ak[i]; + st->pi_gain[sub] += ak[i] + ak[i+1]; } + rl = low_pi_gain[sub]; - rl=1/(fabs(rl)+.01); - rh=1/(fabs(rh)+.01); - filter_ratio=fabs(.01+rh)/(.01+fabs(rl)); - - - for (i=0;isubframeSize;i++) - exc[i]=0; +#ifdef FIXED_POINT + filter_ratio=EXTRACT16(SATURATE(PDIV32(SHL32(ADD32(rl,82),7),ADD32(82,rh)),32767)); +#else + filter_ratio=(rl+.01)/(rh+.01); +#endif + + SPEEX_MEMSET(exc, 0, st->subframeSize); if (!SUBMODE(innovation_unquant)) { - float g; + spx_word32_t g; int quant; - for (i=0;isubframeSize;i++) - el+=sqr(low_innov[offset+i]); quant = speex_bits_unpack_unsigned(bits, 5); - g= exp(((float)quant-10)/8.0); - - /*printf ("unquant folding gain: %f\n", g);*/ - g /= filter_ratio; - - /* High-band excitation using the low-band excitation and a gain */ - for (i=0;isubframeSize;i++) - exc[i]=mode->folding_gain*g*low_innov[offset+i]; - /*speex_rand_vec(mode->folding_gain*g*sqrt(el/st->subframeSize), exc, st->subframeSize);*/ + g= spx_exp(MULT16_16(QCONST16(.125f,11),(quant-10))); + + /* Clamp to a minimum of epsilon to avoid division by 0 */ + g = PDIV32(g, MAX16(EPSILON,filter_ratio)); + + for (i=0;isubframeSize;i+=2) + { + exc[i]=SHL32(MULT16_32_P15(MULT16_16_Q15(mode->folding_gain,low_innov_alias[offset+i]),SHL32(g,6)),SIG_SHIFT); + exc[i+1]=NEG32(SHL32(MULT16_32_P15(MULT16_16_Q15(mode->folding_gain,low_innov_alias[offset+i+1]),SHL32(g,6)),SIG_SHIFT)); + } + } else { - float gc, scale; + spx_word16_t gc; + spx_word32_t scale; int qgc = speex_bits_unpack_unsigned(bits, 4); - for (i=0;isubframeSize;i++) - el+=sqr(low_exc[offset+i]); + el = low_exc_rms[sub]; + gc = MULT16_16_Q15(QCONST16(0.87360,15),gc_quant_bound[qgc]); - gc = exp((1/3.7)*qgc-2); + if (st->subframeSize==80) + gc = MULT16_16_P14(QCONST16(1.4142f,14),gc); - scale = gc*sqrt(1+el)/filter_ratio; + scale = SHL32(PDIV32(SHL32(MULT16_16(gc, el),3), MAX16(EPSILON,filter_ratio)),SIG_SHIFT-3); + SUBMODE(innovation_unquant)(exc, SUBMODE(innovation_params), st->subframeSize, + bits, stack, &st->seed); - - SUBMODE(innovation_unquant)(exc, SUBMODE(innovation_params), st->subframeSize, - bits, stack); - for (i=0;isubframeSize;i++) - exc[i]*=scale; + signal_mul(exc,exc,scale,st->subframeSize); if (SUBMODE(double_codebook)) { char *tmp_stack=stack; - float *innov2 = PUSH(tmp_stack, st->subframeSize, float); + VARDECL(spx_sig_t *innov2); + ALLOC(innov2, st->subframeSize, spx_sig_t); + SPEEX_MEMSET(innov2, 0, st->subframeSize); + SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, + bits, stack, &st->seed); + signal_mul(innov2, innov2, MULT16_32_P15(QCONST16(0.4f,15),scale), st->subframeSize); for (i=0;isubframeSize;i++) - innov2[i]=0; - SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, - bits, tmp_stack); - for (i=0;isubframeSize;i++) - innov2[i]*=scale*(1/2.5); - for (i=0;isubframeSize;i++) - exc[i] += innov2[i]; + exc[i] = ADD32(exc[i],innov2[i]); + stack = tmp_stack; } } - for (i=0;isubframeSize;i++) - sp[i]=exc[i]; - if (st->lpc_enh_enabled) + if (st->innov_save) { - /* Use enhanced LPC filter */ - filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize, - st->mem_sp+st->lpcSize); - filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp); - } else { - /* Use regular filter */ - for (i=0;ilpcSize;i++) - st->mem_sp[st->lpcSize+i] = 0; - iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, - st->mem_sp); + for (i=0;isubframeSize;i++) + innov_save[2*i]=EXTRACT16(PSHR32(exc[i],SIG_SHIFT)); } - /*iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);*/ + iir_mem16(st->excBuf, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, + st->mem_sp, stack); + for (i=0;isubframeSize;i++) + st->excBuf[i]=EXTRACT16(PSHR32(exc[i],SIG_SHIFT)); + for (i=0;ilpcSize;i++) + st->interp_qlpc[i] = ak[i]; + st->exc_rms[sub] = compute_rms16(st->excBuf, st->subframeSize); + exc_ener_sum = ADD32(exc_ener_sum, DIV32(MULT16_16(st->exc_rms[sub],st->exc_rms[sub]), st->nbSubframes)); } + st->last_ener = spx_sqrt(exc_ener_sum); - fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack); - fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack); - - for (i=0;ifull_frame_size;i++) - out[i]=2*(st->y0[i]-st->y1[i]); - + qmf_synth(out, out+st->frame_size, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack); for (i=0;ilpcSize;i++) - st->old_qlsp[i] = st->qlsp[i]; + st->old_qlsp[i] = qlsp[i]; st->first=0; return 0; } +#endif /* DISABLE_DECODER */ -int sb_encoder_ctl(void *state, int request, void *ptr) -{ - SBEncState *st; - st=(SBEncState*)state; - switch(request) - { - case SPEEX_GET_FRAME_SIZE: - (*(int*)ptr) = st->full_frame_size; - break; - case SPEEX_SET_HIGH_MODE: - st->submodeSelect = st->submodeID = (*(int*)ptr); - break; - case SPEEX_SET_LOW_MODE: - speex_encoder_ctl(st->st_low, SPEEX_SET_LOW_MODE, ptr); - break; - case SPEEX_SET_DTX: - speex_encoder_ctl(st->st_low, SPEEX_SET_DTX, ptr); - break; - case SPEEX_GET_DTX: - speex_encoder_ctl(st->st_low, SPEEX_GET_DTX, ptr); - break; - case SPEEX_GET_LOW_MODE: - speex_encoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, ptr); - break; - case SPEEX_SET_MODE: - speex_encoder_ctl(st, SPEEX_SET_QUALITY, ptr); - break; - case SPEEX_SET_VBR: - st->vbr_enabled = (*(int*)ptr); - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, ptr); - break; - case SPEEX_GET_VBR: - (*(int*)ptr) = st->vbr_enabled; - break; - case SPEEX_SET_VAD: - st->vad_enabled = (*(int*)ptr); - speex_encoder_ctl(st->st_low, SPEEX_SET_VAD, ptr); - break; - case SPEEX_GET_VAD: - (*(int*)ptr) = st->vad_enabled; - break; - case SPEEX_SET_VBR_QUALITY: - { - int q; - float qual = (*(float*)ptr)+.6; - st->vbr_quality = (*(float*)ptr); - if (qual>10) - qual=10; - q=(int)floor(.5+*(float*)ptr); - if (q>10) - q=10; - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR_QUALITY, &qual); - speex_encoder_ctl(state, SPEEX_SET_QUALITY, &q); - break; - } - case SPEEX_SET_ABR: - st->abr_enabled = (*(int*)ptr); - st->vbr_enabled = 1; - speex_encoder_ctl(st->st_low, SPEEX_SET_VBR, &st->vbr_enabled); - { - int i=10, rate, target; - float vbr_qual; - target = (*(int*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - vbr_qual=i; - if (vbr_qual<0) - vbr_qual=0; - speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); - st->abr_count=0; - st->abr_drift=0; - st->abr_drift2=0; - } - - break; - case SPEEX_GET_ABR: - (*(int*)ptr) = st->abr_enabled; - break; - case SPEEX_SET_QUALITY: - { - int nb_qual; - int quality = (*(int*)ptr); - if (quality < 0) - quality = 0; - if (quality > 10) - quality = 10; - st->submodeSelect = st->submodeID = ((SpeexSBMode*)(st->mode->mode))->quality_map[quality]; - nb_qual = ((SpeexSBMode*)(st->mode->mode))->low_quality_map[quality]; - speex_encoder_ctl(st->st_low, SPEEX_SET_MODE, &nb_qual); - } - break; - case SPEEX_SET_COMPLEXITY: - speex_encoder_ctl(st->st_low, SPEEX_SET_COMPLEXITY, ptr); - st->complexity = (*(int*)ptr); - if (st->complexity<1) - st->complexity=1; - break; - case SPEEX_GET_COMPLEXITY: - (*(int*)ptr) = st->complexity; - break; - case SPEEX_SET_BITRATE: - { - int i=10, rate, target; - target = (*(int*)ptr); - while (i>=0) - { - speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); - speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); - if (rate <= target) - break; - i--; - } - } - break; - case SPEEX_GET_BITRATE: - speex_encoder_ctl(st->st_low, request, ptr); - /*fprintf (stderr, "before: %d\n", (*(int*)ptr));*/ - if (st->submodes[st->submodeID]) - (*(int*)ptr) += st->sampling_rate*SUBMODE(bits_per_frame)/st->full_frame_size; - else - (*(int*)ptr) += st->sampling_rate*(SB_SUBMODE_BITS+1)/st->full_frame_size; - /*fprintf (stderr, "after: %d\n", (*(int*)ptr));*/ - break; - case SPEEX_SET_SAMPLING_RATE: - { - int tmp=(*(int*)ptr); - st->sampling_rate = tmp; - tmp>>=1; - speex_encoder_ctl(st->st_low, SPEEX_SET_SAMPLING_RATE, &tmp); - } - break; - case SPEEX_GET_SAMPLING_RATE: - (*(int*)ptr)=st->sampling_rate; - break; - case SPEEX_RESET_STATE: - { - int i; - st->first = 1; - for (i=0;ilpcSize;i++) - st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1); - for (i=0;ilpcSize;i++) - st->mem_sw[i]=st->mem_sp[i]=st->mem_sp2[i]=0; - for (i=0;ibufSize;i++) - st->excBuf[i]=0; - for (i=0;ih0_mem[i]=st->h1_mem[i]=st->g0_mem[i]=st->g1_mem[i]=0; - } - break; - case SPEEX_GET_PI_GAIN: - { - int i; - float *g = (float*)ptr; - for (i=0;inbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - float *e = (float*)ptr; - for (i=0;ifull_frame_size;i++) - e[i]=0; - for (i=0;iframe_size;i++) - e[2*i]=2*st->exc[i]; - } - break; - case SPEEX_GET_INNOV: - { - int i; - float *e = (float*)ptr; - for (i=0;ifull_frame_size;i++) - e[i]=0; - for (i=0;iframe_size;i++) - e[2*i]=2*st->exc[i]; - } - break; - case SPEEX_GET_RELATIVE_QUALITY: - (*(float*)ptr)=st->relative_quality; - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; -} -int sb_decoder_ctl(void *state, int request, void *ptr) -{ - SBDecState *st; - st=(SBDecState*)state; - switch(request) - { - case SPEEX_GET_LOW_MODE: - speex_decoder_ctl(st->st_low, SPEEX_GET_LOW_MODE, ptr); - break; - case SPEEX_GET_FRAME_SIZE: - (*(int*)ptr) = st->full_frame_size; - break; - case SPEEX_SET_ENH: - speex_decoder_ctl(st->st_low, request, ptr); - st->lpc_enh_enabled = *((int*)ptr); - break; - case SPEEX_GET_BITRATE: - speex_decoder_ctl(st->st_low, request, ptr); - if (st->submodes[st->submodeID]) - (*(int*)ptr) += st->sampling_rate*SUBMODE(bits_per_frame)/st->full_frame_size; - else - (*(int*)ptr) += st->sampling_rate*(SB_SUBMODE_BITS+1)/st->full_frame_size; - break; - case SPEEX_SET_SAMPLING_RATE: - { - int tmp=(*(int*)ptr); - st->sampling_rate = tmp; - tmp>>=1; - speex_decoder_ctl(st->st_low, SPEEX_SET_SAMPLING_RATE, &tmp); - } - break; - case SPEEX_GET_SAMPLING_RATE: - (*(int*)ptr)=st->sampling_rate; - break; - case SPEEX_SET_HANDLER: - speex_decoder_ctl(st->st_low, SPEEX_SET_HANDLER, ptr); - break; - case SPEEX_SET_USER_HANDLER: - speex_decoder_ctl(st->st_low, SPEEX_SET_USER_HANDLER, ptr); - break; - case SPEEX_RESET_STATE: - { - int i; - for (i=0;i<2*st->lpcSize;i++) - st->mem_sp[i]=0; - for (i=0;ih0_mem[i]=st->h1_mem[i]=st->g0_mem[i]=st->g1_mem[i]=0; - } - break; - case SPEEX_GET_PI_GAIN: - { - int i; - float *g = (float*)ptr; - for (i=0;inbSubframes;i++) - g[i]=st->pi_gain[i]; - } - break; - case SPEEX_GET_EXC: - { - int i; - float *e = (float*)ptr; - for (i=0;ifull_frame_size;i++) - e[i]=0; - for (i=0;iframe_size;i++) - e[2*i]=2*st->exc[i]; - } - break; - case SPEEX_GET_INNOV: - { - int i; - float *e = (float*)ptr; - for (i=0;ifull_frame_size;i++) - e[i]=0; - for (i=0;iframe_size;i++) - e[2*i]=2*st->exc[i]; - } - break; - case SPEEX_GET_DTX_STATUS: - speex_decoder_ctl(st->st_low, SPEEX_GET_DTX_STATUS, ptr); - break; - default: - speex_warning_int("Unknown nb_ctl request: ", request); - return -1; - } - return 0; -} +#endif + diff --git a/external/speex/src/sb_celp.h b/external/speex/src/sb_celp.h index 64b23ee..c6b9294 100644 --- a/external/speex/src/sb_celp.h +++ b/external/speex/src/sb_celp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Jean-Marc Valin */ +/* Copyright (C) 2002-2006 Jean-Marc Valin */ /** @file sb_celp.h @brief Sub-band CELP mode used for wideband encoding @@ -7,18 +7,18 @@ 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 @@ -37,80 +37,66 @@ #define SB_CELP_H #include "modes.h" -#include "speex_bits.h" #include "nb_celp.h" /**Structure representing the full state of the sub-band encoder*/ typedef struct SBEncState { - SpeexMode *mode; /**< Pointer to the mode (containing for vtable info) */ - void *st_low; /**< State of the low-band (narrowband) encoder */ - int full_frame_size; /**< Length of full-band frames*/ - int frame_size; /**< Length of high-band frames*/ - int subframeSize; /**< Length of high-band sub-frames*/ - int nbSubframes; /**< Number of high-band sub-frames*/ - int windowSize; /**< Length of high-band LPC window*/ - int lpcSize; /**< Order of high-band LPC analysis */ - int bufSize; /**< Buffer size */ - int first; /**< First frame? */ - float lag_factor; /**< Lag-windowing control parameter */ - float lpc_floor; /**< Controls LPC analysis noise floor */ - float gamma1; /**< Perceptual weighting coef 1 */ - float gamma2; /**< Perceptual weighting coef 2 */ + const SpeexMode *mode; /**< Pointer to the mode (containing for vtable info) */ + void *st_low; /**< State of the low-band (narrowband) encoder */ + int full_frame_size; /**< Length of full-band frames*/ + int frame_size; /**< Length of high-band frames*/ + int subframeSize; /**< Length of high-band sub-frames*/ + int nbSubframes; /**< Number of high-band sub-frames*/ + int windowSize; /**< Length of high-band LPC window*/ + int lpcSize; /**< Order of high-band LPC analysis */ + int first; /**< First frame? */ + spx_word16_t lpc_floor; /**< Controls LPC analysis noise floor */ + spx_word16_t gamma1; /**< Perceptual weighting coef 1 */ + spx_word16_t gamma2; /**< Perceptual weighting coef 2 */ - char *stack; /**< Temporary allocation stack */ - float *x0d, *x1d; /**< QMF filter signals*/ - float *high; /**< High-band signal (buffer) */ - float *y0, *y1; /**< QMF synthesis signals */ - float *h0_mem, *h1_mem, *g0_mem, *g1_mem; /**< QMF memories */ + char *stack; /**< Temporary allocation stack */ + spx_word16_t *high; /**< High-band signal (buffer) */ + spx_word16_t *h0_mem; - float *excBuf; /**< High-band excitation */ - float *exc; /**< High-band excitation (for QMF only)*/ - float *buf; /**< Temporary buffer */ - float *res; /**< Zero-input response (ringing) */ - float *sw; /**< Perceptually weighted signal */ - float *target; /**< Weighted target signal (analysis by synthesis) */ - float *window; /**< LPC analysis window */ - float *lagWindow; /**< Auto-correlation window */ - float *autocorr; /**< Auto-correlation (for LPC analysis) */ - float *rc; /**< Reflection coefficients (unused) */ - float *lpc; /**< LPC coefficients */ - float *lsp; /**< LSP coefficients */ - float *qlsp; /**< Quantized LSPs */ - float *old_lsp; /**< LSPs of previous frame */ - float *old_qlsp; /**< Quantized LSPs of previous frame */ - float *interp_lsp; /**< Interpolated LSPs for current sub-frame */ - float *interp_qlsp; /**< Interpolated quantized LSPs for current sub-frame */ - float *interp_lpc; /**< Interpolated LPCs for current sub-frame */ - float *interp_qlpc; /**< Interpolated quantized LPCs for current sub-frame */ - float *bw_lpc1; /**< Bandwidth-expanded version of LPCs (#1) */ - float *bw_lpc2; /**< Bandwidth-expanded version of LPCs (#2) */ + const spx_word16_t *window; /**< LPC analysis window */ + const spx_word16_t *lagWindow; /**< Auto-correlation window */ + spx_lsp_t *old_lsp; /**< LSPs of previous frame */ + spx_lsp_t *old_qlsp; /**< Quantized LSPs of previous frame */ + spx_coef_t *interp_qlpc; /**< Interpolated quantized LPCs for current sub-frame */ - float *mem_sp; /**< Synthesis signal memory */ - float *mem_sp2; - float *mem_sw; /**< Perceptual signal memory */ - float *pi_gain; + spx_mem_t *mem_sp; /**< Synthesis signal memory */ + spx_mem_t *mem_sp2; + spx_mem_t *mem_sw; /**< Perceptual signal memory */ + spx_word32_t *pi_gain; + spx_word16_t *exc_rms; + spx_word16_t *innov_rms_save; /**< If non-NULL, innovation is copied here */ - float vbr_quality; /**< Quality setting for VBR encoding */ - int vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */ - int abr_enabled; /**< ABR setting (in bps), 0 if off */ +#ifndef DISABLE_VBR + float vbr_quality; /**< Quality setting for VBR encoding */ + int vbr_enabled; /**< 1 for enabling VBR, 0 otherwise */ + spx_int32_t vbr_max; /**< Max bit-rate allowed in VBR mode (total) */ + spx_int32_t vbr_max_high; /**< Max bit-rate allowed in VBR mode for the high-band */ + spx_int32_t abr_enabled; /**< ABR setting (in bps), 0 if off */ float abr_drift; float abr_drift2; float abr_count; - int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */ + int vad_enabled; /**< 1 for enabling VAD, 0 otherwise */ float relative_quality; +#endif /* #ifndef DISABLE_VBR */ - SpeexSubmode **submodes; + int encode_submode; + const SpeexSubmode * const *submodes; int submodeID; int submodeSelect; int complexity; - int sampling_rate; + spx_int32_t sampling_rate; } SBEncState; /**Structure representing the full state of the sub-band decoder*/ typedef struct SBDecState { - SpeexMode *mode; /**< Pointer to the mode (containing for vtable info) */ + const SpeexMode *mode; /**< Pointer to the mode (containing for vtable info) */ void *st_low; /**< State of the low-band (narrowband) encoder */ int full_frame_size; int frame_size; @@ -118,47 +104,48 @@ typedef struct SBDecState { int nbSubframes; int lpcSize; int first; - int sampling_rate; + spx_int32_t sampling_rate; int lpc_enh_enabled; char *stack; - float *x0d, *x1d; - float *high; - float *y0, *y1; - float *h0_mem, *h1_mem, *g0_mem, *g1_mem; + spx_word16_t *g0_mem, *g1_mem; - float *exc; - float *qlsp; - float *old_qlsp; - float *interp_qlsp; - float *interp_qlpc; + spx_word16_t *excBuf; + spx_lsp_t *old_qlsp; + spx_coef_t *interp_qlpc; - float *mem_sp; - float *pi_gain; + spx_mem_t *mem_sp; + spx_word32_t *pi_gain; + spx_word16_t *exc_rms; + spx_word16_t *innov_save; /** If non-NULL, innovation is copied here */ - SpeexSubmode **submodes; + spx_word16_t last_ener; + spx_uint32_t seed; + + int encode_submode; + const SpeexSubmode * const *submodes; int submodeID; } SBDecState; /**Initializes encoder state*/ -void *sb_encoder_init(SpeexMode *m); +void *sb_encoder_init(const SpeexMode *m); /**De-allocates encoder state resources*/ void sb_encoder_destroy(void *state); /**Encodes one frame*/ -int sb_encode(void *state, float *in, SpeexBits *bits); +int sb_encode(void *state, void *in, SpeexBits *bits); /**Initializes decoder state*/ -void *sb_decoder_init(SpeexMode *m); +void *sb_decoder_init(const SpeexMode *m); /**De-allocates decoder state resources*/ void sb_decoder_destroy(void *state); /**Decodes one frame*/ -int sb_decode(void *state, SpeexBits *bits, float *out); +int sb_decode(void *state, SpeexBits *bits, void *out); int sb_encoder_ctl(void *state, int request, void *ptr); diff --git a/external/speex/src/smallft.c b/external/speex/src/smallft.c new file mode 100644 index 0000000..82c3b0a --- /dev/null +++ b/external/speex/src/smallft.c @@ -0,0 +1,1261 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ******************************************************************** + + function: *unnormalized* fft transform + last mod: $Id: smallft.c,v 1.19 2003/10/08 05:12:37 jm Exp $ + + ********************************************************************/ + +/* FFT implementation from OggSquish, minus cosine transforms, + * minus all but radix 2/4 case. In Vorbis we only need this + * cut-down version. + * + * To do more than just power-of-two sized vectors, see the full + * version I wrote for NetLib. + * + * Note that the packing is a little strange; rather than the FFT r/i + * packing following R_0, I_n, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, + * it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the + * FORTRAN version + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "smallft.h" +#include "arch.h" +#include "os_support.h" + +static void drfti1(int n, float *wa, int *ifac){ + static int ntryh[4] = { 4,2,3,5 }; + static float tpi = 6.28318530717958648f; + float arg,argh,argld,fi; + int ntry=0,i,j=-1; + int k1, l1, l2, ib; + int ld, ii, ip, is, nq, nr; + int ido, ipm, nfm1; + int nl=n; + int nf=0; + + L101: + j++; + if (j < 4) + ntry=ntryh[j]; + else + ntry+=2; + + L104: + nq=nl/ntry; + nr=nl-ntry*nq; + if (nr!=0) goto L101; + + nf++; + ifac[nf+1]=ntry; + nl=nq; + if(ntry!=2)goto L107; + if(nf==1)goto L107; + + for (i=1;i>1; + ipp2=ip; + idp2=ido; + nbd=(ido-1)>>1; + t0=l1*ido; + t10=ip*ido; + + if(ido==1)goto L119; + for(ik=0;ikl1){ + for(j=1;j>1; + ipp2=ip; + ipph=(ip+1)>>1; + if(idol1)goto L139; + + is= -ido-1; + t1=0; + for(j=1;jn==1)return; + drftf1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); +} + +void spx_drft_backward(struct drft_lookup *l,float *data){ + if (l->n==1)return; + drftb1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); +} + +void spx_drft_init(struct drft_lookup *l,int n) +{ + l->n=n; + l->trigcache=(float*)speex_alloc(3*n*sizeof(*l->trigcache)); + l->splitcache=(int*)speex_alloc(32*sizeof(*l->splitcache)); + fdrffti(n, l->trigcache, l->splitcache); +} + +void spx_drft_clear(struct drft_lookup *l) +{ + if(l) + { + if(l->trigcache) + speex_free(l->trigcache); + if(l->splitcache) + speex_free(l->splitcache); + } +} diff --git a/external/speex/src/smallft.h b/external/speex/src/smallft.h new file mode 100644 index 0000000..446e2f6 --- /dev/null +++ b/external/speex/src/smallft.h @@ -0,0 +1,46 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ******************************************************************** + + function: fft transform + last mod: $Id: smallft.h,v 1.3 2003/09/16 18:35:45 jm Exp $ + + ********************************************************************/ +/** + @file smallft.h + @brief Discrete Rotational Fourier Transform (DRFT) +*/ + +#ifndef _V_SMFT_H_ +#define _V_SMFT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** Discrete Rotational Fourier Transform lookup */ +struct drft_lookup{ + int n; + float *trigcache; + int *splitcache; +}; + +extern void spx_drft_forward(struct drft_lookup *l,float *data); +extern void spx_drft_backward(struct drft_lookup *l,float *data); +extern void spx_drft_init(struct drft_lookup *l,int n); +extern void spx_drft_clear(struct drft_lookup *l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/speex/src/speex.c b/external/speex/src/speex.c new file mode 100644 index 0000000..33701ba --- /dev/null +++ b/external/speex/src/speex.c @@ -0,0 +1,253 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: speex.c + + Basic Speex functions + + 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "modes.h" +#include +#include "os_support.h" + +#ifndef NULL +#define NULL 0 +#endif + +#define MAX_IN_SAMPLES 640 + + + +EXPORT void *speex_encoder_init(const SpeexMode *mode) +{ + return mode->enc_init(mode); +} + +EXPORT void *speex_decoder_init(const SpeexMode *mode) +{ + return mode->dec_init(mode); +} + +EXPORT void speex_encoder_destroy(void *state) +{ + (*((SpeexMode**)state))->enc_destroy(state); +} + +EXPORT void speex_decoder_destroy(void *state) +{ + (*((SpeexMode**)state))->dec_destroy(state); +} + + + +int speex_encode_native(void *state, spx_word16_t *in, SpeexBits *bits) +{ + return (*((SpeexMode**)state))->enc(state, in, bits); +} + +int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out) +{ + return (*((SpeexMode**)state))->dec(state, bits, out); +} + + + +#ifdef FIXED_POINT + +#ifndef DISABLE_FLOAT_API +EXPORT int speex_encode(void *state, float *in, SpeexBits *bits) +{ + int i; + spx_int32_t N; + spx_int16_t short_in[MAX_IN_SAMPLES]; + speex_encoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); + for (i=0;i32767.f) + short_in[i] = 32767; + else if (in[i]<-32768.f) + short_in[i] = -32768; + else + short_in[i] = (spx_int16_t)floor(.5+in[i]); + } + return (*((SpeexMode**)state))->enc(state, short_in, bits); +} +#endif /* #ifndef DISABLE_FLOAT_API */ + +EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) +{ + SpeexMode *mode; + mode = *(SpeexMode**)state; + return (mode)->enc(state, in, bits); +} + +#ifndef DISABLE_FLOAT_API +EXPORT int speex_decode(void *state, SpeexBits *bits, float *out) +{ + int i, ret; + spx_int32_t N; + spx_int16_t short_out[MAX_IN_SAMPLES]; + speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); + ret = (*((SpeexMode**)state))->dec(state, bits, short_out); + for (i=0;idec(state, bits, out); +} + +#else + +EXPORT int speex_encode(void *state, float *in, SpeexBits *bits) +{ + return (*((SpeexMode**)state))->enc(state, in, bits); +} + +EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) +{ + int i; + spx_int32_t N; + float float_in[MAX_IN_SAMPLES]; + speex_encoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); + for (i=0;ienc(state, float_in, bits); +} + +EXPORT int speex_decode(void *state, SpeexBits *bits, float *out) +{ + return (*((SpeexMode**)state))->dec(state, bits, out); +} + +EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) +{ + int i; + spx_int32_t N; + float float_out[MAX_IN_SAMPLES]; + int ret; + speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &N); + ret = (*((SpeexMode**)state))->dec(state, bits, float_out); + if (ret == 0) + { + for (i=0;i32767.f) + out[i] = 32767; + else if (float_out[i]<-32768.f) + out[i] = -32768; + else + out[i] = (spx_int16_t)floor(.5+float_out[i]); + } + } + return ret; +} +#endif + + + +EXPORT int speex_encoder_ctl(void *state, int request, void *ptr) +{ + return (*((SpeexMode**)state))->enc_ctl(state, request, ptr); +} + +EXPORT int speex_decoder_ctl(void *state, int request, void *ptr) +{ + return (*((SpeexMode**)state))->dec_ctl(state, request, ptr); +} + + + +int nb_mode_query(const void *mode, int request, void *ptr) +{ + const SpeexNBMode *m = (const SpeexNBMode*)mode; + + switch (request) + { + case SPEEX_MODE_FRAME_SIZE: + *((int*)ptr)=m->frameSize; + break; + case SPEEX_SUBMODE_BITS_PER_FRAME: + if (*((int*)ptr)==0) + *((int*)ptr) = NB_SUBMODE_BITS+1; + else if (m->submodes[*((int*)ptr)]==NULL) + *((int*)ptr) = -1; + else + *((int*)ptr) = m->submodes[*((int*)ptr)]->bits_per_frame; + break; + default: + speex_warning_int("Unknown nb_mode_query request: ", request); + return -1; + } + return 0; +} + + + +EXPORT int speex_lib_ctl(int request, void *ptr) +{ + switch (request) + { + case SPEEX_LIB_GET_MAJOR_VERSION: + *((int*)ptr) = SPEEX_MAJOR_VERSION; + break; + case SPEEX_LIB_GET_MINOR_VERSION: + *((int*)ptr) = SPEEX_MINOR_VERSION; + break; + case SPEEX_LIB_GET_MICRO_VERSION: + *((int*)ptr) = SPEEX_MICRO_VERSION; + break; + case SPEEX_LIB_GET_EXTRA_VERSION: + *((const char**)ptr) = SPEEX_EXTRA_VERSION; + break; + case SPEEX_LIB_GET_VERSION_STRING: + *((const char**)ptr) = SPEEX_VERSION; + break; + /*case SPEEX_LIB_SET_ALLOC_FUNC: + break; + case SPEEX_LIB_GET_ALLOC_FUNC: + break; + case SPEEX_LIB_SET_FREE_FUNC: + break; + case SPEEX_LIB_GET_FREE_FUNC: + break;*/ + default: + speex_warning_int("Unknown wb_mode_query request: ", request); + return -1; + } + return 0; +} diff --git a/external/speex/src/speex_callbacks.c b/external/speex/src/speex_callbacks.c index 3b48696..8be9e38 100644 --- a/external/speex/src/speex_callbacks.c +++ b/external/speex/src/speex_callbacks.c @@ -6,18 +6,18 @@ 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 @@ -32,10 +32,15 @@ */ -#include "speex_callbacks.h" -#include "misc.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) +#include "speex/speex_callbacks.h" +#include "arch.h" +#include "os_support.h" + +EXPORT int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) { int id; SpeexCallback *callback; @@ -60,74 +65,78 @@ int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *st adv = 16; else if (id<14) adv = 32; - else + else adv = 64; speex_bits_advance(bits, adv); } return 0; } -int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) { - int m; + spx_int32_t m; m = speex_bits_unpack_unsigned(bits, 4); speex_encoder_ctl(data, SPEEX_SET_MODE, &m); return 0; } -int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data) { - int m; + spx_int32_t m; m = speex_bits_unpack_unsigned(bits, 4); speex_encoder_ctl(data, SPEEX_SET_LOW_MODE, &m); return 0; } -int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data) { - int m; + spx_int32_t m; m = speex_bits_unpack_unsigned(bits, 4); speex_encoder_ctl(data, SPEEX_SET_HIGH_MODE, &m); return 0; } -int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data) +#ifndef DISABLE_VBR +EXPORT int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data) { - int vbr; + spx_int32_t vbr; vbr = speex_bits_unpack_unsigned(bits, 1); speex_encoder_ctl(data, SPEEX_SET_VBR, &vbr); return 0; } +#endif /* #ifndef DISABLE_VBR */ -int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) { - int enh; + spx_int32_t enh; enh = speex_bits_unpack_unsigned(bits, 1); speex_decoder_ctl(data, SPEEX_SET_ENH, &enh); return 0; } -int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data) +#ifndef DISABLE_VBR +EXPORT int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data) { - int qual; + float qual; qual = speex_bits_unpack_unsigned(bits, 4); speex_encoder_ctl(data, SPEEX_SET_VBR_QUALITY, &qual); return 0; } +#endif /* #ifndef DISABLE_VBR */ - -int speex_std_char_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_std_char_handler(SpeexBits *bits, void *state, void *data) { unsigned char ch; ch = speex_bits_unpack_unsigned(bits, 8); _speex_putc(ch, data); + /*printf("speex_std_char_handler ch=%x\n", ch);*/ return 0; } /* Default handler for user callbacks: skip it */ -int speex_default_user_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_default_user_handler(SpeexBits *bits, void *state, void *data) { int req_size = speex_bits_unpack_unsigned(bits, 4); speex_bits_advance(bits, 5+8*req_size); diff --git a/external/speex/src/speex_header.c b/external/speex/src/speex_header.c index 7ee1ef3..5900d36 100644 --- a/external/speex/src/speex_header.c +++ b/external/speex/src/speex_header.c @@ -1,22 +1,22 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: speex_header.c Describes the Speex header 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 @@ -31,14 +31,35 @@ */ -#include "speex_header.h" -#include "misc.h" -#include "speex.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "arch.h" +#include "speex/speex_header.h" +#include "speex/speex.h" +#include "os_support.h" #ifndef NULL #define NULL 0 #endif +/** Convert little endian */ +static inline spx_int32_t le_int(spx_int32_t i) +{ +#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) + spx_uint32_t ui, ret; + ui = i; + ret = ui>>24; + ret |= (ui>>8)&0x0000ff00; + ret |= (ui<<8)&0x00ff0000; + ret |= (ui<<24); + return ret; +#else + return i; +#endif +} + #define ENDIAN_SWITCH(x) {x=le_int(x);} @@ -62,25 +83,25 @@ typedef struct SpeexHeader { } SpeexHeader; */ -void speex_init_header(SpeexHeader *header, int rate, int nb_channels, SpeexMode *m) +EXPORT void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m) { int i; - char *h="Speex "; + const char *h="Speex "; /* strncpy(header->speex_string, "Speex ", 8); - strncpy(header->speex_version, VERSION, SPEEX_HEADER_VERSION_LENGTH-1); + strncpy(header->speex_version, SPEEX_VERSION, SPEEX_HEADER_VERSION_LENGTH-1); header->speex_version[SPEEX_HEADER_VERSION_LENGTH-1]=0; */ for (i=0;i<8;i++) header->speex_string[i]=h[i]; - for (i=0;ispeex_version[i]=VERSION[i]; + for (i=0;ispeex_version[i]=SPEEX_VERSION[i]; for (;ispeex_version[i]=0; - + header->speex_version_id = 1; header->header_size = sizeof(SpeexHeader); - + header->rate = rate; header->mode = m->modeID; header->mode_bitstream_version = m->bitstream_version; @@ -90,20 +111,20 @@ void speex_init_header(SpeexHeader *header, int rate, int nb_channels, SpeexMode header->bitrate = -1; speex_mode_query(m, SPEEX_MODE_FRAME_SIZE, &header->frame_size); header->vbr = 0; - + header->frames_per_packet = 0; header->extra_headers = 0; header->reserved1 = 0; header->reserved2 = 0; } -char *speex_header_to_packet(SpeexHeader *header, int *size) +EXPORT char *speex_header_to_packet(SpeexHeader *header, int *size) { SpeexHeader *le_header; le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); - - speex_move(le_header, header, sizeof(SpeexHeader)); - + + SPEEX_COPY(le_header, header, 1); + /*Make sure everything is now little-endian*/ ENDIAN_SWITCH(le_header->speex_version_id); ENDIAN_SWITCH(le_header->header_size); @@ -121,29 +142,31 @@ char *speex_header_to_packet(SpeexHeader *header, int *size) return (char *)le_header; } -SpeexHeader *speex_packet_to_header(char *packet, int size) +EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size) { int i; SpeexHeader *le_header; - char *h = "Speex "; + const char *h = "Speex "; + + /*FIXME: Do we allow larger headers?*/ + if (size < (int)sizeof(SpeexHeader)) + { + speex_notify("Speex header too small"); + return NULL; + } + + for (i=0;i<8;i++) if (packet[i]!=h[i]) { - speex_warning ("This doesn't look like a Speex file"); + /* This doesn't look like a Speex file */ return NULL; } - - /*FIXME: Do we allow larger headers?*/ - if (size < sizeof(SpeexHeader)) - { - speex_warning("Speex header too small"); - return NULL; - } - + le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); - - speex_move(le_header, packet, sizeof(SpeexHeader)); - + + SPEEX_COPY(le_header, (SpeexHeader*)packet, 1); + /*Make sure everything is converted correctly from little-endian*/ ENDIAN_SWITCH(le_header->speex_version_id); ENDIAN_SWITCH(le_header->header_size); @@ -157,6 +180,23 @@ SpeexHeader *speex_packet_to_header(char *packet, int size) ENDIAN_SWITCH(le_header->frames_per_packet); ENDIAN_SWITCH(le_header->extra_headers); + if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0) + { + speex_notify("Invalid mode specified in Speex header"); + speex_free (le_header); + return NULL; + } + + if (le_header->nb_channels>2) + le_header->nb_channels = 2; + if (le_header->nb_channels<1) + le_header->nb_channels = 1; + return le_header; } + +EXPORT void speex_header_free(void *ptr) +{ + speex_free(ptr); +} diff --git a/external/speex/src/stack_alloc.h b/external/speex/src/stack_alloc.h index 2390b69..a446065 100644 --- a/external/speex/src/stack_alloc.h +++ b/external/speex/src/stack_alloc.h @@ -1,23 +1,24 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: stack_alloc.h - - Temporary memory allocation on stack - +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file stack_alloc.h + @brief Temporary memory allocation on stack +*/ +/* 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 @@ -34,29 +35,81 @@ #ifndef STACK_ALLOC_H #define STACK_ALLOC_H -#if 0 +#ifdef USE_ALLOCA +# ifdef _WIN32 +# include +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# include +# endif +# endif +#endif -/*Aligns the stack to a 'size' boundary */ -#define ALIGN(stack, size) (stack=(void*)((((int)stack)+((size)-1)) & (-(size)))) -/*Aligns the stack to a 'size' boundary minus k */ -#define ALIGN_1(stack, size, k) (stack=(void*)(((((int)stack)+((size)-1+(k))) & (-(size)))-(k))) +/** + * @def ALIGN(stack, size) + * + * Aligns the stack to a 'size' boundary + * + * @param stack Stack + * @param size New size boundary + */ -/* Allocates 'size' elements of type 'type' on the stack */ -#define PUSH(stack, size, type) (ALIGN(stack,sizeof(type)),stack=(void*)(((int)stack)+((size)*sizeof(type))),(type*)(((int)stack)-((size)*sizeof(type)))) +/** + * @def PUSH(stack, size, type) + * + * Allocates 'size' elements of type 'type' on the stack + * + * @param stack Stack + * @param size Number of elements + * @param type Type of element + */ +/** + * @def VARDECL(var) + * + * Declare variable on stack + * + * @param var Variable to declare + */ + +/** + * @def ALLOC(var, size, type) + * + * Allocate 'size' elements of 'type' on stack + * + * @param var Name of variable to allocate + * @param size Number of elements + * @param type Type of element + */ + +#ifdef ENABLE_VALGRIND + +#include + +#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) + +#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) #else -/*Aligns the stack to a 'size' boundary */ -#define ALIGN(stack, size) ((stack) += ((size) - (int)(stack)) & ((size) - 1)) +#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) -/* Allocates 'size' elements of type 'type' on the stack */ #define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) -/* Allocates a struct stack */ -#define PUSHS(stack, type) (ALIGN((stack),sizeof(long)),(stack)+=(sizeof(type)),(type*)((stack)-(sizeof(type)))) +#endif + +#if defined(VAR_ARRAYS) +#define VARDECL(var) +#define ALLOC(var, size, type) type var[size] +#elif defined(USE_ALLOCA) +#define VARDECL(var) var +#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size)) +#else +#define VARDECL(var) var +#define ALLOC(var, size, type) var = PUSH(stack, size, type) +#endif -#endif - #endif diff --git a/external/speex/src/stereo.c b/external/speex/src/stereo.c index e033ce5..e010624 100644 --- a/external/speex/src/stereo.c +++ b/external/speex/src/stereo.c @@ -1,21 +1,21 @@ -/* Copyright (C) 2002 Jean-Marc Valin +/* Copyright (C) 2002 Jean-Marc Valin File: stereo.c 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 @@ -29,25 +29,94 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "speex_stereo.h" -#include "speex_callbacks.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "speex/speex_stereo.h" +#include "speex/speex_callbacks.h" +#include "math_approx.h" #include "vq.h" #include +#include "os_support.h" + +typedef struct RealSpeexStereoState { + spx_word32_t balance; /**< Left/right balance info */ + spx_word32_t e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ + spx_word32_t smooth_left; /**< Smoothed left channel gain */ + spx_word32_t smooth_right; /**< Smoothed right channel gain */ + spx_uint32_t reserved1; /**< Reserved for future use */ + spx_int32_t reserved2; /**< Reserved for future use */ +} RealSpeexStereoState; + /*float e_ratio_quant[4] = {1, 1.26, 1.587, 2};*/ -static float e_ratio_quant[4] = {.25, .315, .397, .5}; +#ifndef FIXED_POINT +static const float e_ratio_quant[4] = {.25f, .315f, .397f, .5f}; +static const float e_ratio_quant_bounds[3] = {0.2825f, 0.356f, 0.4485f}; +#else +static const spx_word16_t e_ratio_quant[4] = {8192, 10332, 13009, 16384}; +static const spx_word16_t e_ratio_quant_bounds[3] = {9257, 11665, 14696}; +static const spx_word16_t balance_bounds[31] = {18, 23, 30, 38, 49, 63, 81, 104, + 134, 172, 221, 284, 364, 468, 600, 771, + 990, 1271, 1632, 2096, 2691, 3455, 4436, 5696, + 7314, 9392, 12059, 15484, 19882, 25529, 32766}; +#endif -void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) +/* This is an ugly compatibility hack that properly resets the stereo state + In case it it compiled in fixed-point, but initialised with the deprecated + floating point static initialiser */ +#ifdef FIXED_POINT +#define COMPATIBILITY_HACK(s) do {if ((s)->reserved1 != 0xdeadbeef) speex_stereo_state_reset((SpeexStereoState*)s); } while (0); +#else +#define COMPATIBILITY_HACK(s) +#endif + +EXPORT SpeexStereoState *speex_stereo_state_init() +{ + SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); + speex_stereo_state_reset(stereo); + return stereo; +} + +EXPORT void speex_stereo_state_reset(SpeexStereoState *_stereo) +{ + RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; +#ifdef FIXED_POINT + stereo->balance = 65536; + stereo->e_ratio = 16384; + stereo->smooth_left = 16384; + stereo->smooth_right = 16384; + stereo->reserved1 = 0xdeadbeef; + stereo->reserved2 = 0; +#else + stereo->balance = 1.0f; + stereo->e_ratio = .5f; + stereo->smooth_left = 1.f; + stereo->smooth_right = 1.f; + stereo->reserved1 = 0; + stereo->reserved2 = 0; +#endif +} + +EXPORT void speex_stereo_state_destroy(SpeexStereoState *stereo) +{ + speex_free(stereo); +} + +#ifndef DISABLE_ENCODER +#ifndef DISABLE_FLOAT_API +EXPORT void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) { int i, tmp; float e_left=0, e_right=0, e_tot=0; float balance, e_ratio; for (i=0;i30) balance=31; - + speex_bits_pack(bits, (int)balance, 5); - - /*Quantize energy ratio*/ - tmp=vq_index(&e_ratio, e_ratio_quant, 1, 4); + + /* FIXME: this is a hack */ + tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 4); speex_bits_pack(bits, tmp, 2); } +#endif /* #ifndef DISABLE_FLOAT_API */ -void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo) +EXPORT void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) +{ + int i, tmp; + spx_word32_t e_left=0, e_right=0, e_tot=0; + spx_word32_t balance, e_ratio; + spx_word32_t largest, smallest; + int balance_id; +#ifdef FIXED_POINT + int shift; + int sqr_shift; + + /* Avoid overflows when summing squares */ + sqr_shift = frame_size >= 512 ? 9 : 8; +#endif + + /* In band marker */ + speex_bits_pack(bits, 14, 5); + /* Stereo marker */ + speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); + + for (i=0;i e_right) + { + speex_bits_pack(bits, 0, 1); + largest = e_left; + smallest = e_right; + } else { + speex_bits_pack(bits, 1, 1); + largest = e_right; + smallest = e_left; + } + + /* Balance quantization */ +#ifdef FIXED_POINT + shift = spx_ilog2(largest)-15; + largest = VSHR32(largest, shift-4); + smallest = VSHR32(smallest, shift); + balance = DIV32(largest, ADD32(smallest, 1)); + if (balance > 32767) + balance = 32767; + balance_id = scal_quant(EXTRACT16(balance), balance_bounds, 32); +#else + balance=(largest+1.)/(smallest+1.); + balance=4*log(balance); + balance_id=floor(.5+fabs(balance)); + if (balance_id>30) + balance_id=31; +#endif + + speex_bits_pack(bits, balance_id, 5); + + /* "coherence" quantisation */ +#ifdef FIXED_POINT + shift = spx_ilog2(e_tot); + e_tot = VSHR32(e_tot, shift-25); + e_left = VSHR32(e_left, shift-10); + e_right = VSHR32(e_right, shift-10); + e_ratio = DIV32(e_tot, e_left+e_right+1); +#else + e_ratio = e_tot/(1.+e_left+e_right); +#endif + + tmp=scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4); + /*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio);*/ + speex_bits_pack(bits, tmp, 2); +} +#else /* DISABLE_ENCODER */ +EXPORT void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) +{ +} +#endif /* DISABLE_ENCODER */ + + +#ifndef DISABLE_FLOAT_API +EXPORT void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo) { - float balance, e_ratio; int i; - float e_tot=0, e_left, e_right, e_sum; + spx_word32_t balance; + spx_word16_t e_left, e_right, e_ratio; + RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; + + COMPATIBILITY_HACK(stereo); balance=stereo->balance; e_ratio=stereo->e_ratio; + + /* These two are Q14, with max value just below 2. */ + e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); + e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); + for (i=frame_size-1;i>=0;i--) { - e_tot += data[i]*data[i]; + spx_word16_t tmp=data[i]; + stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); + stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); + data[2*i] = (float)MULT16_16_P14(stereo->smooth_left, tmp); + data[2*i+1] = (float)MULT16_16_P14(stereo->smooth_right, tmp); } - e_sum=e_tot/e_ratio; - e_left = e_sum*balance / (1+balance); - e_right = e_sum-e_left; +} +#endif /* #ifndef DISABLE_FLOAT_API */ - e_left = sqrt(e_left/(e_tot+.01)); - e_right = sqrt(e_right/(e_tot+.01)); +EXPORT void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) +{ + int i; + spx_word32_t balance; + spx_word16_t e_left, e_right, e_ratio; + RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; + + COMPATIBILITY_HACK(stereo); + + balance=stereo->balance; + e_ratio=stereo->e_ratio; + + /* These two are Q14, with max value just below 2. */ + e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); + e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); for (i=frame_size-1;i>=0;i--) { - float ftmp=data[i]; - stereo->smooth_left = .98*stereo->smooth_left + .02*e_left; - stereo->smooth_right = .98*stereo->smooth_right + .02*e_right; - data[2*i] = stereo->smooth_left*ftmp; - data[2*i+1] = stereo->smooth_right*ftmp; + spx_int16_t tmp=data[i]; + stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); + stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); + data[2*i] = (spx_int16_t)MULT16_16_P14(stereo->smooth_left, tmp); + data[2*i+1] = (spx_int16_t)MULT16_16_P14(stereo->smooth_right, tmp); } } -int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) +EXPORT int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) { - SpeexStereoState *stereo; - float sign=1; + RealSpeexStereoState *stereo; + spx_word16_t sign=1, dexp; int tmp; - stereo = (SpeexStereoState*)data; + stereo = (RealSpeexStereoState*)data; + + COMPATIBILITY_HACK(stereo); + if (speex_bits_unpack_unsigned(bits, 1)) sign=-1; - tmp = speex_bits_unpack_unsigned(bits, 5); - stereo->balance = exp(sign*.25*tmp); - + dexp = speex_bits_unpack_unsigned(bits, 5); +#ifndef FIXED_POINT + stereo->balance = exp(sign*.25*dexp); +#else + stereo->balance = spx_exp(MULT16_16(sign, SHL16(dexp, 9))); +#endif tmp = speex_bits_unpack_unsigned(bits, 2); stereo->e_ratio = e_ratio_quant[tmp]; diff --git a/external/speex/src/testenc.c b/external/speex/src/testenc.c new file mode 100644 index 0000000..1f634ed --- /dev/null +++ b/external/speex/src/testenc.c @@ -0,0 +1,145 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "speex/speex_callbacks.h" +#include +#include + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + +#define FRAME_SIZE 160 +#include +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in_short[FRAME_SIZE]; + short out_short[FRAME_SIZE]; + int snr_frames = 0; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + spx_int32_t tmp; + int bitCount=0; + spx_int32_t skip_group_delay; + SpeexCallback callback; + + st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_NB)); + dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB)); + + /* BEGIN: You probably don't need the following in a real application */ + callback.callback_id = SPEEX_INBAND_CHAR; + callback.func = speex_std_char_handler; + callback.data = stderr; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + callback.callback_id = SPEEX_INBAND_MODE_REQUEST; + callback.func = speex_std_mode_request_handler; + callback.data = st; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + /* END of unnecessary stuff */ + + tmp=1; + speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); + tmp=0; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + tmp=8; + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); + + /* Turn this off if you want to measure SNR (on by default) */ + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &tmp); + speex_decoder_ctl(dec, SPEEX_SET_HIGHPASS, &tmp); + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); + skip_group_delay += tmp; + + if (argc != 4 && argc != 3) + { + fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); + exit(1); + } + inFile = argv[1]; + fin = fopen(inFile, "rb"); + outFile = argv[2]; + fout = fopen(outFile, "wb+"); + if (argc==4) + { + bitsFile = argv[3]; + fbits = fopen(bitsFile, "wb"); + } + speex_bits_init(&bits); + while (!feof(fin)) + { + fread(in_short, sizeof(short), FRAME_SIZE, fin); + if (feof(fin)) + break; + speex_bits_reset(&bits); + + speex_encode_int(st, in_short, &bits); + nbBits = speex_bits_write(&bits, cbits, 200); + bitCount+=bits.nbBits; + + if (argc==4) + fwrite(cbits, 1, nbBits, fbits); + speex_bits_rewind(&bits); + + speex_decode_int(dec, &bits, out_short); + speex_bits_reset(&bits); + + fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); + skip_group_delay = 0; + } + fprintf (stderr, "Total encoded size: %d bits\n", bitCount); + speex_encoder_destroy(st); + speex_decoder_destroy(dec); + speex_bits_destroy(&bits); + +#ifndef DISABLE_FLOAT_API + { + float sigpow,errpow,snr, seg_snr=0; + sigpow = 0; + errpow = 0; + + /* This code just computes SNR, so you don't need it either */ + rewind(fin); + rewind(fout); + + while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) + && + FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) + { + float s=0, e=0; + for (i=0;i +#include + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + +#define FRAME_SIZE 640 +#include +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in_short[FRAME_SIZE]; + short out_short[FRAME_SIZE]; + float sigpow,errpow,snr, seg_snr=0; + int snr_frames = 0; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + spx_int32_t tmp; + int bitCount=0; + spx_int32_t skip_group_delay; + SpeexCallback callback; + + sigpow = 0; + errpow = 0; + + st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB)); + dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB)); + + callback.callback_id = SPEEX_INBAND_CHAR; + callback.func = speex_std_char_handler; + callback.data = stderr; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + callback.callback_id = SPEEX_INBAND_MODE_REQUEST; + callback.func = speex_std_mode_request_handler; + callback.data = st; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + tmp=0; + speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); + tmp=0; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + tmp=7; + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); + skip_group_delay += tmp; + + + if (argc != 4 && argc != 3) + { + fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); + exit(1); + } + inFile = argv[1]; + fin = fopen(inFile, "rb"); + outFile = argv[2]; + fout = fopen(outFile, "wb+"); + if (argc==4) + { + bitsFile = argv[3]; + fbits = fopen(bitsFile, "wb"); + } + speex_bits_init(&bits); + while (!feof(fin)) + { + fread(in_short, sizeof(short), FRAME_SIZE, fin); + if (feof(fin)) + break; + speex_bits_reset(&bits); + + speex_encode_int(st, in_short, &bits); + nbBits = speex_bits_write(&bits, cbits, 200); + bitCount+=bits.nbBits; + + if (argc==4) + fwrite(cbits, 1, nbBits, fbits); + speex_bits_rewind(&bits); + + speex_decode_int(dec, &bits, out_short); + speex_bits_reset(&bits); + + fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); + skip_group_delay = 0; + } + fprintf (stderr, "Total encoded size: %d bits\n", bitCount); + speex_encoder_destroy(st); + speex_decoder_destroy(dec); + + rewind(fin); + rewind(fout); + + while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) + && + FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) + { + float s=0, e=0; + for (i=0;i +#include + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + +#define FRAME_SIZE 320 +#include +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in_short[FRAME_SIZE]; + short out_short[FRAME_SIZE]; + float sigpow,errpow,snr, seg_snr=0; + int snr_frames = 0; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + spx_int32_t tmp; + int bitCount=0; + spx_int32_t skip_group_delay; + SpeexCallback callback; + + sigpow = 0; + errpow = 0; + + st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_WB)); + dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_WB)); + + callback.callback_id = SPEEX_INBAND_CHAR; + callback.func = speex_std_char_handler; + callback.data = stderr; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + callback.callback_id = SPEEX_INBAND_MODE_REQUEST; + callback.func = speex_std_mode_request_handler; + callback.data = st; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + tmp=1; + speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); + tmp=0; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + tmp=8; + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); + tmp=3; + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); + /*tmp=3; + speex_encoder_ctl(st, SPEEX_SET_HIGH_MODE, &tmp); + tmp=6; + speex_encoder_ctl(st, SPEEX_SET_LOW_MODE, &tmp); +*/ + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); + skip_group_delay += tmp; + + + if (argc != 4 && argc != 3) + { + fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); + exit(1); + } + inFile = argv[1]; + fin = fopen(inFile, "rb"); + outFile = argv[2]; + fout = fopen(outFile, "wb+"); + if (argc==4) + { + bitsFile = argv[3]; + fbits = fopen(bitsFile, "wb"); + } + speex_bits_init(&bits); + while (!feof(fin)) + { + fread(in_short, sizeof(short), FRAME_SIZE, fin); + if (feof(fin)) + break; + speex_bits_reset(&bits); + + speex_encode_int(st, in_short, &bits); + nbBits = speex_bits_write(&bits, cbits, 200); + bitCount+=bits.nbBits; + + if (argc==4) + fwrite(cbits, 1, nbBits, fbits); + speex_bits_rewind(&bits); + + speex_decode_int(dec, &bits, out_short); + speex_bits_reset(&bits); + + fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); + skip_group_delay = 0; + } + fprintf (stderr, "Total encoded size: %d bits\n", bitCount); + speex_encoder_destroy(st); + speex_decoder_destroy(dec); + speex_bits_destroy(&bits); + + rewind(fin); + rewind(fout); + + while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) + && + FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) + { + float s=0, e=0; + for (i=0;i #define sqr(x) ((x)*(x)) -#define MIN_ENERGY 6000.0f -#define NOISE_POW .3f +#define MIN_ENERGY 6000 +#define NOISE_POW .3 +#ifndef DISABLE_VBR -float vbr_nb_thresh[9][11]={ - {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* CNG */ - { 3.5, 2.5, 2.0, 1.2, 0.5, 0.0, -0.5, -0.7, -0.8, -0.9, -1.0}, /* 2 kbps */ - {10.0, 6.5, 5.2, 4.5, 3.9, 3.5, 3.0, 2.5, 2.3, 1.8, 1.0}, /* 6 kbps */ - {11.0, 8.8, 7.5, 6.5, 5.0, 3.9, 3.9, 3.9, 3.5, 3.0, 1.0}, /* 8 kbps */ - {11.0, 11.0, 9.9, 9.0, 8.0, 7.0, 6.5, 6.0, 5.0, 4.0, 2.0}, /* 11 kbps */ - {11.0, 11.0, 11.0, 11.0, 9.5, 9.0, 8.0, 7.0, 6.5, 5.0, 3.0}, /* 15 kbps */ - {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 9.5, 8.5, 8.0, 6.5, 4.0}, /* 18 kbps */ - {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 9.8, 7.5, 5.5}, /* 24 kbps */ - { 8.0, 5.0, 3.7, 3.0, 2.5, 2.0, 1.8, 1.5, 1.0, 0.0, 0.0} /* 4 kbps */ +const float vbr_nb_thresh[9][11]={ + {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* CNG */ + { 4.0f, 2.5f, 2.0f, 1.2f, 0.5f,-0.25f, -0.5f, -0.7f, -0.8f, -0.9f, -1.0f}, /* 2 kbps */ + {10.0f, 6.5f, 5.2f, 4.5f, 3.9f, 3.7f, 3.0f, 2.5f, 2.3f, 1.8f, 1.0f}, /* 6 kbps */ + {11.0f, 8.8f, 7.5f, 6.5f, 5.0f, 4.2f, 3.9f, 3.9f, 3.5f, 3.0f, 1.0f}, /* 8 kbps */ + {11.0f, 11.0f, 9.9f, 8.5f, 7.0f, 5.25f, 4.5f, 4.0f, 4.0f, 4.0f, 2.0f}, /* 11 kbps */ + {11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 9.25f, 8.0f, 7.0f, 5.0f, 4.0f, 3.0f}, /* 15 kbps */ + {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.5f, 6.2f, 5.2f, 5.0f}, /* 18 kbps */ + {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 10.0f, 9.8f, 7.5f}, /* 24 kbps */ + { 7.0f, 4.5f, 3.7f, 3.0f, 2.5f, 1.0f, 1.8f, 1.5f, 1.0f, 0.0f, 0.0f} /* 4 kbps */ }; -float vbr_hb_thresh[5][11]={ - {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* silence */ - {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* 2 kbps */ - {11.0, 11.0, 9.5, 8.5, 7.5, 6.0, 5.0, 3.9, 3.0, 2.0, 1.0}, /* 6 kbps */ - {11.0, 11.0, 11.0, 11.0, 11.0, 9.5, 8.7, 7.8, 7.0, 6.5, 4.0}, /* 10 kbps */ - {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 9.8, 7.5, 5.5} /* 18 kbps */ +const float vbr_hb_thresh[5][11]={ + {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* silence */ + {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* 2 kbps */ + {11.0f, 11.0f, 9.5f, 8.5f, 7.5f, 6.0f, 5.0f, 3.9f, 3.0f, 2.0f, 1.0f}, /* 6 kbps */ + {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.7f, 7.8f, 7.0f, 6.5f, 4.0f}, /* 10 kbps */ + {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.8f, 7.5f, 5.5f} /* 18 kbps */ }; -float vbr_uhb_thresh[2][11]={ - {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* silence */ - { 3.9, 2.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0} /* 2 kbps */ +const float vbr_uhb_thresh[2][11]={ + {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* silence */ + { 3.9f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f} /* 2 kbps */ }; void vbr_init(VBRState *vbr) { int i; - vbr->average_energy=0; + vbr->average_energy=1600000; vbr->last_energy=1; vbr->accum_sum=0; - vbr->energy_alpha=.1; vbr->soft_pitch=0; vbr->last_pitch_coef=0; vbr->last_quality=0; - vbr->noise_accum = .05f*pow(MIN_ENERGY, NOISE_POW); + vbr->noise_accum = .05*pow(MIN_ENERGY, NOISE_POW); vbr->noise_accum_count=.05; vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count; vbr->consec_noise=0; @@ -111,27 +115,26 @@ void vbr_init(VBRState *vbr) -Decrease bit-rate for males (low pitch)? - -(wideband only) less bits in the high-band when signal is very + -(wideband only) less bits in the high-band when signal is very non-stationary (harder to notice high-frequency noise)??? */ -float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_coef) +float vbr_analysis(VBRState *vbr, spx_word16_t *sig, int len, int pitch, float pitch_coef) { int i; float ener=0, ener1=0, ener2=0; float qual=7; - int va; float log_energy; float non_st=0; float voicing; float pow_ener; for (i=0;i>1;i++) - ener1 += sig[i]*sig[i]; + ener1 += ((float)sig[i])*sig[i]; for (i=len>>1;i1) non_st=1; - voicing = 3*(pitch_coef-.4f)*fabs(pitch_coef-.4f); - vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener; + voicing = 3*(pitch_coef-.4)*fabs(pitch_coef-.4); + vbr->average_energy = 0.9*vbr->average_energy + .1*ener; vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count; pow_ener = pow(ener,NOISE_POW); if (vbr->noise_accum_count<.06 && ener>MIN_ENERGY) - vbr->noise_accum = .05f*pow_ener; + vbr->noise_accum = .05*pow_ener; if ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level) || (voicing<.3 && non_st < .05 && pow_ener < 1.5*vbr->noise_level) @@ -154,36 +157,35 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co || (voicing<0 && non_st < .05)) { float tmp; - va = 0; + vbr->consec_noise++; if (pow_ener > 3*vbr->noise_level) tmp = 3*vbr->noise_level; - else + else tmp = pow_ener; if (vbr->consec_noise>=4) { - vbr->noise_accum = .95f*vbr->noise_accum + .05f*tmp; - vbr->noise_accum_count = .95f*vbr->noise_accum_count + .05f; + vbr->noise_accum = .95*vbr->noise_accum + .05*tmp; + vbr->noise_accum_count = .95*vbr->noise_accum_count + .05; } } else { - va = 1; vbr->consec_noise=0; } if (pow_ener < vbr->noise_level && ener>MIN_ENERGY) { - vbr->noise_accum = .95f*vbr->noise_accum + .05f*pow_ener; - vbr->noise_accum_count = .95f*vbr->noise_accum_count + .05f; + vbr->noise_accum = .95*vbr->noise_accum + .05*pow_ener; + vbr->noise_accum_count = .95*vbr->noise_accum_count + .05; } /* Checking for very low absolute energy */ if (ener < 30000) { - qual -= .7f; + qual -= .7; if (ener < 10000) - qual-=.7f; + qual-=.7; if (ener < 3000) - qual-=.7f; + qual-=.7; } else { float short_diff, long_diff; short_diff = log((ener+1)/(1+vbr->last_energy)); @@ -196,30 +198,30 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co long_diff=2; if (long_diff>0) - qual += .6f*long_diff; + qual += .6*long_diff; if (long_diff<0) - qual += .5f*long_diff; + qual += .5*long_diff; if (short_diff>0) { if (short_diff>5) short_diff=5; - qual += .5f*short_diff; + qual += 1*short_diff; } /* Checking for energy increases */ - if (ener2 > 1.6f*ener1) - qual += .5f; + if (ener2 > 1.6*ener1) + qual += .5; } vbr->last_energy = ener; - vbr->soft_pitch = .6f*vbr->soft_pitch + .4f*pitch_coef; - qual += 2.2f*((pitch_coef-.4f) + (vbr->soft_pitch-.4f)); + vbr->soft_pitch = .8*vbr->soft_pitch + .2*pitch_coef; + qual += 2.2*((pitch_coef-.4) + (vbr->soft_pitch-.4)); if (qual < vbr->last_quality) - qual = .5f*qual + .5f*vbr->last_quality; + qual = .5*qual + .5*vbr->last_quality; if (qual<4) qual=4; if (qual>10) qual=10; - + /* if (vbr->consec_noise>=2) qual-=1.3; @@ -232,24 +234,24 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co qual=4; if (vbr->consec_noise) - qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3.0f)); + qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3)); if (qual<0) qual=0; - - if (ener<60000) + + if (ener<1600000) { if (vbr->consec_noise>2) - qual-=0.5f*(log(3.0 + vbr->consec_noise)-log(3.0f)); + qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3)); if (ener<10000&&vbr->consec_noise>2) - qual-=0.5f*(log(3.0 + vbr->consec_noise)-log(3.0f)); + qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3)); if (qual<0) qual=0; - qual += .3f*log(ener/60000.0); + qual += .3*log(.0001+ener/1600000.0); } if (qual<-1) qual=-1; - /*printf ("%f %f %f %f %d\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level), va);*/ + /*printf ("%f %f %f %f\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level));*/ vbr->last_pitch_coef = pitch_coef; vbr->last_quality = qual; @@ -258,7 +260,7 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co vbr->last_log_energy[i] = vbr->last_log_energy[i-1]; vbr->last_log_energy[0] = log_energy; - /*printf ("VBR: %f %f %f %d %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, va, vbr->noise_level);*/ + /*printf ("VBR: %f %f %f %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, vbr->noise_level);*/ return qual; } @@ -266,3 +268,5 @@ float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_co void vbr_destroy(VBRState *vbr) { } + +#endif /* #ifndef DISABLE_VBR */ diff --git a/external/speex/src/vbr.h b/external/speex/src/vbr.h index 405b47f..d713a5c 100644 --- a/external/speex/src/vbr.h +++ b/external/speex/src/vbr.h @@ -1,23 +1,24 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: vbr.h - - VBR-related routines - +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file vbr.h + @brief Variable Bit-Rate (VBR) related routines +*/ +/* 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 @@ -36,14 +37,16 @@ #ifndef VBR_H #define VBR_H +#include "arch.h" + #define VBR_MEMORY_SIZE 5 -extern float vbr_nb_thresh[9][11]; -extern float vbr_hb_thresh[5][11]; -extern float vbr_uhb_thresh[2][11]; +extern const float vbr_nb_thresh[9][11]; +extern const float vbr_hb_thresh[5][11]; +extern const float vbr_uhb_thresh[2][11]; +/** VBR state. */ typedef struct VBRState { - float energy_alpha; float average_energy; float last_energy; float last_log_energy[VBR_MEMORY_SIZE]; @@ -59,7 +62,7 @@ typedef struct VBRState { void vbr_init(VBRState *vbr); -float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_coef); +float vbr_analysis(VBRState *vbr, spx_word16_t *sig, int len, int pitch, float pitch_coef); void vbr_destroy(VBRState *vbr); diff --git a/external/speex/src/vorbis_psy.c b/external/speex/src/vorbis_psy.c new file mode 100644 index 0000000..a054158 --- /dev/null +++ b/external/speex/src/vorbis_psy.c @@ -0,0 +1,513 @@ +/* Copyright (C) 2005 Jean-Marc Valin, CSIRO, Christopher Montgomery + File: vorbis_psy.c + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef VORBIS_PSYCHO + +#include "arch.h" +#include "smallft.h" +#include "lpc.h" +#include "vorbis_psy.h" +#include "os_support.h" + +#include +#include +#include + +/* psychoacoustic setup ********************************************/ + +static VorbisPsyInfo example_tuning = { + + .5,.5, + 3,3,25, + + /*63 125 250 500 1k 2k 4k 8k 16k*/ + // vorbis mode 4 style + //{-32,-32,-32,-32,-28,-24,-22,-20,-20, -20, -20, -8, -6, -6, -6, -6, -6}, + { -4, -6, -6, -6, -6, -6, -6, -6, -8, -8,-10,-10, -8, -6, -4, -4, -2}, + + { + 0, 1, 2, 3, 4, 5, 5, 5, /* 7dB */ + 6, 6, 6, 5, 4, 4, 4, 4, /* 15dB */ + 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ + 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ + 11,12,13,14,15,16,17, 18, /* 39dB */ + } + +}; + + + +/* there was no great place to put this.... */ +#include +static void _analysis_output(char *base,int i,float *v,int n,int bark,int dB){ + int j; + FILE *of; + char buffer[80]; + + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); + + if(!of)perror("failed to open data dump file"); + + for(j=0;j> 16; + if( lo>=0 ) break; + hi = b[i] & 0xffff; + + tN = N[hi] + N[-lo]; + tX = X[hi] - X[-lo]; + tXX = XX[hi] + XX[-lo]; + tY = Y[hi] + Y[-lo]; + tXY = XY[hi] - XY[-lo]; + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + if (R < 0.f) + R = 0.f; + + noise[i] = R - offset; + } + + for ( ;; i++, x += 1.f) { + + lo = b[i] >> 16; + hi = b[i] & 0xffff; + if(hi>=n)break; + + tN = N[hi] - N[lo]; + tX = X[hi] - X[lo]; + tXX = XX[hi] - XX[lo]; + tY = Y[hi] - Y[lo]; + tXY = XY[hi] - XY[lo]; + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + if (R < 0.f) R = 0.f; + + noise[i] = R - offset; + } + for ( ; i < n; i++, x += 1.f) { + + R = (A + x * B) / D; + if (R < 0.f) R = 0.f; + + noise[i] = R - offset; + } + + if (fixed <= 0) return; + + for (i = 0, x = 0.f;; i++, x += 1.f) { + hi = i + fixed / 2; + lo = hi - fixed; + if(lo>=0)break; + + tN = N[hi] + N[-lo]; + tX = X[hi] - X[-lo]; + tXX = XX[hi] + XX[-lo]; + tY = Y[hi] + Y[-lo]; + tXY = XY[hi] - XY[-lo]; + + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + + if (R - offset < noise[i]) noise[i] = R - offset; + } + for ( ;; i++, x += 1.f) { + + hi = i + fixed / 2; + lo = hi - fixed; + if(hi>=n)break; + + tN = N[hi] - N[lo]; + tX = X[hi] - X[lo]; + tXX = XX[hi] - XX[lo]; + tY = Y[hi] - Y[lo]; + tXY = XY[hi] - XY[lo]; + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + + if (R - offset < noise[i]) noise[i] = R - offset; + } + for ( ; i < n; i++, x += 1.f) { + R = (A + x * B) / D; + if (R - offset < noise[i]) noise[i] = R - offset; + } +} + +static void _vp_noisemask(VorbisPsy *p, + float *logfreq, + float *logmask){ + + int i,n=p->n/2; + float *work=alloca(n*sizeof(*work)); + + bark_noise_hybridmp(n,p->bark,logfreq,logmask, + 140.,-1); + + for(i=0;ibark,work,logmask,0., + p->vi->noisewindowfixed); + + for(i=0;i=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1; + if(dB<0)dB=0; + logmask[i]= work[i]+p->vi->noisecompand[dB]+p->noiseoffset[i]; + } + +} + +VorbisPsy *vorbis_psy_init(int rate, int n) +{ + long i,j,lo=-99,hi=1; + VorbisPsy *p = speex_alloc(sizeof(VorbisPsy)); + memset(p,0,sizeof(*p)); + + p->n = n; + spx_drft_init(&p->lookup, n); + p->bark = speex_alloc(n*sizeof(*p->bark)); + p->rate=rate; + p->vi = &example_tuning; + + /* BH4 window */ + p->window = speex_alloc(sizeof(*p->window)*n); + float a0 = .35875f; + float a1 = .48829f; + float a2 = .14128f; + float a3 = .01168f; + for(i=0;iwindow[i] = //a0 - a1*cos(2.*M_PI/n*(i+.5)) + a2*cos(4.*M_PI/n*(i+.5)) - a3*cos(6.*M_PI/n*(i+.5)); + sin((i+.5)/n * M_PI)*sin((i+.5)/n * M_PI); + /* bark scale lookups */ + for(i=0;ivi->noisewindowlominvi->noisewindowlo);lo++); + + for(;hi<=n && (hivi->noisewindowhimin || + toBARK(rate/(2*n)*hi)<(bark+p->vi->noisewindowhi));hi++); + + p->bark[i]=((lo-1)<<16)+(hi-1); + + } + + /* set up rolling noise median */ + p->noiseoffset=speex_alloc(n*sizeof(*p->noiseoffset)); + + for(i=0;i=P_BANDS-1)halfoc=P_BANDS-1; + inthalfoc=(int)halfoc; + /*If we hit the P_BANDS-1 clamp above, inthalfoc+1 will be out of bounds, + even though it will have an interpolation weight of 0. + Shift the interval so we don't read past the end of the array.*/ + if(inthalfoc>=P_BANDS-2)inthalfoc=P_BANDS-2; + del=halfoc-inthalfoc; + + p->noiseoffset[i]= + p->vi->noiseoff[inthalfoc]*(1.-del) + + p->vi->noiseoff[inthalfoc+1]*del; + + } +#if 0 + _analysis_output_always("noiseoff0",ls,p->noiseoffset,n,1,0,0); +#endif + + return p; +} + +void vorbis_psy_destroy(VorbisPsy *p) +{ + if(p){ + spx_drft_clear(&p->lookup); + if(p->bark) + speex_free(p->bark); + if(p->noiseoffset) + speex_free(p->noiseoffset); + if(p->window) + speex_free(p->window); + memset(p,0,sizeof(*p)); + speex_free(p); + } +} + +void compute_curve(VorbisPsy *psy, float *audio, float *curve) +{ + int i; + float work[psy->n]; + + float scale=4.f/psy->n; + float scale_dB; + + scale_dB=todB(scale); + + /* window the PCM data; use a BH4 window, not vorbis */ + for(i=0;in;i++) + work[i]=audio[i] * psy->window[i]; + + { + static int seq=0; + + //_analysis_output("win",seq,work,psy->n,0,0); + + seq++; + } + + /* FFT yields more accurate tonal estimation (not phase sensitive) */ + spx_drft_forward(&psy->lookup,work); + + /* magnitudes */ + work[0]=scale_dB+todB(work[0]); + for(i=1;in-1;i+=2){ + float temp = work[i]*work[i] + work[i+1]*work[i+1]; + work[(i+1)>>1] = scale_dB+.5f * todB(temp); + } + + /* derive a noise curve */ + _vp_noisemask(psy,work,curve); +#define SIDEL 12 + for (i=0;in>>1)-i-1]=curve[(psy->n>>1)-SIDEH]; + } + for(i=0;i<((psy->n)>>1);i++) + curve[i] = fromdB(1.2*curve[i]+.2*i); + //curve[i] = fromdB(0.8*curve[i]+.35*i); + //curve[i] = fromdB(0.9*curve[i])*pow(1.0*i+45,1.3); +} + +/* Transform a masking curve (power spectrum) into a pole-zero filter */ +void curve_to_lpc(VorbisPsy *psy, float *curve, float *awk1, float *awk2, int ord) +{ + int i; + float ac[psy->n]; + float tmp; + int len = psy->n >> 1; + for (i=0;i<2*len;i++) + ac[i] = 0; + for (i=1;ilookup, ac); + _spx_lpc(awk1, ac, ord); + tmp = 1.; + for (i=0;ilookup, ac); + /* Compute (power) response of awk1 (all zero) */ + ac[0] *= ac[0]; + for (i=1;ilookup, ac); + _spx_lpc(awk2, ac, ord); + tmp = 1; + for (i=0;i +#include + +#define ORDER 10 +#define CURVE_SIZE 24 + +int main() +{ + int i; + float curve[CURVE_SIZE]; + float awk1[ORDER], awk2[ORDER]; + for (i=0;i1e-13?log((x)*(x))*4.34294480f:-30) +#define fromdB(x) (exp((x)*.11512925f)) + +/* The bark scale equations are approximations, since the original + table was somewhat hand rolled. The below are chosen to have the + best possible fit to the rolled tables, thus their somewhat odd + appearance (these are more accurate and over a longer range than + the oft-quoted bark equations found in the texts I have). The + approximations are valid from 0 - 30kHz (nyquist) or so. + + all f in Hz, z in Bark */ + +#define toBARK(n) (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n)) +#define fromBARK(z) (102.f*(z)-2.f*pow(z,2.f)+.4f*pow(z,3.f)+pow(1.46f,z)-1.f) + +/* Frequency to octave. We arbitrarily declare 63.5 Hz to be octave + 0.0 */ + +#define toOC(n) (log(n)*1.442695f-5.965784f) +#define fromOC(o) (exp(((o)+5.965784f)*.693147f)) + + +typedef struct { + + float noisewindowlo; + float noisewindowhi; + int noisewindowlomin; + int noisewindowhimin; + int noisewindowfixed; + float noiseoff[P_BANDS]; + float noisecompand[NOISE_COMPAND_LEVELS]; + +} VorbisPsyInfo; + + + +typedef struct { + int n; + int rate; + struct drft_lookup lookup; + VorbisPsyInfo *vi; + + float *window; + float *noiseoffset; + long *bark; + +} VorbisPsy; + + +VorbisPsy *vorbis_psy_init(int rate, int size); +void vorbis_psy_destroy(VorbisPsy *psy); +void compute_curve(VorbisPsy *psy, float *audio, float *curve); +void curve_to_lpc(VorbisPsy *psy, float *curve, float *awk1, float *awk2, int ord); + +#endif +#endif diff --git a/external/speex/src/vq.c b/external/speex/src/vq.c index ed36f7d..c7f1396 100644 --- a/external/speex/src/vq.c +++ b/external/speex/src/vq.c @@ -5,18 +5,18 @@ 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 @@ -30,42 +30,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "vq.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -/*Finds the index of the entry in a codebook that best matches the input*/ -int vq_index(float *in, float *codebook, int len, int entries) +#include "vq.h" +#include "stack_alloc.h" +#include "arch.h" + +#ifdef _USE_SSE +#include +#include "vq_sse.h" +#elif defined(SHORTCUTS) && (defined(ARM4_ASM) || defined(ARM5E_ASM)) +#include "vq_arm4.h" +#elif defined(BFIN_ASM) +#include "vq_bfin.h" +#endif + +#ifndef DISABLE_ENCODER +int scal_quant(spx_word16_t in, const spx_word16_t *boundary, int entries) { - int i,j; - float min_dist=0; - int best_index=0; - for (i=0;iboundary[0]) { - float dist=0; - for (j=0;jboundary[0]) + { + boundary++; + i++; + } + return i; +} +#endif /* DISABLE_ENCODER */ +#if !defined(OVERRIDE_VQ_NBEST) && !defined(DISABLE_ENCODER) /*Finds the indices of the n-best entries in a codebook*/ -void vq_nbest(float *in, float *codebook, int len, int entries, float *E, int N, int *nbest, float *best_dist) +void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) { int i,j,k,used; used = 0; for (i=0;i= 1) && (k > used || dist < best_dist[k-1]); k--) @@ -79,26 +100,35 @@ void vq_nbest(float *in, float *codebook, int len, int entries, float *E, int N, } } } +#endif /* !defined(OVERRIDE_VQ_NBEST) && !defined(DISABLE_ENCODER) */ + + + +#if !defined(OVERRIDE_VQ_NBEST_SIGN) && !defined(DISABLE_WIDEBAND) && !defined(DISABLE_ENCODER) /*Finds the indices of the n-best entries in a codebook with sign*/ -void vq_nbest_sign(float *in, float *codebook, int len, int entries, float *E, int N, int *nbest, float *best_dist) +void vq_nbest_sign(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) { int i,j,k, sign, used; used=0; for (i=0;i0) { - sign=1; + sign=0; dist=-dist; } else { - sign=0; + sign=1; } - dist += .5*E[i]; +#ifdef FIXED_POINT + dist = ADD32(dist,SHR32(E[i],1)); +#else + dist = ADD32(dist,.5f*E[i]); +#endif if (i= 1) && (k > used || dist < best_dist[k-1]); k--) @@ -114,3 +144,4 @@ void vq_nbest_sign(float *in, float *codebook, int len, int entries, float *E, i } } } +#endif /* !defined(OVERRIDE_VQ_NBEST_SIGN) && !defined(DISABLE_WIDEBAND) && !defined(DISABLE_ENCODER) */ diff --git a/external/speex/src/vq.h b/external/speex/src/vq.h index e82ba6c..5c707f0 100644 --- a/external/speex/src/vq.h +++ b/external/speex/src/vq.h @@ -1,22 +1,24 @@ -/* Copyright (C) 2002 Jean-Marc Valin - File: vq.h - Vector quantization - +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file vq.h + @brief Vector quantization +*/ +/* 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 @@ -33,10 +35,20 @@ #ifndef VQ_H #define VQ_H -int vq_index(float *in, float *codebook, int len, int entries); +#include "arch.h" -void vq_nbest(float *in, float *codebook, int len, int entries, float *E, int N, int *nbest, float *best_dist); +int scal_quant(spx_word16_t in, const spx_word16_t *boundary, int entries); +int scal_quant32(spx_word32_t in, const spx_word32_t *boundary, int entries); -void vq_nbest_sign(float *in, float *codebook, int len, int entries, float *E, int N, int *nbest, float *best_dist); +#ifdef _USE_SSE +#include +void vq_nbest(spx_word16_t *in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); + +void vq_nbest_sign(spx_word16_t *in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); +#else +void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); + +void vq_nbest_sign(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack); +#endif #endif diff --git a/external/speex/src/vq_arm4.h b/external/speex/src/vq_arm4.h new file mode 100644 index 0000000..957e195 --- /dev/null +++ b/external/speex/src/vq_arm4.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2004 Jean-Marc Valin */ +/** + @file vq_arm4.h + @brief ARM4-optimized vq routine +*/ +/* + 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. +*/ + +#define OVERRIDE_VQ_NBEST +void vq_nbest(spx_word16_t *in, const spx_word16_t *codebook, int len, int entries, spx_word32_t *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) +{ + int i,j; + for (i=0;i>= 1;\n\t" + "A0 = %0;\n\t" + "R0.L = W[%1++%7] || R1.L = W[I0++];\n\t" + "LOOP vq_loop%= LC1 = %5;\n\t" + "LOOP_BEGIN vq_loop%=;\n\t" + "%0 = (A0 -= R0.L*R1.L) (IS) || R0.L = W[%1++%7] || R1.L = W[I0++];\n\t" + "LOOP_END vq_loop%=;\n\t" + "%0 = (A0 -= R0.L*R1.L) (IS);\n\t" + "cc = %0 < %2;\n\t" + "if cc %2 = %0;\n\t" + "if cc %3 = R2;\n\t" + "R2 += 1;\n\t" + "LOOP_END entries_loop%=;\n\t" + : "=&D" (dist), "=&a" (codebook), "=&d" (best_dist[0]), "=&d" (nbest[0]), "=&a" (E) + : "a" (len-1), "a" (in), "a" (2), "d" (entries), "d" (len<<1), "1" (codebook), "4" (E), "2" (best_dist[0]), "3" (nbest[0]) + : "R0", "R1", "R2", "I0", "L0", "B0", "A0", "cc", "memory", + "ASTAT" BFIN_HWLOOP0_REGS BFIN_HWLOOP1_REGS + ); + } + } else { + int i,k,used; + used = 0; + for (i=0;i>= 1;\n\t" + "A0 = %0;\n\t" + "I0 = %3;\n\t" + "L0 = 0;\n\t" + "R0.L = W[%1++%4] || R1.L = W[I0++];\n\t" + "LOOP vq_loop%= LC0 = %2;\n\t" + "LOOP_BEGIN vq_loop%=;\n\t" + "%0 = (A0 -= R0.L*R1.L) (IS) || R0.L = W[%1++%4] || R1.L = W[I0++];\n\t" + "LOOP_END vq_loop%=;\n\t" + "%0 = (A0 -= R0.L*R1.L) (IS);\n\t" + : "=D" (dist), "=a" (codebook) + : "a" (len-1), "a" (in), "a" (2), "1" (codebook), "0" (E[i]) + : "R0", "R1", "I0", "L0", "A0", "ASTAT" BFIN_HWLOOP0_REGS + ); + if (i= 1) && (k > used || dist < best_dist[k-1]); k--) + { + best_dist[k]=best_dist[k-1]; + nbest[k] = nbest[k-1]; + } + best_dist[k]=dist; + nbest[k]=i; + used++; + } + } + } +} diff --git a/external/speex/src/vq_sse.h b/external/speex/src/vq_sse.h new file mode 100644 index 0000000..2abe880 --- /dev/null +++ b/external/speex/src/vq_sse.h @@ -0,0 +1,120 @@ +/* Copyright (C) 2004 Jean-Marc Valin */ +/** + @file vq_sse.h + @brief SSE-optimized vq routine +*/ +/* + 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. +*/ + +#define OVERRIDE_VQ_NBEST +void vq_nbest(spx_word16_t *_in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) +{ + int i,j,k,used; + VARDECL(float *dist); + VARDECL(__m128 *in); + __m128 half; + used = 0; + ALLOC(dist, entries, float); + half = _mm_set_ps1(.5f); + ALLOC(in, len, __m128); + for (i=0;i>2;i++) + { + __m128 d = _mm_mul_ps(E[i], half); + for (j=0;j= 1) && (k > used || dist[i] < best_dist[k-1]); k--) + { + best_dist[k]=best_dist[k-1]; + nbest[k] = nbest[k-1]; + } + best_dist[k]=dist[i]; + nbest[k]=i; + used++; + } + } +} + + + + +#define OVERRIDE_VQ_NBEST_SIGN +void vq_nbest_sign(spx_word16_t *_in, const __m128 *codebook, int len, int entries, __m128 *E, int N, int *nbest, spx_word32_t *best_dist, char *stack) +{ + int i,j,k,used; + VARDECL(float *dist); + VARDECL(__m128 *in); + + used = 0; + ALLOC(dist, entries, float); + + ALLOC(in, len, __m128); + for (i=0;i>2;i++) + { + __m128 d = _mm_setzero_ps(); + for (j=0;j0) + { + sign=0; + dist[i]=-dist[i]; + } else + { + sign=1; + } + dist[i] += .5f*((float*)E)[i]; + if (i= 1) && (k > used || dist[i] < best_dist[k-1]); k--) + { + best_dist[k]=best_dist[k-1]; + nbest[k] = nbest[k-1]; + } + best_dist[k]=dist[i]; + nbest[k]=i; + used++; + if (sign) + nbest[k]+=entries; + } + } +} diff --git a/external/speex/src/window.c b/external/speex/src/window.c new file mode 100644 index 0000000..a89d4d7 --- /dev/null +++ b/external/speex/src/window.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 Jean-Marc Valin + File: window.c + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "arch.h" + +#ifdef FIXED_POINT +const spx_word16_t lag_window[11] = { + 32767, 32675, 32397, 31940, 31311, 30520, 29581, 28508, 27318, 26029, 24661 +}; + +const spx_word16_t lpc_window[200] = { +2621, 2627, 2642, 2668, 2704, 2750, 2807, 2874, +2951, 3038, 3135, 3242, 3359, 3486, 3623, 3769, +3925, 4090, 4264, 4448, 4641, 4843, 5053, 5272, +5500, 5736, 5981, 6233, 6493, 6761, 7036, 7319, +7609, 7905, 8209, 8519, 8835, 9157, 9485, 9819, +10158, 10502, 10852, 11206, 11564, 11926, 12293, 12663, +13037, 13414, 13793, 14176, 14561, 14948, 15337, 15727, +16119, 16512, 16906, 17300, 17695, 18089, 18484, 18877, +19270, 19662, 20053, 20442, 20829, 21214, 21596, 21976, +22353, 22726, 23096, 23463, 23826, 24184, 24538, 24887, +25231, 25570, 25904, 26232, 26555, 26871, 27181, 27484, +27781, 28070, 28353, 28628, 28896, 29157, 29409, 29653, +29889, 30117, 30336, 30547, 30749, 30941, 31125, 31300, +31465, 31621, 31767, 31903, 32030, 32147, 32254, 32352, +32439, 32516, 32582, 32639, 32685, 32722, 32747, 32763, +32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, +32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, +32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, +32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, +32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, +32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, +32767, 32767, 32767, 32723, 32590, 32368, 32058, 31661, +31177, 30610, 29959, 29227, 28416, 27528, 26566, 25532, +24430, 23263, 22034, 20747, 19406, 18015, 16579, 15104, +13594, 12058, 10503, 8941, 7391, 5887, 4498, 3392 +}; +#else +const spx_word16_t lag_window[11] = { + 1.00000f, 0.99716f, 0.98869f, 0.97474f, 0.95554f, 0.93140f, 0.90273f, 0.86998f, 0.83367f, 0.79434f, 0.75258f +}; + +const spx_word16_t lpc_window[200] = { + 0.080000f, 0.080158f, 0.080630f, 0.081418f, 0.082520f, 0.083935f, 0.085663f, 0.087703f, + 0.090052f, 0.092710f, 0.095674f, 0.098943f, 0.102514f, 0.106385f, 0.110553f, 0.115015f, + 0.119769f, 0.124811f, 0.130137f, 0.135744f, 0.141628f, 0.147786f, 0.154212f, 0.160902f, + 0.167852f, 0.175057f, 0.182513f, 0.190213f, 0.198153f, 0.206328f, 0.214731f, 0.223357f, + 0.232200f, 0.241254f, 0.250513f, 0.259970f, 0.269619f, 0.279453f, 0.289466f, 0.299651f, + 0.310000f, 0.320507f, 0.331164f, 0.341965f, 0.352901f, 0.363966f, 0.375151f, 0.386449f, + 0.397852f, 0.409353f, 0.420943f, 0.432615f, 0.444361f, 0.456172f, 0.468040f, 0.479958f, + 0.491917f, 0.503909f, 0.515925f, 0.527959f, 0.540000f, 0.552041f, 0.564075f, 0.576091f, + 0.588083f, 0.600042f, 0.611960f, 0.623828f, 0.635639f, 0.647385f, 0.659057f, 0.670647f, + 0.682148f, 0.693551f, 0.704849f, 0.716034f, 0.727099f, 0.738035f, 0.748836f, 0.759493f, + 0.770000f, 0.780349f, 0.790534f, 0.800547f, 0.810381f, 0.820030f, 0.829487f, 0.838746f, + 0.847800f, 0.856643f, 0.865269f, 0.873672f, 0.881847f, 0.889787f, 0.897487f, 0.904943f, + 0.912148f, 0.919098f, 0.925788f, 0.932214f, 0.938372f, 0.944256f, 0.949863f, 0.955189f, + 0.960231f, 0.964985f, 0.969447f, 0.973615f, 0.977486f, 0.981057f, 0.984326f, 0.987290f, + 0.989948f, 0.992297f, 0.994337f, 0.996065f, 0.997480f, 0.998582f, 0.999370f, 0.999842f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 0.998640f, 0.994566f, 0.987787f, 0.978324f, 0.966203f, + 0.951458f, 0.934131f, 0.914270f, 0.891931f, 0.867179f, 0.840084f, 0.810723f, 0.779182f, + 0.745551f, 0.709930f, 0.672424f, 0.633148f, 0.592223f, 0.549781f, 0.505964f, 0.460932f, + 0.414863f, 0.367968f, 0.320511f, 0.272858f, 0.225569f, 0.179655f, 0.137254f, 0.103524f +}; +#endif