summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2024-05-08 10:36:38 -0400
committerSolomon Peachy <pizza@shaftnet.org>2024-06-20 07:08:35 -0400
commit547b6a570dbad844e79b4ba5eb934f043bab6318 (patch)
tree0cbdb670d73a2544d33985166c5abfa69e20a590 /lib/rbcodec/codecs
parent8ef20383b1e5025f7724e750832de6e28e50680d (diff)
downloadrockbox-547b6a570dbad844e79b4ba5eb934f043bab6318.tar.gz
rockbox-547b6a570dbad844e79b4ba5eb934f043bab6318.zip
codecs: Update libspeex from 1.2beta3 to 1.2rc1
This is a relatively minor bump, but it's the first step towards bringing this current. Change-Id: Iab6c9b0c77f0ba705280434ea74b513364719499
Diffstat (limited to 'lib/rbcodec/codecs')
-rw-r--r--lib/rbcodec/codecs/libspeex/COPYING15
-rw-r--r--lib/rbcodec/codecs/libspeex/README.rockbox6
-rw-r--r--lib/rbcodec/codecs/libspeex/arch.h2
-rw-r--r--lib/rbcodec/codecs/libspeex/bits.c51
-rw-r--r--lib/rbcodec/codecs/libspeex/config-speex.h20
-rw-r--r--lib/rbcodec/codecs/libspeex/fftwrap.c131
-rw-r--r--lib/rbcodec/codecs/libspeex/filters_arm4.h2
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_debug.h58
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_generic.h4
-rw-r--r--lib/rbcodec/codecs/libspeex/jitter.c192
-rw-r--r--lib/rbcodec/codecs/libspeex/mdf.c576
-rw-r--r--lib/rbcodec/codecs/libspeex/modes.c8
-rw-r--r--lib/rbcodec/codecs/libspeex/modes_wb.c10
-rw-r--r--lib/rbcodec/codecs/libspeex/preprocess.c202
-rw-r--r--lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h72
-rw-r--r--lib/rbcodec/codecs/libspeex/resample.c735
-rw-r--r--lib/rbcodec/codecs/libspeex/resample_sse.h128
-rw-r--r--lib/rbcodec/codecs/libspeex/speex.c42
-rw-r--r--lib/rbcodec/codecs/libspeex/speex_callbacks.c28
-rw-r--r--lib/rbcodec/codecs/libspeex/speex_header.c55
-rw-r--r--lib/rbcodec/codecs/libspeex/stereo.c56
21 files changed, 1399 insertions, 994 deletions
diff --git a/lib/rbcodec/codecs/libspeex/COPYING b/lib/rbcodec/codecs/libspeex/COPYING
index 3b6b579cf3..de6fbe2c91 100644
--- a/lib/rbcodec/codecs/libspeex/COPYING
+++ b/lib/rbcodec/codecs/libspeex/COPYING
@@ -1,10 +1,11 @@
1Copyright 2002-2006 1Copyright 2002-2008 Xiph.org Foundation
2 Xiph.org Foundation 2Copyright 2002-2008 Jean-Marc Valin
3 Jean-Marc Valin 3Copyright 2005-2007 Analog Devices Inc.
4 David Rowe 4Copyright 2005-2008 Commonwealth Scientific and Industrial Research
5 EpicGames 5 Organisation (CSIRO)
6 Analog Devices 6Copyright 1993, 2002, 2006 David Rowe
7 Commonwealth Scientific and Industrial Research Organisation (CSIRO) 7Copyright 2003 EpicGames
8Copyright 1992-1994 Jutta Degener, Carsten Bormann
8 9
9Redistribution and use in source and binary forms, with or without 10Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions 11modification, are permitted provided that the following conditions
diff --git a/lib/rbcodec/codecs/libspeex/README.rockbox b/lib/rbcodec/codecs/libspeex/README.rockbox
index 84fff59b60..be809dc40d 100644
--- a/lib/rbcodec/codecs/libspeex/README.rockbox
+++ b/lib/rbcodec/codecs/libspeex/README.rockbox
@@ -1,6 +1,6 @@
1Library: libspeex-1.2beta3 (SVN version 14054) 1Library: libspeex-1.2rc1
2Imported: 2007-03-12 by Dan Everton 2Imported 1.2beta3: 2007-03-12 by Dan Everton
3 3Updated 1.2rc1: 2024-05-08 by Solomon Peachy
4 4
5This directory contains a local version of libspeex for decoding Ogg/Speex 5This directory contains a local version of libspeex for decoding Ogg/Speex
6audio streams. 6audio streams.
diff --git a/lib/rbcodec/codecs/libspeex/arch.h b/lib/rbcodec/codecs/libspeex/arch.h
index 35b5363837..b0a9097f99 100644
--- a/lib/rbcodec/codecs/libspeex/arch.h
+++ b/lib/rbcodec/codecs/libspeex/arch.h
@@ -235,7 +235,7 @@ typedef float spx_word32_t;
235 235
236 236
237#ifdef FIXED_DEBUG 237#ifdef FIXED_DEBUG
238long long spx_mips=0; 238extern long long spx_mips=0;
239#endif 239#endif
240 240
241 241
diff --git a/lib/rbcodec/codecs/libspeex/bits.c b/lib/rbcodec/codecs/libspeex/bits.c
index c7a5c14ede..2580e700fe 100644
--- a/lib/rbcodec/codecs/libspeex/bits.c
+++ b/lib/rbcodec/codecs/libspeex/bits.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2002 Jean-Marc Valin 1/* Copyright (C) 2002 Jean-Marc Valin
2 File: speex_bits.c 2 File: speex_bits.c
3 3
4 Handles bit packing/unpacking 4 Handles bit packing/unpacking
@@ -6,18 +6,18 @@
6 Redistribution and use in source and binary forms, with or without 6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions 7 modification, are permitted provided that the following conditions
8 are met: 8 are met:
9 9
10 - Redistributions of source code must retain the above copyright 10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer. 11 notice, this list of conditions and the following disclaimer.
12 12
13 - Redistributions in binary form must reproduce the above copyright 13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the 14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution. 15 documentation and/or other materials provided with the distribution.
16 16
17 - Neither the name of the Xiph.org Foundation nor the names of its 17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from 18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission. 19 this software without specific prior written permission.
20 20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -46,7 +46,7 @@
46#endif 46#endif
47 47
48#ifdef ROCKBOX_VOICE_ENCODER 48#ifdef ROCKBOX_VOICE_ENCODER
49void speex_bits_init(SpeexBits *bits) 49EXPORT void speex_bits_init(SpeexBits *bits)
50{ 50{
51 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME); 51 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
52 if (!bits->chars) 52 if (!bits->chars)
@@ -62,7 +62,7 @@ void speex_bits_init(SpeexBits *bits)
62 62
63#if 0 63#if 0
64/* Rockbox: unused */ 64/* Rockbox: unused */
65void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size) 65EXPORT void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
66{ 66{
67 bits->chars = (char*)buff; 67 bits->chars = (char*)buff;
68 bits->buf_size = buf_size; 68 bits->buf_size = buf_size;
@@ -73,7 +73,7 @@ void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
73} 73}
74#endif 74#endif
75 75
76void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size) 76EXPORT void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
77{ 77{
78 bits->chars = (char*)buff; 78 bits->chars = (char*)buff;
79 bits->buf_size = buf_size; 79 bits->buf_size = buf_size;
@@ -84,11 +84,11 @@ void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
84 bits->charPtr=0; 84 bits->charPtr=0;
85 bits->bitPtr=0; 85 bits->bitPtr=0;
86 bits->overflow=0; 86 bits->overflow=0;
87 87
88} 88}
89 89
90#ifndef ROCKBOX_VOICE_CODEC 90#ifndef ROCKBOX_VOICE_CODEC
91void speex_bits_destroy(SpeexBits *bits) 91EXPORT void speex_bits_destroy(SpeexBits *bits)
92{ 92{
93 if (bits->owner) 93 if (bits->owner)
94 speex_free(bits->chars); 94 speex_free(bits->chars);
@@ -97,7 +97,7 @@ void speex_bits_destroy(SpeexBits *bits)
97#endif 97#endif
98 98
99#ifdef ROCKBOX_VOICE_ENCODER 99#ifdef ROCKBOX_VOICE_ENCODER
100void speex_bits_reset(SpeexBits *bits) 100EXPORT void speex_bits_reset(SpeexBits *bits)
101{ 101{
102 /* We only need to clear the first byte now */ 102 /* We only need to clear the first byte now */
103 bits->chars[0]=0; 103 bits->chars[0]=0;
@@ -110,7 +110,7 @@ void speex_bits_reset(SpeexBits *bits)
110 110
111#if 0 111#if 0
112/* Rockbox: unused */ 112/* Rockbox: unused */
113void speex_bits_rewind(SpeexBits *bits) 113EXPORT void speex_bits_rewind(SpeexBits *bits)
114{ 114{
115 bits->charPtr=0; 115 bits->charPtr=0;
116 bits->bitPtr=0; 116 bits->bitPtr=0;
@@ -119,7 +119,7 @@ void speex_bits_rewind(SpeexBits *bits)
119#endif 119#endif
120 120
121#if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC) 121#if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC)
122void speex_bits_read_from(SpeexBits *bits, char *chars, int len) 122EXPORT void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
123{ 123{
124 int i; 124 int i;
125 int nchars = len / BYTES_PER_CHAR; 125 int nchars = len / BYTES_PER_CHAR;
@@ -166,9 +166,10 @@ static void speex_bits_flush(SpeexBits *bits)
166 bits->charPtr=0; 166 bits->charPtr=0;
167} 167}
168 168
169void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes) 169EXPORT void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
170{ 170{
171 int i,pos; 171 int i,pos;
172
172 int nchars = nbytes/BYTES_PER_CHAR; 173 int nchars = nbytes/BYTES_PER_CHAR;
173 174
174 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size) 175 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
@@ -200,7 +201,7 @@ void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
200#endif 201#endif
201 202
202#ifndef SPEEX_DISABLE_ENCODER 203#ifndef SPEEX_DISABLE_ENCODER
203int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes) 204EXPORT int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
204{ 205{
205 int i; 206 int i;
206 int max_nchars = max_nbytes/BYTES_PER_CHAR; 207 int max_nchars = max_nbytes/BYTES_PER_CHAR;
@@ -223,7 +224,7 @@ int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
223 return max_nchars*BYTES_PER_CHAR; 224 return max_nchars*BYTES_PER_CHAR;
224} 225}
225 226
226int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes) 227EXPORT int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
227{ 228{
228 int max_nchars = max_nbytes/BYTES_PER_CHAR; 229 int max_nchars = max_nbytes/BYTES_PER_CHAR;
229 int i; 230 int i;
@@ -241,7 +242,7 @@ int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
241 return max_nchars*BYTES_PER_CHAR; 242 return max_nchars*BYTES_PER_CHAR;
242} 243}
243 244
244void speex_bits_pack(SpeexBits *bits, int data, int nbBits) 245EXPORT void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
245{ 246{
246 unsigned int d=data; 247 unsigned int d=data;
247 248
@@ -287,7 +288,7 @@ void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
287 288
288#if 0 289#if 0
289/* Rockbox: unused */ 290/* Rockbox: unused */
290int speex_bits_unpack_signed(SpeexBits *bits, int nbBits) 291EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
291{ 292{
292 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits); 293 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
293 /* If number is negative */ 294 /* If number is negative */
@@ -299,7 +300,7 @@ int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
299} 300}
300#endif 301#endif
301 302
302unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits) 303EXPORT unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
303{ 304{
304 unsigned int d=0; 305 unsigned int d=0;
305 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits) 306 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
@@ -323,7 +324,7 @@ unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
323 324
324#if 0 325#if 0
325/* Rockbox: unused */ 326/* Rockbox: unused */
326unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits) 327EXPORT unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
327{ 328{
328 unsigned int d=0; 329 unsigned int d=0;
329 int bitPtr, charPtr; 330 int bitPtr, charPtr;
@@ -353,7 +354,7 @@ unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
353} 354}
354#endif 355#endif
355 356
356int speex_bits_peek(SpeexBits *bits) 357EXPORT int speex_bits_peek(SpeexBits *bits)
357{ 358{
358 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits) 359 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
359 bits->overflow=1; 360 bits->overflow=1;
@@ -362,7 +363,7 @@ int speex_bits_peek(SpeexBits *bits)
362 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1; 363 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
363} 364}
364 365
365void speex_bits_advance(SpeexBits *bits, int n) 366EXPORT void speex_bits_advance(SpeexBits *bits, int n)
366{ 367{
367 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){ 368 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
368 bits->overflow=1; 369 bits->overflow=1;
@@ -372,7 +373,7 @@ void speex_bits_advance(SpeexBits *bits, int n)
372 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */ 373 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
373} 374}
374 375
375int speex_bits_remaining(SpeexBits *bits) 376EXPORT int speex_bits_remaining(SpeexBits *bits)
376{ 377{
377 if (bits->overflow) 378 if (bits->overflow)
378 return -1; 379 return -1;
@@ -382,14 +383,14 @@ int speex_bits_remaining(SpeexBits *bits)
382 383
383#if 0 384#if 0
384/* Rockbox: unused */ 385/* Rockbox: unused */
385int speex_bits_nbytes(SpeexBits *bits) 386EXPORT int speex_bits_nbytes(SpeexBits *bits)
386{ 387{
387 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR); 388 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
388} 389}
389#endif 390#endif
390 391
391#ifndef SPEEX_DISABLE_ENCODER 392#ifndef SPEEX_DISABLE_ENCODER
392void speex_bits_insert_terminator(SpeexBits *bits) 393EXPORT void speex_bits_insert_terminator(SpeexBits *bits)
393{ 394{
394 if (bits->bitPtr) 395 if (bits->bitPtr)
395 speex_bits_pack(bits, 0, 1); 396 speex_bits_pack(bits, 0, 1);
diff --git a/lib/rbcodec/codecs/libspeex/config-speex.h b/lib/rbcodec/codecs/libspeex/config-speex.h
index 7e0672c150..d6d3b23a0a 100644
--- a/lib/rbcodec/codecs/libspeex/config-speex.h
+++ b/lib/rbcodec/codecs/libspeex/config-speex.h
@@ -1,5 +1,5 @@
1#ifndef ROCKBOX_VOICE_ENCODER 1#ifndef ROCKBOX_VOICE_ENCODER
2#include "codeclib.h" 2#include "codeclib.h"
3#include "autoconf.h" 3#include "autoconf.h"
4#else 4#else
5#define ICODE_ATTR 5#define ICODE_ATTR
@@ -17,7 +17,11 @@
17 17
18/* Make use of ARM4E assembly optimizations */ 18/* Make use of ARM4E assembly optimizations */
19#if defined(CPU_ARM) 19#if defined(CPU_ARM)
20#if (ARM_ARCH < 5)
20#define ARM4_ASM 21#define ARM4_ASM
22#else
23#define ARM5E_ASM
24#endif
21#endif 25#endif
22 26
23/* Make use of Coldfire assembly optimizations */ 27/* Make use of Coldfire assembly optimizations */
@@ -40,10 +44,10 @@
40 44
41#ifndef ROCKBOX_VOICE_ENCODER 45#ifndef ROCKBOX_VOICE_ENCODER
42/* Compile target codec as fixed point */ 46/* Compile target codec as fixed point */
43#define FIXED_POINT 47#define FIXED_POINT
44#else 48#else
45/* Compile voice clip encoder as floating point */ 49/* Compile voice clip encoder as floating point */
46#define FLOATING_POINT 50#define FLOATING_POINT
47#endif 51#endif
48 52
49#ifndef ROCKBOX_VOICE_CODEC 53#ifndef ROCKBOX_VOICE_CODEC
@@ -137,13 +141,13 @@
137#define SPEEX_MAJOR_VERSION 1 141#define SPEEX_MAJOR_VERSION 1
138 142
139/* Version micro */ 143/* Version micro */
140#define SPEEX_MICRO_VERSION 15 144#define SPEEX_MICRO_VERSION 16
141 145
142/* Version minor */ 146/* Version minor */
143#define SPEEX_MINOR_VERSION 1 147#define SPEEX_MINOR_VERSION 1
144 148
145/* Complete version string */ 149/* Complete version string */
146#define SPEEX_VERSION "1.2beta3" 150#define SPEEX_VERSION "1.2rc1"
147 151
148/* Define to 1 if you have the ANSI C header files. */ 152/* Define to 1 if you have the ANSI C header files. */
149#define STDC_HEADERS 1 153#define STDC_HEADERS 1
@@ -155,7 +159,7 @@
155/* #undef USE_ALLOCA */ 159/* #undef USE_ALLOCA */
156 160
157/* Use C99 variable-size arrays */ 161/* Use C99 variable-size arrays */
158#define VAR_ARRAYS 162#define VAR_ARRAYS
159 163
160/* Enable Vorbis-style psychoacoustics (EXPERIMENTAL) */ 164/* Enable Vorbis-style psychoacoustics (EXPERIMENTAL) */
161/* #undef VORBIS_PSYCHO */ 165/* #undef VORBIS_PSYCHO */
@@ -184,3 +188,7 @@
184 188
185#define RELEASE 1 189#define RELEASE 1
186 190
191/* We don't care */
192#define EXPORT
193
194#define USE_KISS_FFT
diff --git a/lib/rbcodec/codecs/libspeex/fftwrap.c b/lib/rbcodec/codecs/libspeex/fftwrap.c
index 2312f755d6..b849e74f7c 100644
--- a/lib/rbcodec/codecs/libspeex/fftwrap.c
+++ b/lib/rbcodec/codecs/libspeex/fftwrap.c
@@ -1,23 +1,23 @@
1/* Copyright (C) 2005-2006 Jean-Marc Valin 1/* Copyright (C) 2005-2006 Jean-Marc Valin
2 File: fftwrap.c 2 File: fftwrap.c
3 3
4 Wrapper for various FFTs 4 Wrapper for various FFTs
5 5
6 Redistribution and use in source and binary forms, with or without 6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions 7 modification, are permitted provided that the following conditions
8 are met: 8 are met:
9 9
10 - Redistributions of source code must retain the above copyright 10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer. 11 notice, this list of conditions and the following disclaimer.
12 12
13 - Redistributions in binary form must reproduce the above copyright 13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the 14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution. 15 documentation and/or other materials provided with the distribution.
16 16
17 - Neither the name of the Xiph.org Foundation nor the names of its 17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from 18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission. 19 this software without specific prior written permission.
20 20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -36,10 +36,6 @@
36#include "config-speex.h" 36#include "config-speex.h"
37#endif 37#endif
38 38
39/*#define USE_SMALLFT*/
40#define USE_KISS_FFT
41
42
43#include "arch.h" 39#include "arch.h"
44#include "os_support.h" 40#include "os_support.h"
45 41
@@ -66,7 +62,7 @@ static int maximize_range(spx_word16_t *in, spx_word16_t *out, spx_word16_t boun
66 for (i=0;i<len;i++) 62 for (i=0;i<len;i++)
67 { 63 {
68 out[i] = SHL16(in[i], shift); 64 out[i] = SHL16(in[i], shift);
69 } 65 }
70 return shift; 66 return shift;
71} 67}
72 68
@@ -130,6 +126,119 @@ void spx_ifft(void *table, float *in, float *out)
130 spx_drft_backward((struct drft_lookup *)table, out); 126 spx_drft_backward((struct drft_lookup *)table, out);
131} 127}
132 128
129#elif defined(USE_INTEL_MKL)
130#include <mkl.h>
131
132struct mkl_config {
133 DFTI_DESCRIPTOR_HANDLE desc;
134 int N;
135};
136
137void *spx_fft_init(int size)
138{
139 struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config));
140 table->N = size;
141 DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size);
142 DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT);
143 DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
144 DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size);
145 DftiCommitDescriptor(table->desc);
146 return table;
147}
148
149void spx_fft_destroy(void *table)
150{
151 struct mkl_config *t = (struct mkl_config *) table;
152 DftiFreeDescriptor(t->desc);
153 speex_free(table);
154}
155
156void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
157{
158 struct mkl_config *t = (struct mkl_config *) table;
159 DftiComputeForward(t->desc, in, out);
160}
161
162void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
163{
164 struct mkl_config *t = (struct mkl_config *) table;
165 DftiComputeBackward(t->desc, in, out);
166}
167
168#elif defined(USE_GPL_FFTW3)
169
170#include <fftw3.h>
171
172struct fftw_config {
173 float *in;
174 float *out;
175 fftwf_plan fft;
176 fftwf_plan ifft;
177 int N;
178};
179
180void *spx_fft_init(int size)
181{
182 struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config));
183 table->in = fftwf_malloc(sizeof(float) * (size+2));
184 table->out = fftwf_malloc(sizeof(float) * (size+2));
185
186 table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT);
187 table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT);
188
189 table->N = size;
190 return table;
191}
192
193void spx_fft_destroy(void *table)
194{
195 struct fftw_config *t = (struct fftw_config *) table;
196 fftwf_destroy_plan(t->fft);
197 fftwf_destroy_plan(t->ifft);
198 fftwf_free(t->in);
199 fftwf_free(t->out);
200 speex_free(table);
201}
202
203
204void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
205{
206 int i;
207 struct fftw_config *t = (struct fftw_config *) table;
208 const int N = t->N;
209 float *iptr = t->in;
210 float *optr = t->out;
211 const float m = 1.0 / N;
212 for(i=0;i<N;++i)
213 iptr[i]=in[i] * m;
214
215 fftwf_execute(t->fft);
216
217 out[0] = optr[0];
218 for(i=1;i<N;++i)
219 out[i] = optr[i+1];
220}
221
222void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
223{
224 int i;
225 struct fftw_config *t = (struct fftw_config *) table;
226 const int N = t->N;
227 float *iptr = t->in;
228 float *optr = t->out;
229
230 iptr[0] = in[0];
231 iptr[1] = 0.0f;
232 for(i=1;i<N;++i)
233 iptr[i+1] = in[i];
234 iptr[N+1] = 0.0f;
235
236 fftwf_execute(t->ifft);
237
238 for(i=0;i<N;++i)
239 out[i] = optr[i];
240}
241
133#elif defined(USE_KISS_FFT) 242#elif defined(USE_KISS_FFT)
134 243
135#include "kiss_fftr.h" 244#include "kiss_fftr.h"
diff --git a/lib/rbcodec/codecs/libspeex/filters_arm4.h b/lib/rbcodec/codecs/libspeex/filters_arm4.h
index 18c2a7d448..eb93715b9b 100644
--- a/lib/rbcodec/codecs/libspeex/filters_arm4.h
+++ b/lib/rbcodec/codecs/libspeex/filters_arm4.h
@@ -86,7 +86,7 @@ int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int le
86 "\tmov %5, %5, asr %3 \n" 86 "\tmov %5, %5, asr %3 \n"
87 "\tstrh %5, [%1], #2 \n" 87 "\tstrh %5, [%1], #2 \n"
88 88
89 "\tbge .normalize16loop%=\n" 89 "\tbgt .normalize16loop%=\n"
90 : "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4), 90 : "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4),
91 "=r" (dead5), "=r" (dead6) 91 "=r" (dead5), "=r" (dead6)
92 : "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift) 92 : "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift)
diff --git a/lib/rbcodec/codecs/libspeex/fixed_debug.h b/lib/rbcodec/codecs/libspeex/fixed_debug.h
index d5c449f4d9..4d5fe11113 100644
--- a/lib/rbcodec/codecs/libspeex/fixed_debug.h
+++ b/lib/rbcodec/codecs/libspeex/fixed_debug.h
@@ -7,18 +7,18 @@
7 Redistribution and use in source and binary forms, with or without 7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions 8 modification, are permitted provided that the following conditions
9 are met: 9 are met:
10 10
11 - Redistributions of source code must retain the above copyright 11 - Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer. 12 notice, this list of conditions and the following disclaimer.
13 13
14 - Redistributions in binary form must reproduce the above copyright 14 - Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the 15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution. 16 documentation and/or other materials provided with the distribution.
17 17
18 - Neither the name of the Xiph.org Foundation nor the names of its 18 - Neither the name of the Xiph.org Foundation nor the names of its
19 contributors may be used to endorse or promote products derived from 19 contributors may be used to endorse or promote products derived from
20 this software without specific prior written permission. 20 this software without specific prior written permission.
21 21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -101,7 +101,7 @@ static inline int _EXTEND32(int x, char *file, int line)
101} 101}
102 102
103#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) 103#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
104static inline short _SHR16(int a, int shift, char *file, int line) 104static inline short _SHR16(int a, int shift, char *file, int line)
105{ 105{
106 int res; 106 int res;
107 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) 107 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
@@ -115,7 +115,7 @@ static inline short _SHR16(int a, int shift, char *file, int line)
115 return res; 115 return res;
116} 116}
117#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) 117#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
118static inline short _SHL16(int a, int shift, char *file, int line) 118static inline short _SHL16(int a, int shift, char *file, int line)
119{ 119{
120 int res; 120 int res;
121 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) 121 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
@@ -129,7 +129,7 @@ static inline short _SHL16(int a, int shift, char *file, int line)
129 return res; 129 return res;
130} 130}
131 131
132static inline int SHR32(long long a, int shift) 132static inline int SHR32(long long a, int shift)
133{ 133{
134 long long res; 134 long long res;
135 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) 135 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
@@ -144,7 +144,7 @@ static inline int SHR32(long long a, int shift)
144 spx_mips++; 144 spx_mips++;
145 return res; 145 return res;
146} 146}
147static inline int SHL32(long long a, int shift) 147static inline int SHL32(long long a, int shift)
148{ 148{
149 long long res; 149 long long res;
150 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) 150 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
@@ -161,7 +161,7 @@ static inline int SHL32(long long a, int shift)
161} 161}
162 162
163#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift)) 163#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
164#define PSHR32(a,shift) (SHR32(ADD32((a),((1<<((shift))>>1))),shift)) 164#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift))
165#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) 165#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
166 166
167#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 167#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
@@ -171,7 +171,7 @@ static inline int SHL32(long long a, int shift)
171//#define SHL(a,shift) ((a) << (shift)) 171//#define SHL(a,shift) ((a) << (shift))
172 172
173#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) 173#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
174static inline short _ADD16(int a, int b, char *file, int line) 174static inline short _ADD16(int a, int b, char *file, int line)
175{ 175{
176 int res; 176 int res;
177 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 177 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -188,7 +188,7 @@ static inline short _ADD16(int a, int b, char *file, int line)
188} 188}
189 189
190#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) 190#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
191static inline short _SUB16(int a, int b, char *file, int line) 191static inline short _SUB16(int a, int b, char *file, int line)
192{ 192{
193 int res; 193 int res;
194 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 194 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -203,7 +203,7 @@ static inline short _SUB16(int a, int b, char *file, int line)
203} 203}
204 204
205#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) 205#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
206static inline int _ADD32(long long a, long long b, char *file, int line) 206static inline int _ADD32(long long a, long long b, char *file, int line)
207{ 207{
208 long long res; 208 long long res;
209 if (!VERIFY_INT(a) || !VERIFY_INT(b)) 209 if (!VERIFY_INT(a) || !VERIFY_INT(b))
@@ -219,7 +219,7 @@ static inline int _ADD32(long long a, long long b, char *file, int line)
219 return res; 219 return res;
220} 220}
221 221
222static inline int SUB32(long long a, long long b) 222static inline int SUB32(long long a, long long b)
223{ 223{
224 long long res; 224 long long res;
225 if (!VERIFY_INT(a) || !VERIFY_INT(b)) 225 if (!VERIFY_INT(a) || !VERIFY_INT(b))
@@ -236,7 +236,7 @@ static inline int SUB32(long long a, long long b)
236#define ADD64(a,b) (MIPS_INC(a)+(b)) 236#define ADD64(a,b) (MIPS_INC(a)+(b))
237 237
238/* result fits in 16 bits */ 238/* result fits in 16 bits */
239static inline short MULT16_16_16(int a, int b) 239static inline short MULT16_16_16(int a, int b)
240{ 240{
241 int res; 241 int res;
242 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 242 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -251,7 +251,7 @@ static inline short MULT16_16_16(int a, int b)
251} 251}
252 252
253#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) 253#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
254static inline int _MULT16_16(int a, int b, char *file, int line) 254static inline int _MULT16_16(int a, int b, char *file, int line)
255{ 255{
256 long long res; 256 long long res;
257 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 257 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -279,8 +279,8 @@ static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
279 { 279 {
280 fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); 280 fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
281 } 281 }
282 if (ABS32(b)>=(1<<(15+Q))) 282 if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
283 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); 283 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
284 res = (((long long)a)*(long long)b) >> Q; 284 res = (((long long)a)*(long long)b) >> Q;
285 if (!VERIFY_INT(res)) 285 if (!VERIFY_INT(res))
286 fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line); 286 fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
@@ -295,9 +295,9 @@ static inline int MULT16_32_PX(int a, long long b, int Q)
295 { 295 {
296 fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b); 296 fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
297 } 297 }
298 if (ABS32(b)>=(1<<(15+Q))) 298 if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
299 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b); 299 fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
300 res = ((((long long)a)*(long long)b) + ((1<<Q)>>1))>> Q; 300 res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q;
301 if (!VERIFY_INT(res)) 301 if (!VERIFY_INT(res))
302 fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res); 302 fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
303 spx_mips+=5; 303 spx_mips+=5;
@@ -323,7 +323,7 @@ static inline int SATURATE(int a, int b)
323 return a; 323 return a;
324} 324}
325 325
326static inline int MULT16_16_Q11_32(int a, int b) 326static inline int MULT16_16_Q11_32(int a, int b)
327{ 327{
328 long long res; 328 long long res;
329 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 329 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -337,7 +337,7 @@ static inline int MULT16_16_Q11_32(int a, int b)
337 spx_mips+=3; 337 spx_mips+=3;
338 return res; 338 return res;
339} 339}
340static inline short MULT16_16_Q13(int a, int b) 340static inline short MULT16_16_Q13(int a, int b)
341{ 341{
342 long long res; 342 long long res;
343 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 343 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -351,7 +351,7 @@ static inline short MULT16_16_Q13(int a, int b)
351 spx_mips+=3; 351 spx_mips+=3;
352 return res; 352 return res;
353} 353}
354static inline short MULT16_16_Q14(int a, int b) 354static inline short MULT16_16_Q14(int a, int b)
355{ 355{
356 long long res; 356 long long res;
357 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 357 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -365,7 +365,7 @@ static inline short MULT16_16_Q14(int a, int b)
365 spx_mips+=3; 365 spx_mips+=3;
366 return res; 366 return res;
367} 367}
368static inline short MULT16_16_Q15(int a, int b) 368static inline short MULT16_16_Q15(int a, int b)
369{ 369{
370 long long res; 370 long long res;
371 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 371 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -382,7 +382,7 @@ static inline short MULT16_16_Q15(int a, int b)
382 return res; 382 return res;
383} 383}
384 384
385static inline short MULT16_16_P13(int a, int b) 385static inline short MULT16_16_P13(int a, int b)
386{ 386{
387 long long res; 387 long long res;
388 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 388 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -399,7 +399,7 @@ static inline short MULT16_16_P13(int a, int b)
399 spx_mips+=4; 399 spx_mips+=4;
400 return res; 400 return res;
401} 401}
402static inline short MULT16_16_P14(int a, int b) 402static inline short MULT16_16_P14(int a, int b)
403{ 403{
404 long long res; 404 long long res;
405 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 405 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -416,7 +416,7 @@ static inline short MULT16_16_P14(int a, int b)
416 spx_mips+=4; 416 spx_mips+=4;
417 return res; 417 return res;
418} 418}
419static inline short MULT16_16_P15(int a, int b) 419static inline short MULT16_16_P15(int a, int b)
420{ 420{
421 long long res; 421 long long res;
422 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) 422 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -436,7 +436,7 @@ static inline short MULT16_16_P15(int a, int b)
436 436
437#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) 437#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
438 438
439static inline int _DIV32_16(long long a, long long b, char *file, int line) 439static inline int _DIV32_16(long long a, long long b, char *file, int line)
440{ 440{
441 long long res; 441 long long res;
442 if (b==0) 442 if (b==0)
@@ -462,7 +462,7 @@ static inline int _DIV32_16(long long a, long long b, char *file, int line)
462} 462}
463 463
464#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) 464#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
465static inline int _DIV32(long long a, long long b, char *file, int line) 465static inline int _DIV32(long long a, long long b, char *file, int line)
466{ 466{
467 long long res; 467 long long res;
468 if (b==0) 468 if (b==0)
diff --git a/lib/rbcodec/codecs/libspeex/fixed_generic.h b/lib/rbcodec/codecs/libspeex/fixed_generic.h
index 2948177c0b..3fb096ed90 100644
--- a/lib/rbcodec/codecs/libspeex/fixed_generic.h
+++ b/lib/rbcodec/codecs/libspeex/fixed_generic.h
@@ -47,14 +47,14 @@
47#define SHR32(a,shift) ((a) >> (shift)) 47#define SHR32(a,shift) ((a) >> (shift))
48#define SHL32(a,shift) ((a) << (shift)) 48#define SHL32(a,shift) ((a) << (shift))
49#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) 49#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
50#define PSHR32(a,shift) (SHR32((a)+((1<<((shift))>>1)),shift)) 50#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
51#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) 51#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
52#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 52#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
53#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 53#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
54 54
55#define SHR(a,shift) ((a) >> (shift)) 55#define SHR(a,shift) ((a) >> (shift))
56#define SHL(a,shift) ((spx_word32_t)(a) << (shift)) 56#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
57#define PSHR(a,shift) (SHR((a)+((1<<((shift))>>1)),shift)) 57#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
58#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 58#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
59 59
60 60
diff --git a/lib/rbcodec/codecs/libspeex/jitter.c b/lib/rbcodec/codecs/libspeex/jitter.c
index d9f6c67b86..f4e3bc2be1 100644
--- a/lib/rbcodec/codecs/libspeex/jitter.c
+++ b/lib/rbcodec/codecs/libspeex/jitter.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2002 Jean-Marc Valin 1/* Copyright (C) 2002 Jean-Marc Valin
2 File: speex_jitter.h 2 File: speex_jitter.h
3 3
4 Adaptive jitter buffer for Speex 4 Adaptive jitter buffer for Speex
@@ -6,18 +6,18 @@
6 Redistribution and use in source and binary forms, with or without 6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions 7 modification, are permitted provided that the following conditions
8 are met: 8 are met:
9 9
10 - Redistributions of source code must retain the above copyright 10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer. 11 notice, this list of conditions and the following disclaimer.
12 12
13 - Redistributions in binary form must reproduce the above copyright 13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the 14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution. 15 documentation and/or other materials provided with the distribution.
16 16
17 - Neither the name of the Xiph.org Foundation nor the names of its 17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from 18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission. 19 this software without specific prior written permission.
20 20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -73,17 +73,17 @@ TODO:
73#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0) 73#define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
74#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0) 74#define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0)
75 75
76#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) 76#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step))
77 77
78#define MAX_TIMINGS 20 78#define MAX_TIMINGS 40
79#define MAX_BUFFERS 3 79#define MAX_BUFFERS 3
80#define TOP_DELAY 20 80#define TOP_DELAY 40
81 81
82/** Buffer that keeps the time of arrival of the latest packets */ 82/** Buffer that keeps the time of arrival of the latest packets */
83struct TimingBuffer { 83struct TimingBuffer {
84 int filled; /**< Number of entries occupied in "timing" and "counts"*/ 84 int filled; /**< Number of entries occupied in "timing" and "counts"*/
85 int curr_count; /**< Number of packet timings we got (including those we discarded) */ 85 int curr_count; /**< Number of packet timings we got (including those we discarded) */
86 spx_int16_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */ 86 spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */
87 spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */ 87 spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */
88}; 88};
89 89
@@ -103,7 +103,7 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
103 tb->curr_count++; 103 tb->curr_count++;
104 return; 104 return;
105 } 105 }
106 106
107 /* Find where the timing info goes in the sorted list */ 107 /* Find where the timing info goes in the sorted list */
108 pos = 0; 108 pos = 0;
109 /* FIXME: Do bisection instead of linear search */ 109 /* FIXME: Do bisection instead of linear search */
@@ -111,9 +111,9 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
111 { 111 {
112 pos++; 112 pos++;
113 } 113 }
114 114
115 speex_assert(pos <= tb->filled && pos < MAX_TIMINGS); 115 speex_assert(pos <= tb->filled && pos < MAX_TIMINGS);
116 116
117 /* Shift everything so we can perform the insertion */ 117 /* Shift everything so we can perform the insertion */
118 if (pos < tb->filled) 118 if (pos < tb->filled)
119 { 119 {
@@ -126,7 +126,7 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
126 /* Insert */ 126 /* Insert */
127 tb->timing[pos] = timing; 127 tb->timing[pos] = timing;
128 tb->counts[pos] = tb->curr_count; 128 tb->counts[pos] = tb->curr_count;
129 129
130 tb->curr_count++; 130 tb->curr_count++;
131 if (tb->filled<MAX_TIMINGS) 131 if (tb->filled<MAX_TIMINGS)
132 tb->filled++; 132 tb->filled++;
@@ -139,12 +139,12 @@ struct JitterBuffer_ {
139 spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */ 139 spx_uint32_t pointer_timestamp; /**< Timestamp of what we will *get* next */
140 spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */ 140 spx_uint32_t last_returned_timestamp; /**< Useful for getting the next packet with the same timestamp (for fragmented media) */
141 spx_uint32_t next_stop; /**< Estimated time the next get() will be called */ 141 spx_uint32_t next_stop; /**< Estimated time the next get() will be called */
142 142
143 spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/ 143 spx_int32_t buffered; /**< Amount of data we think is still buffered by the application (timestamp units)*/
144 144
145 JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */ 145 JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packets stored in the buffer */
146 spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */ 146 spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE]; /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
147 147
148 void (*destroy) (void *); /**< Callback for destroying a packet */ 148 void (*destroy) (void *); /**< Callback for destroying a packet */
149 149
150 spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */ 150 spx_int32_t delay_step; /**< Size of the steps when adjusting buffering (timestamp units) */
@@ -154,7 +154,7 @@ struct JitterBuffer_ {
154 int late_cutoff; /**< How late must a packet be for it not to be considered at all */ 154 int late_cutoff; /**< How late must a packet be for it not to be considered at all */
155 int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */ 155 int interp_requested; /**< An interpolation is requested by speex_jitter_update_delay() */
156 int auto_adjust; /**< Whether to automatically adjust the delay at any time */ 156 int auto_adjust; /**< Whether to automatically adjust the delay at any time */
157 157
158 struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */ 158 struct TimingBuffer _tb[MAX_BUFFERS]; /**< Don't use those directly */
159 struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */ 159 struct TimingBuffer *timeBuffers[MAX_BUFFERS]; /**< Storing arrival time of latest frames so we can compute some stats */
160 int window_size; /**< Total window over which the late frames are counted */ 160 int window_size; /**< Total window over which the late frames are counted */
@@ -162,15 +162,15 @@ struct JitterBuffer_ {
162 int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */ 162 int max_late_rate; /**< Absolute maximum amount of late packets tolerable (in percent) */
163 int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */ 163 int latency_tradeoff; /**< Latency equivalent of losing one percent of packets */
164 int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */ 164 int auto_tradeoff; /**< Latency equivalent of losing one percent of packets (automatic default) */
165 165
166 int lost_count; /**< Number of consecutive lost packets */ 166 int lost_count; /**< Number of consecutive lost packets */
167}; 167};
168 168
169/** Based on available data, this computes the optimal delay for the jitter buffer. 169/** Based on available data, this computes the optimal delay for the jitter buffer.
170 The optimised function is in timestamp units and is: 170 The optimised function is in timestamp units and is:
171 cost = delay + late_factor*[number of frames that would be late if we used that delay] 171 cost = delay + late_factor*[number of frames that would be late if we used that delay]
172 @param tb Array of buffers 172 @param tb Array of buffers
173 @param late_factor Equivalent cost of a late frame (in timestamp units) 173 @param late_factor Equivalent cost of a late frame (in timestamp units)
174 */ 174 */
175static spx_int16_t compute_opt_delay(JitterBuffer *jitter) 175static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
176{ 176{
@@ -186,27 +186,27 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
186 int worst = 0; 186 int worst = 0;
187 spx_int32_t deltaT; 187 spx_int32_t deltaT;
188 struct TimingBuffer *tb; 188 struct TimingBuffer *tb;
189 189
190 tb = jitter->_tb; 190 tb = jitter->_tb;
191 191
192 /* Number of packet timings we have received (including those we didn't keep) */ 192 /* Number of packet timings we have received (including those we didn't keep) */
193 tot_count = 0; 193 tot_count = 0;
194 for (i=0;i<MAX_BUFFERS;i++) 194 for (i=0;i<MAX_BUFFERS;i++)
195 tot_count += tb[i].curr_count; 195 tot_count += tb[i].curr_count;
196 if (tot_count==0) 196 if (tot_count==0)
197 return 0; 197 return 0;
198 198
199 /* Compute cost for one lost packet */ 199 /* Compute cost for one lost packet */
200 if (jitter->latency_tradeoff != 0) 200 if (jitter->latency_tradeoff != 0)
201 late_factor = jitter->latency_tradeoff * 100.0f / tot_count; 201 late_factor = jitter->latency_tradeoff * 100.0f / tot_count;
202 else 202 else
203 late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count; 203 late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count;
204 204
205 /*fprintf(stderr, "late_factor = %f\n", late_factor);*/ 205 /*fprintf(stderr, "late_factor = %f\n", late_factor);*/
206 for (i=0;i<MAX_BUFFERS;i++) 206 for (i=0;i<MAX_BUFFERS;i++)
207 pos[i] = 0; 207 pos[i] = 0;
208 208
209 /* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late 209 /* Pick the TOP_DELAY "latest" packets (doesn't need to actually be late
210 for the current settings) */ 210 for the current settings) */
211 for (i=0;i<TOP_DELAY;i++) 211 for (i=0;i<TOP_DELAY;i++)
212 { 212 {
@@ -225,13 +225,13 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
225 if (next != -1) 225 if (next != -1)
226 { 226 {
227 spx_int32_t cost; 227 spx_int32_t cost;
228 228
229 if (i==0) 229 if (i==0)
230 worst = latest; 230 worst = latest;
231 best = latest; 231 best = latest;
232 latest = ROUND_DOWN(latest, jitter->delay_step); 232 latest = ROUND_DOWN(latest, jitter->delay_step);
233 pos[next]++; 233 pos[next]++;
234 234
235 /* Actual cost function that tells us how bad using this delay would be */ 235 /* Actual cost function that tells us how bad using this delay would be */
236 cost = -latest + late_factor*late; 236 cost = -latest + late_factor*late;
237 /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/ 237 /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/
@@ -243,24 +243,24 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
243 } else { 243 } else {
244 break; 244 break;
245 } 245 }
246 246
247 /* For the next timing we will consider, there will be one more late packet to count */ 247 /* For the next timing we will consider, there will be one more late packet to count */
248 late++; 248 late++;
249 /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */ 249 /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */
250 if (latest >= 0 && !penalty_taken) 250 if (latest >= 0 && !penalty_taken)
251 { 251 {
252 penalty_taken = 1; 252 penalty_taken = 1;
253 late+=2; 253 late+=4;
254 } 254 }
255 } 255 }
256 256
257 deltaT = best-worst; 257 deltaT = best-worst;
258 /* This is a default "automatic latency tradeoff" when none is provided */ 258 /* This is a default "automatic latency tradeoff" when none is provided */
259 jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY; 259 jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY;
260 /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/ 260 /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/
261 261
262 /* FIXME: Compute a short-term estimate too and combine with the long-term one */ 262 /* FIXME: Compute a short-term estimate too and combine with the long-term one */
263 263
264 /* Prevents reducing the buffer size when we haven't really had much data */ 264 /* Prevents reducing the buffer size when we haven't really had much data */
265 if (tot_count < TOP_DELAY && opt > 0) 265 if (tot_count < TOP_DELAY && opt > 0)
266 return 0; 266 return 0;
@@ -269,7 +269,7 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
269 269
270 270
271/** Initialise jitter buffer */ 271/** Initialise jitter buffer */
272JitterBuffer *jitter_buffer_init(int step_size) 272EXPORT JitterBuffer *jitter_buffer_init(int step_size)
273{ 273{
274 JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer)); 274 JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer));
275 if (jitter) 275 if (jitter)
@@ -294,7 +294,7 @@ JitterBuffer *jitter_buffer_init(int step_size)
294} 294}
295 295
296/** Reset jitter buffer */ 296/** Reset jitter buffer */
297void jitter_buffer_reset(JitterBuffer *jitter) 297EXPORT void jitter_buffer_reset(JitterBuffer *jitter)
298{ 298{
299 int i; 299 int i;
300 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) 300 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
@@ -315,7 +315,7 @@ void jitter_buffer_reset(JitterBuffer *jitter)
315 jitter->lost_count = 0; 315 jitter->lost_count = 0;
316 jitter->buffered = 0; 316 jitter->buffered = 0;
317 jitter->auto_tradeoff = 32000; 317 jitter->auto_tradeoff = 32000;
318 318
319 for (i=0;i<MAX_BUFFERS;i++) 319 for (i=0;i<MAX_BUFFERS;i++)
320 { 320 {
321 tb_init(&jitter->_tb[i]); 321 tb_init(&jitter->_tb[i]);
@@ -325,7 +325,7 @@ void jitter_buffer_reset(JitterBuffer *jitter)
325} 325}
326 326
327/** Destroy jitter buffer */ 327/** Destroy jitter buffer */
328void jitter_buffer_destroy(JitterBuffer *jitter) 328EXPORT void jitter_buffer_destroy(JitterBuffer *jitter)
329{ 329{
330 jitter_buffer_reset(jitter); 330 jitter_buffer_reset(jitter);
331 speex_free(jitter); 331 speex_free(jitter);
@@ -365,12 +365,12 @@ static void shift_timings(JitterBuffer *jitter, spx_int16_t amount)
365 365
366 366
367/** Put one packet into the jitter buffer */ 367/** Put one packet into the jitter buffer */
368void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet) 368EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
369{ 369{
370 int i,j; 370 int i,j;
371 int late; 371 int late;
372 /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/ 372 /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/
373 373
374 /* Cleanup buffer (remove old packets that weren't played) */ 374 /* Cleanup buffer (remove old packets that weren't played) */
375 if (!jitter->reset_state) 375 if (!jitter->reset_state)
376 { 376 {
@@ -388,7 +388,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
388 } 388 }
389 } 389 }
390 } 390 }
391 391
392 /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/ 392 /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/
393 /* Check if packet is late (could still be useful though) */ 393 /* Check if packet is late (could still be useful though) */
394 if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop)) 394 if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop))
@@ -398,7 +398,14 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
398 } else { 398 } else {
399 late = 0; 399 late = 0;
400 } 400 }
401 401
402 /* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is
403 * used to resync. */
404 if (jitter->lost_count>20)
405 {
406 jitter_buffer_reset(jitter);
407 }
408
402 /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */ 409 /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
403 if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp)) 410 if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp))
404 { 411 {
@@ -409,7 +416,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
409 if (jitter->packets[i].data==NULL) 416 if (jitter->packets[i].data==NULL)
410 break; 417 break;
411 } 418 }
412 419
413 /*No place left in the buffer, need to make room for it by discarding the oldest packet */ 420 /*No place left in the buffer, need to make room for it by discarding the oldest packet */
414 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 421 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
415 { 422 {
@@ -428,13 +435,9 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
428 else 435 else
429 speex_free(jitter->packets[i].data); 436 speex_free(jitter->packets[i].data);
430 jitter->packets[i].data=NULL; 437 jitter->packets[i].data=NULL;
431 if (jitter->lost_count>20) 438 /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
432 {
433 jitter_buffer_reset(jitter);
434 }
435 /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
436 } 439 }
437 440
438 /* Copy packet in buffer */ 441 /* Copy packet in buffer */
439 if (jitter->destroy) 442 if (jitter->destroy)
440 { 443 {
@@ -454,18 +457,18 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
454 else 457 else
455 jitter->arrival[i] = jitter->next_stop; 458 jitter->arrival[i] = jitter->next_stop;
456 } 459 }
457 460
458 461
459} 462}
460 463
461/** Get one packet from the jitter buffer */ 464/** Get one packet from the jitter buffer */
462int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset) 465EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset)
463{ 466{
464 int i; 467 int i;
465 unsigned int j; 468 unsigned int j;
466 int incomplete = 0; 469 int incomplete = 0;
467 spx_int16_t opt; 470 spx_int16_t opt;
468 471
469 if (start_offset != NULL) 472 if (start_offset != NULL)
470 *start_offset = 0; 473 *start_offset = 0;
471 474
@@ -485,7 +488,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
485 } 488 }
486 if (found) 489 if (found)
487 { 490 {
488 jitter->reset_state=0; 491 jitter->reset_state=0;
489 jitter->pointer_timestamp = oldest; 492 jitter->pointer_timestamp = oldest;
490 jitter->next_stop = oldest; 493 jitter->next_stop = oldest;
491 } else { 494 } else {
@@ -494,36 +497,36 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
494 return JITTER_BUFFER_MISSING; 497 return JITTER_BUFFER_MISSING;
495 } 498 }
496 } 499 }
497 500
498 501
499 jitter->last_returned_timestamp = jitter->pointer_timestamp; 502 jitter->last_returned_timestamp = jitter->pointer_timestamp;
500 503
501 if (jitter->interp_requested != 0) 504 if (jitter->interp_requested != 0)
502 { 505 {
503 packet->timestamp = jitter->pointer_timestamp; 506 packet->timestamp = jitter->pointer_timestamp;
504 packet->span = jitter->interp_requested; 507 packet->span = jitter->interp_requested;
505 508
506 /* Increment the pointer because it got decremented in the delay update */ 509 /* Increment the pointer because it got decremented in the delay update */
507 jitter->pointer_timestamp += jitter->interp_requested; 510 jitter->pointer_timestamp += jitter->interp_requested;
508 packet->len = 0; 511 packet->len = 0;
509 /*fprintf (stderr, "Deferred interpolate\n");*/ 512 /*fprintf (stderr, "Deferred interpolate\n");*/
510 513
511 jitter->interp_requested = 0; 514 jitter->interp_requested = 0;
512 515
513 jitter->buffered = packet->span - desired_span; 516 jitter->buffered = packet->span - desired_span;
514 517
515 return JITTER_BUFFER_INSERTION; 518 return JITTER_BUFFER_INSERTION;
516 } 519 }
517 520
518 /* Searching for the packet that fits best */ 521 /* Searching for the packet that fits best */
519 522
520 /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */ 523 /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
521 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) 524 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
522 { 525 {
523 if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span)) 526 if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span))
524 break; 527 break;
525 } 528 }
526 529
527 /* If no match, try for an "older" packet that still spans (fully) the current chunk */ 530 /* If no match, try for an "older" packet that still spans (fully) the current chunk */
528 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 531 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
529 { 532 {
@@ -533,7 +536,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
533 break; 536 break;
534 } 537 }
535 } 538 }
536 539
537 /* If still no match, try for an "older" packet that spans part of the current chunk */ 540 /* If still no match, try for an "older" packet that spans part of the current chunk */
538 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 541 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
539 { 542 {
@@ -543,7 +546,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
543 break; 546 break;
544 } 547 }
545 } 548 }
546 549
547 /* If still no match, try for earliest packet possible */ 550 /* If still no match, try for earliest packet possible */
548 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE) 551 if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
549 { 552 {
@@ -577,17 +580,17 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
577 if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE) 580 if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
578 { 581 {
579 spx_int32_t offset; 582 spx_int32_t offset;
580 583
581 /* We (obviously) haven't lost this packet */ 584 /* We (obviously) haven't lost this packet */
582 jitter->lost_count = 0; 585 jitter->lost_count = 0;
583 586
584 /* In this case, 0 isn't as a valid timestamp */ 587 /* In this case, 0 isn't as a valid timestamp */
585 if (jitter->arrival[i] != 0) 588 if (jitter->arrival[i] != 0)
586 { 589 {
587 update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin); 590 update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin);
588 } 591 }
589 592
590 593
591 if (jitter->packets[i].len > packet->len) 594 if (jitter->packets[i].len > packet->len)
592 { 595 {
593 speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len); 596 speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len);
@@ -611,10 +614,10 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
611 *start_offset = offset; 614 *start_offset = offset;
612 else if (offset != 0) 615 else if (offset != 0)
613 speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset); 616 speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset);
614 617
615 packet->timestamp = jitter->packets[i].timestamp; 618 packet->timestamp = jitter->packets[i].timestamp;
616 jitter->last_returned_timestamp = packet->timestamp; 619 jitter->last_returned_timestamp = packet->timestamp;
617 620
618 packet->span = jitter->packets[i].span; 621 packet->span = jitter->packets[i].span;
619 packet->sequence = jitter->packets[i].sequence; 622 packet->sequence = jitter->packets[i].sequence;
620 packet->user_data = jitter->packets[i].user_data; 623 packet->user_data = jitter->packets[i].user_data;
@@ -622,36 +625,36 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
622 jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span; 625 jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span;
623 626
624 jitter->buffered = packet->span - desired_span; 627 jitter->buffered = packet->span - desired_span;
625 628
626 if (start_offset != NULL) 629 if (start_offset != NULL)
627 jitter->buffered += *start_offset; 630 jitter->buffered += *start_offset;
628 631
629 return JITTER_BUFFER_OK; 632 return JITTER_BUFFER_OK;
630 } 633 }
631 634
632 635
633 /* If we haven't found anything worth returning */ 636 /* If we haven't found anything worth returning */
634 637
635 /*fprintf (stderr, "not found\n");*/ 638 /*fprintf (stderr, "not found\n");*/
636 jitter->lost_count++; 639 jitter->lost_count++;
637 /*fprintf (stderr, "m");*/ 640 /*fprintf (stderr, "m");*/
638 /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/ 641 /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/
639 642
640 opt = compute_opt_delay(jitter); 643 opt = compute_opt_delay(jitter);
641 644
642 /* Should we force an increase in the buffer or just do normal interpolation? */ 645 /* Should we force an increase in the buffer or just do normal interpolation? */
643 if (opt < 0) 646 if (opt < 0)
644 { 647 {
645 /* Need to increase buffering */ 648 /* Need to increase buffering */
646 649
647 /* Shift histogram to compensate */ 650 /* Shift histogram to compensate */
648 shift_timings(jitter, -opt); 651 shift_timings(jitter, -opt);
649 652
650 packet->timestamp = jitter->pointer_timestamp; 653 packet->timestamp = jitter->pointer_timestamp;
651 packet->span = -opt; 654 packet->span = -opt;
652 /* Don't move the pointer_timestamp forward */ 655 /* Don't move the pointer_timestamp forward */
653 packet->len = 0; 656 packet->len = 0;
654 657
655 jitter->buffered = packet->span - desired_span; 658 jitter->buffered = packet->span - desired_span;
656 return JITTER_BUFFER_INSERTION; 659 return JITTER_BUFFER_INSERTION;
657 /*jitter->pointer_timestamp -= jitter->delay_step;*/ 660 /*jitter->pointer_timestamp -= jitter->delay_step;*/
@@ -659,12 +662,12 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
659 } else { 662 } else {
660 /* Normal packet loss */ 663 /* Normal packet loss */
661 packet->timestamp = jitter->pointer_timestamp; 664 packet->timestamp = jitter->pointer_timestamp;
662 665
663 desired_span = ROUND_DOWN(desired_span, jitter->concealment_size); 666 desired_span = ROUND_DOWN(desired_span, jitter->concealment_size);
664 packet->span = desired_span; 667 packet->span = desired_span;
665 jitter->pointer_timestamp += desired_span; 668 jitter->pointer_timestamp += desired_span;
666 packet->len = 0; 669 packet->len = 0;
667 670
668 jitter->buffered = packet->span - desired_span; 671 jitter->buffered = packet->span - desired_span;
669 return JITTER_BUFFER_MISSING; 672 return JITTER_BUFFER_MISSING;
670 /*fprintf (stderr, "Normal loss\n");*/ 673 /*fprintf (stderr, "Normal loss\n");*/
@@ -673,7 +676,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
673 676
674} 677}
675 678
676int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet) 679EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet)
677{ 680{
678 int i, j; 681 int i, j;
679 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++) 682 for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
@@ -713,11 +716,11 @@ static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket
713{ 716{
714 spx_int16_t opt = compute_opt_delay(jitter); 717 spx_int16_t opt = compute_opt_delay(jitter);
715 /*fprintf(stderr, "opt adjustment is %d ", opt);*/ 718 /*fprintf(stderr, "opt adjustment is %d ", opt);*/
716 719
717 if (opt < 0) 720 if (opt < 0)
718 { 721 {
719 shift_timings(jitter, -opt); 722 shift_timings(jitter, -opt);
720 723
721 jitter->pointer_timestamp += opt; 724 jitter->pointer_timestamp += opt;
722 jitter->interp_requested = -opt; 725 jitter->interp_requested = -opt;
723 /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/ 726 /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/
@@ -727,14 +730,14 @@ static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket
727 jitter->pointer_timestamp += opt; 730 jitter->pointer_timestamp += opt;
728 /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/ 731 /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/
729 } 732 }
730 733
731 return opt; 734 return opt;
732} 735}
733 736
734/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */ 737/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
735int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset) 738EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
736{ 739{
737 /* If the programmer calls jitter_buffer_update_delay() directly, 740 /* If the programmer calls jitter_buffer_update_delay() directly,
738 automatically disable auto-adjustment */ 741 automatically disable auto-adjustment */
739 jitter->auto_adjust = 0; 742 jitter->auto_adjust = 0;
740 743
@@ -742,17 +745,17 @@ int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet,
742} 745}
743 746
744/** Get pointer timestamp of jitter buffer */ 747/** Get pointer timestamp of jitter buffer */
745int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter) 748EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
746{ 749{
747 return jitter->pointer_timestamp; 750 return jitter->pointer_timestamp;
748} 751}
749 752
750void jitter_buffer_tick(JitterBuffer *jitter) 753EXPORT void jitter_buffer_tick(JitterBuffer *jitter)
751{ 754{
752 /* Automatically-adjust the buffering delay if requested */ 755 /* Automatically-adjust the buffering delay if requested */
753 if (jitter->auto_adjust) 756 if (jitter->auto_adjust)
754 _jitter_buffer_update_delay(jitter, NULL, NULL); 757 _jitter_buffer_update_delay(jitter, NULL, NULL);
755 758
756 if (jitter->buffered >= 0) 759 if (jitter->buffered >= 0)
757 { 760 {
758 jitter->next_stop = jitter->pointer_timestamp - jitter->buffered; 761 jitter->next_stop = jitter->pointer_timestamp - jitter->buffered;
@@ -763,12 +766,12 @@ void jitter_buffer_tick(JitterBuffer *jitter)
763 jitter->buffered = 0; 766 jitter->buffered = 0;
764} 767}
765 768
766void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem) 769EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
767{ 770{
768 /* Automatically-adjust the buffering delay if requested */ 771 /* Automatically-adjust the buffering delay if requested */
769 if (jitter->auto_adjust) 772 if (jitter->auto_adjust)
770 _jitter_buffer_update_delay(jitter, NULL, NULL); 773 _jitter_buffer_update_delay(jitter, NULL, NULL);
771 774
772 if (jitter->buffered < 0) 775 if (jitter->buffered < 0)
773 speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered); 776 speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered);
774 jitter->next_stop = jitter->pointer_timestamp - rem; 777 jitter->next_stop = jitter->pointer_timestamp - rem;
@@ -776,7 +779,7 @@ void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
776 779
777 780
778/* Used like the ioctl function to control the jitter buffer parameters */ 781/* Used like the ioctl function to control the jitter buffer parameters */
779int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr) 782EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
780{ 783{
781 int count, i; 784 int count, i;
782 switch(request) 785 switch(request)
@@ -836,4 +839,3 @@ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
836 } 839 }
837 return 0; 840 return 0;
838} 841}
839
diff --git a/lib/rbcodec/codecs/libspeex/mdf.c b/lib/rbcodec/codecs/libspeex/mdf.c
index 1994f2a886..cfbe4d1284 100644
--- a/lib/rbcodec/codecs/libspeex/mdf.c
+++ b/lib/rbcodec/codecs/libspeex/mdf.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2006 Jean-Marc Valin 1/* Copyright (C) 2003-2008 Jean-Marc Valin
2 2
3 File: mdf.c 3 File: mdf.c
4 Echo canceller based on the MDF algorithm (see below) 4 Echo canceller based on the MDF algorithm (see below)
@@ -33,36 +33,36 @@
33/* 33/*
34 The echo canceller is based on the MDF algorithm described in: 34 The echo canceller is based on the MDF algorithm described in:
35 35
36 J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, 36 J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter,
37 IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, 37 IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2,
38 February 1990. 38 February 1990.
39 39
40 We use the Alternatively Updated MDF (AUMDF) variant. Robustness to 40 We use the Alternatively Updated MDF (AUMDF) variant. Robustness to
41 double-talk is achieved using a variable learning rate as described in: 41 double-talk is achieved using a variable learning rate as described in:
42 42
43 Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo 43 Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo
44 Cancellation With Double-Talk. IEEE Transactions on Audio, 44 Cancellation With Double-Talk. IEEE Transactions on Audio,
45 Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007. 45 Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007.
46 http://people.xiph.org/~jm/papers/valin_taslp2006.pdf 46 http://people.xiph.org/~jm/papers/valin_taslp2006.pdf
47 47
48 There is no explicit double-talk detection, but a continuous variation 48 There is no explicit double-talk detection, but a continuous variation
49 in the learning rate based on residual echo, double-talk and background 49 in the learning rate based on residual echo, double-talk and background
50 noise. 50 noise.
51 51
52 About the fixed-point version: 52 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
54 are represented with 32-bit words, but only the top 16 bits are used 54 are represented with 32-bit words, but only the top 16 bits are used
55 in most cases. The lower 16 bits are completely unreliable (due to the 55 in most cases. The lower 16 bits are completely unreliable (due to the
56 fact that the update is done only on the top bits), but help in the 56 fact that the update is done only on the top bits), but help in the
57 adaptation -- probably by removing a "threshold effect" due to 57 adaptation -- probably by removing a "threshold effect" due to
58 quantization (rounding going to zero) when the gradient is small. 58 quantization (rounding going to zero) when the gradient is small.
59 59
60 Another kludge that seems to work good: when performing the weight 60 Another kludge that seems to work good: when performing the weight
61 update, we only move half the way toward the "goal" this seems to 61 update, we only move half the way toward the "goal" this seems to
62 reduce the effect of quantization noise in the update phase. This 62 reduce the effect of quantization noise in the update phase. This
63 can be seen as applying a gradient descent on a "soft constraint" 63 can be seen as applying a gradient descent on a "soft constraint"
64 instead of having a hard constraint. 64 instead of having a hard constraint.
65 65
66*/ 66*/
67 67
68#ifdef HAVE_CONFIG_H 68#ifdef HAVE_CONFIG_H
@@ -88,6 +88,12 @@
88#define WEIGHT_SHIFT 0 88#define WEIGHT_SHIFT 0
89#endif 89#endif
90 90
91#ifdef FIXED_POINT
92#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
93#else
94#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
95#endif
96
91/* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk 97/* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk
92 and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */ 98 and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */
93#define TWO_PATH 99#define TWO_PATH
@@ -131,13 +137,15 @@ struct SpeexEchoState_ {
131 int adapted; 137 int adapted;
132 int saturated; 138 int saturated;
133 int screwed_up; 139 int screwed_up;
140 int C; /** Number of input channels (microphones) */
141 int K; /** Number of output channels (loudspeakers) */
134 spx_int32_t sampling_rate; 142 spx_int32_t sampling_rate;
135 spx_word16_t spec_average; 143 spx_word16_t spec_average;
136 spx_word16_t beta0; 144 spx_word16_t beta0;
137 spx_word16_t beta_max; 145 spx_word16_t beta_max;
138 spx_word32_t sum_adapt; 146 spx_word32_t sum_adapt;
139 spx_word16_t leak_estimate; 147 spx_word16_t leak_estimate;
140 148
141 spx_word16_t *e; /* scratch */ 149 spx_word16_t *e; /* scratch */
142 spx_word16_t *x; /* Far-end input buffer (2N) */ 150 spx_word16_t *x; /* Far-end input buffer (2N) */
143 spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */ 151 spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */
@@ -171,10 +179,10 @@ struct SpeexEchoState_ {
171 spx_word16_t *window; 179 spx_word16_t *window;
172 spx_word16_t *prop; 180 spx_word16_t *prop;
173 void *fft_table; 181 void *fft_table;
174 spx_word16_t memX, memD, memE; 182 spx_word16_t *memX, *memD, *memE;
175 spx_word16_t preemph; 183 spx_word16_t preemph;
176 spx_word16_t notch_radius; 184 spx_word16_t notch_radius;
177 spx_mem_t notch_mem[2]; 185 spx_mem_t *notch_mem;
178 186
179 /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ 187 /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */
180 spx_int16_t *play_buf; 188 spx_int16_t *play_buf;
@@ -182,7 +190,7 @@ struct SpeexEchoState_ {
182 int play_buf_started; 190 int play_buf_started;
183}; 191};
184 192
185static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem) 193static 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)
186{ 194{
187 int i; 195 int i;
188 spx_word16_t den2; 196 spx_word16_t den2;
@@ -190,11 +198,11 @@ static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius,
190 den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius)); 198 den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius));
191#else 199#else
192 den2 = radius*radius + .7*(1-radius)*(1-radius); 200 den2 = radius*radius + .7*(1-radius)*(1-radius);
193#endif 201#endif
194 /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ 202 /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/
195 for (i=0;i<len;i++) 203 for (i=0;i<len;i++)
196 { 204 {
197 spx_word16_t vin = in[i]; 205 spx_word16_t vin = in[i*stride];
198 spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15); 206 spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15);
199#ifdef FIXED_POINT 207#ifdef FIXED_POINT
200 mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1); 208 mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1);
@@ -234,6 +242,18 @@ static inline void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N
234 ps[j]=MULT16_16(X[i],X[i]); 242 ps[j]=MULT16_16(X[i],X[i]);
235} 243}
236 244
245/** Compute power spectrum of a half-complex (packed) vector and accumulate */
246static inline void power_spectrum_accum(const spx_word16_t *X, spx_word32_t *ps, int N)
247{
248 int i, j;
249 ps[0]+=MULT16_16(X[0],X[0]);
250 for (i=1,j=1;i<N-1;i+=2,j++)
251 {
252 ps[j] += MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]);
253 }
254 ps[j]+=MULT16_16(X[i],X[i]);
255}
256
237/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ 257/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */
238#ifdef FIXED_POINT 258#ifdef FIXED_POINT
239static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) 259static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M)
@@ -330,16 +350,17 @@ static inline void weighted_spectral_mul_conj(const spx_float_t *w, const spx_fl
330 prod[i] = FLOAT_MUL32(W,MULT16_16(X[i],Y[i])); 350 prod[i] = FLOAT_MUL32(W,MULT16_16(X[i],Y[i]));
331} 351}
332 352
333static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, spx_word16_t *prop) 353static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, int P, spx_word16_t *prop)
334{ 354{
335 int i, j; 355 int i, j, p;
336 spx_word16_t max_sum = 1; 356 spx_word16_t max_sum = 1;
337 spx_word32_t prop_sum = 1; 357 spx_word32_t prop_sum = 1;
338 for (i=0;i<M;i++) 358 for (i=0;i<M;i++)
339 { 359 {
340 spx_word32_t tmp = 1; 360 spx_word32_t tmp = 1;
341 for (j=0;j<N;j++) 361 for (p=0;p<P;p++)
342 tmp += MULT16_16(EXTRACT16(SHR32(W[i*N+j],18)), EXTRACT16(SHR32(W[i*N+j],18))); 362 for (j=0;j<N;j++)
363 tmp += MULT16_16(EXTRACT16(SHR32(W[p*N*M + i*N+j],18)), EXTRACT16(SHR32(W[p*N*M + i*N+j],18)));
343#ifdef FIXED_POINT 364#ifdef FIXED_POINT
344 /* Just a security in case an overflow were to occur */ 365 /* Just a security in case an overflow were to occur */
345 tmp = MIN32(ABS32(tmp), 536870912); 366 tmp = MIN32(ABS32(tmp), 536870912);
@@ -378,11 +399,20 @@ static void dump_audio(const spx_int16_t *rec, const spx_int16_t *play, const sp
378#endif 399#endif
379 400
380/** Creates a new echo canceller state */ 401/** Creates a new echo canceller state */
381SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length) 402EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
382{ 403{
383 int i,N,M; 404 return speex_echo_state_init_mc(frame_size, filter_length, 1, 1);
405}
406
407EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers)
408{
409 int i,N,M, C, K;
384 SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState)); 410 SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState));
385 411
412 st->K = nb_speakers;
413 st->C = nb_mic;
414 C=st->C;
415 K=st->K;
386#ifdef DUMP_ECHO_CANCEL_DATA 416#ifdef DUMP_ECHO_CANCEL_DATA
387 if (rFile || pFile || oFile) 417 if (rFile || pFile || oFile)
388 speex_fatal("Opening dump files twice"); 418 speex_fatal("Opening dump files twice");
@@ -390,7 +420,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
390 pFile = fopen("aec_play.sw", "wb"); 420 pFile = fopen("aec_play.sw", "wb");
391 oFile = fopen("aec_out.sw", "wb"); 421 oFile = fopen("aec_out.sw", "wb");
392#endif 422#endif
393 423
394 st->frame_size = frame_size; 424 st->frame_size = frame_size;
395 st->window_size = 2*frame_size; 425 st->window_size = 2*frame_size;
396 N = st->window_size; 426 N = st->window_size;
@@ -412,24 +442,24 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
412 st->leak_estimate = 0; 442 st->leak_estimate = 0;
413 443
414 st->fft_table = spx_fft_init(N); 444 st->fft_table = spx_fft_init(N);
415 445
416 st->e = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 446 st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
417 st->x = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 447 st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t));
418 st->input = (spx_word16_t*)speex_alloc(st->frame_size*sizeof(spx_word16_t)); 448 st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t));
419 st->y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 449 st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
420 st->last_y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 450 st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
421 st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 451 st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
422 st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 452 st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
423 st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 453 st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
424 st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 454 st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
425 st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t)); 455 st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
426 456
427 st->X = (spx_word16_t*)speex_alloc((M+1)*N*sizeof(spx_word16_t)); 457 st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t));
428 st->Y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 458 st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
429 st->E = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); 459 st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
430 st->W = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t)); 460 st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t));
431#ifdef TWO_PATH 461#ifdef TWO_PATH
432 st->foreground = (spx_word16_t*)speex_alloc(M*N*sizeof(spx_word16_t)); 462 st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t));
433#endif 463#endif
434 st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 464 st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
435 st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t)); 465 st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t));
@@ -450,7 +480,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
450#endif 480#endif
451 for (i=0;i<=st->frame_size;i++) 481 for (i=0;i<=st->frame_size;i++)
452 st->power_1[i] = FLOAT_ONE; 482 st->power_1[i] = FLOAT_ONE;
453 for (i=0;i<N*M;i++) 483 for (i=0;i<N*M*K*C;i++)
454 st->W[i] = 0; 484 st->W[i] = 0;
455 { 485 {
456 spx_word32_t sum = 0; 486 spx_word32_t sum = 0;
@@ -465,11 +495,13 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
465 } 495 }
466 for (i=M-1;i>=0;i--) 496 for (i=M-1;i>=0;i--)
467 { 497 {
468 st->prop[i] = DIV32(MULT16_16(QCONST16(.8,15), st->prop[i]),sum); 498 st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum);
469 } 499 }
470 } 500 }
471 501
472 st->memX=st->memD=st->memE=0; 502 st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t));
503 st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t));
504 st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t));
473 st->preemph = QCONST16(.9,15); 505 st->preemph = QCONST16(.9,15);
474 if (st->sampling_rate<12000) 506 if (st->sampling_rate<12000)
475 st->notch_radius = QCONST16(.9, 15); 507 st->notch_radius = QCONST16(.9, 15);
@@ -478,30 +510,32 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
478 else 510 else
479 st->notch_radius = QCONST16(.992, 15); 511 st->notch_radius = QCONST16(.992, 15);
480 512
481 st->notch_mem[0] = st->notch_mem[1] = 0; 513 st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t));
482 st->adapted = 0; 514 st->adapted = 0;
483 st->Pey = st->Pyy = FLOAT_ONE; 515 st->Pey = st->Pyy = FLOAT_ONE;
484 516
485#ifdef TWO_PATH 517#ifdef TWO_PATH
486 st->Davg1 = st->Davg2 = 0; 518 st->Davg1 = st->Davg2 = 0;
487 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 519 st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
488#endif 520#endif
489 521
490 st->play_buf = (spx_int16_t*)speex_alloc((PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); 522 st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t));
491 st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; 523 st->play_buf_pos = PLAYBACK_DELAY*st->frame_size;
492 st->play_buf_started = 0; 524 st->play_buf_started = 0;
493 525
494 return st; 526 return st;
495} 527}
496 528
497/** Resets echo canceller state */ 529/** Resets echo canceller state */
498void speex_echo_state_reset(SpeexEchoState *st) 530EXPORT void speex_echo_state_reset(SpeexEchoState *st)
499{ 531{
500 int i, M, N; 532 int i, M, N, C, K;
501 st->cancel_count=0; 533 st->cancel_count=0;
502 st->screwed_up = 0; 534 st->screwed_up = 0;
503 N = st->window_size; 535 N = st->window_size;
504 M = st->M; 536 M = st->M;
537 C=st->C;
538 K=st->K;
505 for (i=0;i<N*M;i++) 539 for (i=0;i<N*M;i++)
506 st->W[i] = 0; 540 st->W[i] = 0;
507#ifdef TWO_PATH 541#ifdef TWO_PATH
@@ -521,13 +555,20 @@ void speex_echo_state_reset(SpeexEchoState *st)
521 { 555 {
522 st->last_y[i] = 0; 556 st->last_y[i] = 0;
523 } 557 }
524 for (i=0;i<N;i++) 558 for (i=0;i<N*C;i++)
525 { 559 {
526 st->E[i] = 0; 560 st->E[i] = 0;
561 }
562 for (i=0;i<N*K;i++)
563 {
527 st->x[i] = 0; 564 st->x[i] = 0;
528 } 565 }
529 st->notch_mem[0] = st->notch_mem[1] = 0; 566 for (i=0;i<2*C;i++)
530 st->memX=st->memD=st->memE=0; 567 st->notch_mem[i] = 0;
568 for (i=0;i<C;i++)
569 st->memD[i]=st->memE[i]=0;
570 for (i=0;i<K;i++)
571 st->memX[i]=0;
531 572
532 st->saturated = 0; 573 st->saturated = 0;
533 st->adapted = 0; 574 st->adapted = 0;
@@ -545,7 +586,7 @@ void speex_echo_state_reset(SpeexEchoState *st)
545} 586}
546 587
547/** Destroys an echo canceller state */ 588/** Destroys an echo canceller state */
548void speex_echo_state_destroy(SpeexEchoState *st) 589EXPORT void speex_echo_state_destroy(SpeexEchoState *st)
549{ 590{
550 spx_fft_destroy(st->fft_table); 591 spx_fft_destroy(st->fft_table);
551 592
@@ -576,9 +617,14 @@ void speex_echo_state_destroy(SpeexEchoState *st)
576#ifdef FIXED_POINT 617#ifdef FIXED_POINT
577 speex_free(st->wtmp2); 618 speex_free(st->wtmp2);
578#endif 619#endif
620 speex_free(st->memX);
621 speex_free(st->memD);
622 speex_free(st->memE);
623 speex_free(st->notch_mem);
624
579 speex_free(st->play_buf); 625 speex_free(st->play_buf);
580 speex_free(st); 626 speex_free(st);
581 627
582#ifdef DUMP_ECHO_CANCEL_DATA 628#ifdef DUMP_ECHO_CANCEL_DATA
583 fclose(rFile); 629 fclose(rFile);
584 fclose(pFile); 630 fclose(pFile);
@@ -587,7 +633,7 @@ void speex_echo_state_destroy(SpeexEchoState *st)
587#endif 633#endif
588} 634}
589 635
590void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out) 636EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out)
591{ 637{
592 int i; 638 int i;
593 /*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/ 639 /*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/
@@ -610,7 +656,7 @@ void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t
610 } 656 }
611} 657}
612 658
613void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 659EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)
614{ 660{
615 /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/ 661 /*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/
616 if (!st->play_buf_started) 662 if (!st->play_buf_started)
@@ -637,16 +683,16 @@ void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)
637} 683}
638 684
639/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */ 685/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */
640void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout) 686EXPORT 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)
641{ 687{
642 speex_echo_cancellation(st, in, far_end, out); 688 speex_echo_cancellation(st, in, far_end, out);
643} 689}
644 690
645/** Performs echo cancellation on a frame */ 691/** Performs echo cancellation on a frame */
646void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out) 692EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out)
647{ 693{
648 int i,j; 694 int i,j, chan, speak;
649 int N,M; 695 int N,M, C, K;
650 spx_word32_t Syy,See,Sxx,Sdd, Sff; 696 spx_word32_t Syy,See,Sxx,Sdd, Sff;
651#ifdef TWO_PATH 697#ifdef TWO_PATH
652 spx_word32_t Dbf; 698 spx_word32_t Dbf;
@@ -658,9 +704,12 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
658 spx_float_t alpha, alpha_1; 704 spx_float_t alpha, alpha_1;
659 spx_word16_t RER; 705 spx_word16_t RER;
660 spx_word32_t tmp32; 706 spx_word32_t tmp32;
661 707
662 N = st->window_size; 708 N = st->window_size;
663 M = st->M; 709 M = st->M;
710 C = st->C;
711 K = st->K;
712
664 st->cancel_count++; 713 st->cancel_count++;
665#ifdef FIXED_POINT 714#ifdef FIXED_POINT
666 ss=DIV32_16(11469,M); 715 ss=DIV32_16(11469,M);
@@ -670,157 +719,198 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
670 ss_1 = 1-ss; 719 ss_1 = 1-ss;
671#endif 720#endif
672 721
673 /* Apply a notch filter to make sure DC doesn't end up causing problems */ 722 for (chan = 0; chan < C; chan++)
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 { 723 {
678 spx_word32_t tmp32; 724 /* Apply a notch filter to make sure DC doesn't end up causing problems */
679 tmp32 = SUB32(EXTEND32(far_end[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memX))); 725 filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C);
680#ifdef FIXED_POINT 726 /* Copy input data to buffer and apply pre-emphasis */
681 /* If saturation occurs here, we need to freeze adaptation for M+1 frames (not just one) */ 727 /* Copy input data to buffer */
682 if (tmp32 > 32767) 728 for (i=0;i<st->frame_size;i++)
683 { 729 {
684 tmp32 = 32767; 730 spx_word32_t tmp32;
685 st->saturated = M+1; 731 /* FIXME: This core has changed a bit, need to merge properly */
732 tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan])));
733#ifdef FIXED_POINT
734 if (tmp32 > 32767)
735 {
736 tmp32 = 32767;
737 if (st->saturated == 0)
738 st->saturated = 1;
739 }
740 if (tmp32 < -32767)
741 {
742 tmp32 = -32767;
743 if (st->saturated == 0)
744 st->saturated = 1;
745 }
746#endif
747 st->memD[chan] = st->input[chan*st->frame_size+i];
748 st->input[chan*st->frame_size+i] = EXTRACT16(tmp32);
686 } 749 }
687 if (tmp32 < -32767) 750 }
751
752 for (speak = 0; speak < K; speak++)
753 {
754 for (i=0;i<st->frame_size;i++)
688 { 755 {
689 tmp32 = -32767; 756 spx_word32_t tmp32;
690 st->saturated = M+1; 757 st->x[speak*N+i] = st->x[speak*N+i+st->frame_size];
691 } 758 tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak])));
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 759#ifdef FIXED_POINT
698 if (tmp32 > 32767) 760 /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */
699 { 761 if (tmp32 > 32767)
700 tmp32 = 32767; 762 {
701 if (st->saturated == 0) 763 tmp32 = 32767;
702 st->saturated = 1; 764 st->saturated = M+1;
703 } 765 }
704 if (tmp32 < -32767) 766 if (tmp32 < -32767)
767 {
768 tmp32 = -32767;
769 st->saturated = M+1;
770 }
771#endif
772 st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32);
773 st->memX[speak] = far_end[i*K+speak];
774 }
775 }
776
777 for (speak = 0; speak < K; speak++)
778 {
779 /* Shift memory: this could be optimized eventually*/
780 for (j=M-1;j>=0;j--)
705 { 781 {
706 tmp32 = -32767; 782 for (i=0;i<N;i++)
707 if (st->saturated == 0) 783 st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i];
708 st->saturated = 1;
709 } 784 }
710#endif 785 /* Convert x (echo input) to frequency domain */
711 st->memD = st->input[i]; 786 spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]);
712 st->input[i] = tmp32;
713 } 787 }
714 788
715 /* Shift memory: this could be optimized eventually*/ 789 Sxx = 0;
716 for (j=M-1;j>=0;j--) 790 for (speak = 0; speak < K; speak++)
717 { 791 {
718 for (i=0;i<N;i++) 792 Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
719 st->X[(j+1)*N+i] = st->X[j*N+i]; 793 power_spectrum_accum(st->X+speak*N, st->Xf, N);
720 } 794 }
721 795
722 /* Convert x (far end) to frequency domain */ 796 Sff = 0;
723 spx_fft(st->fft_table, st->x, &st->X[0]); 797 for (chan = 0; chan < C; chan++)
724 for (i=0;i<N;i++) 798 {
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
731#ifdef TWO_PATH 799#ifdef TWO_PATH
732 /* Compute foreground filter */ 800 /* Compute foreground filter */
733 spectral_mul_accum16(st->X, st->foreground, st->Y, N, M); 801 spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K);
734 spx_ifft(st->fft_table, st->Y, st->e); 802 spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N);
735 for (i=0;i<st->frame_size;i++) 803 for (i=0;i<st->frame_size;i++)
736 st->e[i] = SUB16(st->input[i], st->e[i+st->frame_size]); 804 st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]);
737 Sff = mdf_inner_prod(st->e, st->e, st->frame_size); 805 Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
738#endif 806#endif
739 807 }
808
740 /* Adjust proportional adaption rate */ 809 /* Adjust proportional adaption rate */
741 mdf_adjust_prop (st->W, N, M, st->prop); 810 /* FIXME: Adjust that for C, K*/
811 if (st->adapted)
812 mdf_adjust_prop (st->W, N, M, C*K, st->prop);
742 /* Compute weight gradient */ 813 /* Compute weight gradient */
743 if (st->saturated == 0) 814 if (st->saturated == 0)
744 { 815 {
745 for (j=M-1;j>=0;j--) 816 for (chan = 0; chan < C; chan++)
746 { 817 {
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); 818 for (speak = 0; speak < K; speak++)
748 for (i=0;i<N;i++) 819 {
749 st->W[j*N+i] = ADD32(st->W[j*N+i], st->PHI[i]); 820 for (j=M-1;j>=0;j--)
750 821 {
822 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);
823 for (i=0;i<N;i++)
824 st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i];
825 }
826 }
751 } 827 }
752 } else { 828 } else {
753 st->saturated--; 829 st->saturated--;
754 } 830 }
755 831
832 /* FIXME: MC conversion required */
756 /* Update weight to prevent circular convolution (MDF / AUMDF) */ 833 /* Update weight to prevent circular convolution (MDF / AUMDF) */
757 for (j=0;j<M;j++) 834 for (chan = 0; chan < C; chan++)
758 { 835 {
759 /* This is a variant of the Alternatively Updated MDF (AUMDF) */ 836 for (speak = 0; speak < K; speak++)
760 /* Remove the "if" to make this an MDF filter */
761 if (j==0 || st->cancel_count%(M-1) == j-1)
762 { 837 {
763#ifdef FIXED_POINT 838 for (j=0;j<M;j++)
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++)
768 { 839 {
769 st->wtmp[i]=0; 840 /* This is a variant of the Alternatively Updated MDF (AUMDF) */
770 } 841 /* Remove the "if" to make this an MDF filter */
771 for (i=st->frame_size;i<N;i++) 842 if (j==0 || st->cancel_count%(M-1) == j-1)
772 { 843 {
773 st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 844#ifdef FIXED_POINT
774 } 845 for (i=0;i<N;i++)
775 spx_fft(st->fft_table, st->wtmp, st->wtmp2); 846 st->wtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16));
776 /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 847 spx_ifft(st->fft_table, st->wtmp2, st->wtmp);
777 for (i=0;i<N;i++) 848 for (i=0;i<st->frame_size;i++)
778 st->W[j*N+i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 849 {
850 st->wtmp[i]=0;
851 }
852 for (i=st->frame_size;i<N;i++)
853 {
854 st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP);
855 }
856 spx_fft(st->fft_table, st->wtmp, st->wtmp2);
857 /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */
858 for (i=0;i<N;i++)
859 st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);
779#else 860#else
780 spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 861 spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp);
781 for (i=st->frame_size;i<N;i++) 862 for (i=st->frame_size;i<N;i++)
782 { 863 {
783 st->wtmp[i]=0; 864 st->wtmp[i]=0;
784 } 865 }
785 spx_fft(st->fft_table, st->wtmp, &st->W[j*N]); 866 spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]);
786#endif 867#endif
868 }
869 }
787 } 870 }
788 } 871 }
789 872
790 /* Compute filter response Y */ 873 /* So we can use power_spectrum_accum */
791 spectral_mul_accum(st->X, st->W, st->Y, N, M); 874 for (i=0;i<=st->frame_size;i++)
792 spx_ifft(st->fft_table, st->Y, st->y); 875 st->Rf[i] = st->Yf[i] = st->Xf[i] = 0;
793 876
877 Dbf = 0;
878 See = 0;
794#ifdef TWO_PATH 879#ifdef TWO_PATH
795 /* Difference in response, this is used to estimate the variance of our residual power estimate */ 880 /* Difference in response, this is used to estimate the variance of our residual power estimate */
796 for (i=0;i<st->frame_size;i++) 881 for (chan = 0; chan < C; chan++)
797 st->e[i] = SUB16(st->e[i+st->frame_size], st->y[i+st->frame_size]); 882 {
798 Dbf = 10+mdf_inner_prod(st->e, st->e, st->frame_size); 883 spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K);
884 spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N);
885 for (i=0;i<st->frame_size;i++)
886 st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]);
887 Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
888 for (i=0;i<st->frame_size;i++)
889 st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);
890 See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
891 }
799#endif 892#endif
800 893
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);
804#ifndef TWO_PATH 894#ifndef TWO_PATH
805 Sff = See; 895 Sff = See;
806#endif 896#endif
807 897
808#ifdef TWO_PATH 898#ifdef TWO_PATH
809 /* Logic for updating the foreground filter */ 899 /* Logic for updating the foreground filter */
810 900
811 /* For two time windows, compute the mean of the energy difference, as well as the variance */ 901 /* For two time windows, compute the mean of the energy difference, as well as the variance */
812 st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See))); 902 st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See)));
813 st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See))); 903 st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See)));
814 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))); 904 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)));
815 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))); 905 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 906
817 /* Equivalent float code: 907 /* Equivalent float code:
818 st->Davg1 = .6*st->Davg1 + .4*(Sff-See); 908 st->Davg1 = .6*st->Davg1 + .4*(Sff-See);
819 st->Davg2 = .85*st->Davg2 + .15*(Sff-See); 909 st->Davg2 = .85*st->Davg2 + .15*(Sff-See);
820 st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf; 910 st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf;
821 st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf; 911 st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf;
822 */ 912 */
823 913
824 update_foreground = 0; 914 update_foreground = 0;
825 /* Check if we have a statistically significant reduction in the residual echo */ 915 /* Check if we have a statistically significant reduction in the residual echo */
826 /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */ 916 /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */
@@ -830,18 +920,19 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
830 update_foreground = 1; 920 update_foreground = 1;
831 else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2)))) 921 else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2))))
832 update_foreground = 1; 922 update_foreground = 1;
833 923
834 /* Do we update? */ 924 /* Do we update? */
835 if (update_foreground) 925 if (update_foreground)
836 { 926 {
837 st->Davg1 = st->Davg2 = 0; 927 st->Davg1 = st->Davg2 = 0;
838 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 928 st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
839 /* Copy background filter to foreground filter */ 929 /* Copy background filter to foreground filter */
840 for (i=0;i<N*M;i++) 930 for (i=0;i<N*M*C*K;i++)
841 st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16)); 931 st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16));
842 /* Apply a smooth transition so as to not introduce blocking artifacts */ 932 /* Apply a smooth transition so as to not introduce blocking artifacts */
843 for (i=0;i<st->frame_size;i++) 933 for (chan = 0; chan < C; chan++)
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]); 934 for (i=0;i<st->frame_size;i++)
935 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]);
845 } else { 936 } else {
846 int reset_background=0; 937 int reset_background=0;
847 /* Otherwise, check if the background filter is significantly worse */ 938 /* Otherwise, check if the background filter is significantly worse */
@@ -854,13 +945,16 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
854 if (reset_background) 945 if (reset_background)
855 { 946 {
856 /* Copy foreground filter to background filter */ 947 /* Copy foreground filter to background filter */
857 for (i=0;i<N*M;i++) 948 for (i=0;i<N*M*C*K;i++)
858 st->W[i] = SHL32(EXTEND32(st->foreground[i]),16); 949 st->W[i] = SHL32(EXTEND32(st->foreground[i]),16);
859 /* We also need to copy the output so as to get correct adaptation */ 950 /* We also need to copy the output so as to get correct adaptation */
860 for (i=0;i<st->frame_size;i++) 951 for (chan = 0; chan < C; chan++)
861 st->y[i+st->frame_size] = st->e[i+st->frame_size]; 952 {
862 for (i=0;i<st->frame_size;i++) 953 for (i=0;i<st->frame_size;i++)
863 st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]); 954 st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size];
955 for (i=0;i<st->frame_size;i++)
956 st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);
957 }
864 See = Sff; 958 See = Sff;
865 st->Davg1 = st->Davg2 = 0; 959 st->Davg1 = st->Davg2 = 0;
866 st->Dvar1 = st->Dvar2 = FLOAT_ZERO; 960 st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
@@ -868,50 +962,60 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
868 } 962 }
869#endif 963#endif
870 964
871 /* Compute error signal (for the output with de-emphasis) */ 965 Sey = Syy = Sdd = 0;
872 for (i=0;i<st->frame_size;i++) 966 for (chan = 0; chan < C; chan++)
873 { 967 {
874 spx_word32_t tmp_out; 968 /* Compute error signal (for the output with de-emphasis) */
969 for (i=0;i<st->frame_size;i++)
970 {
971 spx_word32_t tmp_out;
875#ifdef TWO_PATH 972#ifdef TWO_PATH
876 tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->e[i+st->frame_size])); 973 tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size]));
877#else 974#else
878 tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->y[i+st->frame_size])); 975 tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size]));
879#endif 976#endif
880 /* Saturation */ 977 tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan])));
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)));
886 /* This is an arbitrary test for saturation in the microphone signal */ 978 /* This is an arbitrary test for saturation in the microphone signal */
887 if (in[i] <= -32000 || in[i] >= 32000) 979 if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000)
888 { 980 {
889 tmp_out = 0;
890 if (st->saturated == 0) 981 if (st->saturated == 0)
891 st->saturated = 1; 982 st->saturated = 1;
983 }
984 out[i*C+chan] = WORD2INT(tmp_out);
985 st->memE[chan] = tmp_out;
892 } 986 }
893 out[i] = (spx_int16_t)tmp_out; 987
894 st->memE = tmp_out;
895 }
896
897#ifdef DUMP_ECHO_CANCEL_DATA 988#ifdef DUMP_ECHO_CANCEL_DATA
898 dump_audio(in, far_end, out, st->frame_size); 989 dump_audio(in, far_end, out, st->frame_size);
899#endif 990#endif
900 991
901 /* Compute error signal (filter update version) */ 992 /* Compute error signal (filter update version) */
902 for (i=0;i<st->frame_size;i++) 993 for (i=0;i<st->frame_size;i++)
903 { 994 {
904 st->e[i+st->frame_size] = st->e[i]; 995 st->e[chan*N+i+st->frame_size] = st->e[chan*N+i];
905 st->e[i] = 0; 996 st->e[chan*N+i] = 0;
997 }
998
999 /* Compute a bunch of correlations */
1000 /* FIXME: bad merge */
1001 Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);
1002 Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);
1003 Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size);
1004
1005 /* Convert error to frequency domain */
1006 spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N);
1007 for (i=0;i<st->frame_size;i++)
1008 st->y[i+chan*N] = 0;
1009 spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N);
1010
1011 /* Compute power spectrum of echo (X), error (E) and filter response (Y) */
1012 power_spectrum_accum(st->E+chan*N, st->Rf, N);
1013 power_spectrum_accum(st->Y+chan*N, st->Yf, N);
1014
906 } 1015 }
907 1016
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
913 /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/ 1017 /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/
914 1018
915 /* Do some sanity check */ 1019 /* Do some sanity check */
916 if (!(Syy>=0 && Sxx>=0 && See >= 0) 1020 if (!(Syy>=0 && Sxx>=0 && See >= 0)
917#ifndef FIXED_POINT 1021#ifndef FIXED_POINT
@@ -921,7 +1025,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
921 { 1025 {
922 /* Things have gone really bad */ 1026 /* Things have gone really bad */
923 st->screwed_up += 50; 1027 st->screwed_up += 50;
924 for (i=0;i<st->frame_size;i++) 1028 for (i=0;i<st->frame_size*C;i++)
925 out[i] = 0; 1029 out[i] = 0;
926 } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6))) 1030 } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6)))
927 { 1031 {
@@ -941,35 +1045,16 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
941 /* Add a small noise floor to make sure not to have problems when dividing */ 1045 /* Add a small noise floor to make sure not to have problems when dividing */
942 See = MAX32(See, SHR32(MULT16_16(N, 100),6)); 1046 See = MAX32(See, SHR32(MULT16_16(N, 100),6));
943 1047
944 /* Convert error to frequency domain */ 1048 for (speak = 0; speak < K; speak++)
945 spx_fft(st->fft_table, st->e, st->E); 1049 {
946 for (i=0;i<st->frame_size;i++) 1050 Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
947 st->y[i] = 0; 1051 power_spectrum_accum(st->X+speak*N, st->Xf, N);
948 spx_fft(st->fft_table, st->y, st->Y); 1052 }
1053
949 1054
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
955 /* Smooth far end energy estimate over time */ 1055 /* Smooth far end energy estimate over time */
956 for (j=0;j<=st->frame_size;j++) 1056 for (j=0;j<=st->frame_size;j++)
957 st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]); 1057 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 }
973 1058
974 /* Compute filtered spectra and (cross-)correlations */ 1059 /* Compute filtered spectra and (cross-)correlations */
975 for (j=st->frame_size;j>=0;j--) 1060 for (j=st->frame_size;j>=0;j--)
@@ -987,7 +1072,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
987 st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j]; 1072 st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j];
988#endif 1073#endif
989 } 1074 }
990 1075
991 Pyy = FLOAT_SQRT(Pyy); 1076 Pyy = FLOAT_SQRT(Pyy);
992 Pey = FLOAT_DIVU(Pey,Pyy); 1077 Pey = FLOAT_DIVU(Pey,Pyy);
993 1078
@@ -1015,7 +1100,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
1015 else 1100 else
1016 st->leak_estimate = SHL16(st->leak_estimate,1); 1101 st->leak_estimate = SHL16(st->leak_estimate,1);
1017 /*printf ("%f\n", st->leak_estimate);*/ 1102 /*printf ("%f\n", st->leak_estimate);*/
1018 1103
1019 /* Compute Residual to Error Ratio */ 1104 /* Compute Residual to Error Ratio */
1020#ifdef FIXED_POINT 1105#ifdef FIXED_POINT
1021 tmp32 = MULT16_32_Q15(st->leak_estimate,Syy); 1106 tmp32 = MULT16_32_Q15(st->leak_estimate,Syy);
@@ -1071,7 +1156,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
1071 /* Temporary adaption rate if filter is not yet adapted enough */ 1156 /* Temporary adaption rate if filter is not yet adapted enough */
1072 spx_word16_t adapt_rate=0; 1157 spx_word16_t adapt_rate=0;
1073 1158
1074 if (Sxx > SHR32(MULT16_16(N, 1000),6)) 1159 if (Sxx > SHR32(MULT16_16(N, 1000),6))
1075 { 1160 {
1076 tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx); 1161 tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx);
1077#ifdef FIXED_POINT 1162#ifdef FIXED_POINT
@@ -1091,13 +1176,13 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
1091 st->sum_adapt = ADD32(st->sum_adapt,adapt_rate); 1176 st->sum_adapt = ADD32(st->sum_adapt,adapt_rate);
1092 } 1177 }
1093 1178
1094 /* Save residual echo so it can be used by the nonlinear processor */ 1179 /* FIXME: MC conversion required */
1180 for (i=0;i<st->frame_size;i++)
1181 st->last_y[i] = st->last_y[st->frame_size+i];
1095 if (st->adapted) 1182 if (st->adapted)
1096 { 1183 {
1097 /* If the filter is adapted, take the filtered echo */ 1184 /* If the filter is adapted, take the filtered echo */
1098 for (i=0;i<st->frame_size;i++) 1185 for (i=0;i<st->frame_size;i++)
1099 st->last_y[i] = st->last_y[st->frame_size+i];
1100 for (i=0;i<st->frame_size;i++)
1101 st->last_y[st->frame_size+i] = in[i]-out[i]; 1186 st->last_y[st->frame_size+i] = in[i]-out[i];
1102 } else { 1187 } else {
1103 /* If filter isn't adapted yet, all we can do is take the far end signal directly */ 1188 /* If filter isn't adapted yet, all we can do is take the far end signal directly */
@@ -1113,17 +1198,17 @@ void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, in
1113 int i; 1198 int i;
1114 spx_word16_t leak2; 1199 spx_word16_t leak2;
1115 int N; 1200 int N;
1116 1201
1117 N = st->window_size; 1202 N = st->window_size;
1118 1203
1119 /* Apply hanning window (should pre-compute it)*/ 1204 /* Apply hanning window (should pre-compute it)*/
1120 for (i=0;i<N;i++) 1205 for (i=0;i<N;i++)
1121 st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]); 1206 st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]);
1122 1207
1123 /* Compute power spectrum of the echo */ 1208 /* Compute power spectrum of the echo */
1124 spx_fft(st->fft_table, st->y, st->Y); 1209 spx_fft(st->fft_table, st->y, st->Y);
1125 power_spectrum(st->Y, residual_echo, N); 1210 power_spectrum(st->Y, residual_echo, N);
1126 1211
1127#ifdef FIXED_POINT 1212#ifdef FIXED_POINT
1128 if (st->leak_estimate > 16383) 1213 if (st->leak_estimate > 16383)
1129 leak2 = 32767; 1214 leak2 = 32767;
@@ -1138,14 +1223,14 @@ void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, in
1138 /* Estimate residual echo */ 1223 /* Estimate residual echo */
1139 for (i=0;i<=st->frame_size;i++) 1224 for (i=0;i<=st->frame_size;i++)
1140 residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]); 1225 residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]);
1141 1226
1142} 1227}
1143 1228
1144int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) 1229EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)
1145{ 1230{
1146 switch(request) 1231 switch(request)
1147 { 1232 {
1148 1233
1149 case SPEEX_ECHO_GET_FRAME_SIZE: 1234 case SPEEX_ECHO_GET_FRAME_SIZE:
1150 (*(int*)ptr) = st->frame_size; 1235 (*(int*)ptr) = st->frame_size;
1151 break; 1236 break;
@@ -1169,6 +1254,29 @@ int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)
1169 case SPEEX_ECHO_GET_SAMPLING_RATE: 1254 case SPEEX_ECHO_GET_SAMPLING_RATE:
1170 (*(int*)ptr) = st->sampling_rate; 1255 (*(int*)ptr) = st->sampling_rate;
1171 break; 1256 break;
1257 case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE:
1258 /*FIXME: Implement this for multiple channels */
1259 *((spx_int32_t *)ptr) = st->M * st->frame_size;
1260 break;
1261 case SPEEX_ECHO_GET_IMPULSE_RESPONSE:
1262 {
1263 int M = st->M, N = st->window_size, n = st->frame_size, i, j;
1264 spx_int32_t *filt = (spx_int32_t *) ptr;
1265 for(j=0;j<M;j++)
1266 {
1267 /*FIXME: Implement this for multiple channels */
1268#ifdef FIXED_POINT
1269 for (i=0;i<N;i++)
1270 st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN));
1271 spx_ifft(st->fft_table, st->wtmp2, st->wtmp);
1272#else
1273 spx_ifft(st->fft_table, &st->W[j*N], st->wtmp);
1274#endif
1275 for(i=0;i<n;i++)
1276 filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN);
1277 }
1278 }
1279 break;
1172 default: 1280 default:
1173 speex_warning_int("Unknown speex_echo_ctl request: ", request); 1281 speex_warning_int("Unknown speex_echo_ctl request: ", request);
1174 return -1; 1282 return -1;
diff --git a/lib/rbcodec/codecs/libspeex/modes.c b/lib/rbcodec/codecs/libspeex/modes.c
index a58c0786dd..881ff91368 100644
--- a/lib/rbcodec/codecs/libspeex/modes.c
+++ b/lib/rbcodec/codecs/libspeex/modes.c
@@ -450,7 +450,7 @@ static const SpeexNBMode nb_mode = {
450 450
451 451
452/* Default mode for narrowband */ 452/* Default mode for narrowband */
453const SpeexMode speex_nb_mode = { 453EXPORT const SpeexMode speex_nb_mode = {
454 &nb_mode, 454 &nb_mode,
455 nb_mode_query, 455 nb_mode_query,
456 "narrowband", 456 "narrowband",
@@ -479,8 +479,12 @@ const SpeexMode speex_nb_mode = {
479 479
480 480
481 481
482int speex_mode_query(const SpeexMode *mode, int request, void *ptr) 482EXPORT int speex_mode_query(const SpeexMode *mode, int request, void *ptr)
483{ 483{
484 return mode->query(mode->mode, request, ptr); 484 return mode->query(mode->mode, request, ptr);
485} 485}
486 486
487#ifdef FIXED_DEBUG
488long long spx_mips=0;
489#endif
490
diff --git a/lib/rbcodec/codecs/libspeex/modes_wb.c b/lib/rbcodec/codecs/libspeex/modes_wb.c
index 5438551c1b..4fe1ef08fc 100644
--- a/lib/rbcodec/codecs/libspeex/modes_wb.c
+++ b/lib/rbcodec/codecs/libspeex/modes_wb.c
@@ -55,9 +55,9 @@
55#endif 55#endif
56 56
57#ifndef ROCKBOX_VOICE_CODEC 57#ifndef ROCKBOX_VOICE_CODEC
58const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode}; 58EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode};
59#else 59#else
60const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, NULL}; 60EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, NULL};
61#endif 61#endif
62 62
63extern const signed char hexc_table[]; 63extern const signed char hexc_table[];
@@ -250,7 +250,7 @@ static const SpeexSBMode sb_wb_mode = {
250}; 250};
251 251
252 252
253const SpeexMode speex_wb_mode = { 253EXPORT const SpeexMode speex_wb_mode = {
254 &sb_wb_mode, 254 &sb_wb_mode,
255 wb_mode_query, 255 wb_mode_query,
256 "wideband (sub-band CELP)", 256 "wideband (sub-band CELP)",
@@ -285,7 +285,7 @@ const SpeexMode speex_wb_mode = {
285 285
286#ifndef ROCKBOX_VOICE_CODEC 286#ifndef ROCKBOX_VOICE_CODEC
287/* Split-band "ultra-wideband" (32 kbps) CELP mode*/ 287/* Split-band "ultra-wideband" (32 kbps) CELP mode*/
288static const SpeexSBMode sb_uwb_mode = { 288EXPORT static const SpeexSBMode sb_uwb_mode = {
289 &speex_wb_mode, 289 &speex_wb_mode,
290 320, /*frameSize*/ 290 320, /*frameSize*/
291 80, /*subframeSize*/ 291 80, /*subframeSize*/
@@ -365,7 +365,7 @@ const SpeexMode speex_uwb_mode = {
365/* We have defined speex_lib_get_mode() as a macro in speex.h */ 365/* We have defined speex_lib_get_mode() as a macro in speex.h */
366#undef speex_lib_get_mode 366#undef speex_lib_get_mode
367 367
368const SpeexMode * speex_lib_get_mode (int mode) 368EXPORT const SpeexMode * speex_lib_get_mode (int mode)
369{ 369{
370 if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL; 370 if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL;
371 371
diff --git a/lib/rbcodec/codecs/libspeex/preprocess.c b/lib/rbcodec/codecs/libspeex/preprocess.c
index 07a2ad3479..58d213a0a9 100644
--- a/lib/rbcodec/codecs/libspeex/preprocess.c
+++ b/lib/rbcodec/codecs/libspeex/preprocess.c
@@ -1,6 +1,6 @@
1/* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin) 1/* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin)
2 Copyright (C) 2004-2006 Epic Games 2 Copyright (C) 2004-2006 Epic Games
3 3
4 File: preprocess.c 4 File: preprocess.c
5 Preprocessor with denoising based on the algorithm by Ephraim and Malah 5 Preprocessor with denoising based on the algorithm by Ephraim and Malah
6 6
@@ -34,24 +34,24 @@
34 34
35/* 35/*
36 Recommended papers: 36 Recommended papers:
37 37
38 Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error 38 Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error
39 short-time spectral amplitude estimator". IEEE Transactions on Acoustics, 39 short-time spectral amplitude estimator". IEEE Transactions on Acoustics,
40 Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984. 40 Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984.
41 41
42 Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error 42 Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error
43 log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and 43 log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and
44 Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985. 44 Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985.
45 45
46 I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments". 46 I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments".
47 Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001. 47 Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001.
48 48
49 Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic 49 Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic
50 approach to combined acoustic echo cancellation and noise reduction". IEEE 50 approach to combined acoustic echo cancellation and noise reduction". IEEE
51 Transactions on Speech and Audio Processing, 2002. 51 Transactions on Speech and Audio Processing, 2002.
52 52
53 J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation 53 J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation
54 of simultaneous non-stationary sources". In Proceedings IEEE International 54 of simultaneous non-stationary sources". In Proceedings IEEE International
55 Conference on Acoustics, Speech, and Signal Processing, 2004. 55 Conference on Acoustics, Speech, and Signal Processing, 2004.
56*/ 56*/
57 57
@@ -75,7 +75,7 @@
75#define LOUDNESS_EXP 5.f 75#define LOUDNESS_EXP 5.f
76#define AMP_SCALE .001f 76#define AMP_SCALE .001f
77#define AMP_SCALE_1 1000.f 77#define AMP_SCALE_1 1000.f
78 78
79#define NB_BANDS 24 79#define NB_BANDS 24
80 80
81#define SPEECH_PROB_START_DEFAULT QCONST16(0.35f,15) 81#define SPEECH_PROB_START_DEFAULT QCONST16(0.35f,15)
@@ -117,7 +117,7 @@ static inline spx_word16_t DIV32_16_Q8(spx_word32_t a, spx_word32_t b)
117 a = SHL32(a,8); 117 a = SHL32(a,8);
118 return PDIV32_16(a,b); 118 return PDIV32_16(a,b);
119 } 119 }
120 120
121} 121}
122static inline spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b) 122static inline spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b)
123{ 123{
@@ -185,7 +185,7 @@ struct SpeexPreprocessState_ {
185 int sampling_rate; /**< Sampling rate of the input/output */ 185 int sampling_rate; /**< Sampling rate of the input/output */
186 int nbands; 186 int nbands;
187 FilterBank *bank; 187 FilterBank *bank;
188 188
189 /* Parameters */ 189 /* Parameters */
190 int denoise_enabled; 190 int denoise_enabled;
191 int vad_enabled; 191 int vad_enabled;
@@ -198,7 +198,9 @@ struct SpeexPreprocessState_ {
198 int echo_suppress; 198 int echo_suppress;
199 int echo_suppress_active; 199 int echo_suppress_active;
200 SpeexEchoState *echo_state; 200 SpeexEchoState *echo_state;
201 201
202 spx_word16_t speech_prob; /**< Probability last frame was speech */
203
202 /* DSP-related arrays */ 204 /* DSP-related arrays */
203 spx_word16_t *frame; /**< Processing frame (2*ps_size) */ 205 spx_word16_t *frame; /**< Processing frame (2*ps_size) */
204 spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */ 206 spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */
@@ -234,7 +236,6 @@ struct SpeexPreprocessState_ {
234 float *loudness_weight; /**< Perceptual loudness curve */ 236 float *loudness_weight; /**< Perceptual loudness curve */
235 float loudness; /**< Loudness estimate */ 237 float loudness; /**< Loudness estimate */
236 float agc_gain; /**< Current AGC gain */ 238 float agc_gain; /**< Current AGC gain */
237 int nb_loudness_adapt; /**< Number of frames used for loudness adaptation so far */
238 float max_gain; /**< Maximum gain allowed */ 239 float max_gain; /**< Maximum gain allowed */
239 float max_increase_step; /**< Maximum increase in gain from one frame to another */ 240 float max_increase_step; /**< Maximum increase in gain from one frame to another */
240 float max_decrease_step; /**< Maximum decrease in gain from one frame to another */ 241 float max_decrease_step; /**< Maximum decrease in gain from one frame to another */
@@ -259,7 +260,7 @@ static void conj_window(spx_word16_t *w, int len)
259 spx_word16_t tmp; 260 spx_word16_t tmp;
260#ifdef FIXED_POINT 261#ifdef FIXED_POINT
261 spx_word16_t x = DIV32_16(MULT16_16(32767,i),len); 262 spx_word16_t x = DIV32_16(MULT16_16(32767,i),len);
262#else 263#else
263 spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len); 264 spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len);
264#endif 265#endif
265 int inv=0; 266 int inv=0;
@@ -284,10 +285,10 @@ static void conj_window(spx_word16_t *w, int len)
284 } 285 }
285} 286}
286 287
287 288
288#ifdef FIXED_POINT 289#ifdef FIXED_POINT
289/* This function approximates the gain function 290/* This function approximates the gain function
290 y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) 291 y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)
291 which multiplied by xi/(1+xi) is the optimal gain 292 which multiplied by xi/(1+xi) is the optimal gain
292 in the loudness domain ( sqrt[amplitude] ) 293 in the loudness domain ( sqrt[amplitude] )
293 Input in Q11 format, output in Q15 294 Input in Q11 format, output in Q15
@@ -320,7 +321,7 @@ static inline spx_word16_t qcurve(spx_word16_t x)
320static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len) 321static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len)
321{ 322{
322 int i; 323 int i;
323 324
324 if (noise_suppress > effective_echo_suppress) 325 if (noise_suppress > effective_echo_suppress)
325 { 326 {
326 spx_word16_t noise_gain, gain_ratio; 327 spx_word16_t noise_gain, gain_ratio;
@@ -346,8 +347,8 @@ static void compute_gain_floor(int noise_suppress, int effective_echo_suppress,
346} 347}
347 348
348#else 349#else
349/* This function approximates the gain function 350/* This function approximates the gain function
350 y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x) 351 y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)
351 which multiplied by xi/(1+xi) is the optimal gain 352 which multiplied by xi/(1+xi) is the optimal gain
352 in the loudness domain ( sqrt[amplitude] ) 353 in the loudness domain ( sqrt[amplitude] )
353*/ 354*/
@@ -391,7 +392,7 @@ static void compute_gain_floor(int noise_suppress, int effective_echo_suppress,
391} 392}
392 393
393#endif 394#endif
394SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate) 395EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate)
395{ 396{
396 int i; 397 int i;
397 int N, N3, N4, M; 398 int N, N3, N4, M;
@@ -413,8 +414,8 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
413 break; 414 break;
414 } 415 }
415 } 416 }
416 417
417 418
418 if (st->ps_size < 3*st->frame_size/4) 419 if (st->ps_size < 3*st->frame_size/4)
419 st->ps_size = st->ps_size * 3 / 2; 420 st->ps_size = st->ps_size * 3 / 2;
420#else 421#else
@@ -424,7 +425,7 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
424 N = st->ps_size; 425 N = st->ps_size;
425 N3 = 2*N - st->frame_size; 426 N3 = 2*N - st->frame_size;
426 N4 = st->frame_size - N3; 427 N4 = st->frame_size - N3;
427 428
428 st->sampling_rate = sampling_rate; 429 st->sampling_rate = sampling_rate;
429 st->denoise_enabled = 1; 430 st->denoise_enabled = 1;
430 st->vad_enabled = 0; 431 st->vad_enabled = 0;
@@ -439,15 +440,15 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
439 st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT; 440 st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT;
440 441
441 st->echo_state = NULL; 442 st->echo_state = NULL;
442 443
443 st->nbands = NB_BANDS; 444 st->nbands = NB_BANDS;
444 M = st->nbands; 445 M = st->nbands;
445 st->bank = filterbank_new(M, sampling_rate, N, 1); 446 st->bank = filterbank_new(M, sampling_rate, N, 1);
446 447
447 st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); 448 st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
448 st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); 449 st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
449 st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t)); 450 st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
450 451
451 st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); 452 st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
452 st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); 453 st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
453 st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t)); 454 st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
@@ -460,19 +461,19 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
460 st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); 461 st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
461 st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); 462 st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
462 st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t)); 463 st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
463 464
464 st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 465 st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
465 st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 466 st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
466 st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); 467 st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
467 st->update_prob = (int*)speex_alloc(N*sizeof(int)); 468 st->update_prob = (int*)speex_alloc(N*sizeof(int));
468 469
469 st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); 470 st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t));
470 st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t)); 471 st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t));
471 472
472 conj_window(st->window, 2*N3); 473 conj_window(st->window, 2*N3);
473 for (i=2*N3;i<2*st->ps_size;i++) 474 for (i=2*N3;i<2*st->ps_size;i++)
474 st->window[i]=Q15_ONE; 475 st->window[i]=Q15_ONE;
475 476
476 if (N4>0) 477 if (N4>0)
477 { 478 {
478 for (i=N3-1;i>=0;i--) 479 for (i=N3-1;i>=0;i--)
@@ -514,7 +515,6 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
514 /*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/ 515 /*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/
515 st->loudness = 1e-15; 516 st->loudness = 1e-15;
516 st->agc_gain = 1; 517 st->agc_gain = 1;
517 st->nb_loudness_adapt = 0;
518 st->max_gain = 30; 518 st->max_gain = 30;
519 st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate); 519 st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate);
520 st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate); 520 st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate);
@@ -530,7 +530,7 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
530 return st; 530 return st;
531} 531}
532 532
533void speex_preprocess_state_destroy(SpeexPreprocessState *st) 533EXPORT void speex_preprocess_state_destroy(SpeexPreprocessState *st)
534{ 534{
535 speex_free(st->frame); 535 speex_free(st->frame);
536 speex_free(st->ft); 536 speex_free(st->ft);
@@ -573,7 +573,7 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
573 float target_gain; 573 float target_gain;
574 float loudness=1.f; 574 float loudness=1.f;
575 float rate; 575 float rate;
576 576
577 for (i=2;i<N;i++) 577 for (i=2;i<N;i++)
578 { 578 {
579 loudness += 2.f*N*st->ps[i]* st->loudness_weight[i]; 579 loudness += 2.f*N*st->ps[i]* st->loudness_weight[i];
@@ -583,7 +583,6 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
583 loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/ 583 loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/
584 if (Pframe>.3f) 584 if (Pframe>.3f)
585 { 585 {
586 st->nb_loudness_adapt++;
587 /*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/ 586 /*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/
588 rate = .03*Pframe*Pframe; 587 rate = .03*Pframe*Pframe;
589 st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP); 588 st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP);
@@ -592,7 +591,7 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
592 st->init_max *= 1.f + .1f*Pframe*Pframe; 591 st->init_max *= 1.f + .1f*Pframe*Pframe;
593 } 592 }
594 /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/ 593 /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/
595 594
596 target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP); 595 target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP);
597 596
598 if ((Pframe>.5 && st->nb_adapt > 20) || target_gain < st->agc_gain) 597 if ((Pframe>.5 && st->nb_adapt > 20) || target_gain < st->agc_gain)
@@ -605,11 +604,11 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
605 target_gain = st->max_gain; 604 target_gain = st->max_gain;
606 if (target_gain > st->init_max) 605 if (target_gain > st->init_max)
607 target_gain = st->init_max; 606 target_gain = st->init_max;
608 607
609 st->agc_gain = target_gain; 608 st->agc_gain = target_gain;
610 } 609 }
611 /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/ 610 /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/
612 611
613 for (i=0;i<2*N;i++) 612 for (i=0;i<2*N;i++)
614 ft[i] *= st->agc_gain; 613 ft[i] *= st->agc_gain;
615 st->prev_loudness = loudness; 614 st->prev_loudness = loudness;
@@ -629,7 +628,7 @@ static void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x)
629 st->frame[i]=st->inbuf[i]; 628 st->frame[i]=st->inbuf[i];
630 for (i=0;i<st->frame_size;i++) 629 for (i=0;i<st->frame_size;i++)
631 st->frame[N3+i]=x[i]; 630 st->frame[N3+i]=x[i];
632 631
633 /* Update inbuf */ 632 /* Update inbuf */
634 for (i=0;i<N3;i++) 633 for (i=0;i<N3;i++)
635 st->inbuf[i]=x[N4+i]; 634 st->inbuf[i]=x[N4+i];
@@ -648,10 +647,10 @@ static void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x)
648 st->frame[i] = SHL16(st->frame[i], st->frame_shift); 647 st->frame[i] = SHL16(st->frame[i], st->frame_shift);
649 } 648 }
650#endif 649#endif
651 650
652 /* Perform FFT */ 651 /* Perform FFT */
653 spx_fft(st->fft_lookup, st->frame, st->ft); 652 spx_fft(st->fft_lookup, st->frame, st->ft);
654 653
655 /* Power spectrum */ 654 /* Power spectrum */
656 ps[0]=MULT16_16(st->ft[0],st->ft[0]); 655 ps[0]=MULT16_16(st->ft[0],st->ft[0]);
657 for (i=1;i<N;i++) 656 for (i=1;i<N;i++)
@@ -669,11 +668,11 @@ static void update_noise_prob(SpeexPreprocessState *st)
669 int N = st->ps_size; 668 int N = st->ps_size;
670 669
671 for (i=1;i<N-1;i++) 670 for (i=1;i<N-1;i++)
672 st->S[i] = MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1]) 671 st->S[i] = MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1])
673 + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]); 672 + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]);
674 st->S[0] = MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]); 673 st->S[0] = MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]);
675 st->S[N-1] = MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]); 674 st->S[N-1] = MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]);
676 675
677 if (st->nb_adapt==1) 676 if (st->nb_adapt==1)
678 { 677 {
679 for (i=0;i<N;i++) 678 for (i=0;i<N;i++)
@@ -700,12 +699,12 @@ static void update_noise_prob(SpeexPreprocessState *st)
700 for (i=0;i<N;i++) 699 for (i=0;i<N;i++)
701 { 700 {
702 st->Smin[i] = MIN32(st->Smin[i], st->S[i]); 701 st->Smin[i] = MIN32(st->Smin[i], st->S[i]);
703 st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]); 702 st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]);
704 } 703 }
705 } 704 }
706 for (i=0;i<N;i++) 705 for (i=0;i<N;i++)
707 { 706 {
708 if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > ADD32(st->Smin[i],EXTEND32(20))) 707 if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > st->Smin[i])
709 st->update_prob[i] = 1; 708 st->update_prob[i] = 1;
710 else 709 else
711 st->update_prob[i] = 0; 710 st->update_prob[i] = 0;
@@ -719,12 +718,12 @@ static void update_noise_prob(SpeexPreprocessState *st)
719 718
720void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len); 719void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len);
721 720
722int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo) 721EXPORT int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo)
723{ 722{
724 return speex_preprocess_run(st, x); 723 return speex_preprocess_run(st, x);
725} 724}
726 725
727int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x) 726EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
728{ 727{
729 int i; 728 int i;
730 int M; 729 int M;
@@ -736,12 +735,12 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
736 spx_word16_t Pframe; 735 spx_word16_t Pframe;
737 spx_word16_t beta, beta_1; 736 spx_word16_t beta, beta_1;
738 spx_word16_t effective_echo_suppress; 737 spx_word16_t effective_echo_suppress;
739 738
740 st->nb_adapt++; 739 st->nb_adapt++;
741 if (st->nb_adapt>20000) 740 if (st->nb_adapt>20000)
742 st->nb_adapt = 20000; 741 st->nb_adapt = 20000;
743 st->min_count++; 742 st->min_count++;
744 743
745 beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt)); 744 beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt));
746 beta_1 = Q15_ONE-beta; 745 beta_1 = Q15_ONE-beta;
747 M = st->nbands; 746 M = st->nbands;
@@ -775,7 +774,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
775 st->update_prob[i] = 0; 774 st->update_prob[i] = 0;
776 } 775 }
777 */ 776 */
778 777
779 /* Update the noise estimate for the frequencies where it can be */ 778 /* Update the noise estimate for the frequencies where it can be */
780 for (i=0;i<N;i++) 779 for (i=0;i<N;i++)
781 { 780 {
@@ -793,17 +792,17 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
793 for (i=0;i<N+M;i++) 792 for (i=0;i<N+M;i++)
794 { 793 {
795 spx_word16_t gamma; 794 spx_word16_t gamma;
796 795
797 /* Total noise estimate including residual echo and reverberation */ 796 /* Total noise estimate including residual echo and reverberation */
798 spx_word32_t tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(st->noise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]); 797 spx_word32_t tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(st->noise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]);
799 798
800 /* A posteriori SNR = ps/noise - 1*/ 799 /* A posteriori SNR = ps/noise - 1*/
801 st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT)); 800 st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT));
802 st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT)); 801 st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT));
803 802
804 /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */ 803 /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */
805 gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise)))); 804 gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise))));
806 805
807 /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */ 806 /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */
808 st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15)); 807 st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15));
809 st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT)); 808 st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT));
@@ -824,13 +823,13 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
824 for (i=N;i<N+M;i++) 823 for (i=N;i<N+M;i++)
825 Zframe = ADD32(Zframe, EXTEND32(st->zeta[i])); 824 Zframe = ADD32(Zframe, EXTEND32(st->zeta[i]));
826 Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands))); 825 Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands)));
827 826
828 effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15)); 827 effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15));
829 828
830 compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M); 829 compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M);
831 830
832 /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale) 831 /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale)
833 Technically this is actually wrong because the EM gaim assumes a slightly different probability 832 Technically this is actually wrong because the EM gaim assumes a slightly different probability
834 distribution */ 833 distribution */
835 for (i=N;i<N+M;i++) 834 for (i=N;i<N+M;i++)
836 { 835 {
@@ -847,7 +846,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
847#ifdef FIXED_POINT 846#ifdef FIXED_POINT
848 spx_word16_t tmp; 847 spx_word16_t tmp;
849#endif 848#endif
850 849
851 prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); 850 prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
852 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); 851 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));
853 852
@@ -872,12 +871,12 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
872 /* Convert the EM gains and speech prob to linear frequency */ 871 /* Convert the EM gains and speech prob to linear frequency */
873 filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); 872 filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
874 filterbank_compute_psd16(st->bank,st->gain+N, st->gain); 873 filterbank_compute_psd16(st->bank,st->gain+N, st->gain);
875 874
876 /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */ 875 /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */
877 if (1) 876 if (1)
878 { 877 {
879 filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor); 878 filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor);
880 879
881 /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */ 880 /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */
882 for (i=0;i<N;i++) 881 for (i=0;i<N;i++)
883 { 882 {
@@ -887,7 +886,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
887 spx_word16_t tmp; 886 spx_word16_t tmp;
888 spx_word16_t p; 887 spx_word16_t p;
889 spx_word16_t g; 888 spx_word16_t g;
890 889
891 /* Wiener filter gain */ 890 /* Wiener filter gain */
892 prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT))); 891 prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
893 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT)); 892 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));
@@ -898,22 +897,22 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
898 g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM))); 897 g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
899 /* Interpolated speech probability of presence */ 898 /* Interpolated speech probability of presence */
900 p = st->gain2[i]; 899 p = st->gain2[i];
901 900
902 /* Constrain the gain to be close to the Bark scale gain */ 901 /* Constrain the gain to be close to the Bark scale gain */
903 if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i]) 902 if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i])
904 g = MULT16_16(3,st->gain[i]); 903 g = MULT16_16(3,st->gain[i]);
905 st->gain[i] = g; 904 st->gain[i] = g;
906 905
907 /* Save old power spectrum */ 906 /* Save old power spectrum */
908 st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]); 907 st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]);
909 908
910 /* Apply gain floor */ 909 /* Apply gain floor */
911 if (st->gain[i] < st->gain_floor[i]) 910 if (st->gain[i] < st->gain_floor[i])
912 st->gain[i] = st->gain_floor[i]; 911 st->gain[i] = st->gain_floor[i];
913 912
914 /* Exponential decay model for reverberation (unused) */ 913 /* Exponential decay model for reverberation (unused) */
915 /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/ 914 /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/
916 915
917 /* Take into account speech probability of presence (loudness domain MMSE estimator) */ 916 /* Take into account speech probability of presence (loudness domain MMSE estimator) */
918 /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */ 917 /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */
919 tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); 918 tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
@@ -927,20 +926,20 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
927 { 926 {
928 spx_word16_t tmp; 927 spx_word16_t tmp;
929 spx_word16_t p = st->gain2[i]; 928 spx_word16_t p = st->gain2[i];
930 st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]); 929 st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]);
931 tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15))); 930 tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
932 st->gain2[i]=SQR16_Q15(tmp); 931 st->gain2[i]=SQR16_Q15(tmp);
933 } 932 }
934 filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2); 933 filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
935 } 934 }
936 935
937 /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */ 936 /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */
938 if (!st->denoise_enabled) 937 if (!st->denoise_enabled)
939 { 938 {
940 for (i=0;i<N+M;i++) 939 for (i=0;i<N+M;i++)
941 st->gain2[i]=Q15_ONE; 940 st->gain2[i]=Q15_ONE;
942 } 941 }
943 942
944 /* Apply computed gain */ 943 /* Apply computed gain */
945 for (i=1;i<N;i++) 944 for (i=1;i<N;i++)
946 { 945 {
@@ -949,7 +948,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
949 } 948 }
950 st->ft[0] = MULT16_16_P15(st->gain2[0],st->ft[0]); 949 st->ft[0] = MULT16_16_P15(st->gain2[0],st->ft[0]);
951 st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]); 950 st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]);
952 951
953 /*FIXME: This *will* not work for fixed-point */ 952 /*FIXME: This *will* not work for fixed-point */
954#ifndef FIXED_POINT 953#ifndef FIXED_POINT
955 if (st->agc_enabled) 954 if (st->agc_enabled)
@@ -978,7 +977,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
978 } 977 }
979 } 978 }
980#endif 979#endif
981 980
982 /* Synthesis window (for WOLA) */ 981 /* Synthesis window (for WOLA) */
983 for (i=0;i<2*N;i++) 982 for (i=0;i<2*N;i++)
984 st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]); 983 st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]);
@@ -988,15 +987,16 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
988 x[i] = st->outbuf[i] + st->frame[i]; 987 x[i] = st->outbuf[i] + st->frame[i];
989 for (i=0;i<N4;i++) 988 for (i=0;i<N4;i++)
990 x[N3+i] = st->frame[N3+i]; 989 x[N3+i] = st->frame[N3+i];
991 990
992 /* Update outbuf */ 991 /* Update outbuf */
993 for (i=0;i<N3;i++) 992 for (i=0;i<N3;i++)
994 st->outbuf[i] = st->frame[st->frame_size+i]; 993 st->outbuf[i] = st->frame[st->frame_size+i];
995 994
996 /* FIXME: This VAD is a kludge */ 995 /* FIXME: This VAD is a kludge */
996 st->speech_prob = Pframe;
997 if (st->vad_enabled) 997 if (st->vad_enabled)
998 { 998 {
999 if (Pframe > st->speech_prob_start || (st->was_speech && Pframe > st->speech_prob_continue)) 999 if (st->speech_prob > st->speech_prob_start || (st->was_speech && st->speech_prob > st->speech_prob_continue))
1000 { 1000 {
1001 st->was_speech=1; 1001 st->was_speech=1;
1002 return 1; 1002 return 1;
@@ -1010,7 +1010,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
1010 } 1010 }
1011} 1011}
1012 1012
1013void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x) 1013EXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
1014{ 1014{
1015 int i; 1015 int i;
1016 int N = st->ps_size; 1016 int N = st->ps_size;
@@ -1020,11 +1020,11 @@ void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
1020 1020
1021 M = st->nbands; 1021 M = st->nbands;
1022 st->min_count++; 1022 st->min_count++;
1023 1023
1024 preprocess_analysis(st, x); 1024 preprocess_analysis(st, x);
1025 1025
1026 update_noise_prob(st); 1026 update_noise_prob(st);
1027 1027
1028 for (i=1;i<N-1;i++) 1028 for (i=1;i<N-1;i++)
1029 { 1029 {
1030 if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT)) 1030 if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT))
@@ -1045,7 +1045,7 @@ void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
1045} 1045}
1046 1046
1047 1047
1048int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr) 1048EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
1049{ 1049{
1050 int i; 1050 int i;
1051 SpeexPreprocessState *st; 1051 SpeexPreprocessState *st;
@@ -1103,7 +1103,7 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
1103 case SPEEX_PREPROCESS_GET_VAD: 1103 case SPEEX_PREPROCESS_GET_VAD:
1104 (*(spx_int32_t*)ptr) = st->vad_enabled; 1104 (*(spx_int32_t*)ptr) = st->vad_enabled;
1105 break; 1105 break;
1106 1106
1107 case SPEEX_PREPROCESS_SET_DEREVERB: 1107 case SPEEX_PREPROCESS_SET_DEREVERB:
1108 st->dereverb_enabled = (*(spx_int32_t*)ptr); 1108 st->dereverb_enabled = (*(spx_int32_t*)ptr);
1109 for (i=0;i<st->ps_size;i++) 1109 for (i=0;i<st->ps_size;i++)
@@ -1121,7 +1121,7 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
1121 /* FIXME: Re-enable when de-reverberation is actually enabled again */ 1121 /* FIXME: Re-enable when de-reverberation is actually enabled again */
1122 /*(*(float*)ptr) = st->reverb_level;*/ 1122 /*(*(float*)ptr) = st->reverb_level;*/
1123 break; 1123 break;
1124 1124
1125 case SPEEX_PREPROCESS_SET_DEREVERB_DECAY: 1125 case SPEEX_PREPROCESS_SET_DEREVERB_DECAY:
1126 /* FIXME: Re-enable when de-reverberation is actually enabled again */ 1126 /* FIXME: Re-enable when de-reverberation is actually enabled again */
1127 /*st->reverb_decay = (*(float*)ptr);*/ 1127 /*st->reverb_decay = (*(float*)ptr);*/
@@ -1169,17 +1169,51 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
1169 st->echo_state = (SpeexEchoState*)ptr; 1169 st->echo_state = (SpeexEchoState*)ptr;
1170 break; 1170 break;
1171 case SPEEX_PREPROCESS_GET_ECHO_STATE: 1171 case SPEEX_PREPROCESS_GET_ECHO_STATE:
1172 ptr = (void*)st->echo_state; 1172 (*(SpeexEchoState**)ptr) = (SpeexEchoState*)st->echo_state;
1173 break; 1173 break;
1174#ifndef FIXED_POINT 1174#ifndef FIXED_POINT
1175 case SPEEX_PREPROCESS_GET_AGC_LOUDNESS: 1175 case SPEEX_PREPROCESS_GET_AGC_LOUDNESS:
1176 (*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP); 1176 (*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP);
1177 break; 1177 break;
1178 case SPEEX_PREPROCESS_GET_AGC_GAIN:
1179 (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->agc_gain));
1180 break;
1181#endif
1182 case SPEEX_PREPROCESS_GET_PSD_SIZE:
1183 case SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE:
1184 (*(spx_int32_t*)ptr) = st->ps_size;
1185 break;
1186 case SPEEX_PREPROCESS_GET_PSD:
1187 for(i=0;i<st->ps_size;i++)
1188 ((spx_int32_t *)ptr)[i] = (spx_int32_t) st->ps[i];
1189 break;
1190 case SPEEX_PREPROCESS_GET_NOISE_PSD:
1191 for(i=0;i<st->ps_size;i++)
1192 ((spx_int32_t *)ptr)[i] = (spx_int32_t) PSHR32(st->noise[i], NOISE_SHIFT);
1193 break;
1194 case SPEEX_PREPROCESS_GET_PROB:
1195 (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob, 100);
1196 break;
1197#ifndef FIXED_POINT
1198 case SPEEX_PREPROCESS_SET_AGC_TARGET:
1199 st->agc_level = (*(spx_int32_t*)ptr);
1200 if (st->agc_level<1)
1201 st->agc_level=1;
1202 if (st->agc_level>32768)
1203 st->agc_level=32768;
1204 break;
1205 case SPEEX_PREPROCESS_GET_AGC_TARGET:
1206 (*(spx_int32_t*)ptr) = st->agc_level;
1207 break;
1178#endif 1208#endif
1179
1180 default: 1209 default:
1181 speex_warning_int("Unknown speex_preprocess_ctl request: ", request); 1210 speex_warning_int("Unknown speex_preprocess_ctl request: ", request);
1182 return -1; 1211 return -1;
1183 } 1212 }
1184 return 0; 1213 return 0;
1185} 1214}
1215
1216#ifdef FIXED_DEBUG
1217long long spx_mips=0;
1218#endif
1219
diff --git a/lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h b/lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h
index 917047bb56..087b466b75 100644
--- a/lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h
+++ b/lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h
@@ -55,9 +55,9 @@ static int lsp_quant(
55 55
56 __asm__ __volatile__ 56 __asm__ __volatile__
57 ( 57 (
58" %0 = 1 (X);\n\t" /* %0: best_dist */ 58" %0 = 1 (X);\n\t" /* %0: best_dist */
59" %0 <<= 30;\n\t" 59" %0 <<= 30;\n\t"
60" %1 = 0 (X);\n\t" /* %1: best_i */ 60" %1 = 0 (X);\n\t" /* %1: best_i */
61" P2 = %3\n\t" /* P2: ptr to cdbk */ 61" P2 = %3\n\t" /* P2: ptr to cdbk */
62" R5 = 0;\n\t" /* R5: best cb entry */ 62" R5 = 0;\n\t" /* R5: best cb entry */
63 63
@@ -68,19 +68,19 @@ static int lsp_quant(
68" B0 = %2;\n\t" 68" B0 = %2;\n\t"
69 69
70" R2.L = W [I0++];\n\t" 70" R2.L = W [I0++];\n\t"
71" LSETUP (lq1, lq2) LC0 = %4;\n\t" 71" LSETUP (1f, 2f) LC0 = %4;\n\t"
72"lq1: R3 = 0;\n\t" /* R3: dist */ 72"1: R3 = 0;\n\t" /* R3: dist */
73" LSETUP (lq3, lq4) LC1 = %5;\n\t" 73" LSETUP (3f, 4f) LC1 = %5;\n\t"
74"lq3: R1 = B [P2++] (X);\n\t" 74"3: R1 = B [P2++] (X);\n\t"
75" R1 <<= 5;\n\t" 75" R1 <<= 5;\n\t"
76" R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t" 76" R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t"
77" R0 = R0.L*R0.L;\n\t" 77" R0 = R0.L*R0.L;\n\t"
78"lq4: R3 = R3 + R0;\n\t" 78"4: R3 = R3 + R0;\n\t"
79 79
80" cc =R3<%0;\n\t" 80" cc =R3<%0;\n\t"
81" if cc %0=R3;\n\t" 81" if cc %0=R3;\n\t"
82" if cc %1=R5;\n\t" 82" if cc %1=R5;\n\t"
83"lq2: R5 += 1;\n\t" 83"2: R5 += 1;\n\t"
84" L0 = 0;\n\t" 84" L0 = 0;\n\t"
85 : "=&d" (best_dist), "=&d" (best_id) 85 : "=&d" (best_dist), "=&d" (best_id)
86 : "a" (x), "b" (cdbk), "a" (nbVec), "a" (nbDim) 86 : "a" (x), "b" (cdbk), "a" (nbVec), "a" (nbDim)
@@ -117,9 +117,9 @@ static int lsp_weight_quant(
117 117
118 __asm__ __volatile__ 118 __asm__ __volatile__
119 ( 119 (
120" %0 = 1 (X);\n\t" /* %0: best_dist */ 120" %0 = 1 (X);\n\t" /* %0: best_dist */
121" %0 <<= 30;\n\t" 121" %0 <<= 30;\n\t"
122" %1 = 0 (X);\n\t" /* %1: best_i */ 122" %1 = 0 (X);\n\t" /* %1: best_i */
123" P2 = %4\n\t" /* P2: ptr to cdbk */ 123" P2 = %4\n\t" /* P2: ptr to cdbk */
124" R5 = 0;\n\t" /* R5: best cb entry */ 124" R5 = 0;\n\t" /* R5: best cb entry */
125 125
@@ -128,27 +128,27 @@ static int lsp_weight_quant(
128" L0 = R0;\n\t" 128" L0 = R0;\n\t"
129" L1 = R0;\n\t" 129" L1 = R0;\n\t"
130" I0 = %2;\n\t" /* %2: &x[0] */ 130" I0 = %2;\n\t" /* %2: &x[0] */
131" I1 = %3;\n\t" /* %3: &weight[0] */ 131" I1 = %3;\n\t" /* %3: &weight[0] */
132" B0 = %2;\n\t" 132" B0 = %2;\n\t"
133" B1 = %3;\n\t" 133" B1 = %3;\n\t"
134 134
135" LSETUP (lwq1, lwq2) LC0 = %5;\n\t" 135" LSETUP (1f, 2f) LC0 = %5;\n\t"
136"lwq1: R3 = 0 (X);\n\t" /* R3: dist */ 136"1: R3 = 0 (X);\n\t" /* R3: dist */
137" LSETUP (lwq3, lwq4) LC1 = %6;\n\t" 137" LSETUP (3f, 4f) LC1 = %6;\n\t"
138"lwq3: R0.L = W [I0++] || R2.L = W [I1++];\n\t" 138"3: R0.L = W [I0++] || R2.L = W [I1++];\n\t"
139" R1 = B [P2++] (X);\n\t" 139" R1 = B [P2++] (X);\n\t"
140" R1 <<= 5;\n\t" 140" R1 <<= 5;\n\t"
141" R0.L = R0.L - R1.L;\n\t" 141" R0.L = R0.L - R1.L;\n\t"
142" R0 = R0.L*R0.L;\n\t" 142" R0 = R0.L*R0.L;\n\t"
143" A1 = R2.L*R0.L (M,IS);\n\t" 143" A1 = R2.L*R0.L (M,IS);\n\t"
144" A1 = A1 >>> 16;\n\t" 144" A1 = A1 >>> 16;\n\t"
145" R1 = (A1 += R2.L*R0.H) (IS);\n\t" 145" R1 = (A1 += R2.L*R0.H) (IS);\n\t"
146"lwq4: R3 = R3 + R1;\n\t" 146"4: R3 = R3 + R1;\n\t"
147 147
148" cc =R3<%0;\n\t" 148" cc =R3<%0;\n\t"
149" if cc %0=R3;\n\t" 149" if cc %0=R3;\n\t"
150" if cc %1=R5;\n\t" 150" if cc %1=R5;\n\t"
151"lwq2: R5 += 1;\n\t" 151"2: R5 += 1;\n\t"
152" L0 = 0;\n\t" 152" L0 = 0;\n\t"
153" L1 = 0;\n\t" 153" L1 = 0;\n\t"
154 : "=&d" (best_dist), "=&d" (best_id) 154 : "=&d" (best_dist), "=&d" (best_id)
diff --git a/lib/rbcodec/codecs/libspeex/resample.c b/lib/rbcodec/codecs/libspeex/resample.c
index 65dfef28a3..5f5b9c6b4d 100644
--- a/lib/rbcodec/codecs/libspeex/resample.c
+++ b/lib/rbcodec/codecs/libspeex/resample.c
@@ -1,5 +1,6 @@
1/* Copyright (C) 2007 Jean-Marc Valin 1/* Copyright (C) 2007-2008 Jean-Marc Valin
2 2 Copyright (C) 2008 Thorvald Natvig
3
3 File: resample.c 4 File: resample.c
4 Arbitrary resampling code 5 Arbitrary resampling code
5 6
@@ -37,27 +38,27 @@
37 - Low memory requirement 38 - Low memory requirement
38 - Good *perceptual* quality (and not best SNR) 39 - Good *perceptual* quality (and not best SNR)
39 40
40 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
41 all the major bugs and I don't expect the API to change anymore, there 42 all the major bugs and I don't expect the API to change anymore, there
42 may be something I've missed. So use with caution. 43 may be something I've missed. So use with caution.
43 44
44 This algorithm is based on this original resampling algorithm: 45 This algorithm is based on this original resampling algorithm:
45 Smith, Julius O. Digital Audio Resampling Home Page 46 Smith, Julius O. Digital Audio Resampling Home Page
46 Center for Computer Research in Music and Acoustics (CCRMA), 47 Center for Computer Research in Music and Acoustics (CCRMA),
47 Stanford University, 2007. 48 Stanford University, 2007.
48 Web published at http://www-ccrma.stanford.edu/~jos/resample/. 49 Web published at http://www-ccrma.stanford.edu/~jos/resample/.
49 50
50 There is one main difference, though. This resampler uses cubic 51 There is one main difference, though. This resampler uses cubic
51 interpolation instead of linear interpolation in the above paper. This 52 interpolation instead of linear interpolation in the above paper. This
52 makes the table much smaller and makes it possible to compute that table 53 makes the table much smaller and makes it possible to compute that table
53 on a per-stream basis. In turn, being able to tweak the table for each 54 on a per-stream basis. In turn, being able to tweak the table for each
54 stream makes it possible to both reduce complexity on simple ratios 55 stream makes it possible to both reduce complexity on simple ratios
55 (e.g. 2/3), and get rid of the rounding operations in the inner loop. 56 (e.g. 2/3), and get rid of the rounding operations in the inner loop.
56 The latter both reduces CPU time and makes the algorithm more SIMD-friendly. 57 The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
57*/ 58*/
58 59
59#ifdef HAVE_CONFIG_H 60#ifdef HAVE_CONFIG_H
60#include "config-speex.h" 61#include "config.h"
61#endif 62#endif
62 63
63#ifdef OUTSIDE_SPEEX 64#ifdef OUTSIDE_SPEEX
@@ -68,12 +69,13 @@ static void speex_free (void *ptr) {free(ptr);}
68#include "speex_resampler.h" 69#include "speex_resampler.h"
69#include "arch.h" 70#include "arch.h"
70#else /* OUTSIDE_SPEEX */ 71#else /* OUTSIDE_SPEEX */
71 72
72#include "speex/speex_resampler.h" 73#include "speex/speex_resampler.h"
73#include "arch.h" 74#include "arch.h"
74#include "os_support.h" 75#include "os_support.h"
75#endif /* OUTSIDE_SPEEX */ 76#endif /* OUTSIDE_SPEEX */
76 77
78#include "stack_alloc.h"
77#include <math.h> 79#include <math.h>
78 80
79#ifndef M_PI 81#ifndef M_PI
@@ -81,14 +83,10 @@ static void speex_free (void *ptr) {free(ptr);}
81#endif 83#endif
82 84
83#ifdef FIXED_POINT 85#ifdef FIXED_POINT
84#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) 86#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
85#else 87#else
86#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) 88#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
87#endif 89#endif
88
89/*#define float double*/
90#define FILTER_SIZE 64
91#define OVERSAMPLE 8
92 90
93#define IMAX(a,b) ((a) > (b) ? (a) : (b)) 91#define IMAX(a,b) ((a) > (b) ? (a) : (b))
94#define IMIN(a,b) ((a) < (b) ? (a) : (b)) 92#define IMIN(a,b) ((a) < (b) ? (a) : (b))
@@ -97,6 +95,17 @@ static void speex_free (void *ptr) {free(ptr);}
97#define NULL 0 95#define NULL 0
98#endif 96#endif
99 97
98#ifdef _USE_SSE
99#include "resample_sse.h"
100#endif
101
102/* Numer of elements to allocate on the stack */
103#ifdef VAR_ARRAYS
104#define FIXED_STACK_ALLOC 8192
105#else
106#define FIXED_STACK_ALLOC 1024
107#endif
108
100typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); 109typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
101 110
102struct SpeexResamplerState_ { 111struct SpeexResamplerState_ {
@@ -104,28 +113,29 @@ struct SpeexResamplerState_ {
104 spx_uint32_t out_rate; 113 spx_uint32_t out_rate;
105 spx_uint32_t num_rate; 114 spx_uint32_t num_rate;
106 spx_uint32_t den_rate; 115 spx_uint32_t den_rate;
107 116
108 int quality; 117 int quality;
109 spx_uint32_t nb_channels; 118 spx_uint32_t nb_channels;
110 spx_uint32_t filt_len; 119 spx_uint32_t filt_len;
111 spx_uint32_t mem_alloc_size; 120 spx_uint32_t mem_alloc_size;
121 spx_uint32_t buffer_size;
112 int int_advance; 122 int int_advance;
113 int frac_advance; 123 int frac_advance;
114 float cutoff; 124 float cutoff;
115 spx_uint32_t oversample; 125 spx_uint32_t oversample;
116 int initialised; 126 int initialised;
117 int started; 127 int started;
118 128
119 /* These are per-channel */ 129 /* These are per-channel */
120 spx_int32_t *last_sample; 130 spx_int32_t *last_sample;
121 spx_uint32_t *samp_frac_num; 131 spx_uint32_t *samp_frac_num;
122 spx_uint32_t *magic_samples; 132 spx_uint32_t *magic_samples;
123 133
124 spx_word16_t *mem; 134 spx_word16_t *mem;
125 spx_word16_t *sinc_table; 135 spx_word16_t *sinc_table;
126 spx_uint32_t sinc_table_length; 136 spx_uint32_t sinc_table_length;
127 resampler_basic_func resampler_ptr; 137 resampler_basic_func resampler_ptr;
128 138
129 int in_stride; 139 int in_stride;
130 int out_stride; 140 int out_stride;
131} ; 141} ;
@@ -167,7 +177,7 @@ static double kaiser8_table[36] = {
167 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, 177 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
168 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, 178 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
169 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; 179 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
170 180
171static double kaiser6_table[36] = { 181static double kaiser6_table[36] = {
172 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 182 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
173 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, 183 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
@@ -180,7 +190,7 @@ struct FuncDef {
180 double *table; 190 double *table;
181 int oversample; 191 int oversample;
182}; 192};
183 193
184static struct FuncDef _KAISER12 = {kaiser12_table, 64}; 194static struct FuncDef _KAISER12 = {kaiser12_table, 64};
185#define KAISER12 (&_KAISER12) 195#define KAISER12 (&_KAISER12)
186/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; 196/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
@@ -202,7 +212,7 @@ struct QualityMapping {
202 212
203 213
204/* This table maps conversion quality to internal parameters. There are two 214/* This table maps conversion quality to internal parameters. There are two
205 reasons that explain why the up-sampling bandwidth is larger than the 215 reasons that explain why the up-sampling bandwidth is larger than the
206 down-sampling bandwidth: 216 down-sampling bandwidth:
207 1) When up-sampling, we can assume that the spectrum is already attenuated 217 1) When up-sampling, we can assume that the spectrum is already attenuated
208 close to the Nyquist rate (from an A/D or a previous resampling filter) 218 close to the Nyquist rate (from an A/D or a previous resampling filter)
@@ -228,7 +238,7 @@ static double compute_func(float x, struct FuncDef *func)
228{ 238{
229 float y, frac; 239 float y, frac;
230 double interp[4]; 240 double interp[4];
231 int ind; 241 int ind;
232 y = x*func->oversample; 242 y = x*func->oversample;
233 ind = (int)floor(y); 243 ind = (int)floor(y);
234 frac = (y-ind); 244 frac = (y-ind);
@@ -239,7 +249,7 @@ static double compute_func(float x, struct FuncDef *func)
239 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); 249 interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
240 /* Just to make sure we don't have rounding problems */ 250 /* Just to make sure we don't have rounding problems */
241 interp[1] = 1.f-interp[3]-interp[2]-interp[0]; 251 interp[1] = 1.f-interp[3]-interp[2]-interp[0];
242 252
243 /*sum = frac*accum[1] + (1-frac)*accum[2];*/ 253 /*sum = frac*accum[1] + (1-frac)*accum[2];*/
244 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; 254 return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
245} 255}
@@ -317,47 +327,47 @@ static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
317 327
318static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 328static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
319{ 329{
320 int N = st->filt_len; 330 const int N = st->filt_len;
321 int out_sample = 0; 331 int out_sample = 0;
322 spx_word16_t *mem;
323 int last_sample = st->last_sample[channel_index]; 332 int last_sample = st->last_sample[channel_index];
324 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 333 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
325 mem = st->mem + channel_index * st->mem_alloc_size; 334 const spx_word16_t *sinc_table = st->sinc_table;
335 const int out_stride = st->out_stride;
336 const int int_advance = st->int_advance;
337 const int frac_advance = st->frac_advance;
338 const spx_uint32_t den_rate = st->den_rate;
339 spx_word32_t sum;
340 int j;
341
326 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 342 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
327 { 343 {
328 int j; 344 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
329 spx_word32_t sum=0; 345 const spx_word16_t *iptr = & in[last_sample];
330 346
331 /* We already have all the filter coefficients pre-computed in the table */ 347#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
332 const spx_word16_t *ptr; 348 float accum[4] = {0,0,0,0};
333 /* Do the memory part */ 349
334 for (j=0;last_sample-N+1+j < 0;j++) 350 for(j=0;j<N;j+=4) {
335 { 351 accum[0] += sinc[j]*iptr[j];
336 sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]); 352 accum[1] += sinc[j+1]*iptr[j+1];
337 } 353 accum[2] += sinc[j+2]*iptr[j+2];
338 354 accum[3] += sinc[j+3]*iptr[j+3];
339 /* Do the new part */
340 if (in != NULL)
341 {
342 ptr = in+st->in_stride*(last_sample-N+1+j);
343 for (;j<N;j++)
344 {
345 sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
346 ptr += st->in_stride;
347 }
348 } 355 }
349 356 sum = accum[0] + accum[1] + accum[2] + accum[3];
350 *out = PSHR32(sum,15); 357#else
351 out += st->out_stride; 358 sum = inner_product_single(sinc, iptr, N);
352 out_sample++; 359#endif
353 last_sample += st->int_advance; 360
354 samp_frac_num += st->frac_advance; 361 out[out_stride * out_sample++] = PSHR32(sum, 15);
355 if (samp_frac_num >= st->den_rate) 362 last_sample += int_advance;
363 samp_frac_num += frac_advance;
364 if (samp_frac_num >= den_rate)
356 { 365 {
357 samp_frac_num -= st->den_rate; 366 samp_frac_num -= den_rate;
358 last_sample++; 367 last_sample++;
359 } 368 }
360 } 369 }
370
361 st->last_sample[channel_index] = last_sample; 371 st->last_sample[channel_index] = last_sample;
362 st->samp_frac_num[channel_index] = samp_frac_num; 372 st->samp_frac_num[channel_index] = samp_frac_num;
363 return out_sample; 373 return out_sample;
@@ -368,47 +378,47 @@ static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t c
368/* This is the same as the previous function, except with a double-precision accumulator */ 378/* This is the same as the previous function, except with a double-precision accumulator */
369static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 379static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
370{ 380{
371 int N = st->filt_len; 381 const int N = st->filt_len;
372 int out_sample = 0; 382 int out_sample = 0;
373 spx_word16_t *mem;
374 int last_sample = st->last_sample[channel_index]; 383 int last_sample = st->last_sample[channel_index];
375 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 384 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
376 mem = st->mem + channel_index * st->mem_alloc_size; 385 const spx_word16_t *sinc_table = st->sinc_table;
386 const int out_stride = st->out_stride;
387 const int int_advance = st->int_advance;
388 const int frac_advance = st->frac_advance;
389 const spx_uint32_t den_rate = st->den_rate;
390 double sum;
391 int j;
392
377 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 393 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
378 { 394 {
379 int j; 395 const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
380 double sum=0; 396 const spx_word16_t *iptr = & in[last_sample];
381 397
382 /* We already have all the filter coefficients pre-computed in the table */ 398#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
383 const spx_word16_t *ptr; 399 double accum[4] = {0,0,0,0};
384 /* Do the memory part */ 400
385 for (j=0;last_sample-N+1+j < 0;j++) 401 for(j=0;j<N;j+=4) {
386 { 402 accum[0] += sinc[j]*iptr[j];
387 sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]); 403 accum[1] += sinc[j+1]*iptr[j+1];
388 } 404 accum[2] += sinc[j+2]*iptr[j+2];
389 405 accum[3] += sinc[j+3]*iptr[j+3];
390 /* Do the new part */
391 if (in != NULL)
392 {
393 ptr = in+st->in_stride*(last_sample-N+1+j);
394 for (;j<N;j++)
395 {
396 sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
397 ptr += st->in_stride;
398 }
399 } 406 }
400 407 sum = accum[0] + accum[1] + accum[2] + accum[3];
401 *out = sum; 408#else
402 out += st->out_stride; 409 sum = inner_product_double(sinc, iptr, N);
403 out_sample++; 410#endif
404 last_sample += st->int_advance; 411
405 samp_frac_num += st->frac_advance; 412 out[out_stride * out_sample++] = PSHR32(sum, 15);
406 if (samp_frac_num >= st->den_rate) 413 last_sample += int_advance;
414 samp_frac_num += frac_advance;
415 if (samp_frac_num >= den_rate)
407 { 416 {
408 samp_frac_num -= st->den_rate; 417 samp_frac_num -= den_rate;
409 last_sample++; 418 last_sample++;
410 } 419 }
411 } 420 }
421
412 st->last_sample[channel_index] = last_sample; 422 st->last_sample[channel_index] = last_sample;
413 st->samp_frac_num[channel_index] = samp_frac_num; 423 st->samp_frac_num[channel_index] = samp_frac_num;
414 return out_sample; 424 return out_sample;
@@ -417,69 +427,58 @@ static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t c
417 427
418static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 428static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
419{ 429{
420 int N = st->filt_len; 430 const int N = st->filt_len;
421 int out_sample = 0; 431 int out_sample = 0;
422 spx_word16_t *mem;
423 int last_sample = st->last_sample[channel_index]; 432 int last_sample = st->last_sample[channel_index];
424 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 433 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
425 mem = st->mem + channel_index * st->mem_alloc_size; 434 const int out_stride = st->out_stride;
435 const int int_advance = st->int_advance;
436 const int frac_advance = st->frac_advance;
437 const spx_uint32_t den_rate = st->den_rate;
438 int j;
439 spx_word32_t sum;
440
426 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 441 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
427 { 442 {
428 int j; 443 const spx_word16_t *iptr = & in[last_sample];
429 spx_word32_t sum=0; 444
430 445 const int offset = samp_frac_num*st->oversample/st->den_rate;
431 /* We need to interpolate the sinc filter */
432 spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
433 spx_word16_t interp[4];
434 const spx_word16_t *ptr;
435 int offset;
436 spx_word16_t frac;
437 offset = samp_frac_num*st->oversample/st->den_rate;
438#ifdef FIXED_POINT 446#ifdef FIXED_POINT
439 frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); 447 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
440#else 448#else
441 frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; 449 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
442#endif 450#endif
443 /* This code is written like this to make it easy to optimise with SIMD. 451 spx_word16_t interp[4];
444 For most DSPs, it would be best to split the loops in two because most DSPs 452
445 have only two accumulators */ 453
446 for (j=0;last_sample-N+1+j < 0;j++) 454#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
447 { 455 spx_word32_t accum[4] = {0,0,0,0};
448 spx_word16_t curr_mem = mem[last_sample+j]; 456
449 accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 457 for(j=0;j<N;j++) {
450 accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 458 const spx_word16_t curr_in=iptr[j];
451 accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); 459 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
452 accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 460 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
453 } 461 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
454 462 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
455 if (in != NULL)
456 {
457 ptr = in+st->in_stride*(last_sample-N+1+j);
458 /* Do the new part */
459 for (;j<N;j++)
460 {
461 spx_word16_t curr_in = *ptr;
462 ptr += st->in_stride;
463 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
464 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
465 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
466 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
467 }
468 } 463 }
464
469 cubic_coef(frac, interp); 465 cubic_coef(frac, interp);
470 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]); 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]);
471 467#else
472 *out = PSHR32(sum,15); 468 cubic_coef(frac, interp);
473 out += st->out_stride; 469 sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
474 out_sample++; 470#endif
475 last_sample += st->int_advance; 471
476 samp_frac_num += st->frac_advance; 472 out[out_stride * out_sample++] = PSHR32(sum,15);
477 if (samp_frac_num >= st->den_rate) 473 last_sample += int_advance;
474 samp_frac_num += frac_advance;
475 if (samp_frac_num >= den_rate)
478 { 476 {
479 samp_frac_num -= st->den_rate; 477 samp_frac_num -= den_rate;
480 last_sample++; 478 last_sample++;
481 } 479 }
482 } 480 }
481
483 st->last_sample[channel_index] = last_sample; 482 st->last_sample[channel_index] = last_sample;
484 st->samp_frac_num[channel_index] = samp_frac_num; 483 st->samp_frac_num[channel_index] = samp_frac_num;
485 return out_sample; 484 return out_sample;
@@ -490,63 +489,58 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
490/* This is the same as the previous function, except with a double-precision accumulator */ 489/* This is the same as the previous function, except with a double-precision accumulator */
491static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) 490static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
492{ 491{
493 int N = st->filt_len; 492 const int N = st->filt_len;
494 int out_sample = 0; 493 int out_sample = 0;
495 spx_word16_t *mem;
496 int last_sample = st->last_sample[channel_index]; 494 int last_sample = st->last_sample[channel_index];
497 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; 495 spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
498 mem = st->mem + channel_index * st->mem_alloc_size; 496 const int out_stride = st->out_stride;
497 const int int_advance = st->int_advance;
498 const int frac_advance = st->frac_advance;
499 const spx_uint32_t den_rate = st->den_rate;
500 int j;
501 spx_word32_t sum;
502
499 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) 503 while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
500 { 504 {
501 int j; 505 const spx_word16_t *iptr = & in[last_sample];
502 spx_word32_t sum=0; 506
503 507 const int offset = samp_frac_num*st->oversample/st->den_rate;
504 /* We need to interpolate the sinc filter */ 508#ifdef FIXED_POINT
505 double accum[4] = {0.f,0.f, 0.f, 0.f}; 509 const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
506 float interp[4]; 510#else
507 const spx_word16_t *ptr; 511 const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
508 float alpha = ((float)samp_frac_num)/st->den_rate; 512#endif
509 int offset = samp_frac_num*st->oversample/st->den_rate; 513 spx_word16_t interp[4];
510 float frac = alpha*st->oversample - offset; 514
511 /* This code is written like this to make it easy to optimise with SIMD. 515
512 For most DSPs, it would be best to split the loops in two because most DSPs 516#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
513 have only two accumulators */ 517 double accum[4] = {0,0,0,0};
514 for (j=0;last_sample-N+1+j < 0;j++) 518
515 { 519 for(j=0;j<N;j++) {
516 double curr_mem = mem[last_sample+j]; 520 const double curr_in=iptr[j];
517 accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); 521 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
518 accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); 522 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
519 accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); 523 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
520 accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); 524 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
521 }
522 if (in != NULL)
523 {
524 ptr = in+st->in_stride*(last_sample-N+1+j);
525 /* Do the new part */
526 for (;j<N;j++)
527 {
528 double curr_in = *ptr;
529 ptr += st->in_stride;
530 accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
531 accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
532 accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
533 accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
534 }
535 } 525 }
526
536 cubic_coef(frac, interp); 527 cubic_coef(frac, interp);
537 sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3]; 528 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]);
538 529#else
539 *out = PSHR32(sum,15); 530 cubic_coef(frac, interp);
540 out += st->out_stride; 531 sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
541 out_sample++; 532#endif
542 last_sample += st->int_advance; 533
543 samp_frac_num += st->frac_advance; 534 out[out_stride * out_sample++] = PSHR32(sum,15);
544 if (samp_frac_num >= st->den_rate) 535 last_sample += int_advance;
536 samp_frac_num += frac_advance;
537 if (samp_frac_num >= den_rate)
545 { 538 {
546 samp_frac_num -= st->den_rate; 539 samp_frac_num -= den_rate;
547 last_sample++; 540 last_sample++;
548 } 541 }
549 } 542 }
543
550 st->last_sample[channel_index] = last_sample; 544 st->last_sample[channel_index] = last_sample;
551 st->samp_frac_num[channel_index] = samp_frac_num; 545 st->samp_frac_num[channel_index] = samp_frac_num;
552 return out_sample; 546 return out_sample;
@@ -556,11 +550,11 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3
556static void update_filter(SpeexResamplerState *st) 550static void update_filter(SpeexResamplerState *st)
557{ 551{
558 spx_uint32_t old_length; 552 spx_uint32_t old_length;
559 553
560 old_length = st->filt_len; 554 old_length = st->filt_len;
561 st->oversample = quality_map[st->quality].oversample; 555 st->oversample = quality_map[st->quality].oversample;
562 st->filt_len = quality_map[st->quality].base_length; 556 st->filt_len = quality_map[st->quality].base_length;
563 557
564 if (st->num_rate > st->den_rate) 558 if (st->num_rate > st->den_rate)
565 { 559 {
566 /* down-sampling */ 560 /* down-sampling */
@@ -636,25 +630,25 @@ static void update_filter(SpeexResamplerState *st)
636 st->int_advance = st->num_rate/st->den_rate; 630 st->int_advance = st->num_rate/st->den_rate;
637 st->frac_advance = st->num_rate%st->den_rate; 631 st->frac_advance = st->num_rate%st->den_rate;
638 632
639 633
640 /* Here's the place where we update the filter memory to take into account 634 /* Here's the place where we update the filter memory to take into account
641 the change in filter length. It's probably the messiest part of the code 635 the change in filter length. It's probably the messiest part of the code
642 due to handling of lots of corner cases. */ 636 due to handling of lots of corner cases. */
643 if (!st->mem) 637 if (!st->mem)
644 { 638 {
645 spx_uint32_t i; 639 spx_uint32_t i;
646 st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 640 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
647 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 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++)
648 st->mem[i] = 0; 643 st->mem[i] = 0;
649 st->mem_alloc_size = st->filt_len-1;
650 /*speex_warning("init filter");*/ 644 /*speex_warning("init filter");*/
651 } else if (!st->started) 645 } else if (!st->started)
652 { 646 {
653 spx_uint32_t i; 647 spx_uint32_t i;
654 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 648 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
655 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 649 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
650 for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
656 st->mem[i] = 0; 651 st->mem[i] = 0;
657 st->mem_alloc_size = st->filt_len-1;
658 /*speex_warning("reinit filter");*/ 652 /*speex_warning("reinit filter");*/
659 } else if (st->filt_len > old_length) 653 } else if (st->filt_len > old_length)
660 { 654 {
@@ -662,10 +656,10 @@ static void update_filter(SpeexResamplerState *st)
662 /* Increase the filter length */ 656 /* Increase the filter length */
663 /*speex_warning("increase filter size");*/ 657 /*speex_warning("increase filter size");*/
664 int old_alloc_size = st->mem_alloc_size; 658 int old_alloc_size = st->mem_alloc_size;
665 if (st->filt_len-1 > st->mem_alloc_size) 659 if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
666 { 660 {
667 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); 661 st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
668 st->mem_alloc_size = st->filt_len-1; 662 st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
669 } 663 }
670 for (i=st->nb_channels-1;i>=0;i--) 664 for (i=st->nb_channels-1;i>=0;i--)
671 { 665 {
@@ -674,7 +668,7 @@ static void update_filter(SpeexResamplerState *st)
674 /*if (st->magic_samples[i])*/ 668 /*if (st->magic_samples[i])*/
675 { 669 {
676 /* Try and remove the magic samples as if nothing had happened */ 670 /* Try and remove the magic samples as if nothing had happened */
677 671
678 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ 672 /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
679 olen = old_length + 2*st->magic_samples[i]; 673 olen = old_length + 2*st->magic_samples[i];
680 for (j=old_length-2+st->magic_samples[i];j>=0;j--) 674 for (j=old_length-2+st->magic_samples[i];j>=0;j--)
@@ -721,12 +715,12 @@ static void update_filter(SpeexResamplerState *st)
721 715
722} 716}
723 717
724SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) 718EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
725{ 719{
726 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); 720 return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
727} 721}
728 722
729SpeexResamplerState *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) 723EXPORT 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)
730{ 724{
731 spx_uint32_t i; 725 spx_uint32_t i;
732 SpeexResamplerState *st; 726 SpeexResamplerState *st;
@@ -749,12 +743,18 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
749 st->filt_len = 0; 743 st->filt_len = 0;
750 st->mem = 0; 744 st->mem = 0;
751 st->resampler_ptr = 0; 745 st->resampler_ptr = 0;
752 746
753 st->cutoff = 1.f; 747 st->cutoff = 1.f;
754 st->nb_channels = nb_channels; 748 st->nb_channels = nb_channels;
755 st->in_stride = 1; 749 st->in_stride = 1;
756 st->out_stride = 1; 750 st->out_stride = 1;
757 751
752#ifdef FIXED_POINT
753 st->buffer_size = 160;
754#else
755 st->buffer_size = 160;
756#endif
757
758 /* Per channel data */ 758 /* Per channel data */
759 st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); 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)); 760 st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
@@ -769,9 +769,9 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
769 speex_resampler_set_quality(st, quality); 769 speex_resampler_set_quality(st, quality);
770 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); 770 speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
771 771
772 772
773 update_filter(st); 773 update_filter(st);
774 774
775 st->initialised = 1; 775 st->initialised = 1;
776 if (err) 776 if (err)
777 *err = RESAMPLER_ERR_SUCCESS; 777 *err = RESAMPLER_ERR_SUCCESS;
@@ -779,7 +779,7 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
779 return st; 779 return st;
780} 780}
781 781
782void speex_resampler_destroy(SpeexResamplerState *st) 782EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
783{ 783{
784 speex_free(st->mem); 784 speex_free(st->mem);
785 speex_free(st->sinc_table); 785 speex_free(st->sinc_table);
@@ -789,186 +789,168 @@ void speex_resampler_destroy(SpeexResamplerState *st)
789 speex_free(st); 789 speex_free(st);
790} 790}
791 791
792 792static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
793
794static int speex_resampler_process_native(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)
795{ 793{
796 int j=0; 794 int j=0;
797 int N = st->filt_len; 795 const int N = st->filt_len;
798 int out_sample = 0; 796 int out_sample = 0;
799 spx_word16_t *mem; 797 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
800 spx_uint32_t tmp_out_len = 0; 798 spx_uint32_t ilen;
801 mem = st->mem + channel_index * st->mem_alloc_size; 799
802 st->started = 1; 800 st->started = 1;
803 801
804 /* Handle the case where we have samples left from a reduction in filter length */
805 if (st->magic_samples[channel_index])
806 {
807 int istride_save;
808 spx_uint32_t tmp_in_len;
809 spx_uint32_t tmp_magic;
810
811 istride_save = st->in_stride;
812 tmp_in_len = st->magic_samples[channel_index];
813 tmp_out_len = *out_len;
814 /* magic_samples needs to be set to zero to avoid infinite recursion */
815 tmp_magic = st->magic_samples[channel_index];
816 st->magic_samples[channel_index] = 0;
817 st->in_stride = 1;
818 speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
819 st->in_stride = istride_save;
820 /*speex_warning_int("extra samples:", tmp_out_len);*/
821 /* If we couldn't process all "magic" input samples, save the rest for next time */
822 if (tmp_in_len < tmp_magic)
823 {
824 spx_uint32_t i;
825 st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
826 for (i=0;i<st->magic_samples[channel_index];i++)
827 mem[N-1+i]=mem[N-1+i+tmp_in_len];
828 }
829 out += tmp_out_len*st->out_stride;
830 *out_len -= tmp_out_len;
831 }
832
833 /* Call the right resampler through the function ptr */ 802 /* Call the right resampler through the function ptr */
834 out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len); 803 out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
835 804
836 if (st->last_sample[channel_index] < (spx_int32_t)*in_len) 805 if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
837 *in_len = st->last_sample[channel_index]; 806 *in_len = st->last_sample[channel_index];
838 *out_len = out_sample+tmp_out_len; 807 *out_len = out_sample;
839 st->last_sample[channel_index] -= *in_len; 808 st->last_sample[channel_index] -= *in_len;
840 809
841 for (j=0;j<N-1-(spx_int32_t)*in_len;j++) 810 ilen = *in_len;
842 mem[j] = mem[j+*in_len]; 811
843 for (;j<N-1;j++) 812 for(j=0;j<N-1;++j)
844 mem[j] = in[st->in_stride*(j+*in_len-N+1)]; 813 mem[j] = mem[j+ilen];
845 814
846 return RESAMPLER_ERR_SUCCESS; 815 return RESAMPLER_ERR_SUCCESS;
847} 816}
848 817
849#define FIXED_STACK_ALLOC 1024 818static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
819 spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
820 spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
821 const int N = st->filt_len;
822
823 speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
824
825 st->magic_samples[channel_index] -= tmp_in_len;
826
827 /* If we couldn't process all "magic" input samples, save the rest for next time */
828 if (st->magic_samples[channel_index])
829 {
830 spx_uint32_t i;
831 for (i=0;i<st->magic_samples[channel_index];i++)
832 mem[N-1+i]=mem[N-1+i+tmp_in_len];
833 }
834 *out += out_len*st->out_stride;
835 return out_len;
836}
850 837
851#ifdef FIXED_POINT 838#ifdef FIXED_POINT
852int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 839EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
853{
854 spx_uint32_t i;
855 int istride_save, ostride_save;
856#ifdef VAR_ARRAYS
857 spx_word16_t x[*in_len];
858 spx_word16_t y[*out_len];
859 /*VARDECL(spx_word16_t *x);
860 VARDECL(spx_word16_t *y);
861 ALLOC(x, *in_len, spx_word16_t);
862 ALLOC(y, *out_len, spx_word16_t);*/
863 istride_save = st->in_stride;
864 ostride_save = st->out_stride;
865 for (i=0;i<*in_len;i++)
866 x[i] = WORD2INT(in[i*st->in_stride]);
867 st->in_stride = st->out_stride = 1;
868 speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
869 st->in_stride = istride_save;
870 st->out_stride = ostride_save;
871 for (i=0;i<*out_len;i++)
872 out[i*st->out_stride] = y[i];
873#else 840#else
874 spx_word16_t x[FIXED_STACK_ALLOC]; 841EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
875 spx_word16_t y[FIXED_STACK_ALLOC]; 842#endif
876 spx_uint32_t ilen=*in_len, olen=*out_len; 843{
877 istride_save = st->in_stride; 844 int j;
878 ostride_save = st->out_stride; 845 spx_uint32_t ilen = *in_len;
879 while (ilen && olen) 846 spx_uint32_t olen = *out_len;
880 { 847 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
881 spx_uint32_t ichunk, ochunk; 848 const int filt_offs = st->filt_len - 1;
882 ichunk = ilen; 849 const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
883 ochunk = olen; 850 const int istride = st->in_stride;
884 if (ichunk>FIXED_STACK_ALLOC) 851
885 ichunk=FIXED_STACK_ALLOC; 852 if (st->magic_samples[channel_index])
886 if (ochunk>FIXED_STACK_ALLOC) 853 olen -= speex_resampler_magic(st, channel_index, &out, olen);
887 ochunk=FIXED_STACK_ALLOC; 854 if (! st->magic_samples[channel_index]) {
888 for (i=0;i<ichunk;i++) 855 while (ilen && olen) {
889 x[i] = WORD2INT(in[i*st->in_stride]); 856 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
890 st->in_stride = st->out_stride = 1; 857 spx_uint32_t ochunk = olen;
891 speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); 858
892 st->in_stride = istride_save; 859 if (in) {
893 st->out_stride = ostride_save; 860 for(j=0;j<ichunk;++j)
894 for (i=0;i<ochunk;i++) 861 x[j+filt_offs]=in[j*istride];
895 out[i*st->out_stride] = y[i]; 862 } else {
896 out += ochunk; 863 for(j=0;j<ichunk;++j)
897 in += ichunk; 864 x[j+filt_offs]=0;
898 ilen -= ichunk; 865 }
899 olen -= ochunk; 866 speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
867 ilen -= ichunk;
868 olen -= ochunk;
869 out += ochunk * st->out_stride;
870 if (in)
871 in += ichunk * istride;
872 }
900 } 873 }
901 *in_len -= ilen; 874 *in_len -= ilen;
902 *out_len -= olen; 875 *out_len -= olen;
903#endif
904 return RESAMPLER_ERR_SUCCESS; 876 return RESAMPLER_ERR_SUCCESS;
905} 877}
906int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) 878
907{ 879#ifdef FIXED_POINT
908 return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); 880EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
909}
910#else 881#else
911int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 882EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
912{ 883#endif
913 return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
914}
915int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
916{ 884{
917 spx_uint32_t i; 885 int j;
918 int istride_save, ostride_save; 886 const int istride_save = st->in_stride;
887 const int ostride_save = st->out_stride;
888 spx_uint32_t ilen = *in_len;
889 spx_uint32_t olen = *out_len;
890 spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
891 const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
919#ifdef VAR_ARRAYS 892#ifdef VAR_ARRAYS
920 spx_word16_t x[*in_len]; 893 const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
921 spx_word16_t y[*out_len]; 894 VARDECL(spx_word16_t *ystack);
922 /*VARDECL(spx_word16_t *x); 895 ALLOC(ystack, ylen, spx_word16_t);
923 VARDECL(spx_word16_t *y);
924 ALLOC(x, *in_len, spx_word16_t);
925 ALLOC(y, *out_len, spx_word16_t);*/
926 istride_save = st->in_stride;
927 ostride_save = st->out_stride;
928 for (i=0;i<*in_len;i++)
929 x[i] = in[i*st->in_stride];
930 st->in_stride = st->out_stride = 1;
931 speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
932 st->in_stride = istride_save;
933 st->out_stride = ostride_save;
934 for (i=0;i<*out_len;i++)
935 out[i*st->out_stride] = WORD2INT(y[i]);
936#else 896#else
937 spx_word16_t x[FIXED_STACK_ALLOC]; 897 const unsigned int ylen = FIXED_STACK_ALLOC;
938 spx_word16_t y[FIXED_STACK_ALLOC]; 898 spx_word16_t ystack[FIXED_STACK_ALLOC];
939 spx_uint32_t ilen=*in_len, olen=*out_len; 899#endif
940 istride_save = st->in_stride; 900
941 ostride_save = st->out_stride; 901 st->out_stride = 1;
942 while (ilen && olen) 902
943 { 903 while (ilen && olen) {
944 spx_uint32_t ichunk, ochunk; 904 spx_word16_t *y = ystack;
945 ichunk = ilen; 905 spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
946 ochunk = olen; 906 spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
947 if (ichunk>FIXED_STACK_ALLOC) 907 spx_uint32_t omagic = 0;
948 ichunk=FIXED_STACK_ALLOC; 908
949 if (ochunk>FIXED_STACK_ALLOC) 909 if (st->magic_samples[channel_index]) {
950 ochunk=FIXED_STACK_ALLOC; 910 omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
951 for (i=0;i<ichunk;i++) 911 ochunk -= omagic;
952 x[i] = in[i*st->in_stride]; 912 olen -= omagic;
953 st->in_stride = st->out_stride = 1; 913 }
954 speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); 914 if (! st->magic_samples[channel_index]) {
955 st->in_stride = istride_save; 915 if (in) {
956 st->out_stride = ostride_save; 916 for(j=0;j<ichunk;++j)
957 for (i=0;i<ochunk;i++) 917#ifdef FIXED_POINT
958 out[i*st->out_stride] = WORD2INT(y[i]); 918 x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
959 out += ochunk; 919#else
960 in += ichunk; 920 x[j+st->filt_len-1]=in[j*istride_save];
961 ilen -= ichunk; 921#endif
962 olen -= ochunk; 922 } else {
923 for(j=0;j<ichunk;++j)
924 x[j+st->filt_len-1]=0;
925 }
926
927 speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
928 } else {
929 ichunk = 0;
930 ochunk = 0;
931 }
932
933 for (j=0;j<ochunk+omagic;++j)
934#ifdef FIXED_POINT
935 out[j*ostride_save] = ystack[j];
936#else
937 out[j*ostride_save] = WORD2INT(ystack[j]);
938#endif
939
940 ilen -= ichunk;
941 olen -= ochunk;
942 out += (ochunk+omagic) * ostride_save;
943 if (in)
944 in += ichunk * istride_save;
963 } 945 }
946 st->out_stride = ostride_save;
964 *in_len -= ilen; 947 *in_len -= ilen;
965 *out_len -= olen; 948 *out_len -= olen;
966#endif 949
967 return RESAMPLER_ERR_SUCCESS; 950 return RESAMPLER_ERR_SUCCESS;
968} 951}
969#endif
970 952
971int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) 953EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
972{ 954{
973 spx_uint32_t i; 955 spx_uint32_t i;
974 int istride_save, ostride_save; 956 int istride_save, ostride_save;
@@ -989,8 +971,7 @@ int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const flo
989 return RESAMPLER_ERR_SUCCESS; 971 return RESAMPLER_ERR_SUCCESS;
990} 972}
991 973
992 974EXPORT 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)
993int 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)
994{ 975{
995 spx_uint32_t i; 976 spx_uint32_t i;
996 int istride_save, ostride_save; 977 int istride_save, ostride_save;
@@ -1011,25 +992,25 @@ int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_i
1011 return RESAMPLER_ERR_SUCCESS; 992 return RESAMPLER_ERR_SUCCESS;
1012} 993}
1013 994
1014int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) 995EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
1015{ 996{
1016 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); 997 return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
1017} 998}
1018 999
1019void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) 1000EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
1020{ 1001{
1021 *in_rate = st->in_rate; 1002 *in_rate = st->in_rate;
1022 *out_rate = st->out_rate; 1003 *out_rate = st->out_rate;
1023} 1004}
1024 1005
1025int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) 1006EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
1026{ 1007{
1027 spx_uint32_t fact; 1008 spx_uint32_t fact;
1028 spx_uint32_t old_den; 1009 spx_uint32_t old_den;
1029 spx_uint32_t i; 1010 spx_uint32_t i;
1030 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) 1011 if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
1031 return RESAMPLER_ERR_SUCCESS; 1012 return RESAMPLER_ERR_SUCCESS;
1032 1013
1033 old_den = st->den_rate; 1014 old_den = st->den_rate;
1034 st->in_rate = in_rate; 1015 st->in_rate = in_rate;
1035 st->out_rate = out_rate; 1016 st->out_rate = out_rate;
@@ -1044,7 +1025,7 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_nu
1044 st->den_rate /= fact; 1025 st->den_rate /= fact;
1045 } 1026 }
1046 } 1027 }
1047 1028
1048 if (old_den > 0) 1029 if (old_den > 0)
1049 { 1030 {
1050 for (i=0;i<st->nb_channels;i++) 1031 for (i=0;i<st->nb_channels;i++)
@@ -1055,19 +1036,19 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_nu
1055 st->samp_frac_num[i] = st->den_rate-1; 1036 st->samp_frac_num[i] = st->den_rate-1;
1056 } 1037 }
1057 } 1038 }
1058 1039
1059 if (st->initialised) 1040 if (st->initialised)
1060 update_filter(st); 1041 update_filter(st);
1061 return RESAMPLER_ERR_SUCCESS; 1042 return RESAMPLER_ERR_SUCCESS;
1062} 1043}
1063 1044
1064void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) 1045EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
1065{ 1046{
1066 *ratio_num = st->num_rate; 1047 *ratio_num = st->num_rate;
1067 *ratio_den = st->den_rate; 1048 *ratio_den = st->den_rate;
1068} 1049}
1069 1050
1070int speex_resampler_set_quality(SpeexResamplerState *st, int quality) 1051EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1071{ 1052{
1072 if (quality > 10 || quality < 0) 1053 if (quality > 10 || quality < 0)
1073 return RESAMPLER_ERR_INVALID_ARG; 1054 return RESAMPLER_ERR_INVALID_ARG;
@@ -1079,32 +1060,42 @@ int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
1079 return RESAMPLER_ERR_SUCCESS; 1060 return RESAMPLER_ERR_SUCCESS;
1080} 1061}
1081 1062
1082void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) 1063EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
1083{ 1064{
1084 *quality = st->quality; 1065 *quality = st->quality;
1085} 1066}
1086 1067
1087void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) 1068EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
1088{ 1069{
1089 st->in_stride = stride; 1070 st->in_stride = stride;
1090} 1071}
1091 1072
1092void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1073EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1093{ 1074{
1094 *stride = st->in_stride; 1075 *stride = st->in_stride;
1095} 1076}
1096 1077
1097void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) 1078EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
1098{ 1079{
1099 st->out_stride = stride; 1080 st->out_stride = stride;
1100} 1081}
1101 1082
1102void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) 1083EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
1103{ 1084{
1104 *stride = st->out_stride; 1085 *stride = st->out_stride;
1105} 1086}
1106 1087
1107int speex_resampler_skip_zeros(SpeexResamplerState *st) 1088EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
1089{
1090 return st->filt_len / 2;
1091}
1092
1093EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
1094{
1095 return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
1096}
1097
1098EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
1108{ 1099{
1109 spx_uint32_t i; 1100 spx_uint32_t i;
1110 for (i=0;i<st->nb_channels;i++) 1101 for (i=0;i<st->nb_channels;i++)
@@ -1112,7 +1103,7 @@ int speex_resampler_skip_zeros(SpeexResamplerState *st)
1112 return RESAMPLER_ERR_SUCCESS; 1103 return RESAMPLER_ERR_SUCCESS;
1113} 1104}
1114 1105
1115int speex_resampler_reset_mem(SpeexResamplerState *st) 1106EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
1116{ 1107{
1117 spx_uint32_t i; 1108 spx_uint32_t i;
1118 for (i=0;i<st->nb_channels*(st->filt_len-1);i++) 1109 for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
@@ -1120,7 +1111,7 @@ int speex_resampler_reset_mem(SpeexResamplerState *st)
1120 return RESAMPLER_ERR_SUCCESS; 1111 return RESAMPLER_ERR_SUCCESS;
1121} 1112}
1122 1113
1123const char *speex_resampler_strerror(int err) 1114EXPORT const char *speex_resampler_strerror(int err)
1124{ 1115{
1125 switch (err) 1116 switch (err)
1126 { 1117 {
diff --git a/lib/rbcodec/codecs/libspeex/resample_sse.h b/lib/rbcodec/codecs/libspeex/resample_sse.h
new file mode 100644
index 0000000000..d85898067e
--- /dev/null
+++ b/lib/rbcodec/codecs/libspeex/resample_sse.h
@@ -0,0 +1,128 @@
1/* Copyright (C) 2007-2008 Jean-Marc Valin
2 * Copyright (C) 2008 Thorvald Natvig
3 */
4/**
5 @file resample_sse.h
6 @brief Resampler functions (SSE version)
7*/
8/*
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 - Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 - Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in the
18 documentation and/or other materials provided with the distribution.
19
20 - Neither the name of the Xiph.org Foundation nor the names of its
21 contributors may be used to endorse or promote products derived from
22 this software without specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
28 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35*/
36
37#include <xmmintrin.h>
38
39#define OVERRIDE_INNER_PRODUCT_SINGLE
40static inline float inner_product_single(const float *a, const float *b, unsigned int len)
41{
42 int i;
43 float ret;
44 __m128 sum = _mm_setzero_ps();
45 for (i=0;i<len;i+=8)
46 {
47 sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)));
48 sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)));
49 }
50 sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
51 sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
52 _mm_store_ss(&ret, sum);
53 return ret;
54}
55
56#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
57static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
58 int i;
59 float ret;
60 __m128 sum = _mm_setzero_ps();
61 __m128 f = _mm_loadu_ps(frac);
62 for(i=0;i<len;i+=2)
63 {
64 sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)));
65 sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)));
66 }
67 sum = _mm_mul_ps(f, sum);
68 sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
69 sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
70 _mm_store_ss(&ret, sum);
71 return ret;
72}
73
74#ifdef _USE_SSE2
75#include <emmintrin.h>
76#define OVERRIDE_INNER_PRODUCT_DOUBLE
77
78static inline double inner_product_double(const float *a, const float *b, unsigned int len)
79{
80 int i;
81 double ret;
82 __m128d sum = _mm_setzero_pd();
83 __m128 t;
84 for (i=0;i<len;i+=8)
85 {
86 t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i));
87 sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
88 sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
89
90 t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4));
91 sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
92 sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
93 }
94 sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum));
95 _mm_store_sd(&ret, sum);
96 return ret;
97}
98
99#define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
100static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
101 int i;
102 double ret;
103 __m128d sum;
104 __m128d sum1 = _mm_setzero_pd();
105 __m128d sum2 = _mm_setzero_pd();
106 __m128 f = _mm_loadu_ps(frac);
107 __m128d f1 = _mm_cvtps_pd(f);
108 __m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f));
109 __m128 t;
110 for(i=0;i<len;i+=2)
111 {
112 t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample));
113 sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
114 sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
115
116 t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample));
117 sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
118 sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
119 }
120 sum1 = _mm_mul_pd(f1, sum1);
121 sum2 = _mm_mul_pd(f2, sum2);
122 sum = _mm_add_pd(sum1, sum2);
123 sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum));
124 _mm_store_sd(&ret, sum);
125 return ret;
126}
127
128#endif
diff --git a/lib/rbcodec/codecs/libspeex/speex.c b/lib/rbcodec/codecs/libspeex/speex.c
index 92e41f52ae..9836de36b8 100644
--- a/lib/rbcodec/codecs/libspeex/speex.c
+++ b/lib/rbcodec/codecs/libspeex/speex.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2002 Jean-Marc Valin 1/* Copyright (C) 2002 Jean-Marc Valin
2 File: speex.c 2 File: speex.c
3 3
4 Basic Speex functions 4 Basic Speex functions
@@ -6,18 +6,18 @@
6 Redistribution and use in source and binary forms, with or without 6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions 7 modification, are permitted provided that the following conditions
8 are met: 8 are met:
9 9
10 - Redistributions of source code must retain the above copyright 10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer. 11 notice, this list of conditions and the following disclaimer.
12 12
13 - Redistributions in binary form must reproduce the above copyright 13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the 14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution. 15 documentation and/or other materials provided with the distribution.
16 16
17 - Neither the name of the Xiph.org Foundation nor the names of its 17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from 18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission. 19 this software without specific prior written permission.
20 20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -49,25 +49,25 @@
49#define MAX_IN_SAMPLES 640 49#define MAX_IN_SAMPLES 640
50 50
51#ifndef SPEEX_DISABLE_ENCODER 51#ifndef SPEEX_DISABLE_ENCODER
52void *speex_encoder_init(const SpeexMode *mode) 52EXPORT void *speex_encoder_init(const SpeexMode *mode)
53{ 53{
54 return mode->enc_init(mode); 54 return mode->enc_init(mode);
55} 55}
56#endif 56#endif
57 57
58void *speex_decoder_init(const SpeexMode *mode) 58EXPORT void *speex_decoder_init(const SpeexMode *mode)
59{ 59{
60 return mode->dec_init(mode); 60 return mode->dec_init(mode);
61} 61}
62 62
63#ifndef SPEEX_DISABLE_ENCODER 63#ifndef SPEEX_DISABLE_ENCODER
64void speex_encoder_destroy(void *state) 64EXPORT void speex_encoder_destroy(void *state)
65{ 65{
66 (*((SpeexMode**)state))->enc_destroy(state); 66 (*((SpeexMode**)state))->enc_destroy(state);
67} 67}
68#endif 68#endif
69 69
70void speex_decoder_destroy(void *state) 70EXPORT void speex_decoder_destroy(void *state)
71{ 71{
72 (*((SpeexMode**)state))->dec_destroy(state); 72 (*((SpeexMode**)state))->dec_destroy(state);
73} 73}
@@ -90,7 +90,7 @@ int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out)
90 90
91#ifndef SPEEX_DISABLE_ENCODER 91#ifndef SPEEX_DISABLE_ENCODER
92#ifndef DISABLE_FLOAT_API 92#ifndef DISABLE_FLOAT_API
93int speex_encode(void *state, float *in, SpeexBits *bits) 93EXPORT int speex_encode(void *state, float *in, SpeexBits *bits)
94{ 94{
95 int i; 95 int i;
96 spx_int32_t N; 96 spx_int32_t N;
@@ -109,7 +109,7 @@ int speex_encode(void *state, float *in, SpeexBits *bits)
109} 109}
110#endif /* #ifndef DISABLE_FLOAT_API */ 110#endif /* #ifndef DISABLE_FLOAT_API */
111 111
112int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) 112EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
113{ 113{
114 SpeexMode *mode; 114 SpeexMode *mode;
115 mode = *(SpeexMode**)state; 115 mode = *(SpeexMode**)state;
@@ -118,7 +118,7 @@ int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
118#endif /* SPEEX_DISABLE_ENCODER */ 118#endif /* SPEEX_DISABLE_ENCODER */
119 119
120#ifndef DISABLE_FLOAT_API 120#ifndef DISABLE_FLOAT_API
121int speex_decode(void *state, SpeexBits *bits, float *out) 121EXPORT int speex_decode(void *state, SpeexBits *bits, float *out)
122{ 122{
123 int i, ret; 123 int i, ret;
124 spx_int32_t N; 124 spx_int32_t N;
@@ -131,7 +131,7 @@ int speex_decode(void *state, SpeexBits *bits, float *out)
131} 131}
132#endif /* #ifndef DISABLE_FLOAT_API */ 132#endif /* #ifndef DISABLE_FLOAT_API */
133 133
134int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) 134EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
135{ 135{
136 SpeexMode *mode = *(SpeexMode**)state; 136 SpeexMode *mode = *(SpeexMode**)state;
137 return (mode)->dec(state, bits, out); 137 return (mode)->dec(state, bits, out);
@@ -139,12 +139,12 @@ int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
139 139
140#else 140#else
141 141
142int speex_encode(void *state, float *in, SpeexBits *bits) 142EXPORT int speex_encode(void *state, float *in, SpeexBits *bits)
143{ 143{
144 return (*((SpeexMode**)state))->enc(state, in, bits); 144 return (*((SpeexMode**)state))->enc(state, in, bits);
145} 145}
146 146
147int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits) 147EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
148{ 148{
149 int i; 149 int i;
150 spx_int32_t N; 150 spx_int32_t N;
@@ -155,12 +155,12 @@ int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
155 return (*((SpeexMode**)state))->enc(state, float_in, bits); 155 return (*((SpeexMode**)state))->enc(state, float_in, bits);
156} 156}
157 157
158int speex_decode(void *state, SpeexBits *bits, float *out) 158EXPORT int speex_decode(void *state, SpeexBits *bits, float *out)
159{ 159{
160 return (*((SpeexMode**)state))->dec(state, bits, out); 160 return (*((SpeexMode**)state))->dec(state, bits, out);
161} 161}
162 162
163int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out) 163EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
164{ 164{
165 int i; 165 int i;
166 spx_int32_t N; 166 spx_int32_t N;
@@ -182,13 +182,13 @@ int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
182#endif 182#endif
183 183
184#ifndef SPEEX_DISABLE_ENCODER 184#ifndef SPEEX_DISABLE_ENCODER
185int speex_encoder_ctl(void *state, int request, void *ptr) 185EXPORT int speex_encoder_ctl(void *state, int request, void *ptr)
186{ 186{
187 return (*((SpeexMode**)state))->enc_ctl(state, request, ptr); 187 return (*((SpeexMode**)state))->enc_ctl(state, request, ptr);
188} 188}
189#endif 189#endif
190 190
191int speex_decoder_ctl(void *state, int request, void *ptr) 191EXPORT int speex_decoder_ctl(void *state, int request, void *ptr)
192{ 192{
193 return (*((SpeexMode**)state))->dec_ctl(state, request, ptr); 193 return (*((SpeexMode**)state))->dec_ctl(state, request, ptr);
194} 194}
@@ -196,7 +196,7 @@ int speex_decoder_ctl(void *state, int request, void *ptr)
196int nb_mode_query(const void *mode, int request, void *ptr) 196int nb_mode_query(const void *mode, int request, void *ptr)
197{ 197{
198 const SpeexNBMode *m = (const SpeexNBMode*)mode; 198 const SpeexNBMode *m = (const SpeexNBMode*)mode;
199 199
200 switch (request) 200 switch (request)
201 { 201 {
202 case SPEEX_MODE_FRAME_SIZE: 202 case SPEEX_MODE_FRAME_SIZE:
@@ -219,7 +219,7 @@ int nb_mode_query(const void *mode, int request, void *ptr)
219 219
220 220
221 221
222int speex_lib_ctl(int request, void *ptr) 222EXPORT int speex_lib_ctl(int request, void *ptr)
223{ 223{
224 switch (request) 224 switch (request)
225 { 225 {
diff --git a/lib/rbcodec/codecs/libspeex/speex_callbacks.c b/lib/rbcodec/codecs/libspeex/speex_callbacks.c
index f1de038488..ca236ed399 100644
--- a/lib/rbcodec/codecs/libspeex/speex_callbacks.c
+++ b/lib/rbcodec/codecs/libspeex/speex_callbacks.c
@@ -6,18 +6,18 @@
6 Redistribution and use in source and binary forms, with or without 6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions 7 modification, are permitted provided that the following conditions
8 are met: 8 are met:
9 9
10 - Redistributions of source code must retain the above copyright 10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer. 11 notice, this list of conditions and the following disclaimer.
12 12
13 - Redistributions in binary form must reproduce the above copyright 13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the 14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution. 15 documentation and/or other materials provided with the distribution.
16 16
17 - Neither the name of the Xiph.org Foundation nor the names of its 17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from 18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission. 19 this software without specific prior written permission.
20 20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -40,7 +40,7 @@
40#include "arch.h" 40#include "arch.h"
41#include "os_support.h" 41#include "os_support.h"
42 42
43int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) 43EXPORT int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state)
44{ 44{
45 int id; 45 int id;
46 SpeexCallback *callback; 46 SpeexCallback *callback;
@@ -65,7 +65,7 @@ int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *st
65 adv = 16; 65 adv = 16;
66 else if (id<14) 66 else if (id<14)
67 adv = 32; 67 adv = 32;
68 else 68 else
69 adv = 64; 69 adv = 64;
70 speex_bits_advance(bits, adv); 70 speex_bits_advance(bits, adv);
71 } 71 }
@@ -74,7 +74,7 @@ int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *st
74 74
75#if 0 75#if 0
76/* Rockbox: unused */ 76/* Rockbox: unused */
77int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data) 77EXPORT int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data)
78{ 78{
79 (void)state; 79 (void)state;
80 spx_int32_t m; 80 spx_int32_t m;
@@ -83,7 +83,7 @@ int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data)
83 return 0; 83 return 0;
84} 84}
85 85
86int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data) 86EXPORT int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data)
87{ 87{
88 (void)state; 88 (void)state;
89 spx_int32_t m; 89 spx_int32_t m;
@@ -92,7 +92,7 @@ int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data)
92 return 0; 92 return 0;
93} 93}
94 94
95int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data) 95EXPORT int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data)
96{ 96{
97 (void)state; 97 (void)state;
98 spx_int32_t m; 98 spx_int32_t m;
@@ -103,7 +103,7 @@ int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data
103#endif 103#endif
104 104
105#ifndef DISABLE_VBR 105#ifndef DISABLE_VBR
106int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data) 106EXPORT int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
107{ 107{
108 (void)state; 108 (void)state;
109 spx_int32_t vbr; 109 spx_int32_t vbr;
@@ -115,7 +115,7 @@ int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
115 115
116#if 0 116#if 0
117/* Rockbox: unused */ 117/* Rockbox: unused */
118int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data) 118EXPORT int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
119{ 119{
120 (void)state; 120 (void)state;
121 spx_int32_t enh; 121 spx_int32_t enh;
@@ -126,7 +126,7 @@ int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
126#endif 126#endif
127 127
128#ifndef DISABLE_VBR 128#ifndef DISABLE_VBR
129int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data) 129EXPORT int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data)
130{ 130{
131 (void)state; 131 (void)state;
132 float qual; 132 float qual;
@@ -138,7 +138,7 @@ int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *da
138 138
139#if 0 139#if 0
140/* Rockbox: unused */ 140/* Rockbox: unused */
141int speex_std_char_handler(SpeexBits *bits, void *state, void *data) 141EXPORT int speex_std_char_handler(SpeexBits *bits, void *state, void *data)
142{ 142{
143 (void)state; 143 (void)state;
144 unsigned char ch; 144 unsigned char ch;
@@ -150,7 +150,7 @@ int speex_std_char_handler(SpeexBits *bits, void *state, void *data)
150#endif 150#endif
151 151
152/* Default handler for user callbacks: skip it */ 152/* Default handler for user callbacks: skip it */
153int speex_default_user_handler(SpeexBits *bits, void *state, void *data) 153EXPORT int speex_default_user_handler(SpeexBits *bits, void *state, void *data)
154{ 154{
155 (void)state; 155 (void)state;
156 (void)data; 156 (void)data;
diff --git a/lib/rbcodec/codecs/libspeex/speex_header.c b/lib/rbcodec/codecs/libspeex/speex_header.c
index b0e98b7c9c..f83e0f2152 100644
--- a/lib/rbcodec/codecs/libspeex/speex_header.c
+++ b/lib/rbcodec/codecs/libspeex/speex_header.c
@@ -1,22 +1,22 @@
1/* Copyright (C) 2002 Jean-Marc Valin 1/* Copyright (C) 2002 Jean-Marc Valin
2 File: speex_header.c 2 File: speex_header.c
3 Describes the Speex header 3 Describes the Speex header
4 4
5 Redistribution and use in source and binary forms, with or without 5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions 6 modification, are permitted provided that the following conditions
7 are met: 7 are met:
8 8
9 - Redistributions of source code must retain the above copyright 9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer. 10 notice, this list of conditions and the following disclaimer.
11 11
12 - Redistributions in binary form must reproduce the above copyright 12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the 13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution. 14 documentation and/or other materials provided with the distribution.
15 15
16 - Neither the name of the Xiph.org Foundation nor the names of its 16 - Neither the name of the Xiph.org Foundation nor the names of its
17 contributors may be used to endorse or promote products derived from 17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission. 18 this software without specific prior written permission.
19 19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -47,7 +47,7 @@
47/** Convert little endian */ 47/** Convert little endian */
48static inline spx_int32_t le_int(spx_int32_t i) 48static inline spx_int32_t le_int(spx_int32_t i)
49{ 49{
50#ifdef ROCKBOX 50#ifdef ROCKBOX
51 return letoh32(i); 51 return letoh32(i);
52#elif !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) 52#elif !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
53 spx_uint32_t ui, ret; 53 spx_uint32_t ui, ret;
@@ -86,7 +86,7 @@ typedef struct SpeexHeader {
86*/ 86*/
87 87
88#ifndef SPEEX_DISABLE_ENCODER 88#ifndef SPEEX_DISABLE_ENCODER
89void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m) 89EXPORT void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m)
90{ 90{
91 int i; 91 int i;
92 const char *h="Speex "; 92 const char *h="Speex ";
@@ -101,10 +101,10 @@ void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const Spe
101 header->speex_version[i]=SPEEX_VERSION[i]; 101 header->speex_version[i]=SPEEX_VERSION[i];
102 for (;i<SPEEX_HEADER_VERSION_LENGTH;i++) 102 for (;i<SPEEX_HEADER_VERSION_LENGTH;i++)
103 header->speex_version[i]=0; 103 header->speex_version[i]=0;
104 104
105 header->speex_version_id = 1; 105 header->speex_version_id = 1;
106 header->header_size = sizeof(SpeexHeader); 106 header->header_size = sizeof(SpeexHeader);
107 107
108 header->rate = rate; 108 header->rate = rate;
109 header->mode = m->modeID; 109 header->mode = m->modeID;
110 header->mode_bitstream_version = m->bitstream_version; 110 header->mode_bitstream_version = m->bitstream_version;
@@ -114,20 +114,20 @@ void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const Spe
114 header->bitrate = -1; 114 header->bitrate = -1;
115 speex_mode_query(m, SPEEX_MODE_FRAME_SIZE, &header->frame_size); 115 speex_mode_query(m, SPEEX_MODE_FRAME_SIZE, &header->frame_size);
116 header->vbr = 0; 116 header->vbr = 0;
117 117
118 header->frames_per_packet = 0; 118 header->frames_per_packet = 0;
119 header->extra_headers = 0; 119 header->extra_headers = 0;
120 header->reserved1 = 0; 120 header->reserved1 = 0;
121 header->reserved2 = 0; 121 header->reserved2 = 0;
122} 122}
123 123
124char *speex_header_to_packet(SpeexHeader *header, int *size) 124EXPORT char *speex_header_to_packet(SpeexHeader *header, int *size)
125{ 125{
126 SpeexHeader *le_header; 126 SpeexHeader *le_header;
127 le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); 127 le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader));
128 128
129 SPEEX_COPY(le_header, header, 1); 129 SPEEX_COPY(le_header, header, 1);
130 130
131 /*Make sure everything is now little-endian*/ 131 /*Make sure everything is now little-endian*/
132 ENDIAN_SWITCH(le_header->speex_version_id); 132 ENDIAN_SWITCH(le_header->speex_version_id);
133 ENDIAN_SWITCH(le_header->header_size); 133 ENDIAN_SWITCH(le_header->header_size);
@@ -147,7 +147,7 @@ char *speex_header_to_packet(SpeexHeader *header, int *size)
147#endif /* SPEEX_DISABLE_ENCODER */ 147#endif /* SPEEX_DISABLE_ENCODER */
148 148
149static SpeexHeader global_le_header; /* Avoid malloc */ 149static SpeexHeader global_le_header; /* Avoid malloc */
150SpeexHeader *speex_packet_to_header(char *packet, int size) 150EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size)
151{ 151{
152 int i; 152 int i;
153 SpeexHeader *le_header = &global_le_header; 153 SpeexHeader *le_header = &global_le_header;
@@ -158,18 +158,18 @@ SpeexHeader *speex_packet_to_header(char *packet, int size)
158 speex_notify("This doesn't look like a Speex file"); 158 speex_notify("This doesn't look like a Speex file");
159 return NULL; 159 return NULL;
160 } 160 }
161 161
162 /*FIXME: Do we allow larger headers?*/ 162 /*FIXME: Do we allow larger headers?*/
163 if (size < (int)sizeof(SpeexHeader)) 163 if (size < (int)sizeof(SpeexHeader))
164 { 164 {
165 speex_notify("Speex header too small"); 165 speex_notify("Speex header too small");
166 return NULL; 166 return NULL;
167 } 167 }
168 168
169 /* le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); */ 169 /* le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader)); */
170 170
171 SPEEX_COPY(le_header, (SpeexHeader*)packet, 1); 171 SPEEX_COPY(le_header, (SpeexHeader*)packet, 1);
172 172
173 /*Make sure everything is converted correctly from little-endian*/ 173 /*Make sure everything is converted correctly from little-endian*/
174 ENDIAN_SWITCH(le_header->speex_version_id); 174 ENDIAN_SWITCH(le_header->speex_version_id);
175 ENDIAN_SWITCH(le_header->header_size); 175 ENDIAN_SWITCH(le_header->header_size);
@@ -183,6 +183,25 @@ SpeexHeader *speex_packet_to_header(char *packet, int size)
183 ENDIAN_SWITCH(le_header->frames_per_packet); 183 ENDIAN_SWITCH(le_header->frames_per_packet);
184 ENDIAN_SWITCH(le_header->extra_headers); 184 ENDIAN_SWITCH(le_header->extra_headers);
185 185
186 if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0)
187 {
188 speex_notify("Invalid mode specified in Speex header");
189 speex_free (le_header);
190 return NULL;
191 }
192
193 if (le_header->nb_channels>2)
194 le_header->nb_channels = 2;
195 if (le_header->nb_channels<1)
196 le_header->nb_channels = 1;
197
186 return le_header; 198 return le_header;
187 199
188} 200}
201
202#if 0 /* Unused by rockbox */
203EXPORT void speex_header_free(void *ptr)
204{
205 speex_free(ptr);
206}
207#endif
diff --git a/lib/rbcodec/codecs/libspeex/stereo.c b/lib/rbcodec/codecs/libspeex/stereo.c
index 0aca1050fa..e995cde093 100644
--- a/lib/rbcodec/codecs/libspeex/stereo.c
+++ b/lib/rbcodec/codecs/libspeex/stereo.c
@@ -1,21 +1,21 @@
1/* Copyright (C) 2002 Jean-Marc Valin 1/* Copyright (C) 2002 Jean-Marc Valin
2 File: stereo.c 2 File: stereo.c
3 3
4 Redistribution and use in source and binary forms, with or without 4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions 5 modification, are permitted provided that the following conditions
6 are met: 6 are met:
7 7
8 - Redistributions of source code must retain the above copyright 8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer. 9 notice, this list of conditions and the following disclaimer.
10 10
11 - Redistributions in binary form must reproduce the above copyright 11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the 12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution. 13 documentation and/or other materials provided with the distribution.
14 14
15 - Neither the name of the Xiph.org Foundation nor the names of its 15 - Neither the name of the Xiph.org Foundation nor the names of its
16 contributors may be used to endorse or promote products derived from 16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission. 17 this software without specific prior written permission.
18 18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -71,11 +71,11 @@ static const spx_word16_t balance_bounds[31] = {18, 23, 30, 38, 49, 63, 81, 104
71#ifdef FIXED_POINT 71#ifdef FIXED_POINT
72#define COMPATIBILITY_HACK(s) do {if ((s)->reserved1 != 0xdeadbeef) speex_stereo_state_reset((SpeexStereoState*)s); } while (0); 72#define COMPATIBILITY_HACK(s) do {if ((s)->reserved1 != 0xdeadbeef) speex_stereo_state_reset((SpeexStereoState*)s); } while (0);
73#else 73#else
74#define COMPATIBILITY_HACK(s) 74#define COMPATIBILITY_HACK(s)
75#endif 75#endif
76 76
77static SpeexStereoState global_stereo_state; 77static SpeexStereoState global_stereo_state;
78SpeexStereoState *speex_stereo_state_init() 78EXPORT SpeexStereoState *speex_stereo_state_init()
79{ 79{
80 /* SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); */ 80 /* SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); */
81 SpeexStereoState *stereo = &global_stereo_state; 81 SpeexStereoState *stereo = &global_stereo_state;
@@ -83,7 +83,7 @@ SpeexStereoState *speex_stereo_state_init()
83 return stereo; 83 return stereo;
84} 84}
85 85
86void speex_stereo_state_reset(SpeexStereoState *_stereo) 86EXPORT void speex_stereo_state_reset(SpeexStereoState *_stereo)
87{ 87{
88 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; 88 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo;
89#ifdef FIXED_POINT 89#ifdef FIXED_POINT
@@ -100,10 +100,10 @@ void speex_stereo_state_reset(SpeexStereoState *_stereo)
100 stereo->smooth_right = 1.f; 100 stereo->smooth_right = 1.f;
101 stereo->reserved1 = 0; 101 stereo->reserved1 = 0;
102 stereo->reserved2 = 0; 102 stereo->reserved2 = 0;
103#endif 103#endif
104} 104}
105 105
106void speex_stereo_state_destroy(SpeexStereoState *stereo) 106EXPORT void speex_stereo_state_destroy(SpeexStereoState *stereo)
107{ 107{
108 (void)stereo; 108 (void)stereo;
109 /* speex_free(stereo); */ 109 /* speex_free(stereo); */
@@ -111,7 +111,7 @@ void speex_stereo_state_destroy(SpeexStereoState *stereo)
111 111
112#ifndef SPEEX_DISABLE_ENCODER 112#ifndef SPEEX_DISABLE_ENCODER
113#ifndef DISABLE_FLOAT_API 113#ifndef DISABLE_FLOAT_API
114void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) 114EXPORT void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
115{ 115{
116 int i, tmp; 116 int i, tmp;
117 float e_left=0, e_right=0, e_tot=0; 117 float e_left=0, e_right=0, e_tot=0;
@@ -129,7 +129,7 @@ void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
129 /*Quantization*/ 129 /*Quantization*/
130 speex_bits_pack(bits, 14, 5); 130 speex_bits_pack(bits, 14, 5);
131 speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); 131 speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4);
132 132
133 balance=4*log(balance); 133 balance=4*log(balance);
134 134
135 /*Pack sign*/ 135 /*Pack sign*/
@@ -140,16 +140,16 @@ void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
140 balance=floor(.5+fabs(balance)); 140 balance=floor(.5+fabs(balance));
141 if (balance>30) 141 if (balance>30)
142 balance=31; 142 balance=31;
143 143
144 speex_bits_pack(bits, (int)balance, 5); 144 speex_bits_pack(bits, (int)balance, 5);
145 145
146 /* FIXME: this is a hack */ 146 /* FIXME: this is a hack */
147 tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 4); 147 tmp=scal_quant(e_ratio*Q15_ONE, e_ratio_quant_bounds, 4);
148 speex_bits_pack(bits, tmp, 2); 148 speex_bits_pack(bits, tmp, 2);
149} 149}
150#endif /* #ifndef DISABLE_FLOAT_API */ 150#endif /* #ifndef DISABLE_FLOAT_API */
151 151
152void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) 152EXPORT void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
153{ 153{
154 int i, tmp; 154 int i, tmp;
155 spx_word32_t e_left=0, e_right=0, e_tot=0; 155 spx_word32_t e_left=0, e_right=0, e_tot=0;
@@ -159,7 +159,7 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
159#ifdef FIXED_POINT 159#ifdef FIXED_POINT
160 int shift; 160 int shift;
161#endif 161#endif
162 162
163 /* In band marker */ 163 /* In band marker */
164 speex_bits_pack(bits, 14, 5); 164 speex_bits_pack(bits, 14, 5);
165 /* Stereo marker */ 165 /* Stereo marker */
@@ -204,9 +204,9 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
204 if (balance_id>30) 204 if (balance_id>30)
205 balance_id=31; 205 balance_id=31;
206#endif 206#endif
207 207
208 speex_bits_pack(bits, balance_id, 5); 208 speex_bits_pack(bits, balance_id, 5);
209 209
210 /* "coherence" quantisation */ 210 /* "coherence" quantisation */
211#ifdef FIXED_POINT 211#ifdef FIXED_POINT
212 shift = spx_ilog2(e_tot); 212 shift = spx_ilog2(e_tot);
@@ -217,7 +217,7 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
217#else 217#else
218 e_ratio = e_tot/(1.+e_left+e_right); 218 e_ratio = e_tot/(1.+e_left+e_right);
219#endif 219#endif
220 220
221 tmp=scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4); 221 tmp=scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4);
222 /*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio);*/ 222 /*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio);*/
223 speex_bits_pack(bits, tmp, 2); 223 speex_bits_pack(bits, tmp, 2);
@@ -225,18 +225,18 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
225#endif /* SPEEX_DISABLE_ENCODER */ 225#endif /* SPEEX_DISABLE_ENCODER */
226 226
227#ifndef DISABLE_FLOAT_API 227#ifndef DISABLE_FLOAT_API
228void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo) 228EXPORT void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
229{ 229{
230 int i; 230 int i;
231 spx_word32_t balance; 231 spx_word32_t balance;
232 spx_word16_t e_left, e_right, e_ratio; 232 spx_word16_t e_left, e_right, e_ratio;
233 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; 233 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo;
234 234
235 COMPATIBILITY_HACK(stereo); 235 COMPATIBILITY_HACK(stereo);
236 236
237 balance=stereo->balance; 237 balance=stereo->balance;
238 e_ratio=stereo->e_ratio; 238 e_ratio=stereo->e_ratio;
239 239
240 /* These two are Q14, with max value just below 2. */ 240 /* These two are Q14, with max value just below 2. */
241 e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); 241 e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance))));
242 e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); 242 e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8);
@@ -252,7 +252,7 @@ void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
252} 252}
253#endif /* #ifndef DISABLE_FLOAT_API */ 253#endif /* #ifndef DISABLE_FLOAT_API */
254 254
255void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) 255EXPORT void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo)
256{ 256{
257 int i; 257 int i;
258 spx_word32_t balance; 258 spx_word32_t balance;
@@ -260,10 +260,10 @@ void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState
260 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; 260 RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo;
261 261
262 /* COMPATIBILITY_HACK(stereo); */ 262 /* COMPATIBILITY_HACK(stereo); */
263 263
264 balance=stereo->balance; 264 balance=stereo->balance;
265 e_ratio=stereo->e_ratio; 265 e_ratio=stereo->e_ratio;
266 266
267 /* These two are Q14, with max value just below 2. */ 267 /* These two are Q14, with max value just below 2. */
268 e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); 268 e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance))));
269 e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); 269 e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8);
@@ -278,7 +278,7 @@ void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState
278 } 278 }
279} 279}
280 280
281int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) 281EXPORT int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
282{ 282{
283 (void)state; 283 (void)state;
284 RealSpeexStereoState *stereo; 284 RealSpeexStereoState *stereo;
@@ -286,7 +286,7 @@ int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
286 int tmp; 286 int tmp;
287 287
288 stereo = (RealSpeexStereoState*)data; 288 stereo = (RealSpeexStereoState*)data;
289 289
290 /* COMPATIBILITY_HACK(stereo); */ 290 /* COMPATIBILITY_HACK(stereo); */
291 291
292 if (speex_bits_unpack_unsigned(bits, 1)) 292 if (speex_bits_unpack_unsigned(bits, 1))