mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-21 06:59:59 -05:00
resampler: Add pa_resampler_prepare() and pa_resampler_get_delay() functions
The pa_resampler_get_delay() function allows to retrieve the current resampler delay in input samples for all supported resamplers. The return value is a double to maintain precision when using variable rate resamplers. Because in many places the delay is needed in usec, pa_resampler_get_delay_usec() was also supplied. The speex resampler now skips leading zero samples to provide meaningful delay values. In the next patch, the pa_resampler_prepare() function will be used to train the resampler after a rewind. It takes data from a history memblockq and runs it through the resampler. The output data is discarded. To make this logic possible, the soxr resampler had to be converted to use variable rate. The fixed rate version has a variable delay, therefore the logic above could not be applied. Additionally, with fixed rate, the delay is larger than 150ms in some situations, while with variable rate the delay is fixed and comparable to the other resamplers. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/120>
This commit is contained in:
parent
1bfabd6512
commit
656179a8fe
6 changed files with 142 additions and 28 deletions
|
|
@ -65,9 +65,14 @@ static void resampler_soxr_free(pa_resampler *r) {
|
|||
|
||||
static void resampler_soxr_reset(pa_resampler *r) {
|
||||
#if SOXR_THIS_VERSION >= SOXR_VERSION(0, 1, 2)
|
||||
double ratio;
|
||||
|
||||
pa_assert(r);
|
||||
|
||||
soxr_clear(r->impl.data);
|
||||
|
||||
ratio = (double)r->i_ss.rate / (double)r->o_ss.rate;
|
||||
soxr_set_io_ratio(r->impl.data, ratio, 0);
|
||||
#else
|
||||
/* With libsoxr prior to 0.1.2 soxr_clear() makes soxr_process() crash afterwards,
|
||||
* so don't use this function and re-create the context instead. */
|
||||
|
|
@ -89,23 +94,12 @@ static void resampler_soxr_reset(pa_resampler *r) {
|
|||
}
|
||||
|
||||
static void resampler_soxr_update_rates(pa_resampler *r) {
|
||||
soxr_t old_state;
|
||||
double ratio;
|
||||
|
||||
pa_assert(r);
|
||||
|
||||
/* There is no update method in libsoxr,
|
||||
* so just re-create the resampler context */
|
||||
|
||||
old_state = r->impl.data;
|
||||
r->impl.data = NULL;
|
||||
|
||||
if (pa_resampler_soxr_init(r) == 0) {
|
||||
if (old_state)
|
||||
soxr_delete(old_state);
|
||||
} else {
|
||||
r->impl.data = old_state;
|
||||
pa_log_error("Failed to update libsoxr sample rates");
|
||||
}
|
||||
ratio = (double)r->i_ss.rate / (double)r->o_ss.rate;
|
||||
soxr_set_io_ratio(r->impl.data, ratio, 0);
|
||||
}
|
||||
|
||||
int pa_resampler_soxr_init(pa_resampler *r) {
|
||||
|
|
@ -116,6 +110,7 @@ int pa_resampler_soxr_init(pa_resampler *r) {
|
|||
unsigned long quality_recipe;
|
||||
soxr_quality_spec_t quality;
|
||||
soxr_error_t err = NULL;
|
||||
double ratio;
|
||||
|
||||
pa_assert(r);
|
||||
|
||||
|
|
@ -150,14 +145,18 @@ int pa_resampler_soxr_init(pa_resampler *r) {
|
|||
pa_assert_not_reached();
|
||||
}
|
||||
|
||||
quality = soxr_quality_spec(quality_recipe, 0);
|
||||
quality = soxr_quality_spec(quality_recipe, SOXR_VR);
|
||||
|
||||
state = soxr_create(r->i_ss.rate, r->o_ss.rate, r->work_channels, &err, &io_spec, &quality, &runtime_spec);
|
||||
/* Maximum resample ratio is 100:1 */
|
||||
state = soxr_create(100, 1, r->work_channels, &err, &io_spec, &quality, &runtime_spec);
|
||||
if (!state) {
|
||||
pa_log_error("Failed to create libsoxr resampler context: %s.", (err ? err : "[unknown error]"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ratio = (double)r->i_ss.rate / (double)r->o_ss.rate;
|
||||
soxr_set_io_ratio(state, ratio, 0);
|
||||
|
||||
r->impl.free = resampler_soxr_free;
|
||||
r->impl.reset = resampler_soxr_reset;
|
||||
r->impl.update_rates = resampler_soxr_update_rates;
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ static void speex_reset(pa_resampler *r) {
|
|||
state = r->impl.data;
|
||||
|
||||
pa_assert_se(speex_resampler_reset_mem(state) == 0);
|
||||
speex_resampler_skip_zeros(state);
|
||||
}
|
||||
|
||||
static void speex_free(pa_resampler *r) {
|
||||
|
|
@ -172,6 +173,8 @@ int pa_resampler_speex_init(pa_resampler *r) {
|
|||
if (!(state = speex_resampler_init(r->work_channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
|
||||
return -1;
|
||||
|
||||
speex_resampler_skip_zeros(state);
|
||||
|
||||
r->impl.data = state;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue