* Click after draining @ 2004-09-21 20:13 Giuliano Pochini 2004-10-07 18:58 ` Giuliano Pochini 0 siblings, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-09-21 20:13 UTC (permalink / raw) To: Alsa-devel With both the powermac driver and my echoaudio driver, playback ends with a "click". With properly choosen buffer/period/file sizes I can make the card play almost a whole period of old data before the substream is actually stopped. It seems that periods after the last one are not silenced, but I'm not having luck at findind the cause. This is not a recent problem. For example, I made a test sound that is a pure tone with a quick fade to silence at the end: -rw-rw-r-- 1 Giu Giu 606884 set 19 18:56 t2.wav I played it with: "aplay -B1486077 -F600000 -v t2.wav" because it's slow enough I can follow debug messages on the screen. I got this trace from the irq handler (printed just before calling snd_pcm_period_elapsed()): pcm_trigger start irq per=1 state=3 bytes=105984, t=1095614506322223 irq per=2 state=3 bytes=211840, t=1095614506921131 irq per=0 state=3 bytes=262272, t=1095614507206088 irq per=1 state=3 bytes=368128, t=1095614507804997 irq per=2 state=3 bytes=473984, t=1095614508403906 irq per=0 state=5 bytes=524416, t=1095614508688863 irq per=1 state=5 bytes=630272, t=1095614509287772 *** irq per=2 state=5 bytes=736128, t=1095614509886681 pcm_trigger stop per is the period, state is the runtime state (3=running, 5=draining), bytes are the number of bytes the DSP read from memory, t is the time_t in useconds. The line marked with "***" is the period that should be silent (it's past the end of the file) but still contains old data. Also I don't understand why it didn't stop the card at that point. I also looked for this problem on a PC with an intel8x0 chip, but it worked fine. Any hint to debug this issue is VERY welcome because I'm stuck. -- Giuliano. ------------------------------------------------------- This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM. Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-09-21 20:13 Click after draining Giuliano Pochini @ 2004-10-07 18:58 ` Giuliano Pochini 2004-10-08 15:34 ` Takashi Iwai 0 siblings, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-10-07 18:58 UTC (permalink / raw) To: alsa-devel On Tue, 21 Sep 2004 22:13:18 +0200 Giuliano Pochini <pochini@shiny.it> wrote: > With both the powermac driver and my echoaudio driver, playback ends with a > "click". With properly choosen buffer/period/file sizes I can make the card > play almost a whole period of old data before the substream is actually > stopped. It seems that periods after the last one are not silenced, but I'm > not having luck at findind the cause. This is not a recent problem. > [...] I reply myself to add that I asked about this issue at one of the betatesters and he can hear the click also. It's not a mac-only problem... Any ideas ? -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-07 18:58 ` Giuliano Pochini @ 2004-10-08 15:34 ` Takashi Iwai 2004-10-08 16:07 ` Takashi Iwai 0 siblings, 1 reply; 19+ messages in thread From: Takashi Iwai @ 2004-10-08 15:34 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel [-- Attachment #1: Type: text/plain, Size: 858 bytes --] At Thu, 7 Oct 2004 20:58:01 +0200, Giuliano Pochini wrote: > > On Tue, 21 Sep 2004 22:13:18 +0200 > Giuliano Pochini <pochini@shiny.it> wrote: > > > With both the powermac driver and my echoaudio driver, playback ends with a > > "click". With properly choosen buffer/period/file sizes I can make the card > > play almost a whole period of old data before the substream is actually > > stopped. It seems that periods after the last one are not silenced, but I'm > > not having luck at findind the cause. This is not a recent problem. > > [...] > > I reply myself to add that I asked about this issue at one of the > betatesters and he can hear the click also. It's not a mac-only problem... > Any ideas ? ALSA seems not putting silence properly unless silence_size > 0. How about the attached patch? (it's an untested and quick fix, as usual :) Takashi [-- Attachment #2: Type: text/plain, Size: 4862 bytes --] Index: alsa-kernel/include/pcm.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/pcm.h,v retrieving revision 1.50 diff -u -r1.50 pcm.h --- alsa-kernel/include/pcm.h 24 Sep 2004 13:55:55 -0000 1.50 +++ alsa-kernel/include/pcm.h 8 Oct 2004 15:15:07 -0000 @@ -875,6 +875,7 @@ int snd_pcm_playback_xrun_asap(snd_pcm_substream_t *substream); int snd_pcm_capture_xrun_asap(snd_pcm_substream_t *substream); void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr); +int snd_pcm_lib_fill_silence(snd_pcm_substream_t *substream, unsigned int ofs, snd_pcm_uframes_t frames); int snd_pcm_playback_ready(snd_pcm_substream_t *substream); int snd_pcm_capture_ready(snd_pcm_substream_t *substream); long snd_pcm_playback_ready_jiffies(snd_pcm_substream_t *substream); Index: alsa-kernel/core/pcm_lib.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_lib.c,v retrieving revision 1.57 diff -u -r1.57 pcm_lib.c --- alsa-kernel/core/pcm_lib.c 24 Sep 2004 13:55:54 -0000 1.57 +++ alsa-kernel/core/pcm_lib.c 8 Oct 2004 15:33:31 -0000 @@ -95,32 +95,10 @@ ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size; while (frames > 0) { transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || - runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { - if (substream->ops->silence) { - int err; - err = substream->ops->silence(substream, -1, ofs, transfer); - snd_assert(err >= 0, ); - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); - } - } else { - unsigned int c; - unsigned int channels = runtime->channels; - if (substream->ops->silence) { - for (c = 0; c < channels; ++c) { - int err; - err = substream->ops->silence(substream, c, ofs, transfer); - snd_assert(err >= 0, ); - } - } else { - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); - } - } + + if (snd_pcm_lib_fill_silence(substream, ofs, transfer) < 0) { + snd_printk(KERN_ERR "fill_silence error\n"); + break; } runtime->silence_filled += transfer; frames -= transfer; @@ -128,6 +106,42 @@ } } +int snd_pcm_lib_fill_silence(snd_pcm_substream_t *substream, unsigned int ofs, snd_pcm_uframes_t frames) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + int c, channels = runtime->channels; + char *hwbuf; + size_t dma_csize; + + if (substream->ops->silence) { + int err = 0; + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) + err = substream->ops->silence(substream, -1, ofs, frames); + else { + for (c = 0; c < channels; c++) { + if ((err = substream->ops->silence(substream, c, ofs, frames)) < 0) + break; + } + } + return err; + } + + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { + hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); + snd_pcm_format_set_silence(runtime->format, hwbuf, frames * channels); + } else { + dma_csize = runtime->dma_bytes / channels; + hwbuf = runtime->dma_area + samples_to_bytes(runtime, ofs); + for (c = 0; c < channels; c++) { + snd_pcm_format_set_silence(runtime->format, hwbuf, frames); + hwbuf += dma_csize; + } + } + return 0; +} + static void xrun(snd_pcm_substream_t *substream) { snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); Index: alsa-kernel/core/pcm_native.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_native.c,v retrieving revision 1.84 diff -u -r1.84 pcm_native.c --- alsa-kernel/core/pcm_native.c 24 Sep 2004 13:55:55 -0000 1.84 +++ alsa-kernel/core/pcm_native.c 8 Oct 2004 15:26:41 -0000 @@ -1296,7 +1296,18 @@ runtime->status->state = SNDRV_PCM_STATE_DRAINING; break; default: - break; + return 0; /* do nothing */ + } + if (! runtime->silence_size) { + /* fill silence until the priod end */ + snd_pcm_uframes_t period_end = runtime->hw_ptr_interrupt + runtime->period_size; + snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; + snd_pcm_sframes_t delta; + delta = (snd_pcm_sframes_t)(period_end - appl_ptr); + if (delta > 0) + snd_pcm_lib_fill_silence(substream, + appl_ptr % runtime->buffer_size, + delta); } } else { /* stop running stream */ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-08 15:34 ` Takashi Iwai @ 2004-10-08 16:07 ` Takashi Iwai 2004-10-08 20:26 ` Giuliano Pochini 2004-10-16 19:31 ` Giuliano Pochini 0 siblings, 2 replies; 19+ messages in thread From: Takashi Iwai @ 2004-10-08 16:07 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel [-- Attachment #1: Type: text/plain, Size: 998 bytes --] At Fri, 08 Oct 2004 17:34:45 +0200, I wrote: > > At Thu, 7 Oct 2004 20:58:01 +0200, > Giuliano Pochini wrote: > > > > On Tue, 21 Sep 2004 22:13:18 +0200 > > Giuliano Pochini <pochini@shiny.it> wrote: > > > > > With both the powermac driver and my echoaudio driver, playback ends with a > > > "click". With properly choosen buffer/period/file sizes I can make the card > > > play almost a whole period of old data before the substream is actually > > > stopped. It seems that periods after the last one are not silenced, but I'm > > > not having luck at findind the cause. This is not a recent problem. > > > [...] > > > > I reply myself to add that I asked about this issue at one of the > > betatesters and he can hear the click also. It's not a mac-only problem... > > Any ideas ? > > ALSA seems not putting silence properly unless silence_size > 0. > How about the attached patch? > (it's an untested and quick fix, as usual :) And broken, as usual :) The corrected on is below. Takashi [-- Attachment #2: Type: text/plain, Size: 4778 bytes --] Index: alsa-kernel/include/pcm.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/pcm.h,v retrieving revision 1.50 diff -u -r1.50 pcm.h --- alsa-kernel/include/pcm.h 24 Sep 2004 13:55:55 -0000 1.50 +++ alsa-kernel/include/pcm.h 8 Oct 2004 15:15:07 -0000 @@ -875,6 +875,7 @@ int snd_pcm_playback_xrun_asap(snd_pcm_substream_t *substream); int snd_pcm_capture_xrun_asap(snd_pcm_substream_t *substream); void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr); +int snd_pcm_lib_fill_silence(snd_pcm_substream_t *substream, unsigned int ofs, snd_pcm_uframes_t frames); int snd_pcm_playback_ready(snd_pcm_substream_t *substream); int snd_pcm_capture_ready(snd_pcm_substream_t *substream); long snd_pcm_playback_ready_jiffies(snd_pcm_substream_t *substream); Index: alsa-kernel/core/pcm_lib.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_lib.c,v retrieving revision 1.57 diff -u -r1.57 pcm_lib.c --- alsa-kernel/core/pcm_lib.c 24 Sep 2004 13:55:54 -0000 1.57 +++ alsa-kernel/core/pcm_lib.c 8 Oct 2004 15:33:31 -0000 @@ -95,32 +95,10 @@ ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size; while (frames > 0) { transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || - runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { - if (substream->ops->silence) { - int err; - err = substream->ops->silence(substream, -1, ofs, transfer); - snd_assert(err >= 0, ); - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); - } - } else { - unsigned int c; - unsigned int channels = runtime->channels; - if (substream->ops->silence) { - for (c = 0; c < channels; ++c) { - int err; - err = substream->ops->silence(substream, c, ofs, transfer); - snd_assert(err >= 0, ); - } - } else { - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); - } - } + + if (snd_pcm_lib_fill_silence(substream, ofs, transfer) < 0) { + snd_printk(KERN_ERR "fill_silence error\n"); + break; } runtime->silence_filled += transfer; frames -= transfer; @@ -128,6 +106,42 @@ } } +int snd_pcm_lib_fill_silence(snd_pcm_substream_t *substream, unsigned int ofs, snd_pcm_uframes_t frames) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + int c, channels = runtime->channels; + char *hwbuf; + size_t dma_csize; + + if (substream->ops->silence) { + int err = 0; + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) + err = substream->ops->silence(substream, -1, ofs, frames); + else { + for (c = 0; c < channels; c++) { + if ((err = substream->ops->silence(substream, c, ofs, frames)) < 0) + break; + } + } + return err; + } + + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { + hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); + snd_pcm_format_set_silence(runtime->format, hwbuf, frames * channels); + } else { + dma_csize = runtime->dma_bytes / channels; + hwbuf = runtime->dma_area + samples_to_bytes(runtime, ofs); + for (c = 0; c < channels; c++) { + snd_pcm_format_set_silence(runtime->format, hwbuf, frames); + hwbuf += dma_csize; + } + } + return 0; +} + static void xrun(snd_pcm_substream_t *substream) { snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); Index: alsa-kernel/core/pcm_native.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_native.c,v retrieving revision 1.84 diff -u -r1.84 pcm_native.c --- alsa-kernel/core/pcm_native.c 24 Sep 2004 13:55:55 -0000 1.84 +++ alsa-kernel/core/pcm_native.c 8 Oct 2004 16:06:05 -0000 @@ -1296,7 +1296,16 @@ runtime->status->state = SNDRV_PCM_STATE_DRAINING; break; default: - break; + return 0; /* do nothing */ + } + if (! runtime->silence_size) { + /* fill silence until the priod end */ + snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; + snd_pcm_uframes_t delta = appl_ptr % runtime->period_size; + if (delta > 0) + snd_pcm_lib_fill_silence(substream, + appl_ptr % runtime->buffer_size, + runtime->period_size - delta); } } else { /* stop running stream */ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-08 16:07 ` Takashi Iwai @ 2004-10-08 20:26 ` Giuliano Pochini 2004-10-16 19:31 ` Giuliano Pochini 1 sibling, 0 replies; 19+ messages in thread From: Giuliano Pochini @ 2004-10-08 20:26 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On Fri, 08 Oct 2004 18:07:53 +0200 Takashi Iwai <tiwai@suse.de> wrote: > > > > With both the powermac driver and my echoaudio driver, playback ends with a > > > > "click". With properly choosen buffer/period/file sizes I can make the card > > > > play almost a whole period of old data before the substream is actually > > > > stopped. It seems that periods after the last one are not silenced, but I'm > > > > not having luck at findind the cause. This is not a recent problem. > > > > [...] > > > > > > I reply myself to add that I asked about this issue at one of the > > > betatesters and he can hear the click also. It's not a mac-only problem... > > > Any ideas ? > > > > ALSA seems not putting silence properly unless silence_size > 0. > > How about the attached patch? > > (it's an untested and quick fix, as usual :) > > And broken, as usual :) > The corrected on is below. No changes at all, sorry. I'll investigate further tomorrow. -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-08 16:07 ` Takashi Iwai 2004-10-08 20:26 ` Giuliano Pochini @ 2004-10-16 19:31 ` Giuliano Pochini 2004-10-18 11:14 ` Takashi Iwai 1 sibling, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-10-16 19:31 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On Fri, 08 Oct 2004 18:07:53 +0200 Takashi Iwai <tiwai@suse.de> wrote: > > ALSA seems not putting silence properly unless silence_size > 0. > > How about the attached patch? > > (it's an untested and quick fix, as usual :) > > And broken, as usual :) > The corrected on is below. The patch doesn't fix the problem. With your patch snd_pcm_do_drain_init() does: if (! runtime->silence_size) { /* fill silence until the priod end */ snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; snd_pcm_uframes_t delta = appl_ptr % runtime->period_size; if (delta > 0) snd_pcm_lib_fill_silence(substream, appl_ptr % runtime->buffer_size, runtime->period_size - delta); } In my case delta is always 0. It seems ALSA aligns appl_ptr to the offset of the next period without silencing the current one. I could not find where. Anyway, calling _fill_silence() with length=runtime->period_size - delta is wrong IMHO because not all periods have have the same size. The last one can be smaller and in that case it will overflow. Also, I don't think filling with silence until the end of the period is enough. ALSA stops the card some time it gets the interrupt, thus it should silence also the subsequent period, or its beginning part. Replacing the block above with the following code fixes the problem for me: if (!runtime->silence_size) { snd_pcm_uframes_t start, end; start = runtime->control->appl_ptr % runtime->buffer_size; end = runtime->status->hw_ptr % runtime->buffer_size; if (end < start) { snd_pcm_lib_fill_silence(substream, start, runtime->buffer_size - start); snd_pcm_lib_fill_silence(substream, 0, end); } else { snd_pcm_lib_fill_silence(substream, start, end - start); } } * BUT it not the right fix * It works fine when there are 3 or more periods, and in that case it writes more stuff than needed (easily fixable). When there are only 2 periods it's not enough. For example: per 0 per 1 Buffer: |---------------|---------------| ^^ appl_ptr / \ hw_ptr Suppose period 0 is the last period to be played, so draining starts at its end. My code fills just an handful of frames, and they may not be enough to avoid the click when the card will reach the end of period 0 again. ALSA should silence period 1 at the end of period 1. I don't know how to do it. -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-16 19:31 ` Giuliano Pochini @ 2004-10-18 11:14 ` Takashi Iwai 2004-10-18 14:56 ` Giuliano Pochini 2004-11-01 19:29 ` Giuliano Pochini 0 siblings, 2 replies; 19+ messages in thread From: Takashi Iwai @ 2004-10-18 11:14 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel At Sat, 16 Oct 2004 21:31:13 +0200, Giuliano Pochini wrote: > > On Fri, 08 Oct 2004 18:07:53 +0200 > Takashi Iwai <tiwai@suse.de> wrote: > > > > ALSA seems not putting silence properly unless silence_size > 0. > > > How about the attached patch? > > > (it's an untested and quick fix, as usual :) > > > > And broken, as usual :) > > The corrected on is below. > > The patch doesn't fix the problem. > > With your patch snd_pcm_do_drain_init() does: > > if (! runtime->silence_size) { > /* fill silence until the priod end */ > snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; > snd_pcm_uframes_t delta = appl_ptr % runtime->period_size; > if (delta > 0) > snd_pcm_lib_fill_silence(substream, > appl_ptr % runtime->buffer_size, > runtime->period_size - delta); > } > > In my case delta is always 0. It seems ALSA aligns appl_ptr to the offset of > the next period without silencing the current one. If so, it has to be in alsa-lib. Not a bug of ALSA driver. > I could not find where. > Anyway, calling _fill_silence() with length=runtime->period_size - delta is > wrong IMHO because not all periods have have the same size. The last one can > be smaller and in that case it will overflow. The period size is always same even for the last period, AFAIK. > Also, I don't think filling with silence until the end of the period is > enough. ALSA stops the card some time it gets the interrupt, thus it should > silence also the subsequent period, or its beginning part. I thought of that, too, but concluded that it's a questionary behavior. Usually, it's not needed if the interrupt is taken fast enough at the moment the last period is processed. The click noise comes from the garbage data in the last period. Also, the app can specify silence_size if it needs this behavior explicitly. However, there can be a case that the irq isn't handled fast enough, or the DMA and the interrupt isn't synchronized well (e.g. using a timer interrupt because of lack of DMA interrupt). In such a case, auto-silencing would be needed for the proper work... Takashi ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-18 11:14 ` Takashi Iwai @ 2004-10-18 14:56 ` Giuliano Pochini 2004-10-18 15:10 ` Takashi Iwai 2004-11-01 19:29 ` Giuliano Pochini 1 sibling, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-10-18 14:56 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On 18-Oct-2004 Takashi Iwai wrote: >> In my case delta is always 0. It seems ALSA aligns appl_ptr to the offset >> of the next period without silencing the current one. > > If so, it has to be in alsa-lib. Not a bug of ALSA driver. Ok, I'll check that one. >> Anyway, calling _fill_silence() with length=runtime->period_size - delta is >> wrong IMHO because not all periods have have the same size. The last one can >> be smaller and in that case it will overflow. > > The period size is always same even for the last period, AFAIK. Only if the driver explicitly asks for it by calling snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). >> Also, I don't think filling with silence until the end of the period is >> enough. ALSA stops the card some time it gets the interrupt, thus it should >> silence also the subsequent period, or its beginning part. > > I thought of that, too, but concluded that it's a questionary > behavior. > > Usually, it's not needed if the interrupt is taken fast enough at the > moment the last period is processed. "Fast" means <22us at 44100Hz... > The click noise comes from the garbage data in the last period. Indeed. -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-18 14:56 ` Giuliano Pochini @ 2004-10-18 15:10 ` Takashi Iwai 2004-10-18 15:34 ` Giuliano Pochini 0 siblings, 1 reply; 19+ messages in thread From: Takashi Iwai @ 2004-10-18 15:10 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel At Mon, 18 Oct 2004 16:56:11 +0200 (CEST), Giuliano Pochini wrote: > > >> Anyway, calling _fill_silence() with length=runtime->period_size - delta is > >> wrong IMHO because not all periods have have the same size. The last one can > >> be smaller and in that case it will overflow. > > > > The period size is always same even for the last period, AFAIK. > > Only if the driver explicitly asks for it by calling > snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). No, this means that buffer_size = N * period_size, where N is integer. Without this constraint, N doesn't have to be an integer. Takashi ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-18 15:10 ` Takashi Iwai @ 2004-10-18 15:34 ` Giuliano Pochini 2004-10-19 11:03 ` Takashi Iwai 0 siblings, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-10-18 15:34 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On 18-Oct-2004 Takashi Iwai wrote: >> > The period size is always same even for the last period, AFAIK. >> >> Only if the driver explicitly asks for it by calling >> snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). > > No, this means that buffer_size = N * period_size, where N is > integer. Without this constraint, N doesn't have to be an integer. Yes, exactly. If N isn't integer, the buffer is formed by bufsize\persize periods (== the integer part of N) plus one short period which is bufsize%persize long. -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-18 15:34 ` Giuliano Pochini @ 2004-10-19 11:03 ` Takashi Iwai 2004-10-19 15:09 ` Giuliano Pochini 0 siblings, 1 reply; 19+ messages in thread From: Takashi Iwai @ 2004-10-19 11:03 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel At Mon, 18 Oct 2004 17:34:02 +0200 (CEST), Giuliano Pochini wrote: > > > On 18-Oct-2004 Takashi Iwai wrote: > > >> > The period size is always same even for the last period, AFAIK. > >> > >> Only if the driver explicitly asks for it by calling > >> snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). > > > > No, this means that buffer_size = N * period_size, where N is > > integer. Without this constraint, N doesn't have to be an integer. > > > Yes, exactly. If N isn't integer, the buffer is formed by > bufsize\persize periods (== the integer part of N) plus one > short period which is bufsize%persize long. The period size is constant regardless of N because it simply defines the interval of interrupts. When N isn't integer (say, 2.5), the transfer point moves like: 0, 1, 2, 0.5, 1.5, 0, 1, ... That is, when the point is at 2, the transfer is split to two parts (2-2.5 and 0-0.5). Takashi ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-19 11:03 ` Takashi Iwai @ 2004-10-19 15:09 ` Giuliano Pochini 2004-10-19 15:39 ` Takashi Iwai 0 siblings, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-10-19 15:09 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On 19-Oct-2004 Takashi Iwai wrote: >> >> > The period size is always same even for the last period, AFAIK. >> >> >> >> Only if the driver explicitly asks for it by calling >> >> snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). >> > >> > No, this means that buffer_size = N * period_size, where N is >> > integer. Without this constraint, N doesn't have to be an integer. >> >> Yes, exactly. If N isn't integer, the buffer is formed by >> bufsize\persize periods (== the integer part of N) plus one >> short period which is bufsize%persize long. > > The period size is constant regardless of N because it simply defines > the interval of interrupts. When N isn't integer (say, 2.5), the > transfer point moves like: > > 0, 1, 2, 0.5, 1.5, 0, 1, ... > > That is, when the point is at 2, the transfer is split to two parts > (2-2.5 and 0-0.5). Currently my driver uses a short period. To fix it the driver should use a special feature of the DSP that allows the driver to build the s-g list on the fly. It also has the bonus that the DSP automatically stops the trasport when it reaches the last programmed period, so draining and xruns stop exactly where expected. It's more complex than the current ring buffer implementation. Out of curiosity, is there any driver that supports non-integer N ? And why everything works fine even if the driver uses unequal periods ? It should skip all the time. Anyway, _fill_silence() can still overflow. -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-19 15:09 ` Giuliano Pochini @ 2004-10-19 15:39 ` Takashi Iwai 2004-10-20 8:35 ` Giuliano Pochini 0 siblings, 1 reply; 19+ messages in thread From: Takashi Iwai @ 2004-10-19 15:39 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel At Tue, 19 Oct 2004 17:09:25 +0200 (CEST), Giuliano Pochini wrote: > > > On 19-Oct-2004 Takashi Iwai wrote: > > >> >> > The period size is always same even for the last period, AFAIK. > >> >> > >> >> Only if the driver explicitly asks for it by calling > >> >> snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). > >> > > >> > No, this means that buffer_size = N * period_size, where N is > >> > integer. Without this constraint, N doesn't have to be an integer. > >> > >> Yes, exactly. If N isn't integer, the buffer is formed by > >> bufsize\persize periods (== the integer part of N) plus one > >> short period which is bufsize%persize long. > > > > The period size is constant regardless of N because it simply defines > > the interval of interrupts. When N isn't integer (say, 2.5), the > > transfer point moves like: > > > > 0, 1, 2, 0.5, 1.5, 0, 1, ... > > > > That is, when the point is at 2, the transfer is split to two parts > > (2-2.5 and 0-0.5). > > Currently my driver uses a short period. Well, then this is not a supported feature. period_size must be constant in the current implementation. > To fix it the > driver should use a special feature of the DSP that allows > the driver to build the s-g list on the fly. It also has > the bonus that the DSP automatically stops the trasport > when it reaches the last programmed period, so draining > and xruns stop exactly where expected. It's more complex > than the current ring buffer implementation. > > Out of curiosity, is there any driver that supports > non-integer N ? Yes, many drivers. As mentioned, the period_size is nothing but the interrupt interval. On many chips, the interrupt interval is not bound to the certain buffer positions. > And why everything works fine even if the > driver uses unequal periods ? It should skip all the time. Maybe it has worked casually :) In fact, period_size is referred rarely in the code. Only snd_pcm_update_hw_ptr_interrupt() refers it, and changing period_size only once per buffer isn't critical here since hw_ptr_interrupt is corrected at each time from the last hw_ptr. > Anyway, _fill_silence() can still overflow. In your case, yes. But it's exceptional. Usually, the DMA is stopped in the interrupt handler which processes the last period. That is, the resolution of control is in the interrupt interval (= period_size). This means that the whole period data is transferred even if only the short data has been written to the buffer. Takashi ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-19 15:39 ` Takashi Iwai @ 2004-10-20 8:35 ` Giuliano Pochini 2004-10-20 9:38 ` Takashi Iwai 0 siblings, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-10-20 8:35 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On 19-Oct-2004 Takashi Iwai wrote: >> >> >> > The period size is always same even for the last period, AFAIK. >> >> >> >> >> >> Only if the driver explicitly asks for it by calling >> >> >> snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS). >> >> > >> >> > No, this means that buffer_size = N * period_size, where N is >> >> > integer. Without this constraint, N doesn't have to be an integer. >> >> >> >> Yes, exactly. If N isn't integer, the buffer is formed by >> >> bufsize\persize periods (== the integer part of N) plus one >> >> short period which is bufsize%persize long. >> > >> > The period size is constant regardless of N because it simply defines >> > the interval of interrupts. When N isn't integer (say, 2.5), the >> > transfer point moves like: >> > >> > 0, 1, 2, 0.5, 1.5, 0, 1, ... >> > >> > That is, when the point is at 2, the transfer is split to two parts >> > (2-2.5 and 0-0.5). >> >> Currently my driver uses a short period. > > Well, then this is not a supported feature. period_size must be > constant in the current implementation. Ok, I'll add that constraint. I'm not sure if using that DSP feature is worth the effort because those extra features do not come for free. The driver has to do more work in the irq handler and it has to send send one more command to the DSP, which may be pretty slow on old 20-bits cards. I'll evaluate it later. I would like to get the driver included in alsa-driver asap, before starting to add support for the new "3G" cards. >> Anyway, _fill_silence() can still overflow. > > In your case, yes. But it's exceptional. No, it also happens with you example when period_offs+period_len > buffer_size: N=3.5: first round: 0000000011111111222222223333 2nd: 3333444444445555555566666666 .... fill_silence(per=3, period_len) overflows. > Usually, the DMA is stopped in the interrupt handler which processes > the last period. That is, the resolution of control is in the > interrupt interval (= period_size). This means that the whole period > data is transferred even if only the short data has been written to > the buffer. Yes, I know, but the part from the last frame written by the app and the end of the period is not silenced *and* appl_ptr is moved to the end of the period before the call to drain_init(). I'm still looking for the cause. Sorry for my slowness, but I don't have a lot of time right now :( -- Giuliano. ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-20 8:35 ` Giuliano Pochini @ 2004-10-20 9:38 ` Takashi Iwai 0 siblings, 0 replies; 19+ messages in thread From: Takashi Iwai @ 2004-10-20 9:38 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel At Wed, 20 Oct 2004 10:35:34 +0200 (CEST), Giuliano Pochini wrote: > > >> Anyway, _fill_silence() can still overflow. > > > > In your case, yes. But it's exceptional. > > No, it also happens with you example when > period_offs+period_len > buffer_size: > > N=3.5: > > first round: > 0000000011111111222222223333 > > 2nd: > 3333444444445555555566666666 > .... > > fill_silence(per=3, period_len) overflows. Oh, yeah, you're right. This has to be handled correctly in fill_silence(). Takashi ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-10-18 11:14 ` Takashi Iwai 2004-10-18 14:56 ` Giuliano Pochini @ 2004-11-01 19:29 ` Giuliano Pochini 2004-11-09 9:29 ` Takashi Iwai 1 sibling, 1 reply; 19+ messages in thread From: Giuliano Pochini @ 2004-11-01 19:29 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On Mon, 18 Oct 2004 13:14:58 +0200 Takashi Iwai <tiwai@suse.de> wrote: > > With your patch snd_pcm_do_drain_init() does: > > > > if (! runtime->silence_size) { > > /* fill silence until the priod end */ > > snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; > > snd_pcm_uframes_t delta = appl_ptr % runtime->period_size; > > if (delta > 0) > > snd_pcm_lib_fill_silence(substream, > > appl_ptr % runtime->buffer_size, > > runtime->period_size - delta); > > } > > > > In my case delta is always 0. It seems ALSA aligns appl_ptr to the offset of > > the next period without silencing the current one. > > If so, it has to be in alsa-lib. Not a bug of ALSA driver. No, the bug is in my analysis. I had some time to look at this issue again. Your patch is ok. I was fooled by aplay that explicitly fills the last part of each block before writing it in chunks that have always the same size and my driver, which used unequally-sized periods, contributed to mess up the numbers. The patch below is mostly the one you wrote, with these changes: it handles the case when the period to be silences crosses the buffer boundary and it fills with silence the last played period while draining. It's not the right thing of course but it work for me. Actually, it should fill only the first x frames of the period following the last one, but I need another variable. > > Also, I don't think filling with silence until the end of the period is > > enough. ALSA stops the card some time it gets the interrupt, thus it should > > silence also the subsequent period, or its beginning part. > > I thought of that, too, but concluded that it's a questionary behavior. It's a minor problem because it only shows up during playback and if the song has a quick fade out. In my case the card reads at least 32 frames before it's stopped. --- /home/Giu/soft/ad/alsa-kernel/core/pcm_lib.c Fri Oct 8 22:01:08 2004 +++ alsa-kernel/core/pcm_lib.c Mon Nov 1 19:46:09 2004 @@ -95,32 +95,10 @@ ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size; while (frames > 0) { transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || - runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { - if (substream->ops->silence) { - int err; - err = substream->ops->silence(substream, -1, ofs, transfer); - snd_assert(err >= 0, ); - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); - } - } else { - unsigned int c; - unsigned int channels = runtime->channels; - if (substream->ops->silence) { - for (c = 0; c < channels; ++c) { - int err; - err = substream->ops->silence(substream, c, ofs, transfer); - snd_assert(err >= 0, ); - } - } else { - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); - } - } + + if (snd_pcm_lib_fill_silence(substream, ofs, transfer) < 0) { + snd_printk(KERN_ERR "fill_silence error\n"); + break; } runtime->silence_filled += transfer; frames -= transfer; @@ -128,6 +106,60 @@ } } +static int snd_pcm_lib_fill_silence1(snd_pcm_substream_t *substream, unsigned int ofs, snd_pcm_uframes_t frames) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + int c, channels = runtime->channels; + char *hwbuf; + size_t dma_csize; + + //snd_printk("snd_pcm_lib_fill_silence(ofs=%d, frames=%d)\n", ofs, (int)frames); + if (substream->ops->silence) { + int err = 0; + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) + err = substream->ops->silence(substream, -1, ofs, frames); + else { + for (c = 0; c < channels; c++) { + if ((err = substream->ops->silence(substream, c, ofs, frames)) < 0) + break; + } + } + return err; + } + + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { + hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); + //snd_printk("snd_pcm_lib_fill_silence() set_sil()\n"); + snd_pcm_format_set_silence(runtime->format, hwbuf, frames * channels); + } else { + dma_csize = runtime->dma_bytes / channels; + hwbuf = runtime->dma_area + samples_to_bytes(runtime, ofs); + for (c = 0; c < channels; c++) { + snd_pcm_format_set_silence(runtime->format, hwbuf, frames); + hwbuf += dma_csize; + } + } + return 0; +} + +int snd_pcm_lib_fill_silence(snd_pcm_substream_t *substream, unsigned int ofs, snd_pcm_uframes_t frames) +{ + int err; + + if (ofs + frames <= substream->runtime->buffer_size) + return snd_pcm_lib_fill_silence1(substream, ofs, frames); + else { /* Uncommon case: the part to be silenced goes beyond the end of the buffer */ + err = snd_pcm_lib_fill_silence1(substream, ofs, substream->runtime->buffer_size - ofs); + if (err) + return err; + return snd_pcm_lib_fill_silence1(substream, 0, ofs + frames - substream->runtime->buffer_size); + } +}; + + + static void xrun(snd_pcm_substream_t *substream) { snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); @@ -222,10 +254,18 @@ new_hw_ptr = runtime->hw_ptr_base + pos; } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream, new_hw_ptr); - + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (runtime->silence_size > 0) + snd_pcm_playback_silence(substream, new_hw_ptr); +#if 1 + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + snd_pcm_uframes_t start; + start = runtime->status->hw_ptr % runtime->buffer_size; + start -= start % runtime->period_size; + snd_pcm_lib_fill_silence(substream, start, runtime->period_size); + } + } +#endif runtime->status->hw_ptr = new_hw_ptr; runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size; @@ -2080,12 +2120,12 @@ } return 0; } - + typedef int (*transfer_f)(snd_pcm_substream_t *substream, unsigned int hwoff, unsigned long data, unsigned int off, snd_pcm_uframes_t size); -static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, +static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, unsigned long data, snd_pcm_uframes_t size, int nonblock, --- /home/Giu/soft/ad/alsa-kernel/core/pcm_native.c Fri Oct 8 22:01:09 2004 +++ alsa-kernel/core/pcm_native.c Mon Nov 1 19:44:15 2004 @@ -1296,7 +1296,16 @@ runtime->status->state = SNDRV_PCM_STATE_DRAINING; break; default: - break; + return 0; /* do nothing */ + } + if (!runtime->silence_size) { + /* fill silence until the period end */ + snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; + snd_pcm_uframes_t delta = appl_ptr % runtime->period_size; + if (delta > 0) + snd_pcm_lib_fill_silence(substream, + appl_ptr % runtime->buffer_size, + runtime->period_size - delta); } } else { /* stop running stream */ -- Giuliano. ------------------------------------------------------- This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-11-01 19:29 ` Giuliano Pochini @ 2004-11-09 9:29 ` Takashi Iwai 2004-11-09 10:00 ` Giuliano Pochini 0 siblings, 1 reply; 19+ messages in thread From: Takashi Iwai @ 2004-11-09 9:29 UTC (permalink / raw) To: Giuliano Pochini; +Cc: alsa-devel At Mon, 1 Nov 2004 20:29:49 +0100, Giuliano Pochini wrote: > > The patch below is mostly the one you wrote, with these changes: it handles > the case when the period to be silences crosses the buffer boundary and it > fills with silence the last played period while draining. It's not the right > thing of course but it work for me. Actually, it should fill only the first > x frames of the period following the last one, but I need another variable. The first is the right fix, but how about the latter one (filling silence at the last position in snd_pcm_update_hw_ptr_interrupt()) ? Does it fix something? Takashi ------------------------------------------------------- This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Click after draining 2004-11-09 9:29 ` Takashi Iwai @ 2004-11-09 10:00 ` Giuliano Pochini 0 siblings, 0 replies; 19+ messages in thread From: Giuliano Pochini @ 2004-11-09 10:00 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On 09-Nov-2004 Takashi Iwai wrote: > At Mon, 1 Nov 2004 20:29:49 +0100, > Giuliano Pochini wrote: >> >> The patch below is mostly the one you wrote, with these changes: it handles >> the case when the period to be silences crosses the buffer boundary and it >> fills with silence the last played period while draining. It's not the right >> thing of course but it work for me. Actually, it should fill only the first >> x frames of the period following the last one, but I need another variable. > > The first is the right fix It's the part you wrote, with some minor tweaks. > but how about the latter one (filling silence at the last position > in snd_pcm_update_hw_ptr_interrupt()) ? Does it fix something? Yes, it fixes the remaining small click. It happens because the card does not stop immediately when the last interrupt is delivered. In my case it plays the first 32 frames of the next period that still contains old data. It's a very small problem compared to the big click you fixed. My patch fills way too much data than needed of course. It's a just a test and it's not supposed to be applied. -- Giuliano. ------------------------------------------------------- This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click ^ permalink raw reply [flat|nested] 19+ messages in thread
* Click after draining
@ 2007-01-05 22:48 Andrew Johnson
0 siblings, 0 replies; 19+ messages in thread
From: Andrew Johnson @ 2007-01-05 22:48 UTC (permalink / raw)
To: alsa-devel
Hi All,
This bug
(http://thread.gmane.org/gmane.linux.alsa.devel/14700/focus=14700)
appears to exist for the pxa2xx-pcm driver on a PXA270 platform.
- It appears that Takashi's patch isn't included in the ALSA Drivers as
of 2.6.16 - is there any reason why?
- Takashi commented in the thread that the period sizes must all be the
same. Is this still true? If the sizes are not the same (as in the
pxa2xx-pcm driver), could this cause this problem?
I've done some analysis by toggling a GPIO when a period ends. The
result is (N indicates sound, the two N's at the end indicate unwanted
sound which appears to come from earlier in the circular buffer):
|-------------------|-------------------|-------------------|
NNNN NN
^ ^
End of audio data | | SNDRV_PCM_TRIGGER_STOP
So the IRQ is occurring but the ALSA core is not turning off the DMA
until the next IRQ. I've experimented with setting
runtime->stop_threshold = runtime->buffer_size -
runtime->period_size;
And this works but ends up cutting other .wav files short. I have found
that setting
runtime->silence_size = runtime->period_size * 2;
runtime->silence_threshold = runtime->period_size * 2;
causes this problem to go away however this causes issues when playing
multiple sound files back to back.
Any help on this would be much appreciated!
Kind Regards,
Andrew
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
^ permalink raw reply [flat|nested] 19+ messages in threadend of thread, other threads:[~2007-01-05 22:48 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-09-21 20:13 Click after draining Giuliano Pochini 2004-10-07 18:58 ` Giuliano Pochini 2004-10-08 15:34 ` Takashi Iwai 2004-10-08 16:07 ` Takashi Iwai 2004-10-08 20:26 ` Giuliano Pochini 2004-10-16 19:31 ` Giuliano Pochini 2004-10-18 11:14 ` Takashi Iwai 2004-10-18 14:56 ` Giuliano Pochini 2004-10-18 15:10 ` Takashi Iwai 2004-10-18 15:34 ` Giuliano Pochini 2004-10-19 11:03 ` Takashi Iwai 2004-10-19 15:09 ` Giuliano Pochini 2004-10-19 15:39 ` Takashi Iwai 2004-10-20 8:35 ` Giuliano Pochini 2004-10-20 9:38 ` Takashi Iwai 2004-11-01 19:29 ` Giuliano Pochini 2004-11-09 9:29 ` Takashi Iwai 2004-11-09 10:00 ` Giuliano Pochini -- strict thread matches above, loose matches on Subject: below -- 2007-01-05 22:48 Andrew Johnson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.