Alsa - setting volume in an app works different when it is run as a service

180 Views Asked by At

I have an app which is using Alsa to play sounds. Below I show fragments of my code. The problem is that if my software is run as a systemd service, the range in the stVolume method is between 0 and 31. When I run my software as a standard application from the command line, the range is between 0 and 65536. In the first scenario the sound is very distorted and loud, I hear noise. It is much better in the second scenario. What is the reason? Why the same code run in a different way seems to use Alsa/sound card differently? Why Alsa is returning different range in both cases?

void init() {
    snd_mixer_open(&mMixer.handle, 0);
    snd_mixer_attach(mMixer.handle, mCardName);
    snd_mixer_selem_register(mMixer.handle, NULL, NULL);
    snd_mixer_load(mMixer.handle);

    snd_mixer_selem_id_alloca(&mMixer.sid);
    snd_mixer_selem_id_set_index(mMixer.sid, 0);
    snd_mixer_selem_id_set_name(mMixer.sid, mMixerName);
    mMixer.slider = snd_mixer_find_selem(mMixer.handle, mMixer.sid);
}

where mMixer is a following struct:

struct {
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;
    snd_mixer_elem_t *slider;
} mMixer;

and mCardName and mMixerName are:

const char *mCardName = "default";
const char *mMixerName = "Master";

When I want to play sound, I invoke the following method:

void on() {
    try {
        // open audio device
        int err = snd_pcm_open(&mHandle, mCardName,
            SND_PCM_STREAM_PLAYBACK,
            SND_PCM_NONBLOCK);
        
        if (err < 0)
            throw std::runtime_error(snd_strerror(err));

        // configure audio
        g_assert_nonnull(mHandle);

        err = snd_pcm_set_params(mHandle,
            SND_PCM_FORMAT_U8,
            SND_PCM_ACCESS_RW_INTERLEAVED,
            1,         // channels
            SAMPLE_RATE,     // sample rate
            1,         // soft resample allowed
            500000);   // latency (in us)

        if (err < 0)
            throw std::runtime_error(snd_strerror(err));
    } catch(std::runtime_error &e) {
        g_printerr("Can't configure audio: %s\n", e.what());
    }
}

and then I set the volume:

void setVolume(unsigned volume) {
    long min = 0, max = 0;      // NOLINT (type required by ALSA
    snd_mixer_selem_get_playback_volume_range(mMixer.slider, &min, &max);
    snd_mixer_selem_set_playback_volume_all(mMixer.slider, volume * max / 100);

    g_warning("FHR probe volume %ld. Min: %ld, Max: %ld", volume * max / 100, min, max);
}
0

There are 0 best solutions below