Partially revert 86af9de739
The PortParam does not give enough information to derive the direction
of the converter. If the converter is configured in convert/convert
there is just no way to know when to output a quantum or not.
Fix this by doing a quick probe of the follower and then pass the
direction to the converter.
See !2227
Report the "fractional" part of the resampler delay in
spa_io_rate_match::delay_frac, in nanosamples (1/1e9 sample) at node
rate.
The delay values are best reported in units where it is clear what the
clock domain is, so report the value in fractional samples instead of
nanoseconds. Conversion to ns is also just dividision by the appropriate
rate.
Resampler without prefill was sometime outputting with different delay
than with prefill. Adjust initial history by 1 which seems to bring it
more in line.
The resampler phase also appears to depend on how many samples remain in
history which leads to possibly unexpected +-1 variation. Take this into
account in reported phase.
These changes make the resampler delay tests pass.
Both changes are sort of empirical --- I don't fully understand why
these would fix things but they seem to be needed to make the delay
calculations agree with what the resampler outputs.
The delay is always expressed in samples at the output rate of the
resampler. For input streams we need to convert this to the expected
input rate.
Make the delay reporting in playback streams more accurate.
Resampler delay for N taps is N/2-1 input samples.
Add test that checks this.
When input rate is varying, the resampler also accumulates additional
sub-sample delay. The resampler does not currently have API to report
the instantaneous sub-sample delay. Add knownfail test for it.
Make sure we only make the buffer for the follower larger when we
downsample because then we need to ask for more data from the follower
to fill up a quantum.
Never try to make the follower buffer smaller than the quantum limit.
The reason is that the graph rate could be decreased dynamically and
then we would end up with too small buffers.
See #4490
Load multiple graphs with audioconvert.filter-graph.N where N is the
order where the graph is inserted/replaced. Run the graphs before the
channelmixer.
Graphs can be added and removed at runtime.
Instead of recalculating what to do every cycle, we can prepare a
static schedule and just run that. We only need to reevaluate it when
something changes.
For input streams, first run the resampler and then the channelmix. This
ensures that the channelmix is run with the rate of the graph instead
of the rate of the input. This is nicer because rate and quantum align
with the graph and the sample accurate volume ramps will work as
intended.
For output streams, leave the resampler after the channelmix for the same
reasons.
The current biquad calculations are based on RBJ's cookbook [1],
except for low-/highpass. Since the filter configuration is also
based on using the definition of Q, it makes sense to also align
the remaining calculations to use the same filter cookbook instead
of using resonance which doesn't result in the same coefficients
as when using Q.
[1] = https://www.w3.org/TR/audio-eq-cookbook/
Iterate the channels in the inner loop instead of the outer loop. This
makes it handle with 0 channels better but also does the more
complicated phase increment code only once for all channels. Also the
filters might stay in the cache for each channel now.
Add some padding to the delay buffer. If we wrap around, copy the
spilled samples to the front of the buffer. This makes it possible to
use the more optimized sse delay function in more cases.
Use a wrap around delay ringbuffer. We can then avoid some modulo
arithmetic and read more efficiently.
Also handle the delay convolver case better by reversing the taps and
reading the taps and delay buffer without extra overhead.
When the follower doesn't produce enough data for this many attempts,
bail and cause an xrun to avoid an infinite loop.
The limit of 8 cause real-life problems and should be larger. It should
probably depend on the expected size per cycle (node.latency) and the
current quantum but we don't always have this information.
See #4334
Use the helper instead of duplicating the same code.
Also add some helpers to parse a json array of uint32_t
Move some functions to convert between type name and id.
This gets the next key and value from an object. This function is better
because it will skip key/value pairs that don't fit in the array to hold
the key.
The previous code patter would stop parsing the object as soon as a key
larger than the available space was found.
Add spa_json_begin_array/object to replace
spa_json_init+spa_json_begin_array/object
This function is better because it does not waste a useless spa_json
structure as an iterator. The relaxed versions also error out when the
container is mismatched because parsing a mismatched container is not
going to give any results anyway.