概要

 Pythonでのリアルタイムオーディオ信号処理に関する記事。録音と再生が同時にできる独自のクラスの作成に取り掛かった。


背景と目的

 前回までに、pyaudioを使って録音も再生もできることが確認できたが、ソースコードがそこそこの量なので、今後のために録音と再生をより簡単に制御できるように独自のクラスを作ることにした。今回は手始めとして、クラスの骨格を決めるのと使用できるデバイスを取得するメソッドまで実装してみる。


詳細

1.クラス

 クラスの基本的な使い方は、

  • 入出力のwavファイルを指定する
  • 使用するオーディオデバイスを設定する
  • 再生、録音、あるいは両方がすぐにメソッドを呼ぶ

 という感じで簡単に操作したい。このうち、まずは使用するオーディオデバイスが設定できるよう、使用可能なものを取得するメソッドを作ってみる。

2.実装

 まずは、クラス定義とフィールド。フィールドとして、入出力wavファイル、入出力チャンネル数、使用するデバイス、それとpyaudioオブジェクトを用意した。

import pyaudio

class PlayingRecorder:
    __p = pyaudio.PyAudio() # PyAudioクラスオブジェクト
    __mSourceWav = [] # 再生に使用するwavファイルオブジェクト
    __mTargetWav = [] # 録音に使用するwavファイルオブジェクト
    __mDeviceInfo = [] # 使用するデバイス情報
    __mPlayChCount = 0 # 再生チャンネル数
    __mRecChCount = 0 # 録音チャンネル数
    __version = 0.01 #バージョン

 コンストラクタは、とりあえず暫定で使用可能なデバイスを仮設定する。後述するgetAvailableDevicesメソッドを使っている。

    def __init__(self):
        # 使うデバイスを仮設定
        availableDeviceInfo= self.getAvailableDevices(self.__mRecChCount, self.__mPlayChCount, show = False)
        if availableDeviceInfo.count >= 0:
            self.__mDeviceInfo = availableDeviceInfo[1] # とりあえず見つかったものの先頭を設定
        else:
            print "device not found." # デバイスが見つからないことを警告
        return None

 そして、getAvailableDevicesメソッドが、使用可能なものを取得するメソッドだ。引数では必要な入出力チャンネル数を指定する。Showは、Trueのときコマンドラインに出力する。動作確認のためつけておいた。

21行目が誤っていたので修正(2017/08/24)

    def getAvailableDevices(self, inputChCount = 0, outputChCount = 0, show = True):
                                             
        availableDeviceInfo = [] # 空のリスト
        availableDeviceCount = 0
        # ホストAPI数
        hostAPICount = self.__p.get_host_api_count()
        if show == True:
            print "Host API Count = " + str(hostAPICount)
    
        # ホストAPIごとに情報を取得
        for cnt in range(0, hostAPICount):
            apiInfo = self.__p.get_host_api_info_by_index(cnt)
            
            if show == True:
                print "--- " + apiInfo.get("name") + "(index = " + str(apiInfo.get("index")) + ") devices ---"
            # デバイスごとに情報を取得
            availableDeviceCount = 0
            for cnt2 in range(0, apiInfo.get("deviceCount")):
                devInfo = self.__p.get_device_info_by_host_api_device_index(apiInfo.get("index"), cnt2)
                
                if inputChCount <= devInfo.get("maxInputChannels") and outputChCount <= devInfo.get("maxOutputChannels"):
                    availableDeviceInfo.append(devInfo) # 追加
                    availableDeviceCount += 1
                    if show == True:
                        print "index = " + str(devInfo.get("index")) + ", input/output = (" + str(devInfo.get("maxInputChannels")) + ", " + str(devInfo.get("maxOutputChannels")) + "), name = " + devInfo.get("name")
            if show == True:
                print "found " + str(availableDeviceCount) + " devices."
                print ""
                
        return availableDeviceInfo
3.動作確認

 以下のテストプログラムで動作を確認したところ、どうやらちゃんとデバイスが取得できているようだ。

無題
図3.1 戻り値を確認


まとめと今後の課題

 とりあえず、デバイスの取得ができるようになった。次は、wavファイルの指定ができるようにしようと思う。