mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
filter-chain: add support for time delay in convolver
The convolver will parse integers as a sample delay (as before) but will now also fall back to parsing it as a float in the time domain. Specifying the delay in time is better because it does not depend on the samplerate of the graph or the IR.
This commit is contained in:
parent
5e87f1d4f4
commit
24d76e73ab
2 changed files with 22 additions and 15 deletions
|
|
@ -350,7 +350,9 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
|
||||||
* computed automatically from the number of samples in the file.
|
* computed automatically from the number of samples in the file.
|
||||||
* - `tailsize` specifies the size of the tail blocks to use in the FFT.
|
* - `tailsize` specifies the size of the tail blocks to use in the FFT.
|
||||||
* - `gain` the overall gain to apply to the IR file.
|
* - `gain` the overall gain to apply to the IR file.
|
||||||
* - `delay` The extra delay (in samples) to add to the IR.
|
* - `delay` The extra delay to add to the IR. A float number will be interpreted as seconds,
|
||||||
|
* and integer as samples. Using the delay in seconds is independent of the graph
|
||||||
|
* and IR rate and is recommended.
|
||||||
* - `filename` The IR to load or create. Possible values are:
|
* - `filename` The IR to load or create. Possible values are:
|
||||||
* - `/hilbert` creates a [hilbert function](https://en.wikipedia.org/wiki/Hilbert_transform)
|
* - `/hilbert` creates a [hilbert function](https://en.wikipedia.org/wiki/Hilbert_transform)
|
||||||
* that can be used to phase shift the signal by +/-90 degrees. The
|
* that can be used to phase shift the signal by +/-90 degrees. The
|
||||||
|
|
|
||||||
|
|
@ -700,7 +700,7 @@ static float *read_samples_from_sf(SNDFILE *f, SF_INFO info, float gain, int del
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static float *read_closest(char **filenames, float gain, int delay, int offset,
|
static float *read_closest(char **filenames, float gain, float delay_sec, int offset,
|
||||||
int length, int channel, long unsigned *rate, int *n_samples)
|
int length, int channel, long unsigned *rate, int *n_samples)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SNDFILE
|
#ifdef HAVE_SNDFILE
|
||||||
|
|
@ -727,8 +727,9 @@ static float *read_closest(char **filenames, float gain, int delay, int offset,
|
||||||
}
|
}
|
||||||
if (fs[best] != NULL) {
|
if (fs[best] != NULL) {
|
||||||
pw_log_info("loading best rate:%u %s", infos[best].samplerate, filenames[best]);
|
pw_log_info("loading best rate:%u %s", infos[best].samplerate, filenames[best]);
|
||||||
samples = read_samples_from_sf(fs[best], infos[best], gain, delay,
|
samples = read_samples_from_sf(fs[best], infos[best], gain,
|
||||||
offset, length, channel, rate, n_samples);
|
(int) (delay_sec * infos[best].samplerate), offset, length,
|
||||||
|
channel, rate, n_samples);
|
||||||
} else {
|
} else {
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
pw_log_error("Can't open any sample file (CWD %s):",
|
pw_log_error("Can't open any sample file (CWD %s):",
|
||||||
|
|
@ -756,11 +757,12 @@ static float *read_closest(char **filenames, float gain, int delay, int offset,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static float *create_hilbert(const char *filename, float gain, int delay, int offset,
|
static float *create_hilbert(const char *filename, float gain, int rate, float delay_sec, int offset,
|
||||||
int length, int *n_samples)
|
int length, int *n_samples)
|
||||||
{
|
{
|
||||||
float *samples, v;
|
float *samples, v;
|
||||||
int i, n, h;
|
int i, n, h;
|
||||||
|
int delay = (int) (delay_sec * rate);
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
length = 1024;
|
length = 1024;
|
||||||
|
|
@ -786,10 +788,11 @@ static float *create_hilbert(const char *filename, float gain, int delay, int of
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float *create_dirac(const char *filename, float gain, int delay, int offset,
|
static float *create_dirac(const char *filename, float gain, int rate, float delay_sec, int offset,
|
||||||
int length, int *n_samples)
|
int length, int *n_samples)
|
||||||
{
|
{
|
||||||
float *samples;
|
float *samples;
|
||||||
|
int delay = (int) (delay_sec * rate);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = delay + 1;
|
n = delay + 1;
|
||||||
|
|
@ -893,9 +896,8 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
char key[256], v[256];
|
char key[256], v[256];
|
||||||
char *filenames[MAX_RATES] = { 0 };
|
char *filenames[MAX_RATES] = { 0 };
|
||||||
int blocksize = 0, tailsize = 0;
|
int blocksize = 0, tailsize = 0;
|
||||||
int delay = 0;
|
|
||||||
int resample_quality = RESAMPLE_DEFAULT_QUALITY;
|
int resample_quality = RESAMPLE_DEFAULT_QUALITY;
|
||||||
float gain = 1.0f;
|
float gain = 1.0f, delay = 0.0f;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
|
@ -929,7 +931,10 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (spa_streq(key, "delay")) {
|
else if (spa_streq(key, "delay")) {
|
||||||
if (spa_json_parse_int(val, len, &delay) <= 0) {
|
int delay_i;
|
||||||
|
if (spa_json_parse_int(val, len, &delay_i) > 0) {
|
||||||
|
delay = delay_i / (float)SampleRate;
|
||||||
|
} else if (spa_json_parse_float(val, len, &delay) <= 0) {
|
||||||
pw_log_error("convolver:delay requires a number");
|
pw_log_error("convolver:delay requires a number");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -983,16 +988,16 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delay < 0)
|
if (delay < 0.0f)
|
||||||
delay = 0;
|
delay = 0.0f;
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
if (spa_streq(filenames[0], "/hilbert")) {
|
if (spa_streq(filenames[0], "/hilbert")) {
|
||||||
samples = create_hilbert(filenames[0], gain, delay, offset,
|
samples = create_hilbert(filenames[0], gain, SampleRate, delay, offset,
|
||||||
length, &n_samples);
|
length, &n_samples);
|
||||||
} else if (spa_streq(filenames[0], "/dirac")) {
|
} else if (spa_streq(filenames[0], "/dirac")) {
|
||||||
samples = create_dirac(filenames[0], gain, delay, offset,
|
samples = create_dirac(filenames[0], gain, SampleRate, delay, offset,
|
||||||
length, &n_samples);
|
length, &n_samples);
|
||||||
} else {
|
} else {
|
||||||
rate = SampleRate;
|
rate = SampleRate;
|
||||||
|
|
@ -1017,8 +1022,8 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
|
||||||
if (tailsize <= 0)
|
if (tailsize <= 0)
|
||||||
tailsize = SPA_CLAMP(4096, blocksize, 32768);
|
tailsize = SPA_CLAMP(4096, blocksize, 32768);
|
||||||
|
|
||||||
pw_log_info("using n_samples:%u %d:%d blocksize", n_samples,
|
pw_log_info("using n_samples:%u %d:%d blocksize delay:%f", n_samples,
|
||||||
blocksize, tailsize);
|
blocksize, tailsize, delay);
|
||||||
|
|
||||||
impl = calloc(1, sizeof(*impl));
|
impl = calloc(1, sizeof(*impl));
|
||||||
if (impl == NULL)
|
if (impl == NULL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue