Visual Basic 6.0 テクニック
VB6対応

 

Visual Basic 中学校 > VB6 テクニック >

1.VBでサウンドを再生する方法

 

ここではVBでサウンドを再生する方法の一つを説明します。

ここで対象となるサウンドとはファイルの拡張子が .mid .wav . mp2 .mp3 の形式である物を指します。

この回の要約
  • サウンドを再生するにはmciSendString関数を使う。
  • mciSendString関数は「MCIコマンド文字列」でサウンドの再生を制御する。
  • 再生する方法

            Call mciSendString("play """ & FILE_NAME & """", "", 0, 0)

  • 他にも長さを取得したり、再生位置を取得・設定したり繰り返し再生したりできる。
  • サンプルがダウンロードできる。

 

1.方法論

 

VBの機能としてはサウンド再生の機能はほとんど提供されていません。一応 Beep や MsgBox で音は鳴らせますが「サウンド」という点からは不満山積です。そこで、この他にVBからサウンドを再生するのにどういう方法があるか表にまとめてみました。

方法 メリット デメリット
APIを使う
  • どの環境でも使用できる。
  • 著作権等の問題がない。
  • プログラムサイズが小さくてすむ。
  • 初心者には難しい。
ActiveXを使う
  • 高機能が簡単に使える。
  • ActiveXがインストールされていなければ使えない。
  • 配布が面倒くさい。
  • 著作権が心配。
DirectXを使う
  • ActiveX以上の高機能
  • DireceXがインストールされていなければ使えない。
  • 難しい。

■表1:VBからサウンドを再生する方法

「DirectXを使う」というのも「ActiveXを使う」の一種なのですがここでは別項目にまとめてみました。念のために確認しておくとActiveXというのはVBの機能を拡張できる便利なソフトのことです。たとえば、Windowsに付属しているMediaPlayerはActiveXとしてVBから使用することもできるのです。

このようなActiveXは店で売っているものもあるし、Webでフリーウェアやシェアウェアとして公開されているものもありますから使いこなせば何かと便利です。サウンド再生機能があるActiveXで有名なものはMediaPlayerの他にMMControlがあります。MMControlはVBのProfessionalEdition以上に付属していますが現在ではあまり使われていないようですね。

今回は、「どの環境でも使用できる」方がこの記事を読んでいる皆さんの役に立てると思いますのでAPIを使う方法を説明します。

 

2.手っ取り早い方法

 

早く結論を知りたい方のために、さっそくサウンドを演奏するサンプルを載せます。

コントロール 種類 機能
Command1 CommandButton サウンドを再生する
Command2 CommandButton サウンドの再生を停止する

■表2

Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long

Private Const FILE_NAME As String = "C:\Test.mp3"
Private Sub Command1_Click()

    Call mciSendString("play """ & FILE_NAME & """", "", 0, 0)

End Sub
Private Sub Command2_Click()

    Call mciSendString("close """ & FILE_NAME & """", "", 0, 0)

End Sub

■サンプル1:サウンドの再生と停止

このサンプルは C:\Test.mp3 を再生・停止します。ここではmp3を指定していますが、wav、mid、mp2を指定しても正しく再生できます。

しかし問題があります。実はこの方法ではmp3が再生できない環境があるのです。私も詳しいことは分からないのですが多分Windows98 + MediaPlayer 6.4より古い環境ではこの方法ではmp3は再生できないでしょう。wavやmid、mp2は再生できます。Windows 2000以上の環境ならば問題ないと思います。古い環境でmp3を再生したい場合はテクニック 第2回を参考にしてください。

 

.使うAPIは一つだけ

 

さて、サンプル1からも分かるように使うAPIはmciSendStringの一つだけです。その宣言は次の通りです。

Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long

■サンプル2:mciSendString関数の宣言

この関数は奥が深いので詳しい説明はMSDN Library等を参照してください。ここではあくまでも簡単にできる範囲のことを説明します。

このAPI関数は第一引数 が最も重要です。この引数だけで再生したり停止したりを指示します。あとの引数はサンプル1では簡単に設定してしまいましたが、後で少しだけ説明します。

 

.工夫する

 

プログラムを分かりやすくするために少し加工してみましょう。mciSendString関数を利用してサウンドファイルを再生する関数と再生を停止する関数を作ってみます。

Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
Private Sub PlaySound(FileName As String)

    Call mciSendString("play """ & FileName & """", "", 0, 0)

End Sub
Private Sub StopSound(FileName As String)

    Call mciSendString("close """ & FileName & """", "", 0, 0)

End Sub

■サンプル3:サウンドの再生と停止

これであなたはmp3, mp2, wav, midを自由に再生したり停止したりできるようになりました。なんて素敵なんでしょう。

 

.でもこれ低機能

 

しかし再生と停止だけできれば良いのでしょうか。もう少し欲張っていろいろな機能をつけてみたいと思いませんか。mciSendString関数を使えばもっといろいろなことができるし、実際そのうちのいくつかはとても簡単です。

たとえば一時停止する機能を追加するには次のような関数をつくるだけです。

Private Sub PauseSound(FileName As String)

    Call mciSendString("pause """ & FileName & """", "", 0, 0)

End Sub

■サンプル4:サウンドの一時停止

続きから再生するにはmp3の場合、前のサンプル3にあるPlaySound関数を実行するだけなのですがwavの場合にはPlaySound関数を実行するとまた最初からになってしまいます。どうしてこんな違いがあるのかはわかりません。

正式には続きから生成するには次のようにするらしく、この方法ならmp3でもwavでもいけます。

Private Sub ResumeSound(FileName As String)

    Call mciSendString("resume """ & FileName & """", "", 0, 0)

End Sub

■サンプル5:一時停止の続きから再生

とことで、再生・停止・一時停止・続きから再生のどれもほとんどプログラムは一緒ですよね。違うのはmciSendString関数の第1引数だけです。

ここまで理解するとmciSendString関数の第1引数、つまりMCIコマンド文字列が重要だということがわかってくると思います。何をするにもMCIコマンド文字列を使わなければなりません。

MCIコマンド文字列情報は以下のサイトにあります。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_multimedia_command_strings.asp

しかし難解です。英語で書いてあるうえにある程度マルチメディアとC++の知識がなければ理解できません。だいたいこれを読んで分かる人はこのページの説明を読む必要はありません。

次からは私がこのサイトから解読できたいくつかの機能を説明しましょう。

 

.時間を取得する

 

音楽の長さを時間単位で取得する方法を説明しましょう。もちろんMCIコマンド文字列を使うのですが今までとの大きな違いは、「取得する」という点です。今までの再生・停止・一時停止は命令したらしっぱなしでこちらが情報を取得することはありませんでした。

情報を取得するにはmciSendString関数の第2、第3引数を使います。ここでもこれらを呼び出しやすいように次のような関数にまとめてみましょう。

'■ファイルの長さを秒単位で返す。
Private Function GetLength(FileName As String) As Double

    Dim RetBuffer As String * 20
    Dim MCICommandString As String

    MCICommandString = "status """ & FileName & """ length"

    Call mciSendString("open """ & FileName & """", "", 0, 0)
    Call mciSendString(MCICommandString, RetBuffer, Len(RetBuffer), 0)
    Call mciSendString("close """ & FileName & """", "", 0, 0)

    GetLength = Val(RetBuffer) / 1000

End Function

■サンプル6:長さの取得

このように情報を要求した場合、mciSendString関数は第2引数に回答を返してきます。また第3引数には第2引数の長さを渡しておく必要があります。

そして、ファイルの長さを取得するためのMCIコマンド文字列は 「status ファイル名 length」というわけです。 また開いていないファイルの長さは取得できない場合があるので長さを取得する前後にopencloseも入れています。

こうやって説明しているとあまり難しく思えないかもしれませんが、上記のリンクからこの情報を見つけ出すのはちょっと骨が折れました。

ところで実はこの関数には問題があります。対象がmp3やwavの時には正しく長さを取得できるのですがmidの時にはどうも妙な値が返ってきてしまいます。

いろいろ考えたのですがどうもよくわかりません。midの場合には別にテンポの取得して、計算しなければいけないのだと思います。テンポを取得するにはMCIコマンド文字列に「status ファイル名 tempo」と記述します。midの長さの取得方法が分かる方は是非教えてください。

 

.現在位置を取得する

 

再生中に現在再生中の位置を取得するにはMCIコマンド文字列に「status ファイル名 position」を指定します。

これを利用して再生中のファイルの現在位置を取得するコードは次のようになります。

'■再生中のファイルの位置を秒単位で返す。
Private Function GetPosition(FileName As String) As Double

    Dim RetBuffer As String * 20
    Dim MCICommandString As String

    MCICommandString = "status """ & FileName & """ position"
    Call mciSendString(MCICommandString, RetBuffer, Len(RetBuffer), 0)

    GetPosition = Val(RetBuffer) / 1000

End Function

■サンプル7:現在位置の取得

MCIコマンド文字列が変わるだけなのでサンプル6(長さの取得)とほとんど同じです。現在位置がわかれば多くのサウンドプレイヤーがやっているように再生に合わせてスライダーを動かしたりできるようになります。

なお、これも開いていないファイルだと失敗することがあるらしいのですが、「現在位置を取得する」という性質上ファイルは既に開かれているはずですのでファイルを開くopenは記述していません。

 

.現在位置をセットする

 

自分で位置をセットして、途中から再生することもできます。これは「seek ファイル名 to 位置」という形でMCIコマンド文字列を指定します。位置はミリ秒単位の数値で指定します。なお、seekを使用すると再生中のサウンドは停止してしまいますので、seek後にもう一度playを使います。

'■再生位置を秒単位で指定する。
Private Sub SetPosition(FileName As String, Position As Double)

    Dim NewPosition As Long

    NewPosition = Position * 1000

    Call mciSendString("seek """ & FileName & """ to " & NewPosition, "", 0, 0)
    Call mciSendString("play """ & FileName & """", "", 0, 0)

End Sub

■サンプル8:再生位置の指定

 

9.繰り返し再生

 

私の調べた範囲ではMCIコマンド文字列を使って繰り返し再生を指示することはできません。しかし、自分でプログラムすることで繰り返し再生を実現することができます。

繰り返し再生とは、「もし、再生が終了しているなら、初めに戻って、再生せよ。」ということなので現在「再生中」 なのか「停止中」なのか判断できれば自分で繰り返して再生するように命令することができるということです。

そして現在の状態はMCIコマンド文字列を使って「status ファイル名 mode」のようにすることで取得できます。このコマンドを使用すると、mciSendString関数は第2引数に、再生中のとき"Playing"、停止中のとき"Stopped"、一時停止中のとき"Paused"を返してきます。この他にも"not ready"(準備が完了していない?)、"open"(開いている?), "parked"(停止している?), "recording"(録音中?),  "seeking"(探索中?)などの値が用意されているようですが、私はであったことがないので詳細はわかりません。

以上を踏まえて「まず、現在の状態を返す関数を作って、タイマーで定期的にそれを呼び出し、現在の状態が停止中ならもう一度再生させる」という流れで繰り返し再生を実現させましょう。プログラムは次のようになります。

Private Const FILE_NAME As String = "C:\Test.mp3"

Private Sub Command1_Click()

    Call PlaySound(FILE_NAME)

    Timer1.Interval = 100

    Timer1.Enabled = True

End Sub

Private Sub Timer1_Timer()

    If GetSoundStatus(FILE_NAME) = "STOPPED" Then

        Call StopSound(FILE_NAME)

        Call PlaySound(FILE_NAME)

    End If

End Sub

Private Function GetSoundStatus(ByVal FileName As String) As String

    Dim RetBuffer As String

    Dim MCICommandString As String

    RetBuffer = Space(20)

    MCICommandString = "status """ & FileName & """ mode"

    Call mciSendString(MCICommandString, RetBuffer, Len(RetBuffer), 0)

    RetBuffer = Left(RetBuffer, InStr(1, RetBuffer, vbNullChar) - 1)

    GetSoundStatus = UCase(RetBuffer)

End Function

■サンプル9:繰り返し再生

 

10.最後に

 

以上説明してきた技術を使って簡単なサウンドプレイヤーのサンプルを作ってみました。よろしかったらダウンロードしてみてください。

ダウンロード    4.0KB     lha形式(拡張子はlzh)

主な機能:再生、一時停止、一時停止の続きから再生、停止、長さの取得、現在位置の取得、再生位置の指定、繰り返し再生、状態の取得

このプレイヤーではmp3、wav、mid、mp2の再生の制御ができますがはっきりいってWindows Media Playerに比べたら天と地です。それにmidとmp2は一部の機能が利用できません。あくまでプログラムする参考のためのものと思ってください。そのためユーザーインターフェイスまわりはあまり細かい点に気を配っていません。

ところで、この第1回は何年か前に一度書いたのを今回久しぶりに全面改訂したものです。同時は私はWindows98 + Media Player 6.4でしたが、今はWindows XP + Media Player 9 です。そして、改訂前このページの最後にはこう書いていてありました。

「実はこのAPIではMP3を再生できません。(Windowsのバージョンがあがればできるようになると期待しますが)。」

期待があたって今ではMp3も再生できるようになりましたね。うれしい限りです。これからも科学の発展は私たちの夢をかなえてくれるでしょう。

 

今回の重要単語

重要単語 読み方 説明
close クローズ MCIコマンド文字列の一つ。ファイルを閉じて再生を終了する。
length レンクス MCIコマンド文字列の一つ。statusとともに用いファイルの長さを取得する。
mciSendString エムシーアイセンドストリング サウンドをはじめ映像などのメディアファイルを制御するためのWindows API関数。MCIコマンド文字列を使ってメディアを制御する。
mode モード MCIコマンド文字列の一つ。statusとともに用いファイルの状態を取得する。
open オープン MCIコマンド文字列の一つ。ファイルを開く。
pause ポーズ MCIコマンド文字列の一つ。ファイルを一時停止する。
play プレイ MCIコマンド文字列の一つ。ファイルを再生する。
position ポジション MCIコマンド文字列の一つ。statusとともに用いファイルの現在位置を取得する。
resume リジューム MCIコマンド文字列の一つ。一時停止状態から再生を続行する。
seek シーク MCIコマンド文字列の一つ。ファイルを再生位置を指定する。
status ステータス MCIコマンド文字列の一つ。ファイルに関する情報を取得する。
MCIコマンド文字列 エムシーアイコマンドもじれつ マルチメディアを制御するためのスクリプト?マルティメディアコマンド文字列ともいうらしい。

詳細は次のページ

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_multimedia_command_strings.asp

■表3:今回の重要単語