Finale Luaのススメ ~JW Luaで開発編~
前回の投稿から時間が経ってしまいましたが、今回からFinale Luaについてもう少し実践的な「スクリプト開発」をやってみたいと思います。
相変わらず備忘録的な投稿ですが、ご参考まで。。
Finale Luaの開発のやりかた
Finale Luaで使用するLuaスクリプトを作りたい場合は、Finaleの入っているPCの中に開発環境を作って、そこで開発を進めることになります。
ではその開発環境の作り方ですが、ここでは2つほどご紹介します。皆様のお好きな方法でいいですし、他にも方法はたくさんあると思いますので自分なりのやり方を探していただくのもよいかと思いますよ!
【開発環境1.】JW Luaを使う
前回の記事で紹介した、「JW Lua」を使った方法です。
何といっても手軽です。前回の方法で簡単に使うことができ、しかも手軽にスクリプトを動かしたり直したりすることができます。
ですので、初心者の方は最初こちらで慣れるまでいじくり倒してみることをおすすめします。
後ほど、簡単なコードを書いてみますので、そちらを参考に動かしてみてください。
【開発環境2.】コードエディターを使う
もう一つは、コードエディターと呼ばれるコード書く用の色々な機能を持ったテキストエディターを使う方法です。
ここでは、私の環境を例にとりますが、使用環境がWindowsということでMicrosoft謹製の「Visual Studio Code」を使って開発環境を構築していく手法を皆さんにご紹介いたします。
もちろん他にも様々なコードエディターが存在しますので、詳しい方はご自身で調べて探してみてはいかがでしょうか。
とにかく、プログラミングに慣れた方でないと敷居が高いです。またFinale⇔VS Code間の画面の切り替えなどが発生するので、複数のモニタを使用するわけでないのなら、何度もトライアンドエラーをしながら作っていくのには向かないと思います。
あとは、デバッグの機能が豊富なのと最新版のPDK Frameworkが使えるので拡張性に優れている、といったとにかく玄人向けな開発環境です。
こちらは次回詳細な手順を投稿しますので、興味のある方は見てみてください。かなりマニアックです。
とにかく簡単なスクリプトを書いてみる
というわけで、まずはお手軽なJW Luaを使って簡単なスクリプトを書いてみましょう!
まずは画面の説明
前回の投稿に従って「JW Lua」のウィンドウを開きます。(「プラグイン」>[自分で名前を付けたフォルダ名]>「JW Lua…」)
もしタブが「Development」になっていなければ「Development」に変更します。そうすると以下のような表示になっていると思います。各フィールドの説明は画像を参照してください。
今はとりあえず、スクリプトを動かしてみましょう。
事前準備
事前準備として、Lua Scriptで実行する楽譜データを作っておきます。今は適当でOKです。そのうち、本番データで実行したりして楽しみましょう。
A. スクリプト(ファイル)名を付けて保存する
とりあえずA.のリストボックスをクリックして開きます。すると、おなじみのメニューが出てきます。未保存の新規ファイルの場合は「Untitled」という名前になっていますので、「Save As…」をクリックして名前を付けて保存します。luaファイルはどこに保存しても構いません。
B. スクリプトを書く
今はとりあえず例ですので、以下のコードをコピペしてみてください。
local sel_rgn = finenv.Region()
local ui = finenv.UI()
if not sel_rgn:IsEmpty() then
for entry in eachentrysaved(sel_rgn) do
for note in each(entry) do
local midikey = note:CalcMIDIKey()
midikey = midikey + 2
note:SetMIDIKey(midikey)
end
end
else
local AlertMsg = '小節を選択してください。'
ui:AlertInfo(AlertMsg, 'エラー')
end
何のことかさっぱりと思いますが(プログラミング経験者には簡単なレベルではあります)、要するに、選択範囲にある音符をMIDI番号にして2つ上げるというスクリプトになります。
MIDI番号(MIDI Note Number)というのは各音の高さに振られている番号のことで、「真ん中のC」を60としてC♯(D♭)は61、Dは62…となっています。
C. 実行ボタンを押す
では、C.の「Run Script」を押してスクリプトを実行してみます。
エラーが出ましたね。はい、そうです。このスクリプトは「選択された範囲にある音符の音高を上げる」ものなので、選択されていない場合はエラーをポップアップで表示します。
ここの部分ですね。(詳細なコードの説明は改めて)
if not sel_rgn:IsEmpty() then
~
else
local AlertMsg = '小節を選択してください。'
ui:AlertInfo(AlertMsg, 'エラー')
end
それでは、音符が入力された小節を選択して、再度実行してみます。
はい、音の高さがMIDI番号2つ分上に上がりましたね。これで完成です!
A. のリストボックスから保存しましょう。次回からは「Open」でまた開いて作業を開始できます。
D. 出力コンソールを活用する
ちなみにD.には、出力結果が表示されているかと思います。エラーがある場合にはここにエラー内容が表示されるので、ここを確認しつつコードを修正していきましょう。
また、print関数を使ってその場所での変数の値などを調べるデバッグ的な使い方もできるので、割とJW Luaだけで一通りの開発はできてしまいます。
また、左下の「Class Browser」で使用できるクラスの一覧と、ものによっては使い方も表示することができます。こちらのコピペである程度は作成が可能だと思います。
また、英語版ですが以下「Finale PDK Framework」というページでクラスの一覧とその説明を確認することができます。
おまけ:コードの解説
最後に、今回コピペしたコードの解説を簡単に。
local sel_rgn = finenv.Region()
local ui = finenv.UI()
if not sel_rgn:IsEmpty() then
for entry in eachentrysaved(sel_rgn) do
for note in each(entry) do
local midikey = note:CalcMIDIKey()
midikey = midikey + 2
note:SetMIDIKey(midikey)
end
end
else
local AlertMsg = '小節を選択してください。'
ui:AlertInfo(AlertMsg, 'エラー')
end
まず、Finale Luaにおいて「選択範囲のデータを取得」する場合は「finenv.Region()」を使います。1行目で、取得した選択範囲のデータを「sel_rgn」という変数に格納しています。
また、2行目にはUIを制御するクラス(FCUI)を取得して、おなじく「ui」という変数に格納しています。
選択範囲を取得する処理をする際、何も選択されていない場合は、何やら不可思議なエラーが出てしまったりしてスクリプト使用者はともかく作成者も訳が分からなくなったりしますので、必ず以下のような条件分岐を入れて、エラーの原因がわかるようにしておきましょう。
if文はほかのサイト様に説明を委ねるとして、取得した範囲データをIsEmpty()メソッドで空かどうか判定し、条件を分岐させています。
空でなくない(?)場合の処理として行うFCUIクラスのAlertInfoメソッドは、最初の引数でメッセージ内容、2つ目の引数でタイトルバーに入るメッセージの内容を定義します。これによってエラーメッセージを画面に出力します。
if not sel_rgn:IsEmpty() then
~
else
local AlertMsg = '小節を選択してください。'
ui:AlertInfo(AlertMsg, 'エラー')
end
それではいよいよ中のコードですが、まず取り出した範囲内のすべてのデータのうちFCNoteEntryデータ(一つ一つの音符データ)を、1行目でeachentrysaved()メソッドを使って上書き可能な状態で一つづつ取り出します。
取り出した音符データは「和音も含めた一つの音符」の状態になっているため、2行目でその中からまたfor文を使ってそれぞれ和音の中の一つ一つの音を取り出していきます。
※和音でない場合は一回取り出して終わりなためすべて単音の場合は不要そうですが、FCNoteEntryデータには「音の高さ」のプロパティ情報がないため、必ずFCNoteのデータにして取り出す必要があります。
次に3行目でFCNoteクラスのCalcMIDIKey()メソッドを使って一つ一つの音のMIDI番号を取得し、4行目でそのMIDI番号に2を足し、5行目でSetMIDIKey()メソッドを使ってその音符にMIDI番号をセットします。そうすることでその音が2つの音分上に上がるのです。
もちろん、4行目の数字をマイナスにしたら音が下がりますし、1にしたら半音単位で音が動きます。
これを、範囲内のすべての音符データに対して実行します。
for entry in eachentrysaved(sel_rgn) do
for note in each(entry) do
local midikey = note:CalcMIDIKey()
midikey = midikey + 2
note:SetMIDIKey(midikey)
end
end
以上でJW Luaを使ったFinale Luaの開発方法の解説を終わります。もしコードの説明などでそうじゃないだろ!などツッコミがあればどんどんお願いします。というか私にプログラミングを教えてください!
それでは、みなさまJW Luaで楽しいFinale Luaライフを!(そんなものがあるのかは私も聞きたい)