[alsa-devel] [PATCH] external plugin for adding delay to channels
This should be interesting for home theater installations, as I was personnally missing a "per channel delay configuration".
Feel free to tell me what should be modified, I am not really used to proposing a patch.
Thx
At Tue, 30 Sep 2008 22:51:23 +0200, Alex wrote:
This should be interesting for home theater installations, as I was personnally missing a "per channel delay configuration".
Feel free to tell me what should be modified, I am not really used to proposing a patch.
Thanks for the patch. Just looking quickly at it, some comments below.
diff -x libtool -x stamp-h1 -x .vimrc -x rate -x Makefile.in -x Makefile -x .deps -x configure -x config.status -x config.h -x config.log -x a52 -x '*cache*' -x '*aclocal*' -Naur alsa-plugins-1.0.17/configure.in alsa-plugins-1.0.17+delay/configure.in
Maybe it's a good chance to learn git now :)
--- alsa-plugins-1.0.17/configure.in 2008-07-14 10:57:59.000000000 +0200 +++ alsa-plugins-1.0.17+delay/configure.in 2008-09-24 10:52:23.000000000 +0200 @@ -89,6 +89,9 @@ fi
AM_CONDITIONAL(HAVE_PPH, test "$PPH" = "builtin" -o "$PPH" = "lib")
+AM_CONDITIONAL(HAVE_DELAY, test x$HAVE_DELAY = xyes)
AM_CONDITIONAL(USE_LIBSPEEX, test "$PPH" = "lib")
dnl ALSA plugin directory @@ -124,6 +127,7 @@ a52/Makefile rate-lavc/Makefile maemo/Makefile
- delay/Makefile
Try to keep the same indent.
--- alsa-plugins-1.0.17/delay/pcm_delay.c 1970-01-01 01:00:00.000000000 +0100 +++ alsa-plugins-1.0.17+delay/delay/pcm_delay.c 2008-09-30 21:57:56.000000000 +0200
(snip)
+/* Ambient temperature is 20� celsius */
Use ASCII as much as possible. If inevitably necessary, use UTF-8.
+typedef struct {
- snd_pcm_extplug_t ext;
- double *delay_ms;
- unsigned int *delay_sample;
- snd_pcm_channel_area_t *dly_areas;
- snd_pcm_uframes_t *dly_offset;
- unsigned int channels;
- unsigned int mode;
+} snd_pcm_delay_t;
Could you keep the indent level like other codes? Not mandatory, but would be better for us...
+static int snd_pcm_delay_parse_delay(snd_pcm_delay_t *pcm_delay,
snd_config_t *conf_delay,
unsigned char mode)
+{
- snd_config_iterator_t i, next;
- double *delays;
- double delay = 0.0;
- unsigned int cnt = 0;
- unsigned int channel;
- double val;
- pcm_delay->mode = mode;
- if (conf_delay) {
snd_config_for_each(i, next, conf_delay) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
if (snd_config_get_id(n, &id) < 0)
continue;
cnt++;
}
This means cnt includes comments, etc? Then the number is inaccurate (although a bigger doesn't matter much).
pcm_delay->delay_ms = delays = calloc(cnt, sizeof(double));
if (delays == NULL)
return -ENOMEM;
pcm_delay->channels = cnt;
Now you have two "channels", one in this definition and another as pcm_delay->ext.channels. As far as I see, these are used sometimes wrongly, possibly resulting in a segfault.
+static snd_pcm_sframes_t snd_pcm_delay_transfer(snd_pcm_extplug_t *ext,
const snd_pcm_channel_area_t *dst_areas,
snd_pcm_uframes_t dst_offset,
const snd_pcm_channel_area_t *src_areas,
snd_pcm_uframes_t src_offset,
snd_pcm_uframes_t size)
+{
- snd_pcm_delay_t *pcm_delay = (snd_pcm_delay_t *)ext;
- unsigned int i;
- snd_pcm_uframes_t left;
- for (i = 0; i < pcm_delay->ext.channels; i++) {
if (! pcm_delay->delay_sample[i]) {
snd_pcm_area_copy(dst_areas + i, dst_offset,
src_areas + i, src_offset,
size, pcm_delay->ext.format);
continue;
}
if (pcm_delay->delay_sample[i] <= size) {
assert(! pcm_delay->dly_offset[i]);
I'm not sure whether this condition is assured... The size in this callback isn't guaranteed to be a period size.
left = size - pcm_delay->delay_sample[i];
/* delay to dst */
snd_pcm_area_copy(dst_areas + i, dst_offset,
pcm_delay->dly_areas + i, 0,
pcm_delay->delay_sample[i], pcm_delay->ext.format);
if (left) {
/* src to dst left */
snd_pcm_area_copy(dst_areas + i, dst_offset + pcm_delay->delay_sample[i],
src_areas + i, src_offset,
left, pcm_delay->ext.format);
}
/* src left to delay */
snd_pcm_area_copy(pcm_delay->dly_areas + i, 0,
src_areas + i, src_offset + left,
pcm_delay->delay_sample[i], pcm_delay->ext.format);
continue;
}
/* usual (small) delays wont reach this part of the code */
left = pcm_delay->dly_offset[i] + size > pcm_delay->delay_sample[i]
? (pcm_delay->dly_offset[i] + size) % pcm_delay->delay_sample[i] : 0;
/* copy dly to dst */
snd_pcm_area_copy(dst_areas + i, dst_offset,
pcm_delay->dly_areas + i, pcm_delay->dly_offset[i],
size - left, pcm_delay->ext.format);
/* copy src to dly */
snd_pcm_area_copy(pcm_delay->dly_areas + i, pcm_delay->dly_offset[i],
src_areas + i, src_offset,
size - left, pcm_delay->ext.format);
if (left) {
/* copy dly to dst */
snd_pcm_area_copy(dst_areas + i, dst_offset + size - left,
pcm_delay->dly_areas + i, 0,
left, pcm_delay->ext.format);
/* copy src to dly */
snd_pcm_area_copy(pcm_delay->dly_areas + i, 0,
src_areas + i, src_offset + size - left,
left, pcm_delay->ext.format);
pcm_delay->dly_offset[i] = left;
continue;
}
pcm_delay->dly_offset[i] += size;
Hmm, the whole copy mechanism is a bit too hard. I guess this could be simplified more.
+/*
- Main entry point
- */
+SND_PCM_PLUGIN_DEFINE_FUNC(delay)
...
- snd_pcm_extplug_set_param_minmax(&pcm_delay->ext,
SND_PCM_EXTPLUG_HW_CHANNELS,
1, 6);
- snd_pcm_extplug_set_param_list(&pcm_delay->ext,
SND_PCM_EXTPLUG_HW_CHANNELS,
6, chlist);
You don't need both of them. Both do the same job.
- snd_pcm_extplug_set_param(&pcm_delay->ext, SND_PCM_EXTPLUG_HW_FORMAT,
SND_PCM_FORMAT_S16);
- snd_pcm_extplug_set_slave_param(&pcm_delay->ext, SND_PCM_EXTPLUG_HW_FORMAT,
SND_PCM_FORMAT_S16);
Any reason to restrict to S16? Just for copying samples, the sample format doesn't matter much.
thanks,
Takashi
participants (2)
-
Alex
-
Takashi Iwai