mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-05-15 21:44:17 -04:00
audioconvert: allocate memory dynamically
Instead of working with fixed buffer size, allocate everything dynamically. This preserves a lot of memory in the normal case.
This commit is contained in:
parent
cd654efa6a
commit
f1b1f2d97b
5 changed files with 72 additions and 28 deletions
|
|
@ -1630,7 +1630,7 @@ static int parse_prop_params(struct impl *this, struct spa_pod *params)
|
||||||
if (changed) {
|
if (changed) {
|
||||||
this->props.filter_graph_disabled = filter_graph_disabled;
|
this->props.filter_graph_disabled = filter_graph_disabled;
|
||||||
if (this->setup)
|
if (this->setup)
|
||||||
channelmix_init(&this->mix);
|
channelmix_reconfigure(&this->mix);
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
@ -2322,6 +2322,9 @@ static int setup_channelmix(struct impl *this, uint32_t channels, uint32_t *posi
|
||||||
(src_chan != dst_chan || src_mask != dst_mask))
|
(src_chan != dst_chan || src_mask != dst_mask))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
if (this->mix.free)
|
||||||
|
channelmix_free(&this->mix);
|
||||||
|
|
||||||
this->mix.src_chan = src_chan;
|
this->mix.src_chan = src_chan;
|
||||||
this->mix.src_mask = src_mask;
|
this->mix.src_mask = src_mask;
|
||||||
this->mix.dst_chan = dst_chan;
|
this->mix.dst_chan = dst_chan;
|
||||||
|
|
@ -4319,6 +4322,8 @@ static int impl_clear(struct spa_handle *handle)
|
||||||
free(this->graph_descs[i]);
|
free(this->graph_descs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->mix.free)
|
||||||
|
channelmix_free(&this->mix);
|
||||||
if (this->resample.free)
|
if (this->resample.free)
|
||||||
resample_free(&this->resample);
|
resample_free(&this->resample);
|
||||||
if (this->wav_file != NULL)
|
if (this->wav_file != NULL)
|
||||||
|
|
|
||||||
|
|
@ -270,9 +270,9 @@ channelmix_f32_2_4_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
|
||||||
} else {
|
} else {
|
||||||
sub_c(d[2], s[0], s[1], n_samples);
|
sub_c(d[2], s[0], s[1], n_samples);
|
||||||
|
|
||||||
delay_convolve_run_c(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_c(mix->buffer[1], &mix->pos[1], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[3], d[2], -v3, n_samples);
|
mix->taps, mix->n_taps, d[3], d[2], -v3, n_samples);
|
||||||
delay_convolve_run_c(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_c(mix->buffer[0], &mix->pos[0], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[2], d[2], v2, n_samples);
|
mix->taps, mix->n_taps, d[2], d[2], v2, n_samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -338,9 +338,9 @@ channelmix_f32_2_5p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
|
||||||
} else {
|
} else {
|
||||||
sub_c(d[4], s[0], s[1], n_samples);
|
sub_c(d[4], s[0], s[1], n_samples);
|
||||||
|
|
||||||
delay_convolve_run_c(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_c(mix->buffer[1], &mix->pos[1], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[5], d[4], -v5, n_samples);
|
mix->taps, mix->n_taps, d[5], d[4], -v5, n_samples);
|
||||||
delay_convolve_run_c(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_c(mix->buffer[0], &mix->pos[0], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[4], d[4], v4, n_samples);
|
mix->taps, mix->n_taps, d[4], d[4], v4, n_samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -374,9 +374,9 @@ channelmix_f32_2_7p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
|
||||||
} else {
|
} else {
|
||||||
sub_c(d[6], s[0], s[1], n_samples);
|
sub_c(d[6], s[0], s[1], n_samples);
|
||||||
|
|
||||||
delay_convolve_run_c(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_c(mix->buffer[1], &mix->pos[1], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[7], d[6], -v7, n_samples);
|
mix->taps, mix->n_taps, d[7], d[6], -v7, n_samples);
|
||||||
delay_convolve_run_c(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_c(mix->buffer[0], &mix->pos[0], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[6], d[6], v6, n_samples);
|
mix->taps, mix->n_taps, d[6], d[6], v6, n_samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -456,9 +456,9 @@ channelmix_f32_2_5p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
|
||||||
} else {
|
} else {
|
||||||
sub_sse(d[4], s[0], s[1], n_samples);
|
sub_sse(d[4], s[0], s[1], n_samples);
|
||||||
|
|
||||||
delay_convolve_run_sse(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_sse(mix->buffer[1], &mix->pos[1], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[5], d[4], -v5, n_samples);
|
mix->taps, mix->n_taps, d[5], d[4], -v5, n_samples);
|
||||||
delay_convolve_run_sse(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_sse(mix->buffer[0], &mix->pos[0], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[4], d[4], v4, n_samples);
|
mix->taps, mix->n_taps, d[4], d[4], v4, n_samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -492,9 +492,9 @@ channelmix_f32_2_7p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
|
||||||
} else {
|
} else {
|
||||||
sub_sse(d[6], s[0], s[1], n_samples);
|
sub_sse(d[6], s[0], s[1], n_samples);
|
||||||
|
|
||||||
delay_convolve_run_sse(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_sse(mix->buffer[1], &mix->pos[1], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[7], d[6], -v7, n_samples);
|
mix->taps, mix->n_taps, d[7], d[6], -v7, n_samples);
|
||||||
delay_convolve_run_sse(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
|
delay_convolve_run_sse(mix->buffer[0], &mix->pos[0], mix->buffer_size, mix->delay,
|
||||||
mix->taps, mix->n_taps, d[6], d[6], v6, n_samples);
|
mix->taps, mix->n_taps, d[6], d[6], v6, n_samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
#include "channelmix-ops.h"
|
#include "channelmix-ops.h"
|
||||||
#include "hilbert.h"
|
#include "hilbert.h"
|
||||||
|
|
||||||
|
#define MAX_BUFFER_SIZE 4096
|
||||||
|
|
||||||
#define ANY ((uint32_t)-1)
|
#define ANY ((uint32_t)-1)
|
||||||
#define EQ ((uint32_t)-2)
|
#define EQ ((uint32_t)-2)
|
||||||
|
|
||||||
|
|
@ -192,7 +194,7 @@ static bool match_mix(struct channelmix *mix,
|
||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int make_matrix(struct channelmix *mix)
|
static void impl_channelmix_reconfigure(struct channelmix *mix)
|
||||||
{
|
{
|
||||||
float matrix[MAX_CHANNELS][MAX_CHANNELS] = {{ 0.0f }};
|
float matrix[MAX_CHANNELS][MAX_CHANNELS] = {{ 0.0f }};
|
||||||
uint64_t src_mask = mix->src_mask, src_paired;
|
uint64_t src_mask = mix->src_mask, src_paired;
|
||||||
|
|
@ -782,7 +784,6 @@ done:
|
||||||
for (j = 0; j < src_chan; j++)
|
for (j = 0; j < src_chan; j++)
|
||||||
mix->matrix_orig[i][j] /= maxsum;
|
mix->matrix_orig[i][j] /= maxsum;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void impl_channelmix_set_volume(struct channelmix *mix, float volume, bool mute,
|
static void impl_channelmix_set_volume(struct channelmix *mix, float volume, bool mute,
|
||||||
|
|
@ -875,6 +876,8 @@ static void impl_channelmix_set_volume(struct channelmix *mix, float volume, boo
|
||||||
static void impl_channelmix_free(struct channelmix *mix)
|
static void impl_channelmix_free(struct channelmix *mix)
|
||||||
{
|
{
|
||||||
mix->process = NULL;
|
mix->process = NULL;
|
||||||
|
free(mix->data);
|
||||||
|
mix->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void channelmix_reset(struct channelmix *mix)
|
void channelmix_reset(struct channelmix *mix)
|
||||||
|
|
@ -895,6 +898,9 @@ void channelmix_reset(struct channelmix *mix)
|
||||||
int channelmix_init(struct channelmix *mix)
|
int channelmix_init(struct channelmix *mix)
|
||||||
{
|
{
|
||||||
const struct channelmix_info *info;
|
const struct channelmix_info *info;
|
||||||
|
void *d, *b[2];
|
||||||
|
size_t taps_size, buffer_size, alloc_size, dstptr_size, matrow_size, matrix_size, lr4_size;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
if (mix->src_chan > MAX_CHANNELS ||
|
if (mix->src_chan > MAX_CHANNELS ||
|
||||||
mix->dst_chan > MAX_CHANNELS)
|
mix->dst_chan > MAX_CHANNELS)
|
||||||
|
|
@ -908,29 +914,62 @@ int channelmix_init(struct channelmix *mix)
|
||||||
mix->free = impl_channelmix_free;
|
mix->free = impl_channelmix_free;
|
||||||
mix->process = info->process;
|
mix->process = info->process;
|
||||||
mix->set_volume = impl_channelmix_set_volume;
|
mix->set_volume = impl_channelmix_set_volume;
|
||||||
|
mix->reconfigure = impl_channelmix_reconfigure;
|
||||||
mix->delay = (uint32_t)(mix->rear_delay * mix->freq / 1000.0f);
|
mix->delay = (uint32_t)(mix->rear_delay * mix->freq / 1000.0f);
|
||||||
mix->func_cpu_flags = info->cpu_flags;
|
mix->func_cpu_flags = info->cpu_flags;
|
||||||
mix->func_name = info->name;
|
mix->func_name = info->name;
|
||||||
|
|
||||||
spa_zero(mix->taps_mem);
|
if (mix->hilbert_taps > 0)
|
||||||
mix->taps = SPA_PTR_ALIGN(mix->taps_mem, CHANNELMIX_OPS_MAX_ALIGN, float);
|
mix->n_taps = SPA_CLAMP(mix->hilbert_taps, 15u, MAX_TAPS) | 1;
|
||||||
mix->buffer[0] = SPA_PTR_ALIGN(&mix->buffer_mem[0], CHANNELMIX_OPS_MAX_ALIGN, float);
|
else
|
||||||
mix->buffer[1] = SPA_PTR_ALIGN(&mix->buffer_mem[2*BUFFER_SIZE], CHANNELMIX_OPS_MAX_ALIGN, float);
|
mix->n_taps = 1;
|
||||||
|
|
||||||
|
mix->buffer_size = mix->delay + mix->n_taps;
|
||||||
|
if (mix->buffer_size > MAX_BUFFER_SIZE) {
|
||||||
|
mix->buffer_size = MAX_BUFFER_SIZE;
|
||||||
|
mix->delay = MAX_BUFFER_SIZE - mix->n_taps;
|
||||||
|
}
|
||||||
|
|
||||||
|
taps_size = SPA_ROUND_UP(mix->n_taps * sizeof(float), CHANNELMIX_OPS_MAX_ALIGN);
|
||||||
|
buffer_size = SPA_ROUND_UP(mix->buffer_size*2 * sizeof(float), CHANNELMIX_OPS_MAX_ALIGN);
|
||||||
|
dstptr_size = SPA_ROUND_UP(mix->dst_chan * sizeof(void*), CHANNELMIX_OPS_MAX_ALIGN);
|
||||||
|
matrow_size = SPA_ROUND_UP(mix->src_chan * sizeof(float), CHANNELMIX_OPS_MAX_ALIGN);
|
||||||
|
matrix_size = SPA_ROUND_UP(mix->dst_chan * matrow_size, CHANNELMIX_OPS_MAX_ALIGN);
|
||||||
|
lr4_size = SPA_ROUND_UP(mix->dst_chan * sizeof(struct lr4), CHANNELMIX_OPS_MAX_ALIGN);
|
||||||
|
|
||||||
|
alloc_size = taps_size + buffer_size*2 + dstptr_size*2 + lr4_size + matrix_size*2 + CHANNELMIX_OPS_MAX_ALIGN;
|
||||||
|
d = calloc(1, alloc_size);
|
||||||
|
if (d == NULL)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
mix->data = d;
|
||||||
|
mix->taps = SPA_PTR_ALIGN(d, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
mix->buffer[0] = SPA_PTROFF_ALIGN(mix->taps, taps_size, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
mix->buffer[1] = SPA_PTROFF_ALIGN(mix->buffer[0], buffer_size, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
mix->matrix = SPA_PTROFF_ALIGN(mix->buffer[1], buffer_size, CHANNELMIX_OPS_MAX_ALIGN, float*);
|
||||||
|
mix->matrix_orig = SPA_PTROFF_ALIGN(mix->matrix, dstptr_size, CHANNELMIX_OPS_MAX_ALIGN, float*);
|
||||||
|
mix->lr4 = SPA_PTROFF_ALIGN(mix->matrix_orig, dstptr_size, CHANNELMIX_OPS_MAX_ALIGN, struct lr4);
|
||||||
|
|
||||||
|
b[0] = SPA_PTROFF_ALIGN(mix->lr4, lr4_size, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
b[1] = SPA_PTROFF_ALIGN(b[0], matrix_size, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
|
||||||
|
for (i = 0; i < mix->dst_chan; i++) {
|
||||||
|
mix->matrix[i] = SPA_PTROFF_ALIGN(b[0], matrow_size * i, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
mix->matrix_orig[i] = SPA_PTROFF_ALIGN(b[1], matrow_size * i, CHANNELMIX_OPS_MAX_ALIGN, float);
|
||||||
|
}
|
||||||
|
|
||||||
if (mix->hilbert_taps > 0) {
|
if (mix->hilbert_taps > 0) {
|
||||||
mix->n_taps = SPA_CLAMP(mix->hilbert_taps, 15u, MAX_TAPS) | 1;
|
|
||||||
blackman_window(mix->taps, mix->n_taps);
|
blackman_window(mix->taps, mix->n_taps);
|
||||||
hilbert_generate(mix->taps, mix->n_taps);
|
hilbert_generate(mix->taps, mix->n_taps);
|
||||||
reverse_taps(mix->taps, mix->n_taps);
|
reverse_taps(mix->taps, mix->n_taps);
|
||||||
} else {
|
} else {
|
||||||
mix->n_taps = 1;
|
|
||||||
mix->taps[0] = 1.0f;
|
mix->taps[0] = 1.0f;
|
||||||
}
|
}
|
||||||
if (mix->delay + mix->n_taps > BUFFER_SIZE)
|
|
||||||
mix->delay = BUFFER_SIZE - mix->n_taps;
|
|
||||||
|
|
||||||
spa_log_debug(mix->log, "selected %s delay:%d options:%08x", info->name, mix->delay,
|
spa_log_debug(mix->log, "selected %s delay:%d options:%08x", info->name, mix->delay,
|
||||||
mix->options);
|
mix->options);
|
||||||
|
|
||||||
return make_matrix(mix);
|
channelmix_reconfigure(mix);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
|
#define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
|
||||||
#define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
|
#define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
|
||||||
|
|
||||||
#define BUFFER_SIZE 4096
|
|
||||||
#define MAX_TAPS 255u
|
#define MAX_TAPS 255u
|
||||||
#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS
|
#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS
|
||||||
|
|
||||||
|
|
@ -63,8 +62,8 @@ struct channelmix {
|
||||||
#define CHANNELMIX_FLAG_EQUAL (1<<2) /**< all values are equal */
|
#define CHANNELMIX_FLAG_EQUAL (1<<2) /**< all values are equal */
|
||||||
#define CHANNELMIX_FLAG_COPY (1<<3) /**< 1 on diagonal, can be nxm */
|
#define CHANNELMIX_FLAG_COPY (1<<3) /**< 1 on diagonal, can be nxm */
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
float matrix_orig[MAX_CHANNELS][MAX_CHANNELS];
|
float **matrix_orig;
|
||||||
float matrix[MAX_CHANNELS][MAX_CHANNELS];
|
float **matrix;
|
||||||
|
|
||||||
float freq; /* sample frequency */
|
float freq; /* sample frequency */
|
||||||
float lfe_cutoff; /* in Hz, 0 is disabled */
|
float lfe_cutoff; /* in Hz, 0 is disabled */
|
||||||
|
|
@ -75,13 +74,12 @@ struct channelmix {
|
||||||
float lfe_level; /* lfe down/upmix level, 1/2 */
|
float lfe_level; /* lfe down/upmix level, 1/2 */
|
||||||
float surround_level; /* surround down/upmix level, sqrt(1/2) */
|
float surround_level; /* surround down/upmix level, sqrt(1/2) */
|
||||||
uint32_t hilbert_taps; /* to phase shift, 0 disabled */
|
uint32_t hilbert_taps; /* to phase shift, 0 disabled */
|
||||||
struct lr4 lr4[MAX_CHANNELS];
|
struct lr4 *lr4;
|
||||||
|
|
||||||
float buffer_mem[2 * BUFFER_SIZE*2 + CHANNELMIX_OPS_MAX_ALIGN/4];
|
|
||||||
float *buffer[2];
|
float *buffer[2];
|
||||||
|
uint32_t buffer_size;
|
||||||
uint32_t pos[2];
|
uint32_t pos[2];
|
||||||
uint32_t delay;
|
uint32_t delay;
|
||||||
float taps_mem[MAX_TAPS + CHANNELMIX_OPS_MAX_ALIGN/4];
|
|
||||||
float *taps;
|
float *taps;
|
||||||
uint32_t n_taps;
|
uint32_t n_taps;
|
||||||
|
|
||||||
|
|
@ -89,6 +87,7 @@ struct channelmix {
|
||||||
const void * SPA_RESTRICT src[], uint32_t n_samples);
|
const void * SPA_RESTRICT src[], uint32_t n_samples);
|
||||||
void (*set_volume) (struct channelmix *mix, float volume, bool mute,
|
void (*set_volume) (struct channelmix *mix, float volume, bool mute,
|
||||||
uint32_t n_channel_volumes, float *channel_volumes);
|
uint32_t n_channel_volumes, float *channel_volumes);
|
||||||
|
void (*reconfigure) (struct channelmix *mix);
|
||||||
void (*free) (struct channelmix *mix);
|
void (*free) (struct channelmix *mix);
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
@ -118,6 +117,7 @@ static inline uint32_t channelmix_upmix_from_label(const char *label)
|
||||||
|
|
||||||
#define channelmix_process(mix,...) (mix)->process(mix, __VA_ARGS__)
|
#define channelmix_process(mix,...) (mix)->process(mix, __VA_ARGS__)
|
||||||
#define channelmix_set_volume(mix,...) (mix)->set_volume(mix, __VA_ARGS__)
|
#define channelmix_set_volume(mix,...) (mix)->set_volume(mix, __VA_ARGS__)
|
||||||
|
#define channelmix_reconfigure(mix) (mix)->reconfigure(mix)
|
||||||
#define channelmix_free(mix) (mix)->free(mix)
|
#define channelmix_free(mix) (mix)->free(mix)
|
||||||
|
|
||||||
#define DEFINE_FUNCTION(name,arch) \
|
#define DEFINE_FUNCTION(name,arch) \
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue