Chris@161
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@161
|
2
|
Chris@161
|
3 /*
|
Chris@161
|
4 Silvet
|
Chris@161
|
5
|
Chris@161
|
6 A Vamp plugin for note transcription.
|
Chris@161
|
7 Centre for Digital Music, Queen Mary University of London.
|
Chris@161
|
8
|
Chris@161
|
9 This program is free software; you can redistribute it and/or
|
Chris@161
|
10 modify it under the terms of the GNU General Public License as
|
Chris@161
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@161
|
12 License, or (at your option) any later version. See the file
|
Chris@161
|
13 COPYING included with this distribution for more information.
|
Chris@161
|
14 */
|
Chris@161
|
15
|
Chris@161
|
16 #include "Instruments.h"
|
Chris@161
|
17
|
Chris@161
|
18 #include "data/include/templates.h"
|
Chris@161
|
19
|
Chris@161
|
20 #include <iostream>
|
Chris@161
|
21
|
Chris@161
|
22 const int InstrumentPack::templateNoteCount = SILVET_TEMPLATE_NOTE_COUNT;
|
Chris@161
|
23 const int InstrumentPack::templateHeight = SILVET_TEMPLATE_HEIGHT;
|
Chris@161
|
24 const int InstrumentPack::templateMaxShift = SILVET_TEMPLATE_MAX_SHIFT;
|
Chris@161
|
25 const int InstrumentPack::templateSize = SILVET_TEMPLATE_SIZE;
|
Chris@161
|
26
|
Chris@161
|
27 using std::string;
|
Chris@161
|
28 using std::vector;
|
Chris@161
|
29 using std::cerr;
|
Chris@161
|
30 using std::endl;
|
Chris@161
|
31
|
Chris@161
|
32 const char *simpleInstruments[] = {
|
Chris@176
|
33 // Each instrument has two consecutive slots, one for the pack
|
Chris@176
|
34 // name and one for the template to look up
|
Chris@161
|
35 "Guitar", "guitar",
|
Chris@161
|
36 "Violin", "violin",
|
Chris@220
|
37 "Viola", "viola",
|
Chris@161
|
38 "Cello", "cello",
|
Chris@161
|
39 "Horn", "horn",
|
Chris@161
|
40 "Flute", "flute",
|
Chris@161
|
41 "Oboe", "oboe",
|
Chris@161
|
42 "Clarinet", "clarinet",
|
Chris@161
|
43 "Tenor Sax", "tenorsax",
|
Chris@161
|
44 "Bassoon", "bassoon",
|
Chris@161
|
45 };
|
Chris@161
|
46
|
Chris@176
|
47 static bool
|
Chris@220
|
48 isBowedString(int i)
|
Chris@176
|
49 {
|
Chris@176
|
50 string tname(simpleInstruments[i+1]);
|
Chris@176
|
51 return tname == "violin"
|
Chris@220
|
52 || tname == "viola"
|
Chris@176
|
53 || tname == "cello"
|
Chris@176
|
54 ;
|
Chris@176
|
55 }
|
Chris@176
|
56
|
Chris@176
|
57 static bool
|
Chris@176
|
58 isWind(int i)
|
Chris@176
|
59 {
|
Chris@176
|
60 string tname(simpleInstruments[i+1]);
|
Chris@176
|
61 return tname == "horn"
|
Chris@176
|
62 || tname == "flute"
|
Chris@176
|
63 || tname == "oboe"
|
Chris@176
|
64 || tname == "clarinet"
|
Chris@176
|
65 || tname == "tenorsax"
|
Chris@176
|
66 || tname == "bassoon"
|
Chris@176
|
67 ;
|
Chris@176
|
68 }
|
Chris@176
|
69
|
Chris@161
|
70 static InstrumentPack::Templates
|
Chris@161
|
71 templatesFor(string name)
|
Chris@161
|
72 {
|
Chris@161
|
73 for (int i = 0; i < SILVET_TEMPLATE_COUNT; ++i) {
|
Chris@161
|
74
|
Chris@161
|
75 if (string(silvet_templates[i].name) == name) {
|
Chris@161
|
76
|
Chris@161
|
77 silvet_template_t *t = &silvet_templates[i];
|
Chris@161
|
78
|
Chris@161
|
79 InstrumentPack::Templates rt;
|
Chris@161
|
80 rt.lowestNote = t->lowest;
|
Chris@161
|
81 rt.highestNote = t->highest;
|
Chris@161
|
82 rt.data = vector<vector<float> >
|
Chris@161
|
83 (SILVET_TEMPLATE_NOTE_COUNT,
|
Chris@161
|
84 vector<float>(SILVET_TEMPLATE_SIZE, 0.f));
|
Chris@161
|
85
|
Chris@161
|
86 for (int j = 0; j < SILVET_TEMPLATE_NOTE_COUNT; ++j) {
|
Chris@161
|
87 for (int k = 0; k < SILVET_TEMPLATE_SIZE; ++k) {
|
Chris@161
|
88 rt.data[j][k] = t->data[j][k];
|
Chris@161
|
89 }
|
Chris@161
|
90 }
|
Chris@161
|
91
|
Chris@161
|
92 return rt;
|
Chris@161
|
93 }
|
Chris@161
|
94 }
|
Chris@161
|
95
|
Chris@161
|
96 return InstrumentPack::Templates();
|
Chris@161
|
97 }
|
Chris@161
|
98
|
Chris@161
|
99 static bool
|
Chris@161
|
100 isOK(InstrumentPack &d)
|
Chris@161
|
101 {
|
Chris@161
|
102 if (d.name == "") {
|
Chris@161
|
103 cerr << "ERROR: Silvet::InstrumentPack: Empty name in instrument definition" << endl;
|
Chris@161
|
104 return false;
|
Chris@161
|
105 }
|
Chris@161
|
106 if (d.templates.empty()) {
|
Chris@161
|
107 cerr << "ERROR: Silvet::InstrumentPack: Instrument definition \"" << d.name << "\" contains no templates!" << endl;
|
Chris@161
|
108 return false;
|
Chris@161
|
109 }
|
Chris@161
|
110 for (int i = 0; i < int(d.templates.size()); ++i) {
|
Chris@161
|
111 if (d.templates[i].data.empty()) {
|
Chris@161
|
112 cerr << "ERROR: Silvet::InstrumentPack: Instrument definition \"" << d.name << "\" contains one or more empty templates!" << endl;
|
Chris@161
|
113 return false;
|
Chris@161
|
114 }
|
Chris@161
|
115 }
|
Chris@161
|
116 return true;
|
Chris@161
|
117 }
|
Chris@161
|
118
|
Chris@161
|
119 vector<InstrumentPack>
|
Chris@161
|
120 InstrumentPack::listInstrumentPacks()
|
Chris@161
|
121 {
|
Chris@161
|
122 vector<InstrumentPack> ii;
|
Chris@161
|
123
|
Chris@161
|
124 vector<Templates> allTemplates;
|
Chris@161
|
125 allTemplates.push_back(templatesFor("piano1"));
|
Chris@161
|
126
|
Chris@161
|
127 vector<Templates> pianoTemplates;
|
Chris@161
|
128 pianoTemplates.push_back(templatesFor("piano1"));
|
Chris@161
|
129 pianoTemplates.push_back(templatesFor("piano2"));
|
Chris@161
|
130 pianoTemplates.push_back(templatesFor("piano3"));
|
Chris@220
|
131 pianoTemplates.push_back(templatesFor("pianorwc"));
|
Chris@161
|
132 InstrumentPack piano(silvet_templates_lowest_note,
|
Chris@161
|
133 silvet_templates_highest_note,
|
Chris@161
|
134 "Piano",
|
Chris@161
|
135 pianoTemplates);
|
Chris@266
|
136 piano.maxPolyphony = 6;
|
Chris@200
|
137 piano.levelThreshold = 6;
|
Chris@213
|
138 piano.pitchSparsity = 1.0;
|
Chris@213
|
139 piano.sourceSparsity = 1.0;
|
Chris@161
|
140 if (isOK(piano)) {
|
Chris@161
|
141 ii.push_back(piano);
|
Chris@161
|
142 }
|
Chris@161
|
143
|
Chris@176
|
144 vector<Templates> stringTemplates;
|
Chris@176
|
145 vector<Templates> windTemplates;
|
Chris@176
|
146
|
Chris@161
|
147 for (int i = 0;
|
Chris@161
|
148 i < int(sizeof(simpleInstruments)/sizeof(simpleInstruments[0]));
|
Chris@161
|
149 i += 2) {
|
Chris@213
|
150
|
Chris@161
|
151 vector<Templates> tt;
|
Chris@161
|
152 Templates t = templatesFor(simpleInstruments[i+1]);
|
Chris@161
|
153 tt.push_back(t);
|
Chris@161
|
154 allTemplates.push_back(t);
|
Chris@161
|
155 InstrumentPack instr(t.lowestNote,
|
Chris@161
|
156 t.highestNote,
|
Chris@161
|
157 simpleInstruments[i],
|
Chris@161
|
158 tt);
|
Chris@266
|
159
|
Chris@200
|
160 instr.maxPolyphony = 5;
|
Chris@200
|
161 instr.levelThreshold = 6;
|
Chris@266
|
162
|
Chris@220
|
163 if (isBowedString(i)) {
|
Chris@266
|
164 instr.maxPolyphony = 2;
|
Chris@268
|
165 instr.levelThreshold = 5;
|
Chris@183
|
166 stringTemplates.push_back(t);
|
Chris@183
|
167 }
|
Chris@183
|
168 if (isWind(i)) {
|
Chris@266
|
169 instr.maxPolyphony = 2;
|
Chris@183
|
170 windTemplates.push_back(t);
|
Chris@183
|
171 }
|
Chris@161
|
172 if (isOK(instr)) {
|
Chris@161
|
173 ii.push_back(instr);
|
Chris@161
|
174 }
|
Chris@161
|
175 }
|
Chris@161
|
176
|
Chris@161
|
177 InstrumentPack all(silvet_templates_lowest_note,
|
Chris@161
|
178 silvet_templates_highest_note,
|
Chris@161
|
179 "Multiple or unknown instruments",
|
Chris@161
|
180 allTemplates);
|
Chris@183
|
181 all.maxPolyphony = 5;
|
Chris@268
|
182 all.levelThreshold = 6;
|
Chris@161
|
183 if (isOK(all)) {
|
Chris@161
|
184 ii.insert(ii.begin(), all);
|
Chris@161
|
185 }
|
Chris@161
|
186
|
Chris@176
|
187 InstrumentPack strings(silvet_templates_lowest_note, // cello
|
Chris@176
|
188 silvet_templates_highest_note, // violin
|
Chris@220
|
189 "String quartet",
|
Chris@176
|
190 stringTemplates);
|
Chris@183
|
191 strings.maxPolyphony = 5;
|
Chris@268
|
192 strings.levelThreshold = 5;
|
Chris@176
|
193 if (isOK(strings)) {
|
Chris@176
|
194 ii.push_back(strings);
|
Chris@176
|
195 }
|
Chris@176
|
196
|
Chris@176
|
197 InstrumentPack winds(silvet_templates_lowest_note, // basson
|
Chris@176
|
198 silvet_templates_highest_note, // flute
|
Chris@176
|
199 "Wind ensemble",
|
Chris@176
|
200 windTemplates);
|
Chris@183
|
201 winds.maxPolyphony = 5;
|
Chris@183
|
202 winds.levelThreshold = 5;
|
Chris@176
|
203 if (isOK(winds)) {
|
Chris@176
|
204 ii.push_back(winds);
|
Chris@176
|
205 }
|
Chris@176
|
206
|
Chris@161
|
207 return ii;
|
Chris@161
|
208 }
|
Chris@161
|
209
|