diff --git a/.gitignore b/.gitignore index 7fda018..d24ec41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,43 +1,15 @@ -# Compiled Object files -*.slo -*.lo -*.o -*.obj +**/build +**/.gradle +.idea +*.iml +**/msvc/Debug* +**/msvc/Release* +**/msvc/*.sdf +**/msvc/*.opensdf +**/msvc/*.user +**/msvc/*.suo +**/msvc/*.aps +**/msvc/ipch -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.app - -# MSVS user-scoped config files -*.user - -# MSVS internal -*.sdf -*.opensdf -*.suo - -msvc/ipch -msvc/Debug -msvc/Release - -dep/silk/msvc/Debug -dep/silk/msvc/Release - -revoice/msvc/Debug -revoice/msvc/Release \ No newline at end of file +publish +**/appversion.h diff --git a/dep/speex/include/cb_search.h b/dep/speex/include/cb_search.h new file mode 100644 index 0000000..dea5589 --- /dev/null +++ b/dep/speex/include/cb_search.h @@ -0,0 +1,95 @@ +/* Copyright (C) 2002 Jean-Marc Valin & David Rowe + File: cb_search.c + Overlapped codebook search + + 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 CB_SEARCH_H +#define CB_SEARCH_H + +#include "speex_bits.h" + +typedef struct split_cb_params { + int subvect_size; + int nb_subvect; + signed char *shape_cb; + int shape_bits; + int have_sign; +} split_cb_params; + + +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*/ +int p, /* number of LPC coeffs */ +int nsf, /* number of samples in subframe */ +float *exc, +float *r, +SpeexBits *bits, +char *stack, +int complexity +); + +void split_cb_shape_sign_unquant( +float *exc, +void *par, /* non-overlapping codebook */ +int nsf, /* number of samples in subframe */ +SpeexBits *bits, +char *stack +); + + +void noise_codebook_quant( +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*/ +int p, /* number of LPC coeffs */ +int nsf, /* number of samples in subframe */ +float *exc, +float *r, +SpeexBits *bits, +char *stack, +int complexity +); + + +void noise_codebook_unquant( +float *exc, +void *par, /* non-overlapping codebook */ +int nsf, /* number of samples in subframe */ +SpeexBits *bits, +char *stack +); + +#endif diff --git a/dep/speex/include/filters.h b/dep/speex/include/filters.h new file mode 100644 index 0000000..ad6dc02 --- /dev/null +++ b/dep/speex/include/filters.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: filters.h + Various analysis/synthesis filters + + 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 FILTERS_H +#define FILTERS_H + + +typedef struct CombFilterMem { + int last_pitch; + float last_pitch_gain[3]; + float smooth_gain; +} CombFilterMem; + + +void qmf_decomp(float *xx, float *aa, float *y1, float *y2, int N, int M, float *mem, char *stack); +void fir_mem_up(float *x, float *a, float *y, int N, int M, float *mem, char *stack); + + +void filter_mem2(float *x, float *num, float *den, float *y, int N, int ord, float *mem); +void fir_mem2(float *x, float *num, float *y, int N, int ord, float *mem); +void iir_mem2(float *x, float *den, float *y, int N, int ord, float *mem); + +/* Apply bandwidth expansion on LPC coef */ +void bw_lpc(float gamma, float *lpc_in, float *lpc_out, int order); + + + +/* FIR filter */ +void fir_decim_mem(float *x, float *a, float *y, int N, int M, float *mem); + +void syn_percep_zero(float *x, float *ak, float *awk1, float *awk2, float *y, int N, int ord, char *stack); + +void residue_percep_zero(float *xx, float *ak, float *awk1, float *awk2, float *y, int N, int ord, char *stack); + +void comp_filter_mem_init (CombFilterMem *mem); + +void comb_filter( +float *exc, /*decoded excitation*/ +float *new_exc, /*enhanced excitation*/ +float *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 +); + + +#endif diff --git a/dep/speex/include/filters_sse.h b/dep/speex/include/filters_sse.h new file mode 100644 index 0000000..3fba6c8 --- /dev/null +++ b/dep/speex/include/filters_sse.h @@ -0,0 +1,289 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: filters.c + Various analysis/synthesis filters + + 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. +*/ + +void filter_mem2(float *x, float *_num, float *_den, float *y, int N, int ord, float *_mem) +{ + float __num[20], __den[20], __mem[20]; + float *num, *den, *mem; + 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 + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {966DE7A9-EC15-4C1D-8B46-EA813A845723} + Win32Proj + Speex + + + + StaticLibrary + true + v120 + MultiByte + + + StaticLibrary + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + TurnOffAllWarnings + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + $(ProjectDir)../src/;$(ProjectDir)../include/;%(AdditionalIncludeDirectories) + + + Windows + true + + + + + TurnOffAllWarnings + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + $(ProjectDir)../src/;$(ProjectDir)../include/;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/dep/speex/msvc/Speex.vcxproj.filters b/dep/speex/msvc/Speex.vcxproj.filters new file mode 100644 index 0000000..34139fd --- /dev/null +++ b/dep/speex/msvc/Speex.vcxproj.filters @@ -0,0 +1,165 @@ + + + + + {64149522-0cdb-49e1-b9f5-d3c89ac3cd33} + + + {1b002234-71db-4d9c-8d15-0e5efed1c3b6} + + + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + \ No newline at end of file diff --git a/dep/speex/src/bits.c b/dep/speex/src/bits.c new file mode 100644 index 0000000..68285e0 --- /dev/null +++ b/dep/speex/src/bits.c @@ -0,0 +1,352 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: speex_bits.c + + Handles bit packing/unpacking + + 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 "speex_bits.h" +#include "misc.h" + +void speex_bits_init(SpeexBits *bits) +{ + int i; + bits->bytes = (char*)speex_alloc(MAX_BYTES_PER_FRAME); + bits->buf_size = MAX_BYTES_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; +} + +void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) +{ + int i; + bits->bytes = (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; +} + +void speex_bits_destroy(SpeexBits *bits) +{ + if (bits->owner) + speex_free(bits->bytes); + /* Will do something once the allocation is dynamic */ +} + +void speex_bits_reset(SpeexBits *bits) +{ + int i; + for (i=0;ibuf_size;i++) + bits->bytes[i]=0; + bits->nbBits=0; + bits->bytePtr=0; + bits->bitPtr=0; + bits->overflow=0; +} + +void speex_bits_rewind(SpeexBits *bits) +{ + bits->bytePtr=0; + bits->bitPtr=0; + bits->overflow=0; +} + +void speex_bits_read_from(SpeexBits *bits, char *bytes, int len) +{ + int i; + if (len > bits->buf_size) + { + speex_warning_int("Packet if larger than allocated buffer: ", len); + if (bits->owner) + { + char *tmp = (char*)speex_realloc(bits->bytes, len); + if (tmp) + { + bits->buf_size=len; + bits->bytes=tmp; + } else { + len=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; + } + } + for (i=0;ibytes[i]=bytes[i]; + bits->nbBits=len<<3; + bits->bytePtr=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; +} + +void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len) +{ + int i,pos; + + if ((bits->nbBits>>3)+len+1 > bits->buf_size) + { + speex_warning_int("Packet if larger than allocated buffer: ", len); + if (bits->owner) + { + char *tmp = (char*)speex_realloc(bits->bytes, (bits->nbBits>>3)+len+1); + if (tmp) + { + bits->buf_size=(bits->nbBits>>3)+len+1; + bits->bytes=tmp; + } else { + len=bits->buf_size-(bits->nbBits>>3)-1; + speex_warning("Could not resize input buffer: truncating input"); + } + } else { + speex_warning("Do not own input buffer: truncating input"); + len=bits->buf_size; + } + } + + speex_bits_flush(bits); + pos=bits->nbBits>>3; + for (i=0;ibytes[pos+i]=bytes[i]; + bits->nbBits+=len<<3; +} + +int speex_bits_write(SpeexBits *bits, char *bytes, int max_len) +{ + int i; + if (max_len > ((bits->nbBits+7)>>3)) + max_len = ((bits->nbBits+7)>>3); + for (i=0;ibytes[i]; + return max_len; +} + +int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len) +{ + int i; + if (max_len > ((bits->nbBits)>>3)) + max_len = ((bits->nbBits)>>3); + for (i=0;ibytes[i]; + + if (bits->bitPtr>0) + bits->bytes[0]=bits->bytes[max_len]; + 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; +} + + +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) + { + speex_warning("Buffer too small to pack bits"); + if (bits->owner) + { + char *tmp = (char*)speex_realloc(bits->bytes, ((bits->buf_size+5)*3)>>1); + 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; + } else { + speex_warning("Could not resize input buffer: not packing"); + return; + } + } else { + speex_warning("Do not own input buffer: not packing"); + return; + } + } + + while(nbBits) + { + int bit; + bit = (d>>(nbBits-1))&1; + bits->bytes[bits->bytePtr] |= bit<<(7-bits->bitPtr); + bits->bitPtr++; + + if (bits->bitPtr==8) + { + bits->bitPtr=0; + bits->bytePtr++; + } + bits->nbBits++; + nbBits--; + } +} + +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) + bits->overflow=1; + if (bits->overflow) + return 0; + while(nbBits) + { + d<<=1; + d |= (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1; + bits->bitPtr++; + if (bits->bitPtr==8) + { + bits->bitPtr=0; + bits->bytePtr++; + } + nbBits--; + } + return d; +} + +unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) +{ + unsigned int d=0; + int bitPtr, bytePtr; + char *bytes; + + if ((bits->bytePtr<<3)+bits->bitPtr+nbBits>bits->nbBits) + bits->overflow=1; + if (bits->overflow) + return 0; + + bitPtr=bits->bitPtr; + bytePtr=bits->bytePtr; + bytes = bits->bytes; + while(nbBits) + { + d<<=1; + d |= (bytes[bytePtr]>>(7-bitPtr))&1; + bitPtr++; + if (bitPtr==8) + { + bitPtr=0; + bytePtr++; + } + nbBits--; + } + return d; +} + +int speex_bits_peek(SpeexBits *bits) +{ + if ((bits->bytePtr<<3)+bits->bitPtr+1>bits->nbBits) + bits->overflow=1; + if (bits->overflow) + return 0; + return (bits->bytes[bits->bytePtr]>>(7-bits->bitPtr))&1; +} + +void speex_bits_advance(SpeexBits *bits, int n) +{ + int nbytes, nbits; + + if ((bits->bytePtr<<3)+bits->bitPtr+n>bits->nbBits) + 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++; + } +} + +int speex_bits_remaining(SpeexBits *bits) +{ + if (bits->overflow) + return -1; + else + return bits->nbBits-((bits->bytePtr<<3)+bits->bitPtr); +} + +int speex_bits_nbytes(SpeexBits *bits) +{ + return ((bits->nbBits+7)>>3); +} + +void speex_bits_insert_terminator(SpeexBits *bits) +{ + if (bits->bitPtr<7) + speex_bits_pack(bits, 0, 1); + while (bits->bitPtr<7) + speex_bits_pack(bits, 1, 1); +} diff --git a/dep/speex/src/cb_search.c b/dep/speex/src/cb_search.c new file mode 100644 index 0000000..785bb49 --- /dev/null +++ b/dep/speex/src/cb_search.c @@ -0,0 +1,387 @@ +/* Copyright (C) 2002 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 + 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 "cb_search.h" +#include "filters.h" +#include "stack_alloc.h" +#include "vq.h" +#include "misc.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*/ +int p, /* number of LPC coeffs */ +int nsf, /* number of samples in subframe */ +float *exc, +float *r, +SpeexBits *bits, +char *stack, +int complexity +) +{ + int i,j,k,m,n,q; + float *resp; + float *t, *e, *E, *r2; + float *tmp; + float *ndist, *odist; + int *itmp; + float **ot, **nt; + int **nind, **oind; + int *ind; + signed char *shape_cb; + int shape_cb_size, subvect_size, nb_subvect; + split_cb_params *params; + int N=2; + int *best_index; + float *best_dist; + int have_sign; + + N=complexity; + if (N>10) + 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; + 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); + + tmp = PUSH(stack, 2*N*nsf, float); + 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;qshape_bits+have_sign); + } + + /* Put everything back together */ + for (i=0;i=shape_cb_size) + { + sign=-1; + rind-=shape_cb_size; + } + + 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); + + /* Decode codewords and gains */ + for (i=0;ishape_bits); + } + /* Compute decoded excitation */ + for (i=0;i + + +void bw_lpc(float gamma, float *lpc_in, float *lpc_out, int order) +{ + int i; + float tmp=1; + for (i=0;i>1; + for (i=0;ilast_pitch=0; + mem->last_pitch_gain[0]=mem->last_pitch_gain[1]=mem->last_pitch_gain[2]=0; + mem->smooth_gain=1; +} + +void comb_filter( +float *exc, /*decoded excitation*/ +float *new_exc, /*enhanced excitation*/ +float *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 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; + } + step = 1.0/nsf; + fact=0; + /*Apply pitch comb-filter (filter out noise between pitch harmonics)*/ + 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] + ); + } + + 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; + } +} diff --git a/dep/speex/src/gain_table.c b/dep/speex/src/gain_table.c new file mode 100644 index 0000000..b1a2a7d --- /dev/null +++ b/dep/speex/src/gain_table.c @@ -0,0 +1,160 @@ +/* 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. + + 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. +*/ + +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}; diff --git a/dep/speex/src/gain_table_lbr.c b/dep/speex/src/gain_table_lbr.c new file mode 100644 index 0000000..1d6291a --- /dev/null +++ b/dep/speex/src/gain_table_lbr.c @@ -0,0 +1,64 @@ +/* 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. + + 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. +*/ + +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}; diff --git a/dep/speex/src/hexc_10_32_table.c b/dep/speex/src/hexc_10_32_table.c new file mode 100644 index 0000000..39ff1f9 --- /dev/null +++ b/dep/speex/src/hexc_10_32_table.c @@ -0,0 +1,66 @@ +/* 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 + 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. +*/ + +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/dep/speex/src/hexc_table.c b/dep/speex/src/hexc_table.c new file mode 100644 index 0000000..d7b2f51 --- /dev/null +++ b/dep/speex/src/hexc_table.c @@ -0,0 +1,162 @@ +/* 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 + 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. +*/ + +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, +}; diff --git a/dep/speex/src/high_lsp_tables.c b/dep/speex/src/high_lsp_tables.c new file mode 100644 index 0000000..90bea7a --- /dev/null +++ b/dep/speex/src/high_lsp_tables.c @@ -0,0 +1,163 @@ +/* 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. + + 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. +*/ + +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, +-40,-28,82,93,68,45,29,3, +-19,-47,-28,-43,-35,-30,-8,-13, +-39,-91,-91,-123,-96,10,10,-6, +-18,-55,-60,-91,-56,-36,-27,-16, +-48,-75,40,28,-10,-28,35,9, +37,19,1,-20,-31,-41,-18,-25, +-35,-68,-80,45,27,-1,47,13, +0,-29,-35,-57,-50,-79,-73,-38, +-19,5,35,14,-10,-23,16,-8, +5,-24,-40,-62,-23,-27,-22,-16, +-18,-46,-72,-77,43,21,33,1, +-80,-70,-70,-64,-56,-52,-39,-33, +-31,-38,-19,-19,-15,32,33,-2, +7,-15,-15,-24,-23,-33,-41,-56, +-24,-57,5,89,64,41,27,5, +-9,-47,-60,-97,-97,-124,-20,-9, +-44,-73,31,29,-4,64,48,7, +-35,-57,0,-3,-26,-47,-3,-6, +-40,-76,-79,-48,12,81,55,10, +9,-24,-43,-73,-57,-69,16,5, +-28,-53,18,29,20,0,-4,-11, +6,-13,23,7,-17,-35,-37,-37, +-30,-68,-63,6,24,-9,-14,3, +21,-13,-27,-57,-49,-80,-24,-41, +-5,-16,-5,1,45,25,12,-7, +3,-15,-6,-16,-15,-8,6,-13, +-42,-81,-80,-87,14,1,-10,-3, +-43,-69,-46,-24,-28,-29,36,6, +-43,-56,-12,12,54,79,43,9, +54,22,2,8,-12,-43,-46,-52, +-38,-69,-89,-5,75,38,33,5, +-13,-53,-62,-87,-89,-113,-99,-55, +-34,-37,62,55,33,16,21,-2, +-17,-46,-29,-38,-38,-48,-39,-42, +-36,-75,-72,-88,-48,-30,21,2, +-15,-57,-64,-98,-84,-76,25,1, +-46,-80,-12,18,-7,3,34,6, +38,31,23,4,-1,20,14,-15, +-43,-78,-91,-24,14,-3,54,16, +0,-27,-28,-44,-56,-83,-92,-89, +-3,34,56,41,36,22,20,-8, +-7,-35,-42,-62,-49,3,12,-10, +-50,-87,-96,-66,92,70,38,9, +-70,-71,-62,-42,-39,-43,-11,-7, +-50,-79,-58,-50,-31,32,31,-6, +-4,-25,7,-17,-38,-70,-58,-27, +-43,-83,-28,59,36,20,31,2, +-27,-71,-80,-109,-98,-75,-33,-32, +-31,-2,33,15,-6,43,33,-5, +0,-22,-10,-27,-34,-49,-11,-20, +-41,-91,-100,-121,-39,57,41,10, +-19,-50,-38,-59,-60,-70,-18,-20, +-8,-31,-8,-15,1,-14,-26,-25, +33,21,32,17,1,-19,-19,-26, +-58,-81,-35,-22,45,30,11,-11, +3,-26,-48,-87,-67,-83,-58,3, +-1,-26,-20,44,10,25,39,5, +-9,-35,-27,-38,7,10,4,-9, +-42,-85,-102,-127,52,44,28,10, +-47,-61,-40,-39,-17,-1,-10,-33, +-42,-74,-48,21,-4,70,52,10}; + + +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, +40,23,10,10,-46,-13,36,6, +4,-30,-29,62,32,-32,-1,22, +-14,1,-4,-22,-45,2,54,4, +-30,-57,-59,-12,27,-3,-31,8, +-9,5,10,-14,32,66,19,9, +2,-25,-37,23,-15,18,-38,-31, +5,-9,-21,15,0,22,62,30, +15,-12,-14,-46,77,21,33,3, +34,29,-19,50,2,11,9,-38, +-12,-37,62,1,-15,54,32,6, +2,-24,20,35,-21,2,19,24, +-13,55,4,9,39,-19,30,-1, +-21,73,54,33,8,18,3,15, +6,-19,-47,6,-3,-48,-50,1, +26,20,8,-23,-50,65,-14,-55, +-17,-31,-37,-28,53,-1,-17,-53, +1,57,11,-8,-25,-30,-37,64, +5,-52,-45,15,23,31,15,14, +-25,24,33,-2,-44,-56,-18,6, +-21,-43,4,-12,17,-37,20,-10, +34,15,2,15,55,21,-11,-31, +-6,46,25,16,-9,-25,-8,-62, +28,17,20,-32,-29,26,30,25, +-19,2,-16,-17,26,-51,2,50, +42,19,-66,23,29,-2,3,19, +-19,-37,32,15,6,30,-34,13, +11,-5,40,31,10,-42,4,-9, +26,-9,-70,17,-2,-23,20,-22, +-55,51,-24,-31,22,-22,15,-13, +3,-10,-28,-16,56,4,-63,11, +-18,-15,-18,-38,-35,16,-7,34, +-1,-21,-49,-47,9,-37,7,8, +69,55,20,6,-33,-45,-10,-9, +6,-9,12,71,15,-3,-42,-7, +-24,32,-35,-2,-42,-17,-5,0, +-2,-33,-54,13,-12,-34,47,23, +19,55,7,-8,74,31,14,16, +-23,-26,19,12,-18,-49,-28,-31, +-20,2,-14,-20,-47,78,40,13, +-23,-11,21,-6,18,1,47,5, +38,35,32,46,22,8,13,16, +-14,18,51,19,40,39,11,-26, +-1,-17,47,2,-53,-15,31,-22, +38,21,-15,-16,5,-33,53,15, +-38,86,11,-3,-24,49,13,-4, +-11,-18,28,20,-12,-27,-26,35, +-25,-35,-3,-20,-61,30,10,-55, +-12,-22,-52,-54,-14,19,-32,-12, +45,15,-8,-48,-9,11,-32,8, +-16,-34,-13,51,18,38,-2,-32, +-17,22,-2,-18,-28,-70,59,27, +-28,-19,-10,-20,-9,-9,-8,-21, +21,-8,35,-2,45,-3,-9,12, +0,30,7,-39,43,27,-38,-91, +30,26,19,-55,-4,63,14,-17, +13,9,13,2,7,4,6,61, +72,-1,-17,29,-1,-22,-17,8, +-28,-37,63,44,41,3,2,14, +9,-6,75,-8,-7,-12,-15,-12, +13,9,-4,30,-22,-65,15,0, +-45,4,-4,1,5,22,11,23}; diff --git a/dep/speex/src/lpc.c b/dep/speex/src/lpc.c new file mode 100644 index 0000000..9aec141 --- /dev/null +++ b/dep/speex/src/lpc.c @@ -0,0 +1,119 @@ +/* + Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, + Technische Universitaet Berlin + + Any use of this software is permitted provided that this notice is not + removed and that neither the authors nor the Technische Universitaet Berlin + are deemed to have made any representations as to the suitability of this + software for any purpose nor are held responsible for any defects of + this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + + As a matter of courtesy, the authors request to be informed about uses + this software has found, about bugs in this software, and about any + improvements that may be of general interest. + + Berlin, 28.11.1994 + Jutta Degener + Carsten Bormann + + + Code slightly 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 + 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. +*/ + + + +/* LPC- and Reflection Coefficients + * + * The next two functions calculate linear prediction coefficients + * and/or the related reflection coefficients from the first P_MAX+1 + * values of the autocorrelation function. + */ + +/* 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 + ) +{ + int i, j; float r, error = ac[0]; + + if (ac[0] == 0) { + for (i = 0; i < p; i++) ref[i] = 0; return 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. + */ + 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; + } + if (i % 2) lpc[j] += lpc[j] * r; + + error *= 1.0 - r * r; + } + return error; +} + + +/* 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 + */ +void _spx_autocorr( + const float * 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]; + ac[lag] = d; + } +} diff --git a/dep/speex/src/lsp.c b/dep/speex/src/lsp.c new file mode 100644 index 0000000..1af762c --- /dev/null +++ b/dep/speex/src/lsp.c @@ -0,0 +1,328 @@ +/*---------------------------------------------------------------------------*\ +Original copyright + FILE........: AKSLSPD.C + TYPE........: Turbo C + COMPANY.....: Voicetronix + AUTHOR......: David Rowe + DATE CREATED: 24/2/93 + +Modified by Jean-Marc Valin + + This file contains functions for converting Linear Prediction + Coefficients (LPC) to Line Spectral Pair (LSP) and back. Note that the + LSP coefficients are not in radians format but in the x domain of the + unit circle. + + 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 + 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 +#include "lsp.h" +#include "stack_alloc.h" + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: cheb_poly_eva() + + AUTHOR......: David Rowe + DATE CREATED: 24/2/93 + + This function evaluates a series of Chebyshev polynomials + +\*---------------------------------------------------------------------------*/ + + + +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 */ +{ + int i; + float *T,sum; + int m2=m>>1; + + /* Allocate memory for Chebyshev series formulation */ + T=PUSH(stack, m2+1, float); + + /* Initialise values */ + T[0]=1; + T[1]=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++) + { + T[i] = x*T[i-1] - T[i-2]; + sum += coef[m2-i] * T[i]; + } + + return sum; +} + + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: lpc_to_lsp() + + AUTHOR......: David Rowe + DATE CREATED: 24/2/93 + + This function converts LPC coefficients to LSP + coefficients. + +\*---------------------------------------------------------------------------*/ + + +int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) +/* float *a lpc coefficients */ +/* int lpcrdr order of LPC coefficients (10) */ +/* float *freq LSP frequencies in the x domain */ +/* int nb number of sub-intervals (4) */ +/* float delta grid spacing interval (0.02) */ + + +{ + + 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() + 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); + + /* 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)) */ + + px = P; /* initialise ptrs */ + 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++; + } + px = P; + qx = Q; + for(i=0;i= -1.0)){ + float dd; + /* Modified by JMV to provide smaller steps around x=+-1 */ + 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) */ + temp_psumr = psumr; + temp_xr = xr; + + /* if no sign change increment xr and re-evaluate poly(xr). Repeat til + sign change. + if a sign change has occurred the interval is bisected and then + checked again for a sign change which determines in which + interval the zero lies in. + If there is no sign change between poly(xm) and poly(xl) set interval + 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){ + 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.){ + psuml=psumm; + xl=xm; + } + else{ + psumr=psumm; + xr=xm; + } + } + + /* once zero is found, reset initial interval to xr */ + freq[j] = (xm); + xl = xm; + flag = 0; /* reset flag for next search */ + } + else{ + psuml=temp_psumr; + xl=temp_xr; + } + } + } + return(roots); +} + + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: lsp_to_lpc() + + AUTHOR......: David Rowe + DATE CREATED: 24/2/93 + + lsp_to_lpc: This function converts LSP coefficients to LPC + coefficients. + +\*---------------------------------------------------------------------------*/ + + +void lsp_to_lpc(float *freq,float *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; + float xout1,xout2,xin1,xin2; + float *Wp; + float *pw,*n1,*n2,*n3,*n4=NULL; + int m = lpcrdr/2; + + Wp = PUSH(stack, 4*m+2, float); + pw = Wp; + + /* initialise contents of array */ + + for(i=0;i<=4*m+1;i++){ /* set contents of buffer to 0 */ + *pw++ = 0.0; + } + + /* Set pointers up */ + + pw = Wp; + xin1 = 1.0; + xin2 = 1.0; + + /* reconstruct P(z) and Q(z) by cascading second order + polynomials in form 1 - 2xz(-1) +z(-2), where x is the + LSP coefficient */ + + for(j=0;j<=lpcrdr;j++){ + int i2=0; + for(i=0;iM_PI-margin) + lsp[len-1]=M_PI-margin; + for (i=1;ilsp[i+1]-margin) + lsp[i]= .5* (lsp[i] + lsp[i+1]-margin); + } +} diff --git a/dep/speex/src/lsp_tables_nb.c b/dep/speex/src/lsp_tables_nb.c new file mode 100644 index 0000000..a68ce99 --- /dev/null +++ b/dep/speex/src/lsp_tables_nb.c @@ -0,0 +1,360 @@ +/* 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. + + 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. +*/ + +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, +-14,-53,-77,-79,0,-3,-5,19,22,26, +-9,-53,-55,66,90,72,85,68,74,52, +-4,-41,-58,-31,-18,-31,27,32,30,18, +24,3,8,5,-12,-3,26,28,74,63, +-2,-39,-67,-77,-106,-74,59,59,73,65, +44,40,71,72,82,83,98,88,89,60, +-6,-31,-47,-48,-13,-39,-9,7,2,79, +-1,-39,-60,-17,87,81,65,50,45,19, +-21,-67,-91,-87,-41,-50,7,18,39,74, +10,-31,-28,39,24,13,23,5,56,45, +29,10,-5,-13,-11,-35,-18,-8,-10,-8, +-25,-71,-77,-21,2,16,50,63,87,87, +5,-32,-40,-51,-68,0,12,6,54,34, +5,-12,32,52,68,64,69,59,65,45, +14,-16,-31,-40,-65,-67,41,49,47,37, +-11,-52,-75,-84,-4,57,48,42,42,33, +-11,-51,-68,-6,13,0,8,-8,26,32, +-23,-53,0,36,56,76,97,105,111,97, +-1,-28,-39,-40,-43,-54,-44,-40,-18,35, +16,-20,-19,-28,-42,29,47,38,74,45, +3,-29,-48,-62,-80,-104,-33,56,59,59, +10,17,46,72,84,101,117,123,123,106, +-7,-33,-49,-51,-70,-67,-27,-31,70,67, +-16,-62,-85,-20,82,71,86,80,85,74, +-19,-58,-75,-45,-29,-33,-18,-25,45,57, +-12,-42,-5,12,28,36,52,64,81,82, +13,-9,-27,-28,22,3,2,22,26,6, +-6,-44,-51,2,15,10,48,43,49,34, +-19,-62,-84,-89,-102,-24,8,17,61,68, +39,24,23,19,16,-5,12,15,27,15, +-8,-44,-49,-60,-18,-32,-28,52,54,62, +-8,-48,-77,-70,66,101,83,63,61,37, +-12,-50,-75,-64,33,17,13,25,15,77, +1,-42,-29,72,64,46,49,31,61,44, +-8,-47,-54,-46,-30,19,20,-1,-16,0, +16,-12,-18,-9,-26,-27,-10,-22,53,45, +-10,-47,-75,-82,-105,-109,8,25,49,77, +50,65,114,117,124,118,115,96,90,61, +-9,-45,-63,-60,-75,-57,8,11,20,29, +0,-35,-49,-43,40,47,35,40,55,38, +-24,-76,-103,-112,-27,3,23,34,52,75, +8,-29,-43,12,63,38,35,29,24,8, +25,11,1,-15,-18,-43,-7,37,40,21, +-20,-56,-19,-19,-4,-2,11,29,51,63, +-2,-44,-62,-75,-89,30,57,51,74,51, +50,46,68,64,65,52,63,55,65,43, +18,-9,-26,-35,-55,-69,3,6,8,17, +-15,-61,-86,-97,1,86,93,74,78,67, +-1,-38,-66,-48,48,39,29,25,17,-1, +13,13,29,39,50,51,69,82,97,98, +-2,-36,-46,-27,-16,-30,-13,-4,-7,-4, +25,-5,-11,-6,-25,-21,33,12,31,29, +-8,-38,-52,-63,-68,-89,-33,-1,10,74, +-2,-15,59,91,105,105,101,87,84,62, +-7,-33,-50,-35,-54,-47,25,17,82,81, +-13,-56,-83,21,58,31,42,25,72,65, +-24,-66,-91,-56,9,-2,21,10,69,75, +2,-24,11,22,25,28,38,34,48,33, +7,-29,-26,17,15,-1,14,0,-2,0, +-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]={ +-34,-52,-15,45,2, +23,21,52,24,-33, +-9,-1,9,-44,-41, +-13,-17,44,22,-17, +-6,-4,-1,22,38, +26,16,2,50,27, +-35,-34,-9,-41,6, +0,-16,-34,51,8, +-14,-31,-49,15,-33, +45,49,33,-11,-37, +-62,-54,45,11,-5, +-72,11,-1,-12,-11, +24,27,-11,-43,46, +43,33,-12,-9,-1, +1,-4,-23,-57,-71, +11,8,16,17,-8, +-20,-31,-41,53,48, +-16,3,65,-24,-8, +-23,-32,-37,-32,-49, +-10,-17,6,38,5, +-9,-17,-46,8,52, +3,6,45,40,39, +-7,-6,-34,-74,31, +8,1,-16,43,68, +-11,-19,-31,4,6, +0,-6,-17,-16,-38, +-16,-30,2,9,-39, +-16,-1,43,-10,48, +3,3,-16,-31,-3, +62,68,43,13,3, +-10,8,20,-56,12, +12,-2,-18,22,-15, +-40,-36,1,7,41, +0,1,46,-6,-62, +-4,-12,-2,-11,-83, +-13,-2,91,33,-10, +0,4,-11,-16,79, +32,37,14,9,51, +-21,-28,-56,-34,0, +21,9,-26,11,28, +-42,-54,-23,-2,-15, +31,30,8,-39,-66, +-39,-36,31,-28,-40, +-46,35,40,22,24, +33,48,23,-34,14, +40,32,17,27,-3, +25,26,-13,-61,-17, +11,4,31,60,-6, +-26,-41,-64,13,16, +-26,54,31,-11,-23, +-9,-11,-34,-71,-21, +-34,-35,55,50,29, +-22,-27,-50,-38,57, +33,42,57,48,26, +11,0,-49,-31,26, +-4,-14,5,78,37, +17,0,-49,-12,-23, +26,14,2,2,-43, +-17,-12,10,-8,-4, +8,18,12,-6,20, +-12,-6,-13,-25,34, +15,40,49,7,8, +13,20,20,-19,-22, +-2,-8,2,51,-51}; + +signed char cdbk_nb_low2[320]={ +-6,53,-21,-24,4, +26,17,-4,-37,25, +17,-36,-13,31,3, +-6,27,15,-10,31, +28,26,-10,-10,-40, +16,-7,15,13,41, +-9,0,-4,50,-6, +-7,14,38,22,0, +-48,2,1,-13,-19, +32,-3,-60,11,-17, +-1,-24,-34,-1,35, +-5,-27,28,44,13, +25,15,42,-11,15, +51,35,-36,20,8, +-4,-12,-29,19,-47, +49,-15,-4,16,-29, +-39,14,-30,4,25, +-9,-5,-51,-14,-3, +-40,-32,38,5,-9, +-8,-4,-1,-22,71, +-3,14,26,-18,-22, +24,-41,-25,-24,6, +23,19,-10,39,-26, +-27,65,45,2,-7, +-26,-8,22,-12,16, +15,16,-35,-5,33, +-21,-8,0,23,33, +34,6,21,36,6, +-7,-22,8,-37,-14, +31,38,11,-4,-3, +-39,-32,-8,32,-23, +-6,-12,16,20,-28, +-4,23,13,-52,-1, +22,6,-33,-40,-6, +4,-62,13,5,-26, +35,39,11,2,57, +-11,9,-20,-28,-33, +52,-5,-6,-2,22, +-14,-16,-48,35,1, +-58,20,13,33,-1, +-74,56,-18,-22,-31, +12,6,-14,4,-2, +-9,-47,10,-3,29, +-17,-5,61,14,47, +-12,2,72,-39,-17, +92,64,-53,-51,-15, +-30,-38,-41,-29,-28, +27,9,36,9,-35, +-42,81,-21,20,25, +-16,-5,-17,-35,21, +15,-28,48,2,-2, +9,-19,29,-40,30, +-18,-18,18,-16,-57, +15,-20,-12,-15,-37, +-15,33,-39,21,-22, +-13,35,11,13,-38, +-63,29,23,-27,32, +18,3,-26,42,33, +-64,-66,-17,16,56, +2,36,3,31,21, +-41,-39,8,-57,14, +37,-2,19,-36,-19, +-23,-29,-16,1,-3, +-8,-10,31,64,-65}; + +signed char cdbk_nb_high1[320]={ +-26,-8,29,21,4, +19,-39,33,-7,-36, +56,54,48,40,29, +-4,-24,-42,-66,-43, +-60,19,-2,37,41, +-10,-37,-60,-64,18, +-22,77,73,40,25, +4,19,-19,-66,-2, +11,5,21,14,26, +-25,-86,-4,18,1, +26,-37,10,37,-1, +24,-12,-59,-11,20, +-6,34,-16,-16,42, +19,-28,-51,53,32, +4,10,62,21,-12, +-34,27,4,-48,-48, +-50,-49,31,-7,-21, +-42,-25,-4,-43,-22, +59,2,27,12,-9, +-6,-16,-8,-32,-58, +-16,-29,-5,41,23, +-30,-33,-46,-13,-10, +-38,52,52,1,-17, +-9,10,26,-25,-6, +33,-20,53,55,25, +-32,-5,-42,23,21, +66,5,-28,20,9, +75,29,-7,-42,-39, +15,3,-23,21,6, +11,1,-29,14,63, +10,54,26,-24,-51, +-49,7,-23,-51,15, +-66,1,60,25,10, +0,-30,-4,-15,17, +19,59,40,4,-5, +33,6,-22,-58,-70, +-5,23,-6,60,44, +-29,-16,-47,-29,52, +-19,50,28,16,35, +31,36,0,-21,6, +21,27,22,42,7, +-66,-40,-8,7,19, +46,0,-4,60,36, +45,-7,-29,-6,-32, +-39,2,6,-9,33, +20,-51,-34,18,-6, +19,6,11,5,-19, +-29,-2,42,-11,-45, +-21,-55,57,37,2, +-14,-67,-16,-27,-38, +69,48,19,2,-17, +20,-20,-16,-34,-17, +-25,-61,10,73,45, +16,-40,-64,-17,-29, +-22,56,17,-39,8, +-11,8,-25,-18,-13, +-19,8,54,57,36, +-17,-26,-4,6,-21, +40,42,-4,20,31, +53,10,-34,-53,31, +-17,35,0,15,-6, +-20,-63,-73,22,25, +29,17,8,-29,-39, +-69,18,15,-15,-5}; + +signed char cdbk_nb_high2[320]={ +11,47,16,-9,-46, +-32,26,-64,34,-5, +38,-7,47,20,2, +-73,-99,-3,-45,20, +70,-52,15,-6,-7, +-82,31,21,47,51, +39,-3,9,0,-41, +-7,-15,-54,2,0, +27,-31,9,-45,-22, +-38,-24,-24,8,-33, +23,5,50,-36,-17, +-18,-51,-2,13,19, +43,12,-15,-12,61, +38,38,7,13,0, +6,-1,3,62,9, +27,22,-33,38,-35, +-9,30,-43,-9,-32, +-1,4,-4,1,-5, +-11,-8,38,31,11, +-10,-42,-21,-37,1, +43,15,-13,-35,-19, +-18,15,23,-26,59, +1,-21,53,8,-41, +-50,-14,-28,4,21, +25,-28,-40,5,-40, +-41,4,51,-33,-8, +-8,1,17,-60,12, +25,-41,17,34,43, +19,45,7,-37,24, +-15,56,-2,35,-10, +48,4,-47,-2,5, +-5,-54,5,-3,-33, +-10,30,-2,-44,-24, +-38,9,-9,42,4, +6,-56,44,-16,9, +-40,-26,18,-20,10, +28,-41,-21,-4,13, +-18,32,-30,-3,37, +15,22,28,50,-40, +3,-29,-64,7,51, +-19,-11,17,-27,-40, +-64,24,-12,-7,-27, +3,37,48,-1,2, +-9,-38,-34,46,1, +27,-6,19,-13,26, +10,34,20,25,40, +50,-6,-7,30,9, +-24,0,-23,71,-61, +22,58,-34,-4,2, +-49,-33,25,30,-8, +-6,-16,77,2,38, +-8,-35,-6,-30,56, +78,31,33,-20,13, +-39,20,22,4,21, +-8,4,-6,10,-83, +-41,9,-25,-43,15, +-7,-12,-34,-39,-37, +-33,19,30,16,-33, +42,-25,25,-68,44, +-15,-11,-4,23,50, +14,4,-39,-43,20, +-30,60,9,-20,7, +16,19,-33,37,29, +16,-35,7,38,-27}; diff --git a/dep/speex/src/ltp.c b/dep/speex/src/ltp.c new file mode 100644 index 0000000..f95d215 --- /dev/null +++ b/dep/speex/src/ltp.c @@ -0,0 +1,548 @@ +/* Copyright (C) 2002 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 + 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 +#include "ltp.h" +#include "stack_alloc.h" +#include "filters.h" +#include "speex_bits.h" + +#ifdef _USE_SSE +#include "ltp_sse.h" +#else +static float inner_prod(float *x, float *y, int len) +{ + int i; + float sum1=0,sum2=0,sum3=0,sum4=0; + for (i=0;ibest_score[N-1]) + { + 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;j best_score[j]) + { + for (k=N-1;k>j;k--) + { + best_score[k]=best_score[k-1]; + pitch[k]=pitch[k-1]; + gain[k] = gain[k-1]; + } + best_score[j]=score[i-start]; + pitch[j]=i; + gain[j]=g; + break; + } + } + } + } + +} + + + + +/** 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, +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 +) +{ + 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; + + 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); + + x[0]=tmp; + x[1]=tmp+nsf; + x[2]=tmp+2*nsf; + + e[0]=tmp2; + e[1]=tmp2+nsf; + e[2]=tmp2+2*nsf; + + for (i=2;i>=0;i--) + { + int pp=pitch+1-i; + for (j=0;j0) + 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; + + *cdbk_index=best_cdbk; + } + + for (i=0;i10) + N=10; + + nbest=PUSH(stack, N, int); + gains = PUSH(stack, N, float); + params = (ltp_params*) par; + + if (N==0 || endpitch_bits); + speex_bits_pack(bits, 0, params->gain_bits); + for (i=0;iend-start+1) + N=end-start+1; + open_loop_nbest_pitch(sw, start, end, nsf, nbest, gains, N, stack); + for (i=0;ipitch_bits); + speex_bits_pack(bits, best_gain_index, params->gain_bits); + /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/ + for (i=0;igain_cdbk; + + 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; + + if (count_lost && pitch > subframe_offset) + { + float gain_sum; + + if (1) { + float tmp = count_lost < 4 ? last_pitch_gain : 0.4 * 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; + + } + + } + + 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]; + + { + 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;j.99) + pitch_coef=.99; + for (i=0;i.99) + pitch_coef=.99; + 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/dep/speex/src/misc.c b/dep/speex/src/misc.c new file mode 100644 index 0000000..f84e0f6 --- /dev/null +++ b/dep/speex/src/misc.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: mics.c + Various utility routines for Speex + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "misc.h" +#include +#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;ienc_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) +{ + return mode->query(mode->mode, request, ptr); +} diff --git a/dep/speex/src/nb_celp.c b/dep/speex/src/nb_celp.c new file mode 100644 index 0000000..837d2f5 --- /dev/null +++ b/dep/speex/src/nb_celp.c @@ -0,0 +1,1715 @@ +/* Copyright (C) 2002 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 + 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 +#include "nb_celp.h" +#include "lpc.h" +#include "lsp.h" +#include "ltp.h" +#include "quant_lsp.h" +#include "cb_search.h" +#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 "math_approx.h" +#define cos speex_cos +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#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}; + +float exc_gain_quant_scal1[2]={-0.35, 0.05}; + +#define sqr(x) ((x)*(x)) + +void *nb_encoder_init(SpeexMode *m) +{ + EncState *st; + SpeexNBMode *mode; + int i; + + mode=(SpeexNBMode *)m->mode; + st = (EncState*)speex_alloc(sizeof(EncState)+8000*sizeof(float)); + if (!st) + return NULL; + + 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->exc2Buf = PUSH(st->stack, st->bufSize, float); + st->exc2 = st->exc2Buf + st->bufSize - st->windowSize; + + st->innov = PUSH(st->stack, st->frameSize, 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); + } + /* 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->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); + } + + 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->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); + st->vbr_quality = 8; + st->vbr_enabled = 0; + st->vad_enabled = 0; + st->dtx_enabled = 0; + st->abr_enabled = 0; + st->abr_drift = 0; + + st->complexity=2; + st->sampling_rate=8000; + st->dtx_count=0; + + return st; +} + +void nb_encoder_destroy(void *state) +{ + EncState *st=(EncState *)state; + /* Free all allocated memory */ + + vbr_destroy(st->vbr); + + /*Free state memory... should be last*/ + speex_free(st); +} + +int nb_encode(void *state, float *in, SpeexBits *bits) +{ + EncState *st; + int i, sub, roots; + int ol_pitch; + float ol_pitch_coef; + float ol_gain; + float *res, *target, *mem; + char *stack; + float *syn_resp; + float lsp_dist=0; + float *orig; + + 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]; + + /* 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)); + + + /* 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) + { + /* 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++) + { + st->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) */ + { + if (st->first) + for (i=0;ilpcSize;i++) + st->interp_lsp[i] = st->lsp[i]; + else + 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); + + /* 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); + + + /*Open-loop pitch*/ + if (!st->submodes[st->submodeID] || st->vbr_enabled || st->vad_enabled || SUBMODE(forced_pitch_gain) || + SUBMODE(lbr_pitch) != -1) + { + 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); + + open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize, + 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)) + { + /*ol_pitch_coef=nol_pitch_coef[i];*/ + ol_pitch = nol_pitch[i]; + } + } + /*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); + + /* 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); + } + + /*VBR stuff*/ + if (st->vbr && (st->vbr_enabled||st->vad_enabled)) + { + + if (st->abr_enabled) + { + float qual_change=0; + if (st->abr_drift2 * st->abr_drift > 0) + { + /* Only adapt if long-term and short-term drift are the same sign */ + qual_change = -.00001*st->abr_drift/(1+st->abr_count); + if (qual_change>.05) + qual_change=.05; + if (qual_change<-.05) + qual_change=-.05; + } + st->vbr_quality += qual_change; + if (st->vbr_quality>10) + st->vbr_quality=10; + if (st->vbr_quality<0) + st->vbr_quality=0; + } + + st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, ol_pitch_coef); + /*if (delta_qual<0)*/ + /* delta_qual*=.1*(3+st->vbr_quality);*/ + if (st->vbr_enabled) + { + int mode; + int choice=0; + float min_diff=100; + mode = 8; + while (mode) + { + int v1; + float thresh; + v1=(int)floor(st->vbr_quality); + if (v1==10) + 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 && + st->relative_quality-threshrelative_quality-thresh; + } + mode--; + } + mode=choice; + if (mode==0) + { + if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20) + { + mode=1; + st->dtx_count=1; + } else { + mode=0; + st->dtx_count++; + } + } else { + st->dtx_count=0; + } + + speex_encoder_ctl(state, SPEEX_SET_MODE, &mode); + + if (st->abr_enabled) + { + int 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); + st->abr_count += 1.0; + } + + } else { + /*VAD only case*/ + int mode; + if (st->relative_quality<2) + { + if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20) + { + st->dtx_count=1; + mode=1; + } else { + mode=0; + st->dtx_count++; + } + } else { + st->dtx_count = 0; + mode=st->submodeSelect; + } + /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ + st->submodeID=mode; + } + } else { + st->relative_quality = -1; + } + + /* 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); + + + /* 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;ilpcSize;i++) + st->mem_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]; + + return 0; + + } + + /* LSP Quantization */ + if (st->first) + { + for (i=0;ilpcSize;i++) + st->old_lsp[i] = st->lsp[i]; + } + + + /*Quantize LSPs*/ +#if 1 /*0 for unquantized*/ + SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits); +#else + for (i=0;ilpcSize;i++) + st->qlsp[i]=st->lsp[i]; +#endif + + /*If we use low bit-rate pitch mode, transmit open-loop pitch*/ + if (SUBMODE(lbr_pitch)!=-1) + { + speex_bits_pack(bits, ol_pitch-st->min_pitch, 7); + } + + if (SUBMODE(forced_pitch_gain)) + { + int quant; + quant = (int)floor(.5+15*ol_pitch_coef); + if (quant>15) + quant=15; + if (quant<0) + quant=0; + speex_bits_pack(bits, quant, 4); + ol_pitch_coef=0.066667*quant; + } + + + /*Quantize and transmit open-loop excitation gain*/ + { + int qe = (int)(floor(3.5*log(ol_gain))); + if (qe<0) + qe=0; + if (qe>31) + qe=31; + ol_gain = exp(qe/3.5); + speex_bits_pack(bits, qe, 5); + } + + /* Special case for first frame */ + if (st->first) + { + for (i=0;ilpcSize;i++) + st->old_qlsp[i] = st->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]; + + /* Loop on sub-frames */ + for (sub=0;subnbSubframes;sub++) + { + float tmp; + int offset; + float *sp, *sw, *exc, *exc2; + int pitch; + + /* Offset relative to start of frame */ + offset = st->subframeSize*sub; + /* Original signal */ + sp=st->frame+offset; + /* 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); + + /* 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); + + 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 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; + } + + /* 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); + else + { + st->bw_lpc2[0]=1; + st->bw_lpc2[1]=-st->preemph; + for (i=2;i<=st->lpcSize;i++) + st->bw_lpc2[i]=0; + } + + /* Compute impulse response of A(z/g1) / ( A(z)*A(z/g2) )*/ + 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; + + /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */ + for (i=0;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); + + /* 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); + + /* Compute target signal */ + for (i=0;isubframeSize;i++) + target[i]=sw[i]-res[i]; + + for (i=0;isubframeSize;i++) + exc[i]=exc2[i]=0; + + /* If we have a long-term predictor (otherwise, something's wrong) */ + if (SUBMODE(ltp_quant)) + { + int pit_min, pit_max; + /* Long-term prediction */ + if (SUBMODE(lbr_pitch) != -1) + { + /* Low bit-rate pitch handling */ + int margin; + 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; + 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; + } + + /* 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); + + st->pitch[sub]=pitch; + } else { + speex_error ("No pitch prediction, what's wrong"); + } + + /* Update target for adaptive codebook contribution */ + syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, stack); + for (i=0;isubframeSize;i++) + target[i]-=res[i]; + + + /* Quantization of innovation */ + { + float *innov; + float ener=0, ener_1; + + 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"); + } + + /* 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]; + } + + for (i=0;isubframeSize;i++) + target[i]*=ener; + + } + + /*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); + for (i=0;isubframeSize;i++) + exc2[i]=exc[i]; + } + + /* 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]; + } + + if (st->submodeID==1) + { + if (st->dtx_count) + speex_bits_pack(bits, 15, 4); + else + 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]; + + if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0) + st->bounded_pitch = 1; + else + st->bounded_pitch = 0; + + return 1; +} + + +void *nb_decoder_init(SpeexMode *m) +{ + DecState *st; + SpeexNBMode *mode; + int i; + + mode=(SpeexNBMode*)m->mode; + st = (DecState *)speex_alloc(sizeof(DecState)+4000*sizeof(float)); + st->mode=m; + + st->stack = ((char*)st) + sizeof(DecState); + + 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->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->sampling_rate=8000; + st->last_ol_gain = 0; + + st->user_callback.func = &speex_default_user_handler; + st->user_callback.data = NULL; + for (i=0;i<16;i++) + st->speex_callbacks[i].func = NULL; + + st->voc_m1=st->voc_m2=st->voc_mean=0; + st->voc_offset=0; + st->dtx_enabled=0; + return st; +} + +void nb_decoder_destroy(void *state) +{ + 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); +#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; +} + +int nb_decoder_ctl(void *state, int request, void *ptr) +{ + DecState *st; + st=(DecState*)state; + switch(request) + { + case SPEEX_GET_LOW_MODE: + case SPEEX_GET_MODE: + (*(int*)ptr) = st->submodeID; + break; + case SPEEX_SET_ENH: + st->lpc_enh_enabled = *((int*)ptr); + break; + case SPEEX_GET_ENH: + *((int*)ptr) = st->lpc_enh_enabled; + break; + case SPEEX_GET_FRAME_SIZE: + (*(int*)ptr) = st->frameSize; + 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_SET_HANDLER: + { + SpeexCallback *c = (SpeexCallback*)ptr; + st->speex_callbacks[c->callback_id].func=c->func; + st->speex_callbacks[c->callback_id].data=c->data; + st->speex_callbacks[c->callback_id].callback_id=c->callback_id; + } + break; + case SPEEX_SET_USER_HANDLER: + { + SpeexCallback *c = (SpeexCallback*)ptr; + st->user_callback.func=c->func; + st->user_callback.data=c->data; + st->user_callback.callback_id=c->callback_id; + } + break; + case SPEEX_RESET_STATE: + { + int i; + for (i=0;i<2*st->lpcSize;i++) + st->mem_sp[i]=0; + for (i=0;ibufSize;i++) + st->excBuf[i]=st->inBuf[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_DTX_STATUS: + *((int*)ptr) = st->dtx_enabled; + break; + default: + speex_warning_int("Unknown nb_ctl request: ", request); + return -1; + } + return 0; +} diff --git a/dep/speex/src/quant_lsp.c b/dep/speex/src/quant_lsp.c new file mode 100644 index 0000000..c9d797e --- /dev/null +++ b/dep/speex/src/quant_lsp.c @@ -0,0 +1,311 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: quant_lsp.c + LSP 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 + 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 "quant_lsp.h" +#include + +extern int lsp_nb_vqid[64]; +static float quant_weight[MAX_LSP_SIZE]; + +/* 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; + } + + for (i=0;i tmp2 ? tmp1 : tmp2; + } + + for (i=0;i +#include "sb_celp.h" +#include "stdlib.h" +#include "filters.h" +#include "lpc.h" +#include "lsp.h" +#include "stack_alloc.h" +#include "cb_search.h" +#include "quant_lsp.h" +#include "vq.h" +#include "ltp.h" +#include "misc.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + +#define sqr(x) ((x)*(x)) + +#define SUBMODE(x) st->submodes[st->submodeID]->x + +#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 +}; + +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 +}; + +void *sb_encoder_init(SpeexMode *m) +{ + int i; + SBEncState *st; + SpeexSBMode *mode; + + st = (SBEncState*)speex_alloc(sizeof(SBEncState)+8000*sizeof(float)); + st->mode = m; + mode = (SpeexSBMode*)m->mode; + + st->stack = ((char*)st) + sizeof(SBEncState); + + st->st_low = speex_encoder_init(mode->nb_mode); + 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->lpcSize=mode->lpcSize; + st->bufSize=mode->bufSize; + + 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; + 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->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->buf=PUSH(st->stack, st->windowSize, float); + st->excBuf=PUSH(st->stack, st->bufSize, float); + st->exc = st->excBuf + st->bufSize - st->windowSize; + + 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 = 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->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 = PUSH(st->stack, st->lpcSize, float); + st->mem_sp2 = PUSH(st->stack, st->lpcSize, float); + st->mem_sw = PUSH(st->stack, st->lpcSize, float); + + st->vbr_quality = 8; + st->vbr_enabled = 0; + st->vad_enabled = 0; + st->abr_enabled = 0; + st->relative_quality=0; + + st->complexity=2; + speex_decoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); + st->sampling_rate*=2; + + return st; +} + +void sb_encoder_destroy(void *state) +{ + SBEncState *st=(SBEncState*)state; + + speex_encoder_destroy(st->st_low); + + speex_free(st); +} + + +int sb_encode(void *state, float *in, 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; + + 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); + + /* 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]; + + speex_move(st->excBuf, st->excBuf+st->frame_size, (st->bufSize-st->frame_size)*sizeof(float)); + + + low_pi_gain = PUSH(stack, st->nbSubframes, float); + low_exc = PUSH(stack, st->frame_size, float); + low_innov = PUSH(stack, st->frame_size, float); + 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_LOW_MODE, &dtx); + + if (dtx==0) + dtx=1; + else + dtx=0; + + /* Start encoding the high-band */ + for (i=0;iwindowSize;i++) + st->buf[i] = st->high[i] * st->window[i]; + + /* Compute auto-correlation */ + _spx_autocorr(st->buf, st->autocorr, st->lpcSize+1, st->windowSize); + + 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]; + + /* 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); + if (roots!=st->lpcSize) + { + roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, 0.02, 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)); + } + } + } + + /* x-domain to angle domain*/ + for (i=0;ilpcSize;i++) + st->lsp[i] = acos(st->lsp[i]); + + /* VBR code */ + if ((st->vbr_enabled || st->vad_enabled) && !dtx) + { + float e_low=0, e_high=0; + float ratio; + if (st->abr_enabled) + { + float qual_change=0; + if (st->abr_drift2 * st->abr_drift > 0) + { + /* Only adapt if long-term and short-term drift are the same sign */ + qual_change = -.00001*st->abr_drift/(1+st->abr_count); + if (qual_change>.1) + qual_change=.1; + if (qual_change<-.1) + qual_change=-.1; + } + st->vbr_quality += qual_change; + if (st->vbr_quality>10) + st->vbr_quality=10; + if (st->vbr_quality<0) + st->vbr_quality=0; + } + + + 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)); + 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) + { + int modeid; + modeid = mode->nb_modes-1; + st->relative_quality+=1.0*(ratio+2); + if (st->relative_quality<-1) + st->relative_quality=-1; + while (modeid) + { + int v1; + float thresh; + v1=(int)floor(st->vbr_quality); + if (v1==10) + thresh = mode->vbr_thresh[modeid][v1]; + else + 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) + break; + modeid--; + } + speex_encoder_ctl(state, SPEEX_SET_HIGH_MODE, &modeid); + if (st->abr_enabled) + { + int 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); + st->abr_count += 1.0; + } + + } else { + /* VAD only */ + int modeid; + if (st->relative_quality<2.0) + modeid=1; + else + modeid=st->submodeSelect; + /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ + st->submodeID=modeid; + + } + /*fprintf (stderr, "%f %f\n", ratio, low_qual);*/ + } + + 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; + + 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 + + if (dtx) + return 0; + else + return 1; + } + + + /* LSP quantization */ + SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits); + + if (st->first) + { + for (i=0;ilpcSize;i++) + st->old_lsp[i] = st->lsp[i]; + for (i=0;ilpcSize;i++) + st->old_qlsp[i] = st->qlsp[i]; + } + + mem=PUSH(stack, st->lpcSize, float); + syn_resp=PUSH(stack, st->subframeSize, float); + innov = PUSH(stack, st->subframeSize, float); + + for (sub=0;subnbSubframes;sub++) + { + float *exc, *sp, *res, *target, *sw, tmp, filter_ratio; + int offset; + float rl, rh, eh=0, el=0; + int fold; + + offset = st->subframeSize*sub; + sp=st->high+offset; + exc=st->exc+offset; + res=st->res+offset; + target=st->target+offset; + sw=st->sw+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]; + + lsp_enforce_margin(st->interp_lsp, st->lpcSize, .05); + lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .05); + + /* 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(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); + + /* 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++) + { + rh += tmp*st->interp_qlpc[i]; + tmp = -tmp; + st->pi_gain[sub]+=st->interp_qlpc[i]; + } + 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; + + /* Compute "real excitation" */ + fir_mem2(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2); + /* Compute energy of low-band and high-band excitation */ + for (i=0;isubframeSize;i++) + eh+=sqr(exc[i]); + + 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]); + + /* Gain to use if we want to use the low-band excitation for high-band */ + g=eh/(.01+el); + g=sqrt(g); + + g *= filter_ratio; + /*print_vec(&g, 1, "gain factor");*/ + /* Gain quantization */ + { + int quant = (int) floor(.5 + 10 + 8.0 * log((g+.0001))); + /*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); + { + 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); + } + + 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; + + /* 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); + + 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); + + /* 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); + + /* Compute target signal */ + for (i=0;isubframeSize;i++) + target[i]=sw[i]-res[i]; + + for (i=0;isubframeSize;i++) + exc[i]=0; + + + for (i=0;isubframeSize;i++) + target[i]*=scale_1; + + /* Reset excitation */ + for (i=0;isubframeSize;i++) + innov[i]=0; + + /*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); + /*print_vec(target, st->subframeSize, "after");*/ + + for (i=0;isubframeSize;i++) + exc[i] += innov[i]*scale; + + 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.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]; + } + + } + + /*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); + } + + +#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]; + for (i=0;ilpcSize;i++) + st->old_qlsp[i] = st->qlsp[i]; + + st->first=0; + + return 1; +} + + + + + +void *sb_decoder_init(SpeexMode *m) +{ + SBDecState *st; + SpeexSBMode *mode; + st = (SBDecState*)speex_alloc(sizeof(SBDecState)+6000*sizeof(float)); + st->mode = m; + mode=(SpeexSBMode*)m->mode; + + st->stack = ((char*)st) + sizeof(SBDecState); + + + + st->st_low = speex_decoder_init(mode->nb_mode); + 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; + speex_decoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate); + st->sampling_rate*=2; + + st->submodes=mode->submodes; + st->submodeID=mode->defaultSubmode; + + 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->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->exc=PUSH(st->stack, st->frame_size, 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->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; + + return st; +} + +void sb_decoder_destroy(void *state) +{ + SBDecState *st; + st = (SBDecState*)state; + speex_decoder_destroy(st->st_low); + + speex_free(state); +} + +static void sb_decode_lost(SBDecState *st, float *out, int dtx, char *stack) +{ + int i; + float *awk1, *awk2, *awk3; + int saved_modeid=0; + + if (dtx) + { + saved_modeid=st->submodeID; + st->submodeID=1; + } else { + bw_lpc(0.99, 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; + } + + for (i=0;iframe_size;i++) + st->high[i]=st->exc[i]; + + 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]); + + if (dtx) + { + st->submodeID=saved_modeid; + } + + return; +} + +int sb_decode(void *state, SpeexBits *bits, float *out) +{ + 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; + + st = (SBDecState*)state; + stack=st->stack; + mode = (SpeexSBMode*)(st->mode->mode); + + /* Decode the low-band */ + ret = speex_decode(st->st_low, bits, st->x0d); + + speex_decoder_ctl(st->st_low, SPEEX_GET_DTX_STATUS, &dtx); + + /* If error decoding the narrowband part, propagate error */ + if (ret!=0) + { + return ret; + } + + if (!bits) + { + sb_decode_lost(st, out, dtx, stack); + return 0; + } + + /*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_warning("Invalid mode encountered: corrupted stream?"); + return -2; + } + + /* If null mode (no transmission), just set a couple things to zero*/ + if (st->submodes[st->submodeID] == NULL) + { + if (dtx) + { + sb_decode_lost(st, out, 1, stack); + return 0; + } + + for (i=0;iframe_size;i++) + st->exc[i]=0; + + 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); + + 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]); + + 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); + 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); + + SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits); + + if (st->first) + { + for (i=0;ilpcSize;i++) + st->old_qlsp[i] = st->qlsp[i]; + } + + 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++) + { + float *exc, *sp, tmp, filter_ratio, el=0; + int offset; + float 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) + { + 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);*/ + } + + + /* Calculate reponse 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++) + { + rh += tmp*st->interp_qlpc[i]; + tmp = -tmp; + st->pi_gain[sub]+=st->interp_qlpc[i]; + } + 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; + if (!SUBMODE(innovation_unquant)) + { + float 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);*/ + } else { + float gc, scale; + int qgc = speex_bits_unpack_unsigned(bits, 4); + for (i=0;isubframeSize;i++) + el+=sqr(low_exc[offset+i]); + + + gc = exp((1/3.7)*qgc-2); + + scale = gc*sqrt(1+el)/filter_ratio; + + + SUBMODE(innovation_unquant)(exc, SUBMODE(innovation_params), st->subframeSize, + bits, stack); + for (i=0;isubframeSize;i++) + exc[i]*=scale; + + 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]*=scale*(1/2.5); + for (i=0;isubframeSize;i++) + exc[i] += innov2[i]; + } + + } + + for (i=0;isubframeSize;i++) + sp[i]=exc[i]; + 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); + } + /*iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);*/ + + } + + 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]); + + for (i=0;ilpcSize;i++) + st->old_qlsp[i] = st->qlsp[i]; + + st->first=0; + + return 0; +} + + +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; +} diff --git a/dep/speex/src/speex_callbacks.c b/dep/speex/src/speex_callbacks.c new file mode 100644 index 0000000..3b48696 --- /dev/null +++ b/dep/speex/src/speex_callbacks.c @@ -0,0 +1,135 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File speex_callbacks.c + Callback handling and in-band signalling + + + 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 "speex_callbacks.h" +#include "misc.h" + +int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) +{ + int id; + SpeexCallback *callback; + /*speex_bits_advance(bits, 5);*/ + id=speex_bits_unpack_unsigned(bits, 4); + callback = callback_list+id; + + if (callback->func) + { + return callback->func(bits, state, callback->data); + } else + /*If callback is not registered, skip the right number of bits*/ + { + int adv; + if (id<2) + adv = 1; + else if (id<8) + adv = 4; + else if (id<10) + adv = 8; + else if (id<12) + adv = 16; + else if (id<14) + adv = 32; + else + adv = 64; + speex_bits_advance(bits, adv); + } + return 0; +} + +int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) +{ + int 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) +{ + int 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) +{ + int 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) +{ + int vbr; + vbr = speex_bits_unpack_unsigned(bits, 1); + speex_encoder_ctl(data, SPEEX_SET_VBR, &vbr); + return 0; +} + +int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) +{ + int 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) +{ + int qual; + qual = speex_bits_unpack_unsigned(bits, 4); + speex_encoder_ctl(data, SPEEX_SET_VBR_QUALITY, &qual); + return 0; +} + + +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); + return 0; +} + + + +/* Default handler for user callbacks: skip it */ +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); + return 0; +} diff --git a/dep/speex/src/speex_header.c b/dep/speex/src/speex_header.c new file mode 100644 index 0000000..7ee1ef3 --- /dev/null +++ b/dep/speex/src/speex_header.c @@ -0,0 +1,162 @@ +/* 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 + 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 "speex_header.h" +#include "misc.h" +#include "speex.h" + +#ifndef NULL +#define NULL 0 +#endif + +#define ENDIAN_SWITCH(x) {x=le_int(x);} + + +/* +typedef struct SpeexHeader { + char speex_string[8]; + char speex_version[SPEEX_HEADER_VERSION_LENGTH]; + int speex_version_id; + int header_size; + int rate; + int mode; + int mode_bitstream_version; + int nb_channels; + int bitrate; + int frame_size; + int vbr; + int frames_per_packet; + int extra_headers; + int reserved1; + int reserved2; +} SpeexHeader; +*/ + +void speex_init_header(SpeexHeader *header, int rate, int nb_channels, SpeexMode *m) +{ + int i; + char *h="Speex "; + /* + strncpy(header->speex_string, "Speex ", 8); + strncpy(header->speex_version, 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 (;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; + if (m->modeID<0) + speex_warning("This mode is meant to be used alone"); + header->nb_channels = nb_channels; + 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) +{ + SpeexHeader *le_header; + le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); + + speex_move(le_header, header, sizeof(SpeexHeader)); + + /*Make sure everything is now little-endian*/ + ENDIAN_SWITCH(le_header->speex_version_id); + ENDIAN_SWITCH(le_header->header_size); + ENDIAN_SWITCH(le_header->rate); + ENDIAN_SWITCH(le_header->mode); + ENDIAN_SWITCH(le_header->mode_bitstream_version); + ENDIAN_SWITCH(le_header->nb_channels); + ENDIAN_SWITCH(le_header->bitrate); + ENDIAN_SWITCH(le_header->frame_size); + ENDIAN_SWITCH(le_header->vbr); + ENDIAN_SWITCH(le_header->frames_per_packet); + ENDIAN_SWITCH(le_header->extra_headers); + + *size = sizeof(SpeexHeader); + return (char *)le_header; +} + +SpeexHeader *speex_packet_to_header(char *packet, int size) +{ + int i; + SpeexHeader *le_header; + char *h = "Speex "; + for (i=0;i<8;i++) + if (packet[i]!=h[i]) + { + speex_warning ("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)); + + /*Make sure everything is converted correctly from little-endian*/ + ENDIAN_SWITCH(le_header->speex_version_id); + ENDIAN_SWITCH(le_header->header_size); + ENDIAN_SWITCH(le_header->rate); + ENDIAN_SWITCH(le_header->mode); + ENDIAN_SWITCH(le_header->mode_bitstream_version); + ENDIAN_SWITCH(le_header->nb_channels); + ENDIAN_SWITCH(le_header->bitrate); + ENDIAN_SWITCH(le_header->frame_size); + ENDIAN_SWITCH(le_header->vbr); + ENDIAN_SWITCH(le_header->frames_per_packet); + ENDIAN_SWITCH(le_header->extra_headers); + + return le_header; + +} diff --git a/dep/speex/src/stereo.c b/dep/speex/src/stereo.c new file mode 100644 index 0000000..e033ce5 --- /dev/null +++ b/dep/speex/src/stereo.c @@ -0,0 +1,122 @@ +/* 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 + 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 "speex_stereo.h" +#include "speex_callbacks.h" +#include "vq.h" +#include + +/*float e_ratio_quant[4] = {1, 1.26, 1.587, 2};*/ +static float e_ratio_quant[4] = {.25, .315, .397, .5}; + +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;i0) + speex_bits_pack(bits, 0, 1); + else + speex_bits_pack(bits, 1, 1); + balance=floor(.5+fabs(balance)); + if (balance>30) + balance=31; + + speex_bits_pack(bits, (int)balance, 5); + + /*Quantize energy ratio*/ + tmp=vq_index(&e_ratio, e_ratio_quant, 1, 4); + speex_bits_pack(bits, tmp, 2); +} + +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; + + balance=stereo->balance; + e_ratio=stereo->e_ratio; + for (i=frame_size-1;i>=0;i--) + { + e_tot += data[i]*data[i]; + } + e_sum=e_tot/e_ratio; + e_left = e_sum*balance / (1+balance); + e_right = e_sum-e_left; + + e_left = sqrt(e_left/(e_tot+.01)); + e_right = sqrt(e_right/(e_tot+.01)); + + 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; + } +} + +int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) +{ + SpeexStereoState *stereo; + float sign=1; + int tmp; + + stereo = (SpeexStereoState*)data; + if (speex_bits_unpack_unsigned(bits, 1)) + sign=-1; + tmp = speex_bits_unpack_unsigned(bits, 5); + stereo->balance = exp(sign*.25*tmp); + + tmp = speex_bits_unpack_unsigned(bits, 2); + stereo->e_ratio = e_ratio_quant[tmp]; + + return 0; +} diff --git a/dep/speex/src/testenc.c b/dep/speex/src/testenc.c new file mode 100644 index 0000000..27746f8 --- /dev/null +++ b/dep/speex/src/testenc.c @@ -0,0 +1,129 @@ +#include "speex.h" +#include +#include +#include "speex_callbacks.h" + +#pragma warning(disable: 4996) + +#define FRAME_SIZE 160 +#include +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in[FRAME_SIZE]; + float input[FRAME_SIZE], bak[FRAME_SIZE], bak2[FRAME_SIZE]; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + int tmp; + int bitCount=0; + SpeexCallback callback; + + for (i=0;i32000) + input[i]=32000; + else if (input[i]<-32000) + input[i]=-32000; + } + speex_bits_reset(&bits); + for (i=0;i +#include + +#pragma warning(disable: 4996) + +#define FRAME_SIZE 640 +#include +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in[FRAME_SIZE]; + float input[FRAME_SIZE], bak[FRAME_SIZE], bak2[FRAME_SIZE]; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + int tmp; + int bitCount=0; + + for (i=0;i32000) + input[i]=32000; + else if (input[i]<-32000) + input[i]=-32000; + } + speex_bits_reset(&bits); + for (i=0;i +#include + +#pragma warning(disable: 4996) + +#define FRAME_SIZE 320 +#include +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in[FRAME_SIZE]; + float input[FRAME_SIZE], bak[FRAME_SIZE], bak2[FRAME_SIZE]; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + int tmp; + int bitCount=0; + + for (i=0;i32000) + input[i]=32000; + else if (input[i]<-32000) + input[i]=-32000; + } + speex_bits_reset(&bits); + for (i=0;i + + +#define sqr(x) ((x)*(x)) + +#define MIN_ENERGY 6000 +#define NOISE_POW .3 + + +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 */ +}; + + +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 */ +}; + +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 */ +}; + +void vbr_init(VBRState *vbr) +{ + int i; + + vbr->average_energy=0; + 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 = .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; + + + for (i=0;ilast_log_energy[i] = log(MIN_ENERGY); +} + + +/* + This function should analyse the signal and decide how critical the + coding error will be perceptually. The following factors should be + taken into account: + + -Attacks (positive energy derivative) should be coded with more bits + + -Stationary voiced segments should receive more bits + + -Segments with (very) low absolute energy should receive less bits (maybe + only shaped noise?) + + -DTX for near-zero energy? + + -Stationary fricative segments should have less bits + + -Temporal masking: when energy slope is decreasing, decrease the bit-rate + + -Decrease bit-rate for males (low pitch)? + + -(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) +{ + 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]; + + for (i=len>>1;ilast_log_energy[i]); + non_st = non_st/(30*VBR_MEMORY_SIZE); + if (non_st>1) + non_st=1; + + voicing = 3*(pitch_coef-.4)*fabs(pitch_coef-.4); + vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*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 = .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) + || (voicing<.4 && non_st < .05 && pow_ener < 1.2*vbr->noise_level) + || (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 + tmp = pow_ener; + if (vbr->consec_noise>=4) + { + 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 = .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 -= .7; + if (ener < 10000) + qual-=.7; + if (ener < 3000) + qual-=.7; + } else { + float short_diff, long_diff; + short_diff = log((ener+1)/(1+vbr->last_energy)); + long_diff = log((ener+1)/(1+vbr->average_energy)); + /*fprintf (stderr, "%f %f\n", short_diff, long_diff);*/ + + if (long_diff<-5) + long_diff=-5; + if (long_diff>2) + long_diff=2; + + if (long_diff>0) + qual += .6*long_diff; + if (long_diff<0) + qual += .5*long_diff; + if (short_diff>0) + { + if (short_diff>5) + short_diff=5; + qual += .5*short_diff; + } + /* Checking for energy increases */ + if (ener2 > 1.6*ener1) + qual += .5; + } + vbr->last_energy = ener; + vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef; + qual += 2.2*((pitch_coef-.4) + (vbr->soft_pitch-.4)); + + if (qual < 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; + if (vbr->consec_noise>=5) + qual-=1.3; + if (vbr->consec_noise>=12) + qual-=1.3; + */ + if (vbr->consec_noise>=3) + qual=4; + + if (vbr->consec_noise) + qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3)); + if (qual<0) + qual=0; + + if (ener<60000) + { + if (vbr->consec_noise>2) + qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3)); + if (ener<10000&&vbr->consec_noise>2) + qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3)); + if (qual<0) + qual=0; + qual += .3*log(ener/60000.0); + } + if (qual<-1) + qual=-1; + + /*printf ("%f %f %f %f %d\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level), va);*/ + + vbr->last_pitch_coef = pitch_coef; + vbr->last_quality = qual; + + for (i=VBR_MEMORY_SIZE-1;i>0;i--) + 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);*/ + + return qual; +} + +void vbr_destroy(VBRState *vbr) +{ +} diff --git a/dep/speex/src/vq.c b/dep/speex/src/vq.c new file mode 100644 index 0000000..ed36f7d --- /dev/null +++ b/dep/speex/src/vq.c @@ -0,0 +1,116 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: vq.c + 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 + 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 "vq.h" + +/*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) +{ + int i,j; + float min_dist=0; + int best_index=0; + for (i=0;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++; + } + } +} + +/*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) +{ + int i,j,k, sign, used; + used=0; + for (i=0;i0) + { + sign=1; + dist=-dist; + } else + { + sign=0; + } + dist += .5*E[i]; + 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++; + if (sign) + nbest[k]+=entries; + } + } +} diff --git a/msvc/ReVoice.sln b/msvc/ReVoice.sln index ad7262b..9fcf676 100644 --- a/msvc/ReVoice.sln +++ b/msvc/ReVoice.sln @@ -1,15 +1,18 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReVoice", "..\revoice\msvc\ReVoice.vcxproj", "{DAEFE371-7D77-4B72-A8A5-3CD3D1A55786}" ProjectSection(ProjectDependencies) = postProject {E1AC990E-C012-4167-80C2-84C98AA7070C} = {E1AC990E-C012-4167-80C2-84C98AA7070C} + {966DE7A9-EC15-4C1D-8B46-EA813A845723} = {966DE7A9-EC15-4C1D-8B46-EA813A845723} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Silk", "..\dep\silk\msvc\Silk.vcxproj", "{E1AC990E-C012-4167-80C2-84C98AA7070C}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Speex", "..\dep\speex\msvc\Speex.vcxproj", "{966DE7A9-EC15-4C1D-8B46-EA813A845723}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -24,6 +27,10 @@ Global {E1AC990E-C012-4167-80C2-84C98AA7070C}.Debug|Win32.Build.0 = Debug|Win32 {E1AC990E-C012-4167-80C2-84C98AA7070C}.Release|Win32.ActiveCfg = Release|Win32 {E1AC990E-C012-4167-80C2-84C98AA7070C}.Release|Win32.Build.0 = Release|Win32 + {966DE7A9-EC15-4C1D-8B46-EA813A845723}.Debug|Win32.ActiveCfg = Debug|Win32 + {966DE7A9-EC15-4C1D-8B46-EA813A845723}.Debug|Win32.Build.0 = Debug|Win32 + {966DE7A9-EC15-4C1D-8B46-EA813A845723}.Release|Win32.ActiveCfg = Release|Win32 + {966DE7A9-EC15-4C1D-8B46-EA813A845723}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/revoice/msvc/ReVoice.vcxproj b/revoice/msvc/ReVoice.vcxproj index f7197ea..81f95db 100644 --- a/revoice/msvc/ReVoice.vcxproj +++ b/revoice/msvc/ReVoice.vcxproj @@ -27,6 +27,7 @@ + @@ -34,6 +35,8 @@ + + @@ -51,6 +54,8 @@ + + @@ -100,7 +105,7 @@ Level3 Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;REVOICE_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)../src/;$(ProjectDir)../public/;$(ProjectDir)../version/;$(ProjectDir)../include/;$(SolutionDir)../dep/rehlsdk/common/;$(SolutionDir)../dep/rehlsdk/dlls/;$(SolutionDir)../dep/rehlsdk/engine/;$(SolutionDir)../dep/rehlsdk/public/;$(SolutionDir)../dep/silk/include/;$(SolutionDir)../dep/metamod/;%(AdditionalIncludeDirectories) + $(ProjectDir)../src/;$(ProjectDir)../public/;$(ProjectDir)../version/;$(ProjectDir)../include/;$(SolutionDir)../dep/rehlsdk/common/;$(SolutionDir)../dep/rehlsdk/dlls/;$(SolutionDir)../dep/rehlsdk/engine/;$(SolutionDir)../dep/rehlsdk/public/;$(SolutionDir)../dep/silk/include/;$(SolutionDir)../dep/speex/include/;$(SolutionDir)../dep/metamod/;%(AdditionalIncludeDirectories) precompiled.h @@ -118,7 +123,7 @@ true true WIN32;NDEBUG;_WINDOWS;_USRDLL;REVOICE_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)../src/;$(ProjectDir)../public/;$(ProjectDir)../version/;$(ProjectDir)../include/;$(SolutionDir)../dep/rehlsdk/common/;$(SolutionDir)../dep/rehlsdk/dlls/;$(SolutionDir)../dep/rehlsdk/engine/;$(SolutionDir)../dep/rehlsdk/public/;$(SolutionDir)../dep/silk/include/;$(SolutionDir)../dep/metamod/;%(AdditionalIncludeDirectories) + $(ProjectDir)../src/;$(ProjectDir)../public/;$(ProjectDir)../version/;$(ProjectDir)../include/;$(SolutionDir)../dep/rehlsdk/common/;$(SolutionDir)../dep/rehlsdk/dlls/;$(SolutionDir)../dep/rehlsdk/engine/;$(SolutionDir)../dep/rehlsdk/public/;$(SolutionDir)../dep/silk/include/;$(SolutionDir)../dep/speex/include/;$(SolutionDir)../dep/metamod/;%(AdditionalIncludeDirectories) precompiled.h @@ -126,7 +131,7 @@ true true true - ws2_32.lib;%(AdditionalDependencies) + $(OutDir)\speex.lib;ws2_32.lib;%(AdditionalDependencies) revoice.def diff --git a/revoice/msvc/ReVoice.vcxproj.filters b/revoice/msvc/ReVoice.vcxproj.filters index 6fb6654..1f19588 100644 --- a/revoice/msvc/ReVoice.vcxproj.filters +++ b/revoice/msvc/ReVoice.vcxproj.filters @@ -81,6 +81,15 @@ src + + src + + + src + + + src + @@ -119,5 +128,11 @@ src + + src + + + src + \ No newline at end of file diff --git a/revoice/src/VoiceEncoder_Speex.cpp b/revoice/src/VoiceEncoder_Speex.cpp new file mode 100644 index 0000000..3f70a0c --- /dev/null +++ b/revoice/src/VoiceEncoder_Speex.cpp @@ -0,0 +1,141 @@ +#include "precompiled.h" + +size_t ENCODED_FRAME_SIZE[] = { 0x6u, 0x6u, 0xFu, 0xFu, 0x14u, 0x14u, 0x1Cu, 0x1Cu, 0x26u, 0x26u, 0x26u }; + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:70 */ +/*IBaseInterface *CreateSpeexVoiceCodec(void) +{ + IFrameEncoder *pEncoder = (IFrameEncoder *)new VoiceEncoder_Speex; + return (IBaseInterface *)CreateVoiceCodec_Frame(pEncoder); +}*/ + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:82 */ +VoiceEncoder_Speex::VoiceEncoder_Speex() +{ + m_EncoderState = NULL; + m_DecoderState = NULL; + m_Quality = 0; +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:89 */ +VoiceEncoder_Speex::~VoiceEncoder_Speex() +{ + TermStates(); +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:94 */ +bool VoiceEncoder_Speex::Init(int quality, int &rawFrameSize, int &encodedFrameSize) +{ + int postfilter; + int samplerate; + + if (!InitStates()) + return false; + + rawFrameSize = 320; + + switch (quality) { + case 2: + m_Quality = 2; + break; + case 3: + m_Quality = 4; + break; + case 4: + m_Quality = 6; + break; + case 5: + m_Quality = 8; + break; + default: + m_Quality = 0; + break; + } + + encodedFrameSize = ENCODED_FRAME_SIZE[m_Quality]; + + speex_encoder_ctl(m_EncoderState, SPEEX_SET_QUALITY, &m_Quality); + speex_decoder_ctl(m_DecoderState, SPEEX_SET_QUALITY, &m_Quality); + + postfilter = 1; + speex_decoder_ctl(m_DecoderState, SPEEX_SET_ENH, &postfilter); + + samplerate = 8000; + speex_decoder_ctl(m_DecoderState, SPEEX_SET_SAMPLING_RATE, &samplerate); + speex_encoder_ctl(m_EncoderState, SPEEX_SET_SAMPLING_RATE, &samplerate); + + return true; +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:127 */ +void VoiceEncoder_Speex::Release() +{ + delete this; +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:132 */ +void VoiceEncoder_Speex::EncodeFrame(const char *pUncompressedBytes, char *pCompressed) +{ + float input[160]; + int16 *in = (int16 *)pUncompressedBytes; + + for (int i = 0; i < ARRAYSIZE(input); i++, in++) { + input[i] = *in; + } + + speex_bits_reset(&m_Bits); + speex_encode(m_EncoderState, input, &m_Bits); + speex_bits_write(&m_Bits, pCompressed, ENCODED_FRAME_SIZE[m_Quality]); +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:156 */ +void VoiceEncoder_Speex::DecodeFrame(const char *pCompressed, char *pDecompressedBytes) +{ + float output[160]; + int16 *out = (int16 *)pDecompressedBytes; + + speex_bits_read_from(&m_Bits, (char *)pCompressed, ENCODED_FRAME_SIZE[m_Quality]); + speex_decode(m_DecoderState, &m_Bits, output); + + for (int i = 0; i < ARRAYSIZE(output); i++, out++) { + *out = (int)output[i]; + } +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:175 */ +bool VoiceEncoder_Speex::ResetState() +{ + speex_encoder_ctl(m_EncoderState, SPEEX_RESET_STATE, 0); + speex_decoder_ctl(m_DecoderState, SPEEX_RESET_STATE, 0); + + return true; +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:182 */ +bool VoiceEncoder_Speex::InitStates() +{ + speex_bits_init(&m_Bits); + m_EncoderState = speex_encoder_init(&speex_nb_mode); + m_DecoderState = speex_decoder_init(&speex_nb_mode); + return (m_EncoderState != NULL && m_DecoderState != NULL); +} + +/* ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:193 */ +void VoiceEncoder_Speex::TermStates() +{ + if (m_EncoderState != NULL) + { + speex_encoder_destroy(m_EncoderState); + m_EncoderState = NULL; + } + + if (m_DecoderState != NULL) + { + speex_encoder_destroy(m_DecoderState); + m_DecoderState = NULL; + } + + speex_bits_destroy(&m_Bits); +} + +//EXPOSE_INTERFACE_FN(CreateSpeexVoiceCodec, VoiceEncoder_Speex, "voice_speex"); diff --git a/revoice/src/VoiceEncoder_Speex.h b/revoice/src/VoiceEncoder_Speex.h new file mode 100644 index 0000000..b1d03b2 --- /dev/null +++ b/revoice/src/VoiceEncoder_Speex.h @@ -0,0 +1,45 @@ +#pragma once + +#include "IVoiceCodec.h" +#include "iframeencoder.h" +#include "speex.h" + +/* <61c> ../engine/voice_codecs/speex/VoiceEncoder_Speex.h:57 */ +class VoiceEncoder_Speex: IFrameEncoder { +protected: + virtual ~VoiceEncoder_Speex(); + +public: + VoiceEncoder_Speex(); + + /* <6c8> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:94 */ + bool Init(int quality, int &rawFrameSize, int &encodedFrameSize); + + /* <6ff> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:127 */ + void Release(); + + /* <751> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:132 */ + void EncodeFrame(const char *pUncompressedBytes, char *pCompressed); + + /* <723> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:156 */ + void DecodeFrame(const char *pCompressed, char *pDecompressedBytes); + + /* <77f> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:175 */ + bool ResetState(); + +protected: + /* <7a7> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:182 */ + bool InitStates(); + + /* <7c8> ../engine/voice_codecs/speex/VoiceEncoder_Speex.cpp:193 */ + void TermStates(); + +private: + int m_Quality; + void *m_EncoderState; + void *m_DecoderState; + SpeexBits m_Bits; + +}; + +extern IVoiceCodec *CreateVoiceCodec_Frame(IFrameEncoder *pEncoder); diff --git a/revoice/src/iframeencoder.h b/revoice/src/iframeencoder.h new file mode 100644 index 0000000..ba9bec8 --- /dev/null +++ b/revoice/src/iframeencoder.h @@ -0,0 +1,24 @@ +#pragma once + +/* <7e2> ../engine/voice_codecs/speex/../frame_encoder/iframeencoder.h:15 */ +class IFrameEncoder { +protected: + virtual ~IFrameEncoder() {}; + +public: + // quality is in [0..10] + /* <855> ../engine/voice_codecs/speex/../frame_encoder/iframeencoder.h:23 */ + virtual bool Init(int quality, int &rawFrameSize, int &encodedFrameSize) = 0; + + /* <88c> ../engine/voice_codecs/speex/../frame_encoder/iframeencoder.h:25 */ + virtual void Release() = 0; + + /* <8b0> ../engine/voice_codecs/speex/../frame_encoder/iframeencoder.h:29 */ + virtual void EncodeFrame(const char *pUncompressedBytes, char *pCompressed) = 0; + + /* <8de> ../engine/voice_codecs/speex/../frame_encoder/iframeencoder.h:33 */ + virtual void DecodeFrame(const char *pCompressed, char *pDecompressedBytes) = 0; + + /* <90c> ../engine/voice_codecs/speex/../frame_encoder/iframeencoder.h:36 */ + virtual bool ResetState() = 0; +}; diff --git a/revoice/src/precompiled.h b/revoice/src/precompiled.h index c891fa6..2bc7ffb 100644 --- a/revoice/src/precompiled.h +++ b/revoice/src/precompiled.h @@ -17,6 +17,8 @@ #include "revoice_cfg.h" #include "revoice_rehlds_api.h" #include "VoiceEncoder_Silk.h" +#include "VoiceEncoder_Speex.h" +#include "voice_codec_frame.h" #include "interface.h" -#include "utlbuffer.h" +#include "utlbuffer.h" diff --git a/revoice/src/revoice_shared.h b/revoice/src/revoice_shared.h index 7387c9e..165ee5d 100644 --- a/revoice/src/revoice_shared.h +++ b/revoice/src/revoice_shared.h @@ -23,6 +23,21 @@ enum revoice_codec_type { vct_speex, }; +template +T _min(T a, T b) { + return (a < b) ? a : b; +} + +template +T _max(T a, T b) { + return (a < b) ? b : a; +} + +template +T clamp(T a, T min, T max) { + return (a > max) ? max : (a < min) ? min : a; +} + extern char* trimbuf(char *str); extern void LCPrintf(bool critical, const char *fmt, ...); diff --git a/revoice/src/voice_codec_frame.cpp b/revoice/src/voice_codec_frame.cpp new file mode 100644 index 0000000..4fc318e --- /dev/null +++ b/revoice/src/voice_codec_frame.cpp @@ -0,0 +1,121 @@ +#include "precompiled.h" + +/* <1f68> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:23 */ +VoiceCodec_Frame::VoiceCodec_Frame(IFrameEncoder *pEncoder) +{ + m_nEncodeBufferSamples = 0; + m_nRawBytes = m_nRawSamples = m_nEncodedBytes = 0; + m_pFrameEncoder = pEncoder; +} + +/* <2107> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:30 */ +VoiceCodec_Frame::~VoiceCodec_Frame() +{ + if (m_pFrameEncoder != NULL) { + m_pFrameEncoder->Release(); + m_pFrameEncoder = NULL; + } +} + +/* <22bc> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:36 */ +bool VoiceCodec_Frame::Init(int quality) +{ + if (m_pFrameEncoder == NULL) + return false; + + if (m_pFrameEncoder->Init(quality, m_nRawBytes, m_nEncodedBytes)) { + m_nRawSamples = m_nRawBytes >> 1; + return true; + } else { + m_pFrameEncoder->Release(); + m_pFrameEncoder = NULL; + return false; + } +} + +/* <2038> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:54 */ +void VoiceCodec_Frame::Release() +{ + delete this; +} + +/* <21fb> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:59 */ +int VoiceCodec_Frame::Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal) +{ + if (m_pFrameEncoder == NULL) + return 0; + + const int16 *pUncompressed = (const int16*) pUncompressedBytes; + + int nCompressedBytes = 0; + while ((nSamples + m_nEncodeBufferSamples) >= m_nRawSamples && (maxCompressedBytes - nCompressedBytes) >= m_nEncodedBytes) + { + // Get the data block out. + int16 samples[MAX_FRAMEBUFFER_SAMPLES]; + memcpy(samples, m_EncodeBuffer, m_nEncodeBufferSamples*BYTES_PER_SAMPLE); + memcpy(&samples[m_nEncodeBufferSamples], pUncompressed, (m_nRawSamples - m_nEncodeBufferSamples) * BYTES_PER_SAMPLE); + nSamples -= m_nRawSamples - m_nEncodeBufferSamples; + pUncompressed += m_nRawSamples - m_nEncodeBufferSamples; + m_nEncodeBufferSamples = 0; + + // Compress it. + m_pFrameEncoder->EncodeFrame((const char*)samples, &pCompressed[nCompressedBytes]); + nCompressedBytes += m_nEncodedBytes; + } + + // Store the remaining samples. + int nNewSamples = _min(nSamples, _min(m_nRawSamples-m_nEncodeBufferSamples, m_nRawSamples)); + if (nNewSamples) { + memcpy(&m_EncodeBuffer[m_nEncodeBufferSamples], &pUncompressed[nSamples - nNewSamples], nNewSamples*BYTES_PER_SAMPLE); + m_nEncodeBufferSamples += nNewSamples; + } + + // If it must get the last data, just pad with zeros.. + if (bFinal && m_nEncodeBufferSamples && (maxCompressedBytes - nCompressedBytes) >= m_nEncodedBytes) + { + memset(&m_EncodeBuffer[m_nEncodeBufferSamples], 0, (m_nRawSamples - m_nEncodeBufferSamples) * BYTES_PER_SAMPLE); + m_pFrameEncoder->EncodeFrame((const char*)m_EncodeBuffer, &pCompressed[nCompressedBytes]); + nCompressedBytes += m_nEncodedBytes; + m_nEncodeBufferSamples = 0; + } + + return nCompressedBytes; +} + +/* <205e> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:102 */ +int VoiceCodec_Frame::Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes) +{ + if (m_pFrameEncoder == NULL || compressedBytes < m_nEncodedBytes || maxUncompressedBytes < m_nRawBytes) + return 0; + + int nDecompressedBytes = 0; + int curCompressedByte = 0; + + while (true) + { + m_pFrameEncoder->DecodeFrame(&pCompressed[curCompressedByte], &pUncompressed[nDecompressedBytes]); + + curCompressedByte += m_nEncodedBytes; + nDecompressedBytes += m_nRawBytes; + + if (compressedBytes - curCompressedByte < m_nEncodedBytes || maxUncompressedBytes - nDecompressedBytes < m_nRawBytes) + break; + } + + return nDecompressedBytes / BYTES_PER_SAMPLE; +} + +/* <20e1> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:120 */ +bool VoiceCodec_Frame::ResetState() +{ + if (m_pFrameEncoder) + return m_pFrameEncoder->ResetState(); + else + return false; +} + +/* <230a> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:141 */ +IVoiceCodec *CreateVoiceCodec_Frame(IFrameEncoder *pEncoder) +{ + return new VoiceCodec_Frame(pEncoder); +} diff --git a/revoice/src/voice_codec_frame.h b/revoice/src/voice_codec_frame.h new file mode 100644 index 0000000..75407a8 --- /dev/null +++ b/revoice/src/voice_codec_frame.h @@ -0,0 +1,26 @@ +#pragma once + +/* <19b1> ../engine/voice_codecs/speex/../frame_encoder/voice_codec_frame.cpp:18 */ +class VoiceCodec_Frame: public IVoiceCodec { +public: + virtual ~VoiceCodec_Frame(); + VoiceCodec_Frame(IFrameEncoder *pEncoder); + + bool Init(int quality); + void Release(); + int Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal); + int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes); + bool ResetState(); + +protected: + enum { MAX_FRAMEBUFFER_SAMPLES = 1024 }; + + short int m_EncodeBuffer[MAX_FRAMEBUFFER_SAMPLES]; + int m_nEncodeBufferSamples; + + IFrameEncoder *m_pFrameEncoder; + int m_nRawBytes; + int m_nRawSamples; + int m_nEncodedBytes; + +};/* size: 2072, cachelines: 33, members: 7 */