Fixed rounding issues

This commit is contained in:
Abramo Bagnara 2000-12-10 12:08:20 +00:00
parent 5465c299ab
commit b5e96c0161
2 changed files with 38 additions and 19 deletions

View file

@ -133,6 +133,7 @@ void snd_pcm_hw_info_any(snd_pcm_hw_info_t *info)
void snd_pcm_hw_params_to_info(snd_pcm_hw_params_t *params, snd_pcm_hw_info_t *info) void snd_pcm_hw_params_to_info(snd_pcm_hw_params_t *params, snd_pcm_hw_info_t *info)
{ {
int r;
assert(info && params); assert(info && params);
info->flags = 0; info->flags = 0;
info->access_mask = 1U << params->access; info->access_mask = 1U << params->access;
@ -140,9 +141,15 @@ void snd_pcm_hw_params_to_info(snd_pcm_hw_params_t *params, snd_pcm_hw_info_t *i
info->subformat_mask = 1U << params->subformat; info->subformat_mask = 1U << params->subformat;
info->channels_min = info->channels_max = params->channels; info->channels_min = info->channels_max = params->channels;
info->rate_min = info->rate_max = params->rate; info->rate_min = info->rate_max = params->rate;
info->fragment_length_min = info->fragment_length_max = muldiv_down(params->fragment_size, 1000000, params->rate); info->fragment_length_min = muldiv_down(params->fragment_size, 1000000, params->rate);
info->fragment_length_max = muldiv(params->fragment_size + 1, 1000000, params->rate, &r);
if (r == 0)
info->fragment_length_max--;
info->fragments_min = info->fragments_max = params->fragments; info->fragments_min = info->fragments_max = params->fragments;
info->buffer_length_min = info->buffer_length_max = muldiv_down(params->fragment_size * params->fragments, 1000000, params->rate); info->buffer_length_min = muldiv_down(params->fragment_size * params->fragments, 1000000, params->rate);
info->buffer_length_max = muldiv((params->fragment_size + 1) * params->fragments, 1000000, params->rate, &r);
if (r == 0)
info->buffer_length_max--;
} }
int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
@ -1921,7 +1928,8 @@ int snd_pcm_hw_info_to_params(snd_pcm_t *pcm, snd_pcm_hw_info_t *info, snd_pcm_h
} }
assert(info->fragments_min <= info->fragments_max); assert(info->fragments_min <= info->fragments_max);
if (info->fragments_min < info->fragments_max) { if (info->fragments_min < info->fragments_max) {
info->fragments_max = info->fragments_min; /* Defaults to maximum use of buffer */
info->fragments_min = info->fragments_max;
err = snd_pcm_hw_info(pcm, info); err = snd_pcm_hw_info(pcm, info);
assert(err >= 0); assert(err >= 0);
} }

View file

@ -280,28 +280,39 @@ static inline ssize_t _snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size)
return pcm->fast_ops->readn(pcm->fast_op_arg, bufs, size); return pcm->fast_ops->readn(pcm->fast_op_arg, bufs, size);
} }
static inline ssize_t muldiv(ssize_t a, ssize_t b, ssize_t d, ssize_t corr) static inline int muldiv(int a, int b, int c, int *r)
{ {
double v = ((double) a * b + corr) / d; int64_t n = (int64_t)a * b;
if (v > LONG_MAX) int64_t v = n / c;
return LONG_MAX; if (v > INT_MAX) {
if (v < LONG_MIN) *r = 0;
return LONG_MIN; return INT_MAX;
}
if (v < INT_MIN) {
*r = 0;
return INT_MIN;
}
*r = n % c;
return v; return v;
} }
static inline ssize_t muldiv_down(ssize_t a, ssize_t b, ssize_t d) static inline int muldiv_down(int a, int b, int c)
{ {
return muldiv(a, b, d, 0); int64_t v = (int64_t)a * b / c;
if (v > INT_MAX) {
return INT_MAX;
}
if (v < INT_MIN) {
return INT_MIN;
}
return v;
} }
static inline ssize_t muldiv_up(ssize_t a, ssize_t b, ssize_t d) static inline int muldiv_near(int a, int b, int c)
{ {
return muldiv(a, b, d, d - 1); int r;
int n = muldiv(a, b, c, &r);
if (r >= (c + 1) / 2)
n++;
return n;
} }
static inline ssize_t muldiv_near(ssize_t a, ssize_t b, ssize_t d)
{
return muldiv(a, b, d, d / 2);
}