他のアプリケーションが何かを再生し始めたらMOCをフェードアウトする

他のアプリケーションが何かを再生し始めたらMOCをフェードアウトする

mocデーモンのサウンド再生を強制的にフェードダウンする良い方法を見つける必要があります

次のようなシナリオがあります。

私は、MOC (musiconconsole) デーモンとカスタム Ruby アプリケーションを搭載した小さな Ubuntu 12.04 サーバー ボックスを実行しています。

Ruby アプリケーションは、定期的またはイベント駆動型のシナリオで、時々 wav またはその他のサウンド ファイルを再生します。たとえば、午後 7 時に「store_is_closing.mp3」などを再生します。

また、MP3 プレイリストで MOC デーモンを実行し、一日中音楽を再生しています。

ミキシングには ALSA を使用しています。

すべて正常に動作していますが、1 点欠けています。

たとえば、MOC が曲を再生していて、Ruby アプリがサウンド ファイルを再生すると、すべてが同じサウンド レベルになります (当然のことですが)。そのため、Ruby アプリによって再生されたサウンド ファイルの音は何も聞き取れません。

MOC デーモンに曲の再生を強制的に定義済みのパーセンテージ (元のサウンド レベルの 10% とします) までフェード ダウンさせる方法を見つける必要があります。Ruby アプリがサウンド ファイルを再生した後、moc を元のサウンド レベルに戻す必要があります。

答え1

MOC デーモンはmocpクライアントからのみ制御できます。

PulseAudio を使用している場合は、 を使用してpacmdMOC の音量を変更できます。

MOCをMPDmpc、 MPD の音量を変更するために使用できます。

本当に ALSA でこれを実行したい場合は、次の内容を に記述します/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
    }
}

moc_with_volumeの代わりにALSA デバイス名を使用するように MOC を構成しますdefault


ボリューム変更プログラムでミキサー コントロールを設定できない場合は、他のミキサー コントロールを監視し、その値を MOC ミキサー コントロールにコピーする必要があります。これは、次のようなプログラムで実行できます。

#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));
        }
}

(amixer controls実際のコントロール名を確認するために使用します。)

関連情報