mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-01 22:58:49 -04:00
Implemented snd_pcm_rewind() for the dmix plugin
This commit is contained in:
parent
8f16428f9c
commit
70b11d614d
7 changed files with 459 additions and 28 deletions
|
|
@ -162,6 +162,10 @@ struct snd_pcm_direct {
|
||||||
mix_areas_32_t *mix_areas_32;
|
mix_areas_32_t *mix_areas_32;
|
||||||
mix_areas_24_t *mix_areas_24;
|
mix_areas_24_t *mix_areas_24;
|
||||||
mix_areas_u8_t *mix_areas_u8;
|
mix_areas_u8_t *mix_areas_u8;
|
||||||
|
mix_areas_16_t *remix_areas_16;
|
||||||
|
mix_areas_32_t *remix_areas_32;
|
||||||
|
mix_areas_24_t *remix_areas_24;
|
||||||
|
mix_areas_u8_t *remix_areas_u8;
|
||||||
} dmix;
|
} dmix;
|
||||||
struct {
|
struct {
|
||||||
} dsnoop;
|
} dsnoop;
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,70 @@ static void mix_areas(snd_pcm_direct_t *dmix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void remix_areas(snd_pcm_direct_t *dmix,
|
||||||
|
const snd_pcm_channel_area_t *src_areas,
|
||||||
|
const snd_pcm_channel_area_t *dst_areas,
|
||||||
|
snd_pcm_uframes_t src_ofs,
|
||||||
|
snd_pcm_uframes_t dst_ofs,
|
||||||
|
snd_pcm_uframes_t size)
|
||||||
|
{
|
||||||
|
unsigned int src_step, dst_step;
|
||||||
|
unsigned int chn, dchn, channels, sample_size;
|
||||||
|
mix_areas_t *do_remix_areas;
|
||||||
|
|
||||||
|
channels = dmix->channels;
|
||||||
|
switch (dmix->shmptr->s.format) {
|
||||||
|
case SND_PCM_FORMAT_S16_LE:
|
||||||
|
case SND_PCM_FORMAT_S16_BE:
|
||||||
|
sample_size = 2;
|
||||||
|
do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_16;
|
||||||
|
break;
|
||||||
|
case SND_PCM_FORMAT_S32_LE:
|
||||||
|
case SND_PCM_FORMAT_S32_BE:
|
||||||
|
sample_size = 4;
|
||||||
|
do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_32;
|
||||||
|
break;
|
||||||
|
case SND_PCM_FORMAT_S24_3LE:
|
||||||
|
sample_size = 3;
|
||||||
|
do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_24;
|
||||||
|
break;
|
||||||
|
case SND_PCM_FORMAT_U8:
|
||||||
|
sample_size = 1;
|
||||||
|
do_remix_areas = (mix_areas_t *)dmix->u.dmix.remix_areas_u8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dmix->interleaved) {
|
||||||
|
/*
|
||||||
|
* process all areas in one loop
|
||||||
|
* it optimizes the memory accesses for this case
|
||||||
|
*/
|
||||||
|
do_remix_areas(size * channels,
|
||||||
|
(unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,
|
||||||
|
(unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,
|
||||||
|
dmix->u.dmix.sum_buffer + dst_ofs * channels,
|
||||||
|
sample_size,
|
||||||
|
sample_size,
|
||||||
|
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;
|
||||||
|
do_remix_areas(size,
|
||||||
|
((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step,
|
||||||
|
((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step,
|
||||||
|
dmix->u.dmix.sum_buffer + channels * dst_ofs + chn,
|
||||||
|
dst_step,
|
||||||
|
src_step,
|
||||||
|
channels * sizeof(signed int));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if no concurrent access is allowed in the mixing routines, we need to protect
|
* if no concurrent access is allowed in the mixing routines, we need to protect
|
||||||
* the area via semaphore
|
* the area via semaphore
|
||||||
|
|
@ -234,7 +298,7 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
snd_pcm_direct_t *dmix = pcm->private_data;
|
||||||
snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
|
snd_pcm_uframes_t slave_hw_ptr, slave_appl_ptr, slave_size;
|
||||||
snd_pcm_uframes_t appl_ptr, size;
|
snd_pcm_uframes_t appl_ptr, size, transfer;
|
||||||
const snd_pcm_channel_area_t *src_areas, *dst_areas;
|
const snd_pcm_channel_area_t *src_areas, *dst_areas;
|
||||||
|
|
||||||
/* calculate the size to transfer */
|
/* calculate the size to transfer */
|
||||||
|
|
@ -247,6 +311,27 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
|
||||||
if (size >= pcm->boundary / 2)
|
if (size >= pcm->boundary / 2)
|
||||||
size = pcm->boundary - size;
|
size = pcm->boundary - size;
|
||||||
|
|
||||||
|
/* the slave_app_ptr can be far behing the slave_hw_ptr */
|
||||||
|
/* reduce mixing and errors here - just skip not catched writes */
|
||||||
|
if (dmix->slave_hw_ptr < dmix->slave_appl_ptr)
|
||||||
|
slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr;
|
||||||
|
else
|
||||||
|
slave_size = dmix->slave_appl_ptr + (dmix->slave_boundary - dmix->slave_hw_ptr);
|
||||||
|
if (slave_size > dmix->slave_buffer_size) {
|
||||||
|
transfer = dmix->slave_buffer_size - slave_size;
|
||||||
|
if (transfer > size)
|
||||||
|
transfer = size;
|
||||||
|
dmix->last_appl_ptr += transfer;
|
||||||
|
dmix->last_appl_ptr %= pcm->boundary;
|
||||||
|
dmix->slave_appl_ptr += transfer;
|
||||||
|
dmix->slave_appl_ptr %= dmix->slave_boundary;
|
||||||
|
size = dmix->appl_ptr - dmix->last_appl_ptr;
|
||||||
|
if (! size)
|
||||||
|
return;
|
||||||
|
if (size >= pcm->boundary / 2)
|
||||||
|
size = pcm->boundary - size;
|
||||||
|
}
|
||||||
|
|
||||||
/* check the available size in the slave PCM buffer */
|
/* check the available size in the slave PCM buffer */
|
||||||
slave_hw_ptr = dmix->slave_hw_ptr;
|
slave_hw_ptr = dmix->slave_hw_ptr;
|
||||||
/* don't write on the last active period - this area may be cleared
|
/* don't write on the last active period - this area may be cleared
|
||||||
|
|
@ -276,7 +361,7 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
|
||||||
dmix->slave_appl_ptr %= dmix->slave_boundary;
|
dmix->slave_appl_ptr %= dmix->slave_boundary;
|
||||||
dmix_down_sem(dmix);
|
dmix_down_sem(dmix);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
snd_pcm_uframes_t transfer = size;
|
transfer = size;
|
||||||
if (appl_ptr + transfer > pcm->buffer_size)
|
if (appl_ptr + transfer > pcm->buffer_size)
|
||||||
transfer = pcm->buffer_size - appl_ptr;
|
transfer = pcm->buffer_size - appl_ptr;
|
||||||
if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
|
if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
|
||||||
|
|
@ -564,15 +649,78 @@ static int snd_pcm_dmix_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIB
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames ATTRIBUTE_UNUSED)
|
static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
#if 0
|
snd_pcm_direct_t *dmix = pcm->private_data;
|
||||||
/* FIXME: substract samples from the mix ring buffer, too? */
|
snd_pcm_uframes_t slave_appl_ptr, slave_size;
|
||||||
|
snd_pcm_uframes_t appl_ptr, size, transfer, result;
|
||||||
|
const snd_pcm_channel_area_t *src_areas, *dst_areas;
|
||||||
|
|
||||||
|
if (dmix->state == SND_PCM_STATE_RUNNING ||
|
||||||
|
dmix->state == SND_PCM_STATE_DRAINING)
|
||||||
|
return snd_pcm_dmix_hwsync(pcm);
|
||||||
|
|
||||||
|
if (dmix->last_appl_ptr < dmix->appl_ptr)
|
||||||
|
size = dmix->appl_ptr - dmix->last_appl_ptr;
|
||||||
|
else
|
||||||
|
size = dmix->appl_ptr + (pcm->boundary - dmix->last_appl_ptr);
|
||||||
|
if (frames < size)
|
||||||
|
size = frames;
|
||||||
|
snd_pcm_mmap_appl_backward(pcm, size);
|
||||||
|
frames -= size;
|
||||||
|
if (!frames)
|
||||||
|
return size;
|
||||||
|
result = size;
|
||||||
|
|
||||||
|
if (dmix->hw_ptr < dmix->appl_ptr)
|
||||||
|
size = dmix->appl_ptr - dmix->hw_ptr;
|
||||||
|
else
|
||||||
|
size = dmix->appl_ptr + (pcm->boundary - dmix->hw_ptr);
|
||||||
|
if (size > frames)
|
||||||
|
size = frames;
|
||||||
|
if (dmix->slave_hw_ptr < dmix->slave_appl_ptr)
|
||||||
|
slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr;
|
||||||
|
else
|
||||||
|
slave_size = dmix->slave_appl_ptr + (pcm->boundary - dmix->slave_hw_ptr);
|
||||||
|
if (slave_size < size)
|
||||||
|
size = slave_size;
|
||||||
|
frames -= size;
|
||||||
|
result += size;
|
||||||
|
|
||||||
|
/* add sample areas here */
|
||||||
|
src_areas = snd_pcm_mmap_areas(pcm);
|
||||||
|
dst_areas = snd_pcm_mmap_areas(dmix->spcm);
|
||||||
|
dmix->last_appl_ptr -= size;
|
||||||
|
dmix->last_appl_ptr %= pcm->boundary;
|
||||||
|
appl_ptr = dmix->last_appl_ptr % pcm->buffer_size;
|
||||||
|
dmix->slave_appl_ptr -= size;
|
||||||
|
dmix->slave_appl_ptr %= dmix->slave_boundary;
|
||||||
|
slave_appl_ptr = dmix->slave_appl_ptr % dmix->slave_buffer_size;
|
||||||
|
dmix_down_sem(dmix);
|
||||||
|
for (;;) {
|
||||||
|
transfer = size;
|
||||||
|
if (appl_ptr + transfer > pcm->buffer_size)
|
||||||
|
transfer = pcm->buffer_size - appl_ptr;
|
||||||
|
if (slave_appl_ptr + transfer > dmix->slave_buffer_size)
|
||||||
|
transfer = dmix->slave_buffer_size - slave_appl_ptr;
|
||||||
|
remix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
|
||||||
|
size -= transfer;
|
||||||
|
if (! size)
|
||||||
|
break;
|
||||||
|
slave_appl_ptr += transfer;
|
||||||
|
slave_appl_ptr %= dmix->slave_buffer_size;
|
||||||
|
appl_ptr += transfer;
|
||||||
|
appl_ptr %= pcm->buffer_size;
|
||||||
|
}
|
||||||
|
dmix->last_appl_ptr -= frames;
|
||||||
|
dmix->last_appl_ptr %= pcm->boundary;
|
||||||
|
dmix->slave_appl_ptr -= frames;
|
||||||
|
dmix->slave_appl_ptr %= dmix->slave_boundary;
|
||||||
|
dmix_up_sem(dmix);
|
||||||
|
|
||||||
snd_pcm_mmap_appl_backward(pcm, frames);
|
snd_pcm_mmap_appl_backward(pcm, frames);
|
||||||
return frames;
|
|
||||||
#else
|
return result + frames;
|
||||||
return -EIO;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ static void mix_areas_32(unsigned int size,
|
||||||
register signed int sample, old_sample;
|
register signed int sample, old_sample;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sample = *src / 256;
|
sample = *src >> 8;
|
||||||
old_sample = *sum;
|
old_sample = *sum;
|
||||||
if (ARCH_CMPXCHG(dst, 0, 1) == 0)
|
if (ARCH_CMPXCHG(dst, 0, 1) == 0)
|
||||||
sample -= old_sample;
|
sample -= old_sample;
|
||||||
|
|
@ -159,6 +159,37 @@ static void generic_mix_areas_16_native(unsigned int size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generic_remix_areas_16_native(unsigned int size,
|
||||||
|
volatile signed short *dst,
|
||||||
|
signed short *src,
|
||||||
|
volatile signed int *sum,
|
||||||
|
size_t dst_step,
|
||||||
|
size_t src_step,
|
||||||
|
size_t sum_step)
|
||||||
|
{
|
||||||
|
register signed int sample;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
sample = *src;
|
||||||
|
if (! *dst) {
|
||||||
|
*sum = -sample;
|
||||||
|
*dst = *src;
|
||||||
|
} else {
|
||||||
|
*sum = sample = *sum - sample;
|
||||||
|
if (sample > 0x7fff)
|
||||||
|
sample = 0x7fff;
|
||||||
|
else if (sample < -0x8000)
|
||||||
|
sample = -0x8000;
|
||||||
|
*dst = sample;
|
||||||
|
}
|
||||||
|
if (!--size)
|
||||||
|
return;
|
||||||
|
src = (signed short *) ((char *)src + src_step);
|
||||||
|
dst = (signed short *) ((char *)dst + dst_step);
|
||||||
|
sum = (signed int *) ((char *)sum + sum_step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void generic_mix_areas_32_native(unsigned int size,
|
static void generic_mix_areas_32_native(unsigned int size,
|
||||||
volatile signed int *dst,
|
volatile signed int *dst,
|
||||||
signed int *src,
|
signed int *src,
|
||||||
|
|
@ -170,7 +201,7 @@ static void generic_mix_areas_32_native(unsigned int size,
|
||||||
register signed int sample;
|
register signed int sample;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sample = *src / 256;
|
sample = *src >> 8;
|
||||||
if (! *dst) {
|
if (! *dst) {
|
||||||
*sum = sample;
|
*sum = sample;
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
|
@ -193,6 +224,39 @@ static void generic_mix_areas_32_native(unsigned int size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generic_remix_areas_32_native(unsigned int size,
|
||||||
|
volatile signed int *dst,
|
||||||
|
signed int *src,
|
||||||
|
volatile signed int *sum,
|
||||||
|
size_t dst_step,
|
||||||
|
size_t src_step,
|
||||||
|
size_t sum_step)
|
||||||
|
{
|
||||||
|
register signed int sample;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
sample = *src >> 8;
|
||||||
|
if (! *dst) {
|
||||||
|
*sum = -sample;
|
||||||
|
*dst = *src;
|
||||||
|
} else {
|
||||||
|
*sum = sample = *sum - sample;
|
||||||
|
if (sample > 0x7fffff)
|
||||||
|
sample = 0x7fffffff;
|
||||||
|
else if (sample < -0x800000)
|
||||||
|
sample = -0x80000000;
|
||||||
|
else
|
||||||
|
sample *= 256;
|
||||||
|
*dst = sample;
|
||||||
|
}
|
||||||
|
if (!--size)
|
||||||
|
return;
|
||||||
|
src = (signed int *) ((char *)src + src_step);
|
||||||
|
dst = (signed int *) ((char *)dst + dst_step);
|
||||||
|
sum = (signed int *) ((char *)sum + sum_step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void generic_mix_areas_16_swap(unsigned int size,
|
static void generic_mix_areas_16_swap(unsigned int size,
|
||||||
volatile signed short *dst,
|
volatile signed short *dst,
|
||||||
signed short *src,
|
signed short *src,
|
||||||
|
|
@ -225,6 +289,37 @@ static void generic_mix_areas_16_swap(unsigned int size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generic_remix_areas_16_swap(unsigned int size,
|
||||||
|
volatile signed short *dst,
|
||||||
|
signed short *src,
|
||||||
|
volatile signed int *sum,
|
||||||
|
size_t dst_step,
|
||||||
|
size_t src_step,
|
||||||
|
size_t sum_step)
|
||||||
|
{
|
||||||
|
register signed int sample;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
sample = (signed short) bswap_16(*src);
|
||||||
|
if (! *dst) {
|
||||||
|
*sum = -sample;
|
||||||
|
*dst = *src;
|
||||||
|
} else {
|
||||||
|
*sum = sample = *sum - sample;
|
||||||
|
if (sample > 0x7fff)
|
||||||
|
sample = 0x7fff;
|
||||||
|
else if (sample < -0x8000)
|
||||||
|
sample = -0x8000;
|
||||||
|
*dst = (signed short) bswap_16((signed short) sample);
|
||||||
|
}
|
||||||
|
if (!--size)
|
||||||
|
return;
|
||||||
|
src = (signed short *) ((char *)src + src_step);
|
||||||
|
dst = (signed short *) ((char *)dst + dst_step);
|
||||||
|
sum = (signed int *) ((char *)sum + sum_step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void generic_mix_areas_32_swap(unsigned int size,
|
static void generic_mix_areas_32_swap(unsigned int size,
|
||||||
volatile signed int *dst,
|
volatile signed int *dst,
|
||||||
signed int *src,
|
signed int *src,
|
||||||
|
|
@ -236,7 +331,7 @@ static void generic_mix_areas_32_swap(unsigned int size,
|
||||||
register signed int sample;
|
register signed int sample;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sample = bswap_32(*src) / 256;
|
sample = bswap_32(*src) >> 8;
|
||||||
if (! *dst) {
|
if (! *dst) {
|
||||||
*sum = sample;
|
*sum = sample;
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
|
@ -259,6 +354,39 @@ static void generic_mix_areas_32_swap(unsigned int size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generic_remix_areas_32_swap(unsigned int size,
|
||||||
|
volatile signed int *dst,
|
||||||
|
signed int *src,
|
||||||
|
volatile signed int *sum,
|
||||||
|
size_t dst_step,
|
||||||
|
size_t src_step,
|
||||||
|
size_t sum_step)
|
||||||
|
{
|
||||||
|
register signed int sample;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
sample = bswap_32(*src) >> 8;
|
||||||
|
if (! *dst) {
|
||||||
|
*sum = -sample;
|
||||||
|
*dst = *src;
|
||||||
|
} else {
|
||||||
|
*sum = sample = *sum - sample;
|
||||||
|
if (sample > 0x7fffff)
|
||||||
|
sample = 0x7fffffff;
|
||||||
|
else if (sample < -0x800000)
|
||||||
|
sample = -0x80000000;
|
||||||
|
else
|
||||||
|
sample *= 256;
|
||||||
|
*dst = bswap_32(sample);
|
||||||
|
}
|
||||||
|
if (!--size)
|
||||||
|
return;
|
||||||
|
src = (signed int *) ((char *)src + src_step);
|
||||||
|
dst = (signed int *) ((char *)dst + dst_step);
|
||||||
|
sum = (signed int *) ((char *)sum + sum_step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* always little endian */
|
/* always little endian */
|
||||||
static void generic_mix_areas_24(unsigned int size,
|
static void generic_mix_areas_24(unsigned int size,
|
||||||
volatile unsigned char *dst,
|
volatile unsigned char *dst,
|
||||||
|
|
@ -293,6 +421,38 @@ static void generic_mix_areas_24(unsigned int size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generic_remix_areas_24(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)
|
||||||
|
{
|
||||||
|
register signed int sample;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
sample = src[0] | (src[1] << 8) | (((signed char *)src)[2] << 16);
|
||||||
|
if (!(dst[0] | dst[1] | dst[2])) {
|
||||||
|
*sum = -sample;
|
||||||
|
} else {
|
||||||
|
*sum = sample = *sum - sample;
|
||||||
|
if (sample > 0x7fffff)
|
||||||
|
sample = 0x7fffff;
|
||||||
|
else if (sample < -0x800000)
|
||||||
|
sample = -0x800000;
|
||||||
|
}
|
||||||
|
dst[0] = sample;
|
||||||
|
dst[1] = sample >> 8;
|
||||||
|
dst[2] = sample >> 16;
|
||||||
|
if (!--size)
|
||||||
|
return;
|
||||||
|
dst += dst_step;
|
||||||
|
src += src_step;
|
||||||
|
sum = (signed int *) ((char *)sum + sum_step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void generic_mix_areas_u8(unsigned int size,
|
static void generic_mix_areas_u8(unsigned int size,
|
||||||
volatile unsigned char *dst,
|
volatile unsigned char *dst,
|
||||||
unsigned char *src,
|
unsigned char *src,
|
||||||
|
|
@ -322,18 +482,52 @@ static void generic_mix_areas_u8(unsigned int size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generic_remix_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 {
|
||||||
|
*sum = sample = *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)
|
static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
|
||||||
{
|
{
|
||||||
if (snd_pcm_format_cpu_endian(dmix->shmptr->s.format)) {
|
if (snd_pcm_format_cpu_endian(dmix->shmptr->s.format)) {
|
||||||
dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_native;
|
dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_native;
|
||||||
dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_native;
|
dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_native;
|
||||||
|
dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_native;
|
||||||
|
dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_native;
|
||||||
} else {
|
} else {
|
||||||
dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_swap;
|
dmix->u.dmix.mix_areas_16 = generic_mix_areas_16_swap;
|
||||||
dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_swap;
|
dmix->u.dmix.mix_areas_32 = generic_mix_areas_32_swap;
|
||||||
|
dmix->u.dmix.remix_areas_16 = generic_remix_areas_16_swap;
|
||||||
|
dmix->u.dmix.remix_areas_32 = generic_remix_areas_32_swap;
|
||||||
}
|
}
|
||||||
dmix->u.dmix.mix_areas_24 = generic_mix_areas_24;
|
dmix->u.dmix.mix_areas_24 = generic_mix_areas_24;
|
||||||
dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
|
dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
|
||||||
|
dmix->u.dmix.remix_areas_24 = generic_remix_areas_24;
|
||||||
|
dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#define MIX_AREAS_24 mix_areas_24
|
#define MIX_AREAS_24 mix_areas_24
|
||||||
#define MIX_AREAS_24_CMOV mix_areas_24_cmov
|
#define MIX_AREAS_24_CMOV mix_areas_24_cmov
|
||||||
#define LOCK_PREFIX ""
|
#define LOCK_PREFIX ""
|
||||||
|
#define XADD "addl"
|
||||||
|
#define XSUB "subl"
|
||||||
#include "pcm_dmix_i386.h"
|
#include "pcm_dmix_i386.h"
|
||||||
#undef MIX_AREAS_16
|
#undef MIX_AREAS_16
|
||||||
#undef MIX_AREAS_16_MMX
|
#undef MIX_AREAS_16_MMX
|
||||||
|
|
@ -15,6 +17,26 @@
|
||||||
#undef MIX_AREAS_24
|
#undef MIX_AREAS_24
|
||||||
#undef MIX_AREAS_24_CMOV
|
#undef MIX_AREAS_24_CMOV
|
||||||
#undef LOCK_PREFIX
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
|
#define MIX_AREAS_16 remix_areas_16
|
||||||
|
#define MIX_AREAS_16_MMX remix_areas_16_mmx
|
||||||
|
#define MIX_AREAS_32 remix_areas_32
|
||||||
|
#define MIX_AREAS_24 remix_areas_24
|
||||||
|
#define MIX_AREAS_24_CMOV remix_areas_24_cmov
|
||||||
|
#define LOCK_PREFIX ""
|
||||||
|
#define XADD "subl"
|
||||||
|
#define XSUB "addl"
|
||||||
|
#include "pcm_dmix_i386.h"
|
||||||
|
#undef MIX_AREAS_16
|
||||||
|
#undef MIX_AREAS_16_MMX
|
||||||
|
#undef MIX_AREAS_32
|
||||||
|
#undef MIX_AREAS_24
|
||||||
|
#undef MIX_AREAS_24_CMOV
|
||||||
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
#define MIX_AREAS_16 mix_areas_16_smp
|
#define MIX_AREAS_16 mix_areas_16_smp
|
||||||
#define MIX_AREAS_16_MMX mix_areas_16_smp_mmx
|
#define MIX_AREAS_16_MMX mix_areas_16_smp_mmx
|
||||||
|
|
@ -22,6 +44,8 @@
|
||||||
#define MIX_AREAS_24 mix_areas_24_smp
|
#define MIX_AREAS_24 mix_areas_24_smp
|
||||||
#define MIX_AREAS_24_CMOV mix_areas_24_smp_cmov
|
#define MIX_AREAS_24_CMOV mix_areas_24_smp_cmov
|
||||||
#define LOCK_PREFIX "lock ; "
|
#define LOCK_PREFIX "lock ; "
|
||||||
|
#define XADD "addl"
|
||||||
|
#define XSUB "subl"
|
||||||
#include "pcm_dmix_i386.h"
|
#include "pcm_dmix_i386.h"
|
||||||
#undef MIX_AREAS_16
|
#undef MIX_AREAS_16
|
||||||
#undef MIX_AREAS_16_MMX
|
#undef MIX_AREAS_16_MMX
|
||||||
|
|
@ -29,6 +53,26 @@
|
||||||
#undef MIX_AREAS_24
|
#undef MIX_AREAS_24
|
||||||
#undef MIX_AREAS_24_CMOV
|
#undef MIX_AREAS_24_CMOV
|
||||||
#undef LOCK_PREFIX
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
|
#define MIX_AREAS_16 remix_areas_16_smp
|
||||||
|
#define MIX_AREAS_16_MMX remix_areas_16_smp_mmx
|
||||||
|
#define MIX_AREAS_32 remix_areas_32_smp
|
||||||
|
#define MIX_AREAS_24 remix_areas_24_smp
|
||||||
|
#define MIX_AREAS_24_CMOV remix_areas_24_smp_cmov
|
||||||
|
#define LOCK_PREFIX "lock ; "
|
||||||
|
#define XADD "subl"
|
||||||
|
#define XSUB "addl"
|
||||||
|
#include "pcm_dmix_i386.h"
|
||||||
|
#undef MIX_AREAS_16
|
||||||
|
#undef MIX_AREAS_16_MMX
|
||||||
|
#undef MIX_AREAS_32
|
||||||
|
#undef MIX_AREAS_24
|
||||||
|
#undef MIX_AREAS_24_CMOV
|
||||||
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
#define i386_dmix_supported_format \
|
#define i386_dmix_supported_format \
|
||||||
((1ULL << SND_PCM_FORMAT_S16_LE) |\
|
((1ULL << SND_PCM_FORMAT_S16_LE) |\
|
||||||
|
|
@ -71,13 +115,18 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
|
||||||
|
|
||||||
if (mmx) {
|
if (mmx) {
|
||||||
dmix->u.dmix.mix_areas_16 = smp > 1 ? mix_areas_16_smp_mmx : mix_areas_16_mmx;
|
dmix->u.dmix.mix_areas_16 = smp > 1 ? mix_areas_16_smp_mmx : mix_areas_16_mmx;
|
||||||
|
dmix->u.dmix.remix_areas_16 = smp > 1 ? remix_areas_16_smp_mmx : remix_areas_16_mmx;
|
||||||
} else {
|
} else {
|
||||||
dmix->u.dmix.mix_areas_16 = smp > 1 ? mix_areas_16_smp : mix_areas_16;
|
dmix->u.dmix.mix_areas_16 = smp > 1 ? mix_areas_16_smp : mix_areas_16;
|
||||||
|
dmix->u.dmix.remix_areas_16 = smp > 1 ? remix_areas_16_smp : remix_areas_16;
|
||||||
}
|
}
|
||||||
dmix->u.dmix.mix_areas_32 = smp > 1 ? mix_areas_32_smp : mix_areas_32;
|
dmix->u.dmix.mix_areas_32 = smp > 1 ? mix_areas_32_smp : mix_areas_32;
|
||||||
|
dmix->u.dmix.remix_areas_32 = smp > 1 ? remix_areas_32_smp : remix_areas_32;
|
||||||
if (cmov) {
|
if (cmov) {
|
||||||
dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp_cmov : mix_areas_24_cmov;
|
dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp_cmov : mix_areas_24_cmov;
|
||||||
|
dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp_cmov : remix_areas_24_cmov;
|
||||||
} else {
|
} else {
|
||||||
dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp: mix_areas_24;
|
dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp: mix_areas_24;
|
||||||
|
dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp: remix_areas_24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,9 @@ static void MIX_AREAS_16(unsigned int size,
|
||||||
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n"
|
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n"
|
||||||
"\tmovswl (%%esi), %%ecx\n"
|
"\tmovswl (%%esi), %%ecx\n"
|
||||||
"\tjnz 3f\n"
|
"\tjnz 3f\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"3:"
|
"3:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%ebx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
@ -202,9 +202,9 @@ static void MIX_AREAS_16_MMX(unsigned int size,
|
||||||
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n"
|
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n"
|
||||||
"\tmovswl (%%esi), %%ecx\n"
|
"\tmovswl (%%esi), %%ecx\n"
|
||||||
"\tjnz 3f\n"
|
"\tjnz 3f\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"3:"
|
"3:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%ebx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
@ -291,14 +291,14 @@ static void MIX_AREAS_32(unsigned int size,
|
||||||
"\tmovl (%%esi), %%ecx\n"
|
"\tmovl (%%esi), %%ecx\n"
|
||||||
/* sample >>= 8 */
|
/* sample >>= 8 */
|
||||||
"\tsarl $8, %%ecx\n"
|
"\tsarl $8, %%ecx\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"\tjmp 21f\n"
|
"\tjmp 21f\n"
|
||||||
"2:"
|
"2:"
|
||||||
"\tmovl (%%esi), %%ecx\n"
|
"\tmovl (%%esi), %%ecx\n"
|
||||||
/* sample >>= 8 */
|
/* sample >>= 8 */
|
||||||
"\tsarl $8, %%ecx\n"
|
"\tsarl $8, %%ecx\n"
|
||||||
"21:"
|
"21:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%ebx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
@ -403,9 +403,9 @@ static void MIX_AREAS_24(unsigned int size,
|
||||||
"\t" LOCK_PREFIX "btsl $0, (%%edi)\n"
|
"\t" LOCK_PREFIX "btsl $0, (%%edi)\n"
|
||||||
"\tleal (%%ecx,%%eax,1), %%ecx\n"
|
"\tleal (%%ecx,%%eax,1), %%ecx\n"
|
||||||
"\tjc 2f\n"
|
"\tjc 2f\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"2:"
|
"2:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%ebx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
@ -508,9 +508,9 @@ static void MIX_AREAS_24_CMOV(unsigned int size,
|
||||||
"\t" LOCK_PREFIX "btsl $0, (%%edi)\n"
|
"\t" LOCK_PREFIX "btsl $0, (%%edi)\n"
|
||||||
"\tleal (%%ecx,%%eax,1), %%ecx\n"
|
"\tleal (%%ecx,%%eax,1), %%ecx\n"
|
||||||
"\tjc 2f\n"
|
"\tjc 2f\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"2:"
|
"2:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%ebx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
|
||||||
|
|
@ -6,21 +6,57 @@
|
||||||
#define MIX_AREAS_32 mix_areas_32
|
#define MIX_AREAS_32 mix_areas_32
|
||||||
#define MIX_AREAS_24 mix_areas_24
|
#define MIX_AREAS_24 mix_areas_24
|
||||||
#define LOCK_PREFIX ""
|
#define LOCK_PREFIX ""
|
||||||
|
#define XADD "addl"
|
||||||
|
#define XSUB "subl"
|
||||||
#include "pcm_dmix_x86_64.h"
|
#include "pcm_dmix_x86_64.h"
|
||||||
#undef MIX_AREAS_16
|
#undef MIX_AREAS_16
|
||||||
#undef MIX_AREAS_32
|
#undef MIX_AREAS_32
|
||||||
#undef MIX_AREAS_24
|
#undef MIX_AREAS_24
|
||||||
#undef LOCK_PREFIX
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
|
#define MIX_AREAS_16 remix_areas_16
|
||||||
|
#define MIX_AREAS_32 remix_areas_32
|
||||||
|
#define MIX_AREAS_24 remix_areas_24
|
||||||
|
#define LOCK_PREFIX ""
|
||||||
|
#define XADD "subl"
|
||||||
|
#define XSUB "addl"
|
||||||
|
#include "pcm_dmix_x86_64.h"
|
||||||
|
#undef MIX_AREAS_16
|
||||||
|
#undef MIX_AREAS_32
|
||||||
|
#undef MIX_AREAS_24
|
||||||
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
#define MIX_AREAS_16 mix_areas_16_smp
|
#define MIX_AREAS_16 mix_areas_16_smp
|
||||||
#define MIX_AREAS_32 mix_areas_32_smp
|
#define MIX_AREAS_32 mix_areas_32_smp
|
||||||
#define MIX_AREAS_24 mix_areas_24_smp
|
#define MIX_AREAS_24 mix_areas_24_smp
|
||||||
#define LOCK_PREFIX "lock ; "
|
#define LOCK_PREFIX "lock ; "
|
||||||
|
#define XADD "addl"
|
||||||
|
#define XSUB "subl"
|
||||||
#include "pcm_dmix_x86_64.h"
|
#include "pcm_dmix_x86_64.h"
|
||||||
#undef MIX_AREAS_16
|
#undef MIX_AREAS_16
|
||||||
#undef MIX_AREAS_32
|
#undef MIX_AREAS_32
|
||||||
#undef MIX_AREAS_24
|
#undef MIX_AREAS_24
|
||||||
#undef LOCK_PREFIX
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
|
#define MIX_AREAS_16 remix_areas_16_smp
|
||||||
|
#define MIX_AREAS_32 remix_areas_32_smp
|
||||||
|
#define MIX_AREAS_24 remix_areas_24_smp
|
||||||
|
#define LOCK_PREFIX "lock ; "
|
||||||
|
#define XADD "subl"
|
||||||
|
#define XSUB "addl"
|
||||||
|
#include "pcm_dmix_x86_64.h"
|
||||||
|
#undef MIX_AREAS_16
|
||||||
|
#undef MIX_AREAS_32
|
||||||
|
#undef MIX_AREAS_24
|
||||||
|
#undef LOCK_PREFIX
|
||||||
|
#undef XADD
|
||||||
|
#undef XSUB
|
||||||
|
|
||||||
#define x86_64_dmix_supported_format \
|
#define x86_64_dmix_supported_format \
|
||||||
((1ULL << SND_PCM_FORMAT_S16_LE) |\
|
((1ULL << SND_PCM_FORMAT_S16_LE) |\
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ static void MIX_AREAS_16(unsigned int size,
|
||||||
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%rdi)\n"
|
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%rdi)\n"
|
||||||
"\tmovswl (%%rsi), %%ecx\n"
|
"\tmovswl (%%rsi), %%ecx\n"
|
||||||
"\tjnz 2f\n"
|
"\tjnz 2f\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"2:"
|
"2:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%rbx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%rbx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
@ -176,14 +176,14 @@ static void MIX_AREAS_32(unsigned int size,
|
||||||
"\tmovl (%%rsi), %%ecx\n"
|
"\tmovl (%%rsi), %%ecx\n"
|
||||||
/* sample >>= 8 */
|
/* sample >>= 8 */
|
||||||
"\tsarl $8, %%ecx\n"
|
"\tsarl $8, %%ecx\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"\tjmp 21f\n"
|
"\tjmp 21f\n"
|
||||||
"2:"
|
"2:"
|
||||||
"\tmovl (%%rsi), %%ecx\n"
|
"\tmovl (%%rsi), %%ecx\n"
|
||||||
/* sample >>= 8 */
|
/* sample >>= 8 */
|
||||||
"\tsarl $8, %%ecx\n"
|
"\tsarl $8, %%ecx\n"
|
||||||
"21:"
|
"21:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%rbx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%rbx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
@ -290,9 +290,9 @@ static void MIX_AREAS_24(unsigned int size,
|
||||||
"\t" LOCK_PREFIX "btsl $0, (%%rdi)\n"
|
"\t" LOCK_PREFIX "btsl $0, (%%rdi)\n"
|
||||||
"\t.byte 0x67, 0x8d, 0x0c, 0x01\n"
|
"\t.byte 0x67, 0x8d, 0x0c, 0x01\n"
|
||||||
"\tjc 2f\n"
|
"\tjc 2f\n"
|
||||||
"\tsubl %%edx, %%ecx\n"
|
"\t" XSUB " %%edx, %%ecx\n"
|
||||||
"2:"
|
"2:"
|
||||||
"\t" LOCK_PREFIX "addl %%ecx, (%%rbx)\n"
|
"\t" LOCK_PREFIX XADD " %%ecx, (%%rbx)\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do {
|
* do {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue