Next plugin fixes...

This commit is contained in:
Jaroslav Kysela 1999-12-10 00:13:46 +00:00
parent 7da5d03952
commit d0fc70a1c7
2 changed files with 94 additions and 44 deletions

View file

@ -42,6 +42,7 @@ struct rate_private_data {
int dst_voices; int dst_voices;
int src_rate; int src_rate;
int dst_rate; int dst_rate;
int sample_size;
unsigned int pitch; unsigned int pitch;
unsigned int pos; unsigned int pos;
signed short last_S1[MAX_VOICES]; signed short last_S1[MAX_VOICES];
@ -50,7 +51,7 @@ struct rate_private_data {
}; };
static void mix(struct rate_private_data *data, int voices, static void mix16(struct rate_private_data *data, int voices,
signed short *src_ptr, int src_size, signed short *src_ptr, int src_size,
signed short *dst_ptr, int dst_size) signed short *dst_ptr, int dst_size)
{ {
@ -79,6 +80,7 @@ static void mix(struct rate_private_data *data, int voices,
src += (pos >> SHIFT) * voices; src += (pos >> SHIFT) * voices;
pos &= MASK; pos &= MASK;
S1 = S2; S1 = S2;
if ((src - src_ptr) < src_size * voices)
S2 = *src; S2 = *src;
} }
val = S1 + ((S2 - S1) * (signed int)pos) / BITS; val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
@ -92,8 +94,55 @@ static void mix(struct rate_private_data *data, int voices,
} }
data->last_S1[voice] = S1; data->last_S1[voice] = S1;
data->last_S2[voice] = S2; data->last_S2[voice] = S2;
}
data->pos = pos; data->pos = pos;
}
}
static void mix8(struct rate_private_data *data, int voices,
unsigned char *src_ptr, int src_size,
unsigned char *dst_ptr, int dst_size)
{
unsigned int pos;
signed int val;
signed short S1, S2;
int voice;
unsigned char *src, *dst;
int size;
for (voice = 0; voice < voices; ++voice) {
pos = data->pos;
S1 = data->last_S1[voice];
S2 = data->last_S2[voice];
src = src_ptr + voice;
dst = dst_ptr + voice;
size = dst_size;
if (pos >> SHIFT) {
src += ((pos >> SHIFT) - 1) * voices;
pos &= MASK;
S1 = S2;
S2 = (*src << 8) ^ 0x8000;
}
while (size-- > 0) {
if (pos >> SHIFT) {
src += (pos >> SHIFT) * voices;
pos &= MASK;
S1 = S2;
if ((src - src_ptr) < src_size * voices)
S2 = (*src << 8) ^ 0x8000;
}
val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
if (val < -32768)
val = -32768;
else if (val > 32767)
val = 32767;
*dst = (val >> 8) ^ 0x0080;
dst += voices;
pos += data->pitch;
}
data->last_S1[voice] = S1;
data->last_S2[voice] = S2;
data->pos = pos;
}
} }
static ssize_t rate_transfer(snd_pcm_plugin_t *plugin, static ssize_t rate_transfer(snd_pcm_plugin_t *plugin,
@ -110,10 +159,16 @@ static ssize_t rate_transfer(snd_pcm_plugin_t *plugin,
data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin); data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin);
if (data == NULL) if (data == NULL)
return -EINVAL; return -EINVAL;
mix(data, data->src_voices, if (data->sample_size == 2) {
mix16(data, data->src_voices,
(signed short *)src_ptr, src_size / (data->src_voices * 2), (signed short *)src_ptr, src_size / (data->src_voices * 2),
(signed short *)dst_ptr, dst_size / (data->dst_voices * 2)); (signed short *)dst_ptr, dst_size / (data->dst_voices * 2));
return dst_size / (2 * data->src_voices) * (2 * data->src_voices); } else {
mix8(data, data->src_voices,
src_ptr, src_size / data->src_voices,
dst_ptr, dst_size / data->dst_voices);
}
return dst_size / (data->sample_size * data->src_voices) * (data->sample_size * data->src_voices);
} }
static int rate_action(snd_pcm_plugin_t *plugin, snd_pcm_plugin_action_t action) static int rate_action(snd_pcm_plugin_t *plugin, snd_pcm_plugin_action_t action)
@ -147,14 +202,16 @@ static ssize_t rate_src_size(snd_pcm_plugin_t *plugin, size_t size)
return -EINVAL; return -EINVAL;
data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin); data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin);
res = (((size * data->pitch) + (BITS/2)) >> SHIFT); res = (((size * data->pitch) + (BITS/2)) >> SHIFT);
res = res / (data->src_voices*2) * (data->src_voices*2); res = res / (data->src_voices*data->sample_size) * (data->src_voices*data->sample_size);
/* Why this? */ if (data->old_src_size > 0) {
if (size < 128*1024) { if ((data->old_src_size % size) == 0) {
if (data->old_src_size == size) return (data->old_dst_size * data->old_src_size) / size;
return data->old_dst_size; } else if ((size % data->old_src_size) == 0) {
return (data->old_dst_size * size) / data->old_src_size;
}
}
data->old_src_size = size; data->old_src_size = size;
data->old_dst_size = res; data->old_dst_size = res;
}
return res; return res;
} }
@ -167,14 +224,16 @@ static ssize_t rate_dst_size(snd_pcm_plugin_t *plugin, size_t size)
return -EINVAL; return -EINVAL;
data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin); data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin);
res = (((size << SHIFT) + (data->pitch / 2)) / data->pitch); res = (((size << SHIFT) + (data->pitch / 2)) / data->pitch);
res = res / (data->dst_voices*2) * (data->dst_voices*2); res = res / (data->dst_voices*data->sample_size) * (data->dst_voices*data->sample_size);
/* Why this? */ if (data->old_dst_size > 0) {
if (size < 128*1024) { if ((data->old_dst_size % size) == 0) {
if (data->old_dst_size == size) return (data->old_src_size * data->old_dst_size) / size;
return data->old_src_size; } else if ((size % data->old_dst_size) == 0) {
return (data->old_src_size * size) / data->old_dst_size;
}
}
data->old_dst_size = size; data->old_dst_size = size;
data->old_src_size = res; data->old_src_size = res;
}
return res; return res;
} }
@ -201,8 +260,8 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format,
if (dst_format->voices < 1 || dst_format->voices > MAX_VOICES) if (dst_format->voices < 1 || dst_format->voices > MAX_VOICES)
return -EINVAL; return -EINVAL;
if (src_format->format != SND_PCM_SFMT_S16_LE || if (src_format->format != SND_PCM_SFMT_S16_LE &&
dst_format->format != SND_PCM_SFMT_S16_LE) src_format->format != SND_PCM_SFMT_U8)
return -EINVAL; return -EINVAL;
if (src_format->rate == dst_format->rate) if (src_format->rate == dst_format->rate)
return -EINVAL; return -EINVAL;
@ -211,6 +270,7 @@ int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format,
if (plugin == NULL) if (plugin == NULL)
return -ENOMEM; return -ENOMEM;
data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin); data = (struct rate_private_data *)snd_pcm_plugin_extra_data(plugin);
data->sample_size = src_format->format == SND_PCM_SFMT_S16_LE ? 2 : 1;
data->src_voices = src_format->voices; data->src_voices = src_format->voices;
data->dst_voices = dst_format->voices; data->dst_voices = dst_format->voices;
data->src_rate = src_format->rate; data->src_rate = src_format->rate;

View file

@ -36,8 +36,7 @@ struct voices_private_data {
int src_voices; int src_voices;
int dst_voices; int dst_voices;
int width; /* in bites */ int width; /* in bites */
int flg_merge: 1, int flg_signed: 1;
flg_signed: 1;
}; };
static void divide_8bit(char *src_ptr, char *dst_ptr, int size) static void divide_8bit(char *src_ptr, char *dst_ptr, int size)
@ -60,8 +59,9 @@ static void merge_8bit_unsigned(unsigned char *src_ptr,
unsigned char *dst_ptr, unsigned char *dst_ptr,
int size) int size)
{ {
printf("unsigned!!\n");
while (size-- > 0) { while (size-- > 0) {
*dst_ptr++ = (*src_ptr + *(src_ptr + 1)) / 2; *dst_ptr++ = ((int)*src_ptr + (int)*(src_ptr + 1)) / 2;
src_ptr += 2; src_ptr += 2;
} }
} }
@ -71,7 +71,7 @@ static void merge_8bit_signed(signed char *src_ptr,
int size) int size)
{ {
while (size-- > 0) { while (size-- > 0) {
*dst_ptr++ = (*src_ptr + *(src_ptr + 1)) / 2; *dst_ptr++ = ((int)*src_ptr + (int)*(src_ptr + 1)) / 2;
src_ptr += 2; src_ptr += 2;
} }
} }
@ -81,7 +81,7 @@ static void merge_16bit_unsigned(unsigned short *src_ptr,
int size) int size)
{ {
while (size-- > 0) { while (size-- > 0) {
*dst_ptr++ = (*src_ptr + *(src_ptr + 1)) / 2; *dst_ptr++ = ((int)*src_ptr + (int)*(src_ptr + 1)) / 2;
src_ptr += 2; src_ptr += 2;
} }
} }
@ -91,7 +91,7 @@ static void merge_16bit_signed(signed short *src_ptr,
int size) int size)
{ {
while (size-- > 0) { while (size-- > 0) {
*dst_ptr++ = (*src_ptr + *(src_ptr + 1)) / 2; *dst_ptr++ = ((int)*src_ptr + (int)*(src_ptr + 1)) / 2;
src_ptr += 2; src_ptr += 2;
} }
} }
@ -118,10 +118,8 @@ static ssize_t voices_transfer(snd_pcm_plugin_t *plugin,
} else { } else {
merge_8bit_unsigned(src_ptr, dst_ptr, src_size / 2); merge_8bit_unsigned(src_ptr, dst_ptr, src_size / 2);
} }
return (src_size * data->src_voices) / data->dst_voices;
} else { } else {
divide_8bit(src_ptr, dst_ptr, src_size); divide_8bit(src_ptr, dst_ptr, src_size);
return (src_size * data->dst_voices) / data->src_voices;
} }
break; break;
case 16: case 16:
@ -131,15 +129,14 @@ static ssize_t voices_transfer(snd_pcm_plugin_t *plugin,
} else { } else {
merge_16bit_unsigned((short *)src_ptr, (short *)dst_ptr, src_size / 4); merge_16bit_unsigned((short *)src_ptr, (short *)dst_ptr, src_size / 4);
} }
return (src_size * data->src_voices) / data->dst_voices;
} else { } else {
divide_16bit((short *)src_ptr, (short *)dst_ptr, src_size / 2); divide_16bit((short *)src_ptr, (short *)dst_ptr, src_size / 2);
return (src_size * data->dst_voices) / data->src_voices;
} }
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
return (src_size * data->dst_voices) / data->src_voices;
} }
static ssize_t voices_src_size(snd_pcm_plugin_t *plugin, size_t size) static ssize_t voices_src_size(snd_pcm_plugin_t *plugin, size_t size)
@ -149,10 +146,7 @@ static ssize_t voices_src_size(snd_pcm_plugin_t *plugin, size_t size)
if (!plugin || size <= 0) if (!plugin || size <= 0)
return -EINVAL; return -EINVAL;
data = (struct voices_private_data *)snd_pcm_plugin_extra_data(plugin); data = (struct voices_private_data *)snd_pcm_plugin_extra_data(plugin);
if (data->src_voices < data->dst_voices)
return (size * data->src_voices) / data->dst_voices; return (size * data->src_voices) / data->dst_voices;
else
return (size * data->dst_voices) / data->src_voices;
} }
static ssize_t voices_dst_size(snd_pcm_plugin_t *plugin, size_t size) static ssize_t voices_dst_size(snd_pcm_plugin_t *plugin, size_t size)
@ -162,9 +156,6 @@ static ssize_t voices_dst_size(snd_pcm_plugin_t *plugin, size_t size)
if (!plugin || size <= 0) if (!plugin || size <= 0)
return -EINVAL; return -EINVAL;
data = (struct voices_private_data *)snd_pcm_plugin_extra_data(plugin); data = (struct voices_private_data *)snd_pcm_plugin_extra_data(plugin);
if (data->src_voices > data->dst_voices)
return (size * data->src_voices) / data->dst_voices;
else
return (size * data->dst_voices) / data->src_voices; return (size * data->dst_voices) / data->src_voices;
} }
@ -204,7 +195,6 @@ int snd_pcm_plugin_build_voices(snd_pcm_format_t *src_format,
data->src_voices = src_format->voices; data->src_voices = src_format->voices;
data->dst_voices = dst_format->voices; data->dst_voices = dst_format->voices;
data->width = snd_pcm_format_width(src_format->format); data->width = snd_pcm_format_width(src_format->format);
data->flg_merge = src_format->voices > dst_format->voices;
data->flg_signed = snd_pcm_format_signed(src_format->format); data->flg_signed = snd_pcm_format_signed(src_format->format);
plugin->transfer = voices_transfer; plugin->transfer = voices_transfer;
plugin->src_size = voices_src_size; plugin->src_size = voices_src_size;