key, new_time, old_time = 0,0,0; function OnEvent(event, arg, family) --OutputLogMessage("event = %s, arg = %s, family = %s\n", event, arg, family); if (event == "MOUSE_BUTTON_PRESSED" and arg == 3) then new_time = GetRunningTime(); EnablePrimaryMouseButtonEvents(1); PressKey("lshift"); PressAndReleaseKey("g"); ReleaseKey("lshift"); PressMouseButton(1); end if (event == "MOUSE_BUTTON_RELEASED" and arg == 3) then old_time = GetRunningTime(); --OutputLogMessage("%s %s\n", new_time, old_time); if ((old_time - new_time) < 200) then PressAndReleaseKey("i"); end PressAndReleaseKey("r"); ReleaseMouseButton(1); EnablePrimaryMouseButtonEvents(0); end if (event == "MOUSE_BUTTON_PRESSED" and arg == 5) then new_time = GetRunningTime(); --OutputLogMessage("%s %s\n", new_time, old_time); if ((new_time - old_time) > 2000) then key = 0; end if (key == 0) then PressKey("lalt"); old_time = GetRunningTime(); else PressKey("lctrl"); old_time = GetRunningTime(); end key = math.abs(key - 1); end if (event == "MOUSE_BUTTON_RELEASED" and arg == 5) then ReleaseKey("lalt"); ReleaseKey("lctrl"); end end こっから解説 (中央ボタンのスクリプトで、new_timeとold_timeの意味合いが逆になっていることを先に言っておきます。ボタン5で同じ変数を使ってしまったのでこうなってしまったのかも。別変数にわけたほうがよかったですね) とりあえず変数設定、すべて0
key, new_time, old_time = 0,0,0;
イベント発生
function OnEvent(event, arg, family) テスト用メッセージ
--OutputLogMessage("event = %s, arg = %s, family = %s\n", event, arg, family); もし中央ボタン(3)が押されたならば
if (event == "MOUSE_BUTTON_PRESSED" and arg == 3) then スクリプト起動からの時間をnew_timeとして記録(ミリ秒だったかと)
new_time = GetRunningTime(); 左クリックの制御を有効にする
EnablePrimaryMouseButtonEvents(1); 左シフトキーを押さえっぱなしにする
PressKey("lshift"); キーボードのgを押して離す(要はタイプする。今回はShift+Gがドラッグする前のショートカットキーである)
PressAndReleaseKey("g"); 左シフトキーを離す
ReleaseKey("lshift"); 左クリックボタンを押しっぱなしにする(ドラッグ操作のため)
PressMouseButton(1);
end もし中央ボタン(3)が離されたならば
if (event == "MOUSE_BUTTON_RELEASED" and arg == 3) then 離したときの時間をold_timeとして記録する
old_time = GetRunningTime(); メッセージ
--OutputLogMessage("%s %s\n", new_time, old_time); もし、中央ボタンを離したときの時間が押したときから200ミリ秒未満なら
if ((old_time - new_time) < 200) then 通常のクリックとみなしてキーボードのiを押して離す
PressAndReleaseKey("i");
end
いずれにしても中央ボタンを離すまではドラッグ状態で、離したときキーボードのrを押して離す(これは操作するソフトの都合上、Gを解除するためにRを押しているだけである)
PressAndReleaseKey("r"); ドラッグ終了のため左ボタンを離す
ReleaseMouseButton(1); 念のため、左クリックボタンの制御を無効にする
EnablePrimaryMouseButtonEvents(0);
end もし中央ボタン(5)が押されたならば
if (event == "MOUSE_BUTTON_PRESSED" and arg == 5) then スクリプト起動からの時間をnew_timeとして記録
new_time = GetRunningTime(); メッセージ
--OutputLogMessage("%s %s\n", new_time, old_time); もしボタン5を押したのが、前に押したときより2秒を超えていたら
if ((new_time - old_time) > 2000) then 通常クリックとみなしフラグkeyに0をセット
key = 0;
end 通常クリックならば
if (key == 0) then 左Altキーを押しっぱなしにする
PressKey("lalt"); スクリプト起動からの時間をold_timeとして記録
old_time = GetRunningTime(); もしボタン5を押したのが、前に押したときより2秒以下ならダブルクリックとみなす
else 左Ctrlキーを押しっぱなしにする
PressKey("lctrl"); スクリプト起動からの時間をold_timeとして記録(どうせ同じなんだからnew_timeと比較の後にまとめて書いてもよかったですね)
old_time = GetRunningTime();
end フラグを0なら1、1なら0にする
key = math.abs(key - 1);
end もし中央ボタン(5)が離されたならば
if (event == "MOUSE_BUTTON_RELEASED" and arg == 5) then 左Altボタンを離す
ReleaseKey("lalt"); 左Ctrlボタンを離す
ReleaseKey("lctrl");
end
end
ここで、後者の場合、
on release
dec($Stack)
note_off($Eve_ID)
end on
とすると、
50キーオフで、音は50も60も止まる。
on releaseは1つ分だけ働き、note_offによる重複はないっぽい。
ただし、キーオンを和音にすると、$Eve_IDが順次上書きされ、note_offは最後の一つの音しか消えない。
release時は
$i := 0
while($i<128) if($i=$EVENT_NOTE)
note_off(%Eve_ID[$i])
end if
inc($i)
end while
とすれば、オフにしたキーのみ消えてくれて、全部放すと全部消えてくれる。
しかし、play_noteが開始になってからでないと消えない(1秒経過前にキーオフすると1秒経過後に音が鳴り出し、なり続ける)
###########################
もう一つ注意があるようです。
on controller
message($Stack)
end on
をセットし、
音が鳴っている間、CC1を動かしまわって、$Stackの動きを観察した。
on note
inc($Stack)
wait(1000000)
%Eve_ID[$EVENT_NOTE] := play_note(60,127,0,-1)
end on
on noteの中でplay_noteは、循環しないらしい。
というのは、50キーを押しっぱなしにしたとき、$stackが1以上増えないからである。
on note
inc($Stack)
wait(1000000)
%Eve_ID[$EVENT_NOTE] := play_note(60,127,0,0)
end on
の場合も同じであった。
そして先ほどの例のように、 on release dec($Stack) $i := 0 while($i<128) if($i=$EVENT_NOTE)
note_off(%Eve_ID[$i])
end if inc($i) end while end on
relaese内でのnote_offも循環しないようである。
on note
inc($Stack)
wait(1000000)
%Eve_ID[$EVENT_NOTE] := play_note(60,127,0,0)
wait(1000000)
$i := 0
while($i<128) if($i=$EVENT_NOTE)
note_off(%Eve_ID[$i])
end if
inc($i)
end while
end on
on note inc($Stack) disallow_group($ALL_GROUPS)
wait(1000000) allow_group(find_group("Legato"))
%Eve_ID[$EVENT_NOTE] := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1) end on
on release
dec($Stack)
$i := 0 while($i<128) if($i=$EVENT_NOTE)
note_off(%Eve_ID[$i])
end if inc($i)
end while end on これで、1秒後にグループ"Legato"のキーが鳴り、キーオフで遅れた音も消える、そして$Stackに異常も発生しないプログラムのできあがりです。(保障しませんが)これを応用すると、1つのキーオンで2つ以上の任意の音をつないでレガートを作れるはずです。 $Stackが0のときは通常のグループを鳴らし、$Stack>0のときは、このディレイを使って、2つ以上の音をつなげるLegatoグループを鳴らすというわけです。
on note %Alive_NOTE[$EVENT_NOTE] := 1 inc($Stack) wait(1000000) if(%Alive_NOTE[$EVENT_NOTE] = 1) %Eve_ID[$EVENT_NOTE] := play_note(60,127,0,0) end if end on
on release %Alive_NOTE[$EVENT_NOTE] := 0 dec($Stack) $i := 0 while($i<128) if($i=$EVENT_NOTE) note_off(%Eve_ID[$i]) end if inc($i) end while end on