dmix: simplify mix_areas()

The code for the three supported sample widths is almost the same, so it
makes sense to merge the three cases.
This commit is contained in:
Clemens Ladisch 2007-12-10 12:32:36 +01:00
parent 79db4a6bfa
commit a3fe1f7800
2 changed files with 52 additions and 86 deletions

View file

@ -24,6 +24,11 @@
#define DIRECT_IPC_SEMS 1 #define DIRECT_IPC_SEMS 1
#define DIRECT_IPC_SEM_CLIENT 0 #define DIRECT_IPC_SEM_CLIENT 0
typedef void (mix_areas_t)(unsigned int size,
volatile void *dst, void *src,
volatile signed int *sum, size_t dst_step,
size_t src_step, size_t sum_step);
typedef void (mix_areas_16_t)(unsigned int size, typedef void (mix_areas_16_t)(unsigned int size,
volatile signed short *dst, signed short *src, volatile signed short *dst, signed short *src,
volatile signed int *sum, size_t dst_step, volatile signed int *sum, size_t dst_step,

View file

@ -156,95 +156,56 @@ static void mix_areas(snd_pcm_direct_t *dmix,
snd_pcm_uframes_t dst_ofs, snd_pcm_uframes_t dst_ofs,
snd_pcm_uframes_t size) snd_pcm_uframes_t size)
{ {
volatile signed int *sum;
unsigned int src_step, dst_step; unsigned int src_step, dst_step;
unsigned int chn, dchn, channels; unsigned int chn, dchn, channels, sample_size;
mix_areas_t *do_mix_areas;
channels = dmix->channels; channels = dmix->channels;
if (dmix->shmptr->s.format == SND_PCM_FORMAT_S16_LE || switch (dmix->shmptr->s.format) {
dmix->shmptr->s.format == SND_PCM_FORMAT_S16_BE) { case SND_PCM_FORMAT_S16_LE:
signed short *src; case SND_PCM_FORMAT_S16_BE:
volatile signed short *dst; sample_size = 2;
if (dmix->interleaved) { do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_16;
/* break;
* process all areas in one loop case SND_PCM_FORMAT_S32_LE:
* it optimizes the memory accesses for this case case SND_PCM_FORMAT_S32_BE:
*/ sample_size = 4;
dmix->u.dmix.mix_areas_16(size * channels, do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_32;
((signed short *)dst_areas[0].addr) + (dst_ofs * channels), break;
((signed short *)src_areas[0].addr) + (src_ofs * channels), case SND_PCM_FORMAT_S24_3LE:
dmix->u.dmix.sum_buffer + (dst_ofs * channels), sample_size = 3;
sizeof(signed short), do_mix_areas = (mix_areas_t *)dmix->u.dmix.mix_areas_24;
sizeof(signed short), break;
sizeof(signed int)); default:
return; return;
} }
for (chn = 0; chn < channels; chn++) { if (dmix->interleaved) {
dchn = dmix->bindings ? dmix->bindings[chn] : chn; /*
if (dchn >= dmix->shmptr->s.channels) * process all areas in one loop
continue; * it optimizes the memory accesses for this case
src_step = src_areas[chn].step / 8; */
dst_step = dst_areas[dchn].step / 8; do_mix_areas(size * channels,
src = (signed short *)(((char *)src_areas[chn].addr + src_areas[chn].first / 8) + (src_ofs * src_step)); (unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,
dst = (signed short *)(((char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + (dst_ofs * dst_step)); (unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,
sum = dmix->u.dmix.sum_buffer + channels * dst_ofs + chn; dmix->u.dmix.sum_buffer + dst_ofs * channels,
dmix->u.dmix.mix_areas_16(size, dst, src, sum, dst_step, src_step, channels * sizeof(signed int)); sample_size,
} sample_size,
} else if (dmix->shmptr->s.format == SND_PCM_FORMAT_S32_LE || sizeof(signed int));
dmix->shmptr->s.format == SND_PCM_FORMAT_S32_BE) { return;
signed int *src; }
volatile signed int *dst; for (chn = 0; chn < channels; chn++) {
if (dmix->interleaved) { dchn = dmix->bindings ? dmix->bindings[chn] : chn;
/* if (dchn >= dmix->shmptr->s.channels)
* process all areas in one loop continue;
* it optimizes the memory accesses for this case src_step = src_areas[chn].step / 8;
*/ dst_step = dst_areas[dchn].step / 8;
dmix->u.dmix.mix_areas_32(size * channels, do_mix_areas(size,
((signed int *)dst_areas[0].addr) + (dst_ofs * channels), ((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step,
((signed int *)src_areas[0].addr) + (src_ofs * channels), ((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step,
dmix->u.dmix.sum_buffer + (dst_ofs * channels), dmix->u.dmix.sum_buffer + channels * dst_ofs + chn,
sizeof(signed int), dst_step,
sizeof(signed int), src_step,
sizeof(signed int)); channels * sizeof(signed int));
return;
}
for (chn = 0; chn < channels; chn++) {
dchn = dmix->bindings ? dmix->bindings[chn] : chn;
if (dchn >= dmix->shmptr->s.channels)
continue;
src_step = src_areas[chn].step / 8;
dst_step = dst_areas[dchn].step / 8;
src = (signed int *)(((char *)src_areas[chn].addr + src_areas[chn].first / 8) + (src_ofs * src_step));
dst = (signed int *)(((char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + (dst_ofs * dst_step));
sum = dmix->u.dmix.sum_buffer + channels * dst_ofs + chn;
dmix->u.dmix.mix_areas_32(size, dst, src, sum, dst_step, src_step, channels * sizeof(signed int));
}
} else { /* SND_PCM_FORMAT_S24_3LE */
unsigned char *src;
volatile unsigned char *dst;
if (dmix->interleaved) {
/*
* process all areas in one loop
* it optimizes the memory accesses for this case
*/
dmix->u.dmix.mix_areas_24(size * channels,
((unsigned char *)dst_areas[0].addr) + 3 * dst_ofs * channels,
((unsigned char *)src_areas[0].addr) + 3 * src_ofs * channels,
dmix->u.dmix.sum_buffer + (dst_ofs * channels),
3, 3, sizeof(signed int));
return;
}
for (chn = 0; chn < channels; chn++) {
dchn = dmix->bindings ? dmix->bindings[chn] : chn;
if (dchn >= dmix->shmptr->s.channels)
continue;
src_step = src_areas[chn].step / 8;
dst_step = dst_areas[dchn].step / 8;
src = (unsigned char *)(((char *)src_areas[chn].addr + src_areas[chn].first / 8) + (src_ofs * src_step));
dst = (unsigned char *)(((char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + (dst_ofs * dst_step));
sum = dmix->u.dmix.sum_buffer + channels * dst_ofs + chn;
dmix->u.dmix.mix_areas_24(size, dst, src, sum, dst_step, src_step, channels * sizeof(signed int));
}
} }
} }