Go Back   Cockos Incorporated Forums > REAPER Forums > ReaScript, JSFX, REAPER Plug-in Extensions, Developer Forum

Reply
 
Thread Tools Display Modes
Old 04-09-2014, 01:06 PM   #41
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Hi gofer,
EELed version of your "Smooth CC values" seems to be working great :

Download:
https://stash.reaper.fm/20305/Smoothen%20CCs.zip


Last edited by spk77; 04-16-2014 at 11:59 AM. Reason: Zip updated - bug fixes (MSB/LSB pair related)
spk77 is offline   Reply With Quote
Old 04-09-2014, 01:58 PM   #42
heda
Human being with feelings
 
heda's Avatar
 
Join Date: Jun 2012
Location: Spain
Posts: 7,268
Default

Very cool spk77!
It's exactly as expected
Thank you gofer and spk77!
heda is offline   Reply With Quote
Old 04-09-2014, 02:48 PM   #43
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

SPLENDID!

Thanks a lot, I'm going to look into the code, of course, too see what you did there . It seems to be working really good so far . Too bad, it can't go back to original moving the slider back left. But it does proper undo, I figure, with naming in both undo list and menu bar! I never got that to work, so there's another thing I'll have a close look at.

I think you could just allow 14bit, even if the script doesn't touch the LSB messages for these. It won't be 14bit smooth, but at least does the job as good as for 7bit values for the time being.

I do have a vague idea how to do proper 14bit (the problem is that I think it needs to be reliable even if there isn't exactly one LSB with each MSB), maybe if I can find some time.

Last edited by gofer; 04-09-2014 at 02:58 PM.
gofer is offline   Reply With Quote
Old 04-09-2014, 05:02 PM   #44
Soli Deo Gloria
Human being with feelings
 
Soli Deo Gloria's Avatar
 
Join Date: Oct 2013
Location: Argentina
Posts: 1,303
Default

Thanks so much, Gofer and Spk77!!!

This thread is becoming a source of midi jewels!
Soli Deo Gloria is offline   Reply With Quote
Old 04-11-2014, 05:51 AM   #45
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Thanks everybody.

Quote:
Originally Posted by gofer View Post
SPLENDID!

Thanks a lot, I'm going to look into the code, of course, too see what you did there . It seems to be working really good so far . Too bad, it can't go back to original moving the slider back left. But it does proper undo, I figure, with naming in both undo list and menu bar! I never got that to work, so there's another thing I'll have a close look at.

I think you could just allow 14bit, even if the script doesn't touch the LSB messages for these. It won't be 14bit smooth, but at least does the job as good as for 7bit values for the time being.

I do have a vague idea how to do proper 14bit (the problem is that I think it needs to be reliable even if there isn't exactly one LSB with each MSB), maybe if I can find some time.
I'll clean/optimize the code (there is some unnecessary code there) and get rid of the arrays - it will be faster that way. I have to study how to "combine" 14bit values. Btw, I'm using Undo_OnStateChange("Smoothen CCs") to add undo points (it adds an undo point when the lmb is released).

Which one is better (in the gif below)?
  • old version - get average values from selected CCs only
  • new version - get average values from selected CCs + first unselected CC (or last unselected CCs before the selection)



(same behavior in both versions when all CCs are selected in the "last clicked lane")
spk77 is offline   Reply With Quote
Old 04-11-2014, 07:21 AM   #46
Soli Deo Gloria
Human being with feelings
 
Soli Deo Gloria's Avatar
 
Join Date: Oct 2013
Location: Argentina
Posts: 1,303
Default

Quote:
Originally Posted by spk77 View Post
Which one is better (in the gif below)?
  • old version - get average values from selected CCs only
  • new version - get average values from selected CCs + first unselected CC (or last unselected CCs before the selection)


Well, for me it depends on the need of the moment. Is it difficult/annoying to add an option?
Soli Deo Gloria is offline   Reply With Quote
Old 04-11-2014, 07:24 AM   #47
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by Soli Deo Gloria View Post


Well, for me it depends on the need of the moment. Is it difficult/annoying to add an option?
It's difficult/annoying, but I'll add it as an option
spk77 is offline   Reply With Quote
Old 04-11-2014, 07:24 AM   #48
Breeder
Human being with feelings
 
Breeder's Avatar
 
Join Date: Nov 2010
Posts: 2,436
Default

Quote:
Originally Posted by spk77 View Post
I have to study how to "combine" 14bit values.
Just shift MSB a bit (no pun intented) to make room for LSB and then OR it to add them

MSB << 7 | LSB
Breeder is offline   Reply With Quote
Old 04-11-2014, 07:40 AM   #49
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by Breeder View Post
Just shift MSB a bit (no pun intented) to make room for LSB and then OR it to add them

MSB << 7 | LSB
Thanks Breeder (I'll poke them with mouse cursor and see if they umm..."combine" )
spk77 is offline   Reply With Quote
Old 04-11-2014, 08:46 AM   #50
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

Quote:
Originally Posted by spk77 View Post
Thanks everybody.



I'll clean/optimize the code (there is some unnecessary code there) and get rid of the arrays - it will be faster that way. I have to study how to "combine" 14bit values. Btw, I'm using Undo_OnStateChange("Smoothen CCs") to add undo points (it adds an undo point when the lmb is released).

Which one is better (in the gif below)?
  • old version - get average values from selected CCs only
  • new version - get average values from selected CCs + first unselected CC (or last unselected CCs before the selection)

[cool licecap]

(same behavior in both versions when all CCs are selected in the "last clicked lane")
If I had to choose I'd vote for the old behavior any time. Although the new version definitely has something to it, I find it can stray away from the original "curves" too much.
I have yet another useful behavior to ponder: I made one that leaves the first and last selected event untouched (but uses them to calculate the neighbor value, of course).


As of 14bit, keep in mind that although Reaper's drawn 14bit always come nicely in MSB/LSB pairs on the same timestamp, this is most likely, but not guaranteed to be the case. There could potentially be multiple LSB between two MSB and there could also be MSB without accompaining LSB for whatever reason. So you'll need to check each LSB and calculate it based on the latest MSB in all cases.

You can practice the basic math with pitchbend (shameless plug to add support for pitch messages ). The basic math is the same, but the handling is lots easier, as both MSB and LSB come in a single event. My clumsy take on it is in the pitch section of my "smooth" example script.
gofer is offline   Reply With Quote
Old 04-11-2014, 10:44 AM   #51
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by gofer View Post
If I had to choose I'd vote for the old behavior any time. Although the new version definitely has something to it, I find it can stray away from the original "curves" too much.
I have yet another useful behavior to ponder: I made one that leaves the first and last selected event untouched (but uses them to calculate the neighbor value, of course).

Ok, I uploaded a new version (download link is in the post #41):
  • not using arrays anymore
  • keeps the original curve better (more expected behavior)



Edit: This didn't work correctly when different CC types were selected -> back to the (optimized) original version. Zip file updated.

Last edited by spk77; 04-13-2014 at 01:23 PM.
spk77 is offline   Reply With Quote
Old 04-15-2014, 08:34 AM   #52
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

I hope this works. (Smooth 14-bit CCs - Please test first )
(download link is in the post#41)

spk77 is offline   Reply With Quote
Old 04-15-2014, 09:54 AM   #53
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

Hard to tell whether 14bit smoothing works mathematically correct, but it looks damn cool . Good work!

Maybe the readout should be a bit different? Instead of "CC 260, Foot Pedal MSB(14-bit) I think something like "CC 4/36, Foot Pedal MSB/LSB(14-bit) would be better (I don't think Reaper calls it CC260 anywhere but the API).

Can't tell you how much I appreciate your work on this.
gofer is offline   Reply With Quote
Old 04-16-2014, 12:14 PM   #54
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by gofer View Post
Hard to tell whether 14bit smoothing works mathematically correct, but it looks damn cool . Good work!

Maybe the readout should be a bit different? Instead of "CC 260, Foot Pedal MSB(14-bit) I think something like "CC 4/36, Foot Pedal MSB/LSB(14-bit) would be better (I don't think Reaper calls it CC260 anywhere but the API).

Can't tell you how much I appreciate your work on this.
Thanks gofer,
I had to do some bug fixes (MSB/LSB -pair related), it wasn't working at all at certain conditions. The file is updated again (post#41) - I'll modify the "CC info" part later.
spk77 is offline   Reply With Quote
Old 07-18-2014, 07:53 AM   #55
Stroudy
Human being with feelings
 
Stroudy's Avatar
 
Join Date: Jul 2014
Location: London
Posts: 734
Default

I'm really struggling to get this to work.

I'm new to reaper and scripts. I've made a text file, saved it as and .eel and put it in the scipt folder and loaded it in my actions list, but I get a Syntax error - seems to be on the first line.

A lot of the other scripts here seem to be working - and they're amazing! so thanks

Quote:
Originally Posted by gofer View Post
5) Select only highest notes of selected chords
The high-note version of 3)
Code:
# Unselect all notes of the current selection which are not the highest note of a chord (only active take in the current active MIDI editor)
# unselects all single notes

from reaper_python import *

def selectHighestNoteInSelectedChords():

	take = RPR_MIDIEditor_GetTake(RPR_MIDIEditor_GetActive())
	countNotes = RPR_MIDI_CountEvts(take, 0, 0, 0)[2]
	selNotes = []
	chordPitch = [] # for some reason it seemed faster to create this extra list of pitches parallel to the full properties list instead of just using that??
	chordProp = []
	noChord = 0
	time = 0.0, 0.0
	
	if countNotes !=0:
		sel = RPR_MIDI_EnumSelNotes(take, -1)
		while sel != -1:
			ok, take, i, isSelected, isMuted, startPpqPos, endPpqPos, channel, pitch, velocity = RPR_MIDI_GetNote(take, sel, 0, 0, 0.0, 0.0, 0, 0, 0)
			noteProp = ok, take, i, isSelected, isMuted, startPpqPos, endPpqPos, channel, pitch, velocity
			
			if startPpqPos > time[1] - 120: # is no overlap (chord). (-120) to allow notes to overlap a little without counting as chord
				time = startPpqPos, endPpqPos # set new time range with the current note
				chordPropOld = chordProp
				chordPitch = []  # clear list...
				chordPitch.append(pitch) #...to try a new chord with the current note (in next iteration)
				chordProp = []  # clear list...
				chordProp.append(noteProp) #...to try a new chord with the current note (in next iteration)
				if noChord > 0: #last iteration was no chord -> unselect last iteration's note
					n = len(chordPropOld)-1
					RPR_MIDI_SetNote(take, chordPropOld[n][2], 0, chordPropOld[n][4], chordPropOld[n][5], chordPropOld[n][6], chordPropOld[n][7], chordPropOld[n][8], chordPropOld[n][9])
					chordPropOld =[]
				else:
					noChord += 1
					
				#fixage for "the very last selected note is no chord":
				sel2 = RPR_MIDI_EnumSelNotes(take, sel)
				if sel2 == -1:
					n = len(chordProp)-1
					RPR_MIDI_SetNote(take, chordProp[n][2], 0, chordProp[n][4], chordProp[n][5], chordProp[n][6], chordProp[n][7], chordProp[n][8], chordProp[n][9])

			elif startPpqPos <= time[1] - 120: # is chord. (-120) to allow notes to overlap a little without counting as chord
				noChord = 0
				chordPitch.append(pitch)
				chordProp.append(noteProp)
				if endPpqPos > time[1]: # widen time range to include the current note
					time = time[0], endPpqPos
						
			for k in range(len(chordProp)):
				if chordPitch[k] < max(chordPitch):
					RPR_MIDI_SetNote(take, chordProp[k][2], 0, chordProp[k][4], chordProp[k][5], chordProp[k][6], chordProp[k][7], chordProp[k][8], chordProp[k][9])			
			
			sel = RPR_MIDI_EnumSelNotes(take, sel)

selectHighestNoteInSelectedChords()
6) Select only highest notes of selected chords - leave single notes selected
The high-note version of 4)
Code:
# Unselect all notes of the current selection which are not the highest note of a chord (only active take in the current active MIDI editor)
# keeps single notes selected

from reaper_python import *

def selectHighestNoteInSelectedChords2():

	take = RPR_MIDIEditor_GetTake(RPR_MIDIEditor_GetActive())
	countNotes = RPR_MIDI_CountEvts(take, 0, 0, 0)[2]
	selNotes = []
	chordPitch = [] # for some reason it seemed faster to create this extra list of pitches parallel to the full properties list instead of just using that??
	chordProp = []
	noChord = 0
	time = 0.0, 0.0
	
	if countNotes !=0:
		sel = RPR_MIDI_EnumSelNotes(take, -1)
		while sel != -1:
			ok, take, i, isSelected, isMuted, startPpqPos, endPpqPos, channel, pitch, velocity = RPR_MIDI_GetNote(take, sel, 0, 0, 0.0, 0.0, 0, 0, 0)
			noteProp = ok, take, i, isSelected, isMuted, startPpqPos, endPpqPos, channel, pitch, velocity
			
			if startPpqPos > time[1] - 120: # is no overlap (chord). (-120) to allow notes to overlap a little without counting as chord
				time = startPpqPos, endPpqPos # set new time range with the current note
				chordPitch = []  # clear list...
				chordPitch.append(pitch) #...to try a new chord with the current note (in next iteration)
				chordProp = []  # clear list...
				chordProp.append(noteProp) #...to try a new chord with the current note (in next iteration)
				if noChord == 0: #last iteration was no chord -> unselect last iteration's note
					noChord += 1

			elif startPpqPos <= time[1] - 120: # is chord. (-120) to allow notes to overlap a little without counting as chord
				noChord = 0
				chordPitch.append(pitch)
				chordProp.append(noteProp)
				if endPpqPos > time[1]: # widen time range to include the current note
					time = time[0], endPpqPos
						
			for k in range(len(chordProp)):
				if chordPitch[k] < max(chordPitch):
					RPR_MIDI_SetNote(take, chordProp[k][2], 0, chordProp[k][4], chordProp[k][5], chordProp[k][6], chordProp[k][7], chordProp[k][8], chordProp[k][9])			
			
			sel = RPR_MIDI_EnumSelNotes(take, sel)

selectHighestNoteInSelectedChords2()
Stroudy is offline   Reply With Quote
Old 07-18-2014, 08:26 AM   #56
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by Stroudy View Post
I'm really struggling to get this to work.

I'm new to reaper and scripts. I've made a text file, saved it as and .eel and put it in the scipt folder and loaded it in my actions list, but I get a Syntax error - seems to be on the first line.

A lot of the other scripts here seem to be working - and they're amazing! so thanks
Those are Python scripts - save as "scriptname.py".
(You have to install Python if you don't have it installed.)
spk77 is offline   Reply With Quote
Old 07-18-2014, 09:31 AM   #57
Stroudy
Human being with feelings
 
Stroudy's Avatar
 
Join Date: Jul 2014
Location: London
Posts: 734
Default

Quote:
Originally Posted by spk77 View Post
Those are Python scripts - save as "scriptname.py".
(You have to install Python if you don't have it installed.)
Ah, I see. Thanks.

Wow, these are great. I thought these were gonna be functions I'd miss from Logic, but no, instead they're better.

Cheers
Stroudy is offline   Reply With Quote
Old 07-18-2014, 11:15 AM   #58
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

Thanks
Ah yeah, Python vs Eel example was really sometimes not clear enough without actually reading the code. I edited my posts to make it more obvious which is .py and which is .eel. Alas, most of mine are still not "eelized", I just don't get around to it enough to make real progress.

Anecdote: the "select notes of the same pitch class" script is born directly out of the wish to have Logic's "select similar event" function in Reaper . Initially I planned to do the CC part of it as well, but found I only ever used it with notes, so I didn't...

As of the "select hi/low note in chord" scripts, I probably should also do some to select second highest (second lowest) notes. And versions which unselect the specific notes instead and leave the other notes selected.

Last edited by gofer; 07-18-2014 at 11:20 AM.
gofer is offline   Reply With Quote
Old 07-21-2014, 11:43 AM   #59
Stroudy
Human being with feelings
 
Stroudy's Avatar
 
Join Date: Jul 2014
Location: London
Posts: 734
Default

Quote:
Originally Posted by gofer View Post
Thanks
Ah yeah, Python vs Eel example was really sometimes not clear enough without actually reading the code. I edited my posts to make it more obvious which is .py and which is .eel. Alas, most of mine are still not "eelized", I just don't get around to it enough to make real progress.

Anecdote: the "select notes of the same pitch class" script is born directly out of the wish to have Logic's "select similar event" function in Reaper . Initially I planned to do the CC part of it as well, but found I only ever used it with notes, so I didn't...

As of the "select hi/low note in chord" scripts, I probably should also do some to select second highest (second lowest) notes. And versions which unselect the specific notes instead and leave the other notes selected.
If they work - I'm happy wether they're python, eel, newt, reptile or amphibian.

I forgot how much I used "select similar event". I used it to select notes in a played harp gliss using the white keys when making gliss chords or non-maj-min scale stuff.

Selecting other voices in a chord could be good. I got pretty quick in eliminating notes using what Logic had, but "select 2nd, 3rd, 4th voice" would be useful in a tool bar.

I've added email notifications for this thread so I hope to see it on here one day

thanks again
Stroudy is offline   Reply With Quote
Old 07-21-2014, 01:41 PM   #60
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

I tried to do "select second lowest" last weekend but ran against some tough walls. I thought it would be as easy as change a value or two, but naah...

But I need to crack it at some point, can't be that hard, it's prolly just that my braincell is so easily confused .
I'm a really bad keyboardist when it comes to chords, so the stuff I play in is mostly close voicings. I long for a function to select all the "second lowest" (the second highest) and transpose them all 1 octave down (up) to widen my voicings fast and easy (or copy them for the extra fat).
gofer is offline   Reply With Quote
Old 05-04-2015, 12:52 PM   #61
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,107
Default

Quote:
Originally Posted by spk77 View Post
Just for fun - MIDI note selector
...for MIDI notes in time selection. If the time selection isn't set -> range == item start to item end (thanks gofer ) [...].
This note selector tool (which I use all the time, thank you !) works fine in R4 with pooled items.

Seems this functionality is broken in R5
Still works fine with unpooled MIDI items but when I try to use it on pooled items, nothing happens.

Any chance this could get fixed for R5 please ?

edit:
Tested in pre29

Last edited by nofish; 05-04-2015 at 12:58 PM.
nofish is offline   Reply With Quote
Old 05-04-2015, 02:02 PM   #62
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by nofish View Post
This note selector tool (which I use all the time, thank you !) works fine in R4 with pooled items.

Seems this functionality is broken in R5
Still works fine with unpooled MIDI items but when I try to use it on pooled items, nothing happens.

Any chance this could get fixed for R5 please ?

edit:
Tested in pre29
I think it works here (v5.0pre29, Win8.1):

(These items are pooled)
spk77 is offline   Reply With Quote
Old 05-04-2015, 06:16 PM   #63
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,107
Default

Quote:
Originally Posted by spk77 View Post
I think it works here (v5.0pre29, Win8.1):
Thanks for checking spk77.

I did some more testing now and I noticed it seems to depend on which item is selected (active / editable).

When first item is selected it works, but not when the second one is selected.
When both are selected it also works.

nofish is offline   Reply With Quote
Old 05-15-2015, 01:15 PM   #64
mezzo
Human being with feelings
 
Join Date: Sep 2014
Posts: 28
Default

gofer

Thanks for scripts ! Cool!
But in Reaper 5 (pre31,sws 2.7.1) "Select highest note..." and some stopped worked (((.In 4.78 all OK.It's normally? No chance? :-)
mezzo is offline   Reply With Quote
Old 05-16-2015, 12:54 AM   #65
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

Yep. You're getting a message about "positional argument missing", right?

MIDI_SetNote has changed a bit in v5. There has been an argument added (noSortInOptional) to the function. I'm not sure whether it's a bug that Reaper complains about it, as it has "Optional" in the name.
I don't think it would be a good idea to fix the codes here in the thread, because then it won't work in v4.x anymore. Also, Cockos might/should fix the error message coming up on their end (by really making that argument optional). Normally, they don't tend to introduce backward incompatibility.


The fix is easy, though, and you can do it yourself:

For each of the scripts that throws the "MIDI_SetNote misses an argument" error, open it in the script editor (action list -> ReaScript: -> Edit...) and look for lines with "RPR_MIDI_SetNote( yadda, ladda, bla ...)" and simply add in a ", 0" (comma space zero without the "") at the end of the function's arguments, inside the round brackets. You may forget the space, but comma and zero are mandatory. Do this for all "RPR_MIDI_SetNote()", but only for those. Do not change anything else, unless you know what you're doing.

I can't give you a line to copy/paste, as each looks a tad different. But here's an example of how the last SetNote line of "select highest of selected chords" has to look. It's at the very end of the line, so you may need to scroll this code box (I colored the change in red):

Code:
RPR_MIDI_SetNote(take, chordProp[k][2], 0, chordProp[k][4], chordProp[k][5], chordProp[k][6], chordProp[k][7], chordProp[k][8], chordProp[k][9], 0)
As said, don't copy paste from here, just place your cursor and type in ", 0" at the appropriate spots. Then hit ctrl+s to save.
If you still get the message, you forgot one. As soon as you did this change to all MIDI_SetNote function calls, the error message is history.

Last edited by gofer; 05-16-2015 at 01:14 AM.
gofer is offline   Reply With Quote
Old 05-16-2015, 06:24 AM   #66
mezzo
Human being with feelings
 
Join Date: Sep 2014
Posts: 28
Default

You're Wizard! :-) Worked!
Great Thanks!
mezzo is offline   Reply With Quote
Old 05-18-2015, 02:28 AM   #67
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default

YAY! I (think I) have finally cracked porting "select high(low)est note.." scripts to EEL .

On the way I found out that the above error (number of arguments for MIDI_SetNote) is not an issue in EEL, not sure about LUA, but sure is in Python.

Now the last one of the bunch in this thread that's still not completely eeled is the smooth CC thing. But there's spk77's beautiful slider version of it to be had .
Think I bundle the finished eel versions and put them onto stash. Later today, though. First I'll have to endure some RL duties.


I tried to come up with one that unselects only the lowest note, but am trapped by my own approach as of now. A pity, because "Unselect only lowest" + "Select only lowest" would effectively be "Select only second lowest". Which I was trying to do as well.
gofer is offline   Reply With Quote
Old 05-19-2015, 01:55 AM   #68
gofer
-blänk-
 
gofer's Avatar
 
Join Date: Jun 2008
Posts: 11,359
Default Thanks, everybody :)

Get the bunch of eels from the stash while they're fresh! basket full of fish

Missing is "Smooth values of selected events on last touched CC lane", but spk77 made an awesomized slider version you can find in post #41 of this very thread.


It's a huge pleasure for me to see how some fantastic scripts have spawned during the course of this thread .
Make sure you have a look at spk's hugely enhanced slider version of "Unselect every second event:post #26.
And the magical "MIDI Velocity tool", which actually is able to create ramps not only on velocities, but on CC as well. Get it here.

If I have missed to link some, please shout.
gofer is offline   Reply With Quote
Old 06-07-2015, 12:33 PM   #69
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,458
Default

Is it possible to do a modified version of this script that would work on the currently selected notes and not on a defined pitch, as it currently stands?

Quote:
Originally Posted by spk77 View Post
Just for fun - MIDI note selector
...for MIDI notes in time selection. If the time selection isn't set -> range == item start to item end (thanks gofer ).
  • Use mouse wheel to adjust values
  • Ctrl+lmb resets the values
  • "Pitch" (filter) changes the active note row in MIDI editor.
  • Two modes: select or unselect every nth note" (left click to change the mode)



Code:
// MIDI note selector (original "note selection logic" by Veto and gofer :))
//  9.3.2014 (spk77)
//  - added "pitch filter"
//  - added "unselect mode"
//  - no time selection -> range == item start to item end, thanks gofer

function highlight_mouse_hover()
(
  gfx_r += 0.1;
  gfx_g += 0.1;
  gfx_b += 0.1;
);

function highlight_mouse_on_press()
(
  gfx_r += 0.2;
  gfx_g += 0.2;
  gfx_b += 0.2;
);

 function draw_string_step(x, y, r, g, b, a) local (w, h)
( 
  gfx_r = r;
  gfx_g = g;
  gfx_b = b;
  gfx_a = a;
  
  step_s = sprintf(#, "%d", step);
  gfx_measurestr(step_s, w, h);
  // is mouse on string?
  mouse_x >= x && mouse_x <= x + gfx_w && mouse_y >= y && mouse_y <= y + h ? (
    highlight_mouse_hover();
    mouse_wheel != 0 ? (
      highlight_mouse_on_press();
      step += (mouse_wheel / abs(mouse_wheel));
      step < 1 ? step = 1;
      mouse_wheel = 0;
    );
    mouse_cap == 5 ? (
      step = 1;
    );
  );
  mode == "select" ? gfx_printf("Select every ") : gfx_printf("Unselect every ");
  gfx_printf("%d", step);
  gfx_printf(". note");
);

 function draw_string_offset(x, y, r, g, b, a) local (w, h)
( 
  gfx_r = r;
  gfx_g = g;
  gfx_b = b;
  gfx_a = a;
  
  offset_s = sprintf(#, "%d", offset);
  gfx_measurestr(offset_s, w, h);
  // is mouse on string?
  mouse_x >= x && mouse_x <= x + gfx_w && mouse_y >= y && mouse_y <= y + h ? (
    highlight_mouse_hover();
    mouse_wheel != 0 ? (
      highlight_mouse_on_press();
      offset += (mouse_wheel / abs(mouse_wheel));
      offset < 0 ? offset = 0;
      offset > step - 1 ? offset = step - 1;
      mouse_wheel = 0;
    );
    mouse_cap == 5 ? (
      offset = 0;
    );
  );
  gfx_printf("Offset: ");
  gfx_printf("%d", offset);
);

 function draw_string_pitch(x, y, r, g, b, a) local (w, h)
( 
  gfx_r = r;
  gfx_g = g;
  gfx_b = b;
  gfx_a = a;
  
  sel_pitch_s = sprintf(#, "%d", sel_pitch);
  gfx_measurestr(sel_pitch_s, w, h);
  // is mouse on string?
  mouse_x >= x && mouse_x <= x + gfx_w && mouse_y >= y && mouse_y <= y + h ? (
    highlight_mouse_hover();
    mouse_wheel != 0 ? (
      highlight_mouse_on_press();
      mouse_wheel / abs(mouse_wheel) < 0 ? (
        sel_pitch > 0 ? (
          MIDIEditor_OnCommand(MIDIEditor_GetActive(), 40050);
        );
      ) : sel_pitch < 127 ? (
        MIDIEditor_OnCommand(MIDIEditor_GetActive(), 40049);
      );
      sel_pitch = MIDIEditor_GetSetting_int(MIDIEditor_GetActive(), "active_note_row");
      mouse_wheel = 0;
    );
  );
  gfx_printf("Pitch: ");
  gfx_printf("%d", sel_pitch);
);

 function draw_string_mode(x, y, r, g, b, a) local (w, h)
( 
  gfx_r = r;
  gfx_g = g;
  gfx_b = b;
  gfx_a = a;
  
  mode_s = sprintf(#, "%d", offset);
  gfx_measurestr(offset_s, w, h);
  // is mouse on string?
  mouse_x >= x && mouse_x <= x + gfx_w && mouse_y >= y && mouse_y <= y + h ? (
    highlight_mouse_hover();
    mouse_cap == 1 && lmb_down == 0 ? (
      highlight_mouse_on_press();
      mode == "select" ? mode = "unselect" : mode = "select";
      need_update = 1;
    );
  );
  gfx_printf("Mode: ");
  gfx_printf("%s", mode);
);

function select_notes()
(
  index = 0;
  k = -offset;
  loop(note_count,
    MIDI_GetNote(take, index, isSelected, isMuted, startPpqPos, endPpqPos, channel, note_pitch, velocity) ? (
      k % step == 0 && (endPpqPos > time_sel_start && startPpqPos < time_sel_end) && note_pitch == sel_pitch ? (
        mode == "select" ? (
          MIDI_SetNote(take, index, 1, isMuted, startPpqPos, endPpqPos, channel, note_pitch, velocity);
        ) : mode == "unselect" ? (
          MIDI_SetNote(take, index, 0, isMuted, startPpqPos, endPpqPos, channel, note_pitch, velocity);
        );
      ) : mode == "select" ? (
          MIDI_SetNote(take, index, 0, isMuted, startPpqPos, endPpqPos, channel, note_pitch, velocity);
      ) : mode == "unselect" && note_pitch == sel_pitch && (endPpqPos > time_sel_start && startPpqPos < time_sel_end) ? (
          MIDI_SetNote(take, index, 1, isMuted, startPpqPos, endPpqPos, channel, note_pitch, velocity);
      ) : (
          MIDI_SetNote(take, index, 0, isMuted, startPpqPos, endPpqPos, channel, note_pitch, velocity);
      );
      endPpqPos > time_sel_start && startPpqPos < time_sel_end && note_pitch == sel_pitch ? k += 1;
    );
    index += 1;
  );
  last_step = step;
  last_offset = offset;
  last_pitch = sel_pitch;
);
function run()
(
  gfx_x = gfx_y = 20;
  gfx_r = 0.5;
  gfx_g = 0.8;
  gfx_b = 0.5;
  gfx_a = 1; 
  draw_string_mode(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);
  gfx_x = 20;
  gfx_y += 2 * gfx_texth;
  
  draw_string_step(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);
  gfx_x = 20;
  gfx_y += 2 * gfx_texth;
  gfx_g = 0.8;
  gfx_b = 0.5;
  gfx_a = 1;
 
  draw_string_offset(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);
  gfx_x = 20;
  gfx_y += 2 * gfx_texth;
  
  draw_string_pitch(gfx_x, gfx_y, 0.5, 0.8, 0.5, 1);
  
  GetSet_LoopTimeRange(0, 0, time_sel_start, time_sel_end, 0);
  (take = MIDIEditor_GetTake(MIDIEditor_GetActive())) ? (
    sel_pitch = MIDIEditor_GetSetting_int(MIDIEditor_GetActive(), "active_note_row");
    time_sel_start = MIDI_GetPPQPosFromProjTime(take, time_sel_start);
    time_sel_end = MIDI_GetPPQPosFromProjTime(take, time_sel_end);
    
    // no time selection -> range == item start to item end, thanks gofer :)
    time_sel_start == time_sel_end ? ( 
      item = GetMediaItemTake_Item(take);
      item_start = GetMediaItemInfo_Value(item, "D_POSITION");
      item_end = item_start + GetMediaItemInfo_Value(item, "D_LENGTH");
      time_sel_start = MIDI_GetPPQPosFromProjTime(take, item_start);
      time_sel_end = MIDI_GetPPQPosFromProjTime(take, item_end);
    );
    
    MIDI_CountEvts(take, note_count, cc_count, sysEx_count);

    (mouse_x >= 0 && mouse_x <= gfx_w && mouse_y >= 0 && mouse_y <= gfx_h) && (last_step != step || last_offset != offset || last_pitch != sel_pitch || need_update == 1) ? (
      select_notes();
    );
    last_step = step;
    last_offset = offset;
    last_pitch = sel_pitch;
  );
  need_update = 0;
  mouse_cap == 1 ? lmb_down = 1 : lmb_down = 0;
  
  gfx_update();
  gfx_getchar() >= 0 ? defer("run();");
);

gfx_init("MIDI note selector", 200, 150);
gfx_setfont(1, "Verdana", 16);

step = 1;
last_step = -1;
offset = 0;
last_offset = -1;
sel_pitch = 0;
last_pitch = -1;

mode = "select";

need_update = 0;

lmb_down = 0;

run();
amagalma is offline   Reply With Quote
Old 06-11-2015, 06:33 AM   #70
drew
Mobile
 
drew's Avatar
 
Join Date: Jan 2006
Location: London & São Paulo. Hardcore commercial REAPERite
Posts: 1,669
Default

@gofer.. Just to say - loving your work.. and your creative ideas!
__________________
Proudly using REAPER exclusively for...
* Media and event music composition & production, sound design + auto-processing at Qsonics.com
* Broadcast branding, promos, education & training and narration voice-overs at DrewWhite.com
drew is offline   Reply With Quote
Old 07-02-2016, 06:09 PM   #71
pcartwright
Human being with feelings
 
Join Date: Jan 2009
Posts: 1,030
Default

Quote:
Originally Posted by amagalma View Post
Is it possible to do a modified version of this script that would work on the currently selected notes and not on a defined pitch, as it currently stands?
+1. I have a need for this type of functionality as well.
pcartwright is offline   Reply With Quote
Old 11-27-2016, 03:13 PM   #72
o_e
Human being with feelings
 
o_e's Avatar
 
Join Date: May 2016
Posts: 681
Default

Quote:
Originally Posted by spk77 View Post
Just for fun - MIDI note selector
...for MIDI notes in time selection. If the time selection isn't set -> range == item start to item end (thanks gofer ).

Updates:
  • 5-Sep-2015
    • Now it shows note numbers and note names



Instructions:
  • Use mouse wheel to adjust values
  • Ctrl+lmb resets the values
  • "Pitch" (filter) changes the active note row in MIDI editor.
  • Two modes: select or unselect every nth note" (left click to change the mode)



Download:
https://stash.reaper.fm/25039/MIDI%20note%20selector.eel

Great! Thanks!
Does the script also work if I have different pitches, like a melody where I want to modify every other note (or is it possible to modify the script in that sense..)?

ole

edit: Or even better would be if a pitch range could be set e.g. '60-72'
edit2: just saw that this functionalty is already requested..
o_e is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 10:19 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.