Help us understand the problem. What is going on with this article?

REAPERで音の長さを変えるスクリプト

はじめに

20年ほど昔Logicでステップ入力していて、
TABキーで音の長さを伸ばせる機能があって、
もしかしてREAPERのスクリプトなら似たような事ができるかもと思い試してみたメモ。
output.gif

スクリプト

tatAddLength.py
RPR_ClearConsole()

midieditor = RPR_MIDIEditor_GetActive()
take = RPR_MIDIEditor_GetTake( midieditor )

notecntOut = 0
ccevtcntOut = 0
textsyxevtcntOut = 0

( retval, take, notecntOut, ccevtcntOut, textsyxevtcntOut ) = RPR_MIDI_CountEvts(take, notecntOut, ccevtcntOut, textsyxevtcntOut )

noteidx = notecntOut-1  #last note
selectedOut = True
mutedOut = True
startppqposOut = 0
endppqposOut = 0
chanOut = 0
pitchOut = 0
velOut = 0

( retval, take, noteidx, selectedOut, mutedOut, startppqposOut, endppqposOut, chanOut, pitchOut, velOut ) = RPR_MIDI_GetNote(take, noteidx, selectedOut, mutedOut, startppqposOut, endppqposOut, chanOut, pitchOut, velOut )

retval = RPR_MIDI_SetNote( take, noteidx, True, mutedOut, startppqposOut, endppqposOut+240, chanOut, pitchOut, velOut, False )

adjust = 0.125 * 120/RPR_TimeMap2_GetDividedBpmAtTime(0,0.125) # Tempo
RPR_MoveEditCursor(adjust, False)

なかなかうまくいかない点

音を伸ばす単位とカーソルを動かす単位が違う?

- 音の長さを変える

retval = RPR_MIDI_SetNote( take, noteidx, True, mutedOut, startppqposOut, endppqposOut+240, chanOut, pitchOut, velOut, False )

SetNoteで指定するのはQNとよばれるMIDI分解能の数値。
16分音符がメインなので、決め打ちで240足している。

※QNはテンポに依存せず音楽的、楽譜的に扱える。反面実時間に直すにはグローバルテンポを参照する必要がある。

960 = 4分音符
480 = 8分音符
240 = 16分音符

  • カーソルを移動する
adjust = 0.125 * 120/RPR_TimeMap2_GetDividedBpmAtTime(0,0.125) # Tempo
RPR_MoveEditCursor(adjust, False)

MoveEditCursorは・・・ これよくわからない。

試行錯誤して、BPM120の時1を入れると1ビート進むという感じがする。
時間なのかと思ってQNTotTimeとかそれっぽいの試してもなんか違う・・・

RPR_TimeMap2_GetDividedBpmAtTime(0,0.125)
がテンポと同じ値を返すので、120から比率だして、
これで一拍の長さがとれたので、1/4倍して16分音符の長さにしている。
※ココあっているか自信ない

キー設定

おそらくTABキーはシステム的にビューを切り替えるのが標準なので、ショートカットを割り当てるのはよくない感じがする。(割り当ててもうまく動かない)
ので、今回は左下の方のキーのXを使うことにした。
打ち間違えたときなど、Ctr-Zもよく使う。

image.png

あと、Cキーで16分音符だけ進めるようにした。
休符を入れているイメージ。

image.png

※Xキーもウィンドウ閉じるとかとバッティングしていて、うまく動かないときもある・・・謎。

ちょっと違うけどだいたい満足

Logicの時はノートオフが来る前の(長さが未確定な)音を伸ばすとかだったので、和音とかもいけていたのだが、
REAPERでは記録されている最後のノートだけ伸ばすことにしている。

Grid対応

  • 16分音符固定にしているけど、ここは変えられても良いかなぁとか。グリッドに合わせるとか。
( grid, take,  swingOutOptional,  noteLenOutOptional) = RPR_MIDI_GetGrid(take, 0, 0)

retval = RPR_MIDI_SetNote( take, noteidx, True, mutedOut, startppqposOut, endppqposOut+960*grid, chanOut, pitchOut, velOut, False )

adjust = grid * 60/RPR_TimeMap2_GetDividedBpmAtTime(0,0.25) # Tempo

こんな感じだろうか

tatAddLengthGrid.py
RPR_ClearConsole()

midieditor = RPR_MIDIEditor_GetActive()
take = RPR_MIDIEditor_GetTake( midieditor )

notecntOut = 0
ccevtcntOut = 0
textsyxevtcntOut = 0

( retval, take, notecntOut, ccevtcntOut, textsyxevtcntOut ) = RPR_MIDI_CountEvts(take, notecntOut, ccevtcntOut, textsyxevtcntOut )

noteidx = notecntOut-1  #last note
selectedOut = True
mutedOut = True
startppqposOut = 0
endppqposOut = 0
chanOut = 0
pitchOut = 0
velOut = 0

( retval, take, noteidx, selectedOut, mutedOut, startppqposOut, endppqposOut, chanOut, pitchOut, velOut ) = RPR_MIDI_GetNote(take, noteidx, selectedOut, mutedOut, startppqposOut, endppqposOut, chanOut, pitchOut, velOut )


( grid, take,  swingOutOptional,  noteLenOutOptional) = RPR_MIDI_GetGrid(take, 0, 0)

retval = RPR_MIDI_SetNote( take, noteidx, True, mutedOut, startppqposOut, endppqposOut+960*grid, chanOut, pitchOut, velOut, False )

adjust = grid * 60/RPR_TimeMap2_GetDividedBpmAtTime(0,0.25) # Tempo
RPR_MoveEditCursor(adjust, False)

ToDo:

  • ペダルで伸ばせるようにする(これはMIDIだけど、モードが異なるとき誤爆してしまうのをどうするのか ステップ入力時のみ機能させたい感じ)
  • 戻しつつ消すみたいな動作とか
  • 和音対応(これは最後のノートと同じスタートのノートに適用すればできそう)
tatmos
mydearest
VR×日本的アニメコンテンツで世界中にときめきを!一人称視点による主人公体験をVR上で提供します。
https://mydearestvr.com/company/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away