Jump to content

Script to transpose music chord notation in a text file


Recommended Posts

I write a lot of music chord sheets for the guys in my band, both from original and cover songs. I start off with just putting it down in a text file with chords on one line and then the lyrics on the next like this:

Gm           Cm7              F                      Bb
Times are hard You're afraid to pay the fee
             Eb                    Ab                     Bb                F/A   Eb/G   F   Eb
So you find yourself somebody Who can do the job for free

Many times after I write it all out, I'll want to transpose the key up or down a few steps and it's a pain to go through manually and change my chords. I know there are music programs that allow you to enter your music there and they can do the transposing, but I'd like to write a little Autoit script to be able to just take my text file, find the chords, transpose them by an inputted amount, and then allow me to either rewrite the file or just display it onscreen first. Sounded easy, until I tried it! I thought I'd just scan the input file for capital letters and rotate them up or down a few notches. UNLESS they're part of the lyrics. Then what about "#" and "b"? How do I recognize "Adim" as a chord and not part of some lyric? Gets to be a real mess!

Has anyone ever ventured into this kind of project? Any tips on how to go about it?

 

Link to comment
Share on other sites

I suppose if you knew the steps yourself, used only flats (as adding sharps and naturals would make the transposition harder).  You could get away with stepping the notes yourself.  This probably has many flaws and is really only acceptable as pseudo code:

#include <array.au3>

$str = "Gm           Cm7              F                      Bb" & @LF & _
"Times are hard You're afraid to pay the fee" & @LF & _
"             Eb                    Ab                     Bb                F   Eb   F   Eb" & @LF  & _
"So you find yourself somebody Who can do the job for free"

$aStr = stringsplit($str , @LF , 2)

for $i = 0 to ubound($aStr) - 1 step 2
   $aStr[$i] = stringregexpreplace($aStr[$i] , "\s+" , " ")
   $aChords = stringsplit(stringstripWS($aStr[$i] , 1) , " " , 2)
   $aChordTranspose = _Transpose(-2 , $aChords)
   _ArrayDisplay($aChordTranspose)
next


Func _Transpose($halfsteps , $array)

   Local $aNotes = ["Bb" , "B" , "C" , "Db" , "D" , "Eb" , "E" , "F" , "Gb" , "G" , "Ab" , "A" ,"Bb" , "B" , "C" , "Db" , "D" , "Eb" , "E" , "F" , "Gb" , "G" , "Ab" , "A" , "Bb" , "B" , "C" , "Db" , "D" , "Eb" , "E" , "F" , "Gb" , "G" , "Ab" , "A"]

   For $i = 0 to ubound($array) - 1
      $sTarget = stringregexp($array[$i] , "(\Db*)" , 3)[0]
      $aMatches = _ArrayFindAll($aNotes , $sTarget)
      $array[$i] = stringreplace($array[$i] , $sTarget , $aNotes[$aMatches[1] + $halfsteps])
   Next

   _ArrayDisplay($array , $halfsteps & " Steps")

EndFunc

 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

This is not too difficult! Make a transposition table with intervals and note names (2D array). Search for the note in your table and read the transposed note name directly from the table.

Name  1     2     3     4   <== semitones
C     C#    D     Eb    E
C#    D     Eb    E     F
Db    D     Eb    E     F
D     Eb    E     F     F#

Whether you use sharps or flats is up to you. You could respell the names after transposition anyway. You will probably want to avoid double sharps and double flats. Any problems, then post your attempt.

Edit: To transpose down, use (12 - interval). @iamtheky's method is also good, and a bit easier to implement.

Edited by czardas
Link to comment
Share on other sites

@czardas
Hehe, not so easy to get exactly the wanted result ... :idiot:

Here is my try... the pattern should be better defined of course

#include <Array.au3>

$str = "Gm           Cm7              F                      Bb" & @crlf & _
"Times are hard You're afraid to pay the fee" & @crlf & _
"             Eb                    Ab                     Bb                F/A   Eb/G   F   Eb" & @crlf  & _
"So you find yourself somebody Who can do the job for free" & @crlf
Msgbox(0,"", $str)

Msgbox(0,"", _Transpose($str, 2) )

Func _Transpose($song, $step)
  Local $aNotes = ["Bb" , "B" , "C" , "Db" , "D" , "Eb" , "E" , "F" , "Gb" , "G" , "Ab" , "A"]
  If $step < 0 Then $step = 12 + $step
  $pattern = '([A-Z]b?)(?=\s|/|m7?|dim|$)'
  $tmp = Execute('"' & StringRegExpReplace($song, $pattern, '" & $aNotes[Mod(_ArraySearch($aNotes, "$1")+$step, 12)] & "') & '"')
  Return $tmp
EndFunc

 

Link to comment
Share on other sites

@wysocki I think you would be interested in look here:

 

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 *

 

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE * IE on Windows 11

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2023-04-24

Link to comment
Share on other sites

I guess I can't keep this from your inquisitive minds any longer. I have some libraries which are totally overkill for this. Actually I have written a lot of stuff but it's still no where near ready for release. Here is a small sample from a few years back. The theory is too difficult to explain, but you might want to research it yourself. To understand this, you also need to understand formulaic chord/scale construction. The last row gives the number of semitones. Actually harmonic construction and transposition are not the same thing, but this covers the full range of note names and musical intervals. It might give you some ideas. A typical chord formula might look like this: p1, mi3, dim5, dim7 (diminished seventh).

Func _LoadIntervalMap()
    Local $aTemp[10][32] = _
    [["1","#1","b2","2","bb3","#2","b3","3","b4","#3","4","#4","b5","5","bb6","#5","b6","6","bb7","#6","b7","7","b8","b9","9","#9","b10","b11","11","#11","b13","13"], _
    ["C","C#","Db","D","Ebb","D#","Eb","E","Fb","E#","F","F#","Gb","G","Abb","G#","Ab","A","Bbb","A#","Bb","B","Cb","Db","D","D#","Eb","Fb","F","F#","Ab","A"], _
    ["D","D#","Eb","E","Fb","E#","F","F#","Gb","Fx","G","G#","Ab","A","Bbb","A#","Bb","B","Cb","B#","C","C#","Db","Eb","E","E#","F","Gb","G","G#","Bb","B"], _
    ["E","E#","F","F#","Gb","Fx","G","G#","Ab","Gx","A","A#","Bb","B","Cb","B#","C","C#","Db","Cx","D","D#","Eb","F","F#","Fx","G","Ab","A","A#","C","C#"], _
    ["F","F#","Gb","G","Abb","G#","Ab","A","Bbb","A#","Bb","B","Cb","C","Dbb","C#","Db","D","Ebb","D#","Eb","E","Fb","Gb","G","G#","Ab","Bbb","Bb","B","Db","D"], _
    ["G","G#","Ab","A","Bbb","A#","Bb","B","Cb","B#","C","C#","Db","D","Ebb","D#","Eb","E","Fb","E#","F","F#","Gb","Ab","A","A#","Bb","Cb","C","C#","Eb","E"], _
    ["A","A#","Bb","B","Cb","B#","C","C#","Db","Cx","D","D#","Eb","E","Fb","E#","F","F#","Gb","Fx","G","G#","Ab","Bb","B","B#","C","Db","D","D#","F","F#"], _
    ["B","B#","C","C#","Db","Cx","D","D#","Eb","Dx","E","E#","F","F#","Gb","Fx","G","G#","Ab","Gx","A","A#","Bb","C","C#","Cx","D","Eb","E","E#","G","G#"], _
    ["p1","aug1","mi2","ma2","dim3","aug2","mi3","ma3","dim4","aug3","p4","aug4","dim5","p5","dim6","aug5","mi6","ma6","dim7","aug6","mi7","ma7","dim8","mi9","ma9","aug9","mi10","dim11","p11","aug11","mi13","ma13"], _
    [0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,13,14,15,15,16,17,18,20,21]]
    Return $aTemp
EndFunc

NB: To use the 1D array method suggested by others, you might want to use the following simplified (mixed) sequence:
C, C#, D, Eb, E, F, F#, G, Ab, A, Bb, B . . . my recommendation!
for the 12 chord root names within the octave. The sequence conforms to the most commonly found chord roots. It's not theoretically correct to do this, but it is common practice to ignore such subtleties and also quite a practical solution. :)

Edit: Also this can be used to respell note names (R stands for root):

Func _LoadEnharmonicEquivalents()
    Local $aTemp[8][5] = _
    [["R","bb","b","#","x"],["C","Bb","B","Db","D"],["D","C","C#","Eb","E"],["E","D","D#","F","F#"], _
    ["F","Eb","E","Gb","G"],["G","F","F#","Ab","A"],["A","G","G#","Bb","B"],["B","A","A#","C","C#"]]
    Return $aTemp
EndFunc

@mikell Very nice. :thumbsup:

Edited by czardas
Link to comment
Share on other sites

czardas,
Following your recommendation I suggest this

#include <Array.au3>

$str = "Gm           Cm7              F#                      Bb" & @crlf & _
"Times are hard You're afraid to pay the fee" & @crlf & _
"             Eb                    Ab                     Bb                F/A   Eb/G   F   Eb" & @crlf  & _
"So you find yourself somebody Who can do the job for free" & @crlf
;Msgbox(0,"", $str)

Msgbox(0,"", _Transpose($str, -2, 1) )

Func _Transpose($song, $step, $mix = 0)
  If $mix = 0 Then
     Local $aNotes = ["Bb" , "B" , "C" , "Db" , "D" , "Eb" , "E" , "F" , "Gb" , "G" , "Ab" , "A"] 
  Else
     Local $aNotes = ["Bb" , "B" , "C" , "C#" , "D" , "Eb" , "E" , "F" , "F#" , "G" , "G#" , "A"]
  EndIf
  $pattern = '([A-G][b#]?)(?=\s|/|[45679]|m[45679]?|dim|$)'
  $tmp = Execute('"' & StringRegExpReplace($song, $pattern, _ 
        '" & $aNotes[Mod(_ArraySearch($aNotes, "$1")+12+$step, 12)] & "') & '"')
  Return $tmp
EndFunc

still in the context of the OP's asking "a little Autoit script to be able to just take my text file, find the chords, transpose them by an inputted amount, and then allow me to either rewrite the file or just display it "

As you said, the chord transposition is not too difficult by itself, but the text-file-in/text-file-out thing was a pretty tricky challenge  :)

BTW your mus++ is ... totally insane, fantastic. Seriously, this deserved a handy user manual and/or a cute gui so the common user could plainly understand and appreciate the power and acuteness of this script

 

Edited by mikell
Link to comment
Share on other sites

That's much more flexible.

1 hour ago, mikell said:

the text-file-in/text-file-out thing was a pretty tricky challenge

That's why I left that to you. :) One thing I'm curious about though - you used G# instead of Ab. Actually this is a 50/50 case. You will often see brass instruments tuned to Bb or Eb. Likewise there are a whole range of instruments tuned to keys containing sharps: G major contains F#, and D major contains F# and C#. The notes G# = Ab have an equal likelihood of occurrence. So what you did still fits well with my suggestion. A more theoretical treatment would be overkill for this particular purpose IMO.

2 hours ago, mikell said:

your mus++ is ... totally insane, fantastic.

I very much appreciate you saying this. Thanks!

Link to comment
Share on other sites

1 hour ago, czardas said:

One thing I'm curious about though - you used G# instead of Ab

This is not a specific choice ... when I formerly began to learn guitar I got a lot of sheet music using this chord notation, and this habit still remains
Anyway my code is mainly for the concept, it allows the OP to easily populate the array according to his particular needs - and also to modify the pattern if I forgot/missed something

Edit
the pattern should be amended indeed - it produces strange results if the lyrics contain "Eminent, "Amplitude" etc   :D

Edited by mikell
Link to comment
Share on other sites

4 hours ago, mikell said:

when I formerly began to learn guitar I got a lot of sheet music using this chord notation

It is indeed more typical for guitar music to use more sharps than flats: this has everything to do with tuning and the ease with which the most common chord shapes can be reached by the fingers. Anyway I fear we veer slightly away from the topic, because this was not necessarily a guitar specific question. I tend to get carried away on subjects like this. :whistle:

Edit: I think you need to separate the chords from the lyrics and recombine after transposition. You can't predict the type of nomenclature used for the chord quality and there's a lot of disparity in song sheets - different symbols used etc... It's an outrageous task to try and cover every convention. I wouldn't say it's impossible, but I pity anyone who tries. I gave up this particular idea because some conventions appear to collide. I may look at it again in the future.

Edited by czardas
Link to comment
Share on other sites

1 hour ago, czardas said:

I think you need to separate the chords from the lyrics and recombine after transposition.

This IS the reason why it's tricky  :)

Edit
In fact I first tried this way (doing something like iamtheky did) but a tiny headache advised me to give it up. I would by far prefer to build a 2-lines regex pattern if necessary  :D

Edited by mikell
Link to comment
Share on other sites

I think if you write the transposition, you should be able to set the parameters for the sheet music syntax.  There are way too many notations, and novice folk like me who screw it up and call F/A something like FaddA, when everyone else is screaming that it already has an A in it.  And I'm like, but I'm adding another?

 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

Here is an interface based on mikell's example.

When using this example, a feature or problem found is when "Chord List# 2" and a "Transpose Value" of 0 is selected.
There is no "Ab" in  "Chord List# 2" to be displayed in the modified text.  So, nothing is displayed in the "Modified Text" edit control.

#include <Array.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <UpDownConstants.au3>
#include <StaticConstants.au3>
#include <FileConstants.au3>
#include <WinAPI.au3>

TranspostKeys()


Func TranspostKeys()
    Local $sFileSaveDialog, $tPosS, $id
    Local $sComboDat, $sTTip
    Local $aNotes = _
            ['Bb,B,C,Db,D,Eb,E,F,Gb,G,Ab,A', _
            'Bb,B,C,C#,D,Eb,E,F,F#,G,Ab,A', _
            'Bb,B,C,C#,D,Eb,E,F,F#,G,G#,A']
    For $i = 0 To UBound($aNotes) - 1
        $sComboDat &= "Chord List# " & $i & "|"
        $sTTip &= "Chord List# " & $i & " = " & $aNotes[$i] & @CRLF
    Next
    $sComboDat = StringTrimRight($sComboDat, 1) ; Remove trailing "|"
    ;_ArrayDisplay($aNotes)

    Local $str = "Gm           Cm7              F          Bb" & @CRLF & _
            "Times are hard You're afraid to pay the fee" & @CRLF & _
            "       Eb             Ab              Bb                F/A   Eb/G   F   Eb" & @CRLF & _
            "So you find yourself somebody Who can do the job for free" & @CRLF

    Local $hGui = GUICreate("Transpose Keys", 606, 906, -1, -1, $WS_SIZEBOX)
    GUISetFont(10, 400)

    Local $idChdLab = GUICtrlCreateLabel("Select Chord List >", 140, 6, 125, 25)
    Local $idCombo = GUICtrlCreateCombo("Chord List# 0", 260, 3, 130, 25)
    GUICtrlSetData($idCombo, StringTrimLeft($sComboDat, 14))
    Local $idOpen = GUICtrlCreateButton('Open a chord file', 395, 3, 170, 26)
    GUICtrlCreateLabel("Original Text", 3, 14, 100, 20, -1, $WS_EX_CLIENTEDGE)
    Local $idOrig = GUICtrlCreateEdit($str, 3, 33, 600, 400)
    GUICtrlCreateLabel("TransposeValue", 20, 443, 110, 20)
    Local $idInput = GUICtrlCreateInput("-2", 130, 443, 80, 20)
    GUICtrlCreateUpdown($idInput, BitOR($UDS_ALIGNRIGHT, $UDS_WRAP, $UDS_NOTHOUSANDS))
    Local $idTranspose = GUICtrlCreateButton("Run Transpose", 250, 440, 120, 26)
    Local $idSave = GUICtrlCreateButton('Save "Modified Text" As', 395, 440, 170, 26)
    GUICtrlCreateLabel("Modified Text", 3, 467, 100, 20, -1, $WS_EX_CLIENTEDGE)
    Local $idMod = GUICtrlCreateEdit(_Transpose($str, $aNotes[StringRegExpReplace(GUICtrlRead($idCombo), "\N", "")], GUICtrlRead($idInput)), 3, 486, 600, 400)

    GUISetState(@SW_SHOW)

    While 1
        ; ------ ToolTip --------
        $id = _WinAPI_GetDlgCtrlID(_WinAPI_WindowFromPoint(_WinAPI_GetMousePos()))
        If $id = $idChdLab Or $id = $idCombo Then
            ToolTip($sTTip)
        Else
            ToolTip("")
        EndIf
        ; --- End of ToolTip -----

        Sleep(10)
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idOpen
                Local $sFileOpenDialog = FileOpenDialog("Open a Chord file", "", "Text (*.txt)|All Files (*.*)", $FD_FILEMUSTEXIST)
                If $sFileOpenDialog <> "" Then
                    GUICtrlSetData($idOrig, FileRead($sFileOpenDialog), "")
                EndIf
            Case $idTranspose
                $iList = StringRegExpReplace(GUICtrlRead($idCombo), "\D", "")
                GUICtrlSetData($idMod, _Transpose(GUICtrlRead($idOrig), $aNotes[$iList], GUICtrlRead($idInput)), "")
            Case $idSave
                $sFileSaveDialog = FileSaveDialog("Choose a filename.", "::{450D8FBA-AD25-11D0-98A8-0800361B1103}", "Text (*.txt)|All Files (*.*)", $FD_PATHMUSTEXIST, "Modified.txt")
                If $sFileSaveDialog <> "" Then
                    If FileExists($sFileSaveDialog) Then
                        $iMsgB = MsgBox(4, "Replace Existing File", '"' & $sFileSaveDialog & '" aready exists.' & @CRLF & @CRLF & 'Press "Yes" to continue, and, replace the contents of this file.')
                        If $iMsgB = 6 Then
                            FileDelete($sFileSaveDialog)
                            FileWrite($sFileSaveDialog, GUICtrlRead($idMod))
                        EndIf
                    Else
                        FileWrite($sFileSaveDialog, GUICtrlRead($idMod))
                    EndIf
                EndIf
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>TranspostKeys

Func _Transpose($song, $sNotes, $step)
    Local $aNotes = StringSplit($sNotes, ",", 2)
    If $step < 0 Then $step += UBound($aNotes) * (Ceiling(Abs($step) / UBound($aNotes)))
    Local $pattern = '([A-G][b#]?)(?=\s|/|m[45679]?|dim|$)'
    Return Execute('"' & StringRegExpReplace($song, $pattern, '" & $aNotes[Mod(_ArraySearch($aNotes, "$1") + $step, UBound($aNotes))] & "') & '"')
EndFunc   ;==>_Transpose

 

Link to comment
Share on other sites

Malkey,
This could easily be fixed by first changing all the chords to flats, then transpose

Func _Transpose($song, $sNotes, $step)
    Local $tmp[5][2] = [["Bb", "A#"], ["Db", "C#"], ["Eb", "D#"], ["Gb", "F#"], ["Ab", "G#"]]
    For $i = 0 to 4
       $song = StringReplace($song, $tmp[$i][1], $tmp[$i][0])
    Next
    Local $aNotesIn = ["Bb", "B", "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A"] 
    Local $aNotesOut = StringSplit($sNotes, ",", 2)
    If $step < 0 Then $step += 12*(Ceiling(Abs($step)/12))
    Local $pattern = '([A-G][b#]?)(?=\s|/|[45679]|m(?=[/\s#\d]|$)|dim|aug|sus|$)'
    Return Execute('"' & StringRegExpReplace($song, $pattern, '" & $aNotesOut[Mod(_ArraySearch($aNotesIn, "$1")+$step, 12)] & "') & '"')
EndFunc   ;==>_Transpose

 

Edited by mikell
added sus in the pattern
Link to comment
Share on other sites

@mikell Another common chord type uses 'sus': it should be included.


I'm wondering what happened to wysocki, did they get the answer they wanted? Some aspects of my own project are far in advance of many similar commercial music programs on the market, and I am reluctant to give freebies to lazy companies who can't be bothered to employ professional musicians to develop their apps, which seems frequently to be the case. I'm happy to give hints here and there for simple things like this, so please don't get me wrong. One day I'm going to release an amazing program, the likes of which nobody has seen - no hints on that one! :whistle:

Edited by czardas
Link to comment
Share on other sites

czardas,
Added 'sus' in the pattern
I know that my little code (and so Malkey's) is raw and incomplete, as I said it doesn't pretend to be fully comprehensive but it should work in the limits of the requirements defined by the title of the thread  :)
Obviously as I'm not a professional musician your comments are welcome, so would be some from wysocki to refine the code to better fit their needs if necessary
BTW "no hints on that one" ? you rascal, you make our mouthes water :D

 

Edited by mikell
Link to comment
Share on other sites

  • 2 weeks later...

Wow, what great response to this issue! Sorry for not being in the loop here but I was out for a couple weeks vacation just after I started the thread. Oddly, I didn't get any notifs of replies even though it was checked??

I had tried using Band-In-A-Box, entering the whole song with lyrics, then BIAB allows you easily change the key. Problem is that is doesn't print chord+lyric sheets as I wanted so I thought about writing my own transposer. Can't wait to read through all the ideas, thanks all!  Especially want to check out mus++, it looks amazing!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...