0

I need to find a good way to force fade down the sound playback of a moc daemon

I have the following scenario:

I have running a small Ubuntu 12.04 server box with a MOC (musiconconsole) daemon and a custom ruby application.

The ruby application occasionally plays a wav or other soundfile in periodic or event driven scenarios. e.g. at 7 p.m. it plays "store_is_closing.mp3" or something like that.

I also have a MOC daemon running with a mp3 playlist, which plays music the whole day.

I am using ALSA to do the mixing.

Everything works fine but I am missing one point.

If, let's say MOC is playing a song and the ruby app plays a sound file, everything is on the same sound level (obviously). so, you can't understand anything of the sound file played by the ruby app.

I need to find a way to force the MOC daemon to fade down his playback of the song to a defined percentage (let's say 10% of the original sound level) and after the ruby app played the sound file, moc should be toggled back back to the origin sound level.

2
  • How are you mixing with ALSA? dmix? – CL. Nov 12 '13 at 11:54
  • alsamixer, i guess – Ello Nov 12 '13 at 12:06
0

The MOC daemon can be controlled only with the mocp client.

If you were using PulseAudio, you could use pacmd to change MOC's volume.

If you replaced MOC with MPD, you could use mpc to change MPD's volume.

If you really want to do this with ALSA, you could put the following into /etc/asound.conf:

pcm.moc_with_volume {
    type softvol
    slave.pcm "default"  # or whatever you're using in MOC
    control {
        name "MOC Playback Volume"
        count 1
    }
}

and configure MOC to use the ALSA device name moc_with_volume instead of default.


If your volume-changing program does not allow to configure its mixer control, you have to monitor the other mixer control and copy its value to the MOC mixer control. This could be done with a program like this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alsa/asoundlib.h>

#define CHECK(fn) check((fn), #fn)
static void check(int err, const char *fn)
{
        if (err < 0) {
                fprintf(stderr, "%s failed: %s\n", fn, snd_strerror(err));
                exit(EXIT_FAILURE);
        }
}

int main()
{
        snd_ctl_t *ctl;
        snd_ctl_event_t *event;
        snd_ctl_elem_id_t *id_src, *id_dst;
        snd_ctl_elem_value_t *value;
        unsigned int mask;
        long raw, db;

        CHECK(snd_ctl_open(&ctl, "hw:0", 0));
        CHECK(snd_ctl_subscribe_events(ctl, 1));
        snd_ctl_event_alloca(&event);
        snd_ctl_elem_id_alloca(&id_src);
        snd_ctl_elem_id_alloca(&id_dst);
        snd_ctl_elem_value_alloca(&value);
        snd_ctl_elem_id_set_interface(id_dst, SND_CTL_ELEM_IFACE_MIXER);
        snd_ctl_elem_id_set_name(id_dst, "MOC Playback Volume");
        for (;;) {
                CHECK(snd_ctl_read(ctl, event));
                if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM)
                        continue;
                mask = snd_ctl_event_elem_get_mask(event);
                if (mask == SND_CTL_EVENT_MASK_REMOVE ||
                    !(mask & SND_CTL_EVENT_MASK_VALUE) ||
                    strcmp(snd_ctl_event_elem_get_name(event),
                           "Some Mic Capture Volume"))
                        continue;
                snd_ctl_event_elem_get_id(event, id_src);
                snd_ctl_elem_value_set_id(value, id_src);
                CHECK(snd_ctl_elem_read(ctl, value));
                raw = snd_ctl_elem_value_get_integer(value, 0);
                CHECK(snd_ctl_convert_to_dB(ctl, id_src, raw, &db));
                CHECK(snd_ctl_convert_from_dB(ctl, id_dst, db, &raw, 0));
                snd_ctl_elem_value_set_id(value, id_dst);
                snd_ctl_elem_value_set_integer(value, 0, raw);
                snd_ctl_elem_value_set_integer(value, 1, raw);
                CHECK(snd_ctl_elem_write(ctl, value));
        }
}

(Use amixer controls to check the actual control names.)

13
  • thank you, but i have not the problem with the playback, i have a problem with simultanious playback. if MOC or MPD is playing a song AND the ruby app is playing a sound file, i want the MOC/MPD playback fade down the sound level as long as the ruby app is playing the soundfile, then i want the music back to his origin sound level – Ello Nov 12 '13 at 12:39
  • Call amixer/mpc to reduce the MOC/MPD volume, then call the ruby app, then call amixer/mpc to raise the volume. If the ruby is running continuously, call the tool from there. – CL. Nov 12 '13 at 12:50
  • sry, didn't get it to work the way i wanted. darn. i guess i have to find another way. anyway, thanks for your help – Ello Nov 14 '13 at 9:52
  • Please edit your question to show how your Ruby app plays the sound. – CL. Nov 15 '13 at 11:52
  • i don't know how the ruby app plays the sound, it is written by another developer. i would be happy if i could create a virtual sound card which outputs the MOC sound to the INPUT (Mic) Channel of my physical card. this would be enough at the moment. i contacted the developer and he told me, that he will fix the ruby app to fade down the "Mic" channel on the physical card – Ello Nov 15 '13 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.