忘備ログ

失い続ける履歴 Pythonとか趣味とかいろいろ

Pythonで音楽を再生したい(6) pygame編

こんにちは、スドウです。

Pygameを使った音楽プレイヤー(もどき)の作成記録です。

前回のソースを(何故か)大幅に変更しました。

【前回の記事】

sudo2501lab01.hatenablog.com

1番大きな変更はClass化したことでしょうか。
そのClass化に至った理由ですが、
Class化の勉強しよう。まずは作りかけの音楽プレイヤーでやってみよう。」
と言うその場のノリと勢いで決めたワケじゃないんですが。。。
正直。。。特に理由らしい理由はない。。。です。
(でも、なんとなくClass化のやり方はわかってきた。。。よ)

Class化以外にも少し機能を追加したので、
変更内容を下記にまとめます。

変更内容
  • Class化
  • ファイル未選択時は一時停止/再開ボタンを無効にする
  • ファイル選択毎に一時停止/再開ボタンを初期化する

いつものように wavファイル を再生します。
※ ソースと同じフォルダに wavファイル がなくてもOKです。

以下ソースです。

import os
import sys
import tkinter as tk
from tkinter import ttk
from tkinter import *
from tkinter.ttk import *
from tkinter import filedialog

import pygame.mixer as pymix
import wave

# ウィンドウクラス
class Frame(ttk.Frame):

    # 初期化
    def __init__(self, master = None):
        super().__init__(master)
        self.master.title('Music Player by Pygame (test12)') # タイトル
        self.master.resizable(False, False) # サイズ変更の禁止
        self.pack()
        self.create_buttons() # ボタン
        self.create_label()   # ラベル
        
    # 終了
    def push_exit(self):
        exit()

    # ファイル選択処理
    def file_select(self):
    
        # ファイル拡張子の指定
        #fType = [("", "*")] # 全てのファイル
        #fType = [("", "*.wav *.mp3")] #.wav,.mp3のみ
        fType = [("", "*.wav")] #.wavのみ
       
       # ディレクトリ名を返す
        iDir = os.path.abspath(os.path.dirname(__file__))

        # ファイル選択ダイアログ(選択ファイルの絶対パスを取得)
        fPath = filedialog.askopenfilename(filetype = fType, initialdir = iDir)

        if (fPath != ""): # 絶対パスが空ではない
        
            # ファイル名のみ表示
            fName = os.path.basename(fPath)

            # ファイル名前をセット
            self.file2.set(fName) # ファイル名のみ(曲名表示用)

            # 再生関連の初期化
            self.setting_init()

            # ファイルを自動再生
            self.music_start(fPath) # 絶対パスを引数として渡す
        
        else : # ファイルパスが空
            pass

    # 音楽再生関連の設定を初期化
    def setting_init(self):
        
        # 一時停止/再生ボタンを有効にする
        self.pause_btn.state(["!disabled"])

        # 一時停止/再生ボタンの初期化
        self.pause_btn_act = 0
        self.btn_text.set("一時停止")

        # 音量スライダを生成する
        self.create_scal()    # 音量スライダ        

    # 音楽再生
    def music_start(self, fPath):

        # 再生中の音楽を終了する
        pymix.quit()

        # 再生するファイルパスを取得
        sound_file = fPath

        # 初期設定
        pymix.init(frequency = 44100, size = -16, channels = 2, buffer = 4096)

        # 再生ファイルを設定
        sounds = pymix.Sound((str)(sound_file))

        # 音楽再生 (loops = -1:無限ループ)
        music_play = sounds.play( loops = -1)

        # 音量初期値
        music_play.set_volume(0.1)

        # 音量スケール初期化
        self.vol_scal.set(10)

        # Sound.play オブジェクトをインスタンス(?)変数化
        self.music_obj = music_play

    # 音楽:一時停止  
    def music_pause(self):
        self.music_obj.pause()

    # 音楽:再開  
    def music_unpause(self):
        self.music_obj.unpause()

    # 音量調節
    def sound_vol(self, n):
        # 0.01刻みで0.00 ~ 1.00 の範囲で変化
        self.music_obj.set_volume((float)(self.vol_scal.get()/100))

    # 再生/一時停止
    def push_pause(self):
        if(self.pause_btn_act == 0):
            self.music_pause()   # 一時停止
            self.pause_btn_act = 1
            self.btn_text.set("再開")
        elif(self.pause_btn_act == 1):
            self.music_unpause() # 再開
            self.pause_btn_act = 0
            self.btn_text.set("一時停止")
        
    # ボタンの作成
    def create_buttons(self):
        # ファイル選択ボタン
        self.file_btn            = ttk.Button(self)
        self.file_btn["text"]    = "ファイル"
        self.file_btn["command"] = self.file_select
        self.file_btn.grid(row = 0, column = 0)

        # 終了ボタン
        self.exit_btn            = ttk.Button(self)
        self.exit_btn["text"]    = "終了"
        self.exit_btn["command"] = self.push_exit
        self.exit_btn.grid(row = 0, column = 1)

        # 再生/一時停止ボタン
        self.btn_text = StringVar()
        self.btn_text.set("一時停止")
        
        self.pause_btn                 = ttk.Button(self)
        self.pause_btn["textvariable"] = self.btn_text
        self.pause_btn["command"]      = self.push_pause
        self.pause_btn.state(["disabled"])  # ボタンを無効(初期状態)
        self.pause_btn.grid(row = 2, column = 0)

    # 音量スライダの作成
    def create_scal(self):
        self.vol_scal               = tk.Scale(self)
        self.vol_scal["orient"]     = HORIZONTAL
        self.vol_scal["length"]     = 400
        self.vol_scal["from_"]      = 0.0
        self.vol_scal["to"]         = 100.0
        self.vol_scal["resolution"] = 1.0
        self.vol_scal["command"]    = self.sound_vol        
        self.vol_scal.grid(row = 3, column = 1)

    # ラベルの作成
    def create_label(self):
        # ファイル名取得
        self.file2 = StringVar()  # 名前のみ取得(表示用)
         
        # ファイル名表示ラベル
        self.name_label                 = ttk.Label(self)
        self.name_label["textvariable"] = self.file2
        self.name_label["font"]         = ("",12)
        self.name_label["width"]        = 50
        self.name_label.grid(row = 1, column = 1)

        # 音量スライダラベル
        self.volume_label         = ttk.Label(self)
        self.volume_label["text"] = "音量" 
        self.volume_label.grid(row = 3, column = 0)        

if __name__ == '__main__':
    
    root = Frame()
    root.mainloop()

IDLEからプログラムを実行します。

見た目と基本的な操作は前回と同じです。

前回も少し触れましたが、Pygame以外の音声処理ライブラリとして
wxPythonの使用を考えています。
まだ、情報を集めている段階なので断言はできないのですが。。。

それと今後、音楽プレイヤーに追加したい機能ですが
* 再生できる形式が多い(Pygameではmp3の再生に制限があるため)
* 再生シークの追加(ファイルポインタの制御ができること)
* 再生時間の表示
* リピート再生のON/OFF
です。
(おそらく、もっとあると思いますが。。。 )
そして、上記にある再生できる形式が多い
現在のPygameからライブラリを変更したい理由です。

2018年 おそらく さいごの記事はPythonでした。
年末の大掃除の如く記事を更新しましたが、
これからはゆっくり目な更新になると思います。  

Python関連の記事が音楽プレイヤーばかりですが、
それ以外にもPythonを使ってやりたい事がたくさんあるので、
これから少しずつ始めていきたいです。

(あと、放置しているUTAU式人力も何とかしたいとは思っているけど、たぶん暫くはやらない。)

何事もなければ、本記事が2018年最後の更新になると思います。
技術的にも、文章的にも拙い記事が多かったと思いますが、
読んでいただきありがとうございました。
そして、来年もよろしくお願い致します。

ではでは!

スポンサードリンク