Melodeon.net Forums

Discussions => Tunes => ABC => Topic started by: David on August 07, 2017, 08:38:09 PM

Title: abcmelodeon - annotate abc tunes with button numbers
Post by: David on August 07, 2017, 08:38:09 PM
I was getting tired of writing the button numbers under the notes on tunes I'm trying to learn, so I've written a Python script to add Ed Rennie style numbers to abctunes.

It can be downloaded from here:

https://github.com/mawds/abcmelodeon

Posting it in the hope it's useful to others; feel free to suggest modifications/improvements (or to modify it yourself)
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Martin P on August 08, 2017, 08:56:27 PM
To really benefit from Ed's system, could you make push notes red, pull notes blue and chords black? Mind you, best thing as a learner is get rib of tabs and learn to sight read notes. You will progress a lot faster. Even better, learn the tune and forgo the written score altogether.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: David on August 08, 2017, 09:46:12 PM
I couldn't work out how to get the numbers in colour; I'm not sure if it's possible or not. The numbers are printed as lyric lines in the ABC file.  I guess there's not normally much call for colour.   

I know it's a bad habit looking at the tabs; I'm slowly weaning myself of them  (:)
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Steve_freereeder on August 09, 2017, 02:01:16 AM
Mind you, best thing as a learner is get rib of tabs and learn to sight read notes. You will progress a lot faster. Even better, learn the tune and forgo the written score altogether.
Totally agree with this. Relying on button numbers of whatever system is a burdensome prop. It might be useful at a very early stage but the sooner you can do away with it, the faster you will learn and retain the tunes. If you can sing or hum the tune from memory, then you can play it on the melodeon, because you will have made the all-important step of internalising the tune in your head.

If I have a new or complex tune to learn, I sometimes find it useful to first play the tune on the whistle or recorder. Having been a wind-instrument player since childhood, I am fortunate in being able to sight-read on those instruments easily, which helps me with the internalisation process which I can then transfer to the melodeon.

If you don't play any other instruments, you can use the ABC play-back facility to listen to the tune numerous times to get it fixed in your head before even attempting to play it on the melodeon. If necessary, break the tune into small fragments, say 2 - 4 bars at a time, rather than trying to memorise the whole tune all at once.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Ed Rennie on September 27, 2017, 10:58:32 PM
My word David, that's a very clever thing!

Yes it can be tiresome writing the numbers in, even if you're using Sibelius. Believe me, I know  ;)
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on September 28, 2017, 07:03:00 AM
...so I've written a Python script to add Ed Rennie style numbers to abctunes...
feel free to suggest modifications/improvements (or to modify it yourself)
Fascinating.

Any thoughts about how easy/difficult it would be to modify the script to do the same job for a concertina?

I don't speak Python but I've been thinking about learning - this might be a good 'starter' project.

Thank you.

Roger
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: voyager on September 28, 2017, 07:25:43 PM
Would this PDF Help It's a system I have used with Concertina Players, rather than have every note with the "correct" button a simple print out of the keyboard layout for the particular instrument. For melodeon's available from from here on the forum

!) It can help a new player learn the dots
2) The size can be changed to suit people with eyesight problems

I have taken the Abc from Lester's brilliant Tune A Day site and as our local supermarket has already got Xmas stuff in I hope
this will not be out of place.

Any thoughts on this method are very welcome

Regards Dave

Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: voyager on September 28, 2017, 07:35:51 PM
Sorry I sent the wrong attachment hopefully this is correct

Dave
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: vof on September 28, 2017, 10:05:49 PM
...so I've written a Python script to add Ed Rennie style numbers to abctunes...
feel free to suggest modifications/improvements (or to modify it yourself)
Fascinating.

Any thoughts about how easy/difficult it would be to modify the script to do the same job for a concertina?

I don't speak Python but I've been thinking about learning - this might be a good 'starter' project.

Thank you.

Roger
I'm part way through modifying David's Python source file for my fourth button start G-scale Pokerwork. It is fairly straightforward since Ed Rennie's button numbering scheme - buttons even numbered on the inside row and odd numbered on the outside row - can be used for all two row boxes so the job is mainly changing the table which maps from abc-style note names to button numbers with a preceding character to indicate bellows direction. For your concertina, you would need to first design your button numbering scheme. There may well be a standard one already you could adopt or create your own based for example on the RH/LH split but not being a 'tina player, I don't know anything about button notation on these instruments.

David has been helpful to me about his existing code so if you have further questions, I'm happy to help as would be David I suspect. PM me or him since the subject is definitely off-topic in a melodeon forum in a number of ways :)
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Jack Campin on September 29, 2017, 01:00:49 AM
I suspect it would be much more useful to implement annotations using emojis and then define these numbers as a kind of emoji.  That could have very much wider applications.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on September 29, 2017, 06:54:23 AM
I'm part way through modifying David's Python source file for my fourth button start G-scale Pokerwork. It is fairly straightforward since Ed Rennie's button numbering scheme - buttons even numbered on the inside row and odd numbered on the outside row - can be used for all two row boxes so the job is mainly changing the table which maps from abc-style note names to button numbers with a preceding character to indicate bellows direction. For your concertina, you would need to first design your button numbering scheme. There may well be a standard one already you could adopt or create your own based for example on the RH/LH split but not being a 'tina player, I don't know anything about button notation on these instruments.

David has been helpful to me about his existing code so if you have further questions, I'm happy to help as would be David I suspect. PM me or him since the subject is definitely off-topic in a melodeon forum in a number of ways :)

Thanks. That's extremely helpful. You have confirmed my thoughts about how to re-map the tables of abc notes/melodeon buttons
to abc notes/concertina buttons (the 'standard' numbering system I use is different, and is based on a LH/RH split). I'll also need
to add a third mapping for the buttons on the 'accidentals' row of a 30-button 'tina...

Back-burner for a week or so but definitely looks feasible.

As you say, strictly, OT for melodeons, but your thoughts are very helpful.

Thank you once again.

Roger
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: David on October 05, 2017, 10:14:30 PM
David has been helpful to me about his existing code so if you have further questions, I'm happy to help as would be David I suspect. PM me or him since the subject is definitely off-topic in a melodeon forum in a number of ways :)

Thanks. That's extremely helpful. You have confirmed my thoughts about how to re-map the tables of abc notes/melodeon buttons
to abc notes/concertina buttons (the 'standard' numbering system I use is different, and is based on a LH/RH split). I'll also need
to add a third mapping for the buttons on the 'accidentals' row of a 30-button 'tina...

Back-burner for a week or so but definitely looks feasible.

As you say, strictly, OT for melodeons, but your thoughts are very helpful.

Thank you once again.

Roger

Hi

Sorry for the slow reply - only just saw the thread had sprung to life again.

I think (though I don't know much about concertinas) you should just need to write a single mapping.  The only reason there are two for the melodeon is because we've (sometimes) got a choice of buttons for the same note. 

A mapping links notes (in abc notation, i.e. ^C is c#) to something; for the gRow and dRow mappings these are melodeon button numbers, but they could be anything. There's actually a note names mapping built in too (noteNames).  If you've only got one choice of button for a note you'll only need one mapping.

You probably will need to alter the applykeysig function - at the moment this only handles D and G, which are hard coded in. I don't know enough music theory to easily generalise this to other keys.   That function needs to convert sharpen / flatten the "raw" note according to the key given (i.e. "f" -> "^f" if key == G).

Feel free to PM me if I can be of any help.   I'm happy (and keen) to merge any improvements into the script.

David

Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Ebor_fiddler on October 05, 2017, 11:47:14 PM
A simple way to get printed fingering, can be found AbcEdit.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on October 06, 2017, 06:54:00 AM
Hi

Sorry for the slow reply - only just saw the thread had sprung to life again.

I think (though I don't know much about concertinas) you should just need to write a single mapping.  The only reason there are two for the melodeon is because we've (sometimes) got a choice of buttons for the same note. 

A mapping links notes (in abc notation, i.e. ^C is c#) to something; for the gRow and dRow mappings these are melodeon button numbers, but they could be anything. There's actually a note names mapping built in too (noteNames).  If you've only got one choice of button for a note you'll only need one mapping.

You probably will need to alter the applykeysig function - at the moment this only handles D and G, which are hard coded in. I don't know enough music theory to easily generalise this to other keys.   That function needs to convert sharpen / flatten the "raw" note according to the key given (i.e. "f" -> "^f" if key == G).

Feel free to PM me if I can be of any help.   I'm happy (and keen) to merge any improvements into the script.

David

Thank you for those extra hints. FWIW, there are 'duplicated' notes on an Anglo concertina, so two mappings
will probably be called for - perhaps three mappings to allow for the 'accidental' row on a 30-button instrument.

As it happens, I'm planning to try and install Python on one of my machines on Saturday, so maybe I can give
it a try.

I presume that (on a Windoze machine) I have to run the Python script from within a 'command' prompt window?

Thanks.

Roger.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: David on October 06, 2017, 05:12:28 PM

Thank you for those extra hints. FWIW, there are 'duplicated' notes on an Anglo concertina, so two mappings
will probably be called for - perhaps three mappings to allow for the 'accidental' row on a 30-button instrument.


Ah! I hadn't realised that.  Yes - you'll need as many mappings as there are ways you can make the same note.

Quote
As it happens, I'm planning to try and install Python on one of my machines on Saturday, so maybe I can give
it a try.

I presume that (on a Windoze machine) I have to run the Python script from within a 'command' prompt window?


Yes - that's right.  Anaconda Python seems to be a popular choice. After installing it you should get an icon in the start menu for a python command line.  From memory, this sets up the paths, so it can find the python executable (I'm not a Windows user myself, so my memory is a bit hazy).  Good luck!
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on September 29, 2019, 07:42:57 PM
I'm reviving this one because finally, 2 years down the road, I've managed to get Python
going, and have re-engineered this script for a G/D concertina.  I use a different tabbing
system for the concertina, and the layout of the notes is different. All that was needed
was simply to re-map the existing allocations and to add a third mapping for the accidentals
row. By sneaky manipulation of these mappings, I think I can see a way to make this program
do a couple of things which (I guess) the original designer had not intended.

What I'd like to ask is, has the OP done any development work on the Python script since the
original post in 2017? There is a sort of implied TODO list embedded in the Python script.
I don't even know if the OP still reads this forum...

This is 'interesting' to me, because I've also developed my own completely different program
for writing concertina tabs to an ABC file (it uses the same tabbing system, but is not in Python).

Whatever, I'd like to do a rough qualitative comparison between the two programs and want to
be as sure as I can that I have the most recent version of the Python script...

Ta.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Eshed on September 30, 2019, 07:20:08 AM
You can see the history of changes in GitHub:
https://github.com/mawds/abcmelodeon/commits/master
The last chance was quite recent, so it appears the script on GitHub is the most up to date version.
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on September 30, 2019, 10:05:09 AM
You can see the history of changes in GitHub...

Aah! Thanks for that. I now have the most up-to-date version to work with...

I should perhaps add that I got this working on a W10 machine. I think the original script
was aimed at a Linux/Unix machine? This is only relevant because the installation/use of
Python is a little different on Windoze...
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: David on October 08, 2019, 07:44:44 PM
Hi

Apologies for the slow reply; I was on holiday.   I wrote the original script, but hadn't done much with it until a few months ago when I got it working with a few more tunes (though it still trips up on some tunes).   Good to know you've got it working on Windows 10; I developed it on Linux.

The version on github is the most up to date.   Is the source for your concertina program online anywhere? Would be interesting to compare the two.

David
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: John MacKenzie (Cugiok) on October 08, 2019, 08:43:21 PM
As an ear player, I'd be interested to see what this looks like in print

SJ
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on October 09, 2019, 05:40:47 AM
...Is the source for your concertina program online anywhere? Would be interesting to compare the two....

Thanks for the reply - I hope you had a good holiday. My modded version of your script is included later.

I had to put this project down for 2 years due to a months-long hiatus in my domestic life. It has only
just risen to the top of the pile of delayed projects. I have the most recent version of the source from
Github.

You are discreetly modest - you have added the capability to recognise a wider range of 'pitch sets'
than in the original script - this allows the successful tabbing of all keys with 1-sharp, 2-sharps, etc.
This is brilliant. So far, I have been unable to do the same in my own (Icon) program (see later).

What I have done recently/am continuing to do:
(i) Managed to get Python working on my Windoze 10 machine. (ii) Used your script to tab a few tunes
for melodeon just to see how it works - what a very clever program! (iii) Hacked the script so it now
writes tabs(*) for a G/D Anglo. I have not done any re-programming, merely some hacking of your script.

Briefly (I hope I get this right!), a D/G melodeon has a low (D) row and a high (G) row. The G row
is a fourth higher than the D row. A G/D concertina has a low (G) row and a high (D) row.  The D row
is a fifth higher than the G row.

In your script, note/button allocations are defined, (as I suspected) in 'associative arrays'. It seemed
to me that by carefully re-writing those definitions, it should be possible to modify your script so that
it produced tabs for a G/D concertina. For the benefit of anyone who has looked at your script, I have
renamed the existing arrays: 'dRow' as 'gRow', and 'gRow' as 'dRow'  and then redefined the button/note
mappings.

I have also added a third array to hold the mappings for the accidentals row of a 30-button G/D
concertina. With stunning originality, I have called this 'aRow'.

I have also added a fourth array to hold a global mapping of one button/note mapping for
each note on the concertina In a moment of divinely-inspired inspiration, I called this array 'allRows'.

'allRows' provides a single line of tabs, without any duplication of notes/buttons (in some cases there
are three ways of getting the same note on a 30-button G/D Anglo). This is something I personally
rather like.

I have made only one minor change to the actual code in your Python script - namely to change the
default mapping to 'allRows'.

Yup! It works, though I haven't tested it to destruction yet (that's 'evasive-speak' for 'there are still
some glitches in my version') .

What I won't be doing:
Learning Python. I'll be sticking to hacking - as I said, I've merely hacked your data structures, I've
added no new code. I'm too old to learn a new programming language...

What I've also done:
Written my own progam (using the Icon programming language). I now have a working protototype.
I went a different route than you - for example, by design, my program deals (largely by passing them
unchanged) with:

(1) all non-music lines (ABC headers, comments (%), abcm2ps & abcmidi directives (%%), abcpp directives (#));
(2) all 'bounded strings', as I call them, namely: "..." (annotations, accompaniment chords),
!...! (decorations), [...] (in-line key/meter changes & multi-headed notes), {...} (grace notes);
'&...|' and &...: (voice overlay).
(3) a couple of other 'odds-and-sods' which escape me at 0620...

A very significant difference is that you write your tabs into the w: field of the ABC script, I add my
tabs as annotations placed immediately before the note in question. Both sets of tabs appear below
the staff, however.

What my program doesn't do is the biggie - namely deal properly with different keys. Currently, it only
tabs tunes in G and D (and associated keys in 1- and 2- sharps). Your program does work for a range
of keys, and I hope to be able to use it as a template for getting my program to do the same.

Here is your code as modified by me, but let's be quite clear it is still your program - all I have
done is a little hacking. The modified code also includes some comments to serve as an aide-memoire
when I come back to it:

Code: [Select]
#!/usr/bin/env python
#Add (concertina) button numbers or note names to ABC music files
#
#This Python script will add tabs in the w: field to ABC music files, consisting of the button number for
#each note with a ^ suffix for pull notes. This is basically the Australian Bush Traditions button numbering system.
#
#To use:
#
#Unix:
#./abcconcertina.py infile outfile
#
#Windoze:
#python abcconcertina.py infile outfile
#
#where infile and outfile are the input and output abc music files.
#
#The program takes an optional --mappings argument. This should be supplied with one or more "mappings":
#dRow, gRow, aRow (which will print ABT style tabs for a 30-button Wheatstone/Jefferies G/D concertina),
#or noteNames (which will print the names of each note).
#
#By default the acccidental, G and D row notes will be printed, which helps when trying to work out how to cross rows.
#
#For example, to annotate mytune.abc with G row and note names to the file mytune_out.abc:
#
#Unix:
#./abcconcertina.py --mappings gRow,noteNames mytune.abc mytune_out.abc
#
#Windoze:
#python abcconcertina.py --mappings gRow,noteNames mytune.abc mytune_out.abc
#
#(note no space between gRow and noteNames)

print "abcconcertina.py - v1.0 - September 2019."
print "abcconcertina.py adds concertina tabs for a 3-row G/D Anglo concertina to an existing ABC tune file."
print "The program is based on the Python script abcmelodeon.py (authored by melodeon.net user 'David')"
print "  which adds melodeon tabs for a 2-row D/G melodeon to an existing ABC tune file (August 2019)."
print "The conversion from D/G melodeon to G/D concertina was done by concertina.net user 'lachenal74693'."
print " "

import re
import argparse

# Regexs
# The key line
rxkey = re.compile(r'^K: ?(.+)$')
# a note
rxnote = re.compile(r'([\^_]?[a-gA-G][,\']*)|(".+?")' )
rxtunestart = re.compile(r'^[XT]:')
rxblankline = re.compile(r'^$')
rxfieldline = re.compile(r'^\w:')

notemappings = {}

#Mapping to provide single line of tabs for all rows - added by RJH.
notemappings["allRows"]= {"G,,":"L5",
        "D,":"L5^",
        "D,":"L5^/L4",
        "F,":"L4^",
        "^F,":"L4^",
        "G,":"L3",
        "A,":"L3^",
        "B,":"L2",
        "C":"L2^",
        "^C":"L2^",
        "D":"L1",
        "E":"L1^",
        "G":"R1",
        "F":"R1^",
        "^F":"R1^",
        "B":"R2",
        "A":"R2^",
        "=c":"R3^",
        "c":"R3^",
        "^c":"dR1^",
        "d":"dR1",     
        "f":"dR2s",
        "^f":"dR2",
        "e":"dR2^",
        "a":"dR3",
        "g":"dR3^",
        "d'":"dR4",
        "b":"dR4^",
        "f'":"dR5",
        "^f'":"dR5",
        "c'":"dR5^",
        "^c'":"dR5^"
        }

#Mapping for accidental row of G/D concertina - added by RJH.
notemappings["aRow"]= {"B,":"aL5",
        "=C,":"aL5^",
        "E,":"aL4",
        "=F,":"aL4^",
        "_A,":"aL3",
        "_B,":"aL3^",
        "E":"aL2",
        "D":"aL2^",
        "_E":"aL1",
        "=F":"aL1^",
        "_A":"aR1",
        "_B":"aR1^",
        "e":"aR2",
        "d":"aR2^",
        "_e":"aR3",
        "=f":"aR3^",
        "_a":"aR4",
        "_b":"aR4^",
        "e'":"aR5",
        "=c'":"aR5^"
        }

#Mapping for D-row re-labelled and modified for G-row concertina by RJH.
notemappings["gRow"]= {"G,,":"L5",
        "D,":"L5^",
        "D,":"L5^/L4",
        "F,":"L4^",
        "^F,":"L4^",
        "G,":"L3",
        "A,":"L3^",
        "B,":"L2",
        "C":"L2^",
        "^C":"L2^",
        "D":"L1",
        "E":"L1^",
        "G":"R1",
        "F":"R1^",
        "^F":"R1^",
        "B":"R2",
        "A":"R2^",
        "d":"R3",
        "c":"R3^",
        "^c":"dR1^",
        "g":"R4",
        "e":"R4^",
        "b":"R5",
        "f":"R5^",
        "^f":"R5^"
        }

#Mapping for G-row re-labelled and modified for D-row concertina by RJH.
notemappings["dRow"]= {"F,":"dL5",
        "A,":"dL5^",
        "A,":"dL4",
        "C":"dL4^",
        "^C":"dL4^",
        "D":"dL3",
        "E":"dL3^",
        "F":"dL2",
        "^F":"dL2s",
        "G":"dL2^",
        "A":"dL1",
        "B":"dL1^",
        "d":"dR1",
        "=c":"R3^",
        "c":"R3^",
        "^c":"dR1^",     
        "f":"dR2s",
        "^f":"dR2",
        "e":"dR2^",
        "a":"dR3",
        "g":"dR3^",
        "d'":"dR4",
        "b":"dR4^",
        "f'":"dR5",
        "^f'":"dR5",
        "c'":"dR5^",
        "^c'":"dR5^"
        }

# noteNames will annotate with the note letter
# we build this semi-programatically
notenames = ["A","B","C","D","E","F","G"]
notesflat = ["_" + n for n in notenames]
notessharp = [ "^" + n for n in notenames]

allnotenames = notenames + notesflat + notessharp
allnotesymbs = notenames + \
        [n + 'b' for n in notenames] + \
        [n + '#' for n in notenames]
   

notemappings["noteNames"] = dict(zip(allnotenames, allnotesymbs))
notemappings["noteNames"].update(dict(zip([n.lower() for n in allnotenames], allnotesymbs)))
notemappings["noteNames"].update(dict(zip([n + "," for n in allnotenames], allnotesymbs)))
notemappings["noteNames"].update(dict(zip([n + "'" for n in allnotenames], allnotesymbs)))

def getkey (infile):
    """ Read an abc file and extract the key """
    key = None
    for thisline in infile:
        m = rxkey.search(thisline)
        if m:
            if key is not None:
                raise ValueError("Multiple key lines found")
            key = m.group(1).strip()

    return key


def annotateabc (infile):
    """ Annotate an abc file with button numbers """
    print "Depreciated - use annotabc2"
    quit()
    try:
        key = getkey(infile)
    except ValueError as e:
        print e
        print infile
    notes = extractnotes(infile)

    newnotes = [[applykeysig(n, key=key) for n in nn] for nn in notes]

    notestrings = []
    for m in mappings:
        notestrings.append(getNoteString(newnotes, notemappings[m]))

    outabc = ''
    foundkey = False
    for line in infile:
        outabc += line
        if foundkey:
            for n in notestrings:
                print n
                if len(n) > 0:
                    outabc += ("w: " + n.pop(0) + "\n")
        if rxkey.search(line):
            foundkey = True

    return outabc

def stripdecoration(line):
    """ Strip everything in +s or !s """
    return re.sub('[!\+].+[!\+]', '', line)

def annotateabc2(inabc):
    """ Annotate an abc file with button numbers - take 2
    This assumes we're passing in a whole abc file """
    # TODO Handle inline key changes?

    currentkey = None
    outabc  = ''
    for line in inabc:
        outabc += line

        m = rxkey.search(line)
        if m:
            currentkey = m.group(1).strip()

        if re.match(r'^%', line):
            break
       
        if not rxfieldline.match(line): # On a noteline
            notes = []
            if currentkey is None:
                raise ValueError("Notes found before key has been set")
            # Extract the notes
            line = stripdecoration(line)
            linenotes = [i[0] for i in rxnote.findall(line)]
            # Remove blank notes - these are where a chord was
            # extracted instead
            justnotes = filter(None, linenotes)
            notes.append(justnotes)

            newnotes = [[applykeysig(n, key=currentkey) for n in nn] for nn in notes]
            notestrings = []
            for m in mappings:
                notestrings.append(getNoteString(newnotes, notemappings[m])) # list of button #s
           
            for n in notestrings:
                if len(n) > 0:
                    thesenotes = n.pop(0)
                    if len(thesenotes.strip()) >= 1:
                        outabc += ("w: " + thesenotes + "\n")


    return outabc



def readfile (infile):
    """ Read in a file """
    with open(infile) as file:
        content = file.readlines()

    return content

def extractnotes (infile):
    """ Extract the notes from the file.
    We read everything from the Key line until we get to an empty line.
    We don't care about note length"""
    notes = []
    foundbody = False
    for thisline in infile:
        if rxkey.search(thisline):
            foundbody = True
            continue
        if foundbody:
            linenotes = [i[0] for i in rxnote.findall(thisline)]
            # Remove blank notes - these are where a chord was
            # extracted instead
            justnotes = filter(None, linenotes)
            notes.append( justnotes )

    return notes

def extractabc(tunebook):
    """ Extract the tunes from a tunebook """
    # TODO handle comments, formatting etc.
    tunes = []
    thistune = []
    intune = False
    for thisline in tunebook:
        if rxtunestart.search(thisline) and not intune:
            thistune = []
            intune = True

        if intune:
            thistune.append(thisline)
           

        if thisline in ['\n', '\r\n']:
            if len(thistune) > 3:
                tunes.append(thistune)
            intune = False

    # If there's no blank line at the end,add the tune
    if intune:
        if len(thistune) > 3:
            tunes.append(thistune)
       

    return tunes

def applykeysig(note, key):
    """ Sharpen the appropriate notes
    Only implemented for G/D for now
    """
    # TODO Handle naturals
    # TODO handle other keys - presumably there's a clever way
    # of doing this if you know music theory
#    print key
#keys in the natural pitch set
    if key in ["C", "Cmaj", "Am", "AMin", "Amin", "GDor", "Gdor", "GMix", "Gmix", "DDor", "Ddor"]:
        if note.upper() == "F":
            return ("=" + note)
        return note
#keys in the pitch set 1-sharp
    if key in ["G", "Gmaj", "Em", "EMin", "Emin", "ADor", "Ador", "DMix", "Dmix", "EDor", "Edor"]:
        if note.upper() == "F":
            return ("^" + note)
        return note
#keys in the pitch set 2-sharps
    if key in ["D", "Dmaj", "Bm", "BMin", "Bmin", "EDor", "Edor", "AMix", "Amix"]:
        if note.upper() == "F":
            return ("^" + note)
        if note.upper() == "C":
            return ("^" + note)
        return note
#keys in the pitch set 3-sharps
    if key in ["A", "Amaj", "F#m", "F#Min", "F#Min", "BDor", "Bdor", "EMix", "Emix","C#Phr", "DLyd", "G#Loc"]:
        if note.upper() == "F":
            return ("^" + note)
        if note.upper() == "C":
            return ("^" + note)
        if note.upper() == "G":
            return ("^" + note)
        return note
#keys in the pitch set 1-flat
    if key in ["F", "Fmaj"]:
        if note.upper() == "B":
            return ("_" + note)
        return note
    else:
        # Just return a rest if we can't work out the key
        return "z"



def getNoteString(notes, notemap):
    mappednotes = [[notemap.get(x,"*") for x in y] for y in notes]

    notestring = [' '.join(x)   for x in mappednotes]

    return notestring

parser = argparse.ArgumentParser(description = "Add button numbers to abc file")
parser.add_argument("infile")
parser.add_argument("outfile")
#parser.add_argument("--mappings", default ="aRow,gRow,dRow", \
parser.add_argument("--mappings", default ="allRows", \
       help = "Comma separated list of note names/numbers to show. One or more of: " + \
        ','.join(list(notemappings.keys())))

args = parser.parse_args()
mappings = args.mappings.split(",")

for m in mappings:
    if m not in notemappings:
        print "Cannot find " + m + "in note mappings"
        print "mapping should be one or more of:"
        print ",".join(list(notemappings.keys()))
        quit()


abcfiles = readfile(args.infile)
abcbook = extractabc(abcfiles)
annotatedabc = []
for tune in abcbook:
    annotated = annotateabc2(tune)
    annotatedabc.append(annotated)

with open(args.outfile, "w") as file:
    for abc in annotatedabc:
        file.write(abc)
       
       

I'm aware of one other program (in Java) which does the same sort of thing...

This has the potential to become highly technical, and to bore the pants off other users. If you wish
to take it off-line, my electronic mail address is at the bottom of this post.

Roger.

(*) I have used the tabbing system outlined on the Australian Bush Traditions web-site:
https://www.bushtraditions.org/tutors/concertina.htm (https://www.bushtraditions.org/tutors/concertina.htm)
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on October 10, 2019, 11:05:02 AM
As an ear player, I'd be interested to see what this looks like in print
I presume you mean the printed score? If yes, I'll post an example of a score modified
with concertina tabs (along with the ABC), just to give you an idea of what it all looks
like...
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: David on October 11, 2019, 02:46:16 PM
Quote
You are discreetly modest - you have added the capability to recognise a wider range of 'pitch sets'
than in the original script - this allows the successful tabbing of all keys with 1-sharp, 2-sharps, etc.
This is brilliant. So far, I have been unable to do the same in my own (Icon) program (see later).

Thanks for your kind words.  It *should* be possible to get it to work with any number of sharps / flats, but lacking the music theory to work this out (or an instrument to play them on  ;) ) I didn't get as far as working out how to implement this.

I wrote a rather longer reply, which I'll email you to, as I realised I'd probably strayed into highly technical and boring the pants off other users territory

David
Title: Re: abcmelodeon - annotate abc tunes with button numbers
Post by: Roger Hare on October 11, 2019, 03:13:01 PM
Thanks for your kind words.  It *should* be possible to get it to work with any number of sharps / flats, but
lacking the music theory to work this out (or an instrument to play them on  ;) ) I didn't get as far as working
out how to implement this.

I wrote a rather longer reply, which I'll email you to, as I realised I'd probably strayed into highly technical and
boring the pants off other users territory

Thanks! I did send an even techier PM, and also tried to send the code for my program
separately, but the PM for the code exceeded the maximum message length. I will wait
till I get your email before doing anything else. The email address is at the bottom of this
post. Roger.
SimplePortal 2.3.5 © 2008-2012, SimplePortal