From 6e6f4b9c9347277dce66c342f1eceb2fbab558e2 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 10 Dec 2007 12:35:08 +0100 Subject: [PATCH] dmix: add U8 support Add support for direct mixing of U8 samples (for devices like some USB headsets or the Tux Droid). --- src/pcm/pcm_direct.c | 1 + src/pcm/pcm_direct.h | 6 ++++++ src/pcm/pcm_dmix.c | 4 ++++ src/pcm/pcm_dmix_generic.c | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 64003a0d..3f908e26 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -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; diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h index a96fb4e6..b51ca851 100644 --- a/src/pcm/pcm_direct.h +++ b/src/pcm/pcm_direct.h @@ -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; diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index b2c200d5..b9fb1c7a 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -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; } diff --git a/src/pcm/pcm_dmix_generic.c b/src/pcm/pcm_dmix_generic.c index 492f5f7d..9bef18d6 100644 --- a/src/pcm/pcm_dmix_generic.c +++ b/src/pcm/pcm_dmix_generic.c @@ -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 @@ -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 -- 2.47.1