]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Added proper initialization for expand, added corrections for sw_params (checks for...
authorJaroslav Kysela <perex@perex.cz>
Mon, 11 Mar 2002 14:59:11 +0000 (14:59 +0000)
committerJaroslav Kysela <perex@perex.cz>
Mon, 11 Mar 2002 14:59:11 +0000 (14:59 +0000)
src/pcm/pcm_rate.c

index f1f55324676b0e724d3075539b9fe2914798d047..8d1f11bf0fb7cae706992f9f9742b30bfe3e0642 100644 (file)
@@ -41,6 +41,7 @@ const char *_snd_module_pcm_rate = "";
 #define DIV (1<<16)
 
 typedef struct {
+       int init;
        int16_t sample;
        int sum;
        unsigned int pos;
@@ -69,6 +70,22 @@ typedef struct {
        snd_pcm_rate_state_t *states;
 } snd_pcm_rate_t;
 
+static int16_t initial_sample(const char *src, unsigned int getidx)
+{
+#define GET16_LABELS
+#include "plugin_ops.h"
+#undef GET16_LABELS
+       void *get = get16_labels[getidx];
+       int sample = 0;
+
+       goto *get;
+#define GET16_END after_get
+#include "plugin_ops.h"
+#undef GET16_END
+      after_get:
+       return sample;
+}
+
 static snd_pcm_uframes_t snd_pcm_rate_expand(const snd_pcm_channel_area_t *dst_areas,
                                             snd_pcm_uframes_t dst_offset, snd_pcm_uframes_t *dst_framesp,
                                             const snd_pcm_channel_area_t *src_areas,
@@ -108,6 +125,10 @@ static snd_pcm_uframes_t snd_pcm_rate_expand(const snd_pcm_channel_area_t *dst_a
                dst_step = snd_pcm_channel_area_step(dst_area);
                src_frames1 = 0;
                dst_frames1 = 0;
+               if (states->init) {
+                       old_sample = initial_sample(src, getidx);
+                       states->init = 0;
+               }
                while (dst_frames1 < dst_frames) {
                        if (pos >= get_threshold) {
                                int16_t new_sample;
@@ -178,6 +199,7 @@ static snd_pcm_uframes_t snd_pcm_rate_shrink(const snd_pcm_channel_area_t *dst_a
                int src_step, dst_step;
                sum = states->sum;
                pos = states->pos;
+               states->init = 0;
                src = snd_pcm_channel_area_addr(src_area, src_offset);
                dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
                src_step = snd_pcm_channel_area_step(src_area);
@@ -382,23 +404,40 @@ static int snd_pcm_rate_hw_free(snd_pcm_t *pcm)
        snd_pcm_rate_t *rate = pcm->private_data;
        if (rate->states) {
                free(rate->states);
-               rate->states = 0;
+               rate->states = NULL;
        }
        return snd_pcm_hw_free(rate->plug.slave);
 }
 
+static void recalc(snd_pcm_t *pcm, snd_pcm_uframes_t *val)
+{
+       snd_pcm_rate_t *rate = pcm->private_data;
+       snd_pcm_t *slave = rate->plug.slave;
+       unsigned long div;
+
+       if (*val == pcm->buffer_size) {
+               *val = slave->buffer_size;
+       } else {
+               div = *val / pcm->period_size;
+               if (div * pcm->period_size == *val)
+                       *val = div * slave->period_size;
+               else
+                       *val = muldiv_near(*val, slave->rate, pcm->rate);
+       }
+}
+
 static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
 {
        snd_pcm_rate_t *rate = pcm->private_data;
        snd_pcm_t *slave = rate->plug.slave;
        snd_pcm_sw_params_t sparams;
        sparams = *params;
-       sparams.avail_min = muldiv_near(sparams.avail_min, slave->rate, pcm->rate);
-       sparams.xfer_align = muldiv_near(sparams.xfer_align, slave->rate, pcm->rate);
-       sparams.silence_threshold = muldiv_near(sparams.silence_threshold, slave->rate, pcm->rate);
-       sparams.silence_size = muldiv_near(sparams.silence_size, slave->rate, pcm->rate);
-       sparams.start_threshold = muldiv_near(sparams.start_threshold, slave->rate, pcm->rate);
-       sparams.stop_threshold = muldiv_near(sparams.stop_threshold, slave->rate, pcm->rate);
+       recalc(pcm, &sparams.avail_min);
+       recalc(pcm, &sparams.xfer_align);
+       recalc(pcm, &sparams.start_threshold);
+       recalc(pcm, &sparams.stop_threshold);
+       recalc(pcm, &sparams.silence_threshold);
+       recalc(pcm, &sparams.silence_size);
        return snd_pcm_sw_params(slave, &sparams);
 }
 
@@ -409,12 +448,8 @@ static int snd_pcm_rate_init(snd_pcm_t *pcm)
        for (k = 0; k < pcm->channels; ++k) {
                rate->states[k].sum = 0;
                rate->states[k].sample = 0;
-               if (rate->func == snd_pcm_rate_expand) {
-                       /* Get a sample on entry */
-                       rate->states[k].pos = rate->pitch;
-               } else {
-                       rate->states[k].pos = 0;
-               }
+               rate->states[k].pos = 0;
+               rate->states[k].init = 0;
        }
        return 0;
 }