ref: 9f36bfc9623d0af495913b073a0b5e9e627e3086
parent: 9b1da1fb1f07265dda3621b30ea989911dd4f0bf
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Fri Feb 2 11:55:21 EST 2024
Chopping the oldest silence in a DRED payload
--- a/silk/dred_encoder.c
+++ b/silk/dred_encoder.c
@@ -249,7 +249,15 @@
}
}
-int dred_encode_silk_frame(const DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, int arch) {
+static int dred_voice_active(const unsigned char *activity_mem, int offset) {
+ int i;
+ for (i=0;i<16;i++) {
+ if (activity_mem[8*offset + i] == 1) return 1;
+ }
+ return 0;
+}
+
+int dred_encode_silk_frame(const DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, unsigned char *activity_mem, int arch) {
ec_enc ec_encoder;
int q_level;
@@ -257,6 +265,9 @@
int offset;
int ec_buffer_fill;
int state_qoffset;
+ ec_enc ec_bak;
+ int prev_active=0;
+ int dred_encoded=0;
/* entropy coding of state and latents */
ec_enc_init(&ec_encoder, buf, max_bytes);
@@ -276,11 +287,10 @@
if (ec_tell(&ec_encoder) > 8*max_bytes) {
return 0;
}
+ ec_bak = ec_encoder;
for (i = 0; i < IMIN(2*max_chunks, enc->latents_buffer_fill-enc->latent_offset-1); i += 2)
{
- ec_enc ec_bak;
- ec_bak = ec_encoder;
-
+ int active;
q_level = compute_quantizer(q0, dQ, i/2);
offset = q_level * DRED_LATENT_DIM;
@@ -295,12 +305,21 @@
arch
);
if (ec_tell(&ec_encoder) > 8*max_bytes) {
- ec_encoder = ec_bak;
/* If we haven't been able to code one chunk, give up on DRED completely. */
if (i==0) return 0;
break;
}
+ active = dred_voice_active(activity_mem, i+enc->latent_offset);
+ if (active || prev_active) {
+ ec_bak = ec_encoder;
+ dred_encoded = i+2;
+ }
+ prev_active = active;
}
+ /* Avoid sending empty DRED packets. */
+ if (dred_encoded==0) return 0;
+
+ ec_encoder = ec_bak;
ec_buffer_fill = (ec_tell(&ec_encoder)+7)/8;
ec_enc_shrink(&ec_encoder, ec_buffer_fill);
--- a/silk/dred_encoder.h
+++ b/silk/dred_encoder.h
@@ -66,6 +66,6 @@
void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size, int extra_delay, int arch);
-int dred_encode_silk_frame(const DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, int arch);
+int dred_encode_silk_frame(const DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, unsigned char *activity_mem, int arch);
#endif
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -132,6 +132,7 @@
int dred_q0;
int dred_dQ;
int dred_target_chunks;
+ unsigned char activity_mem[DRED_MAX_FRAMES*4]; /* 2.5ms resolution*/
#endif
int nonfinal_frame; /* current frame is not the final in a packet */
opus_uint32 rangeFinal;
@@ -1841,10 +1842,16 @@
#ifdef ENABLE_DRED
if ( st->dred_duration > 0 && st->dred_encoder.loaded ) {
+ int frame_size_400Hz;
/* DRED Encoder */
dred_compute_latents( &st->dred_encoder, &pcm_buf[total_buffer*st->channels], frame_size, total_buffer, st->arch );
+ frame_size_400Hz = frame_size*400/st->Fs;
+ OPUS_MOVE(&st->activity_mem[frame_size_400Hz], st->activity_mem, 4*DRED_MAX_FRAMES-frame_size_400Hz);
+ for (i=0;i<frame_size_400Hz;i++)
+ st->activity_mem[i] = activity;
} else {
st->dred_encoder.latents_buffer_fill = 0;
+ OPUS_CLEAR(st->activity_mem, DRED_MAX_FRAMES);
}
#endif
@@ -2410,7 +2417,8 @@
buf[0] = 'D';
buf[1] = DRED_EXPERIMENTAL_VERSION;
#endif
- dred_bytes = dred_encode_silk_frame(&st->dred_encoder, buf+DRED_EXPERIMENTAL_BYTES, dred_chunks, dred_bytes_left-DRED_EXPERIMENTAL_BYTES, st->dred_q0, st->dred_dQ, st->arch);
+ dred_bytes = dred_encode_silk_frame(&st->dred_encoder, buf+DRED_EXPERIMENTAL_BYTES, dred_chunks, dred_bytes_left-DRED_EXPERIMENTAL_BYTES,
+ st->dred_q0, st->dred_dQ, st->activity_mem, st->arch);
if (dred_bytes > 0) {
dred_bytes += DRED_EXPERIMENTAL_BYTES;
celt_assert(dred_bytes <= dred_bytes_left);
--
⑨