summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2021-06-17 10:20:25 +0200
committerTakashi Iwai <tiwai@suse.de>2021-06-17 10:20:25 +0200
commit5089358aa99d698bd846b05c1890a09613d740b3 (patch)
treeb953e58a4cb2c35732172d8fe062e3e1048254f6
parent81e7923fbfad45b2f353a4d6e3053af51f5f7d0b (diff)
downloadalsa-lib-5089358aa99d698bd846b05c1890a09613d740b3.tar.gz
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>
-rw-r--r--src/pcm/pcm_rate.c80
1 files changed, 49 insertions, 31 deletions
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
index 770aafea..1e996134 100644
--- a/src/pcm/pcm_rate.c
+++ b/src/pcm/pcm_rate.c
@@ -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);