audioconvert: add zeroramp and gap detection to audioconvert

Make a new zeroramp.duration and zeroramp.gap property on audioconver.
It detects N samples of silence before triggering a fade-in or fade-out
of the given zeroramp.duration.

The zeroramp.duration is by default 5ms and zeroramp.gap is set to 0.

When the zeroramp.gap is set to 0, the audioconver will not do any gap
detection but it will only do fade-out from the last sample when the IO
Buffer area is removed from a port.

This by default makes the audio adapter perform a fade-out when the last
input of the port mixer was removed and the mixer is no longer scheduled
and the IO Area removed from the audioconverter input port.
This commit is contained in:
Wim Taymans 2026-06-17 17:11:42 +02:00
parent c2083336a4
commit 8971c488f3
11 changed files with 365 additions and 3 deletions

View file

@ -0,0 +1,77 @@
/* Spa */
/* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <errno.h>
#include <spa/support/cpu.h>
#include <spa/support/log.h>
#include <spa/utils/defs.h>
#include "gaps-ops.h"
typedef int (*gaps_check_func_t) (struct gaps *gaps, const float * SPA_RESTRICT src[],
uint32_t n_samples);
typedef void (*gaps_fix_func_t) (struct gaps *gaps, float * SPA_RESTRICT dst[],
const float * SPA_RESTRICT src[], uint32_t n_samples);
#define MAKE(check,fix,...) \
{ check, fix, #fix , __VA_ARGS__ }
static const struct gaps_info {
gaps_check_func_t check;
gaps_fix_func_t fix;
const char *name;
uint32_t cpu_flags;
} gaps_table[] =
{
MAKE(gaps_check_c, gaps_fix_c, 0),
};
#undef MAKE
#define MATCH_CPU_FLAGS(a,b) ((a) == 0 || ((a) & (b)) == a)
static const struct gaps_info *find_gaps_info(uint32_t cpu_flags)
{
SPA_FOR_EACH_ELEMENT_VAR(gaps_table, t) {
if (MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
return t;
}
return NULL;
}
static void impl_gaps_free(struct gaps *gaps)
{
gaps->fix = NULL;
}
int gaps_init(struct gaps *gaps)
{
const struct gaps_info *info;
uint32_t i;
info = find_gaps_info(gaps->cpu_flags);
if (info == NULL)
return -ENOTSUP;
if (gaps->channels > SPA_AUDIO_MAX_CHANNELS)
return -EINVAL;
gaps->duration = SPA_MIN(gaps->duration, GAPS_MAX_CURVE);
for (i = 0; i < gaps->duration; i++)
gaps->curve[i] = (float)(0.5 + 0.5 * cos(M_PI + M_PI * i / gaps->duration));
for (i = 0; i < gaps->channels; i++)
spa_zero(gaps->states[i]);
gaps->cpu_flags = info->cpu_flags;
gaps->func_name = info->name;
gaps->free = impl_gaps_free;
gaps->check = info->check;
gaps->fix = info->fix;
return 0;
}