Force filter graph reconfiguration in setup_convert.
When adding/removing filter-graphs, only perform setup when we were
already setup, otherwise we will do this in setup_convert later.
Don't do channelmix_init when we were not setup.
Deactivate the filter-graphs when we suspend.
Fixes#4866
Improve the spa_ump_to_midi function so that it can consume multiple UMP
messages and produce multiple midi messages.
Some UMP messages (like program changes) need to be translated into up
to 3 midi messages. Do this byt adding a state to the function and by
making it consume the input bytes, just like the spa_ump_from_midi
function.
Adapt code to this new world. This is a little API break..
When interpolating with rate correction != 1.0, don't floor the
resulting input rate to the nearest smallest integer.
This allows rate corrections < 1/in_rate to have some effect, and
reduces jumps in the response. One of the jumps is inconveniently
between rate=1.0 and rate=1.0+eps and will cause rate corrections to
oscillate if target rate varies close to 1.0.
If phase is float, calculations in impl_native_in_len/out_len can
produce wrong results due to rounding error.
It's probably better to not be in the business of predicting
floating-point rounding, so replace this by fixed-point arithmetic.
Also make sure `offset+1` cannot overflow data->filter array in
do_resample_inter* due to float multiplication possibly rounding up.
If phase is float, calculations in impl_native_in_len/out_len don't
necessarily match with do_resample, because e.g.
float phase0 = 7999.99;
float phase = phase0;
int frac = 8000, out_rate = 8000, n = 64, count = 0;
for (int j = 0; j < n; ++j) {
phase += frac;
if (phase >= out_rate) {
phase -= out_rate;
count++;
}
}
printf("count = %d\n", count); /* count = 64 */
count = (int)(phase0 + n*frac) / out_rate;
printf("count = %d\n", count); /* count = 65 */
don't give the same result.
Also add test where floating point multiplication rounding up to nearest
in
float ph = phase * pm;
uint32_t offset = (uint32_t)floorf(ph);
computation results to offset+1 > data->n_phases, accessing filter array
beyond bounds. (The accessed value is still inside allocated memory
block, but contains unrelated values; the test passes silently.)
We don't actually need to calculate the GCD for each resampler rate
update. The GCD is only used to scale the in/out rates when using the
full resampler and this we can cache and reuse when we did the setup.
The interpolating resampler can work perfectly fine with a GCD of 1 and
so we can just assume that.
Use bits to capture the work that is needed. We clear the bit when
we added the stage, when all bits are cleared we have nothing more to
do. This avoids having to check multiple bookleans.
Make a helper function to calculate the destination buffer. When all
bits are cleared, we can use the output buffer.
Ensure we have at least a `.` after `audioconvert.filter-graph`, so we
don't try to read past the end if it does not exist.
Also document in the param name that an index is expected.
We don't actually have to store the ramp parameters so allocate them on
the stack and then use them to generate the sequence.
Make it possible to generate a sequence into a custom buffer as well.
Make sure we use the right rate (the graph rate) to calculate the number
of samples when converting from time to samples.
We should prefer the value of the follower when fixating to the
PortConfig format.
To make this actually work we need to be able to check if the value is
within the configured ranges. Implement the check for all types by
simply comparing the memory. This should then work also for checking
arrays, such as channel positions.
Including C headers inside of `extern "C"` breaks use from C++. Hoist
the includes of standard C headers above the block so we don't try
to mangle the stdlib.
I initially tried to scope this with a targeted change but it's too
hard to do correctly that way. This way, we avoid whack-a-mole.
Firefox is working around this in their e21461b7b8b39cc31ba53c47d4f6f310c673ff2f
commit.
Bug: https://bugzilla.mozilla.org/1953080
As long as we are in the 'none' PortConfig mode, we set the NEED_CONFIGURE
flag.
This fixes early start in audioadpter nodes because PortConfig is set to
none at init time and this used to clear the NEED_CONFIGURE flag, which
would start the node before the session manager could to a PortConfig
and cause a -22 error.
When the follower has no buffer suggestion, it can return -ENOENT, which
should not generate an error but simply use the converter buffer
suggestion instead.
There is no need to encode the potential format in the format.dsp of
control ports, this is just for legacy compatibility with JACK apps. The
actual format can be negotiated with the types field.
Fixes midi port visibility with apps compiled against 1.2, such as JACK
apps in flatpaks.
Keep per graph latency. Sum all the graph latencies together and keep
this around as the process-latency.
Refactor the port latency setter. Make a function to recalculate the
latency of all other ports. Take into account the graph latencies.
Update the port latencies when the total graph latency changes.
First do the essential properties to set up the node, then set up the
node and then parse the params. The params might do some setup that
relies on a completely configured node, such as emit events.
Move the param enumeration code out of the main enum function.
Emit node events after completion of the set_param functions to ensure
we only emit things once.
Make the converter format a higher priority in all cases. The converter
has been negotiated first and is able to make a better suggestion for
the ideal format in all cases.
Parameter values read into a 512 byte long buffer, which is insufficient
for medium to long filter-graph parameters.
Increase the buffer to 4096 bytes to give some wiggle-room.
Because we advertize on out ports that we support DYNAMIC data, we need
to read the data pointer directly from the buffer and only fall back to
our cache (mmaped) pointer when it is NULL.
With DYNAMIC data, the peer element (mixer-dsp) directly copies the
input data pointer into the buffer data in the processing loop in order
to avoid a memcpy when there is no mixing needed.
When there is no data and the buffer is mmapable, try to mmap it. Unmap
again when clearing the buffers.
Use the mmaped data pointer of the buffer when processing.
Prefer to let the follower allocate buffers. If we are allocating
buffers, first do use_buffers on the allocating node or else the
non-allocating node just ends up with NULL buffers.