Perl Tips: mp3再生
2024/02/23
効果音としてmp3ファイルを再生したい
  • ツール実行の状況を示すのにサウンドを使いたいときがあります。じっと見ているには少し長く、待っている間に他のことをしたい等のケースです。

  • CPANライブラリでmp3操作のモジュールを探しましたが、定番が見つかりません。そこでWindowsで使うこともあり、VBAで馴染みのあるMCI(Multimedia Control Interface)を利用することにしました。Win32::MultiMedia::Mci です。尚、標準moduleではないので、cpanからインストールが必要です。

  • やろうと思っていることは...何か実行中にサウンドを出して、終わったらピンポン/ブーというやつですね。
    • 10秒間 "01 実行.mp3" を非同期再生する。短いサウンドはリピート。
    • 10秒経過後サウンドを止める。
    • (0〜10乱数値>5)がTrueなら "02 パス.mp3"、Falseなら "03 フェイル.mp3" を同期再生

素直にSendStringを使う
  • Win32::MultiMedia::MciにはオブジェクトIFもあるのですが、repeat再生オプションの与え方がわかりませんでした。そのため、今回はmciSndStringに値を渡す
      Win32::MultiMedia::Mci::SendString関数
    を使っています。

  • 記述例を示します。open時にalias記述を積極的に使用しています。

  • 尚、サウンドファイルのファイル名やフォルダパス名に空白を入れているのは検証目的(故意)です。
  • #!perl -w
    use Win32::MultiMedia::Mci (SendString);
    use IO::Handle;
    use strict;
    
    # ==============================================================================
    # メインclosure
    # ==============================================================================
    {
        STDOUT->IO::Handle::autoflush(1); # 画面表示都合によるSTDOUT出力バッファ無効化
      
      # $m_op->{exec}オープン→再生
        SendString('open "sound files\01 実行.mp3" alias exec'); # exec オープン
        SendString('open "sound files\02 パス.mp3" alias pass'); # pass オープン
        SendString('open "sound files\03 フェイル.mp3" alias fail'); # fail オープン
        
        SendString('play exec from 0 repeat'); # exec 非同期再生スタート
      
      # 10秒間再生維持
        print "INF: async playing exec for 10[sec]: ";
        for (my $i=0; $i<10; $i++) {
            print $i; sleep(1); # 1秒wait
        }
        print "\n";
        SendString('stop exec'); # exec 非同期再生ストップ
      
      # 0〜10範囲の乱数の値を見て、5より大きければpassとする
        if (rand(10) > 5) {
            print "INF: random result: pass\n";
            SendString('play pass wait'); # pass同期再生
        } else {
            print "INF: random result: fail\n";
            SendString('play fail wait'); # fail同期再生
        }
    }
    
    >mp3_playback_test_b.pl
    INF: async playing exec for 10[sec]: 0123456789
    INF: random result: fail
    
    >mp3_playback_test_b.pl
    INF: async playing exec for 10[sec]: 0123456789
    INF: random result: pass

SendStringの使い方
  • SendString関数からの引数受け取り先である、mciSendString関数自身のバグ回避目的で、使い方に癖があります

  • コマンドはopen→play→stop→closeが基本。ファイル名直接指定時のバグ回避。
    • SendString('open "サウンドファイル名"')
    • SendString('play "サウンドファイル名"' オプション) ※オプションは後述
    • SendString('stop "サウンドファイル名"')
    • SendString('close "サウンドファイル名"')

  • しかしopenでaliasを使うとplay/stop/closeの自由度が上がる。
    • SendString('open "サウンドファイル名" alias エイリアス名')
    • SendString('play エイリアス名 オプション) ※オプションは後述
    • SendString('stop エイリアス名')
    • SendString('close エイリアス名')

  • playコマンドの代表的オプション: [オプション無し, wait, repeat]
    • オプション無し: 1回の非同期実行(再生終了を待たない)
    • repeat: 繰り返しの非同期実行(再生終了を待たない) [lpszPlayFlags]
      • repeatは[lpszPlayFlags]オプションの一つ。詳しくは[こちら]を参照。
    • wait: 1回の同期実行(再生終了を待つ) [lpszFlags]

  • サウンドファイル名はパスを含めてダブルクォートで囲む ※バグ回避
    • playコマンド以外の動きがおかしくなります。stopできない、切り替えられない等。
    • しかしaliasを使うと回避できます。
2024-02-27: aliasによる不明動作回避を追記に伴いサンプルコードも変更
2024-02-23: 初版
Copyright(C) 2024 Altmo
本HPについて