@@ -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);
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> --- src/pcm/pcm_rate.c | 80 ++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 31 deletions(-)