LoginSignup
0
0

More than 1 year has passed since last update.

ADX2 別プロセスで原音再生

Last updated at Posted at 2021-07-20

はじめに

ADX2スクリプトで原音再生の改良版の紹介。

環境:CRI AtomCraft 3.45.00

スクリプトの流れ

UI系は外部プロセスにしないとCraftごと落ちてしまうことがわかっていて、
バッチみたいな処理にしか利用できていないのが現状なのだけど、

  • 情報収集(選択キューのマテリアルを探し元ファイルパスを得る)
  • 解析  (今回はとくになし)
  • 実行  (音を再生する)

という流れの、
情報収集だけCraft上で動作させて、
解析、実行を別プロセスにしておくと、
Craftを解放できるはず

別プロセスのメリット

  • 中断ができる(プロセスを止めることができる)
  • 非同期実行にできる(重い解析とかでCraftを待たせなくすることができる)
  • Craft上でのスクリプトの実行の制限から解放される
    • UIが表示できる(解析結果表示など)
    • スクリプト分割時の更新など(Craftは一度importしてしまうとCraft再起動するまで外部ファイルの再読み込みをしないため)

別プロセスのデメリット

  • ファイルが増える
  • デバッグや、結果の収集、インタラクティブなやりとり(プロセス間通信)に少し工夫が必要になる。 (Craftはサーバー機能でもスクリプト動かせるので駆使すればできなくはないが)

改善点

長い音の再生をキャンセルできない問題

前回の再生の場合、同じプロセスで再生をしてしまうため、
曲のような長い音を再生した場合、再生が終わるまで待たないといけない状態でした。

そこで、再生処理を別プロセスに投げてしまうことで、キャンセルできるようにします。

キューを選択し、PlayWav.pyを実行すると
マテリアルのフルパスを得ることができ、
subprocessを利用して
Z_ExtAudioPlay.pyを実行します。
引数の波形を再生します。

また、再生しているウィンドウを閉じることで、中断することができます。

プロセスを起動するスクリプト

PlayWav.py
# --Description:[tatmos][Preview]選択したオブジェクトの原音を再生

import subprocess
from time import sleep
import cri.atomcraft.project as acproject
import cri.atomcraft.debug as acdebug

#--------

#選択中のマテリアルまたはウェーブフォームリージョンまたはキューを得る
selectedMaterials = acproject.get_selected_objects("Material")["data"]
selectedWaveformRegions = acproject.get_selected_objects("WaveformRegion")["data"]
selectedCues = acproject.get_selected_objects("Cue")["data"]

selectedMaterial = None

if len(selectedMaterials) > 0:
    selectedMaterial = selectedMaterials[0]
if len(selectedCues) > 0:
    selectedWaveformRegions = acproject.find_objects(selectedCues[0],"WaveformRegion")["data"]
if len(selectedWaveformRegions) > 0:
    selectedMaterial = acproject.get_value(selectedWaveformRegions[0], "LinkMaterial")["data"]

if not selectedMaterial:
    acdebug.warning("再生するマテリアルまたはウェーブフォームリージョンまたはキューを選択してください。")
    sys.exit()

print(acproject.get_value(selectedMaterial, "Name")["data"])

input_path = acproject.get_value(selectedMaterial, "SrcFileAbsolutePath")["data"]

if not input_path:
    acdebug.warning("マテリアルのパスがみつかりません。")
    sys.exit()

print("Path:" + str(input_path))

#別プロセスで再生

command = ["python","C:/MyDearest/github/ADX2Robot/local/Z_ExtAudioPlay.py",input_path]
proc = subprocess.Popen(command) 
proc.communicate()

再生をするスクリプト

Z_ExtAudioPlay.py
import pyaudio
import wave
import time
import sys

args = sys.argv
input_path = args[1]

p = pyaudio.PyAudio()

#--------
#AUDIOのDEVICEを列挙
#hostAPICount = p.get_host_api_count()
#for cnt in range(hostAPICount):
#    print(a.get_host_api_info_by_index(cnt))

#音を鳴らすDEVICEを指定
DEVICE_INDEX = 0

#--------
#ファイルを開く
wf = wave.open(input_path, "rb")

def callback(in_data, frame_count, time_info, status):
    data = wf.readframes(frame_count)
    return (data, pyaudio.paContinue)

#ストリームの作成
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                input_device_index = DEVICE_INDEX,
                output=True,
                stream_callback=callback)

#再生
stream.start_stream()
print("再生中 ... " + input_path)

#再生終わりまで待つ
while stream.is_active():
    time.sleep(0.1)

print("done.")
stream.stop_stream()
stream.close()
p.terminate()
wf.close()
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0