PySide (Qt for Python) は、Qt(キュート)の Python バインディングで、GUI などを構築するためのクロスプラットフォームなライブラリです。Linux/X11, macOS および Microsoft Windows をサポートしています。配布ライセンスは LGPL で公開されています。
Wikipedia によると、wav を拡張子に持つファイルは、Microsoft とIBM により開発された RIFF waveform Audio Format (WAV) という音声ファイルフォーマットです。クリックやチャイムなど、効果音に利用されている比較的小さなサイズのファイルです。
PySide6 の QSoundEffect クラスは、マニュアル [1] によると、WAV ファイルのような低レイテンシな非圧縮のオーディオファイルを再生することができ、ユーザーのアクションに応答する「フィードバック 」タイプ(クリック音)のサウンド、例えば、仮想キーボードのクリック音、ポップアップダイアログの Yes / No の応答、あるいはゲームの効果音用途に適しているとあります。
さらに、低レイテンシが重要でない場合には、代わりに QMediaPlayer クラスの使用を検討してくださいともあります。
まずは QSoundEffect クラスの使い方を覚えようと、シンプルな Wav Player なるものを作ってみました。
下記の OS 環境で動作確認をしています。
|
RHEL 9.4 | x86_64 |
| Python | 3.12.1 | |
| PySide6 | 6.7.2 |
なお、QSoundEffect クラスが含まれる QtMultimedia パッケージを利用するために、本 RHEL では追加で libva をインストールする必要がありました。
[bitwalk@rhel9 ~]$ rpm -qa | grep libva
libva-2.20.0-1.el9.x86_64
libva-devel-2.20.0-1.el9.x86_64
[bitwalk@rhel9 ~]$
サンプルを以下に示しました。ひとつにまとめたところ、200 行を越える長めのサンプルになってしまいました。
サンプルの実行例を下記に示しました。
WAV ファイルは、参考サイト [2] からダウンロードできるファイルを利用させていただきました。
サンプルの説明
WAV ファイルを読み込み、PLAY/STOP したり、ボリューム調整をする操作は、すべて QToolBar クラスを継承した MyToolBar クラスにまとめています。
class MyToolBar(QToolBar):
wavSelected = Signal(str)
wavPlay = Signal()
wavStop = Signal()
wavVolume = Signal(float)
def __init__(self):
super().__init__()
but_folder = QToolButton()
but_folder.setToolTip('Choose wav file.')
ico_folder = get_icon(self, 'SP_DirIcon')
but_folder.setIcon(ico_folder)
but_folder.clicked.connect(self.file_dialog)
self.addWidget(but_folder)
self.but_play = but_play = QToolButton()
but_play.setToolTip('Start playing wav file.')
ico_play = get_icon(self, 'SP_MediaPlay')
but_play.setIcon(ico_play)
but_play.setEnabled(False)
but_play.clicked.connect(self.wav_play)
self.addWidget(but_play)
(以下省略)
QSoundEffect のインスタンスを扱うのは、QMainWindow クラスを継承した MyWavPlayer クラスです。ここでは QPlainTextEdit クラスを利用して、操作イベントのログ表示もしています。
class MyWavPlayer(QMainWindow):
def __init__(self):
super().__init__()
icon_win = get_icon(self, 'SP_TitleBarMenuButton')
self.setWindowIcon(icon_win)
self.setWindowTitle('Wav Player')
self.effect = None
self.toolbar = toolbar = MyToolBar()
toolbar.wavSelected.connect(self.source_selected)
toolbar.wavPlay.connect(self.sound_play)
toolbar.wavStop.connect(self.sound_stop)
toolbar.wavVolume.connect(self.set_volume)
self.addToolBar(toolbar)
self.pte = pte = QPlainTextEdit()
pte.setReadOnly(True)
pte.setStyleSheet('QPlainTextEdit {background-color: white;}')
self.setCentralWidget(pte)
(以下省略)
なお、QSoundEffect のインスタンスに読み込んだ WAV ファイルの変更ができなかったので、別の WAV ファイルを読み込む度に create_sound_effect メソッドでインスタンスを作り直しています。
def create_sound_effect(self, wav_file: str):
self.effect = QSoundEffect()
self.effect.loopsRemainingChanged.connect(self.remaining_changed)
self.effect.sourceChanged.connect(self.source_changed)
self.effect.statusChanged.connect(self.status_changed)
self.effect.volumeChanged.connect(self.volume_changed)
self.effect.setSource(QUrl.fromLocalFile(wav_file))
self.effect.setVolume(self.toolbar.getVolume())
PySide6 に組み込まれている標準のビットマップイメージ (Pixmap) を利用するために、名前を指定してアイコンを取得する関数を冒頭に記載しています。
def get_icon(parent, name: str) -> QIcon:
pixmap = getattr(QStyle.StandardPixmap, name)
icon = parent.style().standardIcon(pixmap)
return icon
気づいたこと
QSoundEffect クラスのインスタンス effect について、二点、気になることがありました。
effect = QSoundEffect()
setSource メソッドで他の WAV ファイルを読み込んでも、再生されるサウンドに反映されなかった。
effect.setSource(QUrl.fromLocalFile(file))
再生ループで下記の無限ループの enum (QSoundEffect.Loop.Infinite) が利用できなかった。
effect.setLoopCount(QSoundEffect.Loop.Infinite)
使い方が間違っているのかもしれませんが、バグがもしれないので問い合わせてみることにします。
参考サイト
にほんブログ村
#オープンソース




0 件のコメント:
コメントを投稿