Re: [alsa-devel] [Alsa-user] Master volume control
From: Clemens Ladisch [mailto:cladisch@googlemail.com]
#include <stdio.h> #include <stdlib.h> #include <alsa/asoundlib.h>
static void check(int err, const char *f) { if (err < 0) { fprintf(stderr, "%s failed: %s\n", f, snd_strerror(err)); exit(EXIT_FAILURE); } } #define CHECK(f) check(f, #f)
int main() { snd_ctl_t *ctl; snd_ctl_elem_value_t *value;
CHECK(snd_ctl_open(&ctl, "default", 0)); snd_ctl_elem_value_alloca(&value); snd_ctl_elem_value_set_interface(value,
SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name(value, "Master Playback Volume"); snd_ctl_elem_value_set_integer(value, 0, 42); CHECK(snd_ctl_elem_write(ctl, value));
snd_ctl_close(ctl); return 0;
}
Well, I finally got a chance to try this. It "works", but the snd_ctl_elem_write call takes a couple of milliseconds (that's around a million instructions on my Atom), and it apparently spends this time in kernel state, because it causes my sound thread to underrun, so it's not usable.
If I use alsamixer, I don't have this problem; I can manipulate the master volume smoothly while I'm playing my synth app. So I went through the source, and found that it's using snd_mixer_selem_set_playback_volume. This is apparently part of something called the "Simple Mixer Interface", yet another section of ALSA which is completely undocumented, other than the Doxygen stuff (which is only meaningful as a reference for someone who already knows it inside out, but can't remember e.g. whether playback_pcm comes before or after capture_pcm in the snd_mixer_selem_regopt structure).
So what's the minimum I need to do in order to get at the Master Playback Volume, via the Simple Mixer Interface?
On 13.03.2013 17:47, Paul D. DeRocco wrote:
From: Clemens Ladisch [mailto:cladisch@googlemail.com]
#include <stdio.h> #include <stdlib.h> #include <alsa/asoundlib.h>
static void check(int err, const char *f) { if (err < 0) { fprintf(stderr, "%s failed: %s\n", f, snd_strerror(err)); exit(EXIT_FAILURE); } } #define CHECK(f) check(f, #f)
int main() { snd_ctl_t *ctl; snd_ctl_elem_value_t *value;
CHECK(snd_ctl_open(&ctl, "default", 0)); snd_ctl_elem_value_alloca(&value); snd_ctl_elem_value_set_interface(value,
SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name(value, "Master Playback Volume"); snd_ctl_elem_value_set_integer(value, 0, 42); CHECK(snd_ctl_elem_write(ctl, value));
snd_ctl_close(ctl); return 0;
}
Well, I finally got a chance to try this. It "works", but the snd_ctl_elem_write call takes a couple of milliseconds (that's around a million instructions on my Atom), and it apparently spends this time in kernel state, because it causes my sound thread to underrun, so it's not usable.
So why are you doing this from your sound thread then?
Daniel
If I use alsamixer, I don't have this problem; I can manipulate the master volume smoothly while I'm playing my synth app. So I went through the source, and found that it's using snd_mixer_selem_set_playback_volume. This is apparently part of something called the "Simple Mixer Interface", yet another section of ALSA which is completely undocumented, other than the Doxygen stuff (which is only meaningful as a reference for someone who already knows it inside out, but can't remember e.g. whether playback_pcm comes before or after capture_pcm in the snd_mixer_selem_regopt structure).
So what's the minimum I need to do in order to get at the Master Playback Volume, via the Simple Mixer Interface?
From: Daniel Mack [mailto:zonque@gmail.com]
So why are you doing this from your sound thread then?
I'm not. I'm doing it from another thread, but somehow it's causing underruns in my two sound threads (on a dual-core Atom). I'm speculating that it's hogging one CPU by sitting in the kernel.
My synth app, running on a dual-core Atom, has two sound generation threads, running at a "nice" value of -20, and a normal control thread running at nice 0. The control thread is what calls snd_ctl_elem_write when I move the volume slider. My sound threads normally consume less than 50% of their respective CPUs, but when I move the volume slider, I get underruns.
If I run "top -H" in a terminal window, I see three other processes that suddenly consume gobs of CPU time as I change the volume.
name nice CPU% pulseaudio -11 19 threaded-ml 0 14 indicator-sound 0 11
If instead of using my synth's volume slider, I open alsamixer in another terminal window, I don't see the same CPU usage, but I now attribute that to the fact that the keyboard is issuing volume changes at a much slower rate than my slider, which is read in a 200Hz loop. In fact, when I use alsamixer, and ramp the volume up and down, every now and then I do get an underrun. So it apparently won't matter whether I use snd_ctl_elem_write or snd_mixer_selem_set_playback_volume.
So what I'd like to know is why the hell does changing the volume every 5ms suck up 44% of one CPU core? I get the feeling that the above processes aren't integral to ALSA, and may go away when I move my app to a pure embedded system, as opposed to Ubuntu. Is that the case? Am I chasing phantoms? Since I'm not doing _anything_ related to sound on this machine, other than developing my synth app (I don't even need a terminal beep), is there any way I can uninstall the things that are hogging the CPU, like pulseaudio?
Paul D. DeRocco wrote:
snd_ctl_elem_value_set_interface(value, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name(value, "Master Playback Volume"); snd_ctl_elem_value_set_integer(value, 0, 42); CHECK(snd_ctl_elem_write(ctl, value));
Well, I finally got a chance to try this. It "works", but the snd_ctl_elem_write call takes a couple of milliseconds (that's around a million instructions on my Atom), and it apparently spends this time in kernel state, because it causes my sound thread to underrun, so it's not usable.
I'd guess that some driver uses a busy loop for writing the codec registers.
Which drivers are you using for your sound hardware?
If I use alsamixer, I don't have this problem; I can manipulate the master volume smoothly while I'm playing my synth app. So I went through the source, and found that it's using snd_mixer_selem_set_playback_volume.
Ultimately, this is a wrapper for the snd_ctl_* functions.
Regards, Clemens
From: Clemens Ladisch [mailto:clemens@ladisch.de]
I'd guess that some driver uses a busy loop for writing the codec registers.
Which drivers are you using for your sound hardware?
It's Intel HD Audio.
But the point is that three other processes light up when I move the slider. I think they're all monitoring the master volume changes, and not actually involved in doing the volume change. I would expect lots of CPU usage if I had alsamixer open at the time, because it monitors these changes, and updates its display. But the numbers I got from "top -H" were with no monitoring apps running that I know of.
What I'm wondering about these processes (pulseaudio, threaded-ml, indicator-sound) is two things:
* Is there any way to disable or uninstall them in Ubuntu?
* If I create my own minimal embedded distro (I'm trying to use the Yocto project for that), will they simply not be there, or will I have to go to some lengths there, too, to disable or uninstall them?
If this is just an issue with Ubuntu, then it's not worth spending much time on it, since this synth is targeted purely for an embedded environment.
Paul D. DeRocco wrote:
I'd guess that some driver uses a busy loop for writing the codec registers.
Which drivers are you using for your sound hardware?
It's Intel HD Audio.
That driver works fine.
But the point is that three other processes light up when I move the slider. I think they're all monitoring the master volume changes, and not actually involved in doing the volume change.
I guess your CPU doesn't have too many cores ...
What I'm wondering about these processes (pulseaudio, threaded-ml, indicator-sound)
PulseAudio has its own virtual volume sliders on top of the hardware controls. indicator-sound appears to be an OSD of your desktop environment. I don't know what threaded-ml is (maybe part of Chrome?).
I would expect lots of CPU usage if I had alsamixer open at the time, because it monitors these changes, and updates its display.
Well, how much increas in CPU usage do you get wth alsamixer?
- If I create my own minimal embedded distro (I'm trying to use the Yocto
project for that), will they simply not be there
If you don't included the relevant packages.
Regards, Clemens
participants (3)
-
Clemens Ladisch
-
Daniel Mack
-
Paul D. DeRocco