Bug 1948436 - Update opus to c79a9bd1dd2898cd57bb793e037d58c937555c2c r=kinetik

Differential Revision: https://phabricator.services.mozilla.com/D238339
This commit is contained in:
Updatebot
2025-02-16 22:40:13 +00:00
parent c89afbb999
commit c8eb931250
48 changed files with 3013 additions and 1223 deletions

View File

@@ -54,8 +54,13 @@
#define SAMP_MIN -SAMP_MAX #define SAMP_MIN -SAMP_MAX
#ifdef ENABLE_QEXT
# define S_MUL(a,b) MULT32_32_Q31(b, a)
# define S_MUL2(a,b) MULT32_32_Q31(b, a)
#else
# define S_MUL(a,b) MULT16_32_Q15(b, a) # define S_MUL(a,b) MULT16_32_Q15(b, a)
# define S_MUL2(a,b) MULT16_32_Q16(b, a)
#endif
# define C_MUL(m,a,b) \ # define C_MUL(m,a,b) \
do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
@@ -104,6 +109,7 @@
#else /* not FIXED_POINT*/ #else /* not FIXED_POINT*/
# define S_MUL(a,b) ( (a)*(b) ) # define S_MUL(a,b) ( (a)*(b) )
# define S_MUL2(a,b) ( (a)*(b) )
#define C_MUL(m,a,b) \ #define C_MUL(m,a,b) \
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0) (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)

View File

@@ -56,7 +56,7 @@
#define CELT_SIG_SCALE 32768.f #define CELT_SIG_SCALE 32768.f
#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__); #define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__)
#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING) #if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
#ifdef __GNUC__ #ifdef __GNUC__
@@ -105,6 +105,16 @@ void celt_fatal(const char *str, const char *file, int line)
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */ #define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
#define UADD32(a,b) ((a)+(b)) #define UADD32(a,b) ((a)+(b))
#define USUB32(a,b) ((a)-(b)) #define USUB32(a,b) ((a)-(b))
#define MAXG(a,b) MAX32(a, b)
#define MING(a,b) MIN32(a, b)
/* Throughout the code, we use the following scaling for signals:
FLOAT: used for float API, normalized to +/-1.
INT16: used for 16-bit API, normalized to +/- 32768
RES: internal Opus resolution, defined as +/-1. in float builds, or either 16-bit or 24-bit int for fixed-point builds
SIG: internal CELT resolution: defined as +/- 32768. in float builds, or Q27 in fixed-point builds (int16 shifted by 12)
*/
/* Set this if opus_int64 is a native type of the CPU. */ /* Set this if opus_int64 is a native type of the CPU. */
/* Assume that all LP64 architectures have fast 64-bit types; also x86_64 /* Assume that all LP64 architectures have fast 64-bit types; also x86_64
@@ -126,10 +136,65 @@ typedef opus_int64 opus_val64;
typedef opus_val32 celt_sig; typedef opus_val32 celt_sig;
typedef opus_val16 celt_norm; typedef opus_val16 celt_norm;
typedef opus_val32 celt_ener; typedef opus_val32 celt_ener;
typedef opus_val32 celt_glog;
#ifdef ENABLE_RES24
typedef opus_val32 opus_res;
#define RES_SHIFT 8
#define SIG2RES(a) PSHR32(a, SIG_SHIFT-RES_SHIFT)
#define RES2INT16(a) SAT16(PSHR32(a, RES_SHIFT))
#define RES2INT24(a) (a)
#define RES2FLOAT(a) ((1.f/32768.f/256.)*(a))
#define INT16TORES(a) SHL32(EXTEND32(a), RES_SHIFT)
#define INT24TORES(a) (a)
#define ADD_RES(a, b) ADD32(a, b)
#define FLOAT2RES(a) float2int(32768.f*256.f*(a))
#define RES2SIG(a) SHL32((a), SIG_SHIFT-RES_SHIFT)
#define MULT16_RES_Q15(a,b) MULT16_32_Q15(a,b)
#define MAX_ENCODING_DEPTH 24
#else
typedef opus_val16 opus_res;
#define RES_SHIFT 0
#define SIG2RES(a) SIG2WORD16(a)
#define RES2INT16(a) (a)
#define RES2INT24(a) SHL32(EXTEND32(a), 8)
#define RES2FLOAT(a) ((1.f/32768.f)*(a))
#define INT16TORES(a) (a)
#define INT24TORES(a) SAT16(PSHR32(a, 8))
#define ADD_RES(a, b) SAT16(ADD32((a), (b)));
#define FLOAT2RES(a) FLOAT2INT16(a)
#define RES2SIG(a) SHL32(EXTEND32(a), SIG_SHIFT)
#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
#define MAX_ENCODING_DEPTH 16
#endif
#define RES2VAL16(a) RES2INT16(a)
#define FLOAT2SIG(a) float2int(((opus_int32)32768<<SIG_SHIFT)*(a))
#define INT16TOSIG(a) SHL32(EXTEND32(a), SIG_SHIFT)
#define INT24TOSIG(a) SHL32(a, SIG_SHIFT-8)
#ifdef ENABLE_QEXT
typedef opus_val32 celt_coef;
#define COEF_ONE Q31ONE
#define MULT_COEF_32(a, b) MULT32_32_Q31(a,b)
#define MAC_COEF_32_ARM(c, a, b) ADD32((c), MULT32_32_Q32(a,b))
#define MULT_COEF(a, b) MULT32_32_Q31(a,b)
#define MULT_COEF_TAPS(a, b) SHL32(MULT16_16(a,b), 1)
#define COEF2VAL16(x) EXTRACT16(SHR32(x, 16))
#else
typedef opus_val16 celt_coef;
#define COEF_ONE Q15ONE
#define MULT_COEF_32(a, b) MULT16_32_Q15(a,b)
#define MAC_COEF_32_ARM(a, b, c) MAC16_32_Q16(a,b,c)
#define MULT_COEF(a, b) MULT16_16_Q15(a,b)
#define MULT_COEF_TAPS(a, b) MULT16_16_P15(a,b)
#define COEF2VAL16(x) (x)
#endif
#define celt_isnan(x) 0 #define celt_isnan(x) 0
#define Q15ONE 32767 #define Q15ONE 32767
#define Q31ONE 2147483647
#define SIG_SHIFT 12 #define SIG_SHIFT 12
/* Safe saturation value for 32-bit signals. We need to make sure that we can /* Safe saturation value for 32-bit signals. We need to make sure that we can
@@ -143,15 +208,13 @@ typedef opus_val32 celt_ener;
#define NORM_SCALING 16384 #define NORM_SCALING 16384
#define DB_SHIFT 10 #define DB_SHIFT 24
#define EPSILON 1 #define EPSILON 1
#define VERY_SMALL 0 #define VERY_SMALL 0
#define VERY_LARGE16 ((opus_val16)32767) #define VERY_LARGE16 ((opus_val16)32767)
#define Q15_ONE ((opus_val16)32767) #define Q15_ONE ((opus_val16)32767)
#define SCALEIN(a) (a)
#define SCALEOUT(a) (a)
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) #define ABS16(x) ((x) < 0 ? (-(x)) : (x))
#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) #define ABS32(x) ((x) < 0 ? (-(x)) : (x))
@@ -191,6 +254,10 @@ typedef float opus_val64;
typedef float celt_sig; typedef float celt_sig;
typedef float celt_norm; typedef float celt_norm;
typedef float celt_ener; typedef float celt_ener;
typedef float celt_glog;
typedef float opus_res;
typedef float celt_coef;
#ifdef FLOAT_APPROX #ifdef FLOAT_APPROX
/* This code should reliably detect NaN/inf even when -ffast-math is used. /* This code should reliably detect NaN/inf even when -ffast-math is used.
@@ -209,6 +276,9 @@ static OPUS_INLINE int celt_isnan(float x)
#endif #endif
#define Q15ONE 1.0f #define Q15ONE 1.0f
#define Q31ONE 1.0f
#define COEF_ONE 1.0f
#define COEF2VAL16(x) (x)
#define NORM_SCALING 1.f #define NORM_SCALING 1.f
@@ -223,6 +293,7 @@ static OPUS_INLINE int celt_isnan(float x)
#define QCONST16(x,bits) (x) #define QCONST16(x,bits) (x)
#define QCONST32(x,bits) (x) #define QCONST32(x,bits) (x)
#define GCONST(x) (x)
#define NEG16(x) (-(x)) #define NEG16(x) (-(x))
#define NEG32(x) (-(x)) #define NEG32(x) (-(x))
@@ -264,6 +335,7 @@ static OPUS_INLINE int celt_isnan(float x)
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) #define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
#define MAC16_32_Q16(c,a,b) ((c)+(a)*(b)) #define MAC16_32_Q16(c,a,b) ((c)+(a)*(b))
#define MAC_COEF_32_ARM(c,a,b) ((c)+(a)*(b))
#define MULT16_16_Q11_32(a,b) ((a)*(b)) #define MULT16_16_Q11_32(a,b) ((a)*(b))
#define MULT16_16_Q11(a,b) ((a)*(b)) #define MULT16_16_Q11(a,b) ((a)*(b))
@@ -275,13 +347,29 @@ static OPUS_INLINE int celt_isnan(float x)
#define MULT16_16_P14(a,b) ((a)*(b)) #define MULT16_16_P14(a,b) ((a)*(b))
#define MULT16_32_P16(a,b) ((a)*(b)) #define MULT16_32_P16(a,b) ((a)*(b))
#define MULT_COEF_32(a, b) ((a)*(b))
#define MULT_COEF(a, b) ((a)*(b))
#define MULT_COEF_TAPS(a, b) ((a)*(b))
#define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b)) #define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b))
#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b)) #define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b))
#define SCALEIN(a) ((a)*CELT_SIG_SCALE) #define SIG2RES(a) ((1/CELT_SIG_SCALE)*(a))
#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE)) #define RES2INT16(a) FLOAT2INT16(a)
#define RES2INT24(a) float2int(32768.f*256.f*(a))
#define RES2FLOAT(a) (a)
#define INT16TORES(a) ((a)*(1/CELT_SIG_SCALE))
#define INT24TORES(a) ((1.f/32768.f/256.)*(a))
#define ADD_RES(a, b) ADD32(a, b)
#define FLOAT2RES(a) (a)
#define RES2SIG(a) (CELT_SIG_SCALE*(a))
#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
#define SIG2WORD16(x) (x) #define RES2VAL16(a) (a)
#define FLOAT2SIG(a) ((a)*CELT_SIG_SCALE)
#define INT16TOSIG(a) ((float)(a))
#define INT24TOSIG(a) ((float)(a)*(1.f/256.f))
#define MAX_ENCODING_DEPTH 24
#endif /* !FIXED_POINT */ #endif /* !FIXED_POINT */

View File

@@ -108,20 +108,27 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
maxval = celt_maxabs32(&X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM); maxval = celt_maxabs32(&X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM);
if (maxval > 0) if (maxval > 0)
{ {
int shift = celt_ilog2(maxval) - 14 + (((m->logN[i]>>BITRES)+LM+1)>>1); int shift, shift2;
shift = celt_ilog2(maxval) - 14;
shift2 = (((m->logN[i]>>BITRES)+LM+1)>>1);
j=eBands[i]<<LM; j=eBands[i]<<LM;
if (shift>0) if (shift>0)
{ {
do { do {
sum = MAC16_16(sum, EXTRACT16(SHR32(X[j+c*N],shift)), sum = ADD32(sum, SHR32(MULT16_16(EXTRACT16(SHR32(X[j+c*N],shift)),
EXTRACT16(SHR32(X[j+c*N],shift))); EXTRACT16(SHR32(X[j+c*N],shift))), 2*shift2));
} while (++j<eBands[i+1]<<LM); } while (++j<eBands[i+1]<<LM);
} else { } else {
do { do {
sum = MAC16_16(sum, EXTRACT16(SHL32(X[j+c*N],-shift)), sum = ADD32(sum, SHR32(MULT16_16(EXTRACT16(SHL32(X[j+c*N],-shift)),
EXTRACT16(SHL32(X[j+c*N],-shift))); EXTRACT16(SHL32(X[j+c*N],-shift))), 2*shift2));
} while (++j<eBands[i+1]<<LM); } while (++j<eBands[i+1]<<LM);
} }
shift+=shift2;
while (sum < 1<<28) {
sum <<=2;
shift -= 1;
}
/* We're adding one here to ensure the normalized band isn't larger than unity norm */ /* We're adding one here to ensure the normalized band isn't larger than unity norm */
bandE[i+c*m->nbEBands] = EPSILON+VSHR32(celt_sqrt(sum),-shift); bandE[i+c*m->nbEBands] = EPSILON+VSHR32(celt_sqrt(sum),-shift);
} else { } else {
@@ -143,13 +150,19 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
i=0; do { i=0; do {
opus_val16 g; opus_val16 g;
int j,shift; int j,shift;
opus_val16 E; opus_val32 E;
shift = celt_zlog2(bandE[i+c*m->nbEBands])-13; shift = celt_zlog2(bandE[i+c*m->nbEBands])-14;
E = VSHR32(bandE[i+c*m->nbEBands], shift); E = VSHR32(bandE[i+c*m->nbEBands], shift-2);
g = EXTRACT16(celt_rcp(SHL32(E,3))); g = EXTRACT16(celt_rcp(E));
if (shift > 0) {
j=M*eBands[i]; do { j=M*eBands[i]; do {
X[j+c*N] = MULT16_16_Q15(VSHR32(freq[j+c*N],shift-1),g); X[j+c*N] = PSHR32(MULT16_32_Q15(g, freq[j+c*N]),shift);
} while (++j<M*eBands[i+1]); } while (++j<M*eBands[i+1]);
} else {
j=M*eBands[i]; do {
X[j+c*N] = SHL32(MULT16_32_Q15(g, freq[j+c*N]),-shift);
} while (++j<M*eBands[i+1]);
}
} while (++i<end); } while (++i<end);
} while (++c<C); } while (++c<C);
} }
@@ -194,7 +207,7 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
/* De-normalise the energy to produce the synthesis from the unit-energy bands */ /* De-normalise the energy to produce the synthesis from the unit-energy bands */
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
celt_sig * OPUS_RESTRICT freq, const opus_val16 *bandLogE, int start, celt_sig * OPUS_RESTRICT freq, const celt_glog *bandLogE, int start,
int end, int M, int downsample, int silence) int end, int M, int downsample, int silence)
{ {
int i, N; int i, N;
@@ -218,26 +231,26 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
for (i=start;i<end;i++) for (i=start;i<end;i++)
{ {
int j, band_end; int j, band_end;
opus_val16 g; opus_val32 g;
opus_val16 lg; celt_glog lg;
#ifdef FIXED_POINT #ifdef FIXED_POINT
int shift; int shift;
#endif #endif
j=M*eBands[i]; j=M*eBands[i];
band_end = M*eBands[i+1]; band_end = M*eBands[i+1];
lg = SATURATE16(ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],6))); lg = ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],DB_SHIFT-4));
#ifndef FIXED_POINT #ifndef FIXED_POINT
g = celt_exp2(MIN32(32.f, lg)); g = celt_exp2_db(MIN32(32.f, lg));
#else #else
/* Handle the integer part of the log energy */ /* Handle the integer part of the log energy */
shift = 16-(lg>>DB_SHIFT); shift = 15-(lg>>DB_SHIFT);
if (shift>31) if (shift>31)
{ {
shift=0; shift=0;
g=0; g=0;
} else { } else {
/* Handle the fractional part. */ /* Handle the fractional part. */
g = celt_exp2_frac(lg&((1<<DB_SHIFT)-1)); g = celt_exp2_db_frac((lg&((1<<DB_SHIFT)-1)));
} }
/* Handle extreme gains with negative shift. */ /* Handle extreme gains with negative shift. */
if (shift<0) if (shift<0)
@@ -247,17 +260,17 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
This shouldn't trigger unless the bitstream is already corrupted. */ This shouldn't trigger unless the bitstream is already corrupted. */
if (shift <= -2) if (shift <= -2)
{ {
g = 16384; g = 16384*32768;
shift = -2; shift = -2;
} }
do { do {
*f++ = SHL32(MULT16_16(*x++, g), -shift); *f++ = SHL32(MULT16_32_Q15(*x++, g), -shift);
} while (++j<band_end); } while (++j<band_end);
} else } else
#endif #endif
/* Be careful of the fixed-point "else" just above when changing this code */ /* Be careful of the fixed-point "else" just above when changing this code */
do { do {
*f++ = SHR32(MULT16_16(*x++, g), shift); *f++ = SHR32(MULT16_32_Q15(*x++, g), shift);
} while (++j<band_end); } while (++j<band_end);
} }
celt_assert(start <= end); celt_assert(start <= end);
@@ -266,8 +279,8 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
/* This prevents energy collapse for transients with multiple short MDCTs */ /* This prevents energy collapse for transients with multiple short MDCTs */
void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size, void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
int start, int end, const opus_val16 *logE, const opus_val16 *prev1logE, int start, int end, const celt_glog *logE, const celt_glog *prev1logE,
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, int encode, int arch) const celt_glog *prev2logE, const int *pulses, opus_uint32 seed, int encode, int arch)
{ {
int c, i, j, k; int c, i, j, k;
for (i=start;i<end;i++) for (i=start;i<end;i++)
@@ -303,8 +316,8 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
c=0; do c=0; do
{ {
celt_norm *X; celt_norm *X;
opus_val16 prev1; celt_glog prev1;
opus_val16 prev2; celt_glog prev2;
opus_val32 Ediff; opus_val32 Ediff;
opus_val16 r; opus_val16 r;
int renormalize=0; int renormalize=0;
@@ -312,16 +325,16 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
prev2 = prev2logE[c*m->nbEBands+i]; prev2 = prev2logE[c*m->nbEBands+i];
if (!encode && C==1) if (!encode && C==1)
{ {
prev1 = MAX16(prev1,prev1logE[m->nbEBands+i]); prev1 = MAXG(prev1,prev1logE[m->nbEBands+i]);
prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]); prev2 = MAXG(prev2,prev2logE[m->nbEBands+i]);
} }
Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2)); Ediff = logE[c*m->nbEBands+i]-MING(prev1,prev2);
Ediff = MAX32(0, Ediff); Ediff = MAX32(0, Ediff);
#ifdef FIXED_POINT #ifdef FIXED_POINT
if (Ediff < 16384) if (Ediff < GCONST(16.f))
{ {
opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(Ediff)),1); opus_val32 r32 = SHR32(celt_exp2_db(-Ediff),1);
r = 2*MIN16(16383,r32); r = 2*MIN16(16383,r32);
} else { } else {
r = 0; r = 0;
@@ -333,7 +346,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
#else #else
/* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because /* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because
short blocks don't have the same energy as long */ short blocks don't have the same energy as long */
r = 2.f*celt_exp2(-Ediff); r = 2.f*celt_exp2_db(-Ediff);
if (LM==3) if (LM==3)
r *= 1.41421356f; r *= 1.41421356f;
r = MIN16(thresh, r); r = MIN16(thresh, r);
@@ -356,7 +369,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
} }
/* We just added some energy, so we need to renormalise */ /* We just added some energy, so we need to renormalise */
if (renormalize) if (renormalize)
renormalise_vector(X, N0<<LM, Q15ONE, arch); renormalise_vector(X, N0<<LM, Q31ONE, arch);
} while (++c<C); } while (++c<C);
} }
} }
@@ -423,12 +436,11 @@ static void stereo_split(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
} }
} }
static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val16 mid, int N, int arch) static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val32 mid, int N, int arch)
{ {
int j; int j;
opus_val32 xp=0, side=0; opus_val32 xp=0, side=0;
opus_val32 El, Er; opus_val32 El, Er;
opus_val16 mid2;
#ifdef FIXED_POINT #ifdef FIXED_POINT
int kl, kr; int kl, kr;
#endif #endif
@@ -437,11 +449,10 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
/* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */ /* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
dual_inner_prod(Y, X, Y, N, &xp, &side, arch); dual_inner_prod(Y, X, Y, N, &xp, &side, arch);
/* Compensating for the mid normalization */ /* Compensating for the mid normalization */
xp = MULT16_32_Q15(mid, xp); xp = MULT32_32_Q31(mid, xp);
/* mid and side are in Q15, not Q14 like X and Y */ /* mid and side are in Q15, not Q14 like X and Y */
mid2 = SHR16(mid, 1); El = SHR32(MULT32_32_Q31(mid, mid),3) + side - 2*xp;
El = MULT16_16(mid2, mid2) + side - 2*xp; Er = SHR32(MULT32_32_Q31(mid, mid),3) + side + 2*xp;
Er = MULT16_16(mid2, mid2) + side + 2*xp;
if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28)) if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28))
{ {
OPUS_COPY(Y, X, N); OPUS_COPY(Y, X, N);
@@ -468,7 +479,7 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
{ {
celt_norm r, l; celt_norm r, l;
/* Apply mid scaling (side is already scaled) */ /* Apply mid scaling (side is already scaled) */
l = MULT16_16_P15(mid, X[j]); l = MULT32_32_Q31(mid, X[j]);
r = Y[j]; r = Y[j];
X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, SUB16(l,r)), kl+1)); X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, SUB16(l,r)), kl+1));
Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, ADD16(l,r)), kr+1)); Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, ADD16(l,r)), kr+1));
@@ -943,14 +954,14 @@ static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X, static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
int N, int b, int B, celt_norm *lowband, int N, int b, int B, celt_norm *lowband,
int LM, int LM,
opus_val16 gain, int fill) opus_val32 gain, int fill)
{ {
const unsigned char *cache; const unsigned char *cache;
int q; int q;
int curr_bits; int curr_bits;
int imid=0, iside=0; int imid=0, iside=0;
int B0=B; int B0=B;
opus_val16 mid=0, side=0; opus_val32 mid=0, side=0;
unsigned cm=0; unsigned cm=0;
celt_norm *Y=NULL; celt_norm *Y=NULL;
int encode; int encode;
@@ -990,8 +1001,8 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
itheta = sctx.itheta; itheta = sctx.itheta;
qalloc = sctx.qalloc; qalloc = sctx.qalloc;
#ifdef FIXED_POINT #ifdef FIXED_POINT
mid = imid; mid = SHL32(EXTEND32(imid), 16);
side = iside; side = SHL32(EXTEND32(iside), 16);
#else #else
mid = (1.f/32768)*imid; mid = (1.f/32768)*imid;
side = (1.f/32768)*iside; side = (1.f/32768)*iside;
@@ -1018,20 +1029,20 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
if (mbits >= sbits) if (mbits >= sbits)
{ {
cm = quant_partition(ctx, X, N, mbits, B, lowband, LM, cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
MULT16_16_P15(gain,mid), fill); MULT32_32_Q31(gain,mid), fill);
rebalance = mbits - (rebalance-ctx->remaining_bits); rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0) if (rebalance > 3<<BITRES && itheta!=0)
sbits += rebalance - (3<<BITRES); sbits += rebalance - (3<<BITRES);
cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM, cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); MULT32_32_Q31(gain,side), fill>>B)<<(B0>>1);
} else { } else {
cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM, cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); MULT32_32_Q31(gain,side), fill>>B)<<(B0>>1);
rebalance = sbits - (rebalance-ctx->remaining_bits); rebalance = sbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=16384) if (rebalance > 3<<BITRES && itheta!=16384)
mbits += rebalance - (3<<BITRES); mbits += rebalance - (3<<BITRES);
cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM, cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
MULT16_16_P15(gain,mid), fill); MULT32_32_Q31(gain,mid), fill);
} }
} else { } else {
/* This is the basic no-split case */ /* This is the basic no-split case */
@@ -1109,7 +1120,7 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
static unsigned quant_band(struct band_ctx *ctx, celt_norm *X, static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
int N, int b, int B, celt_norm *lowband, int N, int b, int B, celt_norm *lowband,
int LM, celt_norm *lowband_out, int LM, celt_norm *lowband_out,
opus_val16 gain, celt_norm *lowband_scratch, int fill) opus_val32 gain, celt_norm *lowband_scratch, int fill)
{ {
int N0=N; int N0=N;
int N_B=N; int N_B=N;
@@ -1239,7 +1250,7 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
{ {
int imid=0, iside=0; int imid=0, iside=0;
int inv = 0; int inv = 0;
opus_val16 mid=0, side=0; opus_val32 mid=0, side=0;
unsigned cm=0; unsigned cm=0;
int mbits, sbits, delta; int mbits, sbits, delta;
int itheta; int itheta;
@@ -1268,8 +1279,8 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
itheta = sctx.itheta; itheta = sctx.itheta;
qalloc = sctx.qalloc; qalloc = sctx.qalloc;
#ifdef FIXED_POINT #ifdef FIXED_POINT
mid = imid; mid = SHL32(EXTEND32(imid), 16);
side = iside; side = SHL32(EXTEND32(iside), 16);
#else #else
mid = (1.f/32768)*imid; mid = (1.f/32768)*imid;
side = (1.f/32768)*iside; side = (1.f/32768)*iside;
@@ -1308,7 +1319,7 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
sign = 1-2*sign; sign = 1-2*sign;
/* We use orig_fill here because we want to fold the side, but if /* We use orig_fill here because we want to fold the side, but if
itheta==16384, we'll have cleared the low bits of fill. */ itheta==16384, we'll have cleared the low bits of fill. */
cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE, cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
lowband_scratch, orig_fill); lowband_scratch, orig_fill);
/* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse), /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
and there's no need to worry about mixing with the other channel. */ and there's no need to worry about mixing with the other channel. */
@@ -1317,10 +1328,10 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
if (ctx->resynth) if (ctx->resynth)
{ {
celt_norm tmp; celt_norm tmp;
X[0] = MULT16_16_Q15(mid, X[0]); X[0] = MULT32_32_Q31(mid, X[0]);
X[1] = MULT16_16_Q15(mid, X[1]); X[1] = MULT32_32_Q31(mid, X[1]);
Y[0] = MULT16_16_Q15(side, Y[0]); Y[0] = MULT32_32_Q31(side, Y[0]);
Y[1] = MULT16_16_Q15(side, Y[1]); Y[1] = MULT32_32_Q31(side, Y[1]);
tmp = X[0]; tmp = X[0];
X[0] = SUB16(tmp,Y[0]); X[0] = SUB16(tmp,Y[0]);
Y[0] = ADD16(tmp,Y[0]); Y[0] = ADD16(tmp,Y[0]);
@@ -1341,7 +1352,7 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
{ {
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */ mid for folding later. */
cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE, cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
lowband_scratch, fill); lowband_scratch, fill);
rebalance = mbits - (rebalance-ctx->remaining_bits); rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0) if (rebalance > 3<<BITRES && itheta!=0)
@@ -1359,7 +1370,7 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
mbits += rebalance - (3<<BITRES); mbits += rebalance - (3<<BITRES);
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */ mid for folding later. */
cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE, cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
lowband_scratch, fill); lowband_scratch, fill);
} }
} }
@@ -1573,10 +1584,10 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
{ {
x_cm = quant_band(&ctx, X, N, b/2, B, x_cm = quant_band(&ctx, X, N, b/2, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM, effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm); last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm);
y_cm = quant_band(&ctx, Y, N, b/2, B, y_cm = quant_band(&ctx, Y, N, b/2, B,
effective_lowband != -1 ? norm2+effective_lowband : NULL, LM, effective_lowband != -1 ? norm2+effective_lowband : NULL, LM,
last?NULL:norm2+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, y_cm); last?NULL:norm2+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, y_cm);
} else { } else {
if (Y!=NULL) if (Y!=NULL)
{ {
@@ -1652,7 +1663,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
} else { } else {
x_cm = quant_band(&ctx, X, N, b, B, x_cm = quant_band(&ctx, X, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM, effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm); last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm|y_cm);
} }
y_cm = x_cm; y_cm = x_cm;
} }

View File

@@ -62,7 +62,7 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
* @param bandE Square root of the energy for each band * @param bandE Square root of the energy for each band
*/ */
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
celt_sig * OPUS_RESTRICT freq, const opus_val16 *bandE, int start, celt_sig * OPUS_RESTRICT freq, const celt_glog *bandE, int start,
int end, int M, int downsample, int silence); int end, int M, int downsample, int silence);
#define SPREAD_NONE (0) #define SPREAD_NONE (0)
@@ -112,8 +112,8 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
void anti_collapse(const CELTMode *m, celt_norm *X_, void anti_collapse(const CELTMode *m, celt_norm *X_,
unsigned char *collapse_masks, int LM, int C, int size, int start, unsigned char *collapse_masks, int LM, int C, int size, int start,
int end, const opus_val16 *logE, const opus_val16 *prev1logE, int end, const celt_glog *logE, const celt_glog *prev1logE,
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, const celt_glog *prev2logE, const int *pulses, opus_uint32 seed,
int encode, int arch); int encode, int arch);
opus_uint32 celt_lcg_rand(opus_uint32 seed); opus_uint32 celt_lcg_rand(opus_uint32 seed);

View File

@@ -89,6 +89,7 @@ int resampling_factor(opus_int32 rate)
return ret; return ret;
} }
#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C) #if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
/* This version should be faster on ARM */ /* This version should be faster on ARM */
#ifdef OPUS_ARM_ASM #ifdef OPUS_ARM_ASM
@@ -96,7 +97,7 @@ int resampling_factor(opus_int32 rate)
static static
#endif #endif
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N, void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12) celt_coef g10, celt_coef g11, celt_coef g12)
{ {
opus_val32 x0, x1, x2, x3, x4; opus_val32 x0, x1, x2, x3, x4;
int i; int i;
@@ -108,33 +109,33 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
{ {
opus_val32 t; opus_val32 t;
x0=SHL32(x[i-T+2],1); x0=SHL32(x[i-T+2],1);
t = MAC16_32_Q16(x[i], g10, x2); t = MAC_COEF_32_ARM(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
t = SATURATE(t, SIG_SAT); t = SATURATE(t, SIG_SAT);
y[i] = t; y[i] = t;
x4=SHL32(x[i-T+3],1); x4=SHL32(x[i-T+3],1);
t = MAC16_32_Q16(x[i+1], g10, x1); t = MAC_COEF_32_ARM(x[i+1], g10, x1);
t = MAC16_32_Q16(t, g11, ADD32(x0,x2)); t = MAC_COEF_32_ARM(t, g11, ADD32(x0,x2));
t = MAC16_32_Q16(t, g12, ADD32(x4,x3)); t = MAC_COEF_32_ARM(t, g12, ADD32(x4,x3));
t = SATURATE(t, SIG_SAT); t = SATURATE(t, SIG_SAT);
y[i+1] = t; y[i+1] = t;
x3=SHL32(x[i-T+4],1); x3=SHL32(x[i-T+4],1);
t = MAC16_32_Q16(x[i+2], g10, x0); t = MAC_COEF_32_ARM(x[i+2], g10, x0);
t = MAC16_32_Q16(t, g11, ADD32(x4,x1)); t = MAC_COEF_32_ARM(t, g11, ADD32(x4,x1));
t = MAC16_32_Q16(t, g12, ADD32(x3,x2)); t = MAC_COEF_32_ARM(t, g12, ADD32(x3,x2));
t = SATURATE(t, SIG_SAT); t = SATURATE(t, SIG_SAT);
y[i+2] = t; y[i+2] = t;
x2=SHL32(x[i-T+5],1); x2=SHL32(x[i-T+5],1);
t = MAC16_32_Q16(x[i+3], g10, x4); t = MAC_COEF_32_ARM(x[i+3], g10, x4);
t = MAC16_32_Q16(t, g11, ADD32(x3,x0)); t = MAC_COEF_32_ARM(t, g11, ADD32(x3,x0));
t = MAC16_32_Q16(t, g12, ADD32(x2,x1)); t = MAC_COEF_32_ARM(t, g12, ADD32(x2,x1));
t = SATURATE(t, SIG_SAT); t = SATURATE(t, SIG_SAT);
y[i+3] = t; y[i+3] = t;
x1=SHL32(x[i-T+6],1); x1=SHL32(x[i-T+6],1);
t = MAC16_32_Q16(x[i+4], g10, x3); t = MAC_COEF_32_ARM(x[i+4], g10, x3);
t = MAC16_32_Q16(t, g11, ADD32(x2,x4)); t = MAC_COEF_32_ARM(t, g11, ADD32(x2,x4));
t = MAC16_32_Q16(t, g12, ADD32(x1,x0)); t = MAC_COEF_32_ARM(t, g12, ADD32(x1,x0));
t = SATURATE(t, SIG_SAT); t = SATURATE(t, SIG_SAT);
y[i+4] = t; y[i+4] = t;
} }
@@ -143,9 +144,9 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
{ {
opus_val32 t; opus_val32 t;
x0=SHL32(x[i-T+2],1); x0=SHL32(x[i-T+2],1);
t = MAC16_32_Q16(x[i], g10, x2); t = MAC_COEF_32_ARM(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
t = SATURATE(t, SIG_SAT); t = SATURATE(t, SIG_SAT);
y[i] = t; y[i] = t;
x4=x3; x4=x3;
@@ -160,7 +161,7 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
static static
#endif #endif
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N, void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12) celt_coef g10, celt_coef g11, celt_coef g12)
{ {
opus_val32 x0, x1, x2, x3, x4; opus_val32 x0, x1, x2, x3, x4;
int i; int i;
@@ -172,9 +173,9 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
{ {
x0=x[i-T+2]; x0=x[i-T+2];
y[i] = x[i] y[i] = x[i]
+ MULT16_32_Q15(g10,x2) + MULT_COEF_32(g10,x2)
+ MULT16_32_Q15(g11,ADD32(x1,x3)) + MULT_COEF_32(g11,ADD32(x1,x3))
+ MULT16_32_Q15(g12,ADD32(x0,x4)); + MULT_COEF_32(g12,ADD32(x0,x4));
y[i] = SATURATE(y[i], SIG_SAT); y[i] = SATURATE(y[i], SIG_SAT);
x4=x3; x4=x3;
x3=x2; x3=x2;
@@ -189,11 +190,11 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
#ifndef OVERRIDE_comb_filter #ifndef OVERRIDE_comb_filter
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap, int arch) const celt_coef *window, int overlap, int arch)
{ {
int i; int i;
/* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
opus_val16 g00, g01, g02, g10, g11, g12; celt_coef g00, g01, g02, g10, g11, g12;
opus_val32 x0, x1, x2, x3, x4; opus_val32 x0, x1, x2, x3, x4;
static const opus_val16 gains[3][3] = { static const opus_val16 gains[3][3] = {
{QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)}, {QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
@@ -211,12 +212,12 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
to have then be at least 2 to avoid processing garbage data. */ to have then be at least 2 to avoid processing garbage data. */
T0 = IMAX(T0, COMBFILTER_MINPERIOD); T0 = IMAX(T0, COMBFILTER_MINPERIOD);
T1 = IMAX(T1, COMBFILTER_MINPERIOD); T1 = IMAX(T1, COMBFILTER_MINPERIOD);
g00 = MULT16_16_P15(g0, gains[tapset0][0]); g00 = MULT_COEF_TAPS(g0, gains[tapset0][0]);
g01 = MULT16_16_P15(g0, gains[tapset0][1]); g01 = MULT_COEF_TAPS(g0, gains[tapset0][1]);
g02 = MULT16_16_P15(g0, gains[tapset0][2]); g02 = MULT_COEF_TAPS(g0, gains[tapset0][2]);
g10 = MULT16_16_P15(g1, gains[tapset1][0]); g10 = MULT_COEF_TAPS(g1, gains[tapset1][0]);
g11 = MULT16_16_P15(g1, gains[tapset1][1]); g11 = MULT_COEF_TAPS(g1, gains[tapset1][1]);
g12 = MULT16_16_P15(g1, gains[tapset1][2]); g12 = MULT_COEF_TAPS(g1, gains[tapset1][2]);
x1 = x[-T1+1]; x1 = x[-T1+1];
x2 = x[-T1 ]; x2 = x[-T1 ];
x3 = x[-T1-1]; x3 = x[-T1-1];
@@ -226,16 +227,16 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
overlap=0; overlap=0;
for (i=0;i<overlap;i++) for (i=0;i<overlap;i++)
{ {
opus_val16 f; celt_coef f;
x0=x[i-T1+2]; x0=x[i-T1+2];
f = MULT16_16_Q15(window[i],window[i]); f = MULT_COEF(window[i],window[i]);
y[i] = x[i] y[i] = x[i]
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0]) + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g00),x[i-T0])
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1])) + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2])) + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
+ MULT16_32_Q15(MULT16_16_Q15(f,g10),x2) + MULT_COEF_32(MULT_COEF(f,g10),x2)
+ MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3)) + MULT_COEF_32(MULT_COEF(f,g11),ADD32(x1,x3))
+ MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4)); + MULT_COEF_32(MULT_COEF(f,g12),ADD32(x0,x4));
y[i] = SATURATE(y[i], SIG_SAT); y[i] = SATURATE(y[i], SIG_SAT);
x4=x3; x4=x3;
x3=x2; x3=x2;

View File

@@ -41,6 +41,7 @@
#include "entenc.h" #include "entenc.h"
#include "entdec.h" #include "entdec.h"
#include "arch.h" #include "arch.h"
#include "kiss_fft.h"
#ifdef ENABLE_DEEP_PLC #ifdef ENABLE_DEEP_PLC
#include "lpcnet.h" #include "lpcnet.h"
@@ -83,6 +84,8 @@ typedef struct {
#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr))) #define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
#define __celt_check_glog_ptr(ptr) ((ptr) + ((ptr) - (celt_glog*)(ptr)))
/* Encoder/decoder Requests */ /* Encoder/decoder Requests */
@@ -130,7 +133,7 @@ typedef struct {
#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x) #define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x)
#define OPUS_SET_ENERGY_MASK_REQUEST 10026 #define OPUS_SET_ENERGY_MASK_REQUEST 10026
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x) #define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __celt_check_glog_ptr(x)
#define CELT_SET_SILK_INFO_REQUEST 10028 #define CELT_SET_SILK_INFO_REQUEST 10028
#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x) #define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
@@ -139,7 +142,7 @@ typedef struct {
int celt_encoder_get_size(int channels); int celt_encoder_get_size(int channels);
int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_res * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
int arch); int arch);
@@ -154,14 +157,14 @@ int celt_decoder_get_size(int channels);
int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels); int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
#ifdef ENABLE_DEEP_PLC #ifdef ENABLE_DEEP_PLC
,LPCNetPLCState *lpcnet ,LPCNetPLCState *lpcnet
#endif #endif
); );
int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum); int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum);
#define celt_encoder_ctl opus_custom_encoder_ctl #define celt_encoder_ctl opus_custom_encoder_ctl
#define celt_decoder_ctl opus_custom_decoder_ctl #define celt_decoder_ctl opus_custom_decoder_ctl
@@ -229,19 +232,19 @@ void validate_celt_decoder(CELTDecoder *st);
int resampling_factor(opus_int32 rate); int resampling_factor(opus_int32 rate);
void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip); int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip);
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap, int arch); const celt_coef *window, int overlap, int arch);
void init_caps(const CELTMode *m,int *cap,int LM,int C); void init_caps(const CELTMode *m,int *cap,int LM,int C);
#ifdef RESYNTH #ifdef RESYNTH
void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum); void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum);
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
opus_val16 *oldBandE, int start, int effEnd, int C, int CC, int isTransient, celt_glog *oldBandE, int start, int effEnd, int C, int CC, int isTransient,
int LM, int downsample, int silence, int arch); int LM, int downsample, int silence, int arch);
#endif #endif

View File

@@ -116,10 +116,10 @@ struct OpusCustomDecoder {
celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */ celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
/* opus_val16 lpc[], Size = channels*CELT_LPC_ORDER */ /* opus_val16 lpc[], Size = channels*CELT_LPC_ORDER */
/* opus_val16 oldEBands[], Size = 2*mode->nbEBands */ /* celt_glog oldEBands[], Size = 2*mode->nbEBands */
/* opus_val16 oldLogE[], Size = 2*mode->nbEBands */ /* celt_glog oldLogE[], Size = 2*mode->nbEBands */
/* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */ /* celt_glog oldLogE2[], Size = 2*mode->nbEBands */
/* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ /* celt_glog backgroundLogE[], Size = 2*mode->nbEBands */
}; };
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS) #if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
@@ -171,7 +171,7 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int
int size = sizeof(struct CELTDecoder) int size = sizeof(struct CELTDecoder)
+ (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
+ channels*CELT_LPC_ORDER*sizeof(opus_val16) + channels*CELT_LPC_ORDER*sizeof(opus_val16)
+ 4*2*mode->nbEBands*sizeof(opus_val16); + 4*2*mode->nbEBands*sizeof(celt_glog);
return size; return size;
} }
@@ -246,7 +246,7 @@ void opus_custom_decoder_destroy(CELTDecoder *st)
/* Special case for stereo with no downsampling and no accumulation. This is /* Special case for stereo with no downsampling and no accumulation. This is
quite common and we can make it faster by processing both channels in the quite common and we can make it faster by processing both channels in the
same loop, reducing overhead due to the dependency loop in the IIR filter. */ same loop, reducing overhead due to the dependency loop in the IIR filter. */
static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0, static void deemphasis_stereo_simple(celt_sig *in[], opus_res *pcm, int N, const opus_val16 coef0,
celt_sig *mem) celt_sig *mem)
{ {
celt_sig * OPUS_RESTRICT x0; celt_sig * OPUS_RESTRICT x0;
@@ -265,8 +265,8 @@ static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, con
tmp1 = SATURATE(x1[j] + VERY_SMALL + m1, SIG_SAT); tmp1 = SATURATE(x1[j] + VERY_SMALL + m1, SIG_SAT);
m0 = MULT16_32_Q15(coef0, tmp0); m0 = MULT16_32_Q15(coef0, tmp0);
m1 = MULT16_32_Q15(coef0, tmp1); m1 = MULT16_32_Q15(coef0, tmp1);
pcm[2*j ] = SCALEOUT(SIG2WORD16(tmp0)); pcm[2*j ] = SIG2RES(tmp0);
pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1)); pcm[2*j+1] = SIG2RES(tmp1);
} }
mem[0] = m0; mem[0] = m0;
mem[1] = m1; mem[1] = m1;
@@ -276,7 +276,7 @@ static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, con
#ifndef RESYNTH #ifndef RESYNTH
static static
#endif #endif
void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef,
celt_sig *mem, int accum) celt_sig *mem, int accum)
{ {
int c; int c;
@@ -292,10 +292,6 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
deemphasis_stereo_simple(in, pcm, N, coef[0], mem); deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
return; return;
} }
#endif
#ifndef FIXED_POINT
(void)accum;
celt_assert(accum==0);
#endif #endif
ALLOC(scratch, N, celt_sig); ALLOC(scratch, N, celt_sig);
coef0 = coef[0]; coef0 = coef[0];
@@ -303,7 +299,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
c=0; do { c=0; do {
int j; int j;
celt_sig * OPUS_RESTRICT x; celt_sig * OPUS_RESTRICT x;
opus_val16 * OPUS_RESTRICT y; opus_res * OPUS_RESTRICT y;
celt_sig m = mem[c]; celt_sig m = mem[c];
x =in[c]; x =in[c];
y = pcm+c; y = pcm+c;
@@ -335,23 +331,21 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
apply_downsampling=1; apply_downsampling=1;
} else { } else {
/* Shortcut for the standard (non-custom modes) case */ /* Shortcut for the standard (non-custom modes) case */
#ifdef FIXED_POINT
if (accum) if (accum)
{ {
for (j=0;j<N;j++) for (j=0;j<N;j++)
{ {
celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT); celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
m = MULT16_32_Q15(coef0, tmp); m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp)))); y[j*C] = ADD_RES(y[j*C], SIG2RES(tmp));
} }
} else } else
#endif
{ {
for (j=0;j<N;j++) for (j=0;j<N;j++)
{ {
celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT); celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
m = MULT16_32_Q15(coef0, tmp); m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SCALEOUT(SIG2WORD16(tmp)); y[j*C] = SIG2RES(tmp);
} }
} }
} }
@@ -360,16 +354,14 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
if (apply_downsampling) if (apply_downsampling)
{ {
/* Perform down-sampling */ /* Perform down-sampling */
#ifdef FIXED_POINT
if (accum) if (accum)
{ {
for (j=0;j<Nd;j++) for (j=0;j<Nd;j++)
y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample])))); y[j*C] = ADD_RES(y[j*C], SIG2RES(scratch[j*downsample]));
} else } else
#endif
{ {
for (j=0;j<Nd;j++) for (j=0;j<Nd;j++)
y[j*C] = SCALEOUT(SIG2WORD16(scratch[j*downsample])); y[j*C] = SIG2RES(scratch[j*downsample]);
} }
} }
} while (++c<C); } while (++c<C);
@@ -380,7 +372,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
static static
#endif #endif
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
opus_val16 *oldBandE, int start, int effEnd, int C, int CC, celt_glog *oldBandE, int start, int effEnd, int C, int CC,
int isTransient, int LM, int downsample, int isTransient, int LM, int downsample,
int silence, int arch) int silence, int arch)
{ {
@@ -543,8 +535,8 @@ static void prefilter_and_fold(CELTDecoder * OPUS_RESTRICT st, int N)
for (i=0;i<overlap/2;i++) for (i=0;i<overlap/2;i++)
{ {
decode_mem[c][DECODE_BUFFER_SIZE-N+i] = decode_mem[c][DECODE_BUFFER_SIZE-N+i] =
MULT16_32_Q15(mode->window[i], etmp[overlap-1-i]) MULT16_32_Q15(COEF2VAL16(mode->window[i]), etmp[overlap-1-i])
+ MULT16_32_Q15(mode->window[overlap-i-1], etmp[i]); + MULT16_32_Q15 (COEF2VAL16(mode->window[overlap-i-1]), etmp[i]);
} }
} while (++c<CC); } while (++c<CC);
} }
@@ -613,7 +605,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
celt_sig *decode_mem[2]; celt_sig *decode_mem[2];
celt_sig *out_syn[2]; celt_sig *out_syn[2];
opus_val16 *lpc; opus_val16 *lpc;
opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
const OpusCustomMode *mode; const OpusCustomMode *mode;
int nbEBands; int nbEBands;
int overlap; int overlap;
@@ -633,7 +625,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N; out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
} while (++c<C); } while (++c<C);
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C); lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C);
oldBandE = lpc+C*CELT_LPC_ORDER; oldBandE = (celt_glog*)(lpc+C*CELT_LPC_ORDER);
oldLogE = oldBandE + 2*nbEBands; oldLogE = oldBandE + 2*nbEBands;
oldLogE2 = oldLogE + 2*nbEBands; oldLogE2 = oldLogE + 2*nbEBands;
backgroundLogE = oldLogE2 + 2*nbEBands; backgroundLogE = oldLogE2 + 2*nbEBands;
@@ -652,7 +644,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
opus_uint32 seed; opus_uint32 seed;
int end; int end;
int effEnd; int effEnd;
opus_val16 decay; celt_glog decay;
end = st->end; end = st->end;
effEnd = IMAX(start, IMIN(end, mode->effEBands)); effEnd = IMAX(start, IMIN(end, mode->effEBands));
@@ -667,11 +659,11 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
} }
/* Energy decay */ /* Energy decay */
decay = loss_duration==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); decay = loss_duration==0 ? GCONST(1.5f) : GCONST(.5f);
c=0; do c=0; do
{ {
for (i=start;i<end;i++) for (i=start;i<end;i++)
oldBandE[c*nbEBands+i] = MAX16(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay); oldBandE[c*nbEBands+i] = MAXG(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
} while (++c<C); } while (++c<C);
seed = st->rng; seed = st->rng;
for (c=0;c<C;c++) for (c=0;c<C;c++)
@@ -688,7 +680,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
seed = celt_lcg_rand(seed); seed = celt_lcg_rand(seed);
X[boffs+j] = (celt_norm)((opus_int32)seed>>20); X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
} }
renormalise_vector(X+boffs, blen, Q15ONE, st->arch); renormalise_vector(X+boffs, blen, Q31ONE, st->arch);
} }
} }
st->rng = seed; st->rng = seed;
@@ -700,7 +692,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
} else { } else {
int exc_length; int exc_length;
/* Pitch-based PLC */ /* Pitch-based PLC */
const opus_val16 *window; const celt_coef *window;
opus_val16 *exc; opus_val16 *exc;
opus_val16 fade = Q15ONE; opus_val16 fade = Q15ONE;
int pitch_index; int pitch_index;
@@ -888,7 +880,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
for (i=0;i<overlap;i++) for (i=0;i<overlap;i++)
{ {
opus_val16 tmp_g = Q15ONE opus_val16 tmp_g = Q15ONE
- MULT16_16_Q15(window[i], Q15ONE-ratio); - MULT16_16_Q15(COEF2VAL16(window[i]), Q15ONE-ratio);
buf[DECODE_BUFFER_SIZE-N+i] = buf[DECODE_BUFFER_SIZE-N+i] =
MULT16_32_Q15(tmp_g, buf[DECODE_BUFFER_SIZE-N+i]); MULT16_32_Q15(tmp_g, buf[DECODE_BUFFER_SIZE-N+i]);
} }
@@ -968,7 +960,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
} }
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
#ifdef ENABLE_DEEP_PLC #ifdef ENABLE_DEEP_PLC
,LPCNetPLCState *lpcnet ,LPCNetPLCState *lpcnet
#endif #endif
@@ -989,7 +981,7 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
celt_sig *decode_mem[2]; celt_sig *decode_mem[2];
celt_sig *out_syn[2]; celt_sig *out_syn[2];
opus_val16 *lpc; opus_val16 *lpc;
opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
int shortBlocks; int shortBlocks;
int isTransient; int isTransient;
@@ -1018,7 +1010,7 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
int nbEBands; int nbEBands;
int overlap; int overlap;
const opus_int16 *eBands; const opus_int16 *eBands;
opus_val16 max_background_increase; celt_glog max_background_increase;
ALLOC_STACK; ALLOC_STACK;
VALIDATE_CELT_DECODER(st); VALIDATE_CELT_DECODER(st);
@@ -1031,7 +1023,7 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
frame_size *= st->downsample; frame_size *= st->downsample;
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC); lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC);
oldBandE = lpc+CC*CELT_LPC_ORDER; oldBandE = (celt_glog*)(lpc+CC*CELT_LPC_ORDER);
oldLogE = oldBandE + 2*nbEBands; oldLogE = oldBandE + 2*nbEBands;
oldLogE2 = oldLogE + 2*nbEBands; oldLogE2 = oldLogE + 2*nbEBands;
backgroundLogE = oldLogE2 + 2*nbEBands; backgroundLogE = oldLogE2 + 2*nbEBands;
@@ -1114,7 +1106,7 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
if (C==1) if (C==1)
{ {
for (i=0;i<nbEBands;i++) for (i=0;i<nbEBands;i++)
oldBandE[i]=MAX16(oldBandE[i],oldBandE[nbEBands+i]); oldBandE[i]=MAXG(oldBandE[i],oldBandE[nbEBands+i]);
} }
total_bits = len*8; total_bits = len*8;
@@ -1171,13 +1163,13 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
if (!intra_ener && st->loss_duration != 0) { if (!intra_ener && st->loss_duration != 0) {
c=0; do c=0; do
{ {
opus_val16 safety = 0; celt_glog safety = 0;
int missing = IMIN(10, st->loss_duration>>LM); int missing = IMIN(10, st->loss_duration>>LM);
if (LM==0) safety = QCONST16(1.5f,DB_SHIFT); if (LM==0) safety = GCONST(1.5f);
else if (LM==1) safety = QCONST16(.5f,DB_SHIFT); else if (LM==1) safety = GCONST(.5f);
for (i=start;i<end;i++) for (i=start;i<end;i++)
{ {
if (oldBandE[c*nbEBands+i] < MAX16(oldLogE[c*nbEBands+i], oldLogE2[c*nbEBands+i])) { if (oldBandE[c*nbEBands+i] < MAXG(oldLogE[c*nbEBands+i], oldLogE2[c*nbEBands+i])) {
/* If energy is going down already, continue the trend. */ /* If energy is going down already, continue the trend. */
opus_val32 slope; opus_val32 slope;
opus_val32 E0, E1, E2; opus_val32 E0, E1, E2;
@@ -1185,11 +1177,12 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
E1 = oldLogE[c*nbEBands+i]; E1 = oldLogE[c*nbEBands+i];
E2 = oldLogE2[c*nbEBands+i]; E2 = oldLogE2[c*nbEBands+i];
slope = MAX32(E1 - E0, HALF32(E2 - E0)); slope = MAX32(E1 - E0, HALF32(E2 - E0));
slope = MING(slope, GCONST(2.f));
E0 -= MAX32(0, (1+missing)*slope); E0 -= MAX32(0, (1+missing)*slope);
oldBandE[c*nbEBands+i] = MAX32(-QCONST16(20.f,DB_SHIFT), E0); oldBandE[c*nbEBands+i] = MAX32(-GCONST(20.f), E0);
} else { } else {
/* Otherwise take the min of the last frames. */ /* Otherwise take the min of the last frames. */
oldBandE[c*nbEBands+i] = MIN16(MIN16(oldBandE[c*nbEBands+i], oldLogE[c*nbEBands+i]), oldLogE2[c*nbEBands+i]); oldBandE[c*nbEBands+i] = MING(MING(oldBandE[c*nbEBands+i], oldLogE[c*nbEBands+i]), oldLogE2[c*nbEBands+i]);
} }
/* Shorter frames have more natural fluctuations -- play it safe. */ /* Shorter frames have more natural fluctuations -- play it safe. */
oldBandE[c*nbEBands+i] -= safety; oldBandE[c*nbEBands+i] -= safety;
@@ -1291,7 +1284,7 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
if (silence) if (silence)
{ {
for (i=0;i<C*nbEBands;i++) for (i=0;i<C*nbEBands;i++)
oldBandE[i] = -QCONST16(28.f,DB_SHIFT); oldBandE[i] = -GCONST(28.f);
} }
if (st->prefilter_and_fold) { if (st->prefilter_and_fold) {
prefilter_and_fold(st, N); prefilter_and_fold(st, N);
@@ -1333,26 +1326,26 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
OPUS_COPY(oldLogE, oldBandE, 2*nbEBands); OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
} else { } else {
for (i=0;i<2*nbEBands;i++) for (i=0;i<2*nbEBands;i++)
oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]); oldLogE[i] = MING(oldLogE[i], oldBandE[i]);
} }
/* In normal circumstances, we only allow the noise floor to increase by /* In normal circumstances, we only allow the noise floor to increase by
up to 2.4 dB/second, but when we're in DTX we give the weight of up to 2.4 dB/second, but when we're in DTX we give the weight of
all missing packets to the update packet. */ all missing packets to the update packet. */
max_background_increase = IMIN(160, st->loss_duration+M)*QCONST16(0.001f,DB_SHIFT); max_background_increase = IMIN(160, st->loss_duration+M)*GCONST(0.001f);
for (i=0;i<2*nbEBands;i++) for (i=0;i<2*nbEBands;i++)
backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]); backgroundLogE[i] = MING(backgroundLogE[i] + max_background_increase, oldBandE[i]);
/* In case start or end were to change */ /* In case start or end were to change */
c=0; do c=0; do
{ {
for (i=0;i<start;i++) for (i=0;i<start;i++)
{ {
oldBandE[c*nbEBands+i]=0; oldBandE[c*nbEBands+i]=0;
oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
} }
for (i=end;i<nbEBands;i++) for (i=end;i<nbEBands;i++)
{ {
oldBandE[c*nbEBands+i]=0; oldBandE[c*nbEBands+i]=0;
oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
} }
} while (++c<2); } while (++c<2);
st->rng = dec->rng; st->rng = dec->rng;
@@ -1369,7 +1362,7 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
} }
int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum) int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
{ {
return celt_decode_with_ec_dred(st, data, len, pcm, frame_size, dec, accum return celt_decode_with_ec_dred(st, data, len, pcm, frame_size, dec, accum
#ifdef ENABLE_DEEP_PLC #ifdef ENABLE_DEEP_PLC
@@ -1380,47 +1373,77 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
#ifdef FIXED_POINT #if defined(FIXED_POINT) && !defined(ENABLE_RES24)
int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size) int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
{ {
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0); return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
} }
#else
int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
{
int j, ret, C, N;
VARDECL(opus_res, out);
ALLOC_STACK;
if (pcm==NULL)
return OPUS_BAD_ARG;
C = st->channels;
N = frame_size;
ALLOC(out, C*N, opus_res);
ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
if (ret>0)
for (j=0;j<C*ret;j++)
pcm[j]=RES2INT16(out[j]);
RESTORE_STACK;
return ret;
}
#endif
#if defined(FIXED_POINT) && defined(ENABLE_RES24)
int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
{
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
}
#else
int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
{
int j, ret, C, N;
VARDECL(opus_res, out);
ALLOC_STACK;
if (pcm==NULL)
return OPUS_BAD_ARG;
C = st->channels;
N = frame_size;
ALLOC(out, C*N, opus_res);
ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
if (ret>0)
for (j=0;j<C*ret;j++)
pcm[j]=RES2INT24(out[j]);
RESTORE_STACK;
return ret;
}
#endif
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{
int j, ret, C, N;
VARDECL(opus_int16, out);
ALLOC_STACK;
if (pcm==NULL)
return OPUS_BAD_ARG;
C = st->channels;
N = frame_size;
ALLOC(out, C*N, opus_int16);
ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
if (ret>0)
for (j=0;j<C*ret;j++)
pcm[j]=out[j]*(1.f/32768.f);
RESTORE_STACK;
return ret;
}
#endif /* DISABLE_FLOAT_API */
#else
# if !defined(FIXED_POINT)
int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size) int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{ {
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0); return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
} }
# else
int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size) int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
{ {
int j, ret, C, N; int j, ret, C, N;
VARDECL(celt_sig, out); VARDECL(opus_res, out);
ALLOC_STACK; ALLOC_STACK;
if (pcm==NULL) if (pcm==NULL)
@@ -1428,19 +1451,20 @@ int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data
C = st->channels; C = st->channels;
N = frame_size; N = frame_size;
ALLOC(out, C*N, celt_sig);
ALLOC(out, C*N, opus_res);
ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0); ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
if (ret>0) if (ret>0)
for (j=0;j<C*ret;j++) for (j=0;j<C*ret;j++)
pcm[j] = FLOAT2INT16 (out[j]); pcm[j]=RES2FLOAT(out[j]);
RESTORE_STACK; RESTORE_STACK;
return ret; return ret;
} }
# endif
#endif #endif
#endif /* CUSTOM_MODES */ #endif /* CUSTOM_MODES */
int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...) int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
@@ -1514,16 +1538,17 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
case OPUS_RESET_STATE: case OPUS_RESET_STATE:
{ {
int i; int i;
opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2; opus_val16 *lpc;
celt_glog *oldBandE, *oldLogE, *oldLogE2;
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels); lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels);
oldBandE = lpc+st->channels*CELT_LPC_ORDER; oldBandE = (celt_glog*)(lpc+st->channels*CELT_LPC_ORDER);
oldLogE = oldBandE + 2*st->mode->nbEBands; oldLogE = oldBandE + 2*st->mode->nbEBands;
oldLogE2 = oldLogE + 2*st->mode->nbEBands; oldLogE2 = oldLogE + 2*st->mode->nbEBands;
OPUS_CLEAR((char*)&st->DECODER_RESET_START, OPUS_CLEAR((char*)&st->DECODER_RESET_START,
opus_custom_decoder_get_size(st->mode, st->channels)- opus_custom_decoder_get_size(st->mode, st->channels)-
((char*)&st->DECODER_RESET_START - (char*)st)); ((char*)&st->DECODER_RESET_START - (char*)st));
for (i=0;i<2*st->mode->nbEBands;i++) for (i=0;i<2*st->mode->nbEBands;i++)
oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); oldLogE[i]=oldLogE2[i]=-GCONST(28.f);
st->skip_plc = 1; st->skip_plc = 1;
} }
break; break;

File diff suppressed because it is too large Load Diff

View File

@@ -277,7 +277,7 @@ void celt_iir(const opus_val32 *_x,
int _celt_autocorr( int _celt_autocorr(
const opus_val16 *x, /* in: [0...n-1] samples x */ const opus_val16 *x, /* in: [0...n-1] samples x */
opus_val32 *ac, /* out: [0...lag-1] ac values */ opus_val32 *ac, /* out: [0...lag-1] ac values */
const opus_val16 *window, const celt_coef *window,
int overlap, int overlap,
int lag, int lag,
int n, int n,
@@ -302,8 +302,9 @@ int _celt_autocorr(
xx[i] = x[i]; xx[i] = x[i];
for (i=0;i<overlap;i++) for (i=0;i<overlap;i++)
{ {
xx[i] = MULT16_16_Q15(x[i],window[i]); opus_val16 w = COEF2VAL16(window[i]);
xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); xx[i] = MULT16_16_Q15(x[i],w);
xx[n-i-1] = MULT16_16_Q15(x[n-i-1],w);
} }
xptr = xx; xptr = xx;
} }

View File

@@ -61,6 +61,6 @@ void celt_iir(const opus_val32 *x,
int arch); int arch);
int _celt_autocorr(const opus_val16 *x, opus_val32 *ac, int _celt_autocorr(const opus_val16 *x, opus_val32 *ac,
const opus_val16 *window, int overlap, int lag, int n, int arch); const celt_coef *window, int overlap, int lag, int n, int arch);
#endif /* PLC_H */ #endif /* PLC_H */

View File

@@ -43,6 +43,7 @@ extern opus_int64 celt_mips;
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b)) #define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15)) #define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ /** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16)) #define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
@@ -50,7 +51,9 @@ extern opus_int64 celt_mips;
#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16) #define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits)))) #define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits)))) #define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val64)1)<<(bits))))
#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits))))
#define GCONST(x) GCONST2((x),DB_SHIFT)
#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)

View File

@@ -71,11 +71,24 @@
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15)) #define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15))
#endif #endif
/** 32x32 multiplication, followed by a 32-bit shift right. Results fits in 32 bits */
#if OPUS_FAST_INT64
#define MULT32_32_Q32(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),32))
#else
#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
#endif
/** Compile-time conversion of float constant to 16-bit value */ /** Compile-time conversion of float constant to 16-bit value */
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits)))) #define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
/** Compile-time conversion of float constant to 32-bit value */ /** Compile-time conversion of float constant to 32-bit value */
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits)))) #define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_int64)1)<<(bits))))
/** Compile-time conversion of float constant to log gain value */
#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits))))
/** Compile-time conversion of float constant to DB_SHFIT log gain value */
#define GCONST(x) GCONST2((x),DB_SHIFT)
/** Negate a 16-bit value */ /** Negate a 16-bit value */
#define NEG16(x) (-(x)) #define NEG16(x) (-(x))

View File

@@ -41,6 +41,10 @@
#include "mathops.h" #include "mathops.h"
#include "stack_alloc.h" #include "stack_alloc.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
/* The guts header contains all the multiplication and addition macros that are defined for /* The guts header contains all the multiplication and addition macros that are defined for
complex numbers. It also delares the kf_ internal functions. complex numbers. It also delares the kf_ internal functions.
*/ */
@@ -70,8 +74,8 @@ static void kf_bfly2(
} else } else
#endif #endif
{ {
opus_val16 tw; celt_coef tw;
tw = QCONST16(0.7071067812f, 15); tw = QCONST32(0.7071067812f, COEF_SHIFT-1);
/* We know that m==4 here because the radix-2 is just after a radix-4 */ /* We know that m==4 here because the radix-2 is just after a radix-4 */
celt_assert(m==4); celt_assert(m==4);
for (i=0;i<N;i++) for (i=0;i<N;i++)
@@ -192,7 +196,7 @@ static void kf_bfly3(
kiss_fft_cpx * Fout_beg = Fout; kiss_fft_cpx * Fout_beg = Fout;
#ifdef FIXED_POINT #ifdef FIXED_POINT
/*epi3.r = -16384;*/ /* Unused */ /*epi3.r = -16384;*/ /* Unused */
epi3.i = -28378; epi3.i = -QCONST32(0.86602540f, COEF_SHIFT-1);
#else #else
epi3 = st->twiddles[fstride*m]; epi3 = st->twiddles[fstride*m];
#endif #endif
@@ -249,10 +253,10 @@ static void kf_bfly5(
kiss_fft_cpx * Fout_beg = Fout; kiss_fft_cpx * Fout_beg = Fout;
#ifdef FIXED_POINT #ifdef FIXED_POINT
ya.r = 10126; ya.r = QCONST32(0.30901699f, COEF_SHIFT-1);
ya.i = -31164; ya.i = -QCONST32(0.95105652f, COEF_SHIFT-1);
yb.r = -26510; yb.r = -QCONST32(0.80901699f, COEF_SHIFT-1);
yb.i = -19261; yb.i = -QCONST32(0.58778525f, COEF_SHIFT-1);
#else #else
ya = st->twiddles[fstride*m]; ya = st->twiddles[fstride*m];
yb = st->twiddles[fstride*2*m]; yb = st->twiddles[fstride*2*m];
@@ -412,7 +416,12 @@ static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
#ifdef FIXED_POINT #ifdef FIXED_POINT
for (i=0;i<nfft;++i) { for (i=0;i<nfft;++i) {
opus_val32 phase = -i; opus_val32 phase = -i;
#ifdef ENABLE_QEXT
twiddles[i].r = floor(.5+2147483647*cos((2*M_PI/nfft)*phase));
twiddles[i].i = floor(.5+2147483647*sin((2*M_PI/nfft)*phase));
#else
kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft)); kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
#endif
} }
#else #else
for (i=0;i<nfft;++i) { for (i=0;i<nfft;++i) {
@@ -454,10 +463,17 @@ kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
st->nfft=nfft; st->nfft=nfft;
#ifdef FIXED_POINT #ifdef FIXED_POINT
st->scale_shift = celt_ilog2(st->nfft); st->scale_shift = celt_ilog2(st->nfft);
# ifdef ENABLE_QEXT
if (st->nfft == 1<<st->scale_shift)
st->scale = QCONST32(1.0f, 30);
else
st->scale = (((opus_int64)1073741824<<st->scale_shift)+st->nfft/2)/st->nfft;
# else
if (st->nfft == 1<<st->scale_shift) if (st->nfft == 1<<st->scale_shift)
st->scale = Q15ONE; st->scale = Q15ONE;
else else
st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift);
# endif
#else #else
st->scale = 1.f/nfft; st->scale = 1.f/nfft;
#endif #endif
@@ -569,7 +585,7 @@ void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout)
void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
{ {
int i; int i;
opus_val16 scale; celt_coef scale;
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* Allows us to scale with MULT16_32_Q16(), which is faster than /* Allows us to scale with MULT16_32_Q16(), which is faster than
MULT16_32_Q15() on ARM. */ MULT16_32_Q15() on ARM. */
@@ -582,8 +598,8 @@ void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *f
for (i=0;i<st->nfft;i++) for (i=0;i<st->nfft;i++)
{ {
kiss_fft_cpx x = fin[i]; kiss_fft_cpx x = fin[i];
fout[st->bitrev[i]].r = SHR32(MULT16_32_Q16(scale, x.r), scale_shift); fout[st->bitrev[i]].r = SHR32(S_MUL2(x.r, scale), scale_shift);
fout[st->bitrev[i]].i = SHR32(MULT16_32_Q16(scale, x.i), scale_shift); fout[st->bitrev[i]].i = SHR32(S_MUL2(x.i, scale), scale_shift);
} }
opus_fft_impl(st, fout); opus_fft_impl(st, fout);
} }

View File

@@ -50,7 +50,13 @@ extern "C" {
#include "arch.h" #include "arch.h"
# define kiss_fft_scalar opus_int32 # define kiss_fft_scalar opus_int32
# define kiss_twiddle_scalar opus_int16 # ifdef ENABLE_QEXT
# define COEF_SHIFT 32
# else
# define COEF_SHIFT 16
# endif
# define kiss_twiddle_scalar celt_coef
/* Some 32-bit CPUs would load/store a kiss_twiddle_cpx with a single memory /* Some 32-bit CPUs would load/store a kiss_twiddle_cpx with a single memory
* access, and could benefit from additional alignment. * access, and could benefit from additional alignment.
@@ -58,6 +64,7 @@ extern "C" {
# define KISS_TWIDDLE_CPX_ALIGNMENT (sizeof(opus_int32)) # define KISS_TWIDDLE_CPX_ALIGNMENT (sizeof(opus_int32))
#else #else
# ifndef kiss_fft_scalar # ifndef kiss_fft_scalar
/* default is float */ /* default is float */
# define kiss_fft_scalar float # define kiss_fft_scalar float
@@ -95,7 +102,7 @@ typedef struct arch_fft_state{
typedef struct kiss_fft_state{ typedef struct kiss_fft_state{
int nfft; int nfft;
opus_val16 scale; celt_coef scale;
#ifdef FIXED_POINT #ifdef FIXED_POINT
int scale_shift; int scale_shift;
#endif #endif

View File

@@ -67,7 +67,7 @@ unsigned isqrt32(opus_uint32 _val){
#ifdef FIXED_POINT #ifdef FIXED_POINT
opus_val32 frac_div32(opus_val32 a, opus_val32 b) opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b)
{ {
opus_val16 rcp; opus_val16 rcp;
opus_val32 result, rem; opus_val32 result, rem;
@@ -79,6 +79,11 @@ opus_val32 frac_div32(opus_val32 a, opus_val32 b)
result = MULT16_32_Q15(rcp, a); result = MULT16_32_Q15(rcp, a);
rem = PSHR32(a,2)-MULT32_32_Q31(result, b); rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2)); result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
return result;
}
opus_val32 frac_div32(opus_val32 a, opus_val32 b) {
opus_val32 result = frac_div32_q29(a,b);
if (result >= 536870912) /* 2^29 */ if (result >= 536870912) /* 2^29 */
return 2147483647; /* 2^31 - 1 */ return 2147483647; /* 2^31 - 1 */
else if (result <= -536870912) /* -2^29 */ else if (result <= -536870912) /* -2^29 */
@@ -121,7 +126,10 @@ opus_val32 celt_sqrt(opus_val32 x)
int k; int k;
opus_val16 n; opus_val16 n;
opus_val32 rt; opus_val32 rt;
static const opus_val16 C[5] = {23175, 11561, -3011, 1699, -664}; /* These coeffs are optimized in fixed-point to minimize both RMS and max error
of sqrt(x) over .25<x<1 without exceeding 32767.
The RMS error is 3.4e-5 and the max is 8.2e-5. */
static const opus_val16 C[6] = {23171, 11574, -2901, 1592, -1002, 336};
if (x==0) if (x==0)
return 0; return 0;
else if (x>=1073741824) else if (x>=1073741824)
@@ -129,8 +137,8 @@ opus_val32 celt_sqrt(opus_val32 x)
k = (celt_ilog2(x)>>1)-7; k = (celt_ilog2(x)>>1)-7;
x = VSHR32(x, 2*k); x = VSHR32(x, 2*k);
n = x-32768; n = x-32768;
rt = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], rt = ADD32(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2],
MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, (C[4]))))))))); MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, ADD16(C[4], MULT16_16_Q15(n, (C[5])))))))))));
rt = VSHR32(rt,7-k); rt = VSHR32(rt,7-k);
return rt; return rt;
} }

View File

@@ -1,7 +1,7 @@
/* Copyright (c) 2002-2008 Jean-Marc Valin /* Copyright (c) 2002-2008 Jean-Marc Valin
Copyright (c) 2007-2008 CSIRO Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */ Written by Jean-Marc Valin, and Yunho Huh */
/** /**
@file mathops.h @file mathops.h
@brief Various math functions @brief Various math functions
@@ -91,6 +91,26 @@ static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
} }
#endif #endif
#ifdef ENABLE_RES24
static OPUS_INLINE opus_res celt_maxabs_res(const opus_res *x, int len)
{
int i;
opus_res maxval = 0;
opus_res minval = 0;
for (i=0;i<len;i++)
{
maxval = MAX32(maxval, x[i]);
minval = MIN32(minval, x[i]);
}
/* opus_res should never reach such amplitude, so we should be safe. */
celt_sig_assert(minval != -2147483648);
return MAX32(maxval,-minval);
}
#else
#define celt_maxabs_res celt_maxabs16
#endif
#ifndef OVERRIDE_CELT_MAXABS32 #ifndef OVERRIDE_CELT_MAXABS32
#ifdef FIXED_POINT #ifdef FIXED_POINT
static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len) static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
@@ -120,17 +140,48 @@ static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
#define celt_rcp(x) (1.f/(x)) #define celt_rcp(x) (1.f/(x))
#define celt_div(a,b) ((a)/(b)) #define celt_div(a,b) ((a)/(b))
#define frac_div32(a,b) ((float)(a)/(b)) #define frac_div32(a,b) ((float)(a)/(b))
#define frac_div32_q29(a,b) frac_div32(a,b)
#ifdef FLOAT_APPROX #ifdef FLOAT_APPROX
/* Calculates the base-2 logarithm (log2(x)) of a number. It is designed for
* systems using radix-2 floating-point representation, with the exponent
* located at bits 23 to 30 and an offset of 127. Note that special cases like
* denormalized numbers, positive/negative infinity, and NaN are not handled.
* log2(x) = log2(x^exponent * mantissa)
* = exponent + log2(mantissa) */
/* Note: This assumes radix-2 floating point with the exponent at bits 23..30 and an offset of 127 /* Log2 x normalization single precision coefficients calculated by
denorm, +/- inf and NaN are *not* handled */ * 1 / (1 + 0.125 * index).
* Coefficients in Double Precision
* double log2_x_norm_coeff[8] = {
* 1.0000000000000000000, 8.888888888888888e-01,
* 8.000000000000000e-01, 7.272727272727273e-01,
* 6.666666666666666e-01, 6.153846153846154e-01,
* 5.714285714285714e-01, 5.333333333333333e-01} */
static const float log2_x_norm_coeff[8] = {
1.000000000000000000000000000f, 8.88888895511627197265625e-01f,
8.00000000000000000000000e-01f, 7.27272748947143554687500e-01f,
6.66666686534881591796875e-01f, 6.15384638309478759765625e-01f,
5.71428596973419189453125e-01f, 5.33333361148834228515625e-01f};
/* Log2 y normalization single precision coefficients calculated by
* log2(1 + 0.125 * index).
* Coefficients in Double Precision
* double log2_y_norm_coeff[8] = {
* 0.0000000000000000000, 1.699250014423124e-01,
* 3.219280948873623e-01, 4.594316186372973e-01,
* 5.849625007211562e-01, 7.004397181410922e-01,
* 8.073549220576041e-01, 9.068905956085185e-01}; */
static const float log2_y_norm_coeff[8] = {
0.0000000000000000000000000000f, 1.699250042438507080078125e-01f,
3.219280838966369628906250e-01f, 4.594316184520721435546875e-01f,
5.849624872207641601562500e-01f, 7.004396915435791015625000e-01f,
8.073549270629882812500000e-01f, 9.068905711174011230468750e-01f};
/** Base-2 log approximation (log2(x)). */
static OPUS_INLINE float celt_log2(float x) static OPUS_INLINE float celt_log2(float x)
{ {
int integer; int integer;
float frac; opus_int32 range_idx;
union { union {
float f; float f;
opus_uint32 i; opus_uint32 i;
@@ -138,13 +189,36 @@ static OPUS_INLINE float celt_log2(float x)
in.f = x; in.f = x;
integer = (in.i>>23)-127; integer = (in.i>>23)-127;
in.i -= (opus_uint32)integer<<23; in.i -= (opus_uint32)integer<<23;
frac = in.f - 1.5f;
frac = -0.41445418f + frac*(0.95909232f /* Normalize the mantissa range from [1, 2] to [1,1.125], and then shift x
+ frac*(-0.33951290f + frac*0.16541097f)); * by 1.0625 to [-0.0625, 0.0625]. */
return 1+integer+frac; range_idx = (in.i >> 20) & 0x7;
in.f = in.f * log2_x_norm_coeff[range_idx] - 1.0625f;
/* Polynomial coefficients approximated in the [1, 1.125] range.
* Lolremez command: lolremez --degree 4 --range -0.0625:0.0625
* "log(x+1.0625)/log(2)"
* Coefficients in Double Precision
* A0: 8.7462840624502679e-2 A1: 1.3578296070972002
* A2: -6.3897703690210047e-1 A3: 4.0197125617419959e-1
* A4: -2.8415445877832832e-1 */
#define LOG2_COEFF_A0 8.74628424644470214843750000e-02f
#define LOG2_COEFF_A1 1.357829570770263671875000000000f
#define LOG2_COEFF_A2 -6.3897705078125000000000000e-01f
#define LOG2_COEFF_A3 4.01971250772476196289062500e-01f
#define LOG2_COEFF_A4 -2.8415444493293762207031250e-01f
in.f = LOG2_COEFF_A0 + in.f * (LOG2_COEFF_A1
+ in.f * (LOG2_COEFF_A2
+ in.f * (LOG2_COEFF_A3
+ in.f * (LOG2_COEFF_A4))));
return integer + in.f + log2_y_norm_coeff[range_idx];
} }
/** Base-2 exponential approximation (2^x). */ /* Calculates an approximation of 2^x. The approximation was achieved by
* employing a base-2 exponential function and utilizing a Remez approximation
* of order 5, ensuring a controlled relative error.
* exp2(x) = exp2(integer + fraction)
* = exp2(integer) * exp2(fraction) */
static OPUS_INLINE float celt_exp2(float x) static OPUS_INLINE float celt_exp2(float x)
{ {
int integer; int integer;
@@ -157,9 +231,22 @@ static OPUS_INLINE float celt_exp2(float x)
if (integer < -50) if (integer < -50)
return 0; return 0;
frac = x-integer; frac = x-integer;
/* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */
res.f = 0.99992522f + frac * (0.69583354f /* Polynomial coefficients approximated in the [0, 1] range.
+ frac * (0.22606716f + 0.078024523f*frac)); * Lolremez command: lolremez --degree 5 --range 0:1
* "exp(x*0.693147180559945)" "exp(x*0.693147180559945)"
* NOTE: log(2) ~ 0.693147180559945 */
#define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f
#define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f
#define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f
#define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f
#define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f
#define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f
res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1
+ frac * (EXP2_COEFF_A2
+ frac * (EXP2_COEFF_A3
+ frac * (EXP2_COEFF_A4
+ frac * (EXP2_COEFF_A5)))));
res.i = (res.i + ((opus_uint32)integer<<23)) & 0x7fffffff; res.i = (res.i + ((opus_uint32)integer<<23)) & 0x7fffffff;
return res.f; return res.f;
} }
@@ -169,6 +256,9 @@ static OPUS_INLINE float celt_exp2(float x)
#define celt_exp2(x) ((float)exp(0.6931471805599453094*(x))) #define celt_exp2(x) ((float)exp(0.6931471805599453094*(x)))
#endif #endif
#define celt_exp2_db celt_exp2
#define celt_log2_db celt_log2
#endif #endif
#ifdef FIXED_POINT #ifdef FIXED_POINT
@@ -204,13 +294,13 @@ static OPUS_INLINE opus_val16 celt_log2(opus_val32 x)
opus_val16 n, frac; opus_val16 n, frac;
/* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605, /* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
0.15530808010959576, -0.08556153059057618 */ 0.15530808010959576, -0.08556153059057618 */
static const opus_val16 C[5] = {-6801+(1<<(13-DB_SHIFT)), 15746, -5217, 2545, -1401}; static const opus_val16 C[5] = {-6801+(1<<(13-10)), 15746, -5217, 2545, -1401};
if (x==0) if (x==0)
return -32767; return -32767;
i = celt_ilog2(x); i = celt_ilog2(x);
n = VSHR32(x,i-15)-32768-16384; n = VSHR32(x,i-15)-32768-16384;
frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4])))))))); frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4]))))))));
return SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT); return SHL32(i-13,10)+SHR32(frac,14-10);
} }
/* /*
@@ -250,10 +340,103 @@ static OPUS_INLINE opus_val32 celt_exp2(opus_val16 x)
return VSHR32(EXTEND32(frac), -integer-2); return VSHR32(EXTEND32(frac), -integer-2);
} }
#ifdef ENABLE_QEXT
/* Calculates the base-2 logarithm of a Q14 input value. The result is returned
* in Q(DB_SHIFT). If the input value is 0, the function will output -32.0f. */
static OPUS_INLINE opus_val32 celt_log2_db(opus_val32 x) {
/* Q30 */
static const opus_val32 log2_x_norm_coeff[8] = {
1073741824, 954437184, 858993472, 780903168,
715827904, 660764224, 613566784, 572662336};
/* Q24 */
static const opus_val32 log2_y_norm_coeff[8] = {
0, 2850868, 5401057, 7707983,
9814042, 11751428, 13545168, 15215099};
static const opus_val32 LOG2_COEFF_A0 = 1467383; /* Q24 */
static const opus_val32 LOG2_COEFF_A1 = 182244800; /* Q27 */
static const opus_val32 LOG2_COEFF_A2 = -21440512; /* Q25 */
static const opus_val32 LOG2_COEFF_A3 = 107903336; /* Q28 */
static const opus_val32 LOG2_COEFF_A4 = -610217024; /* Q31 */
opus_int32 integer, norm_coeff_idx, tmp;
opus_val32 mantissa;
if (x==0) {
return -536870912; /* -32.0f */
}
integer = SUB32(celt_ilog2(x), 14); /* Q0 */
mantissa = VSHR32(x, integer + 14 - 29); /* Q29 */
norm_coeff_idx = SHR32(mantissa, 29 - 3) & 0x7;
/* mantissa is in Q28 (29 + Q_NORM_CONST - 31 where Q_NORM_CONST is Q30)
* 285212672 (Q28) is 1.0625f. */
mantissa = SUB32(MULT32_32_Q31(mantissa, log2_x_norm_coeff[norm_coeff_idx]),
285212672);
/* q_a3(Q28): q_mantissa + q_a4 - 31
* q_a2(Q25): q_mantissa + q_a3 - 31
* q_a1(Q27): q_mantissa + q_a2 - 31 + 5
* q_a0(Q24): q_mantissa + q_a1 - 31
* where q_mantissa is Q28 */
/* Split evaluation in steps to avoid exploding macro expansion. */
tmp = MULT32_32_Q31(mantissa, LOG2_COEFF_A4);
tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A3, tmp));
tmp = SHL32(MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A2, tmp)), 5 /* SHL32 for LOG2_COEFF_A1 */);
tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A1, tmp));
return ADD32(log2_y_norm_coeff[norm_coeff_idx],
ADD32(SHL32(integer, DB_SHIFT),
ADD32(LOG2_COEFF_A0, tmp)));
}
/* Calculates exp2 for Q28 within a specific range (0 to 1.0) using fixed-point
* arithmetic. The input number must be adjusted for Q DB_SHIFT. */
static OPUS_INLINE opus_val32 celt_exp2_db_frac(opus_val32 x)
{
/* Approximation constants. */
static const opus_int32 EXP2_COEFF_A0 = 268435440; /* Q28 */
static const opus_int32 EXP2_COEFF_A1 = 744267456; /* Q30 */
static const opus_int32 EXP2_COEFF_A2 = 1031451904; /* Q32 */
static const opus_int32 EXP2_COEFF_A3 = 959088832; /* Q34 */
static const opus_int32 EXP2_COEFF_A4 = 617742720; /* Q36 */
static const opus_int32 EXP2_COEFF_A5 = 516104352; /* Q38 */
opus_int32 tmp;
/* Converts input value from Q24 to Q29. */
opus_val32 x_q29 = SHL32(x, 29 - 24);
/* Split evaluation in steps to avoid exploding macro expansion. */
tmp = ADD32(EXP2_COEFF_A4, MULT32_32_Q31(x_q29, EXP2_COEFF_A5));
tmp = ADD32(EXP2_COEFF_A3, MULT32_32_Q31(x_q29, tmp));
tmp = ADD32(EXP2_COEFF_A2, MULT32_32_Q31(x_q29, tmp));
tmp = ADD32(EXP2_COEFF_A1, MULT32_32_Q31(x_q29, tmp));
return ADD32(EXP2_COEFF_A0, MULT32_32_Q31(x_q29, tmp));
}
/* Calculates exp2 for Q16 using fixed-point arithmetic. The input number must
* be adjusted for Q DB_SHIFT. */
static OPUS_INLINE opus_val32 celt_exp2_db(opus_val32 x)
{
int integer;
opus_val32 frac;
integer = SHR32(x,DB_SHIFT);
if (integer>14)
return 0x7f000000;
else if (integer <= -17)
return 0;
frac = celt_exp2_db_frac(x-SHL32(integer, DB_SHIFT)); /* Q28 */
return VSHR32(frac, -integer + 28 - 16); /* Q16 */
}
#else
#define celt_log2_db(x) SHL32(EXTEND32(celt_log2(x)), DB_SHIFT-10)
#define celt_exp2_db_frac(x) SHL32(celt_exp2_frac(PSHR32(x, DB_SHIFT-10)), 14)
#define celt_exp2_db(x) celt_exp2(PSHR32(x, DB_SHIFT-10))
#endif
opus_val32 celt_rcp(opus_val32 x); opus_val32 celt_rcp(opus_val32 x);
#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b)) #define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b))
opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b);
opus_val32 frac_div32(opus_val32 a, opus_val32 b); opus_val32 frac_div32(opus_val32 a, opus_val32 b);
#define M1 32767 #define M1 32767

View File

@@ -57,6 +57,9 @@
#include "mips/mdct_mipsr1.h" #include "mips/mdct_mipsr1.h"
#endif #endif
#ifndef M_PI
#define M_PI 3.141592653
#endif
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
@@ -86,12 +89,12 @@ int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch)
{ {
/* We have enough points that sine isn't necessary */ /* We have enough points that sine isn't necessary */
#if defined(FIXED_POINT) #if defined(FIXED_POINT)
#if 1 #ifndef ENABLE_QEXT
for (i=0;i<N2;i++) for (i=0;i<N2;i++)
trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2+16384),N)); trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2+16384),N));
#else #else
for (i=0;i<N2;i++) for (i=0;i<N2;i++)
trig[i] = (kiss_twiddle_scalar)MAX32(-32767,MIN32(32767,floor(.5+32768*cos(2*M_PI*(i+.125)/N)))); trig[i] = (kiss_twiddle_scalar)MAX32(-2147483647,MIN32(2147483647,floor(.5+2147483648*cos(2*M_PI*(i+.125)/N))));
#endif #endif
#else #else
for (i=0;i<N2;i++) for (i=0;i<N2;i++)
@@ -117,7 +120,7 @@ void clt_mdct_clear(mdct_lookup *l, int arch)
/* Forward MDCT trashes the input array */ /* Forward MDCT trashes the input array */
#ifndef OVERRIDE_clt_mdct_forward #ifndef OVERRIDE_clt_mdct_forward
void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride, int arch) const celt_coef *window, int overlap, int shift, int stride, int arch)
{ {
int i; int i;
int N, N2, N4; int N, N2, N4;
@@ -125,11 +128,12 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
VARDECL(kiss_fft_cpx, f2); VARDECL(kiss_fft_cpx, f2);
const kiss_fft_state *st = l->kfft[shift]; const kiss_fft_state *st = l->kfft[shift];
const kiss_twiddle_scalar *trig; const kiss_twiddle_scalar *trig;
opus_val16 scale; celt_coef scale;
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* Allows us to scale with MULT16_32_Q16(), which is faster than /* Allows us to scale with MULT16_32_Q16(), which is faster than
MULT16_32_Q15() on ARM. */ MULT16_32_Q15() on ARM. */
int scale_shift = st->scale_shift-1; int scale_shift = st->scale_shift-1;
int headroom;
#endif #endif
SAVE_STACK; SAVE_STACK;
(void)arch; (void)arch;
@@ -155,13 +159,13 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1); const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1); const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
kiss_fft_scalar * OPUS_RESTRICT yp = f; kiss_fft_scalar * OPUS_RESTRICT yp = f;
const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); const celt_coef * OPUS_RESTRICT wp1 = window+(overlap>>1);
const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1; const celt_coef * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
for(i=0;i<((overlap+3)>>2);i++) for(i=0;i<((overlap+3)>>2);i++)
{ {
/* Real part arranged as -d-cR, Imag part arranged as -b+aR*/ /* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
*yp++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2); *yp++ = S_MUL(xp1[N2], *wp2) + S_MUL(*xp2, *wp1);
*yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]); *yp++ = S_MUL(*xp1, *wp1) - S_MUL(xp2[-N2], *wp2);
xp1+=2; xp1+=2;
xp2-=2; xp2-=2;
wp1+=2; wp1+=2;
@@ -180,8 +184,8 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
for(;i<N4;i++) for(;i<N4;i++)
{ {
/* Real part arranged as a-bR, Imag part arranged as -c-dR */ /* Real part arranged as a-bR, Imag part arranged as -c-dR */
*yp++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2); *yp++ = -S_MUL(xp1[-N2], *wp1) + S_MUL(*xp2, *wp2);
*yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]); *yp++ = S_MUL(*xp1, *wp2) + S_MUL(xp2[N2], *wp1);
xp1+=2; xp1+=2;
xp2-=2; xp2-=2;
wp1+=2; wp1+=2;
@@ -192,6 +196,9 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
{ {
kiss_fft_scalar * OPUS_RESTRICT yp = f; kiss_fft_scalar * OPUS_RESTRICT yp = f;
const kiss_twiddle_scalar *t = &trig[0]; const kiss_twiddle_scalar *t = &trig[0];
#ifdef FIXED_POINT
opus_val32 maxval=1;
#endif
for(i=0;i<N4;i++) for(i=0;i<N4;i++)
{ {
kiss_fft_cpx yc; kiss_fft_cpx yc;
@@ -205,10 +212,21 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
yi = S_MUL(im,t0) + S_MUL(re,t1); yi = S_MUL(im,t0) + S_MUL(re,t1);
yc.r = yr; yc.r = yr;
yc.i = yi; yc.i = yi;
yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift); yc.r = S_MUL2(yc.r, scale);
yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift); yc.i = S_MUL2(yc.i, scale);
#ifdef FIXED_POINT
maxval = MAX32(maxval, MAX32(yc.r, yc.i));
#endif
f2[st->bitrev[i]] = yc; f2[st->bitrev[i]] = yc;
} }
#ifdef FIXED_POINT
headroom = IMAX(0, IMIN(scale_shift-1, 28-celt_ilog2(maxval)));
for(i=0;i<N4;i++)
{
f2[i].r = PSHR32(f2[i].r, scale_shift-headroom);
f2[i].i = PSHR32(f2[i].i, scale_shift-headroom);
}
#endif
} }
/* N/4 complex FFT, does not downscale anymore */ /* N/4 complex FFT, does not downscale anymore */
@@ -225,8 +243,8 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
for(i=0;i<N4;i++) for(i=0;i<N4;i++)
{ {
kiss_fft_scalar yr, yi; kiss_fft_scalar yr, yi;
yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]); yr = PSHR32(S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]), headroom);
yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]); yi = PSHR32(S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]), headroom);
*yp1 = yr; *yp1 = yr;
*yp2 = yi; *yp2 = yi;
fp++; fp++;
@@ -240,7 +258,7 @@ void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scal
#ifndef OVERRIDE_clt_mdct_backward #ifndef OVERRIDE_clt_mdct_backward
void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) const celt_coef * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch)
{ {
int i; int i;
int N, N2, N4; int N, N2, N4;
@@ -269,9 +287,12 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
{ {
int rev; int rev;
kiss_fft_scalar yr, yi; kiss_fft_scalar yr, yi;
opus_val32 x1, x2;
rev = *bitrev++; rev = *bitrev++;
yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i])); x1 = SHL32(*xp1, IMDCT_HEADROOM);
yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i])); x2 = SHL32(*xp2, IMDCT_HEADROOM);
yr = ADD32_ovflw(S_MUL(x2, t[i]), S_MUL(x1, t[N4+i]));
yi = SUB32_ovflw(S_MUL(x1, t[i]), S_MUL(x2, t[N4+i]));
/* We swap real and imag because we use an FFT instead of an IFFT. */ /* We swap real and imag because we use an FFT instead of an IFFT. */
yp[2*rev+1] = yr; yp[2*rev+1] = yr;
yp[2*rev] = yi; yp[2*rev] = yi;
@@ -301,8 +322,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
t0 = t[i]; t0 = t[i];
t1 = t[N4+i]; t1 = t[N4+i];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */ /* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)); yr = PSHR32(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), IMDCT_HEADROOM);
yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)); yi = PSHR32(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), IMDCT_HEADROOM);
/* We swap real and imag because we're using an FFT instead of an IFFT. */ /* We swap real and imag because we're using an FFT instead of an IFFT. */
re = yp1[1]; re = yp1[1];
im = yp1[0]; im = yp1[0];
@@ -312,8 +333,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
t0 = t[(N4-i-1)]; t0 = t[(N4-i-1)];
t1 = t[(N2-i-1)]; t1 = t[(N2-i-1)];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */ /* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)); yr = PSHR32(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), IMDCT_HEADROOM);
yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)); yi = PSHR32(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), IMDCT_HEADROOM);
yp1[0] = yr; yp1[0] = yr;
yp0[1] = yi; yp0[1] = yi;
yp0 += 2; yp0 += 2;
@@ -325,16 +346,16 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
{ {
kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1; kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1;
kiss_fft_scalar * OPUS_RESTRICT yp1 = out; kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
const opus_val16 * OPUS_RESTRICT wp1 = window; const celt_coef * OPUS_RESTRICT wp1 = window;
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; const celt_coef * OPUS_RESTRICT wp2 = window+overlap-1;
for(i = 0; i < overlap/2; i++) for(i = 0; i < overlap/2; i++)
{ {
kiss_fft_scalar x1, x2; kiss_fft_scalar x1, x2;
x1 = *xp1; x1 = *xp1;
x2 = *yp1; x2 = *yp1;
*yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1)); *yp1++ = SUB32_ovflw(S_MUL(x2, *wp2), S_MUL(x1, *wp1));
*xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1)); *xp1-- = ADD32_ovflw(S_MUL(x2, *wp1), S_MUL(x1, *wp2));
wp1++; wp1++;
wp2--; wp2--;
} }

View File

@@ -57,6 +57,9 @@ typedef struct {
#include "arm/mdct_arm.h" #include "arm/mdct_arm.h"
#endif #endif
/* There should be 2 bits of headroom in the IMDCT which we can take
advantage of to maximize accuracy. */
#define IMDCT_HEADROOM 2
int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch); int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch);
void clt_mdct_clear(mdct_lookup *l, int arch); void clt_mdct_clear(mdct_lookup *l, int arch);
@@ -64,14 +67,14 @@ void clt_mdct_clear(mdct_lookup *l, int arch);
/** Compute a forward MDCT and scale by 4/N, trashes the input array */ /** Compute a forward MDCT and scale by 4/N, trashes the input array */
void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, const celt_coef *window, int overlap,
int shift, int stride, int arch); int shift, int stride, int arch);
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add /** Compute a backward MDCT (no scaling) and performs weighted overlap-add
(scales implicitly by 1/2) */ (scales implicitly by 1/2) */
void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window, const celt_coef * OPUS_RESTRICT window,
int overlap, int shift, int stride, int arch); int overlap, int shift, int stride, int arch);
#if !defined(OVERRIDE_OPUS_MDCT) #if !defined(OVERRIDE_OPUS_MDCT)
@@ -80,7 +83,7 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in,
extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])( extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(
const mdct_lookup *l, kiss_fft_scalar *in, const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, const opus_val16 *window, kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window,
int overlap, int shift, int stride, int arch); int overlap, int shift, int stride, int arch);
#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \ #define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
@@ -90,7 +93,7 @@ extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(
extern void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])( extern void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(
const mdct_lookup *l, kiss_fft_scalar *in, const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, const opus_val16 *window, kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window,
int overlap, int shift, int stride, int arch); int overlap, int shift, int stride, int arch);
#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \ #define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \

View File

@@ -230,7 +230,7 @@ CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
CELTMode *mode=NULL; CELTMode *mode=NULL;
int res; int res;
opus_val16 *window; celt_coef *window;
opus_int16 *logN; opus_int16 *logN;
int LM; int LM;
int arch = opus_select_arch(); int arch = opus_select_arch();
@@ -370,16 +370,21 @@ CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
if (mode->allocVectors==NULL) if (mode->allocVectors==NULL)
goto failure; goto failure;
window = (opus_val16*)opus_alloc(mode->overlap*sizeof(opus_val16)); window = (celt_coef*)opus_alloc(mode->overlap*sizeof(*window));
if (window==NULL) if (window==NULL)
goto failure; goto failure;
#ifndef FIXED_POINT #ifndef FIXED_POINT
for (i=0;i<mode->overlap;i++) for (i=0;i<mode->overlap;i++)
window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)); window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
#else
# ifdef ENABLE_QEXT
for (i=0;i<mode->overlap;i++)
window[i] = 2147483647*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
# else # else
for (i=0;i<mode->overlap;i++) for (i=0;i<mode->overlap;i++)
window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)))); window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap))));
# endif
#endif #endif
mode->window = window; mode->window = window;

View File

@@ -66,7 +66,7 @@ struct OpusCustomMode {
const unsigned char *allocVectors; /**< Number of bits in each band for several rates */ const unsigned char *allocVectors; /**< Number of bits in each band for several rates */
const opus_int16 *logN; const opus_int16 *logN;
const opus_val16 *window; const celt_coef *window;
mdct_lookup mdct; mdct_lookup mdct;
PulseCache cache; PulseCache cache;
}; };

View File

@@ -436,7 +436,7 @@ static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy
den = celt_rsqrt_norm(x2y2); den = celt_rsqrt_norm(x2y2);
g = MULT16_32_Q15(den, xy); g = MULT16_32_Q15(den, xy);
g = VSHR32(g, (shift>>1)-1); g = VSHR32(g, (shift>>1)-1);
return EXTRACT16(MIN32(g, Q15ONE)); return EXTRACT16(MAX32(-Q15ONE, MIN32(g, Q15ONE)));
} }
#else #else
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy) static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)

View File

@@ -139,25 +139,25 @@ static const unsigned char e_prob_model[4][2][42] = {
static const unsigned char small_energy_icdf[3]={2,1,0}; static const unsigned char small_energy_icdf[3]={2,1,0};
static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBands, int start, int end, int len, int C) static opus_val32 loss_distortion(const celt_glog *eBands, celt_glog *oldEBands, int start, int end, int len, int C)
{ {
int c, i; int c, i;
opus_val32 dist = 0; opus_val32 dist = 0;
c=0; do { c=0; do {
for (i=start;i<end;i++) for (i=start;i<end;i++)
{ {
opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3)); celt_glog d = PSHR32(SUB32(eBands[i+c*len], oldEBands[i+c*len]), DB_SHIFT-7);
dist = MAC16_16(dist, d,d); dist = MAC16_16(dist, d,d);
} }
} while (++c<C); } while (++c<C);
return MIN32(200,SHR32(dist,2*DB_SHIFT-6)); return MIN32(200,SHR32(dist,14));
} }
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end, static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
const opus_val16 *eBands, opus_val16 *oldEBands, const celt_glog *eBands, celt_glog *oldEBands,
opus_int32 budget, opus_int32 tell, opus_int32 budget, opus_int32 tell,
const unsigned char *prob_model, opus_val16 *error, ec_enc *enc, const unsigned char *prob_model, celt_glog *error, ec_enc *enc,
int C, int LM, int intra, opus_val16 max_decay, int lfe) int C, int LM, int intra, celt_glog max_decay, int lfe)
{ {
int i, c; int i, c;
int badness = 0; int badness = 0;
@@ -184,29 +184,28 @@ static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
int bits_left; int bits_left;
int qi, qi0; int qi, qi0;
opus_val32 q; opus_val32 q;
opus_val16 x; celt_glog x;
opus_val32 f, tmp; opus_val32 f, tmp;
opus_val16 oldE; celt_glog oldE;
opus_val16 decay_bound; celt_glog decay_bound;
x = eBands[i+c*m->nbEBands]; x = eBands[i+c*m->nbEBands];
oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); oldE = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]);
#ifdef FIXED_POINT #ifdef FIXED_POINT
f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c]; f = x - MULT16_32_Q15(coef,oldE) - prev[c];
/* Rounding to nearest integer here is really important! */ /* Rounding to nearest integer here is really important! */
qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7); qi = (f+QCONST32(.5f,DB_SHIFT))>>DB_SHIFT;
decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT), decay_bound = MAXG(-GCONST(28.f), SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay));
SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay)));
#else #else
f = x-coef*oldE-prev[c]; f = x-coef*oldE-prev[c];
/* Rounding to nearest integer here is really important! */ /* Rounding to nearest integer here is really important! */
qi = (int)floor(.5f+f); qi = (int)floor(.5f+f);
decay_bound = MAX16(-QCONST16(28.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]) - max_decay; decay_bound = MAXG(-GCONST(28.f), oldEBands[i+c*m->nbEBands]) - max_decay;
#endif #endif
/* Prevent the energy from going down too quickly (e.g. for bands /* Prevent the energy from going down too quickly (e.g. for bands
that have just one bin) */ that have just one bin) */
if (qi < 0 && x < decay_bound) if (qi < 0 && x < decay_bound)
{ {
qi += (int)SHR16(SUB16(decay_bound,x), DB_SHIFT); qi += (int)SHR32(SUB32(decay_bound,x), DB_SHIFT);
if (qi > 0) if (qi > 0)
qi = 0; qi = 0;
} }
@@ -243,30 +242,30 @@ static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
} }
else else
qi = -1; qi = -1;
error[i+c*m->nbEBands] = PSHR32(f,7) - SHL16(qi,DB_SHIFT); error[i+c*m->nbEBands] = f - SHL32(qi,DB_SHIFT);
badness += abs(qi0-qi); badness += abs(qi0-qi);
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7); tmp = MULT16_32_Q15(coef,oldE) + prev[c] + q;
#ifdef FIXED_POINT #ifdef FIXED_POINT
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); tmp = MAX32(-GCONST(28.f), tmp);
#endif #endif
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); oldEBands[i+c*m->nbEBands] = tmp;
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); prev[c] = prev[c] + q - MULT16_32_Q15(beta,q);
} while (++c < C); } while (++c < C);
} }
return lfe ? 0 : badness; return lfe ? 0 : badness;
} }
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget,
opus_val16 *error, ec_enc *enc, int C, int LM, int nbAvailableBytes, celt_glog *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe) int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe)
{ {
int intra; int intra;
opus_val16 max_decay; celt_glog max_decay;
VARDECL(opus_val16, oldEBands_intra); VARDECL(celt_glog, oldEBands_intra);
VARDECL(opus_val16, error_intra); VARDECL(celt_glog, error_intra);
ec_enc enc_start_state; ec_enc enc_start_state;
opus_uint32 tell; opus_uint32 tell;
int badness1=0; int badness1=0;
@@ -282,21 +281,21 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
if (tell+3 > budget) if (tell+3 > budget)
two_pass = intra = 0; two_pass = intra = 0;
max_decay = QCONST16(16.f,DB_SHIFT); max_decay = GCONST(16.f);
if (end-start>10) if (end-start>10)
{ {
#ifdef FIXED_POINT #ifdef FIXED_POINT
max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3)); max_decay = SHL32(MIN32(SHR32(max_decay,DB_SHIFT-3), EXTEND32(nbAvailableBytes)),DB_SHIFT-3);
#else #else
max_decay = MIN32(max_decay, .125f*nbAvailableBytes); max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
#endif #endif
} }
if (lfe) if (lfe)
max_decay = QCONST16(3.f,DB_SHIFT); max_decay = GCONST(3.f);
enc_start_state = *enc; enc_start_state = *enc;
ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16); ALLOC(oldEBands_intra, C*m->nbEBands, celt_glog);
ALLOC(error_intra, C*m->nbEBands, opus_val16); ALLOC(error_intra, C*m->nbEBands, celt_glog);
OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands); OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands);
if (two_pass || intra) if (two_pass || intra)
@@ -358,7 +357,7 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
RESTORE_STACK; RESTORE_STACK;
} }
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C) void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, ec_enc *enc, int C)
{ {
int i, c; int i, c;
@@ -371,10 +370,10 @@ void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBa
c=0; c=0;
do { do {
int q2; int q2;
opus_val16 offset; celt_glog offset;
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* Has to be without rounding */ /* Has to be without rounding */
q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]); q2 = (error[i+c*m->nbEBands]+GCONST(.5f))>>(DB_SHIFT-fine_quant[i]);
#else #else
q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac); q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac);
#endif #endif
@@ -384,7 +383,7 @@ void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBa
q2 = 0; q2 = 0;
ec_enc_bits(enc, q2, fine_quant[i]); ec_enc_bits(enc, q2, fine_quant[i]);
#ifdef FIXED_POINT #ifdef FIXED_POINT
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); offset = SUB32(VSHR32(2*q2+1, fine_quant[i]-DB_SHIFT+1), GCONST(.5f));
#else #else
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
#endif #endif
@@ -395,7 +394,7 @@ void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBa
} }
} }
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C) void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C)
{ {
int i, prio, c; int i, prio, c;
@@ -409,11 +408,11 @@ void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *ol
c=0; c=0;
do { do {
int q2; int q2;
opus_val16 offset; celt_glog offset;
q2 = error[i+c*m->nbEBands]<0 ? 0 : 1; q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
ec_enc_bits(enc, q2, 1); ec_enc_bits(enc, q2, 1);
#ifdef FIXED_POINT #ifdef FIXED_POINT
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1);
#else #else
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif #endif
@@ -425,7 +424,7 @@ void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *ol
} }
} }
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM) void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM)
{ {
const unsigned char *prob_model = e_prob_model[LM][intra]; const unsigned char *prob_model = e_prob_model[LM][intra];
int i, c; int i, c;
@@ -479,18 +478,18 @@ void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *ol
qi = -1; qi = -1;
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
oldEBands[i+c*m->nbEBands] = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); oldEBands[i+c*m->nbEBands] = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]);
tmp = PSHR32(MULT16_16(coef,oldEBands[i+c*m->nbEBands]),8) + prev[c] + SHL32(q,7); tmp = MULT16_32_Q15(coef,oldEBands[i+c*m->nbEBands]) + prev[c] + q;
#ifdef FIXED_POINT #ifdef FIXED_POINT
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); tmp = MAX32(-GCONST(28.f), tmp);
#endif #endif
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); oldEBands[i+c*m->nbEBands] = tmp;
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); prev[c] = prev[c] + q - MULT16_32_Q15(beta,q);
} while (++c < C); } while (++c < C);
} }
} }
void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C) void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, ec_dec *dec, int C)
{ {
int i, c; int i, c;
/* Decode finer resolution */ /* Decode finer resolution */
@@ -501,10 +500,10 @@ void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldE
c=0; c=0;
do { do {
int q2; int q2;
opus_val16 offset; celt_glog offset;
q2 = ec_dec_bits(dec, fine_quant[i]); q2 = ec_dec_bits(dec, fine_quant[i]);
#ifdef FIXED_POINT #ifdef FIXED_POINT
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); offset = SUB32(VSHR32(2*q2+1, fine_quant[i]-DB_SHIFT+1), GCONST(.5f));
#else #else
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
#endif #endif
@@ -513,7 +512,7 @@ void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldE
} }
} }
void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C) void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C)
{ {
int i, prio, c; int i, prio, c;
@@ -527,10 +526,10 @@ void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *
c=0; c=0;
do { do {
int q2; int q2;
opus_val16 offset; celt_glog offset;
q2 = ec_dec_bits(dec, 1); q2 = ec_dec_bits(dec, 1);
#ifdef FIXED_POINT #ifdef FIXED_POINT
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1);
#else #else
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif #endif
@@ -542,7 +541,7 @@ void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *
} }
void amp2Log2(const CELTMode *m, int effEnd, int end, void amp2Log2(const CELTMode *m, int effEnd, int end,
celt_ener *bandE, opus_val16 *bandLogE, int C) celt_ener *bandE, celt_glog *bandLogE, int C)
{ {
int c, i; int c, i;
c=0; c=0;
@@ -550,14 +549,14 @@ void amp2Log2(const CELTMode *m, int effEnd, int end,
for (i=0;i<effEnd;i++) for (i=0;i<effEnd;i++)
{ {
bandLogE[i+c*m->nbEBands] = bandLogE[i+c*m->nbEBands] =
celt_log2(bandE[i+c*m->nbEBands]) celt_log2_db(bandE[i+c*m->nbEBands])
- SHL16((opus_val16)eMeans[i],6); - SHL32((celt_glog)eMeans[i],DB_SHIFT-4);
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */ /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT); bandLogE[i+c*m->nbEBands] += GCONST(2.f);
#endif #endif
} }
for (i=effEnd;i<end;i++) for (i=effEnd;i<end;i++)
bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT); bandLogE[c*m->nbEBands+i] = -GCONST(14.f);
} while (++c < C); } while (++c < C);
} }

View File

@@ -42,25 +42,25 @@ extern const opus_val16 eMeans[25];
#endif #endif
void amp2Log2(const CELTMode *m, int effEnd, int end, void amp2Log2(const CELTMode *m, int effEnd, int end,
celt_ener *bandE, opus_val16 *bandLogE, int C); celt_ener *bandE, celt_glog *bandLogE, int C);
void log2Amp(const CELTMode *m, int start, int end, void log2Amp(const CELTMode *m, int start, int end,
celt_ener *eBands, const opus_val16 *oldEBands, int C); celt_ener *eBands, const celt_glog *oldEBands, int C);
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget,
opus_val16 *error, ec_enc *enc, int C, int LM, celt_glog *error, ec_enc *enc, int C, int LM,
int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra, int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra,
int two_pass, int loss_rate, int lfe); int two_pass, int loss_rate, int lfe);
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C); void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, ec_enc *enc, int C);
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C); void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C);
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM); void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM);
void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C); void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, ec_dec *dec, int C);
void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C); void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C);
#endif /* QUANT_BANDS */ #endif /* QUANT_BANDS */

View File

@@ -140,8 +140,9 @@ extern char *global_stack_top;
#else #else
#include "arch.h"
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/(sizeof(char))),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)((stack)-(size)*(sizeof(type)/(sizeof(char))))) #define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/(sizeof(char))),(void)(((int)((size)*(sizeof(type)/(sizeof(char)))) <= (scratch_ptr)+GLOBAL_STACK_SIZE-(stack))?0:CELT_FATAL("pseudostack overflow")),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)((stack)-(size)*(sizeof(type)/(sizeof(char)))))
#if 0 /* Set this to 1 to instrument pseudostack usage */ #if 0 /* Set this to 1 to instrument pseudostack usage */
#define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack) #define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack)
#else #else

File diff suppressed because it is too large Load Diff

View File

@@ -119,7 +119,7 @@ void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
/** Takes the pitch vector and the decoded residual vector, computes the gain /** Takes the pitch vector and the decoded residual vector, computes the gain
that will give ||p+g*y||=1 and mixes the residual with the pitch. */ that will give ||p+g*y||=1 and mixes the residual with the pitch. */
static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
int N, opus_val32 Ryy, opus_val16 gain) int N, opus_val32 Ryy, opus_val32 gain)
{ {
int i; int i;
#ifdef FIXED_POINT #ifdef FIXED_POINT
@@ -132,7 +132,7 @@ static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT
k = celt_ilog2(Ryy)>>1; k = celt_ilog2(Ryy)>>1;
#endif #endif
t = VSHR32(Ryy, 2*(k-7)); t = VSHR32(Ryy, 2*(k-7));
g = MULT16_16_P15(celt_rsqrt_norm(t),gain); g = MULT32_32_Q31(celt_rsqrt_norm(t),gain);
i=0; i=0;
do do
@@ -328,7 +328,7 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
} }
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc, unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
opus_val16 gain, int resynth, int arch) opus_val32 gain, int resynth, int arch)
{ {
VARDECL(int, iy); VARDECL(int, iy);
opus_val16 yy; opus_val16 yy;
@@ -361,7 +361,7 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
/** Decode pulse vector and combine the result with the pitch vector to produce /** Decode pulse vector and combine the result with the pitch vector to produce
the final normalised signal in the current band. */ the final normalised signal in the current band. */
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B, unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
ec_dec *dec, opus_val16 gain) ec_dec *dec, opus_val32 gain)
{ {
opus_val32 Ryy; opus_val32 Ryy;
unsigned collapse_mask; unsigned collapse_mask;
@@ -380,7 +380,7 @@ unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
} }
#ifndef OVERRIDE_renormalise_vector #ifndef OVERRIDE_renormalise_vector
void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch) void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch)
{ {
int i; int i;
#ifdef FIXED_POINT #ifdef FIXED_POINT
@@ -395,7 +395,7 @@ void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
k = celt_ilog2(E)>>1; k = celt_ilog2(E)>>1;
#endif #endif
t = VSHR32(E, 2*(k-7)); t = VSHR32(E, 2*(k-7));
g = MULT16_16_P15(celt_rsqrt_norm(t),gain); g = MULT32_32_Q31(celt_rsqrt_norm(t),gain);
xptr = X; xptr = X;
for (i=0;i<N;i++) for (i=0;i<N;i++)

View File

@@ -60,7 +60,7 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
* @ret A mask indicating which blocks in the band received pulses * @ret A mask indicating which blocks in the band received pulses
*/ */
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc, unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
opus_val16 gain, int resynth, int arch); opus_val32 gain, int resynth, int arch);
/** Algebraic pulse decoder /** Algebraic pulse decoder
* @param X Decoded normalised spectrum (returned) * @param X Decoded normalised spectrum (returned)
@@ -70,9 +70,9 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
* @ret A mask indicating which blocks in the band received pulses * @ret A mask indicating which blocks in the band received pulses
*/ */
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B, unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
ec_dec *dec, opus_val16 gain); ec_dec *dec, opus_val32 gain);
void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch); void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch);
int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch); int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch);

View File

@@ -268,6 +268,42 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
opus_int32 max_data_bytes opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes an Opus frame.
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
* @param [in] pcm <tt>opus_int32*</tt>: Input signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length is frame_size*channels*sizeof(opus_int32)
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
* input signal.
* This must be an Opus frame size for
* the encoder's sampling rate.
* For example, at 48 kHz the permitted
* values are 120, 240, 480, 960, 1920,
* and 2880.
* Passing in a duration of less than
* 10 ms (480 samples at 48 kHz) will
* prevent the encoder from using the LPC
* or hybrid modes.
* @param [out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode24(
OpusEncoder *st,
const opus_int32 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes an Opus frame from floating point input. /** Encodes an Opus frame from floating point input.
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
* @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0. * @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
@@ -483,6 +519,31 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
int decode_fec int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an Opus packet.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
* @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
* is frame_size*channels*sizeof(opus_int32)
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
* decoded. If no such data is available, the frame is decoded as if it were lost.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode24(
OpusDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int32 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an Opus packet with floating point output. /** Decode an Opus packet with floating point output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
@@ -596,7 +657,7 @@ OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const
*/ */
OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst); OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
/** Decode audio from an Opus DRED packet with floating point output. /** Decode audio from an Opus DRED packet with 16-bit output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] dred <tt>OpusDRED*</tt>: DRED state * @param [in] dred <tt>OpusDRED*</tt>: DRED state
* @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet). * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
@@ -608,6 +669,18 @@ OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src
*/ */
OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size); OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size);
/** Decode audio from an Opus DRED packet with 24-bit output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
* @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
* @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size Number of samples per channel to decode in \a pcm.
* frame_size <b>must</b> be a multiple of 2.5 ms.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size);
/** Decode audio from an Opus DRED packet with floating point output. /** Decode audio from an Opus DRED packet with floating point output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] dred <tt>OpusDRED*</tt>: DRED state * @param [in] dred <tt>OpusDRED*</tt>: DRED state

View File

@@ -230,6 +230,27 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
int maxCompressedBytes int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>opus_int32*</tt>: PCM audio in signed 32-bit format (native endian) representing (or slightly exceeding) 24-bit values.
* There must be exactly frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode24(
OpusCustomEncoder *st,
const opus_int32 *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom encoder. /** Perform a CTL function on an Opus custom encoder.
* *
* Generally the request and subsequent arguments are generated * Generally the request and subsequent arguments are generated
@@ -326,6 +347,23 @@ OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
int frame_size int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an opus custom frame
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
* is frame_size*channels*sizeof(opus_int32)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode24(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
opus_int32 *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom decoder. /** Perform a CTL function on an Opus custom decoder.
* *
* Generally the request and subsequent arguments are generated * Generally the request and subsequent arguments are generated

View File

@@ -382,6 +382,44 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
opus_int32 max_data_bytes opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a multistream Opus frame.
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
* @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
* samples representing (or slightly exceeding) 24-bit values.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode24(
OpusMSEncoder *st,
const opus_int32 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a multistream Opus frame from floating point input. /** Encodes a multistream Opus frame from floating point input.
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state. * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
@@ -591,6 +629,44 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
int decode_fec int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a multistream Opus packet.
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
* samples representing (or slightly exceeding) 24-bit values.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode24(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int32 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a multistream Opus packet with floating point output. /** Decode a multistream Opus packet with floating point output.
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state. * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload. * @param[in] data <tt>const unsigned char*</tt>: Input payload.

View File

@@ -260,6 +260,44 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
opus_int32 max_data_bytes opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a projection Opus frame.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
* @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
* samples representing (or slightly exceeding) 24-bit values.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode24(
OpusProjectionEncoder *st,
const opus_int32 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a projection Opus frame from floating point input. /** Encodes a projection Opus frame from floating point input.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state. * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
@@ -493,6 +531,43 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
int decode_fec int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a projection Opus packet.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
* samples representing (or slightly exceeding) 24-bit values.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode24(
OpusProjectionDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int32 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a projection Opus packet with floating point output. /** Decode a projection Opus packet with floating point output.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state. * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.

View File

@@ -21,7 +21,7 @@ FINAL_LIBRARY = "gkcodecs"
NoVisibilityFlags() NoVisibilityFlags()
DEFINES["OPUS_BUILD"] = True DEFINES["OPUS_BUILD"] = True
DEFINES["OPUS_VERSION"] = "734aed05d09af3d2690f8cb5aafa97f052746daf" DEFINES["OPUS_VERSION"] = "c79a9bd1dd2898cd57bb793e037d58c937555c2c"
DEFINES["USE_ALLOCA"] = True DEFINES["USE_ALLOCA"] = True
DEFINES["ENABLE_HARDENING"] = True DEFINES["ENABLE_HARDENING"] = True

View File

@@ -20,11 +20,11 @@ origin:
# Human-readable identifier for this version/release # Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS" # Generally "version NNN", "tag SSS", "bookmark SSS"
release: 734aed05d09af3d2690f8cb5aafa97f052746daf (2025-02-10T14:18:25.000-05:00). release: c79a9bd1dd2898cd57bb793e037d58c937555c2c (2025-02-13T12:50:05.000-05:00).
# Revision to pull in # Revision to pull in
# Must be a long or short commit SHA (long preferred) # Must be a long or short commit SHA (long preferred)
revision: 734aed05d09af3d2690f8cb5aafa97f052746daf revision: c79a9bd1dd2898cd57bb793e037d58c937555c2c
# The package's license, where possible using the mnemonic from # The package's license, where possible using the mnemonic from
# https://spdx.org/licenses/ # https://spdx.org/licenses/

View File

@@ -80,7 +80,7 @@ opus_int silk_InitEncoder( /* O Returns error co
opus_int silk_Encode( /* O Returns error code */ opus_int silk_Encode( /* O Returns error code */
void *encState, /* I/O State */ void *encState, /* I/O State */
silk_EncControlStruct *encControl, /* I Control status */ silk_EncControlStruct *encControl, /* I Control status */
const opus_int16 *samplesIn, /* I Speech sample input vector */ const opus_res *samplesIn, /* I Speech sample input vector */
opus_int nSamplesIn, /* I Number of samples in input vector */ opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */ ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */ opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
@@ -129,7 +129,7 @@ opus_int silk_Decode( /* O Returns error co
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */ opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
ec_dec *psRangeDec, /* I/O Compressor data structure */ ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */ opus_res *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut, /* O Number of samples decoded */ opus_int32 *nSamplesOut, /* O Number of samples decoded */
#ifdef ENABLE_DEEP_PLC #ifdef ENABLE_DEEP_PLC
LPCNetPLCState *lpcnet, LPCNetPLCState *lpcnet,

View File

@@ -135,7 +135,7 @@ opus_int silk_Decode( /* O Returns error co
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */ opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
ec_dec *psRangeDec, /* I/O Compressor data structure */ ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */ opus_res *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut, /* O Number of samples decoded */ opus_int32 *nSamplesOut, /* O Number of samples decoded */
#ifdef ENABLE_DEEP_PLC #ifdef ENABLE_DEEP_PLC
LPCNetPLCState *lpcnet, LPCNetPLCState *lpcnet,
@@ -147,7 +147,6 @@ opus_int silk_Decode( /* O Returns error co
opus_int32 nSamplesOutDec, LBRR_symbol; opus_int32 nSamplesOutDec, LBRR_symbol;
opus_int16 *samplesOut1_tmp[ 2 ]; opus_int16 *samplesOut1_tmp[ 2 ];
VARDECL( opus_int16, samplesOut1_tmp_storage1 ); VARDECL( opus_int16, samplesOut1_tmp_storage1 );
VARDECL( opus_int16, samplesOut1_tmp_storage2 );
VARDECL( opus_int16, samplesOut2_tmp ); VARDECL( opus_int16, samplesOut2_tmp );
opus_int32 MS_pred_Q13[ 2 ] = { 0 }; opus_int32 MS_pred_Q13[ 2 ] = { 0 };
opus_int16 *resample_out_ptr; opus_int16 *resample_out_ptr;
@@ -155,7 +154,6 @@ opus_int silk_Decode( /* O Returns error co
silk_decoder_state *channel_state = psDec->channel_state; silk_decoder_state *channel_state = psDec->channel_state;
opus_int has_side; opus_int has_side;
opus_int stereo_to_mono; opus_int stereo_to_mono;
int delay_stack_alloc;
SAVE_STACK; SAVE_STACK;
celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 ); celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
@@ -312,19 +310,10 @@ opus_int silk_Decode( /* O Returns error co
/* Check if the temp buffer fits into the output PCM buffer. If it fits, /* Check if the temp buffer fits into the output PCM buffer. If it fits,
we can delay allocating the temp buffer until after the SILK peak stack we can delay allocating the temp buffer until after the SILK peak stack
usage. We need to use a < and not a <= because of the two extra samples. */ usage. We need to use a < and not a <= because of the two extra samples. */
delay_stack_alloc = decControl->internalSampleRate*decControl->nChannelsInternal ALLOC( samplesOut1_tmp_storage1, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ),
< decControl->API_sampleRate*decControl->nChannelsAPI;
ALLOC( samplesOut1_tmp_storage1, delay_stack_alloc ? ALLOC_NONE
: decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ),
opus_int16 ); opus_int16 );
if ( delay_stack_alloc )
{
samplesOut1_tmp[ 0 ] = samplesOut;
samplesOut1_tmp[ 1 ] = samplesOut + channel_state[ 0 ].frame_length + 2;
} else {
samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage1; samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage1;
samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage1 + channel_state[ 0 ].frame_length + 2; samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage1 + channel_state[ 0 ].frame_length + 2;
}
if( lostFlag == FLAG_DECODE_NORMAL ) { if( lostFlag == FLAG_DECODE_NORMAL ) {
has_side = !decode_only_middle; has_side = !decode_only_middle;
@@ -384,23 +373,9 @@ opus_int silk_Decode( /* O Returns error co
*nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) ); *nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) );
/* Set up pointers to temp buffers */ /* Set up pointers to temp buffers */
ALLOC( samplesOut2_tmp, ALLOC( samplesOut2_tmp, *nSamplesOut, opus_int16 );
decControl->nChannelsAPI == 2 ? *nSamplesOut : ALLOC_NONE, opus_int16 );
if( decControl->nChannelsAPI == 2 ) {
resample_out_ptr = samplesOut2_tmp; resample_out_ptr = samplesOut2_tmp;
} else {
resample_out_ptr = samplesOut;
}
ALLOC( samplesOut1_tmp_storage2, delay_stack_alloc
? decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 )
: ALLOC_NONE,
opus_int16 );
if ( delay_stack_alloc ) {
OPUS_COPY(samplesOut1_tmp_storage2, samplesOut, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2));
samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage2;
samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage2 + channel_state[ 0 ].frame_length + 2;
}
for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
/* Resample decoded signal to API_sampleRate */ /* Resample decoded signal to API_sampleRate */
@@ -409,7 +384,11 @@ opus_int silk_Decode( /* O Returns error co
/* Interleave if stereo output and stereo stream */ /* Interleave if stereo output and stereo stream */
if( decControl->nChannelsAPI == 2 ) { if( decControl->nChannelsAPI == 2 ) {
for( i = 0; i < *nSamplesOut; i++ ) { for( i = 0; i < *nSamplesOut; i++ ) {
samplesOut[ n + 2 * i ] = resample_out_ptr[ i ]; samplesOut[ n + 2 * i ] = INT16TORES(resample_out_ptr[ i ]);
}
} else {
for( i = 0; i < *nSamplesOut; i++ ) {
samplesOut[ i ] = INT16TORES(resample_out_ptr[ i ]);
} }
} }
} }
@@ -422,7 +401,7 @@ opus_int silk_Decode( /* O Returns error co
ret += silk_resampler( &channel_state[ 1 ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ 0 ][ 1 ], nSamplesOutDec ); ret += silk_resampler( &channel_state[ 1 ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ 0 ][ 1 ], nSamplesOutDec );
for( i = 0; i < *nSamplesOut; i++ ) { for( i = 0; i < *nSamplesOut; i++ ) {
samplesOut[ 1 + 2 * i ] = resample_out_ptr[ i ]; samplesOut[ 1 + 2 * i ] = INT16TORES(resample_out_ptr[ i ]);
} }
} else { } else {
for( i = 0; i < *nSamplesOut; i++ ) { for( i = 0; i < *nSamplesOut; i++ ) {

View File

@@ -144,7 +144,7 @@ static opus_int silk_QueryEncoder( /* O Returns error co
opus_int silk_Encode( /* O Returns error code */ opus_int silk_Encode( /* O Returns error code */
void *encState, /* I/O State */ void *encState, /* I/O State */
silk_EncControlStruct *encControl, /* I Control status */ silk_EncControlStruct *encControl, /* I Control status */
const opus_int16 *samplesIn, /* I Speech sample input vector */ const opus_res *samplesIn, /* I Speech sample input vector */
opus_int nSamplesIn, /* I Number of samples in input vector */ opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */ ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */ opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
@@ -282,7 +282,7 @@ opus_int silk_Encode( /* O Returns error co
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
for( n = 0; n < nSamplesFromInput; n++ ) { for( n = 0; n < nSamplesFromInput; n++ ) {
buf[ n ] = samplesIn[ 2 * n ]; buf[ n ] = RES2INT16(samplesIn[ 2 * n ]);
} }
/* Making sure to start both resamplers from the same state when switching from mono to stereo */ /* Making sure to start both resamplers from the same state when switching from mono to stereo */
if( psEnc->nPrevChannelsInternal == 1 && id==0 ) { if( psEnc->nPrevChannelsInternal == 1 && id==0 ) {
@@ -296,7 +296,7 @@ opus_int silk_Encode( /* O Returns error co
nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx;
nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
for( n = 0; n < nSamplesFromInput; n++ ) { for( n = 0; n < nSamplesFromInput; n++ ) {
buf[ n ] = samplesIn[ 2 * n + 1 ]; buf[ n ] = RES2INT16(samplesIn[ 2 * n + 1 ]);
} }
ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
@@ -305,7 +305,7 @@ opus_int silk_Encode( /* O Returns error co
} else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) {
/* Combine left and right channels before resampling */ /* Combine left and right channels before resampling */
for( n = 0; n < nSamplesFromInput; n++ ) { for( n = 0; n < nSamplesFromInput; n++ ) {
sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]; sum = RES2INT16(samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]);
buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 );
} }
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
@@ -323,7 +323,9 @@ opus_int silk_Encode( /* O Returns error co
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} else { } else {
celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16)); for( n = 0; n < nSamplesFromInput; n++ ) {
buf[n] = RES2INT16(samplesIn[n]);
}
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;

View File

@@ -106,13 +106,14 @@ static OPUS_INLINE opus_int32 silk_sar_round_32(opus_int32 a, int bits)
static OPUS_INLINE opus_int64 silk_sar_round_smulww(opus_int32 a, opus_int32 b, int bits) static OPUS_INLINE opus_int64 silk_sar_round_smulww(opus_int32 a, opus_int32 b, int bits)
{ {
opus_int64 t;
silk_assert(bits > 0 && bits < 63); silk_assert(bits > 0 && bits < 63);
#ifdef OPUS_CHECK_ASM #ifdef OPUS_CHECK_ASM
return silk_RSHIFT_ROUND(silk_SMULWW(a, b), bits); return silk_RSHIFT_ROUND(silk_SMULWW(a, b), bits);
#else #else
/* This code is more correct, but it won't overflow like the C code in some rare cases. */ /* This code is more correct, but it won't overflow like the C code in some rare cases. */
silk_assert(bits > 0 && bits < 63); silk_assert(bits > 0 && bits < 63);
opus_int64 t = ((opus_int64)a) * ((opus_int64)b); t = ((opus_int64)a) * ((opus_int64)b);
bits += 16; bits += 16;
t += 1ull << (bits-1); t += 1ull << (bits-1);
return t >> bits; return t >> bits;

View File

@@ -163,7 +163,6 @@ static opus_val32 silk_resampler_down2_hp(
static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs) static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs)
{ {
VARDECL(opus_val32, tmp); VARDECL(opus_val32, tmp);
opus_val32 scale;
int j; int j;
opus_val32 ret = 0; opus_val32 ret = 0;
SAVE_STACK; SAVE_STACK;
@@ -180,17 +179,11 @@ static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opu
ALLOC(tmp, subframe, opus_val32); ALLOC(tmp, subframe, opus_val32);
downmix(_x, tmp, subframe, offset, c1, c2, C); downmix(_x, tmp, subframe, offset, c1, c2, C);
#ifdef FIXED_POINT if ((c2==-2 && C==2) || c2>-1) {
scale = (1<<SIG_SHIFT); for (j=0;j<subframe;j++) {
#else tmp[j] = HALF32(tmp[j]);
scale = 1.f/32768; }
#endif }
if (c2==-2)
scale /= C;
else if (c2>-1)
scale /= 2;
for (j=0;j<subframe;j++)
tmp[j] *= scale;
if (Fs == 48000) if (Fs == 48000)
{ {
ret = silk_resampler_down2_hp(S, y, tmp, subframe); ret = silk_resampler_down2_hp(S, y, tmp, subframe);
@@ -211,6 +204,9 @@ static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opu
silk_resampler_down2_hp(S, y, tmp3x, 3*subframe); silk_resampler_down2_hp(S, y, tmp3x, 3*subframe);
} }
RESTORE_STACK; RESTORE_STACK;
#ifndef FIXED_POINT
ret *= 1.f/32768/32768;
#endif
return ret; return ret;
} }
@@ -422,7 +418,7 @@ static const float std_feature_bias[9] = {
#define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT))) #define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT)))
#define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e)) #define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e))
#else #else
#define SCALE_ENER(e) (e) #define SCALE_ENER(e) ((1.f/32768/32768)*e)
#endif #endif
#ifdef FIXED_POINT #ifdef FIXED_POINT

View File

@@ -86,7 +86,7 @@ void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const float *input, const float *input,
int input_rows, int input_rows,
opus_val16 *output, opus_res *output,
int output_row, int output_row,
int output_rows, int output_rows,
int frame_size) int frame_size)
@@ -108,17 +108,13 @@ void mapping_matrix_multiply_channel_in_float(
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] * matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)]; input[MATRIX_INDEX(input_rows, col, i)];
} }
#if defined(FIXED_POINT) output[output_rows * i] = FLOAT2RES((1/32768.f)*tmp);
output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
#else
output[output_rows * i] = (1/32768.f)*tmp;
#endif
} }
} }
void mapping_matrix_multiply_channel_out_float( void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const opus_val16 *input, const opus_res *input,
int input_row, int input_row,
int input_rows, int input_rows,
float *output, float *output,
@@ -137,11 +133,7 @@ void mapping_matrix_multiply_channel_out_float(
for (i = 0; i < frame_size; i++) for (i = 0; i < frame_size; i++)
{ {
#if defined(FIXED_POINT) input_sample = RES2FLOAT(input[input_rows * i]);
input_sample = (1/32768.f)*input[input_rows * i];
#else
input_sample = input[input_rows * i];
#endif
for (row = 0; row < output_rows; row++) for (row = 0; row < output_rows; row++)
{ {
float tmp = float tmp =
@@ -157,7 +149,7 @@ void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const opus_int16 *input, const opus_int16 *input,
int input_rows, int input_rows,
opus_val16 *output, opus_res *output,
int output_row, int output_row,
int output_rows, int output_rows,
int frame_size) int frame_size)
@@ -186,7 +178,7 @@ void mapping_matrix_multiply_channel_in_short(
#endif #endif
} }
#if defined(FIXED_POINT) #if defined(FIXED_POINT)
output[output_rows * i] = (opus_int16)((tmp + 64) >> 7); output[output_rows * i] = INT16TORES((tmp + 64) >> 7);
#else #else
output[output_rows * i] = (1/(32768.f*32768.f))*tmp; output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
#endif #endif
@@ -195,7 +187,7 @@ void mapping_matrix_multiply_channel_in_short(
void mapping_matrix_multiply_channel_out_short( void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const opus_val16 *input, const opus_res *input,
int input_row, int input_row,
int input_rows, int input_rows,
opus_int16 *output, opus_int16 *output,
@@ -213,11 +205,7 @@ void mapping_matrix_multiply_channel_out_short(
for (i = 0; i < frame_size; i++) for (i = 0; i < frame_size; i++)
{ {
#if defined(FIXED_POINT) input_sample = RES2INT16(input[input_rows * i]);
input_sample = (opus_int32)input[input_rows * i];
#else
input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
#endif
for (row = 0; row < output_rows; row++) for (row = 0; row < output_rows; row++)
{ {
opus_int32 tmp = opus_int32 tmp =
@@ -228,6 +216,72 @@ void mapping_matrix_multiply_channel_out_short(
} }
} }
void mapping_matrix_multiply_channel_in_int24(
const MappingMatrix *matrix,
const opus_int32 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
opus_val64 tmp = 0;
for (col = 0; col < input_rows; col++)
{
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
(opus_val64)input[MATRIX_INDEX(input_rows, col, i)];
}
#if defined(FIXED_POINT)
output[output_rows * i] = INT24TORES((tmp + 16384) >> 15);
#else
output[output_rows * i] = INT24TORES((1/(32768.f))*tmp);
#endif
}
}
void mapping_matrix_multiply_channel_out_int24(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int32 *output,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
opus_int32 input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
input_sample = RES2INT24(input[input_rows * i]);
for (row = 0; row < output_rows; row++)
{
opus_int64 tmp =
(opus_int64)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 }; const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_mixing_data[36] = { const opus_int16 mapping_matrix_foa_mixing_data[36] = {
16384, 0, -16384, 23170, 0, 0, 16384, 23170, 16384, 0, -16384, 23170, 0, 0, 16384, 23170,

View File

@@ -66,7 +66,7 @@ void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const float *input, const float *input,
int input_rows, int input_rows,
opus_val16 *output, opus_res *output,
int output_row, int output_row,
int output_rows, int output_rows,
int frame_size int frame_size
@@ -74,7 +74,7 @@ void mapping_matrix_multiply_channel_in_float(
void mapping_matrix_multiply_channel_out_float( void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const opus_val16 *input, const opus_res *input,
int input_row, int input_row,
int input_rows, int input_rows,
float *output, float *output,
@@ -87,7 +87,7 @@ void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const opus_int16 *input, const opus_int16 *input,
int input_rows, int input_rows,
opus_val16 *output, opus_res *output,
int output_row, int output_row,
int output_rows, int output_rows,
int frame_size int frame_size
@@ -95,7 +95,7 @@ void mapping_matrix_multiply_channel_in_short(
void mapping_matrix_multiply_channel_out_short( void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix, const MappingMatrix *matrix,
const opus_val16 *input, const opus_res *input,
int input_row, int input_row,
int input_rows, int input_rows,
opus_int16 *output, opus_int16 *output,
@@ -103,6 +103,26 @@ void mapping_matrix_multiply_channel_out_short(
int frame_size int frame_size
); );
void mapping_matrix_multiply_channel_in_int24(
const MappingMatrix *matrix,
const opus_int32 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_int24(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int32 *output,
int output_rows,
int frame_size
);
/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics. /* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
* foa: first-order ambisonics * foa: first-order ambisonics
* soa: second-order ambisonics * soa: second-order ambisonics

View File

@@ -202,8 +202,26 @@ OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error)
return st; return st;
} }
static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, #ifdef ENABLE_RES24
opus_val16 *out, int overlap, int channels, static void smooth_fade(const opus_res *in1, const opus_res *in2,
opus_res *out, int overlap, int channels,
const celt_coef *window, opus_int32 Fs)
{
int i, c;
int inc = 48000/Fs;
for (c=0;c<channels;c++)
{
for (i=0;i<overlap;i++)
{
celt_coef w = MULT_COEF(window[i*inc], window[i*inc]);
out[i*channels+c] = ADD32(MULT_COEF_32(w,in2[i*channels+c]),
MULT_COEF_32(COEF_ONE-w, in1[i*channels+c]));
}
}
}
#else
static void smooth_fade(const opus_res *in1, const opus_res *in2,
opus_res *out, int overlap, int channels,
const opus_val16 *window, opus_int32 Fs) const opus_val16 *window, opus_int32 Fs)
{ {
int i, c; int i, c;
@@ -218,6 +236,7 @@ static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2,
} }
} }
} }
#endif
static int opus_packet_get_mode(const unsigned char *data) static int opus_packet_get_mode(const unsigned char *data)
{ {
@@ -235,22 +254,20 @@ static int opus_packet_get_mode(const unsigned char *data)
} }
static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) opus_int32 len, opus_res *pcm, int frame_size, int decode_fec)
{ {
void *silk_dec; void *silk_dec;
CELTDecoder *celt_dec; CELTDecoder *celt_dec;
int i, silk_ret=0, celt_ret=0; int i, silk_ret=0, celt_ret=0;
ec_dec dec; ec_dec dec;
opus_int32 silk_frame_size; opus_int32 silk_frame_size;
int pcm_silk_size;
VARDECL(opus_int16, pcm_silk);
int pcm_transition_silk_size; int pcm_transition_silk_size;
VARDECL(opus_val16, pcm_transition_silk); VARDECL(opus_res, pcm_transition_silk);
int pcm_transition_celt_size; int pcm_transition_celt_size;
VARDECL(opus_val16, pcm_transition_celt); VARDECL(opus_res, pcm_transition_celt);
opus_val16 *pcm_transition=NULL; opus_res *pcm_transition=NULL;
int redundant_audio_size; int redundant_audio_size;
VARDECL(opus_val16, redundant_audio); VARDECL(opus_res, redundant_audio);
int audiosize; int audiosize;
int mode; int mode;
@@ -262,7 +279,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
int celt_to_silk=0; int celt_to_silk=0;
int c; int c;
int F2_5, F5, F10, F20; int F2_5, F5, F10, F20;
const opus_val16 *window; const celt_coef *window;
opus_uint32 redundant_rng = 0; opus_uint32 redundant_rng = 0;
int celt_accum; int celt_accum;
ALLOC_STACK; ALLOC_STACK;
@@ -335,11 +352,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
/* In fixed-point, we can tell CELT to do the accumulation on top of the /* In fixed-point, we can tell CELT to do the accumulation on top of the
SILK PCM buffer. This saves some stack space. */ SILK PCM buffer. This saves some stack space. */
#ifdef FIXED_POINT celt_accum = (mode != MODE_CELT_ONLY);
celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10);
#else
celt_accum = 0;
#endif
pcm_transition_silk_size = ALLOC_NONE; pcm_transition_silk_size = ALLOC_NONE;
pcm_transition_celt_size = ALLOC_NONE; pcm_transition_celt_size = ALLOC_NONE;
@@ -355,7 +368,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
else else
pcm_transition_silk_size = F5*st->channels; pcm_transition_silk_size = F5*st->channels;
} }
ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16); ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_res);
if (transition && mode == MODE_CELT_ONLY) if (transition && mode == MODE_CELT_ONLY)
{ {
pcm_transition = pcm_transition_celt; pcm_transition = pcm_transition_celt;
@@ -370,21 +383,22 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
frame_size = audiosize; frame_size = audiosize;
} }
/* Don't allocate any memory when in CELT-only mode */
pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE;
ALLOC(pcm_silk, pcm_silk_size, opus_int16);
/* SILK processing */ /* SILK processing */
if (mode != MODE_CELT_ONLY) if (mode != MODE_CELT_ONLY)
{ {
int lost_flag, decoded_samples; int lost_flag, decoded_samples;
opus_int16 *pcm_ptr; opus_res *pcm_ptr;
#ifdef FIXED_POINT int pcm_too_small;
if (celt_accum) int pcm_silk_size = ALLOC_NONE;
pcm_ptr = pcm; VARDECL(opus_res, pcm_silk);
else pcm_too_small = (frame_size < F10);
#endif if (pcm_too_small)
pcm_silk_size = F10*st->channels;
ALLOC(pcm_silk, pcm_silk_size, opus_res);
if (pcm_too_small)
pcm_ptr = pcm_silk; pcm_ptr = pcm_silk;
else
pcm_ptr = pcm;
if (st->prev_mode==MODE_CELT_ONLY) if (st->prev_mode==MODE_CELT_ONLY)
silk_ResetDecoder( silk_dec ); silk_ResetDecoder( silk_dec );
@@ -447,6 +461,9 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
pcm_ptr += silk_frame_size * st->channels; pcm_ptr += silk_frame_size * st->channels;
decoded_samples += silk_frame_size; decoded_samples += silk_frame_size;
} while( decoded_samples < frame_size ); } while( decoded_samples < frame_size );
if (pcm_too_small) {
OPUS_COPY(pcm, pcm_silk, frame_size*st->channels);
}
} }
start_band = 0; start_band = 0;
@@ -488,7 +505,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
pcm_transition_silk_size=ALLOC_NONE; pcm_transition_silk_size=ALLOC_NONE;
} }
ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_res);
if (transition && mode != MODE_CELT_ONLY) if (transition && mode != MODE_CELT_ONLY)
{ {
@@ -526,7 +543,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
/* Only allocation memory for redundancy if/when needed */ /* Only allocation memory for redundancy if/when needed */
redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE; redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
ALLOC(redundant_audio, redundant_audio_size, opus_val16); ALLOC(redundant_audio, redundant_audio_size, opus_res);
/* 5 ms redundant frame for CELT->SILK*/ /* 5 ms redundant frame for CELT->SILK*/
if (redundancy && celt_to_silk) if (redundancy && celt_to_silk)
@@ -574,17 +591,6 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
} }
} }
if (mode != MODE_CELT_ONLY && !celt_accum)
{
#ifdef FIXED_POINT
for (i=0;i<frame_size*st->channels;i++)
pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i]));
#else
for (i=0;i<frame_size*st->channels;i++)
pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
#endif
}
{ {
const CELTMode *celt_mode; const CELTMode *celt_mode;
MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode))); MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)));
@@ -668,7 +674,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
} }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, int opus_decode_native(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, opus_int32 len, opus_res *pcm, int frame_size, int decode_fec,
int self_delimited, opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset) int self_delimited, opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset)
{ {
int i, nb_samples; int i, nb_samples;
@@ -811,20 +817,24 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
#define OPTIONAL_CLIP 0
#else
#define OPTIONAL_CLIP 1
#endif
#if defined(FIXED_POINT) && !defined(ENABLE_RES24)
int opus_decode(OpusDecoder *st, const unsigned char *data, int opus_decode(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{ {
if(frame_size<=0) if(frame_size<=0)
return OPUS_BAD_ARG; return OPUS_BAD_ARG;
return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0); return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
} }
#else
#ifndef DISABLE_FLOAT_API int opus_decode(OpusDecoder *st, const unsigned char *data,
int opus_decode_float(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{ {
VARDECL(opus_int16, out); VARDECL(opus_res, out);
int ret, i; int ret, i;
int nb_samples; int nb_samples;
ALLOC_STACK; ALLOC_STACK;
@@ -843,13 +853,57 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data,
return OPUS_INVALID_PACKET; return OPUS_INVALID_PACKET;
} }
celt_assert(st->channels == 1 || st->channels == 2); celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, opus_int16); ALLOC(out, frame_size*st->channels, opus_res);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, OPTIONAL_CLIP, NULL, 0);
if (ret > 0)
{
for (i=0;i<ret*st->channels;i++)
pcm[i] = RES2INT16(out[i]);
}
RESTORE_STACK;
return ret;
}
#endif
#if defined(FIXED_POINT) && defined(ENABLE_RES24)
int opus_decode24(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
{
if(frame_size<=0)
return OPUS_BAD_ARG;
return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
}
#else
int opus_decode24(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
{
VARDECL(opus_res, out);
int ret, i;
int nb_samples;
ALLOC_STACK;
if(frame_size<=0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
if (data != NULL && len > 0 && !decode_fec)
{
nb_samples = opus_decoder_get_nb_samples(st, data, len);
if (nb_samples>0)
frame_size = IMIN(frame_size, nb_samples);
else
return OPUS_INVALID_PACKET;
}
celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, opus_res);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0); ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
if (ret > 0) if (ret > 0)
{ {
for (i=0;i<ret*st->channels;i++) for (i=0;i<ret*st->channels;i++)
pcm[i] = (1.f/32768.f)*(out[i]); pcm[i] = RES2INT24(out[i]);
} }
RESTORE_STACK; RESTORE_STACK;
return ret; return ret;
@@ -857,11 +911,21 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data,
#endif #endif
#else #ifndef DISABLE_FLOAT_API
int opus_decode(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) # if !defined(FIXED_POINT)
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{ {
VARDECL(float, out); if(frame_size<=0)
return OPUS_BAD_ARG;
return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
}
# else
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
VARDECL(opus_res, out);
int ret, i; int ret, i;
int nb_samples; int nb_samples;
ALLOC_STACK; ALLOC_STACK;
@@ -871,7 +935,6 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
RESTORE_STACK; RESTORE_STACK;
return OPUS_BAD_ARG; return OPUS_BAD_ARG;
} }
if (data != NULL && len > 0 && !decode_fec) if (data != NULL && len > 0 && !decode_fec)
{ {
nb_samples = opus_decoder_get_nb_samples(st, data, len); nb_samples = opus_decoder_get_nb_samples(st, data, len);
@@ -881,28 +944,22 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
return OPUS_INVALID_PACKET; return OPUS_INVALID_PACKET;
} }
celt_assert(st->channels == 1 || st->channels == 2); celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, float); ALLOC(out, frame_size*st->channels, opus_res);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1, NULL, 0); ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
if (ret > 0) if (ret > 0)
{ {
for (i=0;i<ret*st->channels;i++) for (i=0;i<ret*st->channels;i++)
pcm[i] = FLOAT2INT16(out[i]); pcm[i] = RES2FLOAT(out[i]);
} }
RESTORE_STACK; RESTORE_STACK;
return ret; return ret;
} }
# endif
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{
if(frame_size<=0)
return OPUS_BAD_ARG;
return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
}
#endif #endif
int opus_decoder_ctl(OpusDecoder *st, int request, ...) int opus_decoder_ctl(OpusDecoder *st, int request, ...)
{ {
int ret = OPUS_OK; int ret = OPUS_OK;
@@ -1457,7 +1514,41 @@ int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 d
if (ret > 0) if (ret > 0)
{ {
for (i=0;i<ret*st->channels;i++) for (i=0;i<ret*st->channels;i++)
pcm[i] = FLOAT2INT16(out[i]); pcm[i] = RES2INT16(out[i]);
}
RESTORE_STACK;
return ret;
#else
(void)st;
(void)dred;
(void)dred_offset;
(void)pcm;
(void)frame_size;
return OPUS_UNIMPLEMENTED;
#endif
}
int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size)
{
#ifdef ENABLE_DRED
VARDECL(float, out);
int ret, i;
ALLOC_STACK;
if(frame_size<=0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, float);
ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
if (ret > 0)
{
for (i=0;i<ret*st->channels;i++)
pcm[i] = RES2INT24(out[i]);
} }
RESTORE_STACK; RESTORE_STACK;
return ret; return ret;

View File

@@ -119,9 +119,9 @@ struct OpusEncoder {
int silk_bw_switch; int silk_bw_switch;
/* Sampling rate (at the API level) */ /* Sampling rate (at the API level) */
int first; int first;
opus_val16 * energy_masking; celt_glog * energy_masking;
StereoWidthState width_mem; StereoWidthState width_mem;
opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2]; opus_res delay_buffer[MAX_ENCODER_BUFFER*2];
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int detected_bandwidth; int detected_bandwidth;
int nb_no_activity_ms_Q1; int nb_no_activity_ms_Q1;
@@ -328,13 +328,52 @@ static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channel
return toc; return toc;
} }
#ifndef FIXED_POINT #ifdef FIXED_POINT
static void silk_biquad_float( /* Second order ARMA filter, alternative implementation */
const opus_val16 *in, /* I: Input signal */ void silk_biquad_res(
const opus_res *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [2] */
opus_res *out, /* O output signal */
const opus_int32 len, /* I signal length (must be even) */
int stride
)
{
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
opus_int k;
opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
/* Negate A_Q28 values and split in two parts */
A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
for( k = 0; k < len; k++ ) {
/* S[ 0 ], S[ 1 ]: Q12 */
inval = RES2INT16(in[ k*stride ]);
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
/* Scale back to Q0 and saturate */
out[ k*stride ] = INT16TORES( silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ) );
}
}
#else
static void silk_biquad_res(
const opus_res *in, /* I: Input signal */
const opus_int32 *B_Q28, /* I: MA coefficients [3] */ const opus_int32 *B_Q28, /* I: MA coefficients [3] */
const opus_int32 *A_Q28, /* I: AR coefficients [2] */ const opus_int32 *A_Q28, /* I: AR coefficients [2] */
opus_val32 *S, /* I/O: State vector [2] */ opus_val32 *S, /* I/O: State vector [2] */
opus_val16 *out, /* O: Output signal */ opus_res *out, /* O: Output signal */
const opus_int32 len, /* I: Signal length (must be even) */ const opus_int32 len, /* I: Signal length (must be even) */
int stride int stride
) )
@@ -368,7 +407,7 @@ static void silk_biquad_float(
} }
#endif #endif
static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs, int arch) static void hp_cutoff(const opus_res *in, opus_int32 cutoff_Hz, opus_res *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs, int arch)
{ {
opus_int32 B_Q28[ 3 ], A_Q28[ 2 ]; opus_int32 B_Q28[ 3 ], A_Q28[ 2 ];
opus_int32 Fc_Q19, r_Q28, r_Q22; opus_int32 Fc_Q19, r_Q28, r_Q22;
@@ -391,22 +430,22 @@ static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) ); A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) );
A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 ); A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 );
#ifdef FIXED_POINT #if defined(FIXED_POINT) && !defined(ENABLE_RES24)
if( channels == 1 ) { if( channels == 1 ) {
silk_biquad_alt_stride1( in, B_Q28, A_Q28, hp_mem, out, len ); silk_biquad_alt_stride1( in, B_Q28, A_Q28, hp_mem, out, len );
} else { } else {
silk_biquad_alt_stride2( in, B_Q28, A_Q28, hp_mem, out, len, arch ); silk_biquad_alt_stride2( in, B_Q28, A_Q28, hp_mem, out, len, arch );
} }
#else #else
silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels ); silk_biquad_res( in, B_Q28, A_Q28, hp_mem, out, len, channels );
if( channels == 2 ) { if( channels == 2 ) {
silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); silk_biquad_res( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
} }
#endif #endif
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) static void dc_reject(const opus_res *in, opus_int32 cutoff_Hz, opus_res *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
{ {
int c, i; int c, i;
int shift; int shift;
@@ -418,10 +457,15 @@ static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
for (i=0;i<len;i++) for (i=0;i<len;i++)
{ {
opus_val32 x, y; opus_val32 x, y;
x = SHL32(EXTEND32(in[channels*i+c]), 14); x = SHL32((opus_val32)in[channels*i+c], 14-RES_SHIFT);
y = x-hp_mem[2*c]; y = x-hp_mem[2*c];
hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift); hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767)); #ifdef ENABLE_RES24
/* Don't saturate if we have the headroom to avoid it. */
out[channels*i+c] = PSHR32(y, 14-RES_SHIFT);
#else
out[channels*i+c] = SATURATE(PSHR32(y, 14-RES_SHIFT), 32767);
#endif
} }
} }
} }
@@ -468,8 +512,8 @@ static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
} }
#endif #endif
static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, static void stereo_fade(const opus_res *in, opus_res *out, opus_val16 g1, opus_val16 g2,
int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) int overlap48, int frame_size, int channels, const celt_coef *window, opus_int32 Fs)
{ {
int i; int i;
int overlap; int overlap;
@@ -482,26 +526,27 @@ static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, op
{ {
opus_val32 diff; opus_val32 diff;
opus_val16 g, w; opus_val16 g, w;
w = MULT16_16_Q15(window[i*inc], window[i*inc]); w = COEF2VAL16(window[i*inc]);
w = MULT16_16_Q15(w, w);
g = SHR32(MAC16_16(MULT16_16(w,g2), g = SHR32(MAC16_16(MULT16_16(w,g2),
Q15ONE-w, g1), 15); Q15ONE-w, g1), 15);
diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1])); diff = HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]);
diff = MULT16_16_Q15(g, diff); diff = MULT16_RES_Q15(g, diff);
out[i*channels] = out[i*channels] - diff; out[i*channels] = out[i*channels] - diff;
out[i*channels+1] = out[i*channels+1] + diff; out[i*channels+1] = out[i*channels+1] + diff;
} }
for (;i<frame_size;i++) for (;i<frame_size;i++)
{ {
opus_val32 diff; opus_val32 diff;
diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1])); diff = HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]);
diff = MULT16_16_Q15(g2, diff); diff = MULT16_RES_Q15(g2, diff);
out[i*channels] = out[i*channels] - diff; out[i*channels] = out[i*channels] - diff;
out[i*channels+1] = out[i*channels+1] + diff; out[i*channels+1] = out[i*channels+1] + diff;
} }
} }
static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, static void gain_fade(const opus_res *in, opus_res *out, opus_val16 g1, opus_val16 g2,
int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) int overlap48, int frame_size, int channels, const celt_coef *window, opus_int32 Fs)
{ {
int i; int i;
int inc; int inc;
@@ -514,26 +559,28 @@ static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus
for (i=0;i<overlap;i++) for (i=0;i<overlap;i++)
{ {
opus_val16 g, w; opus_val16 g, w;
w = MULT16_16_Q15(window[i*inc], window[i*inc]); w = COEF2VAL16(window[i*inc]);
w = MULT16_16_Q15(w, w);
g = SHR32(MAC16_16(MULT16_16(w,g2), g = SHR32(MAC16_16(MULT16_16(w,g2),
Q15ONE-w, g1), 15); Q15ONE-w, g1), 15);
out[i] = MULT16_16_Q15(g, in[i]); out[i] = MULT16_RES_Q15(g, in[i]);
} }
} else { } else {
for (i=0;i<overlap;i++) for (i=0;i<overlap;i++)
{ {
opus_val16 g, w; opus_val16 g, w;
w = MULT16_16_Q15(window[i*inc], window[i*inc]); w = COEF2VAL16(window[i*inc]);
w = MULT16_16_Q15(w, w);
g = SHR32(MAC16_16(MULT16_16(w,g2), g = SHR32(MAC16_16(MULT16_16(w,g2),
Q15ONE-w, g1), 15); Q15ONE-w, g1), 15);
out[i*2] = MULT16_16_Q15(g, in[i*2]); out[i*2] = MULT16_RES_Q15(g, in[i*2]);
out[i*2+1] = MULT16_16_Q15(g, in[i*2+1]); out[i*2+1] = MULT16_RES_Q15(g, in[i*2+1]);
} }
} }
c=0;do { c=0;do {
for (i=overlap;i<frame_size;i++) for (i=overlap;i<frame_size;i++)
{ {
out[i*channels+c] = MULT16_16_Q15(g2, in[i*channels+c]); out[i*channels+c] = MULT16_RES_Q15(g2, in[i*channels+c]);
} }
} }
while (++c<channels); while (++c<channels);
@@ -648,12 +695,6 @@ static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int m
} }
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
#ifdef FIXED_POINT
#define PCM2VAL(x) FLOAT2INT16(x)
#else
#define PCM2VAL(x) SCALEIN(x)
#endif
void downmix_float(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C) void downmix_float(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
{ {
const float *x; const float *x;
@@ -661,18 +702,18 @@ void downmix_float(const void *_x, opus_val32 *y, int subframe, int offset, int
x = (const float *)_x; x = (const float *)_x;
for (j=0;j<subframe;j++) for (j=0;j<subframe;j++)
y[j] = PCM2VAL(x[(j+offset)*C+c1]); y[j] = FLOAT2SIG(x[(j+offset)*C+c1]);
if (c2>-1) if (c2>-1)
{ {
for (j=0;j<subframe;j++) for (j=0;j<subframe;j++)
y[j] += PCM2VAL(x[(j+offset)*C+c2]); y[j] += FLOAT2SIG(x[(j+offset)*C+c2]);
} else if (c2==-2) } else if (c2==-2)
{ {
int c; int c;
for (c=1;c<C;c++) for (c=1;c<C;c++)
{ {
for (j=0;j<subframe;j++) for (j=0;j<subframe;j++)
y[j] += PCM2VAL(x[(j+offset)*C+c]); y[j] += FLOAT2SIG(x[(j+offset)*C+c]);
} }
} }
} }
@@ -685,18 +726,41 @@ void downmix_int(const void *_x, opus_val32 *y, int subframe, int offset, int c1
x = (const opus_int16 *)_x; x = (const opus_int16 *)_x;
for (j=0;j<subframe;j++) for (j=0;j<subframe;j++)
y[j] = x[(j+offset)*C+c1]; y[j] = INT16TOSIG(x[(j+offset)*C+c1]);
if (c2>-1) if (c2>-1)
{ {
for (j=0;j<subframe;j++) for (j=0;j<subframe;j++)
y[j] += x[(j+offset)*C+c2]; y[j] += INT16TOSIG(x[(j+offset)*C+c2]);
} else if (c2==-2) } else if (c2==-2)
{ {
int c; int c;
for (c=1;c<C;c++) for (c=1;c<C;c++)
{ {
for (j=0;j<subframe;j++) for (j=0;j<subframe;j++)
y[j] += x[(j+offset)*C+c]; y[j] += INT16TOSIG(x[(j+offset)*C+c]);
}
}
}
void downmix_int24(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
{
const opus_int32 *x;
int j;
x = (const opus_int32 *)_x;
for (j=0;j<subframe;j++)
y[j] = INT24TOSIG(x[(j+offset)*C+c1]);
if (c2>-1)
{
for (j=0;j<subframe;j++)
y[j] += INT24TOSIG(x[(j+offset)*C+c2]);
} else if (c2==-2)
{
int c;
for (c=1;c<C;c++)
{
for (j=0;j<subframe;j++)
y[j] += INT24TOSIG(x[(j+offset)*C+c]);
} }
} }
} }
@@ -726,7 +790,7 @@ opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_
return new_size; return new_size;
} }
opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem) opus_val16 compute_stereo_width(const opus_res *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
{ {
opus_val32 xx, xy, yy; opus_val32 xx, xy, yy;
opus_val16 sqrt_xx, sqrt_yy; opus_val16 sqrt_xx, sqrt_yy;
@@ -747,23 +811,23 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
opus_val32 pxy=0; opus_val32 pxy=0;
opus_val32 pyy=0; opus_val32 pyy=0;
opus_val16 x, y; opus_val16 x, y;
x = pcm[2*i]; x = RES2VAL16(pcm[2*i]);
y = pcm[2*i+1]; y = RES2VAL16(pcm[2*i+1]);
pxx = SHR32(MULT16_16(x,x),2); pxx = SHR32(MULT16_16(x,x),2);
pxy = SHR32(MULT16_16(x,y),2); pxy = SHR32(MULT16_16(x,y),2);
pyy = SHR32(MULT16_16(y,y),2); pyy = SHR32(MULT16_16(y,y),2);
x = pcm[2*i+2]; x = RES2VAL16(pcm[2*i+2]);
y = pcm[2*i+3]; y = RES2VAL16(pcm[2*i+3]);
pxx += SHR32(MULT16_16(x,x),2); pxx += SHR32(MULT16_16(x,x),2);
pxy += SHR32(MULT16_16(x,y),2); pxy += SHR32(MULT16_16(x,y),2);
pyy += SHR32(MULT16_16(y,y),2); pyy += SHR32(MULT16_16(y,y),2);
x = pcm[2*i+4]; x = RES2VAL16(pcm[2*i+4]);
y = pcm[2*i+5]; y = RES2VAL16(pcm[2*i+5]);
pxx += SHR32(MULT16_16(x,x),2); pxx += SHR32(MULT16_16(x,x),2);
pxy += SHR32(MULT16_16(x,y),2); pxy += SHR32(MULT16_16(x,y),2);
pyy += SHR32(MULT16_16(y,y),2); pyy += SHR32(MULT16_16(y,y),2);
x = pcm[2*i+6]; x = RES2VAL16(pcm[2*i+6]);
y = pcm[2*i+7]; y = RES2VAL16(pcm[2*i+7]);
pxx += SHR32(MULT16_16(x,x),2); pxx += SHR32(MULT16_16(x,x),2);
pxy += SHR32(MULT16_16(x,y),2); pxy += SHR32(MULT16_16(x,y),2);
pyy += SHR32(MULT16_16(y,y),2); pyy += SHR32(MULT16_16(y,y),2);
@@ -930,14 +994,14 @@ static opus_int32 compute_equiv_rate(opus_int32 bitrate, int channels,
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth) int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth)
{ {
int silence = 0; int silence = 0;
opus_val32 sample_max = 0; opus_val32 sample_max = 0;
#ifdef MLP_TRAINING #ifdef MLP_TRAINING
return 0; return 0;
#endif #endif
sample_max = celt_maxabs16(pcm, frame_size*channels); sample_max = celt_maxabs_res(pcm, frame_size*channels);
#ifdef FIXED_POINT #ifdef FIXED_POINT
silence = (sample_max == 0); silence = (sample_max == 0);
@@ -950,7 +1014,7 @@ int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch) static opus_val32 compute_frame_energy(const opus_res *pcm, int frame_size, int channels, int arch)
{ {
int i; int i;
opus_val32 sample_max; opus_val32 sample_max;
@@ -960,7 +1024,7 @@ static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, in
int len = frame_size*channels; int len = frame_size*channels;
(void)arch; (void)arch;
/* Max amplitude in the signal */ /* Max amplitude in the signal */
sample_max = celt_maxabs16(pcm, len); sample_max = RES2INT16(celt_maxabs_res(pcm, len));
/* Compute the right shift required in the MAC to avoid an overflow */ /* Compute the right shift required in the MAC to avoid an overflow */
max_shift = celt_ilog2(len); max_shift = celt_ilog2(len);
@@ -968,7 +1032,7 @@ static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, in
/* Compute the energy */ /* Compute the energy */
for (i=0; i<len; i++) for (i=0; i<len; i++)
energy += SHR32(MULT16_16(pcm[i], pcm[i]), shift); energy += SHR32(MULT16_16(RES2INT16(pcm[i]), RES2INT16(pcm[i])), shift);
/* Normalize energy by the frame size and left-shift back to the original position */ /* Normalize energy by the frame size and left-shift back to the original position */
energy /= len; energy /= len;
@@ -1042,7 +1106,7 @@ static int compute_redundancy_bytes(opus_int32 max_data_bytes, opus_int32 bitrat
return redundancy_bytes; return redundancy_bytes;
} }
static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 max_data_bytes, unsigned char *data, opus_int32 max_data_bytes,
int float_api, int first_frame, int float_api, int first_frame,
#ifdef ENABLE_DRED #ifdef ENABLE_DRED
@@ -1054,7 +1118,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
int redundancy, int celt_to_silk, int prefill, int redundancy, int celt_to_silk, int prefill,
opus_int32 equiv_rate, int to_celt); opus_int32 equiv_rate, int to_celt);
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth, unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api) int analysis_channels, downmix_func downmix, int float_api)
@@ -1562,6 +1626,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
unsigned char *curr_data; unsigned char *curr_data;
int tmp_len; int tmp_len;
int dtx_count = 0; int dtx_count = 0;
int bak_to_mono;
if (st->mode == MODE_SILK_ONLY) if (st->mode == MODE_SILK_ONLY)
{ {
@@ -1606,7 +1671,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
opus_repacketizer_init(rp); opus_repacketizer_init(rp);
int bak_to_mono = st->silk_mode.toMono; bak_to_mono = st->silk_mode.toMono;
if (bak_to_mono) if (bak_to_mono)
st->force_channels = 1; st->force_channels = 1;
else else
@@ -1695,7 +1760,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
} }
} }
static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 max_data_bytes, unsigned char *data, opus_int32 max_data_bytes,
int float_api, int first_frame, int float_api, int first_frame,
#ifdef ENABLE_DRED #ifdef ENABLE_DRED
@@ -1728,8 +1793,8 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
int delay_compensation; int delay_compensation;
int total_buffer; int total_buffer;
opus_int activity = VAD_NO_DECISION; opus_int activity = VAD_NO_DECISION;
VARDECL(opus_val16, pcm_buf); VARDECL(opus_res, pcm_buf);
VARDECL(opus_val16, tmp_prefill); VARDECL(opus_res, tmp_prefill);
SAVE_STACK; SAVE_STACK;
st->rangeFinal = 0; st->rangeFinal = 0;
@@ -1790,7 +1855,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
ec_enc_init(&enc, data, max_data_bytes-1); ec_enc_init(&enc, data, max_data_bytes-1);
ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16); ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_res);
OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels); OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels);
if (st->mode == MODE_CELT_ONLY) if (st->mode == MODE_CELT_ONLY)
@@ -1866,12 +1931,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
if (st->mode != MODE_CELT_ONLY) if (st->mode != MODE_CELT_ONLY)
{ {
opus_int32 total_bitRate, celt_rate; opus_int32 total_bitRate, celt_rate;
#ifdef FIXED_POINT const opus_res *pcm_silk;
const opus_int16 *pcm_silk;
#else
VARDECL(opus_int16, pcm_silk);
ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
#endif
/* Distribute bits between SILK and CELT */ /* Distribute bits between SILK and CELT */
total_bitRate = 8 * bytes_target * frame_rate; total_bitRate = 8 * bytes_target * frame_rate;
@@ -1895,7 +1955,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
if (st->energy_masking && st->use_vbr && !st->lfe) if (st->energy_masking && st->use_vbr && !st->lfe)
{ {
opus_val32 mask_sum=0; opus_val32 mask_sum=0;
opus_val16 masking_depth; celt_glog masking_depth;
opus_int32 rate_offset; opus_int32 rate_offset;
int c; int c;
int end = 17; int end = 17;
@@ -1913,18 +1973,18 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
{ {
for(i=0;i<end;i++) for(i=0;i<end;i++)
{ {
opus_val16 mask; celt_glog mask;
mask = MAX16(MIN16(st->energy_masking[21*c+i], mask = MAXG(MING(st->energy_masking[21*c+i],
QCONST16(.5f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); GCONST(.5f)), -GCONST(2.0f));
if (mask > 0) if (mask > 0)
mask = HALF16(mask); mask = HALF32(mask);
mask_sum += mask; mask_sum += mask;
} }
} }
/* Conservative rate reduction, we cut the masking in half */ /* Conservative rate reduction, we cut the masking in half */
masking_depth = mask_sum / end*st->channels; masking_depth = mask_sum / end*st->channels;
masking_depth += QCONST16(.2f, DB_SHIFT); masking_depth += GCONST(.2f);
rate_offset = (opus_int32)PSHR32(MULT16_16(srate, masking_depth), DB_SHIFT); rate_offset = (opus_int32)PSHR32(MULT16_16(srate, SHR32(masking_depth, DB_SHIFT-10)), 10);
rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3); rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3);
/* Split the rate change between the SILK and CELT part for hybrid. */ /* Split the rate change between the SILK and CELT part for hybrid. */
if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND) if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND)
@@ -2024,23 +2084,13 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset, gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset,
0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs); 0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs);
OPUS_CLEAR(st->delay_buffer, prefill_offset); OPUS_CLEAR(st->delay_buffer, prefill_offset);
#ifdef FIXED_POINT
pcm_silk = st->delay_buffer; pcm_silk = st->delay_buffer;
#else
for (i=0;i<st->encoder_buffer*st->channels;i++)
pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
#endif
silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, prefill, activity ); silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, prefill, activity );
/* Prevent a second switch in the real encode call. */ /* Prevent a second switch in the real encode call. */
st->silk_mode.opusCanSwitch = 0; st->silk_mode.opusCanSwitch = 0;
} }
#ifdef FIXED_POINT
pcm_silk = pcm_buf+total_buffer*st->channels; pcm_silk = pcm_buf+total_buffer*st->channels;
#else
for (i=0;i<frame_size*st->channels;i++)
pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]);
#endif
ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0, activity ); ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0, activity );
if( ret ) { if( ret ) {
/*fprintf (stderr, "SILK encode error: %d\n", ret);*/ /*fprintf (stderr, "SILK encode error: %d\n", ret);*/
@@ -2115,7 +2165,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred)); celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred));
} }
ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16); ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_res);
if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0) if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0)
{ {
OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400); OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400);
@@ -2458,50 +2508,24 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pc
return ret; return ret;
} }
#ifdef FIXED_POINT
#ifndef DISABLE_FLOAT_API
opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, #if defined(FIXED_POINT) && !defined(ENABLE_RES24)
opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes) unsigned char *data, opus_int32 max_data_bytes)
{
int i, ret;
int frame_size;
VARDECL(opus_int16, in);
ALLOC_STACK;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
if (frame_size <= 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
ALLOC(in, frame_size*st->channels, opus_int16);
for (i=0;i<frame_size*st->channels;i++)
in[i] = FLOAT2INT16(pcm[i]);
ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
RESTORE_STACK;
return ret;
}
#endif
opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 out_data_bytes)
{ {
int frame_size; int frame_size;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs); frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, return opus_encode_native(st, pcm, frame_size, data, max_data_bytes, 16,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
} }
#else #else
opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes) unsigned char *data, opus_int32 max_data_bytes)
{ {
int i, ret; int i, ret;
int frame_size; int frame_size;
VARDECL(float, in); VARDECL(opus_res, in);
ALLOC_STACK; ALLOC_STACK;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs); frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
@@ -2510,23 +2534,90 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram
RESTORE_STACK; RESTORE_STACK;
return OPUS_BAD_ARG; return OPUS_BAD_ARG;
} }
ALLOC(in, frame_size*st->channels, float); ALLOC(in, frame_size*st->channels, opus_res);
for (i=0;i<frame_size*st->channels;i++) for (i=0;i<frame_size*st->channels;i++)
in[i] = (1.0f/32768)*pcm[i]; in[i] = INT16TORES(pcm[i]);
ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0); pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 1);
RESTORE_STACK; RESTORE_STACK;
return ret; return ret;
} }
#endif
#if defined(FIXED_POINT) && defined(ENABLE_RES24)
opus_int32 opus_encode24(OpusEncoder *st, const opus_int32 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes)
{
int frame_size;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
return opus_encode_native(st, pcm, frame_size, data, max_data_bytes, MAX_ENCODING_DEPTH,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_int24, 0);
}
#else
opus_int32 opus_encode24(OpusEncoder *st, const opus_int32 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes)
{
int i, ret;
int frame_size;
VARDECL(opus_res, in);
ALLOC_STACK;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
if (frame_size <= 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
ALLOC(in, frame_size*st->channels, opus_res);
for (i=0;i<frame_size*st->channels;i++)
in[i] = INT24TORES(pcm[i]);
ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, MAX_ENCODING_DEPTH,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_int24, 1);
RESTORE_STACK;
return ret;
}
#endif
#ifndef DISABLE_FLOAT_API
# if !defined(FIXED_POINT)
opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 out_data_bytes) unsigned char *data, opus_int32 out_data_bytes)
{ {
int frame_size; int frame_size;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs); frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, MAX_ENCODING_DEPTH,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1); pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
} }
# else
opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes)
{
int i, ret;
int frame_size;
VARDECL(opus_res, in);
ALLOC_STACK;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
if (frame_size <= 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
ALLOC(in, frame_size*st->channels, opus_res);
for (i=0;i<frame_size*st->channels;i++)
in[i] = FLOAT2RES(pcm[i]);
ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, MAX_ENCODING_DEPTH,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
RESTORE_STACK;
return ret;
}
# endif
#endif #endif
@@ -3014,7 +3105,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
break; break;
case OPUS_SET_ENERGY_MASK_REQUEST: case OPUS_SET_ENERGY_MASK_REQUEST:
{ {
opus_val16 *value = va_arg(ap, opus_val16*); celt_glog *value = va_arg(ap, celt_glog*);
st->energy_masking = value; st->energy_masking = value;
ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value)); ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
} }

View File

@@ -193,7 +193,7 @@ int opus_multistream_decode_native(
int s, c; int s, c;
char *ptr; char *ptr;
int do_plc=0; int do_plc=0;
VARDECL(opus_val16, buf); VARDECL(opus_res, buf);
ALLOC_STACK; ALLOC_STACK;
VALIDATE_MS_DECODER(st); VALIDATE_MS_DECODER(st);
@@ -205,7 +205,7 @@ int opus_multistream_decode_native(
/* Limit frame_size to avoid excessive stack allocations. */ /* Limit frame_size to avoid excessive stack allocations. */
MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs))); MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
frame_size = IMIN(frame_size, Fs/25*3); frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_val16); ALLOC(buf, 2*frame_size, opus_res);
ptr = (char*)st + align(sizeof(OpusMSDecoder)); ptr = (char*)st + align(sizeof(OpusMSDecoder));
coupled_size = opus_decoder_get_size(2); coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1); mono_size = opus_decoder_get_size(1);
@@ -311,7 +311,7 @@ static void opus_copy_channel_out_float(
void *dst, void *dst,
int dst_stride, int dst_stride,
int dst_channel, int dst_channel,
const opus_val16 *src, const opus_res *src,
int src_stride, int src_stride,
int frame_size, int frame_size,
void *user_data void *user_data
@@ -324,11 +324,7 @@ static void opus_copy_channel_out_float(
if (src != NULL) if (src != NULL)
{ {
for (i=0;i<frame_size;i++) for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT) float_dst[i*dst_stride+dst_channel] = RES2FLOAT(src[i*src_stride]);
float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
#else
float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
#endif
} }
else else
{ {
@@ -342,7 +338,7 @@ static void opus_copy_channel_out_short(
void *dst, void *dst,
int dst_stride, int dst_stride,
int dst_channel, int dst_channel,
const opus_val16 *src, const opus_res *src,
int src_stride, int src_stride,
int frame_size, int frame_size,
void *user_data void *user_data
@@ -355,11 +351,7 @@ static void opus_copy_channel_out_short(
if (src != NULL) if (src != NULL)
{ {
for (i=0;i<frame_size;i++) for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT) short_dst[i*dst_stride+dst_channel] = RES2INT16(src[i*src_stride]);
short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
#else
short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
#endif
} }
else else
{ {
@@ -368,9 +360,38 @@ static void opus_copy_channel_out_short(
} }
} }
static void opus_copy_channel_out_int24(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data
)
{
opus_int32 *short_dst;
opus_int32 i;
(void)user_data;
short_dst = (opus_int32*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = RES2INT24(src[i*src_stride]);
}
else
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = 0;
}
}
#ifdef FIXED_POINT #ifdef FIXED_POINT
#define OPTIONAL_CLIP 0
#else
#define OPTIONAL_CLIP 1
#endif
int opus_multistream_decode( int opus_multistream_decode(
OpusMSDecoder *st, OpusMSDecoder *st,
const unsigned char *data, const unsigned char *data,
@@ -381,7 +402,20 @@ int opus_multistream_decode(
) )
{ {
return opus_multistream_decode_native(st, data, len, return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL); pcm, opus_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP, NULL);
}
int opus_multistream_decode24(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int32 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_int24, frame_size, decode_fec, 0, NULL);
} }
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
@@ -393,29 +427,6 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
} }
#endif #endif
#else
int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
}
int opus_multistream_decode_float(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_val16 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request, int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
va_list ap) va_list ap)
{ {

View File

@@ -184,35 +184,35 @@ static void channel_pos(int channels, int pos[8])
#if 1 #if 1
/* Computes a rough approximation of log2(2^a + 2^b) */ /* Computes a rough approximation of log2(2^a + 2^b) */
static opus_val16 logSum(opus_val16 a, opus_val16 b) static opus_val16 logSum(celt_glog a, celt_glog b)
{ {
opus_val16 max; celt_glog max;
opus_val32 diff; celt_glog diff;
opus_val16 frac; celt_glog frac;
static const opus_val16 diff_table[17] = { static const celt_glog diff_table[17] = {
QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT), GCONST(0.5000000f), GCONST(0.2924813f), GCONST(0.1609640f), GCONST(0.0849625f),
QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT), GCONST(0.0437314f), GCONST(0.0221971f), GCONST(0.0111839f), GCONST(0.0056136f),
QCONST16(0.0028123f, DB_SHIFT) GCONST(0.0028123f)
}; };
int low; int low;
if (a>b) if (a>b)
{ {
max = a; max = a;
diff = SUB32(EXTEND32(a),EXTEND32(b)); diff = SUB32(a,b);
} else { } else {
max = b; max = b;
diff = SUB32(EXTEND32(b),EXTEND32(a)); diff = SUB32(b,a);
} }
if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */ if (!(diff < GCONST(8.f))) /* inverted to catch NaNs */
return max; return max;
#ifdef FIXED_POINT #ifdef FIXED_POINT
low = SHR32(diff, DB_SHIFT-1); low = SHR32(diff, DB_SHIFT-1);
frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT); frac = VSHR32(diff - SHL32(low, DB_SHIFT-1), DB_SHIFT-16);
#else #else
low = (int)floor(2*diff); low = (int)floor(2*diff);
frac = 2*diff - low; frac = 2*diff - low;
#endif #endif
return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low])); return max + diff_table[low] + MULT16_32_Q15(frac, SUB32(diff_table[low+1], diff_table[low]));
} }
#else #else
opus_val16 logSum(opus_val16 a, opus_val16 b) opus_val16 logSum(opus_val16 a, opus_val16 b)
@@ -221,7 +221,7 @@ opus_val16 logSum(opus_val16 a, opus_val16 b)
} }
#endif #endif
void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem, void surround_analysis(const CELTMode *celt_mode, const void *pcm, celt_glog *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch
) )
{ {
@@ -234,9 +234,9 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
int freq_size; int freq_size;
opus_val16 channel_offset; opus_val16 channel_offset;
opus_val32 bandE[21]; opus_val32 bandE[21];
opus_val16 maskLogE[3][21]; celt_glog maskLogE[3][21];
VARDECL(opus_val32, in); VARDECL(opus_val32, in);
VARDECL(opus_val16, x); VARDECL(opus_res, x);
VARDECL(opus_val32, freq); VARDECL(opus_val32, freq);
SAVE_STACK; SAVE_STACK;
@@ -250,14 +250,14 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
break; break;
ALLOC(in, frame_size+overlap, opus_val32); ALLOC(in, frame_size+overlap, opus_val32);
ALLOC(x, len, opus_val16); ALLOC(x, len, opus_res);
ALLOC(freq, freq_size, opus_val32); ALLOC(freq, freq_size, opus_val32);
channel_pos(channels, pos); channel_pos(channels, pos);
for (c=0;c<3;c++) for (c=0;c<3;c++)
for (i=0;i<21;i++) for (i=0;i<21;i++)
maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT); maskLogE[c][i] = -GCONST(28.f);
for (c=0;c<channels;c++) for (c=0;c<channels;c++)
{ {
@@ -303,9 +303,9 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1); amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
/* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */ /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
for (i=1;i<21;i++) for (i=1;i<21;i++)
bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT)); bandLogE[21*c+i] = MAXG(bandLogE[21*c+i], bandLogE[21*c+i-1]-GCONST(1.f));
for (i=19;i>=0;i--) for (i=19;i>=0;i--)
bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT)); bandLogE[21*c+i] = MAXG(bandLogE[21*c+i], bandLogE[21*c+i+1]-GCONST(2.f));
if (pos[c]==1) if (pos[c]==1)
{ {
for (i=0;i<21;i++) for (i=0;i<21;i++)
@@ -318,8 +318,8 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
{ {
for (i=0;i<21;i++) for (i=0;i<21;i++)
{ {
maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-GCONST(.5f));
maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-GCONST(.5f));
} }
} }
#if 0 #if 0
@@ -347,7 +347,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
#endif #endif
for (c=0;c<channels;c++) for (c=0;c<channels;c++)
{ {
opus_val16 *mask; celt_glog *mask;
if (pos[c]!=0) if (pos[c]!=0)
{ {
mask = &maskLogE[pos[c]-1][0]; mask = &maskLogE[pos[c]-1][0];
@@ -819,14 +819,14 @@ int opus_multistream_encode_native
int s; int s;
char *ptr; char *ptr;
int tot_size; int tot_size;
VARDECL(opus_val16, buf); VARDECL(opus_res, buf);
VARDECL(opus_val16, bandSMR); VARDECL(celt_glog, bandSMR);
unsigned char tmp_data[MS_FRAME_TMP]; unsigned char tmp_data[MS_FRAME_TMP];
OpusRepacketizer rp; OpusRepacketizer rp;
opus_int32 vbr; opus_int32 vbr;
const CELTMode *celt_mode; const CELTMode *celt_mode;
opus_int32 bitrates[256]; opus_int32 bitrates[256];
opus_val16 bandLogE[42]; celt_glog bandLogE[42];
opus_val32 *mem = NULL; opus_val32 *mem = NULL;
opus_val32 *preemph_mem=NULL; opus_val32 *preemph_mem=NULL;
int frame_size; int frame_size;
@@ -862,11 +862,11 @@ int opus_multistream_encode_native
RESTORE_STACK; RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL; return OPUS_BUFFER_TOO_SMALL;
} }
ALLOC(buf, 2*frame_size, opus_val16); ALLOC(buf, 2*frame_size, opus_res);
coupled_size = opus_encoder_get_size(2); coupled_size = opus_encoder_get_size(2);
mono_size = opus_encoder_get_size(1); mono_size = opus_encoder_get_size(1);
ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16); ALLOC(bandSMR, 21*st->layout.nb_channels, celt_glog);
if (st->mapping_type == MAPPING_TYPE_SURROUND) if (st->mapping_type == MAPPING_TYPE_SURROUND)
{ {
surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch); surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
@@ -1014,7 +1014,7 @@ int opus_multistream_encode_native
#if !defined(DISABLE_FLOAT_API) #if !defined(DISABLE_FLOAT_API)
static void opus_copy_channel_in_float( static void opus_copy_channel_in_float(
opus_val16 *dst, opus_res *dst,
int dst_stride, int dst_stride,
const void *src, const void *src,
int src_stride, int src_stride,
@@ -1028,16 +1028,12 @@ static void opus_copy_channel_in_float(
(void)user_data; (void)user_data;
float_src = (const float *)src; float_src = (const float *)src;
for (i=0;i<frame_size;i++) for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT) dst[i*dst_stride] = FLOAT2RES(float_src[i*src_stride+src_channel]);
dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
#else
dst[i*dst_stride] = float_src[i*src_stride+src_channel];
#endif
} }
#endif #endif
static void opus_copy_channel_in_short( static void opus_copy_channel_in_short(
opus_val16 *dst, opus_res *dst,
int dst_stride, int dst_stride,
const void *src, const void *src,
int src_stride, int src_stride,
@@ -1051,54 +1047,25 @@ static void opus_copy_channel_in_short(
(void)user_data; (void)user_data;
short_src = (const opus_int16 *)src; short_src = (const opus_int16 *)src;
for (i=0;i<frame_size;i++) for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT) dst[i*dst_stride] = INT16TORES(short_src[i*src_stride+src_channel]);
dst[i*dst_stride] = short_src[i*src_stride+src_channel];
#else
dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
#endif
} }
static void opus_copy_channel_in_int24(
#ifdef FIXED_POINT opus_res *dst,
int opus_multistream_encode( int dst_stride,
OpusMSEncoder *st, const void *src,
const opus_val16 *pcm, int src_stride,
int src_channel,
int frame_size, int frame_size,
unsigned char *data, void *user_data
opus_int32 max_data_bytes
) )
{ {
return opus_multistream_encode_native(st, opus_copy_channel_in_short, const opus_int32 *short_src;
pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL); opus_int32 i;
} (void)user_data;
short_src = (const opus_int32 *)src;
#ifndef DISABLE_FLOAT_API for (i=0;i<frame_size;i++)
int opus_multistream_encode_float( dst[i*dst_stride] = INT24TORES(short_src[i*src_stride+src_channel]);
OpusMSEncoder *st,
const float *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
}
#endif
#else
int opus_multistream_encode_float
(
OpusMSEncoder *st,
const opus_val16 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
} }
int opus_multistream_encode( int opus_multistream_encode(
@@ -1112,6 +1079,31 @@ int opus_multistream_encode(
return opus_multistream_encode_native(st, opus_copy_channel_in_short, return opus_multistream_encode_native(st, opus_copy_channel_in_short,
pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL); pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
} }
int opus_multistream_encode24(
OpusMSEncoder *st,
const opus_int32 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_int24,
pcm, frame_size, data, max_data_bytes, MAX_ENCODING_DEPTH, downmix_int24, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
int opus_multistream_encode_float(
OpusMSEncoder *st,
const float *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
pcm, frame_size, data, max_data_bytes, MAX_ENCODING_DEPTH, downmix_float, 1, NULL);
}
#endif #endif
int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request, int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,

View File

@@ -125,7 +125,7 @@ int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev); int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
typedef void (*opus_copy_channel_in_func)( typedef void (*opus_copy_channel_in_func)(
opus_val16 *dst, opus_res *dst,
int dst_stride, int dst_stride,
const void *src, const void *src,
int src_stride, int src_stride,
@@ -138,7 +138,7 @@ typedef void (*opus_copy_channel_out_func)(
void *dst, void *dst,
int dst_stride, int dst_stride,
int dst_channel, int dst_channel,
const opus_val16 *src, const opus_res *src,
int src_stride, int src_stride,
int frame_size, int frame_size,
void *user_data void *user_data
@@ -174,19 +174,20 @@ typedef void (*opus_copy_channel_out_func)(
typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int); typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C); void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C); void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth); void downmix_int24(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth);
int encode_size(int size, unsigned char *data); int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs); opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth, unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api); int analysis_channels, downmix_func downmix, int float_api);
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, opus_res *pcm, int frame_size, int decode_fec, int self_delimited,
opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset); opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset);
/* Make sure everything is properly aligned. */ /* Make sure everything is properly aligned. */

View File

@@ -49,7 +49,7 @@ static void opus_projection_copy_channel_out_float(
void *dst, void *dst,
int dst_stride, int dst_stride,
int dst_channel, int dst_channel,
const opus_val16 *src, const opus_res *src,
int src_stride, int src_stride,
int frame_size, int frame_size,
void *user_data) void *user_data)
@@ -72,7 +72,7 @@ static void opus_projection_copy_channel_out_short(
void *dst, void *dst,
int dst_stride, int dst_stride,
int dst_channel, int dst_channel,
const opus_val16 *src, const opus_res *src,
int src_stride, int src_stride,
int frame_size, int frame_size,
void *user_data) void *user_data)
@@ -89,6 +89,27 @@ static void opus_projection_copy_channel_out_short(
src_stride, short_dst, dst_stride, frame_size); src_stride, short_dst, dst_stride, frame_size);
} }
static void opus_projection_copy_channel_out_int24(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data)
{
opus_int32 *short_dst;
const MappingMatrix *matrix;
short_dst = (opus_int32 *)dst;
matrix = (const MappingMatrix *)user_data;
if (dst_channel == 0)
OPUS_CLEAR(short_dst, frame_size * dst_stride);
if (src != NULL)
mapping_matrix_multiply_channel_out_int24(matrix, src, dst_channel,
src_stride, short_dst, dst_stride, frame_size);
}
static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st) static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
{ {
/* void* cast avoids clang -Wcast-align warning */ /* void* cast avoids clang -Wcast-align warning */
@@ -210,24 +231,28 @@ OpusProjectionDecoder *opus_projection_decoder_create(
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data, #define OPTIONAL_CLIP 0
opus_int32 len, opus_int16 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st));
}
#else #else
#define OPTIONAL_CLIP 1
#endif
int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data, int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, opus_int32 len, opus_int16 *pcm, int frame_size,
int decode_fec) int decode_fec)
{ {
return opus_multistream_decode_native(get_multistream_decoder(st), data, len, return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 1, pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP,
get_dec_demixing_matrix(st));
}
int opus_projection_decode24(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int32 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_int24, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st)); get_dec_demixing_matrix(st));
} }
#endif
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data, int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,

View File

@@ -47,7 +47,7 @@ struct OpusProjectionEncoder
#if !defined(DISABLE_FLOAT_API) #if !defined(DISABLE_FLOAT_API)
static void opus_projection_copy_channel_in_float( static void opus_projection_copy_channel_in_float(
opus_val16 *dst, opus_res *dst,
int dst_stride, int dst_stride,
const void *src, const void *src,
int src_stride, int src_stride,
@@ -62,7 +62,7 @@ static void opus_projection_copy_channel_in_float(
#endif #endif
static void opus_projection_copy_channel_in_short( static void opus_projection_copy_channel_in_short(
opus_val16 *dst, opus_res *dst,
int dst_stride, int dst_stride,
const void *src, const void *src,
int src_stride, int src_stride,
@@ -75,6 +75,20 @@ static void opus_projection_copy_channel_in_short(
(const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size); (const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
} }
static void opus_projection_copy_channel_in_int24(
opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_int24((const MappingMatrix*)user_data,
(const opus_int32*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
static int get_order_plus_one_from_channels(int channels, int *order_plus_one) static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
{ {
int order_plus_one_; int order_plus_one_;
@@ -392,26 +406,24 @@ int opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st)); max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
} }
int opus_projection_encode24(OpusProjectionEncoder *st, const opus_int32 *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_int24, pcm, frame_size, data,
max_data_bytes, MAX_ENCODING_DEPTH, downmix_int, 0, get_mixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
#ifdef FIXED_POINT
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm, int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data, int frame_size, unsigned char *data,
opus_int32 max_data_bytes) opus_int32 max_data_bytes)
{ {
return opus_multistream_encode_native(get_multistream_encoder(st), return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_float, pcm, frame_size, data, opus_projection_copy_channel_in_float, pcm, frame_size, data,
max_data_bytes, 16, downmix_float, 1, get_mixing_matrix(st)); max_data_bytes, MAX_ENCODING_DEPTH, downmix_float, 1, get_mixing_matrix(st));
} }
#else
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_float, pcm, frame_size, data,
max_data_bytes, 24, downmix_float, 1, get_mixing_matrix(st));
}
#endif
#endif #endif
void opus_projection_encoder_destroy(OpusProjectionEncoder *st) void opus_projection_encoder_destroy(OpusProjectionEncoder *st)

View File

@@ -158,10 +158,10 @@ opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
/* incorporate any extensions from the repacketizer padding */ /* incorporate any extensions from the repacketizer padding */
for (i=begin;i<end;i++) for (i=begin;i<end;i++)
{ {
int j; int j, ret;
opus_int32 frame_ext_count; opus_int32 frame_ext_count;
frame_ext_count = total_ext_count - ext_count; frame_ext_count = total_ext_count - ext_count;
int ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i], ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i],
&all_extensions[ext_count], &frame_ext_count, rp->padding_nb_frames[i]); &all_extensions[ext_count], &frame_ext_count, rp->padding_nb_frames[i]);
if (ret<0) if (ret<0)
{ {