Last modified: March 20, 2013
Contents
The OTR toolkit is out-of-the-box already adaptive to different tablature symbols: you do not need to hack on the toolkit, but simply need to train the symbols of your print as described in the user's manual.
This document is for those who need to extend the toolkit beyond that, and describes two typical use cases:
The core functionality of this toolkit is wrapped in two classes: TabPage and TabGlyphList. In order to extend their functionality while still having access to the provided functions, you should derive from these classes.
Choosing a different staff removal algorithm requires changes only to the Tabpage class. As TabPage uses the staff removal interface of the MusicStaves Toolkit, this requires minimal effort.
The staff removal is not implemented in TabPage itself, but in the classes provided by the MusicStaves toolkit. In this toolkit, each class represents a specific staff removal algorithm. TabPage uses the class MusicStaves_rl_simple, which is initialized in the constructor of TabPage and assigned to the member variable musicstaves:
# import wanted staff removal implementation from gamera.toolkits.musicstaves import MusicStaves_rl_simple as MusicStaves class TabPage: def __init__(self, img, online=0, tab_type='french', staffline_height=0, staffspace_height=0): # set general properties self.stafflist=[] # list of staffobj (staffno, yposlist) self.staffranges=[] # list of [start, end] of staves self.on_lines=online # tab symbols in courses if tab_type not in ['french', 'italian']: raise RuntimeError, tab_type + ": Unknown Tabtype" else: self.tabtype=tab_type # use staff removal class rom MusicStaves toolkit self.music_staves=MusicStaves(img, staffline_height, staffspace_height) self.image=self.music_staves.image self.staffline_height=self.music_staves.staffline_height self.staffspace_height=self.music_staves.staffspace_height
TabPage.remove_staves simply calls the method remove_staves of the underlying MusicStaves class:
def remove_staves(self, crossing_symbols='auto', num_lines=0): if crossing_symbols=='auto': if self.on_lines==1: crossing_symbols='all' else: crossing_symbols='bars' # remove staves and extract information self.music_staves.remove_staves(crossing_symbols=crossing_symbols, num_lines=num_lines) self.stafflist=self.music_staves.get_staffpos() self.image=self.music_staves.image
All you need to do is to set self.musicstaves to an instance of a MusicStaves class of your choice. This requires two steps:
The following example will use Fujinaga's staff removal algorithm, which is provided by the class MusicStaves_rl_fujinaga in the MusicStaves toolkit:
# import wanted MusicStaves class from gamera.toolkits.musicstaves import MusicStaves_rl_fujinaga as myMusicStaves # original TabPage class from gamera.toolkits.otr.otr_glyph import * class myTabPage(TabPage): def __init__(self, img, online=0, tab_type='french', staffline_height=0, staffspace_height=0): # initialize all necessary data from base class TabPage.__init__(self, img, online, tab_type, staffline_height, staffspace_height) # use different external class module for removing the staves self.music_staves = myMusicStaves(img, staffline_height, staffspace_height) self.image = self.music_staves.image self.staffline_height = self.music_staves.staffline_height self.staffspace_height = self.music_staves.staffspace_height
Note that we have called the constructor of the base class first. Although this will unnecessarily call the constructor of MusicStaves_rl_simple, it has the advantage that all member variables required by TabPage will be correctly initialized.
Now you can use your own class just like the TabPage class:
tab = myTabPage(image) tab.remove_staves(num_lines=5)
The class TabGlyphList can generate an abc tablature encoding and a music transcription in abc. To create a custom tablature code or interpret custom trained symbol names in a special way, you must derive a custom class from TabGlyphList and add your own output method.
The abc tablature code is created in TabGlyphList.to_abctab, so the code of this function is a good starting point. It requires that TabGlyphList.set_glyph_properties is already called. Here are some points for clarification:
Let us assume that our "tablature code" simply consists of all symbol names together with their position (staff, x_number, course); we call this code glyphliststring.
As we want to keep all functionality from the OTR toolkit, we derive a new class myTabGlyphList from TabGlyphList and add a new output method:
# original TabGlyphList class from gamera.toolkits.otr.otr_glyph import * class myTabGlyphList(TabGlyphList): # our custom function def to_glyphliststring(self): string="" for g in self.glyphs: # ignore symbols that are outside the staves if g.course < 0 or g.staff < 0: continue # handling of the symbols if g.match_id_name('*bar*'): string+="bar line" else: string+=g.id_name[0][1] # information of a symbol's position string+=" (staff: %d, course: %d, x_number: %d)\n"\ % (g.staff, g.course, g.x_number) return string
A more realistic tablature encoding like abc would require to encode staff breaks and process one chord at a time. This is easily achieved with group breaks on changing staff and x_number.