]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Abramo Bagnara <abbagnara@racine.ra.it>
authorJaroslav Kysela <perex@perex.cz>
Mon, 6 Dec 1999 00:01:26 +0000 (00:01 +0000)
committerJaroslav Kysela <perex@perex.cz>
Mon, 6 Dec 1999 00:01:26 +0000 (00:01 +0000)
Sun, 05 Dec 1999 19:02:01 +0100

Bug fixed:
- duplicated deallocation for mmap'ed area
- missing deallocation in es18xx
- some bugs in volbal conversion

New features:
- virtual mixer for card-share (it seems to work, but I feel that it
  need further testing)

Misc:
- reorganization and extension of rate.c

Jaroslav changes:
- volbal source is mostly reverted back (no card-share mixer polling)

include/pcm.h
src/pcm/plugin/rate.c
src/pcm/plugin/volbal.c

index 13b8c9dac9a85b9321a357d1e68f593d3119ec00..b58f5c1b99458e2bb568889b66170516fd022f6a 100644 (file)
@@ -146,7 +146,7 @@ int snd_pcm_plugin_build_voices(snd_pcm_format_t *src_format,
 int snd_pcm_plugin_build_volbal(snd_pcm_format_t *src_format,
                                snd_pcm_format_t *dst_format,
                                int *ttable,
-                               snd_pcm_plugin_t **r_plugin);
+                               snd_pcm_plugin_t **r_plugin);
 
 /*
  *  Loopback interface
index af849895a12fc03088607bd9f40609fafed771db..85814d7ead87aafc2a7504b8b8a5bb934a6e37e4 100644 (file)
@@ -31,6 +31,7 @@
 #define SHIFT  11
 #define BITS   (1<<SHIFT)
 #define MASK   (BITS-1)
+#define MAX_VOICES 6
 
 /*
  *  Basic rate conversion plugin
@@ -43,98 +44,51 @@ struct rate_private_data {
        int dst_rate;
        unsigned int pitch;
        unsigned int pos;
-       signed short last_L_S1, last_R_S1;
-       signed short last_L_S2, last_R_S2;
+       signed short last_S1[MAX_VOICES];
+       signed short last_S2[MAX_VOICES];
        ssize_t old_src_size, old_dst_size;
 };
 
-static void mix_mono(struct rate_private_data *data,
-                    signed short *src_ptr, int src_size,
-                    signed short *dst_ptr, int dst_size)
-{
-       unsigned int pos;
-       signed int val;
-       signed int L_S1, L_S2;
-       
-       pos = data->pos;
-       L_S1 = data->last_L_S1;
-       L_S2 = data->last_L_S2;
-       if (pos >> SHIFT) {
-               src_ptr += ((pos >> SHIFT) - 1); pos &= MASK;
-               L_S1 = L_S2;
-               L_S2 = *src_ptr;
-       }
-       while (dst_size-- > 0) {
-               if (pos >> SHIFT) {
-                       src_ptr += (pos >> SHIFT); pos &= MASK;
-                       L_S1 = L_S2;
-                       L_S2 = *src_ptr;
-               }
-               
-               val = L_S1 + ((L_S2 - L_S1) * (signed int)pos) / BITS;
-               if (val < -32768)
-                       val = -32768;
-               else if (val > 32767)
-                       val = 32767;
-               *dst_ptr++ = val;
-               
-               pos += data->pitch;
-       }
-       data->last_L_S1 = L_S1;
-       data->last_L_S2 = L_S2;
-       data->pos = pos;
-}
 
-static void mix_stereo(struct rate_private_data *data,
-                      signed short *src_ptr, int src_size,
-                      signed short *dst_ptr, int dst_size)
+static void mix(struct rate_private_data *data, int voices,
+               signed short *src_ptr, int src_size,
+               signed short *dst_ptr, int dst_size)
 {
        unsigned int pos;
        signed int val;
-       signed int L_S1, R_S1, L_S2, R_S2;
+       signed short *S1, *S2;
+       int voice;
        
        pos = data->pos;
-       L_S1 = data->last_L_S1;
-       R_S1 = data->last_R_S1;
-       L_S2 = data->last_L_S2;
-       R_S2 = data->last_R_S2;
+       S1 = data->last_S1;
+       S2 = data->last_S2;
        if (pos >> SHIFT) {
-               src_ptr += ((pos >> SHIFT) - 1) * 2; pos &= MASK;
-               L_S1 = L_S2;
-               R_S1 = R_S2;
-               L_S2 = *src_ptr;
-               R_S2 = *(src_ptr + 1);
+               src_ptr += ((pos >> SHIFT) - 1) * voices; pos &= MASK;
+               for (voice = 0; voice < voices; ++voice) {
+                       S1[voice] = S2[voice];
+                       S2[voice] = src_ptr[voice];
+               }
        }
        while (dst_size-- > 0) {
                if (pos >> SHIFT) {
-                       src_ptr += (pos >> SHIFT) * 2; pos &= MASK;
-                       L_S1 = L_S2;
-                       R_S1 = R_S2;
-                       L_S2 = *src_ptr;
-                       R_S2 = *(src_ptr + 1);
+                       src_ptr += (pos >> SHIFT) * voices; pos &= MASK;
+                       for (voice = 0; voice < voices; ++voice) {
+                               S1[voice] = S2[voice];
+                               S2[voice] = src_ptr[voice];
+                       }
                }
                
-               val = L_S1 + ((L_S2 - L_S1) * (signed int)pos) / BITS;
-               if (val < -32768)
-                       val = -32768;
-               else if (val > 32767)
-                       val = 32767;
-               *dst_ptr++ = val;
-               // printf("L_S1 = %i, L_S2 = %i, pos = %i, val = %i\n", L_S1, L_S2, pos, val);
-               
-               val = R_S1 + ((R_S2 - R_S1) * (signed int)pos) / BITS;
-               if (val < -32768)
-                       val = -32768;
-               else if (val > 32767)
-                       val = 32767;
-               *dst_ptr++ = val;
+               for (voice = 0; voice < voices; ++voice) {
+                       val = S1[voice] + ((S2[voice] - S1[voice]) * (signed int)pos) / BITS;
+                       if (val < -32768)
+                               val = -32768;
+                       else if (val > 32767)
+                               val = 32767;
+                       *dst_ptr++ = val;
+               }
                
                pos += data->pitch;
        }
-       data->last_L_S1 = L_S1;
-       data->last_R_S1 = R_S1;
-       data->last_L_S2 = L_S2;
-       data->last_R_S2 = R_S2;
        data->pos = pos;
 }
 
@@ -152,23 +106,16 @@ static ssize_t rate_transfer(snd_pcm_plugin_t *plugin,
        data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin);
        if (data == NULL)
                return -EINVAL;
-       if (data->src_voices == 1) {
-               mix_mono(data, (signed short *)src_ptr, src_size / 2,
-                              (signed short *)dst_ptr, dst_size / 2);
-               return (dst_size / 2) * 2;
-       } 
-       else if (data->src_voices == 2) {
-               mix_stereo(data, (signed short *)src_ptr, src_size / 4,
-                                (signed short *)dst_ptr, dst_size / 4);
-               return (dst_size / 4) * 4;
-       } else {
-               return -EINVAL;
-       }
+       mix(data, data->src_voices,
+           (signed short *)src_ptr, src_size / (data->src_voices * 2),
+           (signed short *)dst_ptr, dst_size / (data->dst_voices * 2));
+       return dst_size / (2 * data->src_voices) * (2 * data->src_voices);
 }
 
 static int rate_action(snd_pcm_plugin_t *plugin, snd_pcm_plugin_action_t action)
 {
        struct rate_private_data *data;
+       int voice;
 
        if (plugin == NULL)
                return -EINVAL;
@@ -179,8 +126,9 @@ static int rate_action(snd_pcm_plugin_t *plugin, snd_pcm_plugin_action_t action)
        case DRAIN:
        case FLUSH:
                data->pos = 0;
-               data->last_L_S1 = data->last_R_S1 = 0;
-               data->last_L_S2 = data->last_R_S2 = 0;
+               for (voice = 0; voice < data->src_voices; ++voice) {
+                       data->last_S1[voice] = data->last_S2[voice] = 0;
+               }
                break;
        }
        return 0;       /* silenty ignore other actions */
@@ -215,7 +163,7 @@ static ssize_t rate_dst_size(snd_pcm_plugin_t *plugin, size_t size)
                return -EINVAL;
        data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin);
        res = (((size << SHIFT) + (data->pitch / 2)) / data->pitch);
-       res = res / (data->src_voices*2) * (data->src_voices*2);
+       res = res / (data->dst_voices*2) * (data->dst_voices*2);
        /* Why this? */
        if (size < 128*1024) {
                if (data->old_dst_size == size)
@@ -232,6 +180,7 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format,
 {
        struct rate_private_data *data;
        snd_pcm_plugin_t *plugin;
+       int voice;
 
        if (!r_plugin)
                return -EINVAL;
@@ -245,7 +194,7 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format,
                return -EINVAL;
        if (src_format->voices != dst_format->voices)
                return -EINVAL;
-       if (dst_format->voices != 1 && dst_format->voices != 2)
+       if (dst_format->voices < 1 || dst_format->voices > MAX_VOICES)
                return -EINVAL;
 
        if (src_format->format != SND_PCM_SFMT_S16_LE ||
@@ -264,8 +213,9 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format,
        data->dst_rate = dst_format->rate;
        data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate;
        data->pos = 0;
-       data->last_L_S1 = data->last_R_S1 = 0;
-       data->last_L_S2 = data->last_R_S2 = 0;
+       for (voice = 0; voice < data->src_voices; ++voice) {
+               data->last_S1[voice] = data->last_S2[voice] = 0;
+       }
        data->old_src_size = data->old_dst_size = 0;
        plugin->transfer = rate_transfer;
        plugin->src_size = rate_src_size;
index 3747e20886b73f3f6368a10281e3e739abf47f0d..6deef5e6ca1d46fcf373ecb4f8f5fba062293acb 100644 (file)
 #include <byteswap.h>
 #include "../pcm_local.h"
 
-
 #define VOLBAL_RESOLUTION 16
 
 struct volbal_private_data {
        int src_voices;
-       int noop;
+       unsigned int noop:1;
        int ttable[0];
 };
 
+static int volbal_load_ttable(struct volbal_private_data *data, 
+                             const int *src_ttable)
+{
+       int src_voice, dst_voice;
+       const int *sptr;
+       int *dptr;
+       data->noop = 1;
+       if (src_ttable == NULL)
+               return 0;
+       dptr = data->ttable;
+       sptr = src_ttable;
+       for (dst_voice = 0; dst_voice < data->src_voices; ++dst_voice) {
+               int t = 0;
+               for (src_voice = 0; src_voice < data->src_voices; ++src_voice) {
+                       if (*sptr < 0 || *sptr > VOLBAL_RESOLUTION)
+                               return -EINVAL;
+                       if (src_voice == dst_voice) {
+                               if (*sptr != VOLBAL_RESOLUTION)
+                                       data->noop = 0;
+                       }
+                       else {
+                               if (*sptr != 0)
+                                       data->noop = 0;
+                       }
+                       t += *sptr;
+                       *dptr++ = *sptr++;
+               }
+               if (t > VOLBAL_RESOLUTION)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
 static void volbal(int voices, int samples, int *ttable,
                   signed short *src_ptr, signed short *dst_ptr)
 {
@@ -48,11 +80,11 @@ static void volbal(int voices, int samples, int *ttable,
                        int src_voice;
                        signed short *s = src_ptr;
                        for (src_voice = 0; src_voice < voices; ++src_voice) {
-                               v +=  *s++ * *t++ / VOLBAL_RESOLUTION;
+                               v +=  (int) *s++ * *t++ / VOLBAL_RESOLUTION;
                        }
                        *dst_ptr++ = v;
-                       src_ptr += voices;
                }
+               src_ptr += voices;
        }
 }
 
@@ -61,16 +93,17 @@ static ssize_t volbal_transfer(snd_pcm_plugin_t *plugin,
                             char *dst_ptr, size_t dst_size)
 {
        struct volbal_private_data *data;
+
        if (plugin == NULL || src_ptr == NULL || src_size < 0 ||
                              dst_ptr == NULL || dst_size < 0)
                return -EINVAL;
        if (src_size == 0)
                return 0;
        data = (struct volbal_private_data *)snd_pcm_plugin_extra_data(plugin);
-       if (data == NULL)
-               return -EINVAL;
-       if (data->noop)
-               return 0;
+       if (data->noop) {
+               memcpy(dst_ptr, src_ptr, src_size);
+               return src_size;
+       }
 
        volbal(data->src_voices, src_size / 2 / data->src_voices, data->ttable,
               (signed short *)src_ptr, (signed short *)dst_ptr);
@@ -91,41 +124,6 @@ static ssize_t volbal_dst_size(snd_pcm_plugin_t *plugin, size_t size)
        return size;
 }
 
-
-static int volbal_load_ttable(struct volbal_private_data *data, 
-                             const int *src_ttable)
-{
-       int src_voice, dst_voice;
-       const int *sptr;
-       int *dptr;
-       data->noop = 1;
-       if (src_ttable == NULL)
-               return 0;
-       sptr = src_ttable;
-       dptr = data->ttable;
-       for (dst_voice = 0; dst_voice < data->src_voices; ++dst_voice) {
-               int t = 0;
-               for (src_voice = 0; src_voice < data->src_voices; ++src_voice) {
-                       if (*sptr < 0 || *sptr > VOLBAL_RESOLUTION)
-                               return -EINVAL;
-                       if (src_voice == dst_voice) {
-                               if (*sptr != VOLBAL_RESOLUTION)
-                                       data->noop = 0;
-                       }
-                       else {
-                               if (*sptr != 0)
-                                       data->noop = 0;
-                       }
-                       t += *sptr;
-                       *dptr++ = *sptr++;
-               }
-               if (t > VOLBAL_RESOLUTION)
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-
 int snd_pcm_plugin_build_volbal(snd_pcm_format_t *src_format,
                                snd_pcm_format_t *dst_format,
                                int *ttable,
@@ -133,7 +131,7 @@ int snd_pcm_plugin_build_volbal(snd_pcm_format_t *src_format,
 {
        struct volbal_private_data *data;
        snd_pcm_plugin_t *plugin;
-       int res;
+       int err;
 
        if (!r_plugin)
                return -EINVAL;
@@ -159,10 +157,10 @@ int snd_pcm_plugin_build_volbal(snd_pcm_format_t *src_format,
        if (plugin == NULL)
                return -ENOMEM;
        data = (struct volbal_private_data *)snd_pcm_plugin_extra_data(plugin);
-       data->src_voices = src_format->voices;
-       if ((res = volbal_load_ttable(data, ttable)) < 0)
-               return res;
 
+       data->src_voices = src_format->voices;
+       if ((err = volbal_load_ttable(data, ttable)) < 0)
+               return err;
        plugin->transfer = volbal_transfer;
        plugin->src_size = volbal_src_size;
        plugin->dst_size = volbal_dst_size;