Changeset 6129


Ignore:
Timestamp:
Jan 9, 2020 9:05:50 AM (5 years ago)
Author:
ming
Message:

Closed #589: Update Speex AEC to the latest version to get multichannel EC

Location:
pjproject/trunk
Files:
4 added
21 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/echo_common.c

    r5982 r6129  
    100100static struct ec_operations speex_aec_op =  
    101101{ 
    102     "AEC", 
     102    "Speex AEC", 
    103103    &speex_aec_create, 
    104104    &speex_aec_destroy, 
  • pjproject/trunk/pjmedia/src/pjmedia/echo_speex.c

    r4981 r6129  
    3636{ 
    3737    SpeexEchoState       *state; 
    38     SpeexPreprocessState *preprocess; 
     38    SpeexDecorrState     *decorr; 
     39    SpeexPreprocessState **preprocess; 
    3940 
    4041    unsigned              samples_per_frame; 
    41     unsigned              prefetch; 
     42    unsigned              channel_count; 
     43    unsigned              spf_per_channel; 
    4244    unsigned              options; 
    4345    pj_int16_t           *tmp_frame; 
     
    5860{ 
    5961    speex_ec *echo; 
    60     int sampling_rate; 
     62    int i, sampling_rate; 
    6163 
    6264    *p_echo = NULL; 
     
    6567    PJ_ASSERT_RETURN(echo != NULL, PJ_ENOMEM); 
    6668 
     69    echo->channel_count = channel_count; 
    6770    echo->samples_per_frame = samples_per_frame; 
     71    echo->spf_per_channel = samples_per_frame / channel_count; 
    6872    echo->options = options; 
    6973 
    70 #if 0 
    71     echo->state = speex_echo_state_init_mc(echo->samples_per_frame, 
     74#if 1 
     75    echo->state = speex_echo_state_init_mc(echo->spf_per_channel, 
    7276                                           clock_rate * tail_ms / 1000, 
    7377                                           channel_count, channel_count); 
     
    8084                                        clock_rate * tail_ms / 1000); 
    8185#endif 
    82     if (echo->state == NULL) { 
     86    if (echo->state == NULL) 
    8387        return PJ_ENOMEM; 
    84     } 
     88 
     89    echo->decorr = speex_decorrelate_new(clock_rate, channel_count, 
     90                                         echo->spf_per_channel); 
     91    if (echo->decorr == NULL) 
     92        return PJ_ENOMEM; 
    8593 
    8694    /* Set sampling rate */ 
     
    8997                   &sampling_rate); 
    9098 
    91     echo->preprocess = speex_preprocess_state_init(echo->samples_per_frame, 
    92                                                    clock_rate); 
    93     if (echo->preprocess == NULL) { 
    94         speex_echo_state_destroy(echo->state); 
     99    /* We need to create one state per channel processed. */ 
     100    echo->preprocess = PJ_POOL_ZALLOC_T(pool, SpeexPreprocessState *); 
     101    for (i = 0; i < channel_count; i++) { 
     102        spx_int32_t enabled; 
     103 
     104        echo->preprocess[i] = speex_preprocess_state_init( 
     105                                  echo->spf_per_channel, clock_rate); 
     106        if (echo->preprocess[i] == NULL) { 
     107            speex_aec_destroy(echo); 
     108            return PJ_ENOMEM; 
     109        } 
     110 
     111        /* Enable/disable AGC & denoise */ 
     112        enabled = PJMEDIA_SPEEX_AEC_USE_AGC; 
     113        speex_preprocess_ctl(echo->preprocess[i], SPEEX_PREPROCESS_SET_AGC, 
     114                             &enabled); 
     115 
     116        enabled = PJMEDIA_SPEEX_AEC_USE_DENOISE; 
     117        speex_preprocess_ctl(echo->preprocess[i], 
     118                             SPEEX_PREPROCESS_SET_DENOISE, &enabled); 
     119 
     120        /* Currently, VAD and dereverb are set at default setting. */ 
     121        /* 
     122        enabled = 1; 
     123        speex_preprocess_ctl(echo->preprocess[i], SPEEX_PREPROCESS_SET_VAD, 
     124                             &enabled); 
     125        speex_preprocess_ctl(echo->preprocess[i], 
     126                             SPEEX_PREPROCESS_SET_DEREVERB, 
     127                             &enabled); 
     128        */ 
     129 
     130        /* Control echo cancellation in the preprocessor */ 
     131        speex_preprocess_ctl(echo->preprocess[i], 
     132                             SPEEX_PREPROCESS_SET_ECHO_STATE, echo->state); 
     133    } 
     134 
     135    /* Create temporary frame for echo cancellation */ 
     136    echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, sizeof(pj_int16_t) * 
     137                                                   channel_count * 
     138                                                   samples_per_frame); 
     139    if (!echo->tmp_frame) { 
     140        speex_aec_destroy(echo); 
    95141        return PJ_ENOMEM; 
    96142    } 
    97  
    98     /* Disable all preprocessing, we only want echo cancellation */ 
    99 #if 0 
    100     disabled = 0; 
    101     enabled = 1; 
    102     speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE,  
    103                          &enabled); 
    104     speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC,  
    105                          &disabled); 
    106     speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_VAD,  
    107                          &disabled); 
    108     speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DEREVERB,  
    109                          &enabled); 
    110 #endif 
    111  
    112     /* Enable/disable AGC & denoise */ 
    113     { 
    114         spx_int32_t enabled; 
    115  
    116         enabled = PJMEDIA_SPEEX_AEC_USE_AGC; 
    117         speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_AGC,  
    118                              &enabled); 
    119  
    120         enabled = PJMEDIA_SPEEX_AEC_USE_DENOISE; 
    121         speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_DENOISE,  
    122                              &enabled); 
    123     } 
    124  
    125     /* Control echo cancellation in the preprocessor */ 
    126    speex_preprocess_ctl(echo->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE,  
    127                         echo->state); 
    128  
    129  
    130     /* Create temporary frame for echo cancellation */ 
    131     echo->tmp_frame = (pj_int16_t*) pj_pool_zalloc(pool, 2*samples_per_frame); 
    132     PJ_ASSERT_RETURN(echo->tmp_frame != NULL, PJ_ENOMEM); 
    133143 
    134144    /* Done */ 
     
    145155{ 
    146156    speex_ec *echo = (speex_ec*) state; 
     157    unsigned i; 
    147158 
    148159    PJ_ASSERT_RETURN(echo && echo->state, PJ_EINVAL); 
     
    153164    } 
    154165 
     166    if (echo->decorr) { 
     167        speex_decorrelate_destroy(echo->decorr); 
     168        echo->decorr = NULL; 
     169    } 
     170 
    155171    if (echo->preprocess) { 
    156         speex_preprocess_state_destroy(echo->preprocess); 
     172        for (i = 0; i < echo->channel_count; i++) { 
     173            if (echo->preprocess[i]) { 
     174                speex_preprocess_state_destroy(echo->preprocess[i]); 
     175                echo->preprocess[i] = NULL; 
     176            } 
     177        } 
    157178        echo->preprocess = NULL; 
    158179    } 
     
    182203{ 
    183204    speex_ec *echo = (speex_ec*) state; 
     205    unsigned i; 
    184206 
    185207    /* Sanity checks */ 
     
    193215 
    194216 
    195     /* Preprocess output */ 
    196     speex_preprocess_run(echo->preprocess, (spx_int16_t*)echo->tmp_frame); 
     217    /* Preprocess output per channel */ 
     218    for (i = 0; i < echo->channel_count; i++) { 
     219        spx_int16_t *buf = (spx_int16_t*)echo->tmp_frame; 
     220        unsigned j; 
     221 
     222        /* De-interleave each channel. */ 
     223        if (echo->channel_count > 1) { 
     224            for (j = 0; j < echo->spf_per_channel; j++) { 
     225                rec_frm[j] = echo->tmp_frame[j * echo->channel_count + i]; 
     226            } 
     227            buf = (spx_int16_t*)rec_frm; 
     228        } 
     229 
     230        speex_preprocess_run(echo->preprocess[i], buf); 
     231 
     232        if (echo->channel_count > 1) { 
     233            for (j = 0; j < echo->spf_per_channel; j++) { 
     234                echo->tmp_frame[j * echo->channel_count + i] = rec_frm[j]; 
     235            } 
     236        } 
     237    } 
    197238 
    198239    /* Copy temporary buffer back to original rec_frm */ 
     
    213254    /* Sanity checks */ 
    214255    PJ_ASSERT_RETURN(echo && play_frm, PJ_EINVAL); 
     256 
     257    /* Channel decorrelation algorithm is useful for multi-channel echo 
     258     * cancellation only . 
     259     */ 
     260    if (echo->channel_count > 1) { 
     261        pjmedia_copy_samples(echo->tmp_frame, play_frm, echo->samples_per_frame); 
     262        speex_decorrelate(echo->decorr, (spx_int16_t*)echo->tmp_frame, 
     263                          (spx_int16_t*)play_frm, 100); 
     264    } 
    215265 
    216266    speex_echo_playback(echo->state, (spx_int16_t*)play_frm); 
     
    228278{ 
    229279    speex_ec *echo = (speex_ec*) state; 
     280    unsigned i; 
    230281 
    231282    /* Sanity checks */ 
     
    235286 
    236287    /* Cancel echo */ 
    237     pjmedia_copy_samples(echo->tmp_frame, rec_frm, echo->samples_per_frame); 
    238288    speex_echo_capture(echo->state, 
    239                        (spx_int16_t*)echo->tmp_frame, 
    240                        (spx_int16_t*)rec_frm); 
    241  
    242     /* Apply preprocessing */ 
    243     speex_preprocess_run(echo->preprocess, (spx_int16_t*)rec_frm); 
     289                       (spx_int16_t*)rec_frm, 
     290                       (spx_int16_t*)echo->tmp_frame); 
     291 
     292    /* Apply preprocessing per channel. */ 
     293    for (i = 0; i < echo->channel_count; i++) { 
     294        spx_int16_t *buf = (spx_int16_t*)echo->tmp_frame; 
     295        unsigned j; 
     296 
     297        /* De-interleave each channel. */ 
     298        if (echo->channel_count > 1) { 
     299            for (j = 0; j < echo->spf_per_channel; j++) { 
     300                rec_frm[j] = echo->tmp_frame[j * echo->channel_count + i]; 
     301            } 
     302            buf = (spx_int16_t*)rec_frm; 
     303        } 
     304 
     305        speex_preprocess_run(echo->preprocess[i], buf); 
     306 
     307        if (echo->channel_count > 1) { 
     308            for (j = 0; j < echo->spf_per_channel; j++) { 
     309                echo->tmp_frame[j * echo->channel_count + i] = rec_frm[j]; 
     310            } 
     311        } 
     312    } 
     313 
     314    pjmedia_copy_samples(rec_frm, echo->tmp_frame, echo->samples_per_frame); 
    244315 
    245316    return PJ_SUCCESS; 
  • pjproject/trunk/third_party/build/speex/Makefile

    r4786 r6129  
    4040                        quant_lsp.o resample.o sb_celp.o smallft.o \ 
    4141                        speex.o speex_callbacks.o speex_header.o \ 
    42                         stereo.o vbr.o vq.o window.o 
     42                        scal.o stereo.o vbr.o vq.o window.o 
    4343 
    4444export SPEEX_CFLAGS = -DHAVE_CONFIG_H $(_CFLAGS) 
  • pjproject/trunk/third_party/speex/include/speex/speex_buffer.h

    r2002 r6129  
    3535#define SPEEX_BUFFER_H 
    3636 
    37 #include "speex/speex_types.h" 
     37#include "speexdsp_types.h" 
    3838 
    3939#ifdef __cplusplus 
  • pjproject/trunk/third_party/speex/include/speex/speex_echo.h

    r2002 r6129  
    3838 *  @{ 
    3939 */ 
    40 #include "speex/speex_types.h" 
     40#include "speexdsp_types.h" 
    4141 
    4242#ifdef __cplusplus 
  • pjproject/trunk/third_party/speex/include/speex/speex_jitter.h

    r2002 r6129  
    4242 */ 
    4343 
    44 #include "speex/speex_types.h" 
     44#include "speexdsp_types.h" 
    4545 
    4646#ifdef __cplusplus 
  • pjproject/trunk/third_party/speex/include/speex/speex_preprocess.h

    r2002 r6129  
    4444 */ 
    4545 
    46 #include "speex/speex_types.h" 
     46#include "speexdsp_types.h" 
    4747 
    4848#ifdef __cplusplus 
  • pjproject/trunk/third_party/speex/include/speex/speex_resampler.h

    r2002 r6129  
    8383#define spx_uint32_t unsigned int 
    8484       
     85#define speex_assert(cond) 
     86 
    8587#else /* OUTSIDE_SPEEX */ 
    8688 
    87 #include "speex/speex_types.h" 
     89#include "speexdsp_types.h" 
    8890 
    8991#endif /* OUTSIDE_SPEEX */ 
     
    105107   RESAMPLER_ERR_INVALID_ARG     = 3, 
    106108   RESAMPLER_ERR_PTR_OVERLAP     = 4, 
     109   RESAMPLER_ERR_OVERFLOW        = 5, 
    107110    
    108111   RESAMPLER_ERR_MAX_ERROR 
     
    303306                                      spx_uint32_t *stride); 
    304307 
    305 /** Get the latency in input samples introduced by the resampler. 
     308/** Get the latency introduced by the resampler measured in input samples. 
    306309 * @param st Resampler state 
    307310 */ 
    308311int speex_resampler_get_input_latency(SpeexResamplerState *st); 
    309312 
    310 /** Get the latency in output samples introduced by the resampler. 
     313/** Get the latency introduced by the resampler measured in output samples. 
    311314 * @param st Resampler state 
    312315 */ 
  • pjproject/trunk/third_party/speex/libspeex/arch.h

    r2002 r6129  
    88   modification, are permitted provided that the following conditions 
    99   are met: 
    10     
     10 
    1111   - Redistributions of source code must retain the above copyright 
    1212   notice, this list of conditions and the following disclaimer. 
    13     
     13 
    1414   - Redistributions in binary form must reproduce the above copyright 
    1515   notice, this list of conditions and the following disclaimer in the 
    1616   documentation and/or other materials provided with the distribution. 
    17     
     17 
    1818   - Neither the name of the Xiph.org Foundation nor the names of its 
    1919   contributors may be used to endorse or promote products derived from 
    2020   this software without specific prior written permission. 
    21     
     21 
    2222   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2323   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    5050#error You cannot compile as floating point and fixed point at the same time 
    5151#endif 
    52 #ifdef _USE_SSE 
     52#ifdef USE_SSE 
    5353#error SSE is only for floating-point 
    5454#endif 
     
    7676 
    7777#ifndef OUTSIDE_SPEEX 
    78 #include "speex/speex_types.h" 
     78#include "speex/speexdsp_types.h" 
    7979#endif 
    8080 
     
    9090 
    9191typedef spx_int16_t spx_word16_t; 
    92 typedef spx_int32_t   spx_word32_t; 
     92typedef spx_int32_t spx_word32_t; 
    9393typedef spx_word32_t spx_mem_t; 
    9494typedef spx_word16_t spx_coef_t; 
     
    109109#define SIG_SHIFT    14 
    110110#define GAIN_SHIFT   6 
     111 
     112#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 
    111113 
    112114#define VERY_SMALL 0 
     
    172174#define SATURATE16(x,a) (x) 
    173175#define SATURATE32(x,a) (x) 
     176#define SATURATE32PSHR(x,shift,a) (x) 
    174177 
    175178#define PSHR(a,shift)       (a) 
     
    211214#define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b)) 
    212215 
    213  
     216#define WORD2INT(x) ((x) < -32767.5f ? -32768 : \ 
     217                    ((x) > 32766.5f ? 32767 : (spx_int16_t)floor(.5 + (x)))) 
    214218#endif 
    215219 
     
    218222 
    219223/* 2 on TI C5x DSP */ 
    220 #define BYTES_PER_CHAR 2  
     224#define BYTES_PER_CHAR 2 
    221225#define BITS_PER_CHAR 16 
    222226#define LOG2_BITS_PER_CHAR 4 
    223227 
    224 #else  
     228#else 
    225229 
    226230#define BYTES_PER_CHAR 1 
  • pjproject/trunk/third_party/speex/libspeex/buffer.c

    r2002 r6129  
    11/* Copyright (C) 2007 Jean-Marc Valin 
    2        
     2 
    33   File: buffer.c 
    44   This is a very simple ring buffer implementation. It is not thread-safe 
     
    3939#include "os_support.h" 
    4040#include "arch.h" 
    41 #include <speex/speex_buffer.h> 
     41#include "speex/speex_buffer.h" 
    4242 
    4343struct SpeexBuffer_ { 
     
    100100EXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len) 
    101101{ 
    102    /* This is almost the same as for speex_buffer_write() but using  
     102   /* This is almost the same as for speex_buffer_write() but using 
    103103   SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */ 
    104104   int end; 
     
    136136   if (len > st->available) 
    137137   { 
    138       SPEEX_MEMSET(data+st->available, 0, st->size-st->available); 
     138      SPEEX_MEMSET(data+st->available, 0, len - st->available); 
    139139      len = st->available; 
    140140   } 
  • pjproject/trunk/third_party/speex/libspeex/fftwrap.c

    r2002 r6129  
    1 /* Copyright (C) 2005-2006 Jean-Marc Valin  
     1/* Copyright (C) 2005-2006 Jean-Marc Valin 
    22   File: fftwrap.c 
    33 
    4    Wrapper for various FFTs  
     4   Wrapper for various FFTs 
    55 
    66   Redistribution and use in source and binary forms, with or without 
    77   modification, are permitted provided that the following conditions 
    88   are met: 
    9     
     9 
    1010   - Redistributions of source code must retain the above copyright 
    1111   notice, this list of conditions and the following disclaimer. 
    12     
     12 
    1313   - Redistributions in binary form must reproduce the above copyright 
    1414   notice, this list of conditions and the following disclaimer in the 
    1515   documentation and/or other materials provided with the distribution. 
    16     
     16 
    1717   - Neither the name of the Xiph.org Foundation nor the names of its 
    1818   contributors may be used to endorse or promote products derived from 
    1919   this software without specific prior written permission. 
    20     
     20 
    2121   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2222   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    6363   { 
    6464      out[i] = SHL16(in[i], shift); 
    65    }    
     65   } 
    6666   return shift; 
    6767} 
     
    166166} 
    167167 
     168#elif defined(USE_INTEL_IPP) 
     169 
     170#include <ipps.h> 
     171 
     172struct ipp_fft_config 
     173{ 
     174  IppsDFTSpec_R_32f *dftSpec; 
     175  Ipp8u *buffer; 
     176}; 
     177 
     178void *spx_fft_init(int size) 
     179{ 
     180  int bufferSize = 0; 
     181  int hint; 
     182  struct ipp_fft_config *table; 
     183 
     184  table = (struct ipp_fft_config *)speex_alloc(sizeof(struct ipp_fft_config)); 
     185 
     186  /* there appears to be no performance difference between ippAlgHintFast and 
     187     ippAlgHintAccurate when using the with the floating point version 
     188     of the fft. */ 
     189  hint = ippAlgHintAccurate; 
     190 
     191  ippsDFTInitAlloc_R_32f(&table->dftSpec, size, IPP_FFT_DIV_FWD_BY_N, hint); 
     192 
     193  ippsDFTGetBufSize_R_32f(table->dftSpec, &bufferSize); 
     194  table->buffer = ippsMalloc_8u(bufferSize); 
     195 
     196  return table; 
     197} 
     198 
     199void spx_fft_destroy(void *table) 
     200{ 
     201  struct ipp_fft_config *t = (struct ipp_fft_config *)table; 
     202  ippsFree(t->buffer); 
     203  ippsDFTFree_R_32f(t->dftSpec); 
     204  speex_free(t); 
     205} 
     206 
     207void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out) 
     208{ 
     209  struct ipp_fft_config *t = (struct ipp_fft_config *)table; 
     210  ippsDFTFwd_RToPack_32f(in, out, t->dftSpec, t->buffer); 
     211} 
     212 
     213void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 
     214{ 
     215  struct ipp_fft_config *t = (struct ipp_fft_config *)table; 
     216  ippsDFTInv_PackToR_32f(in, out, t->dftSpec, t->buffer); 
     217} 
     218 
    168219#elif defined(USE_GPL_FFTW3) 
    169220 
     
    220271} 
    221272 
    222 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)  
     273void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out) 
    223274{ 
    224275  int i; 
     
    235286 
    236287  fftwf_execute(t->ifft); 
    237    
     288 
    238289  for(i=0;i<N;++i) 
    239290    out[i] = optr[i]; 
  • pjproject/trunk/third_party/speex/libspeex/fixed_bfin.h

    r2002 r6129  
    99   modification, are permitted provided that the following conditions 
    1010   are met: 
    11     
     11 
    1212   - Redistributions of source code must retain the above copyright 
    1313   notice, this list of conditions and the following disclaimer. 
    14     
     14 
    1515   - Redistributions in binary form must reproduce the above copyright 
    1616   notice, this list of conditions and the following disclaimer in the 
    1717   documentation and/or other materials provided with the distribution. 
    18     
     18 
    1919   - Neither the name of the Xiph.org Foundation nor the names of its 
    2020   contributors may be used to endorse or promote products derived from 
    2121   this software without specific prior written permission. 
    22     
     22 
    2323   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2424   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    3636#ifndef FIXED_BFIN_H 
    3737#define FIXED_BFIN_H 
     38 
     39#include "bfin.h" 
    3840 
    3941#undef PDIV32_16 
     
    5860   : "=m" (res) 
    5961   : "m" (a), "m" (bb) 
    60    : "P0", "R0", "R1", "cc"); 
     62   : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); 
    6163   return res; 
    6264} 
     
    6769   spx_word32_t res, bb; 
    6870   bb = b; 
    69    /* Make the roundinf consistent with the C version  
     71   /* Make the roundinf consistent with the C version 
    7072      (do we need to do that?)*/ 
    71    if (a<0)  
     73   if (a<0) 
    7274      a += (b-1); 
    7375   __asm__  ( 
     
    8587   : "=m" (res) 
    8688   : "m" (a), "m" (bb) 
    87    : "P0", "R0", "R1", "cc"); 
     89   : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); 
    8890   return res; 
    8991} 
     
    99101   : "=d" (res) 
    100102   : "%d" (a), "d" (b) 
     103   : "ASTAT" 
    101104   ); 
    102105   return res; 
     
    114117   : "=&W" (res), "=&d" (b) 
    115118   : "d" (a), "1" (b) 
    116    : "A1" 
     119   : "A1", "ASTAT" 
    117120   ); 
    118121   return res; 
     
    131134   : "=&W" (res), "=&d" (b) 
    132135   : "d" (a), "1" (b), "d" (c) 
    133    : "A1" 
     136   : "A1", "ASTAT" 
    134137         ); 
    135138   return res; 
     
    148151   : "=W" (res), "=d" (a), "=d" (b) 
    149152   : "1" (a), "2" (b) 
    150    : "A1" 
     153   : "A1", "ASTAT" 
    151154         ); 
    152155   return res; 
     
    166169   : "=&W" (res), "=&d" (b) 
    167170   : "d" (a), "1" (b), "d" (c) 
    168    : "A1" 
     171   : "A1", "ASTAT" 
    169172         ); 
    170173   return res; 
  • pjproject/trunk/third_party/speex/libspeex/fixed_generic.h

    r2002 r6129  
    88   modification, are permitted provided that the following conditions 
    99   are met: 
    10     
     10 
    1111   - Redistributions of source code must retain the above copyright 
    1212   notice, this list of conditions and the following disclaimer. 
    13     
     13 
    1414   - Redistributions in binary form must reproduce the above copyright 
    1515   notice, this list of conditions and the following disclaimer in the 
    1616   documentation and/or other materials provided with the distribution. 
    17     
     17 
    1818   - Neither the name of the Xiph.org Foundation nor the names of its 
    1919   contributors may be used to endorse or promote products derived from 
    2020   this software without specific prior written permission. 
    21     
     21 
    2222   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2323   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    5252#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 
    5353#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 
     54 
     55#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \ 
     56                                   (x)<=-(SHL32(a,shift)) ? -(a) : \ 
     57                                   (PSHR32(x, shift))) 
    5458 
    5559#define SHR(a,shift) ((a) >> (shift)) 
  • pjproject/trunk/third_party/speex/libspeex/jitter.c

    r2002 r6129  
    5656 
    5757#include "arch.h" 
    58 #include <speex/speex.h> 
    59 #include <speex/speex_bits.h> 
    6058#include <speex/speex_jitter.h> 
    6159#include "os_support.h" 
     
    467465   int i; 
    468466   unsigned int j; 
    469    int incomplete = 0; 
    470467   spx_int16_t opt; 
    471468    
     
    572569      { 
    573570         i=besti; 
    574          incomplete = 1; 
    575571         /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/ 
    576572      } 
  • pjproject/trunk/third_party/speex/libspeex/math_approx.h

    r2002 r6129  
    88   modification, are permitted provided that the following conditions 
    99   are met: 
    10     
     10 
    1111   - Redistributions of source code must retain the above copyright 
    1212   notice, this list of conditions and the following disclaimer. 
    13     
     13 
    1414   - Redistributions in binary form must reproduce the above copyright 
    1515   notice, this list of conditions and the following disclaimer in the 
    1616   documentation and/or other materials provided with the distribution. 
    17     
     17 
    1818   - Neither the name of the Xiph.org Foundation nor the names of its 
    1919   contributors may be used to endorse or promote products derived from 
    2020   this software without specific prior written permission. 
    21     
     21 
    2222   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2323   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    169169   } 
    170170   x = SUB16(16384,x); 
    171     
     171 
    172172   x = x >> 1; 
    173173   sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3)))))); 
    174174   ret = spx_sqrt(SHL32(EXTEND32(sq),13)); 
    175     
     175 
    176176   /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/ 
    177177   if (s) 
     
    209209{ 
    210210   spx_word16_t x2; 
    211     
     211 
    212212   x2 = MULT16_16_P15(x,x); 
    213213   return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2)))))))); 
  • pjproject/trunk/third_party/speex/libspeex/mdf.c

    r2198 r6129  
    1 /* Copyright (C) 2003-2006 Jean-Marc Valin 
     1/* Copyright (C) 2003-2008 Jean-Marc Valin 
    22 
    33   File: mdf.c 
     
    3434   The echo canceller is based on the MDF algorithm described in: 
    3535 
    36    J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter,  
    37    IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2,  
     36   J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, 
     37   IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, 
    3838   February 1990. 
    39     
    40    We use the Alternatively Updated MDF (AUMDF) variant. Robustness to  
     39 
     40   We use the Alternatively Updated MDF (AUMDF) variant. Robustness to 
    4141   double-talk is achieved using a variable learning rate as described in: 
    42     
    43    Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo  
     42 
     43   Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo 
    4444   Cancellation With Double-Talk. IEEE Transactions on Audio, 
    4545   Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007. 
    4646   http://people.xiph.org/~jm/papers/valin_taslp2006.pdf 
    47     
     47 
    4848   There is no explicit double-talk detection, but a continuous variation 
    4949   in the learning rate based on residual echo, double-talk and background 
    5050   noise. 
    51     
     51 
    5252   About the fixed-point version: 
    53    All the signals are represented with 16-bit words. The filter weights  
     53   All the signals are represented with 16-bit words. The filter weights 
    5454   are represented with 32-bit words, but only the top 16 bits are used 
    5555   in most cases. The lower 16 bits are completely unreliable (due to the 
     
    5757   adaptation -- probably by removing a "threshold effect" due to 
    5858   quantization (rounding going to zero) when the gradient is small. 
    59     
     59 
    6060   Another kludge that seems to work good: when performing the weight 
    6161   update, we only move half the way toward the "goal" this seems to 
     
    6363   can be seen as applying a gradient descent on a "soft constraint" 
    6464   instead of having a hard constraint. 
    65     
     65 
    6666*/ 
    6767 
     
    132132   int saturated; 
    133133   int screwed_up; 
     134   int C;                    /** Number of input channels (microphones) */ 
     135   int K;                    /** Number of output channels (loudspeakers) */ 
    134136   spx_int32_t sampling_rate; 
    135137   spx_word16_t spec_average; 
     
    138140   spx_word32_t sum_adapt; 
    139141   spx_word16_t leak_estimate; 
    140     
     142 
    141143   spx_word16_t *e;      /* scratch */ 
    142144   spx_word16_t *x;      /* Far-end input buffer (2N) */ 
     
    172174   spx_word16_t *prop; 
    173175   void *fft_table; 
    174    spx_word16_t memX, memD, memE; 
     176   spx_word16_t *memX, *memD, *memE; 
    175177   spx_word16_t preemph; 
    176178   spx_word16_t notch_radius; 
    177    spx_mem_t notch_mem[2]; 
     179   spx_mem_t *notch_mem; 
    178180 
    179181   /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ 
     
    183185}; 
    184186 
    185 static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem) 
     187static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride) 
    186188{ 
    187189   int i; 
     
    191193#else 
    192194   den2 = radius*radius + .7*(1-radius)*(1-radius); 
    193 #endif    
     195#endif 
    194196   /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ 
    195197   for (i=0;i<len;i++) 
    196198   { 
    197       spx_word16_t vin = in[i]; 
     199      spx_word16_t vin = in[i*stride]; 
    198200      spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15); 
    199201#ifdef FIXED_POINT 
     
    235237} 
    236238 
     239/** Compute power spectrum of a half-complex (packed) vector and accumulate */ 
     240static inline void power_spectrum_accum(const spx_word16_t *X, spx_word32_t *ps, int N) 
     241{ 
     242   int i, j; 
     243   ps[0]+=MULT16_16(X[0],X[0]); 
     244   for (i=1,j=1;i<N-1;i+=2,j++) 
     245   { 
     246      ps[j] +=  MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]); 
     247   } 
     248   ps[j]+=MULT16_16(X[i],X[i]); 
     249} 
     250 
    237251/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ 
    238252#ifdef FIXED_POINT 
     
    331345} 
    332346 
    333 static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, spx_word16_t *prop) 
    334 { 
    335    int i, j; 
     347static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, int P, spx_word16_t *prop) 
     348{ 
     349   int i, j, p; 
    336350   spx_word16_t max_sum = 1; 
    337351   spx_word32_t prop_sum = 1; 
     
    339353   { 
    340354      spx_word32_t tmp = 1; 
    341       for (j=0;j<N;j++) 
    342          tmp += MULT16_16(EXTRACT16(SHR32(W[i*N+j],18)), EXTRACT16(SHR32(W[i*N+j],18))); 
     355      for (p=0;p<P;p++) 
     356         for (j=0;j<N;j++) 
     357            tmp += MULT16_16(EXTRACT16(SHR32(W[p*N*M + i*N+j],18)), EXTRACT16(SHR32(W[p*N*M + i*N+j],18))); 
    343358#ifdef FIXED_POINT 
    344359      /* Just a security in case an overflow were to occur */ 
     
    379394 
    380395/** Creates a new echo canceller state */ 
    381 SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 
    382 { 
    383    int i,N,M; 
     396EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 
     397{ 
     398   return speex_echo_state_init_mc(frame_size, filter_length, 1, 1); 
     399} 
     400 
     401EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers) 
     402{ 
     403   int i,N,M, C, K; 
    384404   SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState)); 
    385405 
     406   st->K = nb_speakers; 
     407   st->C = nb_mic; 
     408   C=st->C; 
     409   K=st->K; 
    386410#ifdef DUMP_ECHO_CANCEL_DATA 
    387411   if (rFile || pFile || oFile) 
     
    391415   oFile = fopen("aec_out.sw", "wb"); 
    392416#endif 
    393     
     417 
    394418   st->frame_size = frame_size; 
    395419   st->window_size = 2*frame_size; 
     
    413437 
    414438   st->fft_table = spx_fft_init(N); 
    415     
    416    st->e = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 
    417    st->x = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 
    418    st->input = (spx_word16_t*)speex_alloc(st->frame_size*sizeof(spx_word16_t)); 
    419    st->y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 
    420    st->last_y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 
     439 
     440   st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 
     441   st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t)); 
     442   st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t)); 
     443   st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 
     444   st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 
    421445   st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 
    422446   st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 
     
    425449   st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 
    426450 
    427    st->X = (spx_word16_t*)speex_alloc((M+1)*N*sizeof(spx_word16_t)); 
    428    st->Y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 
    429    st->E = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 
    430    st->W = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t)); 
     451   st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t)); 
     452   st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 
     453   st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t)); 
     454   st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t)); 
    431455#ifdef TWO_PATH 
    432    st->foreground = (spx_word16_t*)speex_alloc(M*N*sizeof(spx_word16_t)); 
     456   st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t)); 
    433457#endif 
    434458   st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 
     
    451475   for (i=0;i<=st->frame_size;i++) 
    452476      st->power_1[i] = FLOAT_ONE; 
    453    for (i=0;i<N*M;i++) 
     477   for (i=0;i<N*M*K*C;i++) 
    454478      st->W[i] = 0; 
    455479   { 
     
    466490      for (i=M-1;i>=0;i--) 
    467491      { 
    468          st->prop[i] = DIV32(MULT16_16(QCONST16(.8,15), st->prop[i]),sum); 
    469       } 
    470    } 
    471     
    472    st->memX=st->memD=st->memE=0; 
     492         st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum); 
     493      } 
     494   } 
     495 
     496   st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t)); 
     497   st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); 
     498   st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t)); 
    473499   st->preemph = QCONST16(.9,15); 
    474500   if (st->sampling_rate<12000) 
     
    479505      st->notch_radius = QCONST16(.992, 15); 
    480506 
    481    st->notch_mem[0] = st->notch_mem[1] = 0; 
     507   st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t)); 
    482508   st->adapted = 0; 
    483509   st->Pey = st->Pyy = FLOAT_ONE; 
    484     
     510 
    485511#ifdef TWO_PATH 
    486512   st->Davg1 = st->Davg2 = 0; 
    487513   st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 
    488514#endif 
    489     
    490    st->play_buf = (spx_int16_t*)speex_alloc((PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); 
     515 
     516   st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); 
    491517   st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; 
    492518   st->play_buf_started = 0; 
    493     
     519 
    494520   return st; 
    495521} 
    496522 
    497523/** Resets echo canceller state */ 
    498 void speex_echo_state_reset(SpeexEchoState *st) 
    499 { 
    500    int i, M, N; 
     524EXPORT void speex_echo_state_reset(SpeexEchoState *st) 
     525{ 
     526   int i, M, N, C, K; 
    501527   st->cancel_count=0; 
    502528   st->screwed_up = 0; 
    503529   N = st->window_size; 
    504530   M = st->M; 
     531   C=st->C; 
     532   K=st->K; 
    505533   for (i=0;i<N*M;i++) 
    506534      st->W[i] = 0; 
     
    522550      st->last_y[i] = 0; 
    523551   } 
    524    for (i=0;i<N;i++) 
     552   for (i=0;i<N*C;i++) 
    525553   { 
    526554      st->E[i] = 0; 
     555   } 
     556   for (i=0;i<N*K;i++) 
     557   { 
    527558      st->x[i] = 0; 
    528559   } 
    529    st->notch_mem[0] = st->notch_mem[1] = 0; 
    530    st->memX=st->memD=st->memE=0; 
     560   for (i=0;i<2*C;i++) 
     561      st->notch_mem[i] = 0; 
     562   for (i=0;i<C;i++) 
     563      st->memD[i]=st->memE[i]=0; 
     564   for (i=0;i<K;i++) 
     565      st->memX[i]=0; 
    531566 
    532567   st->saturated = 0; 
     
    546581 
    547582/** Destroys an echo canceller state */ 
    548 void speex_echo_state_destroy(SpeexEchoState *st) 
     583EXPORT void speex_echo_state_destroy(SpeexEchoState *st) 
    549584{ 
    550585   spx_fft_destroy(st->fft_table); 
     
    577612   speex_free(st->wtmp2); 
    578613#endif 
     614   speex_free(st->memX); 
     615   speex_free(st->memD); 
     616   speex_free(st->memE); 
     617   speex_free(st->notch_mem); 
     618 
    579619   speex_free(st->play_buf); 
    580620   speex_free(st); 
    581     
     621 
    582622#ifdef DUMP_ECHO_CANCEL_DATA 
    583623   fclose(rFile); 
     
    588628} 
    589629 
    590 void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) 
     630EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) 
    591631{ 
    592632   int i; 
     
    611651} 
    612652 
    613 void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 
     653EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 
    614654{ 
    615655   /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/ 
     
    638678 
    639679/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */ 
    640 void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) 
     680EXPORT void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) 
    641681{ 
    642682   speex_echo_cancellation(st, in, far_end, out); 
     
    644684 
    645685/** Performs echo cancellation on a frame */ 
    646 void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) 
    647 { 
    648    int i,j; 
    649    int N,M; 
     686EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) 
     687{ 
     688   int i,j, chan, speak; 
     689   int N,M, C, K; 
    650690   spx_word32_t Syy,See,Sxx,Sdd, Sff; 
    651691#ifdef TWO_PATH 
     
    659699   spx_word16_t RER; 
    660700   spx_word32_t tmp32; 
    661     
     701 
    662702   N = st->window_size; 
    663703   M = st->M; 
     704   C = st->C; 
     705   K = st->K; 
     706 
    664707   st->cancel_count++; 
    665708#ifdef FIXED_POINT 
     
    671714#endif 
    672715 
    673    /* Apply a notch filter to make sure DC doesn't end up causing problems */ 
    674    filter_dc_notch16(in, st->notch_radius, st->input, st->frame_size, st->notch_mem); 
    675    /* Copy input data to buffer and apply pre-emphasis */ 
    676    for (i=0;i<st->frame_size;i++) 
    677    { 
    678       spx_word32_t tmp32; 
    679       tmp32 = SUB32(EXTEND32(far_end[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memX))); 
    680 #ifdef FIXED_POINT 
    681       /* If saturation occurs here, we need to freeze adaptation for M+1 frames (not just one) */ 
    682       if (tmp32 > 32767) 
    683       { 
    684          tmp32 = 32767; 
    685          st->saturated = M+1; 
    686       } 
    687       if (tmp32 < -32767) 
    688       { 
    689          tmp32 = -32767; 
    690          st->saturated = M+1; 
    691       }       
    692 #endif 
    693       st->x[i+st->frame_size] = EXTRACT16(tmp32); 
    694       st->memX = far_end[i]; 
    695        
    696       tmp32 = SUB32(EXTEND32(st->input[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD))); 
    697 #ifdef FIXED_POINT 
    698       if (tmp32 > 32767) 
    699       { 
    700          tmp32 = 32767; 
    701          if (st->saturated == 0) 
    702             st->saturated = 1; 
    703       }       
    704       if (tmp32 < -32767) 
    705       { 
    706          tmp32 = -32767; 
    707          if (st->saturated == 0) 
    708             st->saturated = 1; 
    709       } 
    710 #endif 
    711       st->memD = st->input[i]; 
    712       st->input[i] = tmp32; 
    713    } 
    714  
    715    /* Shift memory: this could be optimized eventually*/ 
    716    for (j=M-1;j>=0;j--) 
    717    { 
    718       for (i=0;i<N;i++) 
    719          st->X[(j+1)*N+i] = st->X[j*N+i]; 
    720    } 
    721  
    722    /* Convert x (far end) to frequency domain */ 
    723    spx_fft(st->fft_table, st->x, &st->X[0]); 
    724    for (i=0;i<N;i++) 
    725       st->last_y[i] = st->x[i]; 
    726    Sxx = mdf_inner_prod(st->x+st->frame_size, st->x+st->frame_size, st->frame_size); 
    727    for (i=0;i<st->frame_size;i++) 
    728       st->x[i] = st->x[i+st->frame_size]; 
    729    /* From here on, the top part of x is used as scratch space */ 
    730     
     716   for (chan = 0; chan < C; chan++) 
     717   { 
     718      /* Apply a notch filter to make sure DC doesn't end up causing problems */ 
     719      filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C); 
     720      /* Copy input data to buffer and apply pre-emphasis */ 
     721      /* Copy input data to buffer */ 
     722      for (i=0;i<st->frame_size;i++) 
     723      { 
     724         spx_word32_t tmp32; 
     725         /* FIXME: This core has changed a bit, need to merge properly */ 
     726         tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan]))); 
     727#ifdef FIXED_POINT 
     728         if (tmp32 > 32767) 
     729         { 
     730            tmp32 = 32767; 
     731            if (st->saturated == 0) 
     732               st->saturated = 1; 
     733         } 
     734         if (tmp32 < -32767) 
     735         { 
     736            tmp32 = -32767; 
     737            if (st->saturated == 0) 
     738               st->saturated = 1; 
     739         } 
     740#endif 
     741         st->memD[chan] = st->input[chan*st->frame_size+i]; 
     742         st->input[chan*st->frame_size+i] = EXTRACT16(tmp32); 
     743      } 
     744   } 
     745 
     746   for (speak = 0; speak < K; speak++) 
     747   { 
     748      for (i=0;i<st->frame_size;i++) 
     749      { 
     750         spx_word32_t tmp32; 
     751         st->x[speak*N+i] = st->x[speak*N+i+st->frame_size]; 
     752         tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak]))); 
     753#ifdef FIXED_POINT 
     754         /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */ 
     755         if (tmp32 > 32767) 
     756         { 
     757            tmp32 = 32767; 
     758            st->saturated = M+1; 
     759         } 
     760         if (tmp32 < -32767) 
     761         { 
     762            tmp32 = -32767; 
     763            st->saturated = M+1; 
     764         } 
     765#endif 
     766         st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32); 
     767         st->memX[speak] = far_end[i*K+speak]; 
     768      } 
     769   } 
     770 
     771   for (speak = 0; speak < K; speak++) 
     772   { 
     773      /* Shift memory: this could be optimized eventually*/ 
     774      for (j=M-1;j>=0;j--) 
     775      { 
     776         for (i=0;i<N;i++) 
     777            st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i]; 
     778      } 
     779      /* Convert x (echo input) to frequency domain */ 
     780      spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]); 
     781   } 
     782 
     783   Sxx = 0; 
     784   for (speak = 0; speak < K; speak++) 
     785   { 
     786      Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); 
     787      power_spectrum_accum(st->X+speak*N, st->Xf, N); 
     788   } 
     789 
     790   Sff = 0; 
     791   for (chan = 0; chan < C; chan++) 
     792   { 
    731793#ifdef TWO_PATH 
    732    /* Compute foreground filter */ 
    733    spectral_mul_accum16(st->X, st->foreground, st->Y, N, M);    
    734    spx_ifft(st->fft_table, st->Y, st->e); 
    735    for (i=0;i<st->frame_size;i++) 
    736       st->e[i] = SUB16(st->input[i], st->e[i+st->frame_size]); 
    737    Sff = mdf_inner_prod(st->e, st->e, st->frame_size); 
    738 #endif 
    739     
     794      /* Compute foreground filter */ 
     795      spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K); 
     796      spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N); 
     797      for (i=0;i<st->frame_size;i++) 
     798         st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]); 
     799      Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 
     800#endif 
     801   } 
     802 
    740803   /* Adjust proportional adaption rate */ 
    741    mdf_adjust_prop (st->W, N, M, st->prop); 
     804   /* FIXME: Adjust that for C, K*/ 
     805   if (st->adapted) 
     806      mdf_adjust_prop (st->W, N, M, C*K, st->prop); 
    742807   /* Compute weight gradient */ 
    743808   if (st->saturated == 0) 
    744809   { 
    745       for (j=M-1;j>=0;j--) 
    746       { 
    747          weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N], st->E, st->PHI, N); 
    748          for (i=0;i<N;i++) 
    749             st->W[j*N+i] = ADD32(st->W[j*N+i], st->PHI[i]); 
    750           
     810      for (chan = 0; chan < C; chan++) 
     811      { 
     812         for (speak = 0; speak < K; speak++) 
     813         { 
     814            for (j=M-1;j>=0;j--) 
     815            { 
     816               weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N*K+speak*N], st->E+chan*N, st->PHI, N); 
     817               for (i=0;i<N;i++) 
     818                  st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i]; 
     819            } 
     820         } 
    751821      } 
    752822   } else { 
    753823      st->saturated--; 
    754824   } 
    755     
     825 
     826   /* FIXME: MC conversion required */ 
    756827   /* Update weight to prevent circular convolution (MDF / AUMDF) */ 
    757    for (j=0;j<M;j++) 
    758    { 
    759       /* This is a variant of the Alternatively Updated MDF (AUMDF) */ 
    760       /* Remove the "if" to make this an MDF filter */ 
    761       if (j==0 || st->cancel_count%(M-1) == j-1) 
    762       { 
    763 #ifdef FIXED_POINT 
    764          for (i=0;i<N;i++) 
    765             st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16)); 
    766          spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 
    767          for (i=0;i<st->frame_size;i++) 
     828   for (chan = 0; chan < C; chan++) 
     829   { 
     830      for (speak = 0; speak < K; speak++) 
     831      { 
     832         for (j=0;j<M;j++) 
    768833         { 
    769             st->wtmp[i]=0; 
     834            /* This is a variant of the Alternatively Updated MDF (AUMDF) */ 
     835            /* Remove the "if" to make this an MDF filter */ 
     836            if (j==0 || st->cancel_count%(M-1) == j-1) 
     837            { 
     838#ifdef FIXED_POINT 
     839               for (i=0;i<N;i++) 
     840                  st->wtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16)); 
     841               spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 
     842               for (i=0;i<st->frame_size;i++) 
     843               { 
     844                  st->wtmp[i]=0; 
     845               } 
     846               for (i=st->frame_size;i<N;i++) 
     847               { 
     848                  st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 
     849               } 
     850               spx_fft(st->fft_table, st->wtmp, st->wtmp2); 
     851               /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 
     852               for (i=0;i<N;i++) 
     853                  st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 
     854#else 
     855               spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp); 
     856               for (i=st->frame_size;i<N;i++) 
     857               { 
     858                  st->wtmp[i]=0; 
     859               } 
     860               spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]); 
     861#endif 
     862            } 
    770863         } 
    771          for (i=st->frame_size;i<N;i++) 
    772          { 
    773             st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 
    774          } 
    775          spx_fft(st->fft_table, st->wtmp, st->wtmp2); 
    776          /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 
    777          for (i=0;i<N;i++) 
    778             st->W[j*N+i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 
    779 #else 
    780          spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 
    781          for (i=st->frame_size;i<N;i++) 
    782          { 
    783             st->wtmp[i]=0; 
    784          } 
    785          spx_fft(st->fft_table, st->wtmp, &st->W[j*N]); 
    786 #endif 
    787       } 
    788    } 
    789  
    790    /* Compute filter response Y */ 
    791    spectral_mul_accum(st->X, st->W, st->Y, N, M); 
    792    spx_ifft(st->fft_table, st->Y, st->y); 
    793  
     864      } 
     865   } 
     866 
     867   /* So we can use power_spectrum_accum */ 
     868   for (i=0;i<=st->frame_size;i++) 
     869      st->Rf[i] = st->Yf[i] = st->Xf[i] = 0; 
     870 
     871   Dbf = 0; 
     872   See = 0; 
    794873#ifdef TWO_PATH 
    795874   /* Difference in response, this is used to estimate the variance of our residual power estimate */ 
    796    for (i=0;i<st->frame_size;i++) 
    797       st->e[i] = SUB16(st->e[i+st->frame_size], st->y[i+st->frame_size]); 
    798    Dbf = 10+mdf_inner_prod(st->e, st->e, st->frame_size); 
    799 #endif 
    800  
    801    for (i=0;i<st->frame_size;i++) 
    802       st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]); 
    803    See = mdf_inner_prod(st->e, st->e, st->frame_size); 
     875   for (chan = 0; chan < C; chan++) 
     876   { 
     877      spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K); 
     878      spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N); 
     879      for (i=0;i<st->frame_size;i++) 
     880         st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]); 
     881      Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 
     882      for (i=0;i<st->frame_size;i++) 
     883         st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); 
     884      See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size); 
     885   } 
     886#endif 
     887 
    804888#ifndef TWO_PATH 
    805889   Sff = See; 
     
    808892#ifdef TWO_PATH 
    809893   /* Logic for updating the foreground filter */ 
    810     
     894 
    811895   /* For two time windows, compute the mean of the energy difference, as well as the variance */ 
    812896   st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See))); 
     
    814898   st->Dvar1 = FLOAT_ADD(FLOAT_MULT(VAR1_SMOOTH, st->Dvar1), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff), MULT16_32_Q15(QCONST16(.4f,15),Dbf))); 
    815899   st->Dvar2 = FLOAT_ADD(FLOAT_MULT(VAR2_SMOOTH, st->Dvar2), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff), MULT16_32_Q15(QCONST16(.15f,15),Dbf))); 
    816     
     900 
    817901   /* Equivalent float code: 
    818902   st->Davg1 = .6*st->Davg1 + .4*(Sff-See); 
     
    821905   st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf; 
    822906   */ 
    823     
     907 
    824908   update_foreground = 0; 
    825909   /* Check if we have a statistically significant reduction in the residual echo */ 
     
    831915   else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2)))) 
    832916      update_foreground = 1; 
    833     
     917 
    834918   /* Do we update? */ 
    835919   if (update_foreground) 
     
    838922      st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 
    839923      /* Copy background filter to foreground filter */ 
    840       for (i=0;i<N*M;i++) 
     924      for (i=0;i<N*M*C*K;i++) 
    841925         st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16)); 
    842926      /* Apply a smooth transition so as to not introduce blocking artifacts */ 
    843       for (i=0;i<st->frame_size;i++) 
    844          st->e[i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[i+st->frame_size]); 
     927      for (chan = 0; chan < C; chan++) 
     928         for (i=0;i<st->frame_size;i++) 
     929            st->e[chan*N+i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[chan*N+i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[chan*N+i+st->frame_size]); 
    845930   } else { 
    846931      int reset_background=0; 
     
    855940      { 
    856941         /* Copy foreground filter to background filter */ 
    857          for (i=0;i<N*M;i++) 
     942         for (i=0;i<N*M*C*K;i++) 
    858943            st->W[i] = SHL32(EXTEND32(st->foreground[i]),16); 
    859944         /* We also need to copy the output so as to get correct adaptation */ 
    860          for (i=0;i<st->frame_size;i++) 
    861             st->y[i+st->frame_size] = st->e[i+st->frame_size]; 
    862          for (i=0;i<st->frame_size;i++) 
    863             st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]); 
     945         for (chan = 0; chan < C; chan++) 
     946         { 
     947            for (i=0;i<st->frame_size;i++) 
     948               st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size]; 
     949            for (i=0;i<st->frame_size;i++) 
     950               st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]); 
     951         } 
    864952         See = Sff; 
    865953         st->Davg1 = st->Davg2 = 0; 
     
    869957#endif 
    870958 
    871    /* Compute error signal (for the output with de-emphasis) */  
    872    for (i=0;i<st->frame_size;i++) 
    873    { 
    874       spx_word32_t tmp_out; 
     959   Sey = Syy = Sdd = 0; 
     960   for (chan = 0; chan < C; chan++) 
     961   { 
     962      /* Compute error signal (for the output with de-emphasis) */ 
     963      for (i=0;i<st->frame_size;i++) 
     964      { 
     965         spx_word32_t tmp_out; 
    875966#ifdef TWO_PATH 
    876       tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->e[i+st->frame_size])); 
    877 #else 
    878       tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->y[i+st->frame_size])); 
    879 #endif 
    880       /* Saturation */ 
    881       if (tmp_out>32767) 
    882          tmp_out = 32767; 
    883       else if (tmp_out<-32768) 
    884          tmp_out = -32768; 
    885       tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE))); 
     967         tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size])); 
     968#else 
     969         tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size])); 
     970#endif 
     971         tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan]))); 
    886972      /* This is an arbitrary test for saturation in the microphone signal */ 
    887       if (in[i] <= -32000 || in[i] >= 32000) 
    888       { 
    889          tmp_out = 0; 
     973         if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000) 
     974         { 
    890975         if (st->saturated == 0) 
    891976            st->saturated = 1; 
    892       } 
    893       out[i] = (spx_int16_t)tmp_out; 
    894       st->memE = tmp_out; 
    895    } 
    896     
     977         } 
     978         out[i*C+chan] = WORD2INT(tmp_out); 
     979         st->memE[chan] = tmp_out; 
     980      } 
     981 
    897982#ifdef DUMP_ECHO_CANCEL_DATA 
    898    dump_audio(in, far_end, out, st->frame_size); 
    899 #endif 
    900     
    901    /* Compute error signal (filter update version) */  
    902    for (i=0;i<st->frame_size;i++) 
    903    { 
    904       st->e[i+st->frame_size] = st->e[i]; 
    905       st->e[i] = 0; 
    906    } 
    907  
    908    /* Compute a bunch of correlations */ 
    909    Sey = mdf_inner_prod(st->e+st->frame_size, st->y+st->frame_size, st->frame_size); 
    910    Syy = mdf_inner_prod(st->y+st->frame_size, st->y+st->frame_size, st->frame_size); 
    911    Sdd = mdf_inner_prod(st->input, st->input, st->frame_size); 
    912     
     983      dump_audio(in, far_end, out, st->frame_size); 
     984#endif 
     985 
     986      /* Compute error signal (filter update version) */ 
     987      for (i=0;i<st->frame_size;i++) 
     988      { 
     989         st->e[chan*N+i+st->frame_size] = st->e[chan*N+i]; 
     990         st->e[chan*N+i] = 0; 
     991      } 
     992 
     993      /* Compute a bunch of correlations */ 
     994      /* FIXME: bad merge */ 
     995      Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); 
     996      Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size); 
     997      Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size); 
     998 
     999      /* Convert error to frequency domain */ 
     1000      spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N); 
     1001      for (i=0;i<st->frame_size;i++) 
     1002         st->y[i+chan*N] = 0; 
     1003      spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N); 
     1004 
     1005      /* Compute power spectrum of echo (X), error (E) and filter response (Y) */ 
     1006      power_spectrum_accum(st->E+chan*N, st->Rf, N); 
     1007      power_spectrum_accum(st->Y+chan*N, st->Yf, N); 
     1008 
     1009   } 
     1010 
    9131011   /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/ 
    914     
     1012 
    9151013   /* Do some sanity check */ 
    9161014   if (!(Syy>=0 && Sxx>=0 && See >= 0) 
     
    9221020      /* Things have gone really bad */ 
    9231021      st->screwed_up += 50; 
    924       for (i=0;i<st->frame_size;i++) 
     1022      for (i=0;i<st->frame_size*C;i++) 
    9251023         out[i] = 0; 
    9261024   } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6))) 
     
    9421040   See = MAX32(See, SHR32(MULT16_16(N, 100),6)); 
    9431041 
    944    /* Convert error to frequency domain */ 
    945    spx_fft(st->fft_table, st->e, st->E); 
    946    for (i=0;i<st->frame_size;i++) 
    947       st->y[i] = 0; 
    948    spx_fft(st->fft_table, st->y, st->Y); 
    949  
    950    /* Compute power spectrum of far end (X), error (E) and filter response (Y) */ 
    951    power_spectrum(st->E, st->Rf, N); 
    952    power_spectrum(st->Y, st->Yf, N); 
    953    power_spectrum(st->X, st->Xf, N); 
    954     
     1042   for (speak = 0; speak < K; speak++) 
     1043   { 
     1044      Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size); 
     1045      power_spectrum_accum(st->X+speak*N, st->Xf, N); 
     1046   } 
     1047 
     1048 
    9551049   /* Smooth far end energy estimate over time */ 
    9561050   for (j=0;j<=st->frame_size;j++) 
    9571051      st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]); 
    958     
    959    /* Enable this to compute the power based only on the tail (would need to compute more  
    960       efficiently to make this really useful */ 
    961    if (0) 
    962    { 
    963       float scale2 = .5f/M; 
    964       for (j=0;j<=st->frame_size;j++) 
    965          st->power[j] = 100; 
    966       for (i=0;i<M;i++) 
    967       { 
    968          power_spectrum(&st->X[i*N], st->Xf, N); 
    969          for (j=0;j<=st->frame_size;j++) 
    970             st->power[j] += scale2*st->Xf[j]; 
    971       } 
    972    } 
    9731052 
    9741053   /* Compute filtered spectra and (cross-)correlations */ 
     
    9881067#endif 
    9891068   } 
    990     
     1069 
    9911070   Pyy = FLOAT_SQRT(Pyy); 
    9921071   Pey = FLOAT_DIVU(Pey,Pyy); 
     
    10161095      st->leak_estimate = SHL16(st->leak_estimate,1); 
    10171096   /*printf ("%f\n", st->leak_estimate);*/ 
    1018     
     1097 
    10191098   /* Compute Residual to Error Ratio */ 
    10201099#ifdef FIXED_POINT 
     
    10721151      spx_word16_t adapt_rate=0; 
    10731152 
    1074       if (Sxx > SHR32(MULT16_16(N, 1000),6))  
     1153      if (Sxx > SHR32(MULT16_16(N, 1000),6)) 
    10751154      { 
    10761155         tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx); 
     
    10921171   } 
    10931172 
    1094    /* Save residual echo so it can be used by the nonlinear processor */ 
    1095    if (st->adapted) 
    1096    { 
    1097       /* If the filter is adapted, take the filtered echo */ 
     1173   /* FIXME: MC conversion required */ 
    10981174      for (i=0;i<st->frame_size;i++) 
    10991175         st->last_y[i] = st->last_y[st->frame_size+i]; 
     1176   if (st->adapted) 
     1177   { 
     1178      /* If the filter is adapted, take the filtered echo */ 
    11001179      for (i=0;i<st->frame_size;i++) 
    11011180         st->last_y[st->frame_size+i] = in[i]-out[i]; 
     
    11141193   spx_word16_t leak2; 
    11151194   int N; 
    1116     
     1195 
    11171196   N = st->window_size; 
    11181197 
     
    11201199   for (i=0;i<N;i++) 
    11211200      st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]); 
    1122        
     1201 
    11231202   /* Compute power spectrum of the echo */ 
    11241203   spx_fft(st->fft_table, st->y, st->Y); 
    11251204   power_spectrum(st->Y, residual_echo, N); 
    1126        
     1205 
    11271206#ifdef FIXED_POINT 
    11281207   if (st->leak_estimate > 16383) 
     
    11391218   for (i=0;i<=st->frame_size;i++) 
    11401219      residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]); 
    1141     
    1142 } 
    1143  
    1144 int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) 
     1220 
     1221} 
     1222 
     1223EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) 
    11451224{ 
    11461225   switch(request) 
    11471226   { 
    1148        
     1227 
    11491228      case SPEEX_ECHO_GET_FRAME_SIZE: 
    11501229         (*(int*)ptr) = st->frame_size; 
     
    11701249         (*(int*)ptr) = st->sampling_rate; 
    11711250         break; 
     1251      case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE: 
     1252         /*FIXME: Implement this for multiple channels */ 
     1253         *((spx_int32_t *)ptr) = st->M * st->frame_size; 
     1254         break; 
     1255      case SPEEX_ECHO_GET_IMPULSE_RESPONSE: 
     1256      { 
     1257         int M = st->M, N = st->window_size, n = st->frame_size, i, j; 
     1258         spx_int32_t *filt = (spx_int32_t *) ptr; 
     1259         for(j=0;j<M;j++) 
     1260         { 
     1261            /*FIXME: Implement this for multiple channels */ 
     1262#ifdef FIXED_POINT 
     1263            for (i=0;i<N;i++) 
     1264               st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN)); 
     1265            spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 
     1266#else 
     1267            spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 
     1268#endif 
     1269            for(i=0;i<n;i++) 
     1270               filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN); 
     1271         } 
     1272      } 
     1273         break; 
    11721274      default: 
    11731275         speex_warning_int("Unknown speex_echo_ctl request: ", request); 
  • pjproject/trunk/third_party/speex/libspeex/misc_bfin.h

    r2002 r6129  
    22/** 
    33   @file misc_bfin.h 
    4    @author Jean-Marc Valin  
     4   @author Jean-Marc Valin 
    55   @brief Various compatibility routines for Speex (Blackfin version) 
    66*/ 
     
    99   modification, are permitted provided that the following conditions 
    1010   are met: 
    11     
     11 
    1212   - Redistributions of source code must retain the above copyright 
    1313   notice, this list of conditions and the following disclaimer. 
    14     
     14 
    1515   - Redistributions in binary form must reproduce the above copyright 
    1616   notice, this list of conditions and the following disclaimer in the 
    1717   documentation and/or other materials provided with the distribution. 
    18     
     18 
    1919   - Neither the name of the Xiph.org Foundation nor the names of its 
    2020   contributors may be used to endorse or promote products derived from 
    2121   this software without specific prior written permission. 
    22     
     22 
    2323   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2424   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    3333   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    3434*/ 
     35 
     36#include "bfin.h" 
    3537 
    3638#define OVERRIDE_SPEEX_MOVE 
     
    4951   : "=a" (src), "=a" (dest) 
    5052   : "a" ((n>>2)-1), "0" (src), "1" (dest) 
    51    : "R0", "I0", "L0", "memory" 
     53   : "R0", "I0", "L0", "memory" BFIN_HWLOOP0_REGS 
    5254         ); 
    5355   return dest; 
  • pjproject/trunk/third_party/speex/libspeex/os_support.h

    r2002 r6129  
    11/* Copyright (C) 2007 Jean-Marc Valin 
    2        
     2 
    33   File: os_support.h 
    44   This is the (tiny) OS abstraction layer. Aside from math.h, this is the 
     
    4646#endif 
    4747 
    48 /** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free  
     48/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free 
    4949    NOTE: speex_alloc needs to CLEAR THE MEMORY */ 
    5050#ifndef OVERRIDE_SPEEX_ALLOC 
    5151static inline void *speex_alloc (int size) 
    5252{ 
    53    /* WARNING: this is not equivalent to malloc(). If you want to use malloc()  
     53   /* WARNING: this is not equivalent to malloc(). If you want to use malloc() 
    5454      or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise 
    5555      you will experience strange bugs */ 
     
    9191#endif 
    9292 
    93 /** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking  */ 
     93/** Copy n elements from src to dst. The 0* term provides compile-time type checking  */ 
    9494#ifndef OVERRIDE_SPEEX_COPY 
    9595#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) 
    9696#endif 
    9797 
    98 /** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term  
     98/** Copy n elements from src to dst, allowing overlapping regions. The 0* term 
    9999    provides compile-time type checking */ 
    100100#ifndef OVERRIDE_SPEEX_MOVE 
     
    102102#endif 
    103103 
    104 /** Set n bytes of memory to value of c, starting at address s */ 
     104/** For n elements worth of memory, set every byte to the value of c, starting at address dst */ 
    105105#ifndef OVERRIDE_SPEEX_MEMSET 
    106106#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) 
  • pjproject/trunk/third_party/speex/libspeex/resample.c

    r2002 r6129  
    11/* Copyright (C) 2007-2008 Jean-Marc Valin 
    22   Copyright (C) 2008      Thorvald Natvig 
    3        
     3 
    44   File: resample.c 
    55   Arbitrary resampling code 
     
    3939      - Good *perceptual* quality (and not best SNR) 
    4040 
    41    Warning: This resampler is relatively new. Although I think I got rid of  
     41   Warning: This resampler is relatively new. Although I think I got rid of 
    4242   all the major bugs and I don't expect the API to change anymore, there 
    4343   may be something I've missed. So use with caution. 
     
    4545   This algorithm is based on this original resampling algorithm: 
    4646   Smith, Julius O. Digital Audio Resampling Home Page 
    47    Center for Computer Research in Music and Acoustics (CCRMA),  
     47   Center for Computer Research in Music and Acoustics (CCRMA), 
    4848   Stanford University, 2007. 
    49    Web published at http://www-ccrma.stanford.edu/~jos/resample/. 
    50  
    51    There is one main difference, though. This resampler uses cubic  
     49   Web published at https://ccrma.stanford.edu/~jos/resample/. 
     50 
     51   There is one main difference, though. This resampler uses cubic 
    5252   interpolation instead of linear interpolation in the above paper. This 
    5353   makes the table much smaller and makes it possible to compute that table 
    54    on a per-stream basis. In turn, being able to tweak the table for each  
    55    stream makes it possible to both reduce complexity on simple ratios  
    56    (e.g. 2/3), and get rid of the rounding operations in the inner loop.  
     54   on a per-stream basis. In turn, being able to tweak the table for each 
     55   stream makes it possible to both reduce complexity on simple ratios 
     56   (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
    5757   The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 
    5858*/ 
     
    6464#ifdef OUTSIDE_SPEEX 
    6565#include <stdlib.h> 
    66 static void *speex_alloc (int size) {return calloc(size,1);} 
    67 static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} 
    68 static void speex_free (void *ptr) {free(ptr);} 
     66static void *speex_alloc(int size) {return calloc(size,1);} 
     67static void *speex_realloc(void *ptr, int size) {return realloc(ptr, size);} 
     68static void speex_free(void *ptr) {free(ptr);} 
     69#ifndef EXPORT 
     70#define EXPORT 
     71#endif 
    6972#include "speex_resampler.h" 
    7073#include "arch.h" 
    7174#else /* OUTSIDE_SPEEX */ 
    72                 
     75 
    7376#include "speex/speex_resampler.h" 
    7477#include "arch.h" 
     
    7679#endif /* OUTSIDE_SPEEX */ 
    7780 
    78 #include "stack_alloc.h" 
    7981#include <math.h> 
     82#include <limits.h> 
    8083 
    8184#ifndef M_PI 
    82 #define M_PI 3.14159263 
    83 #endif 
    84  
    85 #ifdef FIXED_POINT 
    86 #define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))   
    87 #else 
    88 #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))   
    89 #endif 
    90                 
     85#define M_PI 3.14159265358979323846 
     86#endif 
     87 
    9188#define IMAX(a,b) ((a) > (b) ? (a) : (b)) 
    9289#define IMIN(a,b) ((a) < (b) ? (a) : (b)) 
     
    9693#endif 
    9794 
    98 #ifdef _USE_SSE 
     95#ifndef UINT32_MAX 
     96#define UINT32_MAX 4294967295U 
     97#endif 
     98 
     99#ifdef USE_SSE 
    99100#include "resample_sse.h" 
     101#endif 
     102 
     103#ifdef USE_NEON 
     104#include "resample_neon.h" 
    100105#endif 
    101106 
     
    114119   spx_uint32_t num_rate; 
    115120   spx_uint32_t den_rate; 
    116     
     121 
    117122   int    quality; 
    118123   spx_uint32_t nb_channels; 
     
    126131   int          initialised; 
    127132   int          started; 
    128     
     133 
    129134   /* These are per-channel */ 
    130135   spx_int32_t  *last_sample; 
    131136   spx_uint32_t *samp_frac_num; 
    132137   spx_uint32_t *magic_samples; 
    133     
     138 
    134139   spx_word16_t *mem; 
    135140   spx_word16_t *sinc_table; 
    136141   spx_uint32_t sinc_table_length; 
    137142   resampler_basic_func resampler_ptr; 
    138           
     143 
    139144   int    in_stride; 
    140145   int    out_stride; 
    141146} ; 
    142147 
    143 static double kaiser12_table[68] = { 
     148static const double kaiser12_table[68] = { 
    144149   0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, 
    145150   0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, 
     
    155160   0.00001000, 0.00000000}; 
    156161/* 
    157 static double kaiser12_table[36] = { 
     162static const double kaiser12_table[36] = { 
    158163   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, 
    159164   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, 
     
    163168   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; 
    164169*/ 
    165 static double kaiser10_table[36] = { 
     170static const double kaiser10_table[36] = { 
    166171   0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, 
    167172   0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, 
     
    171176   0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; 
    172177 
    173 static double kaiser8_table[36] = { 
     178static const double kaiser8_table[36] = { 
    174179   0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, 
    175180   0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, 
     
    178183   0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 
    179184   0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 
    180     
    181 static double kaiser6_table[36] = { 
     185 
     186static const double kaiser6_table[36] = { 
    182187   0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 
    183188   0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, 
     
    188193 
    189194struct FuncDef { 
    190    double *table; 
     195   const double *table; 
    191196   int oversample; 
    192197}; 
    193        
    194 static struct FuncDef _KAISER12 = {kaiser12_table, 64}; 
    195 #define KAISER12 (&_KAISER12) 
    196 /*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; 
    197 #define KAISER12 (&_KAISER12)*/ 
    198 static struct FuncDef _KAISER10 = {kaiser10_table, 32}; 
    199 #define KAISER10 (&_KAISER10) 
    200 static struct FuncDef _KAISER8 = {kaiser8_table, 32}; 
    201 #define KAISER8 (&_KAISER8) 
    202 static struct FuncDef _KAISER6 = {kaiser6_table, 32}; 
    203 #define KAISER6 (&_KAISER6) 
     198 
     199static const struct FuncDef kaiser12_funcdef = {kaiser12_table, 64}; 
     200#define KAISER12 (&kaiser12_funcdef) 
     201static const struct FuncDef kaiser10_funcdef = {kaiser10_table, 32}; 
     202#define KAISER10 (&kaiser10_funcdef) 
     203static const struct FuncDef kaiser8_funcdef = {kaiser8_table, 32}; 
     204#define KAISER8 (&kaiser8_funcdef) 
     205static const struct FuncDef kaiser6_funcdef = {kaiser6_table, 32}; 
     206#define KAISER6 (&kaiser6_funcdef) 
    204207 
    205208struct QualityMapping { 
     
    208211   float downsample_bandwidth; 
    209212   float upsample_bandwidth; 
    210    struct FuncDef *window_func; 
     213   const struct FuncDef *window_func; 
    211214}; 
    212215 
    213216 
    214217/* This table maps conversion quality to internal parameters. There are two 
    215    reasons that explain why the up-sampling bandwidth is larger than the  
     218   reasons that explain why the up-sampling bandwidth is larger than the 
    216219   down-sampling bandwidth: 
    217220   1) When up-sampling, we can assume that the spectrum is already attenuated 
     
    235238}; 
    236239/*8,24,40,56,80,104,128,160,200,256,320*/ 
    237 static double compute_func(float x, struct FuncDef *func) 
     240static double compute_func(float x, const struct FuncDef *func) 
    238241{ 
    239242   float y, frac; 
    240243   double interp[4]; 
    241    int ind;  
     244   int ind; 
    242245   y = x*func->oversample; 
    243246   ind = (int)floor(y); 
     
    250253   /* Just to make sure we don't have rounding problems */ 
    251254   interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 
    252     
     255 
    253256   /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 
    254257   return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; 
     
    270273#ifdef FIXED_POINT 
    271274/* The slow way of computing a sinc for the table. Should improve that some day */ 
    272 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) 
     275static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func) 
    273276{ 
    274277   /*fprintf (stderr, "%f ", x);*/ 
     
    283286#else 
    284287/* The slow way of computing a sinc for the table. Should improve that some day */ 
    285 static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) 
     288static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func) 
    286289{ 
    287290   /*fprintf (stderr, "%f ", x);*/ 
     
    338341   const spx_uint32_t den_rate = st->den_rate; 
    339342   spx_word32_t sum; 
    340    int j; 
    341343 
    342344   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 
    343345   { 
    344       const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; 
     346      const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; 
    345347      const spx_word16_t *iptr = & in[last_sample]; 
    346348 
    347349#ifndef OVERRIDE_INNER_PRODUCT_SINGLE 
    348       float accum[4] = {0,0,0,0}; 
    349  
     350      int j; 
     351      sum = 0; 
     352      for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]); 
     353 
     354/*    This code is slower on most DSPs which have only 2 accumulators. 
     355      Plus this this forces truncation to 32 bits and you lose the HW guard bits. 
     356      I think we can trust the compiler and let it vectorize and/or unroll itself. 
     357      spx_word32_t accum[4] = {0,0,0,0}; 
    350358      for(j=0;j<N;j+=4) { 
    351         accum[0] += sinc[j]*iptr[j]; 
    352         accum[1] += sinc[j+1]*iptr[j+1]; 
    353         accum[2] += sinc[j+2]*iptr[j+2]; 
    354         accum[3] += sinc[j+3]*iptr[j+3]; 
     359        accum[0] += MULT16_16(sinct[j], iptr[j]); 
     360        accum[1] += MULT16_16(sinct[j+1], iptr[j+1]); 
     361        accum[2] += MULT16_16(sinct[j+2], iptr[j+2]); 
     362        accum[3] += MULT16_16(sinct[j+3], iptr[j+3]); 
    355363      } 
    356364      sum = accum[0] + accum[1] + accum[2] + accum[3]; 
    357 #else 
    358       sum = inner_product_single(sinc, iptr, N); 
    359 #endif 
    360  
    361       out[out_stride * out_sample++] = PSHR32(sum, 15); 
     365*/ 
     366      sum = SATURATE32PSHR(sum, 15, 32767); 
     367#else 
     368      sum = inner_product_single(sinct, iptr, N); 
     369#endif 
     370 
     371      out[out_stride * out_sample++] = sum; 
    362372      last_sample += int_advance; 
    363373      samp_frac_num += frac_advance; 
     
    389399   const spx_uint32_t den_rate = st->den_rate; 
    390400   double sum; 
    391    int j; 
    392401 
    393402   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 
    394403   { 
    395       const spx_word16_t *sinc = & sinc_table[samp_frac_num*N]; 
     404      const spx_word16_t *sinct = & sinc_table[samp_frac_num*N]; 
    396405      const spx_word16_t *iptr = & in[last_sample]; 
    397406 
    398407#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE 
     408      int j; 
    399409      double accum[4] = {0,0,0,0}; 
    400410 
    401411      for(j=0;j<N;j+=4) { 
    402         accum[0] += sinc[j]*iptr[j]; 
    403         accum[1] += sinc[j+1]*iptr[j+1]; 
    404         accum[2] += sinc[j+2]*iptr[j+2]; 
    405         accum[3] += sinc[j+3]*iptr[j+3]; 
     412        accum[0] += sinct[j]*iptr[j]; 
     413        accum[1] += sinct[j+1]*iptr[j+1]; 
     414        accum[2] += sinct[j+2]*iptr[j+2]; 
     415        accum[3] += sinct[j+3]*iptr[j+3]; 
    406416      } 
    407417      sum = accum[0] + accum[1] + accum[2] + accum[3]; 
    408418#else 
    409       sum = inner_product_double(sinc, iptr, N); 
     419      sum = inner_product_double(sinct, iptr, N); 
    410420#endif 
    411421 
     
    436446   const int frac_advance = st->frac_advance; 
    437447   const spx_uint32_t den_rate = st->den_rate; 
    438    int j; 
    439448   spx_word32_t sum; 
    440449 
     
    453462 
    454463#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE 
     464      int j; 
    455465      spx_word32_t accum[4] = {0,0,0,0}; 
    456466 
     
    464474 
    465475      cubic_coef(frac, interp); 
    466       sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]); 
     476      sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); 
     477      sum = SATURATE32PSHR(sum, 15, 32767); 
    467478#else 
    468479      cubic_coef(frac, interp); 
    469480      sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 
    470481#endif 
    471        
    472       out[out_stride * out_sample++] = PSHR32(sum,15); 
     482 
     483      out[out_stride * out_sample++] = sum; 
    473484      last_sample += int_advance; 
    474485      samp_frac_num += frac_advance; 
     
    498509   const int frac_advance = st->frac_advance; 
    499510   const spx_uint32_t den_rate = st->den_rate; 
    500    int j; 
    501511   spx_word32_t sum; 
    502512 
     
    515525 
    516526#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE 
     527      int j; 
    517528      double accum[4] = {0,0,0,0}; 
    518529 
     
    531542      sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); 
    532543#endif 
    533        
     544 
    534545      out[out_stride * out_sample++] = PSHR32(sum,15); 
    535546      last_sample += int_advance; 
     
    548559#endif 
    549560 
    550 static void update_filter(SpeexResamplerState *st) 
    551 { 
    552    spx_uint32_t old_length; 
    553     
    554    old_length = st->filt_len; 
     561/* This resampler is used to produce zero output in situations where memory 
     562   for the filter could not be allocated.  The expected numbers of input and 
     563   output samples are still processed so that callers failing to check error 
     564   codes are not surprised, possibly getting into infinite loops. */ 
     565static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 
     566{ 
     567   int out_sample = 0; 
     568   int last_sample = st->last_sample[channel_index]; 
     569   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 
     570   const int out_stride = st->out_stride; 
     571   const int int_advance = st->int_advance; 
     572   const int frac_advance = st->frac_advance; 
     573   const spx_uint32_t den_rate = st->den_rate; 
     574 
     575   (void)in; 
     576   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 
     577   { 
     578      out[out_stride * out_sample++] = 0; 
     579      last_sample += int_advance; 
     580      samp_frac_num += frac_advance; 
     581      if (samp_frac_num >= den_rate) 
     582      { 
     583         samp_frac_num -= den_rate; 
     584         last_sample++; 
     585      } 
     586   } 
     587 
     588   st->last_sample[channel_index] = last_sample; 
     589   st->samp_frac_num[channel_index] = samp_frac_num; 
     590   return out_sample; 
     591} 
     592 
     593static int multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den) 
     594{ 
     595   spx_uint32_t major = value / den; 
     596   spx_uint32_t remain = value % den; 
     597   /* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */ 
     598   if (remain > UINT32_MAX / num || major > UINT32_MAX / num 
     599       || major * num > UINT32_MAX - remain * num / den) 
     600      return RESAMPLER_ERR_OVERFLOW; 
     601   *result = remain * num / den + major * num; 
     602   return RESAMPLER_ERR_SUCCESS; 
     603} 
     604 
     605static int update_filter(SpeexResamplerState *st) 
     606{ 
     607   spx_uint32_t old_length = st->filt_len; 
     608   spx_uint32_t old_alloc_size = st->mem_alloc_size; 
     609   int use_direct; 
     610   spx_uint32_t min_sinc_table_length; 
     611   spx_uint32_t min_alloc_size; 
     612 
     613   st->int_advance = st->num_rate/st->den_rate; 
     614   st->frac_advance = st->num_rate%st->den_rate; 
    555615   st->oversample = quality_map[st->quality].oversample; 
    556616   st->filt_len = quality_map[st->quality].base_length; 
    557     
     617 
    558618   if (st->num_rate > st->den_rate) 
    559619   { 
    560620      /* down-sampling */ 
    561621      st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; 
    562       /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ 
    563       st->filt_len = st->filt_len*st->num_rate / st->den_rate; 
    564       /* Round down to make sure we have a multiple of 4 */ 
    565       st->filt_len &= (~0x3); 
     622      if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS) 
     623         goto fail; 
     624      /* Round up to make sure we have a multiple of 8 for SSE */ 
     625      st->filt_len = ((st->filt_len-1)&(~0x7))+8; 
    566626      if (2*st->den_rate < st->num_rate) 
    567627         st->oversample >>= 1; 
     
    578638      st->cutoff = quality_map[st->quality].upsample_bandwidth; 
    579639   } 
    580     
     640 
     641#ifdef RESAMPLE_FULL_SINC_TABLE 
     642   use_direct = 1; 
     643   if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len) 
     644      goto fail; 
     645#else 
    581646   /* Choose the resampling type that requires the least amount of memory */ 
    582    if (st->den_rate <= st->oversample) 
     647   use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 
     648                && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; 
     649#endif 
     650   if (use_direct) 
     651   { 
     652      min_sinc_table_length = st->filt_len*st->den_rate; 
     653   } else { 
     654      if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len) 
     655         goto fail; 
     656 
     657      min_sinc_table_length = st->filt_len*st->oversample+8; 
     658   } 
     659   if (st->sinc_table_length < min_sinc_table_length) 
     660   { 
     661      spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t)); 
     662      if (!sinc_table) 
     663         goto fail; 
     664 
     665      st->sinc_table = sinc_table; 
     666      st->sinc_table_length = min_sinc_table_length; 
     667   } 
     668   if (use_direct) 
    583669   { 
    584670      spx_uint32_t i; 
    585       if (!st->sinc_table) 
    586          st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); 
    587       else if (st->sinc_table_length < st->filt_len*st->den_rate) 
    588       { 
    589          st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t)); 
    590          st->sinc_table_length = st->filt_len*st->den_rate; 
    591       } 
    592671      for (i=0;i<st->den_rate;i++) 
    593672      { 
     
    609688   } else { 
    610689      spx_int32_t i; 
    611       if (!st->sinc_table) 
    612          st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); 
    613       else if (st->sinc_table_length < st->filt_len*st->oversample+8) 
    614       { 
    615          st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); 
    616          st->sinc_table_length = st->filt_len*st->oversample+8; 
    617       } 
    618690      for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) 
    619691         st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); 
     
    628700      /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ 
    629701   } 
    630    st->int_advance = st->num_rate/st->den_rate; 
    631    st->frac_advance = st->num_rate%st->den_rate; 
    632  
    633     
     702 
    634703   /* Here's the place where we update the filter memory to take into account 
    635704      the change in filter length. It's probably the messiest part of the code 
    636705      due to handling of lots of corner cases. */ 
    637    if (!st->mem) 
     706 
     707   /* Adding buffer_size to filt_len won't overflow here because filt_len 
     708      could be multiplied by sizeof(spx_word16_t) above. */ 
     709   min_alloc_size = st->filt_len-1 + st->buffer_size; 
     710   if (min_alloc_size > st->mem_alloc_size) 
     711   { 
     712      spx_word16_t *mem; 
     713      if (INT_MAX/sizeof(spx_word16_t)/st->nb_channels < min_alloc_size) 
     714          goto fail; 
     715      else if (!(mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(*mem)))) 
     716          goto fail; 
     717 
     718      st->mem = mem; 
     719      st->mem_alloc_size = min_alloc_size; 
     720   } 
     721   if (!st->started) 
    638722   { 
    639723      spx_uint32_t i; 
    640       st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 
    641       st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 
    642       for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 
    643          st->mem[i] = 0; 
    644       /*speex_warning("init filter");*/ 
    645    } else if (!st->started) 
    646    { 
    647       spx_uint32_t i; 
    648       st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 
    649       st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 
    650724      for (i=0;i<st->nb_channels*st->mem_alloc_size;i++) 
    651725         st->mem[i] = 0; 
     
    653727   } else if (st->filt_len > old_length) 
    654728   { 
    655       spx_int32_t i; 
     729      spx_uint32_t i; 
    656730      /* Increase the filter length */ 
    657731      /*speex_warning("increase filter size");*/ 
    658       int old_alloc_size = st->mem_alloc_size; 
    659       if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size) 
     732      for (i=st->nb_channels;i--;) 
    660733      { 
    661          st->mem_alloc_size = st->filt_len-1 + st->buffer_size; 
    662          st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t)); 
    663       } 
    664       for (i=st->nb_channels-1;i>=0;i--) 
    665       { 
    666          spx_int32_t j; 
     734         spx_uint32_t j; 
    667735         spx_uint32_t olen = old_length; 
    668736         /*if (st->magic_samples[i])*/ 
    669737         { 
    670738            /* Try and remove the magic samples as if nothing had happened */ 
    671              
     739 
    672740            /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 
    673741            olen = old_length + 2*st->magic_samples[i]; 
    674             for (j=old_length-2+st->magic_samples[i];j>=0;j--) 
     742            for (j=old_length-1+st->magic_samples[i];j--;) 
    675743               st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; 
    676744            for (j=0;j<st->magic_samples[i];j++) 
     
    713781      } 
    714782   } 
    715  
     783   return RESAMPLER_ERR_SUCCESS; 
     784 
     785fail: 
     786   st->resampler_ptr = resampler_basic_zero; 
     787   /* st->mem may still contain consumed input samples for the filter. 
     788      Restore filt_len so that filt_len - 1 still points to the position after 
     789      the last of these samples. */ 
     790   st->filt_len = old_length; 
     791   return RESAMPLER_ERR_ALLOC_FAILED; 
    716792} 
    717793 
     
    723799EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 
    724800{ 
    725    spx_uint32_t i; 
    726801   SpeexResamplerState *st; 
    727    if (quality > 10 || quality < 0) 
     802   int filter_err; 
     803 
     804   if (nb_channels == 0 || ratio_num == 0 || ratio_den == 0 || quality > 10 || quality < 0) 
    728805   { 
    729806      if (err) 
     
    732809   } 
    733810   st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); 
     811   if (!st) 
     812   { 
     813      if (err) 
     814         *err = RESAMPLER_ERR_ALLOC_FAILED; 
     815      return NULL; 
     816   } 
    734817   st->initialised = 0; 
    735818   st->started = 0; 
     
    744827   st->mem = 0; 
    745828   st->resampler_ptr = 0; 
    746           
     829 
    747830   st->cutoff = 1.f; 
    748831   st->nb_channels = nb_channels; 
    749832   st->in_stride = 1; 
    750833   st->out_stride = 1; 
    751     
    752 #ifdef FIXED_POINT 
     834 
    753835   st->buffer_size = 160; 
    754 #else 
    755    st->buffer_size = 160; 
    756 #endif 
    757     
     836 
    758837   /* Per channel data */ 
    759    st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); 
    760    st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 
    761    st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); 
    762    for (i=0;i<nb_channels;i++) 
    763    { 
    764       st->last_sample[i] = 0; 
    765       st->magic_samples[i] = 0; 
    766       st->samp_frac_num[i] = 0; 
    767    } 
     838   if (!(st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t)))) 
     839      goto fail; 
     840   if (!(st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) 
     841      goto fail; 
     842   if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) 
     843      goto fail; 
    768844 
    769845   speex_resampler_set_quality(st, quality); 
    770846   speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 
    771847 
    772     
    773    update_filter(st); 
    774     
    775    st->initialised = 1; 
     848   filter_err = update_filter(st); 
     849   if (filter_err == RESAMPLER_ERR_SUCCESS) 
     850   { 
     851      st->initialised = 1; 
     852   } else { 
     853      speex_resampler_destroy(st); 
     854      st = NULL; 
     855   } 
    776856   if (err) 
    777       *err = RESAMPLER_ERR_SUCCESS; 
     857      *err = filter_err; 
    778858 
    779859   return st; 
     860 
     861fail: 
     862   if (err) 
     863      *err = RESAMPLER_ERR_ALLOC_FAILED; 
     864   speex_resampler_destroy(st); 
     865   return NULL; 
    780866} 
    781867 
     
    797883   spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 
    798884   spx_uint32_t ilen; 
    799     
     885 
    800886   st->started = 1; 
    801     
     887 
    802888   /* Call the right resampler through the function ptr */ 
    803889   out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); 
    804     
     890 
    805891   if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 
    806892      *in_len = st->last_sample[channel_index]; 
    807893   *out_len = out_sample; 
    808894   st->last_sample[channel_index] -= *in_len; 
    809     
     895 
    810896   ilen = *in_len; 
    811897 
     
    820906   spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; 
    821907   const int N = st->filt_len; 
    822     
     908 
    823909   speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); 
    824910 
    825911   st->magic_samples[channel_index] -= tmp_in_len; 
    826     
     912 
    827913   /* If we couldn't process all "magic" input samples, save the rest for next time */ 
    828914   if (st->magic_samples[channel_index]) 
     
    850936   const int istride = st->in_stride; 
    851937 
    852    if (st->magic_samples[channel_index])  
     938   if (st->magic_samples[channel_index]) 
    853939      olen -= speex_resampler_magic(st, channel_index, &out, olen); 
    854940   if (! st->magic_samples[channel_index]) { 
     
    856942        spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; 
    857943        spx_uint32_t ochunk = olen; 
    858   
     944 
    859945        if (in) { 
    860946           for(j=0;j<ichunk;++j) 
     
    874960   *in_len -= ilen; 
    875961   *out_len -= olen; 
    876    return RESAMPLER_ERR_SUCCESS; 
     962   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 
    877963} 
    878964 
     
    892978#ifdef VAR_ARRAYS 
    893979   const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; 
    894    VARDECL(spx_word16_t *ystack); 
    895    ALLOC(ystack, ylen, spx_word16_t); 
     980   spx_word16_t ystack[ylen]; 
    896981#else 
    897982   const unsigned int ylen = FIXED_STACK_ALLOC; 
     
    900985 
    901986   st->out_stride = 1; 
    902     
     987 
    903988   while (ilen && olen) { 
    904989     spx_word16_t *y = ystack; 
     
    9371022        out[j*ostride_save] = WORD2INT(ystack[j]); 
    9381023#endif 
    939       
     1024 
    9401025     ilen -= ichunk; 
    9411026     olen -= ochunk; 
     
    9481033   *out_len -= olen; 
    9491034 
    950    return RESAMPLER_ERR_SUCCESS; 
     1035   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 
    9511036} 
    9521037 
     
    9551040   spx_uint32_t i; 
    9561041   int istride_save, ostride_save; 
    957    spx_uint32_t bak_len = *out_len; 
     1042   spx_uint32_t bak_out_len = *out_len; 
     1043   spx_uint32_t bak_in_len = *in_len; 
    9581044   istride_save = st->in_stride; 
    9591045   ostride_save = st->out_stride; 
     
    9611047   for (i=0;i<st->nb_channels;i++) 
    9621048   { 
    963       *out_len = bak_len; 
     1049      *out_len = bak_out_len; 
     1050      *in_len = bak_in_len; 
    9641051      if (in != NULL) 
    9651052         speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); 
     
    9691056   st->in_stride = istride_save; 
    9701057   st->out_stride = ostride_save; 
    971    return RESAMPLER_ERR_SUCCESS; 
    972 } 
    973                 
     1058   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 
     1059} 
     1060 
    9741061EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 
    9751062{ 
    9761063   spx_uint32_t i; 
    9771064   int istride_save, ostride_save; 
    978    spx_uint32_t bak_len = *out_len; 
     1065   spx_uint32_t bak_out_len = *out_len; 
     1066   spx_uint32_t bak_in_len = *in_len; 
    9791067   istride_save = st->in_stride; 
    9801068   ostride_save = st->out_stride; 
     
    9821070   for (i=0;i<st->nb_channels;i++) 
    9831071   { 
    984       *out_len = bak_len; 
     1072      *out_len = bak_out_len; 
     1073      *in_len = bak_in_len; 
    9851074      if (in != NULL) 
    9861075         speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); 
     
    9901079   st->in_stride = istride_save; 
    9911080   st->out_stride = ostride_save; 
    992    return RESAMPLER_ERR_SUCCESS; 
     1081   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS; 
    9931082} 
    9941083 
     
    10021091   *in_rate = st->in_rate; 
    10031092   *out_rate = st->out_rate; 
     1093} 
     1094 
     1095static inline spx_uint32_t compute_gcd(spx_uint32_t a, spx_uint32_t b) 
     1096{ 
     1097   while (b != 0) 
     1098   { 
     1099      spx_uint32_t temp = a; 
     1100 
     1101      a = b; 
     1102      b = temp % b; 
     1103   } 
     1104   return a; 
    10041105} 
    10051106 
     
    10091110   spx_uint32_t old_den; 
    10101111   spx_uint32_t i; 
     1112 
     1113   if (ratio_num == 0 || ratio_den == 0) 
     1114      return RESAMPLER_ERR_INVALID_ARG; 
     1115 
    10111116   if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 
    10121117      return RESAMPLER_ERR_SUCCESS; 
    1013     
     1118 
    10141119   old_den = st->den_rate; 
    10151120   st->in_rate = in_rate; 
     
    10171122   st->num_rate = ratio_num; 
    10181123   st->den_rate = ratio_den; 
    1019    /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ 
    1020    for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) 
    1021    { 
    1022       while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) 
    1023       { 
    1024          st->num_rate /= fact; 
    1025          st->den_rate /= fact; 
    1026       } 
    1027    } 
    1028        
     1124 
     1125   fact = compute_gcd(st->num_rate, st->den_rate); 
     1126 
     1127   st->num_rate /= fact; 
     1128   st->den_rate /= fact; 
     1129 
    10291130   if (old_den > 0) 
    10301131   { 
    10311132      for (i=0;i<st->nb_channels;i++) 
    10321133      { 
    1033          st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; 
     1134         if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS) 
     1135            return RESAMPLER_ERR_OVERFLOW; 
    10341136         /* Safety net */ 
    10351137         if (st->samp_frac_num[i] >= st->den_rate) 
     
    10371139      } 
    10381140   } 
    1039     
     1141 
    10401142   if (st->initialised) 
    1041       update_filter(st); 
     1143      return update_filter(st); 
    10421144   return RESAMPLER_ERR_SUCCESS; 
    10431145} 
     
    10571159   st->quality = quality; 
    10581160   if (st->initialised) 
    1059       update_filter(st); 
     1161      return update_filter(st); 
    10601162   return RESAMPLER_ERR_SUCCESS; 
    10611163} 
     
    11071209{ 
    11081210   spx_uint32_t i; 
     1211   for (i=0;i<st->nb_channels;i++) 
     1212   { 
     1213      st->last_sample[i] = 0; 
     1214      st->magic_samples[i] = 0; 
     1215      st->samp_frac_num[i] = 0; 
     1216   } 
    11091217   for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 
    11101218      st->mem[i] = 0; 
  • pjproject/trunk/third_party/speex/libspeex/resample_sse.h

    r2002 r6129  
    1010   modification, are permitted provided that the following conditions 
    1111   are met: 
    12     
     12 
    1313   - Redistributions of source code must retain the above copyright 
    1414   notice, this list of conditions and the following disclaimer. 
    15     
     15 
    1616   - Redistributions in binary form must reproduce the above copyright 
    1717   notice, this list of conditions and the following disclaimer in the 
    1818   documentation and/or other materials provided with the distribution. 
    19     
     19 
    2020   - Neither the name of the Xiph.org Foundation nor the names of its 
    2121   contributors may be used to endorse or promote products derived from 
    2222   this software without specific prior written permission. 
    23     
     23 
    2424   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    2525   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     
    7272} 
    7373 
    74 #ifdef _USE_SSE2 
     74#ifdef USE_SSE2 
    7575#include <emmintrin.h> 
    7676#define OVERRIDE_INNER_PRODUCT_DOUBLE 
     
    9292      sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); 
    9393   } 
    94    sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); 
     94   sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum)); 
    9595   _mm_store_sd(&ret, sum); 
    9696   return ret; 
     
    121121  sum2 = _mm_mul_pd(f2, sum2); 
    122122  sum = _mm_add_pd(sum1, sum2); 
    123   sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); 
     123  sum = _mm_add_sd(sum, _mm_unpackhi_pd(sum, sum)); 
    124124  _mm_store_sd(&ret, sum); 
    125125  return ret; 
  • pjproject/trunk/third_party/speex/libspeex/scal.c

    r2002 r6129  
    5252#include <math.h> 
    5353#include <stdlib.h> 
     54 
     55#ifndef M_PI 
     56#define M_PI           3.14159265358979323846  /* pi */ 
     57#endif 
    5458 
    5559#define ALLPASS_ORDER 20 
     
    172176 
    173177      x = buff+st->frame_size; 
    174       beta = 1.-.3*amount*amount; 
    175178      if (amount>1) 
    176179         beta = 1-sqrt(.4*amount); 
Note: See TracChangeset for help on using the changeset viewer.