チャートが指定した価格になった場合や、インジケーターが特定の状態になった場合に音を鳴らしたい、という時があると思います。
MQLでは、PlaySound関数を使って簡単に指定の音を鳴らすことができます。PlaySound関数で音を鳴らすには音声ファイルを指定するのですが、そのパスの指定方法がひとクセあるので、いざ使うときに時間をとられないようにクセを克服しておきましょう。
PlaySound関数
まずはPlaySound関数の引数と戻り値を確認しておきましょう。
1 2 3 |
bool PlaySound( string filename // file name ); |
- filename
音声ファイルへのパスを指定します。NULLを指定した場合は、再生中の音を停止します。
戻り値は、音声ファイルが見つかればtrue、それ以外はfalseを返します。
これ以上無いというくらい簡単なパラメータですが、注意点が3点ありますので”MQL4 Reference“から原文のまま抜粋します。
Note
The file must be located in terminal_directory\Sounds or its sub-directory. Only WAV files are played.
Call of PlaySound() with NULL parameter stops playback.
PlaySound() function does not work in the Strategy Tester.
つまり、わかりやすく意訳すると以下のようなことが書いてあります。
|
3番目は上で説明しましたので省略します。また、4番目はストラテジーテスター、つまりバックテストなどのときは動作しないということを言っています。
PlaySound関数にクセがあるといったのは、1番目のファイルパスに関してです。
音声ファイルのパス
先に結論を書いておきますが、「terminal_directory」とはMetaTraderがインストールされているパスです(例えば、C:¥Program Files(x86)¥MT4¥など)。PlaySound関数は、ここに置いてある音声ファイルのみを再生することができます。
私は、この説明のterminal_directoryの次にある「Sounds」という単語を見て、勝手にデータフォルダのSoundsだと勘違いしました。
(C:¥Users¥YOU¥AppData¥Roaming¥MetaQuotes¥Terminal¥xxxxxxx¥MQL4¥Soundsなど)
この勘違いまっただ中のときに書いた、音声を再生するサンプルコードを載せておきます。
1 2 3 4 5 6 7 8 9 |
#property version "1.00" #property strict #property indicator_chart_window int OnInit() { PlaySound("sample.wav"); return(INIT_SUCCEEDED); } |
初期化のタイミング、インジケーターを挿入した後に表示されるダイアログボックスでOKを押すと、”sample.wav”という音声ファイルを再生するだけです。
私はこの”sample.wav”というファイルをデータフォルダのSounds配下において、このインジケーターを実行しました。もちろん再生されません。
ここから原因がわかるまでかなりハマりました。ありとあらゆるフォルダに音声ファイルを移動しては実行を繰り返し、PlaySound関数にあらゆるパスの書き方をためしたり。ちなみにフルパスで書いても再生されません。
1時間くらい悩んだときに、PlaySound関数のリファレンスに書いてある”terminal_directory”にあらためて目がとまりました。気になり調べてみると、MetaTraderの各種ターミナル情報を取得するTerminalInfoString関数を使うと、”terminal_directory”のパスが具体的に得られるということがわかりました。
そこで、以下のようにプログラムを書き換え実行してみました。
1 2 3 4 5 6 7 8 |
int OnInit() { bool retVal; Print("Terminal Path = " + TerminalInfoString(TERMINAL_PATH)); retVal = PlaySound("sample.wav"); Print("Return Value1 = " + retVal); } |
ターミナルパスとPlaySound関数の戻り値を、ログに出力してみました。
このログを見て思わずなんだよ!と叫んでしまいました。
勝手に思い込んでいた自分が悪いのですが、”terminal_directory”はMetaTraderがインストールされているパス(①)だったわけです。
当然ですが、音声は再生されていないのでPlaySound関数の戻り値はfalseになっています(②)。
そこで、sample.wavを置くためにエクスプローラーで”terminal_directory”以下にあるSoundsフォルダを開いてみました。
う・・・、なんかすでにたくさんWAVEファイルが置いてある。
ためしにすでにおいてあるWAVEファイルをダブルクリックして再生してみました。どれもこれもMetaTraderを操作中に聞いたことのある音ばかり。とりあえず、ここに音声ファイルを置けばPlaySound関数は再生してくれるはずだろうということがわかりました。しかし、自分で用意したsample.wavをこのフォルダにコピーしようとすると、「管理者のアクセス許可が必要」というダイアログが表示されます(無理矢理置くことはできますが、ひとまずやめておきました)。
ここにきてPlaySound関数の素性というか、MetaQuote社がどういう狙いでこういう仕様にしたのかがわかってきました。
基本的にPlaySound関数は、MetaTraderがインストールされたときに最初から入っている音声ファイルを再生する仕様である、ということです。
じゃあ、自分で用意した音声ファイルは再生するためには、管理者アクセスが必要なフォルダにファイルを無理矢理置く必要があるのでしょうか?
答えはNOです。それでも解決することは可能ですが、オリジナルの音声ファイルを再生するEAやインジケーターを広く配布する場合に、インストールのハードルがあがってしまい結果音がならないという不具合につながります。
オリジナルの音声ファイルを再生する方法
こちらも先に結論を書いておきます。
オリジナルの音声ファイルを再生するには、データフォルダの「Sounds」に音声ファイルを置いてパスの書き方を一工夫する必要があります。
1 2 3 4 5 6 7 8 9 |
int OnInit() { bool retVal; retVal = PlaySound("¥¥Sounds¥¥sample.wav"); Print("Return Value2 = " + retVal); return(INIT_SUCCEEDED); } |
データフォルダの「Sounds」のパスを指定する場合は、”¥¥Sounds¥¥sample.wav”という風に書きます。なんで冒頭に”¥¥”と書くのかはよくわかりませんが、そういう仕様なのでこういうものだと思うことにしましょう。
これで一件落着・・・・ではありません。
もう1つ課題が残っています。
実行ファイルにリソースを埋め込む
“terminal_directory”のファイルを再生するときにちらっと言及しましたが、指定のフォルダにファイルを配置してそれを再生する仕様にすると、インジケーターをインストールするユーザーが音声ファイルを適切な位置に置く必要があります。決してわかりやすいとは言えないこのパスに、ファイルを置けというのはなかなか酷なものです。インストーラーを作るわけにもいかないので結局音がならないという不具合につながります。
前章の書き方では、オリジナルの音声ファイルを再生することはできましたが、このインストール問題は解決していません。
もちろんこの問題にもちゃんと解決策が準備されています、「実行ファイル(.ex4)にリソース(WAVEファイル)を埋め込む」方法です。実行ファイルにWAVEファイルを埋め込んでしまえば、配布するファイル.ex4だけでよく、ユーザーはリソースファイルの存在など全く意識する必要がなくなります。
実行ファイルにリソースを埋め込むには、パスの書き方とリソースの指定方法を一工夫します。
1 2 3 4 5 6 7 8 9 10 11 |
#resource "¥¥Sounds¥¥sample.wav" int OnInit() { bool retVal; retVal = PlaySound("::Sounds¥¥sample.wav"); Print("Return Value2 = " + retVal); return(INIT_SUCCEEDED); } |
リソースを埋め込む場合は、#resourceディレクティブで音声ファイルのありかを指定し、PlaySound関数の引数では”::Sounds¥¥sample.wav”という風に”::”とコロン2つで指定します。
もうそういうモノだと思ってあきらめましょう。
リソースを埋め込む場合に、気をつけないといけないことが1つあります。WAVEファイルが.ex4ファイルに埋め込まれるため、配布するファイルサイズが大きくなる、ということです。
これを解決する根本的な方策はありませんが、WAVEファイルのスペック(サンプリング周波数・ビットレートを低くする、モノラルにするなど)を調整することで軽減することができると思います。
以上で、PlaySound関数をつかった音声ファイルの再生方法の解説は終了です。
たかが音声を再生するわりには、クセが強い仕様になっているという印象を受けます。1回しっかりと仕様を整理しておけば、迷うことはないので暇なときに頭に入れておくとよいと思います。
まとめ
再生したい音声 | ソースの記述方法 |
MetaTrader付属 | PlaySound(“ok.wav”); |
オリジナル (実行ファイルとは別に配布) |
PlaySound(“¥¥Sounds¥¥sample.wav”); |
オリジナル (実行ファイルに埋め込み) |
#resource “¥¥Sounds¥¥sample.wav” PlaySound(“::Sounds¥¥sample.wav”); |
ありがとうございます。PlaySounds関数でハマっていたところでした。MT5 でも同様でした。
全く同じところでハマってました!助かった~(笑)
まあ、データフォルダが分離されていなかった、以前のMT4はexpertフォルダなどど並列にsoundsフォルダを置いていたので、プログラム本体の方のことなのかな?と思いながら検索したのですが、
埋め込み方まで教えていただいて、すごく頭の中がスッキリしました!
お気に入り登録しとこっと!