1 """Combination of HmmPath with chord recognizer
2
3 Simple extension of baseline to MIDI input by getting a lattice from an
4 HP chord labeler and decoding the baseline on the resulting lattice.
5
6 """
7 """
8 ============================== License ========================================
9 Copyright (C) 2008, 2010-12 University of Edinburgh, Mark Granroth-Wilding
10
11 This file is part of The Jazz Parser.
12
13 The Jazz Parser is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 The Jazz Parser is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with The Jazz Parser. If not, see <http://www.gnu.org/licenses/>.
25
26 ============================ End license ======================================
27
28 """
29 __author__ = "Mark Granroth-Wilding <mark.granroth-wilding@ed.ac.uk>"
30
31 from StringIO import StringIO
32
33 from jazzparser.utils.options import ModuleOption, ModuleOptionError
34 from jazzparser.grammar import get_grammar
35 from jazzparser.utils.strings import str_to_bool
36 from jazzparser.misc.chordlabel.hmm import HPChordLabeler
37
38 from .hmmpath import HmmPathBuilder
39 from ..base import BackoffBuilder
42 """
43 Use an HP chord labeler to get a chord lattice and HmmPath on the lattice.
44 """
45 MODEL_CLASS = None
46 BUILDER_OPTIONS = HmmPathBuilder.BUILDER_OPTIONS + [
47 ModuleOption('labeling_model',
48 help_text="Model name for chord labeler",
49 usage="labeling_model=M, where M is a trained chord labeling model",
50 required=True),
51 ModuleOption('partition_labeler', filter=str_to_bool,
52 help_text="By default, the chord labeling model is not loaded "\
53 "with a partition number, even if the supertagging model is. "\
54 "If this is True, the same partition number will be used for "\
55 "the labeler's model as was given to the supertagger.",
56 usage="partition_labeler=B, where B is True or False",
57 default=False),
58 ModuleOption('latticen', filter=int,
59 help_text="Number of chords per segment to get in the lattice",
60 usage="latticen=N, where N is an integer",
61 default=3),
62 ModuleOption('lattice_beam', filter=float,
63 help_text="Beam ratio to apply to the chord lattice. Removes all "\
64 "chord labels with probability < ratio * highest probability "\
65 "in timestep. Default: 1e-5",
66 usage="lattice_beam=F, where F is a float < 1.0 (e.g. 1e-6)",
67 default=1e-5),
68 ModuleOption('label_viterbi', filter=str_to_bool,
69 help_text="Use Viterbi decoding instead of forward-backward. "\
70 "Only one chord will be returned for every timestep, no "\
71 "matter what latticen is. Default: False",
72 usage="viterbi=B, where B is True or False",
73 default=False),
74 ]
75 INPUT_TYPES = ['segmidi']
76
77 - def __init__(self, input, options={}, grammar=None, *args, **kwargs):
78 super(MidiHmmPathBuilder, self).__init__(input, options, *args, **kwargs)
79 if grammar is None:
80 self.grammar = get_grammar()
81 else:
82 self.grammar = grammar
83
84
85 options = self.options.copy()
86
87 labeling_model_name = options.pop('labeling_model')
88 latticen = options.pop('latticen')
89 beam_ratio = options.pop('lattice_beam')
90 viterbi = options.pop('label_viterbi')
91 partition_labeler = options.pop('partition_labeler')
92
93
94
95
96 if partition_labeler and 'partition' in self.options and \
97 self.options['partition'] is not None:
98 labeling_model_name += "%d" % self.options['partition']
99
100
101
102 labeler = HPChordLabeler.load_model(labeling_model_name)
103 self.labeler = labeler
104
105 lattice = labeler.label_lattice(input, options={
106 'n' : latticen,
107 'nokey' : True,
108 'viterbi' : viterbi },
109 corpus=True)
110
111 self.lattice = lattice
112
113 lattice.apply_ratio_beam(ratio=beam_ratio)
114
115
116 self.hmmpath = HmmPathBuilder(lattice, options, grammar, *args, **kwargs)
117
118 @property
120 return len(self.hmmpath._paths)
121
123 if rank >= len(self.hmmpath._paths):
124 return None
125 else:
126 return self.hmmpath._paths[rank]
127