例題2-2:wavファイルを鳴らす

A: さて、今回は前回作ったwavファイルをpythonのプログラムから鳴らしてみるぞ。 前回のサンプルプログラムを使ってmono.wavとstereo.wavを作っておくように。用意はいいかな?

B: OKでーす。

A: よっしゃ、これが今回のサンプルだ。

B: おお、まるで例題1-1のような短さ。

  • 行番号なしのソースファイルをダウンロード→ 02-2.py

 1#!/usr/bin/env python
 2# -*- coding:shift_jis -*-
 3import pygame.time
 4import pygame.mixer
 5
 6pygame.mixer.init()
 7
 8monoSound = pygame.mixer.Sound('mono.wav')
 9stereoSound = pygame.mixer.Sound('stereo.wav')
10
11monoSound.play()
12while pygame.mixer.get_busy():
13    pass
14
15pygame.time.wait(1000)
16
17stereoSound.play()
18while pygame.mixer.get_busy():
19    pass

A: 解説もすぐ済むぞ。まず3~4行目でpygame.timeとpygame.mixerというモジュールをimportする。 pygame.timeは時間制御用のモジュールで、リーディングスパンテストの時に使ったtimeを使ってもいい。今回はなんとなくpygame.time。

B: 適当だなあ。

A: pygame.mixerが今回のポイントだ。これはずばり、音声ファイルを読み込んで鳴らすためのモジュールだ。 使用する前にかならず6行目のようにpygame.mixer.init()を呼び出して初期化する。pygame.mixer.init()に引数を与えるといろいろ設定できるんだが、このように 引数なしで呼び出すと、デフォルト値を使って初期化してくれる。

B: ふむふむ。

A: 続いて、pygame.mixer.Sound()という関数を使って、pygame.mixerのSoundクラスのインスタンスを生成する。 イメージとしては、引数に指定した音が鳴る楽器をひとつ用意すると思ってほしい。

B: 楽器?

A: そう。pygame.mixer.Sound()で生成したインスタンスのplay()関数を実行すると、音が鳴る。 複数の楽器を用意すると、複数の音を重ねて鳴らせる。

B:

A: かえって分かりにくかったかな? とにかく、8行目から9行目でmonoSoundという変数にmono.wavの音がなるインスタンス、 stereoSoundという変数にstereo.wavの音が鳴るインスタンスを格納している。11行目でmonoSoundのplay()関数を呼び出して、音を鳴らしている。 12行目のpygame.mixer.get_busy()はpygame.mixerの音が何か鳴っていればTrue、何もなっていなければFalseを返す。ここではpygame.mixer.get_busy()の戻り値をwhileの条件式にすることによって、 音が鳴り終わるまで待ってるわけだ。

B: whileループで実行しているpassって何ですか?

A: passは「何もしない」という機能を持つ。音が鳴っている間、 何もしないということをする 。すなわち何もしないと言う事だ。

B: なんかからかわれているような気がするんですが、要するに何もしないんですね?

A: そう。何もしない。

B: …。

A: まだ腑に落ちない顔をしてるな。先へ進むぞ。11行目で鳴らした音が鳴り止めば、12~13行目のwhileを抜ける。 15行目のpygame.time.wait()は引数に指定された時間だけ待つ関数だ。VisionEgg.time_func()と違ってミリ秒で指定しないといけないんで間違えないように。ここでは1000ms、つまり1秒待つ。

B: なんでVisionEgg.time_func()を使わないんですか?

A: VisionEgg.time_func()を使うとさらにwhileで待ちループを書かないといけないだろ。pygame.time.wait()なら1行で済む。

B: じゃあリーディングスパンテストの時もpygame.time.wait()を使えばよかったじゃないですか!

A: あー。あの時はまずwhileの使い方を覚えるという目的があったからな。さらに言うと、PCに「待つ」という事をさせている時に PCは何をしているのかっていう具体的なイメージを持つ、待ちながら何かをする方法を覚えるっていう目的もあった。行き当たりばったりのように見えるかも知れないけどちょっとは考えているのだよ。

B: へー。

A: どうだ。見直したか。解説に戻ると、15行目で1秒待って、17行目からstereo.wavを鳴らしている。鳴らし終わったら終了。おしまい。

B: おお、予告通り解説短かったですね。

A: まあ、ほとんど中身ないからな。最後にちょっと応用問題。12~13行目のwhileループを削除して、pygame.time.wait()の引数を100くらいにしたらどうなると思う?

B: えっと、音が鳴り止む前に処理が進んで、0.1秒待ってstereo.wavの音が鳴って…。

A: 二つのwavファイルは1秒あるんだから…?

B: あぁ! mono.wavが鳴り止む前にstereo.wavが鳴り始める、ですか?

A: そう。mono.wavとstereo.wavが別々の「楽器」だから、こういう具合に重ねて鳴らせるわけだ。

B: さっき「楽器をひとつ用意する」って言ってたのはそういうことですか。さっきの説明じゃ全然わかんないです。

A: そうか。いい説明かな?と思ったんだが。まあ、何にしてもこれでpythonのプログラムの中からwavファイルを鳴らせる。 キー押しに連動させたかったら、リーディングスパンテストの時にやったようにキー押しのイベントが発生したらplay()関数を呼べばいいわけだ。いい練習問題になるからぜひ挑戦してみるといいよ。 じゃあ今回の解説はここまで。