Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

MusE is a DAW for Linux with both MIDI and Audio editing. https://muse-sequencer.github.io

Moderators: MattKingUSA, khz, spamatica

Post Reply
User avatar
GraysonPeddie
Established Member
Posts: 661
Joined: Sun Feb 12, 2012 11:12 pm
Location: Altha, FL
Been thanked: 6 times
Contact:

Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by GraysonPeddie »

Is there a way to reverse MIDI notes as shown in the video for the MusE Sequencer? I could not find the function in either the Function and Scripts menu.

https://www.youtube.com/watch?v=vR-nbz8DJzI
--Grayson Peddie

Music Interest: New Age w/ a mix of modern smooth jazz, light techno/trance & downtempo -- something Epcot Future World/Tomorrowland-flavored.
spamatica
Established Member
Posts: 583
Joined: Mon Feb 08, 2010 10:38 am
Has thanked: 86 times
Been thanked: 101 times

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by spamatica »

Hi Grayson,

I think you are correct, it does not exist currently.

It would however be perfectly doable to implement with a script, both reverse and stretching (kind of, we already have SpeedHalf and SpeedDouble), but before rushing to do so I'd ask anyone who wishes to dip their feet in script writing to try and implement it for us.
I would be happy to lend a hand here in this thread.

The script https://github.com/muse-sequencer/muse/ ... /SpeedHalf is a good start, as well as the README in the same folder.
MusE DAW
User avatar
oscillator
Established Member
Posts: 1127
Joined: Sat Jan 17, 2015 6:07 pm
Location: SWEDEN
Has thanked: 725 times
Been thanked: 298 times
Contact:

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by oscillator »

Well, I did a timestretch script, and sent a pull request for that one, I don't know why it doesn't show up:

https://github.com/muse-sequencer/muse/issues/1037

https://github.com/muse-sequencer/muse/pull/1065

But for the reverse thingie, SpeedHalf should be a good starting point as it doesn't have a UI = simpler code.

/Staffan

MusE DAW running on Debian 11 Testing/XFCE4.
https://oscillator.se/musik

spamatica
Established Member
Posts: 583
Joined: Mon Feb 08, 2010 10:38 am
Has thanked: 86 times
Been thanked: 101 times

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by spamatica »

oscillator wrote: Mon May 02, 2022 8:44 pm Well, I did a timestretch script, and sent a pull request for that one, I don't know why it doesn't show up:
Ah, indeed! It doesn't appear to be in the repository, maybe it wasn't actually added in git?
MusE DAW
User avatar
oscillator
Established Member
Posts: 1127
Joined: Sat Jan 17, 2015 6:07 pm
Location: SWEDEN
Has thanked: 725 times
Been thanked: 298 times
Contact:

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by oscillator »

spamatica wrote: Mon May 02, 2022 10:09 pm Ah, indeed! It doesn't appear to be in the repository, maybe it wasn't actually added in git?
I seemed to have messed up but I did a new pull request with the file, I hope that is the right way to fix it. :)

MusE DAW running on Debian 11 Testing/XFCE4.
https://oscillator.se/musik

User avatar
oscillator
Established Member
Posts: 1127
Joined: Sat Jan 17, 2015 6:07 pm
Location: SWEDEN
Has thanked: 725 times
Been thanked: 298 times
Contact:

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by oscillator »

So, I think I have a working Reverse script:

Code: Select all

import sys,time
testFile = open(sys.argv[1],"r")
inputEvents = testFile.readlines()
testFile.close()

for line in inputEvents:
      if line.startswith('PART'):
            tag,startticks,partticks = line.split(' ')
     
outputEvents=[]
#loop through events
for line in inputEvents:
      if line.startswith('NOTE'):
            tag,tick,pitch,length,velocity = line.split(' ')
            newtick = int(partticks) - int(tick) - int(length)
            newline = tag + " " + str(int(newtick)) + " " + pitch + " " + length + " " + velocity
            outputEvents.append(newline)
      else:
        outputEvents.append(line)

testFile = open(sys.argv[1],"w")
testFile.writelines(outputEvents)
testFile.close()
The README.txt in the scripts folder is wrong. It says:

Code: Select all

PARTLEN <len in ticks of the current Part>
but there is no such tag. But, there is a

Code: Select all

PART <start tick> <len in ticks>
which I use.

The trick with this script was to realise than I can't use "invert" the time (take the len of the part and subtract the start pos of the note), but we must also subtract the note len.

EDIT. This currently only works as expected for note (MIDI) parts, not for drum parts as they have a note length of 32 ticks... I think the solution to this is to change the line with the calculation of newtick to:

Code: Select all

            newtick = int(partticks) - int(tick)
so we could have two scripts, ReverseNotes and ReverseDrums.

We could also modify scripts.cpp to output a tag describing the part type (if there is such a member).

Hmmm, now I see that all scripts can be called for several parts at the same time, I should adjust for that too...

MusE DAW running on Debian 11 Testing/XFCE4.
https://oscillator.se/musik

spamatica
Established Member
Posts: 583
Joined: Mon Feb 08, 2010 10:38 am
Has thanked: 86 times
Been thanked: 101 times

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by spamatica »

oscillator wrote: Tue May 03, 2022 4:53 pm The README.txt in the scripts folder is wrong. It says:

Code: Select all

PARTLEN <len in ticks of the current Part>
but there is no such tag. But, there is a

Code: Select all

PART <start tick> <len in ticks>
which I use.
Alright, seems the format changed at some point, feel free to update the README.txt
I wonder why though, the ticks in the part used to be relative, so start was always zero. Not sure when it would be useful to know the absolute tick values.
oscillator wrote: Tue May 03, 2022 4:53 pm

The trick with this script was to realise than I can't use "invert" the time (take the len of the part and subtract the start pos of the note), but we must also subtract the note len.

EDIT. This currently only works as expected for note (MIDI) parts, not for drum parts as they have a note length of 32 ticks... I think the solution to this is to change the line with the calculation of newtick to:

Code: Select all

            newtick = int(partticks) - int(tick)
so we could have two scripts, ReverseNotes and ReverseDrums.

We could also modify scripts.cpp to output a tag describing the part type (if there is such a member).
I see, the 32 ticks should actually be zero in the drum case?

My stance has been to keep the format as simple as possible but if there is no way to find this out (I guess you could determine this if all notes are 32 ticks, but that may not be the best solution...), adding an easily deciphered tag is not such a big deal.
oscillator wrote: Tue May 03, 2022 4:53 pm Hmmm, now I see that all scripts can be called for several parts at the same time, I should adjust for that too...
Unless I'm mistaken they are processed separately so the script does not need to know that several parts are being processed.
MusE DAW
User avatar
oscillator
Established Member
Posts: 1127
Joined: Sat Jan 17, 2015 6:07 pm
Location: SWEDEN
Has thanked: 725 times
Been thanked: 298 times
Contact:

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by oscillator »

spamatica wrote: Wed May 04, 2022 2:24 pm Alright, seems the format changed at some point, feel free to update the README.txt
Will do! :)
spamatica wrote: Wed May 04, 2022 2:24 pm My stance has been to keep the format as simple as possible but if there is no way to find this out (I guess you could determine this if all notes are 32 ticks, but that may not be the best solution...), adding an easily deciphered tag is not such a big deal.
I've added a new tag (in scripts.cpp) called "TYPE", it finds the track type which is reachable from the part pointer, and can be either "MIDI" or "DRUM".
spamatica wrote: Wed May 04, 2022 2:24 pm Unless I'm mistaken they are processed separately so the script does not need to know that several parts are being processed.
Great! Thank you @spamatica! I will clean this up, and do a pull request tonight!

MusE DAW running on Debian 11 Testing/XFCE4.
https://oscillator.se/musik

User avatar
oscillator
Established Member
Posts: 1127
Joined: Sat Jan 17, 2015 6:07 pm
Location: SWEDEN
Has thanked: 725 times
Been thanked: 298 times
Contact:

Re: Reverse MIDI part similar to Fugue Machine/Bitwig's MIDI reverse feature

Post by oscillator »

I've finished the script and the changes in script.cpp and made a pull request (https://github.com/muse-sequencer/muse/pull/1071). And learned more about how MusE works internally! :)

MusE DAW running on Debian 11 Testing/XFCE4.
https://oscillator.se/musik

Post Reply