Bug 1961240 - Update opus to a41a344a2e30455ce4d1f6662b85332a70dc4b52 r=padenot
Differential Revision: https://phabricator.services.mozilla.com/D245968
This commit is contained in:
@@ -103,6 +103,8 @@ void celt_fatal(const char *str, const char *file, int line)
|
||||
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
|
||||
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */
|
||||
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
|
||||
#define FMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum float value. */
|
||||
#define FMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum float value. */
|
||||
#define UADD32(a,b) ((a)+(b))
|
||||
#define USUB32(a,b) ((a)-(b))
|
||||
#define MAXG(a,b) MAX32(a, b)
|
||||
|
||||
@@ -46,6 +46,14 @@ void (*const CELT_FLOAT2INT16_IMPL[OPUS_ARCHMASK+1])(const float * OPUS_RESTRICT
|
||||
celt_float2int16_neon,/* NEON */
|
||||
celt_float2int16_neon /* DOTPROD */
|
||||
};
|
||||
|
||||
int (*const OPUS_LIMIT2_CHECKWITHIN1_IMPL[OPUS_ARCHMASK+1])(float * samples, int cnt) = {
|
||||
opus_limit2_checkwithin1_c, /* ARMv4 */
|
||||
opus_limit2_checkwithin1_c, /* EDSP */
|
||||
opus_limit2_checkwithin1_c, /* Media */
|
||||
opus_limit2_checkwithin1_neon,/* NEON */
|
||||
opus_limit2_checkwithin1_neon /* DOTPROD */
|
||||
};
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
||||
@@ -86,8 +86,85 @@ void celt_float2int16_neon(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT
|
||||
out[i] = FLOAT2INT16(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int opus_limit2_checkwithin1_neon(float *samples, int cnt)
|
||||
{
|
||||
const float hardclipMin = -2.0f;
|
||||
const float hardclipMax = 2.0f;
|
||||
|
||||
int i = 0;
|
||||
int exceeding1 = 0;
|
||||
int nextIndex = 0;
|
||||
|
||||
#if defined(__ARM_NEON)
|
||||
const int BLOCK_SIZE = 16;
|
||||
const int blockedSize = cnt / BLOCK_SIZE * BLOCK_SIZE;
|
||||
|
||||
float32x4_t min_all_0 = vdupq_n_f32(0.0f);
|
||||
float32x4_t min_all_1 = vdupq_n_f32(0.0f);
|
||||
float32x4_t max_all_0 = vdupq_n_f32(0.0f);
|
||||
float32x4_t max_all_1 = vdupq_n_f32(0.0f);
|
||||
|
||||
float max, min;
|
||||
|
||||
for (i = 0; i < blockedSize; i += BLOCK_SIZE)
|
||||
{
|
||||
const float32x4_t orig_a = vld1q_f32(&samples[i + 0]);
|
||||
const float32x4_t orig_b = vld1q_f32(&samples[i + 4]);
|
||||
const float32x4_t orig_c = vld1q_f32(&samples[i + 8]);
|
||||
const float32x4_t orig_d = vld1q_f32(&samples[i + 12]);
|
||||
max_all_0 = vmaxq_f32(max_all_0, vmaxq_f32(orig_a, orig_b));
|
||||
max_all_1 = vmaxq_f32(max_all_1, vmaxq_f32(orig_c, orig_d));
|
||||
min_all_0 = vminq_f32(min_all_0, vminq_f32(orig_a, orig_b));
|
||||
min_all_1 = vminq_f32(min_all_1, vminq_f32(orig_c, orig_d));
|
||||
}
|
||||
|
||||
max = vmaxvf(vmaxq_f32(max_all_0, max_all_1));
|
||||
min = vminvf(vminq_f32(min_all_0, min_all_1));
|
||||
|
||||
if (min < hardclipMin || max > hardclipMax)
|
||||
{
|
||||
const float32x4_t hardclipMinReg = vdupq_n_f32(hardclipMin);
|
||||
const float32x4_t hardclipMaxReg = vdupq_n_f32(hardclipMax);
|
||||
for (i = 0; i < blockedSize; i += BLOCK_SIZE)
|
||||
{
|
||||
const float32x4_t orig_a = vld1q_f32(&samples[i + 0]);
|
||||
const float32x4_t orig_b = vld1q_f32(&samples[i + 4]);
|
||||
const float32x4_t orig_c = vld1q_f32(&samples[i + 8]);
|
||||
const float32x4_t orig_d = vld1q_f32(&samples[i + 12]);
|
||||
const float32x4_t clipped_a = vminq_f32(hardclipMaxReg, vmaxq_f32(orig_a, hardclipMinReg));
|
||||
const float32x4_t clipped_b = vminq_f32(hardclipMaxReg, vmaxq_f32(orig_b, hardclipMinReg));
|
||||
const float32x4_t clipped_c = vminq_f32(hardclipMaxReg, vmaxq_f32(orig_c, hardclipMinReg));
|
||||
const float32x4_t clipped_d = vminq_f32(hardclipMaxReg, vmaxq_f32(orig_d, hardclipMinReg));
|
||||
vst1q_f32(&samples[i + 0], clipped_a);
|
||||
vst1q_f32(&samples[i + 4], clipped_b);
|
||||
vst1q_f32(&samples[i + 8], clipped_c);
|
||||
vst1q_f32(&samples[i + 12], clipped_d);
|
||||
}
|
||||
}
|
||||
|
||||
nextIndex = blockedSize;
|
||||
exceeding1 |= max > 1.0f || min < -1.0f;
|
||||
|
||||
#endif
|
||||
|
||||
for (i = nextIndex; i < cnt; i++)
|
||||
{
|
||||
const float origVal = samples[i];
|
||||
float clippedVal = origVal;
|
||||
clippedVal = MAX16(hardclipMin, clippedVal);
|
||||
clippedVal = MIN16(hardclipMax, clippedVal);
|
||||
samples[i] = clippedVal;
|
||||
|
||||
exceeding1 |= origVal > 1.0f || origVal < -1.0f;
|
||||
}
|
||||
|
||||
return !exceeding1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FIXED_POINT)
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -46,6 +46,30 @@ static inline int32x4_t vroundf(float32x4_t x)
|
||||
# endif
|
||||
}
|
||||
|
||||
static inline float vminvf(float32x4_t a)
|
||||
{
|
||||
#if defined(__aarch64__)
|
||||
return vminvq_f32(a);
|
||||
#else
|
||||
float32x2_t xy = vmin_f32(vget_low_f32(a), vget_high_f32(a));
|
||||
float x = vget_lane_f32(xy, 0);
|
||||
float y = vget_lane_f32(xy, 1);
|
||||
return x < y ? x : y;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline float vmaxvf(float32x4_t a)
|
||||
{
|
||||
#if defined(__aarch64__)
|
||||
return vmaxvq_f32(a);
|
||||
#else
|
||||
float32x2_t xy = vmax_f32(vget_low_f32(a), vget_high_f32(a));
|
||||
float x = vget_lane_f32(xy, 0);
|
||||
float y = vget_lane_f32(xy, 1);
|
||||
return x > y ? x : y;
|
||||
#endif
|
||||
}
|
||||
|
||||
void celt_float2int16_neon(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt);
|
||||
# if defined(OPUS_HAVE_RTCD) && \
|
||||
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
@@ -60,6 +84,20 @@ extern void
|
||||
# define OVERRIDE_FLOAT2INT16 (1)
|
||||
# define celt_float2int16(in, out, cnt, arch) ((void)(arch), celt_float2int16_neon(in, out, cnt))
|
||||
# endif
|
||||
|
||||
int opus_limit2_checkwithin1_neon(float * samples, int cnt);
|
||||
# if defined(OPUS_HAVE_RTCD) && \
|
||||
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern int (*const OPUS_LIMIT2_CHECKWITHIN1_IMPL[OPUS_ARCHMASK+1])(float * samples, int cnt);
|
||||
|
||||
# define OVERRIDE_LIMIT2_CHECKWITHIN1 (1)
|
||||
# define opus_limit2_checkwithin1(samples, cnt, arch) \
|
||||
((*OPUS_LIMIT2_CHECKWITHIN1_IMPL[(arch)&OPUS_ARCHMASK])(samples, cnt))
|
||||
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_LIMIT2_CHECKWITHIN1 (1)
|
||||
# define opus_limit2_checkwithin1(samples, cnt, arch) ((void)(arch), opus_limit2_checkwithin1_neon(samples, cnt))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* MATHOPS_ARM_H */
|
||||
|
||||
@@ -1042,8 +1042,34 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
|
||||
st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
|
||||
LM = (data0>>3)&0x3;
|
||||
C = 1 + ((data0>>2)&0x1);
|
||||
data++;
|
||||
len--;
|
||||
if ((data[0] & 0x03) == 0x03) {
|
||||
data++;
|
||||
len--;
|
||||
if (len<=0)
|
||||
return OPUS_INVALID_PACKET;
|
||||
if (data[0] & 0x40) {
|
||||
int p;
|
||||
int padding=0;
|
||||
data++;
|
||||
len--;
|
||||
do {
|
||||
int tmp;
|
||||
if (len<=0)
|
||||
return OPUS_INVALID_PACKET;
|
||||
p = *data++;
|
||||
len--;
|
||||
tmp = p==255 ? 254: p;
|
||||
len -= tmp;
|
||||
padding += tmp;
|
||||
} while (p==255);
|
||||
padding--;
|
||||
if (len <= 0 || padding<0) return OPUS_INVALID_PACKET;
|
||||
}
|
||||
} else
|
||||
{
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
if (LM>mode->maxLM)
|
||||
return OPUS_INVALID_PACKET;
|
||||
if (frame_size < mode->shortMdctSize<<LM)
|
||||
|
||||
@@ -229,4 +229,24 @@ void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT ou
|
||||
}
|
||||
}
|
||||
|
||||
int opus_limit2_checkwithin1_c(float * samples, int cnt)
|
||||
{
|
||||
int i;
|
||||
if (cnt <= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
float clippedVal = samples[i];
|
||||
clippedVal = FMAX(-2.0f, clippedVal);
|
||||
clippedVal = FMIN(2.0f, clippedVal);
|
||||
samples[i] = clippedVal;
|
||||
}
|
||||
|
||||
/* C implementation can't provide quick hint. Assume it might exceed -1/+1. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* DISABLE_FLOAT_API */
|
||||
|
||||
@@ -490,6 +490,12 @@ void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT ou
|
||||
#define celt_float2int16(in, out, cnt, arch) ((void)(arch), celt_float2int16_c(in, out, cnt))
|
||||
#endif
|
||||
|
||||
int opus_limit2_checkwithin1_c(float *samples, int cnt);
|
||||
|
||||
#ifndef OVERRIDE_LIMIT2_CHECKWITHIN1
|
||||
#define opus_limit2_checkwithin1(samples, cnt, arch) ((void)(arch), opus_limit2_checkwithin1_c(samples, cnt))
|
||||
#endif
|
||||
|
||||
#endif /* DISABLE_FLOAT_API */
|
||||
|
||||
#endif /* MATHOPS_H */
|
||||
|
||||
@@ -21,7 +21,7 @@ FINAL_LIBRARY = "gkcodecs"
|
||||
NoVisibilityFlags()
|
||||
|
||||
DEFINES["OPUS_BUILD"] = True
|
||||
DEFINES["OPUS_VERSION"] = "d8d7763369e2d5af79925c61bf4b4e7adccb38fa"
|
||||
DEFINES["OPUS_VERSION"] = "a41a344a2e30455ce4d1f6662b85332a70dc4b52"
|
||||
DEFINES["USE_ALLOCA"] = True
|
||||
DEFINES["ENABLE_HARDENING"] = True
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ origin:
|
||||
|
||||
# Human-readable identifier for this version/release
|
||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||
release: d8d7763369e2d5af79925c61bf4b4e7adccb38fa (2025-04-08T13:40:36.000-04:00).
|
||||
release: a41a344a2e30455ce4d1f6662b85332a70dc4b52 (2025-04-17T10:18:04.000-04:00).
|
||||
|
||||
# Revision to pull in
|
||||
# Must be a long or short commit SHA (long preferred)
|
||||
revision: d8d7763369e2d5af79925c61bf4b4e7adccb38fa
|
||||
revision: a41a344a2e30455ce4d1f6662b85332a70dc4b52
|
||||
|
||||
# The package's license, where possible using the mnemonic from
|
||||
# https://spdx.org/licenses/
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
|
||||
Copyright (c) 2024 Arm Limited
|
||||
Written by Jean-Marc Valin and Koen Vos */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,23 +31,40 @@
|
||||
#endif
|
||||
|
||||
#include "opus.h"
|
||||
#include "celt/mathops.h"
|
||||
#include "opus_private.h"
|
||||
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
|
||||
|
||||
void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch)
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
float *x;
|
||||
int all_within_neg1pos1;
|
||||
|
||||
if (C<1 || N<1 || !_x || !declip_mem) return;
|
||||
|
||||
/* First thing: saturate everything to +/- 2 which is the highest level our
|
||||
non-linearity can handle. At the point where the signal reaches +/-2,
|
||||
the derivative will be zero anyway, so this doesn't introduce any
|
||||
discontinuity in the derivative. */
|
||||
for (i=0;i<N*C;i++)
|
||||
_x[i] = MAX16(-2.f, MIN16(2.f, _x[i]));
|
||||
/* Clamp everything within the range [-2, +2] which is the domain of the soft
|
||||
clipping non-linearity. Outside the defined range the derivative will be zero,
|
||||
therefore there is no discontinuity introduced here. The implementation
|
||||
might provide a hint if all input samples are within the [-1, +1] range.
|
||||
|
||||
`opus_limit2_checkwithin1()`:
|
||||
- Clamps all samples within the valid range [-2, +2].
|
||||
- Generic C implementation:
|
||||
* Does not attempt early detection whether samples are within hinted range.
|
||||
* Always returns 0.
|
||||
- Architecture specific implementation:
|
||||
* Uses SIMD instructions to efficiently detect if all samples are
|
||||
within the hinted range [-1, +1].
|
||||
* Returns 1 if no samples exceed the hinted range, 0 otherwise.
|
||||
|
||||
`all_within_neg1pos1`:
|
||||
- Optimization hint to skip per-sample out-of-bound checks.
|
||||
If true, the check can be skipped. */
|
||||
all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch);
|
||||
|
||||
for (c=0;c<C;c++)
|
||||
{
|
||||
float a;
|
||||
@@ -72,10 +90,16 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
|
||||
float maxval;
|
||||
int special=0;
|
||||
int peak_pos;
|
||||
for (i=curr;i<N;i++)
|
||||
/* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */
|
||||
if (all_within_neg1pos1)
|
||||
{
|
||||
if (x[i*C]>1 || x[i*C]<-1)
|
||||
break;
|
||||
i = N;
|
||||
} else {
|
||||
for (i=curr;i<N;i++)
|
||||
{
|
||||
if (x[i*C]>1 || x[i*C]<-1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i==N)
|
||||
{
|
||||
@@ -135,6 +159,12 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
|
||||
declip_mem[c] = a;
|
||||
}
|
||||
}
|
||||
|
||||
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
|
||||
{
|
||||
opus_pcm_soft_clip_impl(_x, N, C, declip_mem, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int encode_size(int size, unsigned char *data)
|
||||
|
||||
@@ -814,7 +814,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
|
||||
OPUS_PRINT_INT(nb_samples);
|
||||
#ifndef FIXED_POINT
|
||||
if (soft_clip)
|
||||
opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem);
|
||||
opus_pcm_soft_clip_impl(pcm, nb_samples, st->channels, st->softclip_mem, st->arch);
|
||||
else
|
||||
st->softclip_mem[0]=st->softclip_mem[1]=0;
|
||||
#endif
|
||||
|
||||
@@ -1151,7 +1151,8 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_si
|
||||
#endif
|
||||
ALLOC_STACK;
|
||||
|
||||
max_data_bytes = IMIN(1276, out_data_bytes);
|
||||
/* Just avoid insane packet sizes here, but the real bounds are applied later on. */
|
||||
max_data_bytes = IMIN(1276*6, out_data_bytes);
|
||||
|
||||
st->rangeFinal = 0;
|
||||
if (frame_size <= 0 || max_data_bytes <= 0)
|
||||
@@ -1265,7 +1266,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_si
|
||||
st->bitrate_bps -= dred_bitrate_bps;
|
||||
#endif
|
||||
if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
|
||||
|| (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
|
||||
|| (frame_rate<50 && (max_data_bytes*(opus_int32)frame_rate<300 || st->bitrate_bps < 2400)))
|
||||
{
|
||||
/*If the space is too low to do something useful, emit 'PLC' frames.*/
|
||||
int tocmode = st->mode;
|
||||
@@ -1761,7 +1762,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_si
|
||||
}
|
||||
|
||||
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 orig_max_data_bytes,
|
||||
int float_api, int first_frame,
|
||||
#ifdef ENABLE_DRED
|
||||
opus_int32 dred_bitrate_bps,
|
||||
@@ -1777,6 +1778,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm,
|
||||
const CELTMode *celt_mode;
|
||||
int i;
|
||||
int ret=0;
|
||||
int max_data_bytes;
|
||||
opus_int32 nBytes;
|
||||
ec_enc enc;
|
||||
int bytes_target;
|
||||
@@ -1797,6 +1799,7 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm,
|
||||
VARDECL(opus_res, tmp_prefill);
|
||||
SAVE_STACK;
|
||||
|
||||
max_data_bytes = IMIN(orig_max_data_bytes, 1276);
|
||||
st->rangeFinal = 0;
|
||||
silk_enc = (char*)st+st->silk_enc_offset;
|
||||
celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
|
||||
@@ -2497,12 +2500,12 @@ static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm,
|
||||
#endif
|
||||
if (apply_padding)
|
||||
{
|
||||
if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK)
|
||||
if (opus_packet_pad(data, ret, orig_max_data_bytes) != OPUS_OK)
|
||||
{
|
||||
RESTORE_STACK;
|
||||
return OPUS_INTERNAL_ERROR;
|
||||
}
|
||||
ret = max_data_bytes;
|
||||
ret = orig_max_data_bytes;
|
||||
}
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
|
||||
@@ -177,6 +177,8 @@ void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int
|
||||
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);
|
||||
|
||||
void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch);
|
||||
|
||||
int encode_size(int size, unsigned char *data);
|
||||
|
||||
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
|
||||
|
||||
Reference in New Issue
Block a user