[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