10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【TouchDesigner】DJシステムをつくる

Last updated at Posted at 2021-12-20

この記事はTouchDesigner Advent Calendar 2021の20日目の記事です。

#はじめに
これはTouchDesignerでDJのシステムをつくろうとしたけど障壁が多すぎたという話です。
当初の目的は果たせなかったものの、Pythonのことをよく知れたし紹介できそうなので良し。

↓一応今回作った画面はこんな感じになります。(クロスフェーダーが無い・・・)
スクリーンショット 2021-12-19 150108.png

下記に今回のファイルアップしてます。
Pythonの必要なモジュールはrequiments.txtを使用してインストールしてください。(venv推奨)

#お品書き
以下DJシステムに必要な最低限の機能です。

  1. 音声ファイルリスト取得/表示
  2. 音声ファイルの波形表示(Python+Script TOP+.venv)
  3. 音声ファイルのBPM計測(Python+subprocess)
  4. BPMをシンクロ
  5. 頭出し~Cue
  6. イコライザー
  7. ミックス~音声出力(オーディオインターフェースでの出力)

###1. 音声ファイルリスト取得/表示
これはスニペットと通常のオペレータを使えば簡単にできます。

  • feildFolderBrowser・・・フォルダ選択のダイアログを出せるスニペットです。
  • Folder Dat・・・feildFolderBrowserが選択したフォルダパスを参照させると、そのフォルダにあるファイルとパスをテーブルで出力してくれます。
  • radioList・・・Folder DatのOutを繋ぐと、そのファイルリストをラジオボタンのリストにしてくれて、ボタンを押すと該当のセルをOutしてくれます。
これで音源の選択ができるようになりました。

###2. 音声ファイルの波形表示(Python+Script TOP+.venv)
これが鬼門でした。
File in CHOPで音声ファイルを読み込むと波形を表示してくれるのでOP Viewer COMPに入れれば良いかと思ったのですが、ファイルを読み込むと一瞬タイムラインが止まります。
この時点で再生している音も止まってしまうのでシステムとして破綻してる。
なのでしょうがなくPythonで実装を試みました。

####2-1. Script TOP
波形の生成はScript TOPで行います。Script TOPは、Pythonを記述するとTOPにイメージを出力してくれる便利なTOPです。

が、音源選択から波形の生成を1つのToeファイル内で波形の生成を行うとやはり全体の処理が止まってしまったため下図の様に2つのToeファイルで行いました。
スクリーンショット 2021-12-09 211343.png
こうすることでメインのToeファイルの処理を止めることなく波形の生成が行えます。
Python自体はtorchaudioというライブラリを使用しています。

↓これは「1. 音声ファイルリスト取得/表示(Operator)」から波形生成までのスクショです。
スクリーンショット 2021-12-09 200153.png

####2-2. 仮想環境(venv)について
今回波形生成のPythonをTouchDesigner内で実行するにあたり**仮想環境(venv)**を使いました。
Anaconda環境含め、PCには複数Pythonがインストールされていますが、venvを使うと本プロジェクトのみに適したPython環境を構築することができます。

参考・・・Extending TouchDesigner @MUTEK.JP

1点、Pythonモジュールの探索パスを追加する際にappendではなくinsertを使用しました。
appendは探索パスリストの最後にvenv環境のパスを追加しますが、insertは第一引数に0を指定することでリストの最初に追加することができます。

今回NumPyを使用していますが、appendで追加した場合別環境のNumPyを参照してしまってバージョンエラーが出たので、venv環境のモジュールを最初に認識させるべくこの対策を取っています。

import sys, os
path = os.path.join(os.path.abspath('.'), '.venv\Lib\site-packages')
if not path in sys.path:
	sys.path.insert(0, path)#←ここをappendじゃなくてinsertにしてる

####補足
正直ここでTouchDesignerでのDJシステムの完成を断念して各機能の開発にしました。
大きな理由は下記2点に尽きます。

  1. Pythonでmp3を使うことが難しい
  2. 波形を自由に伸び縮みさせることが難しい

私の所有するデジタル音楽データはmp3が多いのですが、それが使えないとなると作る意味合いが無くなります。
また、曲の頭出しなどは波形の細かい部分を見てキューをセットするのですが、波形が自由に変形できないとなるとそれも難しい。
残念。。
ですが、単機能ごとの開発は続けます。

###3.音声ファイルのBPM計測(Python+subprocess)
TouchDesignerではリアルタイムでBPMを計測するチュートリアルも公開されていますが、ファイルを読み込んだ時点でBPMが知りたいので、これもPythonを使用します。

これにはPythonのlibrosaというライブラリを使いました。
ですがTouchDesigner内で実行するとTouchDesignerが固まって落ちてしまったので、これはsubprocessを用いてTouchDesignerの外部でPythonを実行します。

subprocessはTouchDesignerのパフォーマンスを下げることなくPythonの複雑な計算などを行えるためおススメです。

参考・・・TOUCHDESIGNER | PYTHON AND THE SUBPROCESS MODULE

具体的にはsubprocessで外部のプログラムを呼び出してcallbackを受け取るという感じですが、callbackというかOSCで計算結果を戻してもらっています。

スクリーンショット 2021-12-09 211359.png

この時、普通にやるとプロンプトのウィンドウが立ち上がってしまいます
これは最高にいけてないので、ウィンドウを起動せずサイレント実行をする記述をします。

port = str(op('udpin').par.port.val)

#venv環境のpythonを実行するようにpython.exeを指定
cmd_python = '{}/.venv/Scripts/python.exe'.format(project.folder)
#実行するpythonファイルを指定
cmd_python_script = '{}/scripts/detectBpm.py'.format(project.folder)
python_args = [cmd_python, cmd_python_script]
#OSCに使うポート番号と、BPMを計測するためのファイルパスを引数で渡す指定
script_args = ['-p', port, '-f', filepath]
cmd_args = python_args + script_args
op('udpin').par.clear.pulse()

#ここでプロンプトのウィンドウを非表示にする設定
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
#コマンド実行
subprocess.Popen(cmd_args, startupinfo=si)

↓Select DATの音源ファイルパスが変わるとpythonが実行され、結果がUDP INに返ってくるところです。
スクリーンショット 2021-12-14 114349.png

一方で音声ファイル、特にダンス系のDJを目的としたファイルには、メタ情報にBPMの情報がついているものがあるのでその情報を使うのもありです。

###4. BPMをシンクロ
音源のBPMが計測出来たところで2つの音源のBPMをシンクロさせる機能を検討します。
まずBPMの考え方ですが、TouchDesignerにおいてはAudio File In のSpeedパラメーターに以下の計算式で適用させようと思います。

セットしたいBPM / 自身の今現在のBPM = Speedの倍率

Audio File Inで音源を読み込んだ時、Speedは1になっています。
セットしたいBPMを、自身の元々のBPMで割ればSpeedの倍率が計算できることになり、その値をSpeedに読み込ませてあげることで、片方の音源からもう片方の音源へBPMのシンクロができます。
これはMath CHOPで2つのチャンネルをDivideしてあげれば簡単に計算ができます。

スクリーンショット 2021-12-19 151048.png

###5. 頭出し~Cue
音源のCueをセットする際に音源をシークします。
これはSlider COMPと音源の長さを一致させることで、Slider COMPのバーを動かして音源の特定の位置で頭出しをし、Cueにセットさせることがきます。

その際Audio File InのPlay ModeをSpicify Indexにし、Indexパラメーターを0~100の値で指定することで実現します。
Slider COMPは0~1の値を出力するのでMath CHOPで100倍してその値をIndexに読ませます。
スクリーンショット 2021-12-19 151531.png
Slider COMPだとあまり小回りが利かないので、ターンテーブル系の、微調整が可能なUIにするとより良いと思います。これをうまくやればスクラッチもいけます

###6. イコライザー
イコライザーはAudio Band EQの、High / Middle/ Lowそれぞれの周波数をknobの出力でコントロールします。
今回knob含めGUIはPaletteのものを使ってます。

Audio File InからAudio Band EQにつなぎ、Audio Device Outすれば調整した音が出力可能です。

###7. ミックス~音声出力(オーディオインターフェースでの出力)
ミックスと書いておきながらクロスフェーダー実装してないんですが、、最後にオーディオインターフェースの話をします。
オーディオインターフェースとは、マルチチャンネルの音声を出力できるデバイスで、PCでDJをする場合は必須のものです。私は10年以上前に購入したAudio 4 DJというデバイスを使用しています。これは2チャンネル(ステレオで4チャンネル)の出力に対応しています。
news_photo1.jpg

TouchDesignerはオーディオインターフェースにも対応しておりマルチチャンネルに出力ができます。
ドライバがインストールされていればおそらくTouchDesignerでも認識ができると思います。
Audio Device OutのDeviceパラメーターに、どのチャンネルで出力するかの選択ができるようになります。
スクリーンショット 2021-12-19 153338.png

最初**DriverをASIOにしてやってみたんですがうまくいかず、**defaultにしていますが、ASIOだと低レイテンシーなので、そちらの方が良いらしいです。

で、Audio 4 DJの場合、**チャンネルAをMaster Out(スピーカー)、チャンネルBをモニター(ヘッドフォン)**に指定することで、曲を流しながら頭出しなんかができます。

#最後に
最初はもっと簡単にできそうかなと思いましたが、最初の方で結構心を折られました。
GitHubにアップしたソースではある程度機能するようにGUIを組んでいます。
バインドの仕方とか細かいところで記事にできそうなところはありましたが、今回は割愛しています。

この先これをアップデートするかどうか迷いますが、、
これを読んでいただいた人の何かの一助になれば幸いです。

10
6
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
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?