NoteWorthy Composer Forum

Forums => Tips & Tricks => User Tools => Topic started by: Rick G. on 2007-04-21 02:15 am

Title: Chord Inversion Tool
Post by: Rick G. on 2007-04-21 02:15 am
A little tool to invert chords. RestChords and Chords with split stems are ignored.
The lowest note in a Chord is moved up by an octave until it occupies its own line.  This results in a new inversion.
Run it more than once to get the inversion you want.
Since the tool doesn't know about implied accidentals, forcing accidentals will sometimes be needed.

Copy the code and save it in your Scripts folder as: invert.vbs
Code: [Select · Download]
Option Explicit ' Invert.vbs, Ver 1.0 - Rick G.
Dim a1, a2, a3, e
Do Until WScript.StdIn.AtEndOfStream
  a1 = Split(WScript.StdIn.ReadLine, "|")
  If UBound(Filter(a1, "Chord")) = 0 Then
    If UBound(Filter(a1, "Dur2:")) = -1 Then
      a2 = Split(Mid(a1(3), 5), ",")
      a3 = aPos(a2(0))
      For Each e In a2
        a3(1) = a3(1) - 7 * (aPos(e)(1) - a3(1) = 0)
      Next
      a2(0) = Join(a3, "")
      a1(3) = "Pos:" & Join(a2, ",")
    End If
  End If
  WScript.StdOut.WriteLine Join(a1, "|")
Loop

Function aPos(s) ' NotePitchPos to array
  Dim test: test = Split("nb#xv ? oxXz ^")
  Dim r(3), c, i ' retval, char, index
  r(1) = s: c = Left(s, 1) ' acc?
  For Each i In Array(0, 3, 2)
    If InStr(test(i), c) Then r(i) = c
    r(1) = Replace(r(1), r(i), "", 1, 1)
    c = Right(r(1), 1) ' tie?, head?
  Next: aPos = r ' acc, pos, head, tie
End Function
Copy this and add it to: nwc2UserTools.ini
Code: [Select · Download]
Invert Chord(s)='wscript scripts\invert.vbs'

All the work is done in the first For/Next loop. The rest of the code parses the input and recombines it.

2007Apr21 - fixed indentation in code.
Title: Re: Chord Inversion Tool
Post by: Lawrie Pardy on 2007-04-21 06:03 am
G'day Rick,
very neat mate, I like it!

Got me to thinking...  A global mod expression:

Chord Pos.0+=7

Will do the same thing until there is something on the octave Pos, then it errors.  Your new tool doesn't have that problem.

If I get some time, it would be worth looking to see how hard it would be to specify moving the bottom note up or the top note down.  This would allow more flexibility.  A little exercise for the student perhaps?  ;)
Title: Re: Chord Inversion Tool
Post by: Rick G. on 2007-04-21 06:16 am
If I get some time, it would be worth looking to see how hard it would be to specify moving the bottom note up or the top note down.
This would require the code to scan the note position array from top to bottom. You couldn't use For Each.

Your Global Mod will choke on a split chord.
Title: Re: Chord Inversion Tool
Post by: Lawrie Pardy on 2007-04-21 06:38 am
G'day Rick,
like I said, an exercise for the student: ME

If I can manage to make the time...

Your Global Mod will choke on a split chord.

Actually, Global Mod is Andrew Purdam's.  I use it a lot, but it does have it's limitations...  I suspect it has outperformed Andrew's original expectations fairly significantly...

Split chord: Depending on the circumstances it will either get it wrong, or error out...  In a preliminary test if the shorter duration is at the top of the chord it will be OK, if at the bottom you get an error...  However in either case, you won't get what you're expecting...
Title: Re: Chord Inversion Tool
Post by: Rick G. on 2007-04-21 07:20 am
I was using the phrase "Your Global Mod" idiomatically, as in: your use of Global Mod. Like most good tools, its uses expand as you use it.
Title: Re: Chord Inversion Tool
Post by: Lawrie Pardy on 2007-04-21 08:33 am
Oops, sorry.  I'm a bit tired and didn't pick that up - bit subtle for me when I'm like this...
Title: Re: Chord Inversion Tool
Post by: Rick G. on 2008-06-17 06:39 am
A JScript version. This handles RestChords but ignores split Chords.
I think I'm getting the "hang" of regular expressions.
Quote from: Invert.js
/*
   NWC2 User Tool, Ver 1.3 - Rick G.
   Purpose: Invert Chord(s)
   &Command: WScript Scripts\Invert.js
*/
var a, j, io = WScript.StdIn.ReadAll().split("\r\n");
for (j in io){
   if (io[j].match(/^|"|Dur:|Pos2?:/g).length != 3) continue;
   a = /(Pos2?:[^-\d]*)(-?\d+)([^|]*)/.exec(io[j]);
   if (a[3].match(/^|-?\d+/g).length < 2) continue;
   while ((a[2] -= -7) <= RegExp.lastMatch) ;
   io[j] = io[j].replace(a[0], a[1] + a[2] + a[3]);
}
WScript.StdOut.Write(io.join("\r\n"));
Edit: Update to ver 1.3
This version always moves the bottom note higher than the top note. Handy for putting the Alto on top of the Soprano.