Skip to content

Latest commit

 

History

History
274 lines (146 loc) · 23.3 KB

06_Play_Audio_File.md

File metadata and controls

274 lines (146 loc) · 23.3 KB

オーディオファイルを再生する

本節では、Blenderが提供するオーディオファイルの再生支援モジュールであるaudモジュールを使って、オーディオファイルを再生する方法を説明します。
そもそも、3DCGを作成するBlenderでオーディオファイルを扱うことに疑問があると思いますが、このようなAPIも用意されているのだという気持ちで本節を読んでもらえればと思います。

作成するアドオンの仕様

オーディオの再生方法と再生中のオーディオ設定を変更する方法を理解するため、次の機能を持つアドオンを作成します。

  • 3Dビュー エリアのツール・シェルフに オーディオ再生 タブを追加し、選択したオーディオファイルを再生するボタンを配置する
  • 再生中の音量をユーザが変更できるUIを提供する

アドオンを作成する

1-5節を参考にして以下のソースコードを入力し、ファイル名 sample_3_6.py として保存してください。

import

アドオンを使用する

アドオンを有効化する

1-5節を参考に作成したアドオンを有効化すると、コンソールウィンドウに以下の文字列が出力されます。

サンプル3-6: アドオン「サンプル3-6」が有効化されました。
3Dビュー エリアのツール・シェルフを表示し、オーディオ再生 タブが追加されていることを確認します。 3-6節 アドオン有効化

アドオンの機能を使用する

有効化したアドオンの機能を使い、動作を確認します。

Work
1
3Dビュー エリアのツール・シェルフから、オーディオ再生 タブを選択します。 3-6節 アドオンの使用 手順1

2
オーディオファイルを選択 ボタンをクリックします。 3-6節 アドオンの使用 手順2

3
ファイルブラウザが開くため、再生するオーディオファイルを選択して オーディオファイルの選択 ボタンをクリックします。本節のサンプルでは、デフォルトで.wavと.mp3の2つの拡張子に絞って表示していますが、ファイルのフィルタリングを有効化ボタン をクリックすることで、他のファイルも選択できるようになります。
※右図では空のディレクトリを表示しています。
3-6節 アドオンの使用 手順3

4
音量 の値を変更することで、オーディオの再生音量を変更することができます。 3-6節 アドオンの使用 手順4

5
停止 ボタンをクリックすることで、オーディオの再生を停止することができます。 3-6節 アドオンの使用 手順5

アドオンを無効化する

1-5節を参考にして有効化したアドオンを無効化すると、コンソールウィンドウに以下の文字列が出力されます。

サンプル3-6: アドオン「サンプル3-6」が無効化されました。

ソースコードの解説

本節までに説明した内容は省略し、オーディオファイルの再生に関することを中心に説明します。サンプルのソースコードに関して、ポイントとなる点を次に示します。

  • オーディオファイルの再生、再生停止方法
  • プロパティの変更を検知する方法

audモジュールのインポート

Blenderは aud モジュールと呼ばれる、オーディオファイルを扱うためのモジュールを提供しています。オーディオファイルを扱うためには、この aud モジュールをインポートする必要があります。

import:"import_aud", unindent:"true"

アドオン内で利用するプロパティを定義する

複数のクラス間で共有するプロパティを次に示します。

変数 意味
paf_volume オーディオの再生音量

また本節のサンプルでは、オーディオ再生で使う次のような変数を AudioDevice クラスのクラス変数としてまとめています。bpy.types.Scene に保存せずにクラス変数としてアクセスするのは、後述するオーディオファイルの音量調整を再生中に行うためです。

クラス変数 意味
device サウンドデバイス
factory サウンドファクトリ
handle サウンドハンドラ

聞き慣れない用語がたくさん出てきましたが、サンプルのソースコードの解説の中で説明しますので、ここでは特に深く考えずに AudioDevice クラスにはオーディオ再生に必要なクラス変数が含まれている、ということだけを理解しておいてください。

オーディオファイルの選択

オーディオファイルを再生する処理を説明する前に、再生するオーディオファイルを選択する処理について解説します。オーディオファイルの選択処理に関するオペレーションクラスは、SelectAudioFile です。2-10節で説明したファイルブラウザを表示するための処理と基本的に同じですが、2点異なるところがあります。

1つ目は、ファイル選択時に呼び出される execute() メソッドの処理です。本節のサンプルでは、ファイルを開いた後にオーディオファイルを再生する処理を行います。2-10節で宣言していたクラス変数 filenamedirectoryexecute() メソッドでは利用していないため、宣言していません。

2つ目は、ファイルブラウザを開いた時に表示されるファイルが、wavファイルとmp3のファイルのみであることです。

import:"filter_glob", unindent:"true"

特定のファイルのみをファイルブラウザで表示する場合は、filter_glob クラス変数を StringProperty クラスで定義し、表示するファイルのリストを引数 default; (セミコロン)区切りで指定します。また、必要に応じて正規表現を使うこともできます。本節のサンプルではwavファイルとmp3ファイル(それぞれ .wav.mp3 の拡張子を持つファイル)を表示するため、*.wav; *.mp3 を指定しています。

StringProperty クラスの引数 options{'HIDDEN'} を指定していますが、これは、ファイルブラウザ エリアのツール・シェルフのオプションに filter_glob の項目が表示されないようにするためです。試しに、引数 options{'HIDDEN'} を指定しないようにソースコードを書き換えて保存し、オーディオファイルの選択 ボタンをクリックしてファイルブラウザを開いてみましょう。ツール・シェルフのオプションに filter_glob の項目が表示されるはずです。

オーディオファイルの再生

ファイルブラウザで選択したオーディオファイルの再生処理について説明します。オーディオファイルの再生処理は次の手順に従って行います。

  1. サウンドデバイスの作成
  2. サウンドファクトリの作成
  3. サウンドハンドラの作成(オーディオファイルの再生)

ここでサウンドデバイス、サウンドファクトリ、サウンドハンドラという3つの用語が出てきましたので、簡単に説明します。サウンドデバイスは、OpenALやSDLなどのサウンドライブラリで扱うデバイスのことを指し、オーディオを再生するために最低限必要なものです。サウンドデバイスがないとそもそも音を出すことができません。サウンドファクトリは、複数の音源をミックスしたり、ハイパスフィルター(HPF)やローパスフィルター(LPF)などのエフェクトをかけたりする時に必要なオブジェクトです。出力サウンドを編集する時に使うことができますが、Blenderはあくまで3DCGソフトなので本節のサンプルではこれらの機能を使っていません。サウンドハンドラは、再生/停止/一時停止/再生再開といった再生制御や、ピッチやボリュームなどの再生時の振る舞いを変更するためのオブジェクトです。

ファイルブラウザでファイルを選択すると、SelectAudioFile クラスの execute() メソッドが実行され、選択したオーディオファイルが再生されます。それでは、オーディオファイルを再生するための具体的なコードを見てみましょう。

import:"select_audio_file_execute", unindent:"true"

1. サウンドデバイスの作成

オーディオファイルの再生処理手順に従い、最初にサウンドデバイスを作成します。サウンドデバイスは、aud.device() 関数を呼び出すことで作成することができます。サウンドデバイスは一度作成したあとは、再生するオーディオファイルを変更しても再度作り直す必要がないため、サンプルでは最初に作成したサウンドデバイスを使いまわしています。このため、再生停止後にオーディオを再度再生した場合、すでにサウンドデバイスが作られていたら、新たにサウンドデバイスを作成しないような処理となっています。aud.device() 関数の戻り値は、AudioDevice.device に代入します。

2. サウンドファクトリの作成

サウンドファクトリは、aud.Factory() 関数を実行することで作成することができます。aud.Factory() 関数は、再生するオーディオファイルのパスを引数に指定します。サウンドデバイスと異なり、サウンドファクトリは再生するオーディオファイルを変更するたびに作成し直す必要があります。aud.Factory() 関数の戻り値は、AudioDevice.factory に代入します。

3. サウンドハンドラの作成(オーディオファイルの再生)

サウンドファクトリ AudioDevice.factory を、サウンドデバイスAudioDevice.deviceplay() メソッドの引数に指定することで、サウンドハンドラが作成されてオーディオファイルが再生されます。作成したサウンドハンドラは AudioDevice.handle に代入します。

最後に、オーディオファイル再生時の音量を設定するために、AudioDevice.handle のメンバ変数である volume音量 プロパティに指定された値 sc.paf_volume を代入します。本節のサンプルでは、音量を調整できる AudioDevice.handle のメンバ変数 volume しか利用していませんが、AudioDevice.handle は次のようなメンバ変数を提供しています。

メンバ変数 意味
volume 音量(最大1、最小0)
pitch ピッチ(最小0)
loop_count ループ回数(ループ回数を指定、ループ回数が0なら1回限りの再生、負の値なら無限ループ再生)
position 再生位置(単位は秒)
status 再生状態

オーディオファイルの再生停止

停止 ボタンが押された時は StopAudioFile クラスの execute() メソッドが呼び出され、オーディオファイルの再生を停止する処理が実行されます。

import:"stop_audio_file", unindent:"true"

サウンドハンドラである AudioDevice.handle は、再生状態を制御するための次のような関数を用意しています。サンプルでは、オーディオファイルの再生を停止するために AudioDevice.handle.stop() 関数利用します。

関数 意味
stop() オーディオファイルの再生停止
pause() オーディオファイルの再生一時停止
resume() オーディオファイルの再生再開

オーディオファイルの再生状態

本節のサンプルでは、オーディオファイルの再生状態に応じてUIを変更する処理が、パネルクラス VIEW3D_PT_PlayAudioFileMenudraw() メソッドに存在します。オーディオが再生停止中の場合には オーディオファイルを選択 ボタンを表示し、再生中の場合には 停止 ボタンを表示します。

import:"check_play_status", unindent:"true"

オーディオファイルの再生状態に応じてUIを変更するために、オーディオファイルの再生状態を知る必要があります。オーディオファイルの再生状態は AudioDevice.handle.status の値から判断できるため、AudioDevice.handle.status の値に応じて表示するUIを決定します。AudioDevice.handle.status は次に示すようにブーリアンの値が代入されます。

意味
True オーディオファイルを再生中、または再生一時停止中(AudioDevice.handle.pause() が呼ばれた)
False オーディオファイルを再生停止(AudioDevice.handle.stop() が呼ばれた)、または最後まで再生完了

AudioDevice.handle.statusTrue であればオーディオファイルを再生中であるため、停止 ボタンを表示します。一方、False であれば再生停止中であるため、オーディオファイルを選択 ボタンを表示します。なお、AudioDevice.handleNone の場合は、オーディオファイルを選択 ボタンを表示しています。この条件判定がないと、if AudioDevice.handle.status: 条件判定で、「AudioDevice.handleNoneType だから status というメンバ変数はない」とエラーが発生してしまい、UIの表示処理が中断してしまいます。

プロパティ変更の検知

サンプルでは、3Dビュー エリアのツール・シェルフのタブ オーディオ再生音量 プロパティからユーザが音量を変更したことを検知し、再生音量を変更しています。ここまで読み進めてきた方は、どのようにこのような処理を実現するのか疑問に思うかもしれません。これまでプロパティを利用した処理としては、2-3節で示したプロパティ値の設定直後に同じ処理を再実行する場合と、3-4節で示したプロパティの値をユーザが設定した後に処理を行う場合の2通りであったため、プロパティが変更されたことを検知する必要がありませんでした。しかし本節のサンプルでは、一度オーディオファイルの再生を開始したあとは、オーディオファイルの再生処理がアドオンの処理とは非同期に行われることになります。つまり、プロパティの値を参照した後に処理を行うこれまでの方法ではうまくいきません。

本節のサンプルのように、プロパティの値が変わったことを検知して独自の処理を行いたい場合は、プロパティクラスの引数 setget に、実行したい関数をプロパティクラス作成時に登録します。引数 set には、プロパティの値が変更された時に呼び出す関数を指定し、引数 get にはプロパティの値を参照するときに呼び出す関数を指定します。サンプルのプロパティの定義を見てみましょう。

import:"prop_volume", unindent:"true"

プロパティクラス FloatProperty の引数 getget_volume() 関数、引数 setset_volume() 関数を指定しています。最初に、get_volume() 関数について説明します。

import:"get_volume", unindent:"true"

get_volume() 関数は、第1引数に bpy.context.scene が指定された状態で呼び出されます。bpy.type.Scenebpy.context.scene は同一です。このため、init_props() 関数で bpy.type.Scene にプロパティクラスを登録すると、プロパティクラスを登録した変数へは bpy.context.scene['paf_volume'] つまり self['paf_volume'] としてアクセスすることができます。

get_volume() 関数は、プロパティを参照する時に呼び出されるため、予期しない時に呼び出される可能性があります。このため、get_volume() 関数が呼び出されるタイミングによっては、参照したい変数が存在しないかもしれません。例えば、init_props() 関数が呼ばれていないために、sc.paf_volume が作られていない場合が考えられます。そこで、self.get() メソッドの第2引数にデフォルト値を指定し、第1引数に指定したインスタンス変数が存在しない場合は、デフォルト値を返すようにします。

続いて、set_volume() 関数について説明します。set_volume() 関数は、第1引数に bpy.context.scene、ユーザがプロパティに設定した値が第2引数に渡されて呼び出されます。

import:"set_volume", unindent:"true"

set_volume() 関数は、self['paf_volume'] = value によりプロパティの値を更新した後、AudioDevice.handle.volume に値を設定することで音量を変更します。このような一連の処理を行うことで、ユーザが 音量 プロパティを変更したことを検知し、オーディオファイルの再生音量を変更することができます。

なお、bpy.type.Scene に登録したプロパティクラス以外のクラスは、引数 getset に指定した関数からアクセスすることができません。プロパティクラス以外のクラスにアクセスするためには、アクセス対象がグローバル変数やクラス変数である必要があります。アドオン内で共通利用するプロパティを、AudioDevice クラスのクラス変数に定義したのはこのためです。

まとめ

Blenderのaudモジュールを使って、オーディオファイルを再生する方法を説明しました。筆者がaudモジュールの存在を初めて知ったとき、3DCGソフトであるBlenderにオーディオファイルを扱うAPIがなぜ存在しているのが理解できず、本書の話題として取り上げるか迷いました。しかし、4-1節で紹介する公式のAPIリファレンスを参照していただければわかると思いますが、audモジュールはStandaloneモジュールに含まれています。このため、ここでaudモジュールについて取り上げることが少し場違いであることを承知のうえで、ここで説明しました。ただやはりaudモジュールは音を扱うため、ゲームエンジン関連のカテゴリであるGame Engine Modulesに含めたほうが理にかなっている気がします。筆者の憶測ですが、動画作成時にオーディオファイルを再生することを考えてゲームエンジンだけに限定しなかったのかもしれません。

本節のサンプルではオーディオファイルの再生/停止の処理に加え、ユーザが変更した音量を検知する方法やファイルブラウザで表示するファイルをフィルタリングする方法を説明しました。audモジュールはマイナーで機能が少ないモジュールのように見えますが、ローパスフィルターやハイパスフィルター、ミックスなどサウンドプログラミングをする上で基本的な機能がAPIとして提供されています。扱いも比較的簡単であるため、ぜひこの機会にBlenderでサウンドプログラミングに挑戦してみてはいかがでしょうか。

ポイント

  • オーディオファイルをアドオンで扱うためには、audモジュールをインポートする必要がある
  • サウンドデバイスはサウンドを出力するために必要な、低レベルのサウンド再生デバイスである
  • サウンドファクトリはオーディオファイルのデータにエフェクトをかけたりミックスしたりするために使うオブジェクトである
  • サウンドハンドラはオーディオの再生制御を行うだけでなく、オーディオ再生の設定(音量やピッチなど)を参照/変更することができる
  • プロパティクラスの値が参照されたときに処理を実行したい場合は、プロパティクラスの作成時の引数 get 、更新されたときに処理を実行したい場合は、プロパティクラスの作成時の引数 set に実行したい関数を指定する