試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PythonからALSAのミキサーを扱う

pyalsaaudio(http://pyalsaaudio.sourceforge.net/)を用いると、PythonのコードからALSAのミキサーやPCMデバイスを操作することができる。
ここではミキサー項目の取得と音量取得/変更を試してみることにする。

ディストリのパッケージ

Gentooでは「pyalsaaudio」、Mandriva/Debian/Ubuntuでは「python-alsaaudio」というパッケージが用意されている。2009年2月現在のDebian/Ubuntuのパッケージはバージョンが古い(0.2系まで)。

ミキサー項目の取得

関数alsaaudio.mixers()を使用することで、利用可能なミキサー項目がリストとして得られる。
以下のコードを実行すると、(0番のサウンドカードにおける)利用可能なミキサー項目を全て表示する。
[任意]ファイル名: mixerlist.py

#! /usr/bin/python
# -*- encoding: utf-8 -*-

import sys
try:
  import alsaaudio
except:
  print >> sys.stderr, "Error: pyalsaaudio not installed"
  sys.exit(1)


for m in alsaaudio.mixers():
  print m

0番*1以外のサウンドカードでは引数による指定が必要。

ミキサーオブジェクトの作成

ミキサー値の取得や変更をするためには、alsaaudio.Mixerオブジェクトを作成しておく必要がある。ミキサーに対する操作は、このオブジェクトのメンバ関数を呼び出して行うことになる。
下の例では(0番のサウンドカードにおける)ミキサー項目(コントロール)「Master」に対するミキサーのオブジェクトを作成する。もしこのミキサー項目がなければ例外alsaaudio.ALSAAudioErrorが発生する。

name = "Master"
try:
  mixer = alsaaudio.Mixer(name)
except alsaaudio.ALSAAudioError:
  print >> sys.stderr, "Error: No such control: %s" % name
  sys.exit(1)

0番以外のサウンドカードを使用する場合、コンストラクタ引数にて指定することもできる。

音量の取得

alsaaudio.Mixerオブジェクトのメンバ関数getvolume()により、該当するミキサー項目の各チャンネルごとの値をリストとして取得できる。

音量の変更

音量を変更するにはalsaaudio.Mixerオブジェクトのメンバ関数setvolume()を使用し、チャンネル(0番からの数字で指定)ごとに音量を指定できる。
もし、全てのチャンネルで同じ値を用いて変更したい場合はチャンネルを指定する部分にalsaaudio.MIXER_CHANNEL_ALLを指定する。

音量変更の例

以下のスクリプトでは、指定した名前のミキサー項目に対して、指定した値に音量を変更する。その際には、変更前後の音量をチャンネルごとに表示する。
[任意]ファイル名: mixerset.py

#! /usr/bin/python
# -*- encoding: utf-8 -*-

import sys
try:
  import alsaaudio
except:
  print >> sys.stderr, "Error: pyalsaaudio not installed"
  sys.exit(1)


if len(sys.argv) < 3:
  print "USAGE: %s [name] [volume/ch1] ( [volume/ch2] )"
  sys.exit(1)

name = sys.argv[1]  # ミキサー項目名
vol = sys.argv[2:4] # 音量のパーセンテージ(0-100)の入ったリスト
# ミキサーオブジェクトの作成
try:
  print 'mixer = alsaaudio.Mixer("%s")' % name
  mixer = alsaaudio.Mixer(name)
except alsaaudio.ALSAAudioError:
  print >> sys.stderr, "Error: No such control: %s" % name
  sys.exit(1)

# (変更前の)音量をチャンネルごとにリストとして取得
# Masterは1ch
oldvol = mixer.getvolume()

# 音量を変更
# setvolume()で0から100以外の値を取ると例外alsaaudio.ALSAAudioErrorが発生
# alsaaudio.ALSAAudioError: Volume must be between 0 and 100
if len(vol) == 1:
  channel = alsaaudio.MIXER_CHANNEL_ALL
  print "mixer.setvolume(%d, alsaaudio.MIXER_CHANNEL_ALL)" % (int(vol[0]))
  mixer.setvolume(int(vol[0]), channel)
else:
  # 各チャンネルの音量を変更
  for i, v in enumerate(vol):
    mixer.setvolume(int(v), i)
    print "mixer.setvolume(%d, %d)" % (int(v), i)

# 変更前後の値を表示
print "%s: %s -> %s" % (name, oldvol, vol)

下は実行例。

(マスターボリュームを60%にする)
$ [mixerset.pyの場所] Master 60
mixer = alsaaudio.Mixer("Master")
mixer.setvolume(60, alsaaudio.MIXER_CHANNEL_ALL)
Master: [ [変更前のMaster値] ] -> ['60']

(PCMの左を60%,右を20%にする)
$ [mixerset.pyの場所] PCM 60 20
mixer = alsaaudio.Mixer("PCM")
mixer.setvolume(60, 0)
mixer.setvolume(20, 1)
PCM: [ [変更前のPCM値(左)], [変更前のPCM値(右)] ] -> ['60', '20']

(範囲外の値を指定してみる)
$ [mixerset.pyの場所] PCM 101
mixer = alsaaudio.Mixer("PCM")
mixer.setvolume(101, alsaaudio.MIXER_CHANNEL_ALL)
Traceback (most recent call last):
  File "[mixerset.pyの場所]", line 36, in <module>
    mixer.setvolume(int(vol[0]), channel)
alsaaudio.ALSAAudioError: Volume must be between 0 and 100

関連記事:

関連URL:

使用したバージョン:

  • Python 2.5.2
  • pyalsaaudio 0.3

*1:カードと番号の対応は/proc/asound/cardsなどで確認できる