audioconvert: improve noise bits

Make a new noise method called PATTERN and use it to add a slow (every
1024 samples) repeating pattern of -1, 0.
Only use this method when we don't already use triangular dither.

See #2540
This commit is contained in:
Wim Taymans 2022-07-18 11:39:24 +02:00
parent 57f63feb92
commit ada39f3048
4 changed files with 43 additions and 20 deletions

View file

@ -33,7 +33,7 @@
#include "fmt-ops.h"
#include "law.h"
#define MAKE_COPY(size) \
#define MAKE_COPY(size) \
void conv_copy ##size## d_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -55,7 +55,7 @@ MAKE_COPY(24);
MAKE_COPY(32);
MAKE_COPY(64);
#define MAKE_D_TO_D(sname,stype,dname,dtype,func) \
#define MAKE_D_TO_D(sname,stype,dname,dtype,func) \
void conv_ ##sname## d_to_ ##dname## d_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -65,11 +65,11 @@ void conv_ ##sname## d_to_ ##dname## d_c(struct convert *conv, \
const stype *s = src[i]; \
dtype *d = dst[i]; \
for (j = 0; j < n_samples; j++) \
d[j] = func (s[j]); \
d[j] = func (s[j]); \
} \
}
#define MAKE_I_TO_I(sname,stype,dname,dtype,func) \
#define MAKE_I_TO_I(sname,stype,dname,dtype,func) \
void conv_ ##sname## _to_ ##dname## _c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -79,10 +79,10 @@ void conv_ ##sname## _to_ ##dname## _c(struct convert *conv, \
dtype *d = dst[0]; \
n_samples *= conv->n_channels; \
for (j = 0; j < n_samples; j++) \
d[j] = func (s[j]); \
d[j] = func (s[j]); \
}
#define MAKE_I_TO_D(sname,stype,dname,dtype,func) \
#define MAKE_I_TO_D(sname,stype,dname,dtype,func) \
void conv_ ##sname## _to_ ##dname## d_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -92,11 +92,11 @@ void conv_ ##sname## _to_ ##dname## d_c(struct convert *conv, \
uint32_t i, j, n_channels = conv->n_channels; \
for (j = 0; j < n_samples; j++) { \
for (i = 0; i < n_channels; i++) \
d[i][j] = func (*s++); \
d[i][j] = func (*s++); \
} \
}
#define MAKE_D_TO_I(sname,stype,dname,dtype,func) \
#define MAKE_D_TO_I(sname,stype,dname,dtype,func) \
void conv_ ##sname## d_to_ ##dname## _c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -106,7 +106,7 @@ void conv_ ##sname## d_to_ ##dname## _c(struct convert *conv, \
uint32_t i, j, n_channels = conv->n_channels; \
for (j = 0; j < n_samples; j++) { \
for (i = 0; i < n_channels; i++) \
*d++ = func (s[i][j]); \
*d++ = func (s[i][j]); \
} \
}
@ -255,10 +255,16 @@ static inline void update_noise_c(struct convert *conv, uint32_t n_samples)
}
*prev = old;
break;
case NOISE_METHOD_PATTERN:
old = *prev;
for (n = 0; n < n_samples; n++)
noise[n] = conv->scale * (1-((old++>>10)&1));
*prev = old;
break;
}
}
#define MAKE_D_noise(dname,dtype,func) \
#define MAKE_D_noise(dname,dtype,func) \
void conv_f32d_to_ ##dname## d_noise_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -277,7 +283,7 @@ void conv_f32d_to_ ##dname## d_noise_c(struct convert *conv, \
} \
}
#define MAKE_I_noise(dname,dtype,func) \
#define MAKE_I_noise(dname,dtype,func) \
void conv_f32d_to_ ##dname## _noise_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -316,7 +322,7 @@ MAKE_I_noise(s24_32s, int32_t, F32_TO_S24_32S_D);
#define SHAPER(type,s,scale,offs,sh,min,max,d) \
({ \
type t; \
float v = s * scale + offs; \
float v = s * scale + offs; \
for (n = 0; n < n_ns; n++) \
v += sh->e[idx + n] * ns[n]; \
t = FTOI(type, v, 1.0f, 0.0f, d, min, max); \
@ -330,7 +336,7 @@ MAKE_I_noise(s24_32s, int32_t, F32_TO_S24_32S_D);
#define F32_TO_S16_SH(s,sh,d) SHAPER(int16_t, s, S16_SCALE, 0, sh, S16_MIN, S16_MAX, d)
#define F32_TO_S16S_SH(s,sh,d) bswap_16(F32_TO_S16_SH(s,sh,d))
#define MAKE_D_shaped(dname,dtype,func) \
#define MAKE_D_shaped(dname,dtype,func) \
void conv_f32d_to_ ##dname## d_shaped_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \
@ -353,7 +359,7 @@ void conv_f32d_to_ ##dname## d_shaped_c(struct convert *conv, \
} \
}
#define MAKE_I_shaped(dname,dtype,func) \
#define MAKE_I_shaped(dname,dtype,func) \
void conv_f32d_to_ ##dname## _shaped_c(struct convert *conv, \
void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
uint32_t n_samples) \

View file

@ -581,7 +581,7 @@ static inline void update_noise_sse2(struct convert *conv, uint32_t n_samples)
{
uint32_t n;
const uint32_t *r = SPA_PTR_ALIGN(conv->random, 16, uint32_t);
const int32_t *p = SPA_PTR_ALIGN(conv->prev, 16, int32_t);
int32_t *p = SPA_PTR_ALIGN(conv->prev, 16, int32_t), op;
__m128 scale = _mm_set1_ps(conv->scale);
__m128 out[1];
float *noise = SPA_PTR_ALIGN(conv->noise, 16, float);
@ -616,6 +616,12 @@ static inline void update_noise_sse2(struct convert *conv, uint32_t n_samples)
}
_mm_store_si128((__m128i*)p, old[0]);
break;
case NOISE_METHOD_PATTERN:
op = *p;
for (n = 0; n < n_samples; n++)
noise[n] = conv->scale * (1-((op++>>10)&1));
*p = op;
break;
}
}

View file

@ -453,9 +453,6 @@ int convert_init(struct convert *conv)
conv->scale = 1.0f / (float)(INT32_MAX);
if (conv->noise_bits > 0)
conv->scale *= (1 << (conv->noise_bits + 1));
/* disable dither if not needed */
if (!need_dither(conv->dst_fmt))
conv->method = DITHER_METHOD_NONE;
@ -465,8 +462,21 @@ int convert_init(struct convert *conv)
return -EINVAL;
conv->noise_method = dinfo->noise_method;
if (conv->noise_bits && conv->noise_method == NOISE_METHOD_NONE)
conv->noise_method = NOISE_METHOD_RECTANGULAR;
if (conv->noise_bits > 0) {
switch (conv->noise_method) {
case NOISE_METHOD_NONE:
conv->noise_method = NOISE_METHOD_PATTERN;
conv->scale = -1.0f * (1 << (conv->noise_bits-1));
break;
case NOISE_METHOD_RECTANGULAR:
conv->noise_method = NOISE_METHOD_TRIANGULAR;
SPA_FALLTHROUGH;
case NOISE_METHOD_TRIANGULAR:
case NOISE_METHOD_TRIANGULAR_HF:
conv->scale *= (1 << (conv->noise_bits-1));
break;
}
}
if (conv->noise_method < NOISE_METHOD_TRIANGULAR)
conv->scale *= 0.5f;

View file

@ -233,6 +233,7 @@ struct convert {
#define NOISE_METHOD_RECTANGULAR 1
#define NOISE_METHOD_TRIANGULAR 2
#define NOISE_METHOD_TRIANGULAR_HF 3
#define NOISE_METHOD_PATTERN 4
uint32_t noise_method;
float *noise;
uint32_t noise_size;