[alsa-devel] intel 8x0 ALSA driver in virtualbox - choppy sound
Dear all
I am having problems with getting sound running well in Arch Linux guest (VirtualBox 3.2.8), the host is OS X Snow Leopard. The problem is that the sound is very choppy. I've checked around VirtualBox and Arch forums and it seems that some others experience these problems as well yet I could not see anyone sufficiently skilled to debug this paying attention. I think there is a problem with either VirtualBox implementation of the sound card or a bug in ALSA driver for that card because I have sound running just fine in VMWare Fusion (using es1371 (?) driver), so the host system definitely is fast enough for decent sound quality.
I would like to offer my help with identifying the cause of the problem and testing solutions if the need be.
I've attached my alsa-info output for your reference. Please let me know if there is anything else I could try to help.
I am very keen to help but I don't know how.
Best regards,
Lex
On Fri, 13 Aug 2010, Lex F wrote:
Dear all
I am having problems with getting sound running well in Arch Linux guest (VirtualBox 3.2.8), the host is OS X Snow Leopard. The problem is that the sound is very choppy. I've checked around VirtualBox and Arch forums and it seems that some others experience these problems as well yet I could not see anyone sufficiently skilled to debug this paying attention. I think there is a problem with either VirtualBox implementation of the sound card or a bug in ALSA driver for that card because I have sound running just fine in VMWare Fusion (using es1371 (?) driver), so the host system definitely is fast enough for decent sound quality.
I would like to offer my help with identifying the cause of the problem and testing solutions if the need be.
I've attached my alsa-info output for your reference. Please let me know if there is anything else I could try to help.
I am very keen to help but I don't know how.
http://www.alsa-project.org/main/index.php/XRUN_Debug is a good start to see if the virtual machine does receive interrupts in the right time.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
At Fri, 13 Aug 2010 17:19:10 +0200 (CEST), Jaroslav Kysela wrote:
On Fri, 13 Aug 2010, Lex F wrote:
Dear all
I am having problems with getting sound running well in Arch Linux guest (VirtualBox 3.2.8), the host is OS X Snow Leopard. The problem is that the sound is very choppy. I've checked around VirtualBox and Arch forums and it seems that some others experience these problems as well yet I could not see anyone sufficiently skilled to debug this paying attention. I think there is a problem with either VirtualBox implementation of the sound card or a bug in ALSA driver for that card because I have sound running just fine in VMWare Fusion (using es1371 (?) driver), so the host system definitely is fast enough for decent sound quality.
We have had many problems with VMware, too :) Which sound backend are you using? Direct ALSA / dmix or PA?
I would like to offer my help with identifying the cause of the problem and testing solutions if the need be.
I've attached my alsa-info output for your reference. Please let me know if there is anything else I could try to help.
I am very keen to help but I don't know how.
http://www.alsa-project.org/main/index.php/XRUN_Debug is a good start to see if the virtual machine does receive interrupts in the right time.
Actually, there is no real interrupt, but just the virtual one, thus it can be never accurate. So, rather the question is how the driver is tolerant for sloppy IRQ updates.
Usually, when the period size is large and the buffer have many periods (not two), the delayed update works more stably.
Takashi
On Fri, 13 Aug 2010, Takashi Iwai wrote:
http://www.alsa-project.org/main/index.php/XRUN_Debug is a good start to see if the virtual machine does receive interrupts in the right time.
Actually, there is no real interrupt, but just the virtual one, thus it can be never accurate. So, rather the question is how the driver is tolerant for sloppy IRQ updates.
Usually, when the period size is large and the buffer have many periods (not two), the delayed update works more stably.
I know. The current position checking in pcm_lib.c should handle delayed updates, but it does not handle well the multiple elapsed() calls merged to one time (double interrupt acknowledges). In some cases, the code things that buffer_size boundary were crossed, thus the hw_ptr position update fails.
I wanted to force the driver to be responsible to call the elapsed() calls at the right time. But it's true that the interrupt controller and other operating system contrainsts and behaviour might influence the interrupt processing which is more visible in the virtual environment.
Thinking more about it, we need probably another quick check against different timing source to check properly for the buffer_size crossing.
What about this patch (the hw_base gets updates in in_interrupt only when delta for next jiffies is bigger than (buffer jiffies / 2)). It should handle all double acks from the interrupt callbacks:
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 85f1c6b..dfd9b76 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -278,6 +278,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ + unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
/* -- HW params -- */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index e23e0e7..a1707cc 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* delta = "expected next hw_ptr" for in_interrupt != 0 */ delta = runtime->hw_ptr_interrupt + runtime->period_size; if (delta > new_hw_ptr) { - hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) - hw_base = 0; - new_hw_ptr = hw_base + pos; - goto __delta; + /* check for double acknowledged interrupts */ + hdelta = jiffies - runtime->hw_ptr_jiffies; + if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { + hw_base += runtime->buffer_size; + if (hw_base >= runtime->boundary) + hw_base = 0; + new_hw_ptr = hw_base + pos; + goto __delta; + } } } /* new_hw_ptr might be lower than old_hw_ptr in case when */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a3b2a64..b5dae26 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); runtime->hw_ptr_jiffies = jiffies; + runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / + runtime->rate; runtime->status->state = state; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0)
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
At Sat, 14 Aug 2010 09:53:38 +0200 (CEST), Jaroslav Kysela wrote:
On Fri, 13 Aug 2010, Takashi Iwai wrote:
http://www.alsa-project.org/main/index.php/XRUN_Debug is a good start to see if the virtual machine does receive interrupts in the right time.
Actually, there is no real interrupt, but just the virtual one, thus it can be never accurate. So, rather the question is how the driver is tolerant for sloppy IRQ updates.
Usually, when the period size is large and the buffer have many periods (not two), the delayed update works more stably.
I know. The current position checking in pcm_lib.c should handle delayed updates, but it does not handle well the multiple elapsed() calls merged to one time (double interrupt acknowledges). In some cases, the code things that buffer_size boundary were crossed, thus the hw_ptr position update fails.
I wanted to force the driver to be responsible to call the elapsed() calls at the right time. But it's true that the interrupt controller and other operating system contrainsts and behaviour might influence the interrupt processing which is more visible in the virtual environment.
Thinking more about it, we need probably another quick check against different timing source to check properly for the buffer_size crossing.
What about this patch (the hw_base gets updates in in_interrupt only when delta for next jiffies is bigger than (buffer jiffies / 2)). It should handle all double acks from the interrupt callbacks:
Looks good. We need some tests, though. Maybe we can put some randomness in dummy driver...
thanks,
Takashi
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 85f1c6b..dfd9b76 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -278,6 +278,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
/* -- HW params -- */
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index e23e0e7..a1707cc 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* delta = "expected next hw_ptr" for in_interrupt != 0 */ delta = runtime->hw_ptr_interrupt + runtime->period_size; if (delta > new_hw_ptr) {
hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary)
hw_base = 0;
new_hw_ptr = hw_base + pos;
goto __delta;
/* check for double acknowledged interrupts */
hdelta = jiffies - runtime->hw_ptr_jiffies;
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary)
hw_base = 0;
new_hw_ptr = hw_base + pos;
goto __delta;
} } /* new_hw_ptr might be lower than old_hw_ptr in case when */}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a3b2a64..b5dae26 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); runtime->hw_ptr_jiffies = jiffies;
- runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
runtime->status->state = state; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0)runtime->rate;
Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
Is there a how-to for installing the alsa-lib correctly on the n810? (hopefully from a fresh install of Diablo?)
participants (4)
-
Jaroslav Kysela
-
John Simpson
-
Lex F
-
Takashi Iwai