OSDN Git Service

dmix: add U8 support
authorClemens Ladisch <clemens@ladisch.de>
Mon, 10 Dec 2007 11:35:08 +0000 (12:35 +0100)
committerClemens Ladisch <clemens@ladisch.de>
Mon, 10 Dec 2007 11:35:08 +0000 (12:35 +0100)
Add support for direct mixing of U8 samples (for devices like some USB
headsets or the Tux Droid).

src/pcm/pcm_direct.c
src/pcm/pcm_direct.h
src/pcm/pcm_dmix.c
src/pcm/pcm_dmix_generic.c

index 64003a0..3f908e2 100644 (file)
@@ -885,6 +885,7 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
                        SND_PCM_FORMAT_S16,
                        SND_PCM_FORMAT_S16 ^ SND_PCM_FORMAT_S16_LE ^ SND_PCM_FORMAT_S16_BE,
                        SND_PCM_FORMAT_S24_3LE,
+                       SND_PCM_FORMAT_U8,
                };
                snd_pcm_format_t format;
                unsigned int i;
index a96fb4e..b51ca85 100644 (file)
@@ -44,6 +44,11 @@ typedef void (mix_areas_24_t)(unsigned int size,
                              volatile signed int *sum, size_t dst_step,
                              size_t src_step, size_t sum_step);
 
+typedef void (mix_areas_u8_t)(unsigned int size,
+                             volatile unsigned char *dst, unsigned char *src,
+                             volatile signed int *sum, size_t dst_step,
+                             size_t src_step, size_t sum_step);
+
 struct slave_params {
        snd_pcm_format_t format;
        int rate;
@@ -156,6 +161,7 @@ struct snd_pcm_direct {
                        mix_areas_16_t *mix_areas_16;
                        mix_areas_32_t *mix_areas_32;
                        mix_areas_24_t *mix_areas_24;
+                       mix_areas_u8_t *mix_areas_u8;
                } dmix;
                struct {
                } dsnoop;
index b2c200d..b9fb1c7 100644 (file)
@@ -176,6 +176,10 @@ static void mix_areas(snd_pcm_direct_t *dmix,
                sample_size = 3;
                do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_24;
                break;
+       case SND_PCM_FORMAT_U8:
+               sample_size = 1;
+               do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_u8;
+               break;
        default:
                return;
        }
index 492f5f7..9bef18d 100644 (file)
@@ -122,7 +122,8 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
 #define generic_dmix_supported_format \
        ((1ULL << SND_PCM_FORMAT_S16_LE) | (1ULL << SND_PCM_FORMAT_S32_LE) |\
         (1ULL << SND_PCM_FORMAT_S16_BE) | (1ULL << SND_PCM_FORMAT_S32_BE) |\
-        (1ULL << SND_PCM_FORMAT_S24_3LE))
+        (1ULL << SND_PCM_FORMAT_S24_3LE) | \
+        (1ULL << SND_PCM_FORMAT_U8))
 
 #include <byteswap.h>
 
@@ -292,6 +293,35 @@ static void generic_mix_areas_24(unsigned int size,
        }
 }
 
+static void generic_mix_areas_u8(unsigned int size,
+                                volatile unsigned char *dst,
+                                unsigned char *src,
+                                volatile signed int *sum,
+                                size_t dst_step,
+                                size_t src_step,
+                                size_t sum_step)
+{
+       for (;;) {
+               register int sample = *src - 0x80;
+               if (*dst == 0x80) {
+                       *sum = sample;
+               } else {
+                       sample += *sum;
+                       *sum = sample;
+                       if (sample > 0x7f)
+                               sample = 0x7f;
+                       else if (sample < -0x80)
+                               sample = -0x80;
+               }
+               *dst = sample + 0x80;
+               if (!--size)
+                       return;
+               dst += dst_step;
+               src += src_step;
+               sum = (signed int *) ((char *)sum + sum_step);
+       }
+}
+
 
 static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
 {
@@ -303,6 +333,7 @@ static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
                dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_swap;
        }
        dmix->u.dmix.mix_areas_24 = generic_mix_areas_24;
+       dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
 }
 
 #endif