pcm: rate: Refactoring temporary buffer allocations

Introduce common helpers to allocate and release the temporary buffers
and the associated snd_pcm_channel.  Now two allocated objects are
used instead of one malloc to be split.

Also, change the snd_pcm_channel set up to be in interleaved mode.
This will be necessary in the following change in the rate plugin.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2021-06-17 10:20:25 +02:00
parent 81e7923fbf
commit 5089358aa9

View File

@ -76,6 +76,45 @@ struct _snd_pcm_rate {
#endif /* DOC_HIDDEN */
/* allocate a channel area and a temporary buffer for the given size */
static snd_pcm_channel_area_t *
rate_alloc_tmp_buf(snd_pcm_rate_t *rate, snd_pcm_format_t format,
unsigned int channels, unsigned int frames)
{
snd_pcm_channel_area_t *ap;
int width = snd_pcm_format_physical_width(format);
int i;
ap = malloc(sizeof(*ap) * channels);
if (!ap)
return NULL;
ap->addr = malloc(frames * channels * width / 8);
if (!ap->addr) {
free(ap);
return NULL;
}
/* set up in interleaved format */
for (i = 0; i < channels; i++) {
ap[i].addr = ap[0].addr + (i * width) / 8;
ap[i].first = 0;
ap[i].step = width * channels;
}
return ap;
}
static void rate_free_tmp_buf(snd_pcm_channel_area_t **ptr)
{
snd_pcm_channel_area_t *c = *ptr;
if (c) {
free(c->addr);
free(c);
*ptr = NULL;
}
}
static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
{
snd_pcm_rate_t *rate = pcm->private_data;
@ -286,28 +325,13 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
if (err < 0)
return err;
rate->pareas = malloc(2 * channels * sizeof(*rate->pareas));
if (rate->pareas == NULL)
rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels,
cinfo->period_size);
rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels,
sinfo->period_size);
if (!rate->pareas || !rate->sareas)
goto error;
cwidth = snd_pcm_format_physical_width(cinfo->format);
swidth = snd_pcm_format_physical_width(sinfo->format);
rate->pareas[0].addr = malloc(((cwidth * channels * cinfo->period_size) / 8) +
((swidth * channels * sinfo->period_size) / 8));
if (rate->pareas[0].addr == NULL)
goto error;
rate->sareas = rate->pareas + channels;
rate->sareas[0].addr = (char *)rate->pareas[0].addr + ((cwidth * channels * cinfo->period_size) / 8);
for (chn = 0; chn < channels; chn++) {
rate->pareas[chn].addr = (char *)rate->pareas[0].addr + (cwidth * chn * cinfo->period_size) / 8;
rate->pareas[chn].first = 0;
rate->pareas[chn].step = cwidth;
rate->sareas[chn].addr = (char *)rate->sareas[0].addr + (swidth * chn * sinfo->period_size) / 8;
rate->sareas[chn].first = 0;
rate->sareas[chn].step = swidth;
}
if (rate->ops.convert_s16) {
rate->get_idx = snd_pcm_linear_get_index(rate->info.in.format, SND_PCM_FORMAT_S16);
rate->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, rate->info.out.format);
@ -322,11 +346,8 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
return 0;
error:
if (rate->pareas) {
free(rate->pareas[0].addr);
free(rate->pareas);
rate->pareas = NULL;
}
rate_free_tmp_buf(&rate->pareas);
rate_free_tmp_buf(&rate->sareas);
if (rate->ops.free)
rate->ops.free(rate->obj);
return -ENOMEM;
@ -335,12 +356,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
static int snd_pcm_rate_hw_free(snd_pcm_t *pcm)
{
snd_pcm_rate_t *rate = pcm->private_data;
if (rate->pareas) {
free(rate->pareas[0].addr);
free(rate->pareas);
rate->pareas = NULL;
rate->sareas = NULL;
}
rate_free_tmp_buf(&rate->pareas);
rate_free_tmp_buf(&rate->sareas);
if (rate->ops.free)
rate->ops.free(rate->obj);
free(rate->src_buf);