mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
context: improve rate selection
Try to upsample to something in the same rate family so that the amount of resample filter is minimal. If that doesn't work, try to downsample to something in the same rate family above the 44100 threshold. If that also doesn't work, downsample to the highest available samplerate.
This commit is contained in:
parent
fab9d12a44
commit
a5b2282b14
1 changed files with 80 additions and 5 deletions
|
|
@ -970,15 +970,90 @@ static int fraction_compare(const struct spa_fraction *a, const struct spa_fract
|
|||
return fa < fb ? -1 : (fa > fb ? 1 : 0);
|
||||
}
|
||||
|
||||
static uint32_t find_best_rate(const uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t best)
|
||||
static inline uint32_t calc_gcd(uint32_t a, uint32_t b)
|
||||
{
|
||||
while (b != 0) {
|
||||
uint32_t temp = a;
|
||||
a = b;
|
||||
b = temp % b;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
struct rate_info {
|
||||
uint32_t rate;
|
||||
uint32_t gcd;
|
||||
uint32_t diff;
|
||||
};
|
||||
|
||||
static inline void update_highest_rate(struct rate_info *best, struct rate_info *current)
|
||||
{
|
||||
/* find highest rate */
|
||||
if (best->rate == 0 || best->rate < current->rate)
|
||||
*best = *current;
|
||||
}
|
||||
|
||||
static inline void update_nearest_gcd(struct rate_info *best, struct rate_info *current)
|
||||
{
|
||||
/* find nearest GCD */
|
||||
if (best->rate == 0 ||
|
||||
(best->gcd < current->gcd) ||
|
||||
(best->gcd == current->gcd && best->diff > current->diff))
|
||||
*best = *current;
|
||||
}
|
||||
|
||||
static uint32_t find_best_rate(const uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t current)
|
||||
{
|
||||
uint32_t i;
|
||||
struct rate_info best;
|
||||
struct rate_info info[n_rates];
|
||||
|
||||
for (i = 0; i < n_rates; i++) {
|
||||
if (SPA_ABS((int32_t)rate - (int32_t)rates[i]) <
|
||||
SPA_ABS((int32_t)rate - (int32_t)best))
|
||||
best = rates[i];
|
||||
info[i].rate = rates[i];
|
||||
info[i].gcd = calc_gcd(rate, rates[i]);
|
||||
info[i].diff = SPA_ABS((int32_t)rate - (int32_t)rates[i]);
|
||||
}
|
||||
return best;
|
||||
|
||||
/* first find higher nearest GCD. This tries to find next bigest rate that
|
||||
* requires the least amount of resample filter banks. Usually these are
|
||||
* rates that are multiples of eachother or multiples of a common rate.
|
||||
*
|
||||
* 44100 and [ 32000 56000 88200 96000 ] -> 88200
|
||||
* 48000 and [ 32000 56000 88200 96000 ] -> 96000
|
||||
* 88200 and [ 44100 48000 96000 192000 ] -> 96000
|
||||
*/
|
||||
spa_zero(best);
|
||||
for (i = 0; i < n_rates; i++) {
|
||||
if (info[i].rate >= rate)
|
||||
update_nearest_gcd(&best, &info[i]);
|
||||
}
|
||||
if (best.rate != 0)
|
||||
return best.rate;
|
||||
|
||||
/* There is nothing above the rate, we need to downsample. Try to downsample
|
||||
* but only to something that is from a common rate family. Also don't
|
||||
* try to downsample to something that will sound worse.
|
||||
*
|
||||
* 88200 and [ 22050 44100 48000 ] -> 44100
|
||||
* 88200 and [ 22050 48000 ] -> 48000
|
||||
*/
|
||||
spa_zero(best);
|
||||
for (i = 0; i < n_rates; i++) {
|
||||
if (info[i].rate >= 44100)
|
||||
update_nearest_gcd(&best, &info[i]);
|
||||
}
|
||||
if (best.rate != 0)
|
||||
return best.rate;
|
||||
|
||||
/* There is nothing to downsample above our threshold. Downsample to whatever
|
||||
* is the highest rate then. */
|
||||
spa_zero(best);
|
||||
for (i = 0; i < n_rates; i++)
|
||||
update_highest_rate(&best, &info[i]);
|
||||
if (best.rate != 0)
|
||||
return best.rate;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
/* here we evaluate the complete state of the graph.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue