convolver: use normal float for complex float array

This commit is contained in:
Wim Taymans 2022-12-16 10:51:19 +01:00
parent 538b6ce35e
commit b6b6efff42
2 changed files with 61 additions and 58 deletions

View file

@ -34,26 +34,22 @@
static struct dsp_ops *dsp; static struct dsp_ops *dsp;
struct fft_cpx {
float *v;
};
struct convolver1 { struct convolver1 {
int blockSize; int blockSize;
int segSize; int segSize;
int segCount; int segCount;
int fftComplexSize; int fftComplexSize;
struct fft_cpx *segments; float **segments;
struct fft_cpx *segmentsIr; float **segmentsIr;
float *fft_buffer; float *fft_buffer;
void *fft; void *fft;
void *ifft; void *ifft;
struct fft_cpx pre_mult; float *pre_mult;
struct fft_cpx conv; float *conv;
float *overlap; float *overlap;
float *inputBuffer; float *inputBuffer;
@ -65,25 +61,33 @@ struct convolver1 {
static void *fft_alloc(int size) static void *fft_alloc(int size)
{ {
return pffft_aligned_malloc(size * sizeof(float)); size_t nb_bytes = size * sizeof(float);
#define ALIGNMENT 64
void *p, *p0 = malloc(nb_bytes + ALIGNMENT);
if (!p0)
return (void *)0;
p = (void *)(((size_t)p0 + ALIGNMENT) & (~((size_t)(ALIGNMENT - 1))));
*((void **)p - 1) = p0;
return p;
} }
static void fft_free(void *data) static void fft_free(void *p)
{ {
pffft_aligned_free(data); if (p)
free(*((void **)p - 1));
} }
static inline void fft_cpx_clear(struct fft_cpx *cpx, int size) static inline void fft_cpx_clear(float *v, int size)
{ {
dsp_ops_clear(dsp, cpx->v, size * 2); dsp_ops_clear(dsp, v, size * 2);
} }
static void fft_cpx_init(struct fft_cpx *cpx, int size) static float *fft_cpx_alloc(int size)
{ {
cpx->v = fft_alloc(size * 2); return fft_alloc(size * 2);
} }
static void fft_cpx_free(struct fft_cpx *cpx) static void fft_cpx_free(float *cpx)
{ {
fft_free(cpx->v); fft_free(cpx);
} }
static int next_power_of_two(int val) static int next_power_of_two(int val)
@ -109,36 +113,36 @@ static inline void fft_destroy(void *fft)
pffft_destroy_setup(fft); pffft_destroy_setup(fft);
} }
static inline void fft_run(void *fft, float *in, struct fft_cpx *out) static inline void fft_run(void *fft, const float *in, float *out)
{ {
pffft_transform(fft, in, out->v, NULL, PFFFT_FORWARD); pffft_transform(fft, in, out, NULL, PFFFT_FORWARD);
} }
static inline void ifft_run(void *ifft, struct fft_cpx *in, float *out) static inline void ifft_run(void *ifft, const float *in, float *out)
{ {
pffft_transform(ifft, in->v, out, NULL, PFFFT_BACKWARD); pffft_transform(ifft, in, out, NULL, PFFFT_BACKWARD);
} }
static inline void fft_convolve(void *fft, struct fft_cpx *r, static inline void fft_convolve(void *fft, float *r,
const struct fft_cpx *a, const struct fft_cpx *b, int len, float scale) const float *a, const float *b, int len, float scale)
{ {
pffft_zconvolve(fft, a->v, b->v, r->v, scale); pffft_zconvolve(fft, a, b, r, scale);
} }
static inline void fft_convolve_accum(void *fft, struct fft_cpx *r, static inline void fft_convolve_accum(void *fft, float *r,
const struct fft_cpx *c, const struct fft_cpx *a, const struct fft_cpx *b, int len, float scale) const float *c, const float *a, const float *b, int len, float scale)
{ {
pffft_zconvolve_accumulate(fft, a->v, b->v, c->v, r->v, scale); pffft_zconvolve_accumulate(fft, a, b, c, r, scale);
} }
static void convolver1_reset(struct convolver1 *conv) static void convolver1_reset(struct convolver1 *conv)
{ {
int i; int i;
for (i = 0; i < conv->segCount; i++) for (i = 0; i < conv->segCount; i++)
fft_cpx_clear(&conv->segments[i], conv->fftComplexSize); fft_cpx_clear(conv->segments[i], conv->fftComplexSize);
dsp_ops_clear(dsp, conv->overlap, conv->blockSize); dsp_ops_clear(dsp, conv->overlap, conv->blockSize);
dsp_ops_clear(dsp, conv->inputBuffer, conv->segSize); dsp_ops_clear(dsp, conv->inputBuffer, conv->segSize);
fft_cpx_clear(&conv->pre_mult, conv->fftComplexSize); fft_cpx_clear(conv->pre_mult, conv->fftComplexSize);
fft_cpx_clear(&conv->conv, conv->fftComplexSize); fft_cpx_clear(conv->conv, conv->fftComplexSize);
conv->inputBufferFill = 0; conv->inputBufferFill = 0;
conv->current = 0; conv->current = 0;
} }
@ -177,24 +181,24 @@ static struct convolver1 *convolver1_new(int block, const float *ir, int irlen)
if (conv->fft_buffer == NULL) if (conv->fft_buffer == NULL)
goto error; goto error;
conv->segments = calloc(sizeof(struct fft_cpx), conv->segCount); conv->segments = calloc(sizeof(float*), conv->segCount);
conv->segmentsIr = calloc(sizeof(struct fft_cpx), conv->segCount); conv->segmentsIr = calloc(sizeof(float*), conv->segCount);
for (i = 0; i < conv->segCount; i++) { for (i = 0; i < conv->segCount; i++) {
int left = irlen - (i * conv->blockSize); int left = irlen - (i * conv->blockSize);
int copy = SPA_MIN(conv->blockSize, left); int copy = SPA_MIN(conv->blockSize, left);
fft_cpx_init(&conv->segments[i], conv->fftComplexSize); conv->segments[i] = fft_cpx_alloc(conv->fftComplexSize);
fft_cpx_init(&conv->segmentsIr[i], conv->fftComplexSize); conv->segmentsIr[i] = fft_cpx_alloc(conv->fftComplexSize);
dsp_ops_copy(dsp, conv->fft_buffer, &ir[i * conv->blockSize], copy); dsp_ops_copy(dsp, conv->fft_buffer, &ir[i * conv->blockSize], copy);
if (copy < conv->segSize) if (copy < conv->segSize)
dsp_ops_clear(dsp, conv->fft_buffer + copy, conv->segSize - copy); dsp_ops_clear(dsp, conv->fft_buffer + copy, conv->segSize - copy);
fft_run(conv->fft, conv->fft_buffer, &conv->segmentsIr[i]); fft_run(conv->fft, conv->fft_buffer, conv->segmentsIr[i]);
} }
fft_cpx_init(&conv->pre_mult, conv->fftComplexSize); conv->pre_mult = fft_cpx_alloc(conv->fftComplexSize);
fft_cpx_init(&conv->conv, conv->fftComplexSize); conv->conv = fft_cpx_alloc(conv->fftComplexSize);
conv->overlap = fft_alloc(conv->blockSize); conv->overlap = fft_alloc(conv->blockSize);
conv->inputBuffer = fft_alloc(conv->segSize); conv->inputBuffer = fft_alloc(conv->segSize);
conv->scale = 1.0f / conv->segSize; conv->scale = 1.0f / conv->segSize;
@ -216,8 +220,8 @@ static void convolver1_free(struct convolver1 *conv)
{ {
int i; int i;
for (i = 0; i < conv->segCount; i++) { for (i = 0; i < conv->segCount; i++) {
fft_cpx_free(&conv->segments[i]); fft_cpx_free(conv->segments[i]);
fft_cpx_free(&conv->segmentsIr[i]); fft_cpx_free(conv->segmentsIr[i]);
} }
if (conv->fft) if (conv->fft)
fft_destroy(conv->fft); fft_destroy(conv->fft);
@ -227,8 +231,8 @@ static void convolver1_free(struct convolver1 *conv)
fft_free(conv->fft_buffer); fft_free(conv->fft_buffer);
free(conv->segments); free(conv->segments);
free(conv->segmentsIr); free(conv->segmentsIr);
fft_cpx_free(&conv->pre_mult); fft_cpx_free(conv->pre_mult);
fft_cpx_free(&conv->conv); fft_cpx_free(conv->conv);
fft_free(conv->overlap); fft_free(conv->overlap);
fft_free(conv->inputBuffer); fft_free(conv->inputBuffer);
free(conv); free(conv);
@ -251,42 +255,42 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
if (inputBufferPos == 0 && processing < conv->blockSize) if (inputBufferPos == 0 && processing < conv->blockSize)
dsp_ops_clear(dsp, conv->inputBuffer + processing, conv->blockSize - processing); dsp_ops_clear(dsp, conv->inputBuffer + processing, conv->blockSize - processing);
fft_run(conv->fft, conv->inputBuffer, &conv->segments[conv->current]); fft_run(conv->fft, conv->inputBuffer, conv->segments[conv->current]);
if (conv->segCount > 1) { if (conv->segCount > 1) {
if (conv->inputBufferFill == 0) { if (conv->inputBufferFill == 0) {
int indexAudio = (conv->current + 1) % conv->segCount; int indexAudio = (conv->current + 1) % conv->segCount;
fft_convolve(conv->fft, &conv->pre_mult, fft_convolve(conv->fft, conv->pre_mult,
&conv->segmentsIr[1], conv->segmentsIr[1],
&conv->segments[indexAudio], conv->segments[indexAudio],
conv->fftComplexSize, conv->scale); conv->fftComplexSize, conv->scale);
for (i = 2; i < conv->segCount; i++) { for (i = 2; i < conv->segCount; i++) {
indexAudio = (conv->current + i) % conv->segCount; indexAudio = (conv->current + i) % conv->segCount;
fft_convolve_accum(conv->fft, fft_convolve_accum(conv->fft,
&conv->pre_mult, conv->pre_mult,
&conv->pre_mult, conv->pre_mult,
&conv->segmentsIr[i], conv->segmentsIr[i],
&conv->segments[indexAudio], conv->segments[indexAudio],
conv->fftComplexSize, conv->scale); conv->fftComplexSize, conv->scale);
} }
} }
fft_convolve_accum(conv->fft, fft_convolve_accum(conv->fft,
&conv->conv, conv->conv,
&conv->pre_mult, conv->pre_mult,
&conv->segments[conv->current], conv->segments[conv->current],
&conv->segmentsIr[0], conv->segmentsIr[0],
conv->fftComplexSize, conv->scale); conv->fftComplexSize, conv->scale);
} else { } else {
fft_convolve(conv->fft, &conv->conv, fft_convolve(conv->fft, conv->conv,
&conv->segments[conv->current], conv->segments[conv->current],
&conv->segmentsIr[0], conv->segmentsIr[0],
conv->fftComplexSize, conv->scale); conv->fftComplexSize, conv->scale);
} }
ifft_run(conv->ifft, &conv->conv, conv->fft_buffer); ifft_run(conv->ifft, conv->conv, conv->fft_buffer);
dsp_ops_sum(dsp, output + processed, conv->fft_buffer + inputBufferPos, dsp_ops_sum(dsp, output + processed, conv->fft_buffer + inputBufferPos,
conv->overlap + inputBufferPos, processing); conv->overlap + inputBufferPos, processing);

View file

@ -92,7 +92,6 @@ int dsp_ops_init(struct dsp_ops *ops)
return -ENOTSUP; return -ENOTSUP;
ops->priv = info; ops->priv = info;
ops->cpu_flags = info->cpu_flags;
ops->free = impl_dsp_ops_free; ops->free = impl_dsp_ops_free;
ops->funcs = info->funcs; ops->funcs = info->funcs;