皆さんはphpで音を鳴らしたいと思ったことがありますか?
私はありません。
いえ、↓こういうのではなく
1 2 3 |
<?php echo "<audio controls src='hoge.mp3'></audio>"; |
イメージ的には↓こういった感じのやつです。
1 2 3 4 5 |
<?php sound_play(); // sound start sound_stop(); // sound stop |
おそらく長い人類史の中でもphpで音を鳴らそうと思った人はけっして多くないでしょう。
その証拠に「php 音」で検索してみると、phpで音は鳴らせないと書く記事やhtmlで音を再生する記事しか出てきません。
しかし、もしあなたが人類史上稀にみる”phpで”音を鳴らすことを望む人ならば、この記事が役立つかもしれません。
今回はphpのopenal関数の紹介です。
openal関数はphpでOpenALを扱うための関数です。
OpenALについて深く理解する必要は今のところありません。PCから音を鳴らすためのライブラリ程度の理解で問題ないです。
OpenALとは
https://openal.org/
https://ja.wikipedia.org/wiki/OpenAL
ドキュメント
https://openal.org/documentation/OpenAL_Programmers_Guide.pdf
OpenALはゲームなど様々なアプリケーションで使用されています。
自分が昔使っていたSFMLという描画ライブラリも音関連の機能はOpenALが使用されていました。
phpのopenal関数ですが、OpenALの主要な機能はおおよそサポートされているので、直接OpenALを扱うのと大差ない程には音を出す感覚が掴めるはずです。
とはいえ、phpで音を鳴らしたところでブラウザでは再生されませんし、Web系の周辺技術としての意義は皆無だと思います。
(何のためにあるんでしょうね、この機能は)
それでは、openal関数を使用するために必要なモジュールをインストールしていきます。
(モジュールの概要はここで公開されています。)
※このモジュールはいくつかの問題により、今のところphp8.0以上では使用できないか、ソースを変更して機能を制限しないとビルドが行えません。(2021/8/30)
※phpのバージョン切り替えツールでphp8.0を使用している場合も同様の問題が起きる可能性があります。
※今回はWSL2(ubuntu20.04)でphp7.4を使用しています。
まず必要なツールなどを用意するために任意のディレクトリで下記のコマンドを実行してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 必要ならば $ sudo apt update # パッケージ管理ツール(Composerのようなもの) $ sudo apt install php-pear # 拡張モジュールのビルドで使用 $ sudo apt install php-dev # OpenAL関連 $ sudo apt install libalut0 $ sudo apt install libalut-dev $ sudo apt install libopenal1 |
次に拡張モジュールのソースと、ビルドに必要なopenalのソースを用意します。
どちらもダウンロードして任意のディレクトリへ配置してください。
git cloneでも問題ありません。
https://github.com/Ponup/php-openal(拡張モジュールのソース)
https://github.com/kcat/openal-soft(ビルドに必要なopenalのソース)
ダウンロードが完了したら、php-openalのディレクトリ(/path/to/php-openal)へ移動してビルドを行います。
1 2 3 4 5 6 7 |
$ phpize $ ./configure --with-openal=/path/to/openal-soft # ダウンロードしたopenal-softのパスを設定 $ make $ sudo make install |
最後にphp.iniの任意の箇所に下記を追記してください。
(他のextensionの記述に近い箇所がおすすめです。)
1 |
extension=openal |
ここまででopenal関数を使う準備が整いました。
ここで少しWSL環境などでopenal関数を使用する際の注意点を書いておきます。
ここまでの手順を踏んだ状態でopenal_device_openという関数を実行しようとすると下記エラーが発生することがあります。
1 2 3 4 5 6 7 8 9 |
ALSA lib confmisc.c:767:(parse_card) cannot find card '0' ALSA lib conf.c:4732:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings ALSA lib conf.c:4732:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory ALSA lib confmisc.c:1246:(snd_func_refer) error evaluating name ALSA lib conf.c:4732:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory ALSA lib conf.c:5220:(snd_config_expand) Evaluate error: No such file or directory ALSA lib pcm.c:2642:(snd_pcm_open_noupdate) Unknown PCM default AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': No such file or directory |
このエラーの一部はサウンドデバイスを見つけることが出来なかった場合に発生するもので、解消するためにはWSLからサウンドデバイスを使用できるようにしなければいけません。
WSLはWindowsが持つサウンドデバイスへのアクセスが出来ないので、PulseAudioを使用するのが一般的のようです。
WSLとWSL2でも設定方法が違い、書いていくと長くなるので自分が参考にしたサイトのリンクを貼っておきます。(WSL2向け)
https://astherier.com/blog/2020/08/wsl2-ubuntu-sound-setting/
これはphp以外の言語で音を出すときにも同様です。
また、オーディオデバイスが正常に認識されているかは下記のコマンドでテストすることが可能です。
1 |
$ aplay /usr/share/sounds/alsa/Noise.wav<br> |
これでphpで音を鳴らす準備が整いました。
ここに単純なノイズを鳴らすための簡単なソースを用意しました。
正常に動作していれば数秒間ホワイトノイズが再生されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php // デバイスを開く $device = openal_device_open(null); $context = openal_context_create($device); openal_context_current($context); // リソースを作成 $source = openal_source_create(); $buffer = openal_buffer_create(); $data = ''; // データ格納用 $hz = 44100; // 周波数 $sec = 5; // 秒数 $length = $hz * 2 * $sec; // 音声のデータ長 // 音声データを作成 for ($i=0; $i < $length; $i++) { $data .= str_pad( rand()%100, 2, 0, STR_PAD_LEFT); } // bufferリソースへ音声データなどをセット openal_buffer_data( $buffer, AL_FORMAT_STEREO16, $data, $hz); // sourceリソースのプロパティをセット openal_source_set($source, AL_BUFFER, $buffer); // bufferリソースをセット openal_source_set($source, AL_LOOPING, true); // ループを有効に設定 openal_source_play($source); // 再生 sleep($sec); // 再生中に処理が止まらないようsleep openal_source_stop($source); // 停止 // デバイスを閉じる openal_context_destroy($context); openal_device_close($device); |
簡単にコメントで説明を書いていますが、詳しい関数の説明は次回に解説できればと思います。
次 => (未定)