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 //!!! is piano-maps-SptkBGCl the same as one of piano1, piano2, piano3?
|
Chris@161
|
126 allTemplates.push_back(templatesFor("piano1"));
|
Chris@214
|
127 allTemplates.push_back(templatesFor("piano2"));
|
Chris@214
|
128 allTemplates.push_back(templatesFor("piano3"));
|
Chris@220
|
129 allTemplates.push_back(templatesFor("pianorwc"));
|
Chris@161
|
130
|
Chris@161
|
131 vector<Templates> pianoTemplates;
|
Chris@161
|
132 pianoTemplates.push_back(templatesFor("piano1"));
|
Chris@161
|
133 pianoTemplates.push_back(templatesFor("piano2"));
|
Chris@161
|
134 pianoTemplates.push_back(templatesFor("piano3"));
|
Chris@220
|
135 pianoTemplates.push_back(templatesFor("pianorwc"));
|
Chris@161
|
136 InstrumentPack piano(silvet_templates_lowest_note,
|
Chris@161
|
137 silvet_templates_highest_note,
|
Chris@161
|
138 "Piano",
|
Chris@161
|
139 pianoTemplates);
|
Chris@200
|
140 // piano.maxPolyphony = 8;
|
Chris@213
|
141 // piano.levelThreshold = 4;
|
Chris@200
|
142 piano.maxPolyphony = 5;
|
Chris@200
|
143 piano.levelThreshold = 6;
|
Chris@213
|
144 piano.pitchSparsity = 1.0;
|
Chris@213
|
145 piano.sourceSparsity = 1.0;
|
Chris@161
|
146 if (isOK(piano)) {
|
Chris@161
|
147 ii.push_back(piano);
|
Chris@161
|
148 }
|
Chris@161
|
149
|
Chris@176
|
150 vector<Templates> stringTemplates;
|
Chris@176
|
151 vector<Templates> windTemplates;
|
Chris@176
|
152
|
Chris@161
|
153 for (int i = 0;
|
Chris@161
|
154 i < int(sizeof(simpleInstruments)/sizeof(simpleInstruments[0]));
|
Chris@161
|
155 i += 2) {
|
Chris@213
|
156
|
Chris@161
|
157 vector<Templates> tt;
|
Chris@161
|
158 Templates t = templatesFor(simpleInstruments[i+1]);
|
Chris@161
|
159 tt.push_back(t);
|
Chris@161
|
160 allTemplates.push_back(t);
|
Chris@161
|
161 InstrumentPack instr(t.lowestNote,
|
Chris@161
|
162 t.highestNote,
|
Chris@161
|
163 simpleInstruments[i],
|
Chris@161
|
164 tt);
|
Chris@200
|
165 // instr.pitchSparsity = 1.5;
|
Chris@200
|
166 instr.maxPolyphony = 5;
|
Chris@200
|
167 instr.levelThreshold = 6;
|
Chris@220
|
168 if (isBowedString(i)) {
|
Chris@200
|
169 // instr.maxPolyphony = 2;
|
Chris@200
|
170 // instr.levelThreshold = 3;
|
Chris@183
|
171 stringTemplates.push_back(t);
|
Chris@183
|
172 }
|
Chris@183
|
173 if (isWind(i)) {
|
Chris@200
|
174 // instr.maxPolyphony = 1;
|
Chris@200
|
175 // instr.levelThreshold = 5;
|
Chris@183
|
176 windTemplates.push_back(t);
|
Chris@183
|
177 }
|
Chris@161
|
178 if (isOK(instr)) {
|
Chris@161
|
179 ii.push_back(instr);
|
Chris@161
|
180 }
|
Chris@161
|
181 }
|
Chris@161
|
182
|
Chris@161
|
183 InstrumentPack all(silvet_templates_lowest_note,
|
Chris@161
|
184 silvet_templates_highest_note,
|
Chris@161
|
185 "Multiple or unknown instruments",
|
Chris@161
|
186 allTemplates);
|
Chris@183
|
187 all.maxPolyphony = 5;
|
Chris@183
|
188 all.levelThreshold = 6;//!!! but this does need to be a parameter too, or else we need to be able to detect very quiet stuff somehow
|
Chris@161
|
189 if (isOK(all)) {
|
Chris@161
|
190 ii.insert(ii.begin(), all);
|
Chris@161
|
191 }
|
Chris@161
|
192
|
Chris@176
|
193 InstrumentPack strings(silvet_templates_lowest_note, // cello
|
Chris@176
|
194 silvet_templates_highest_note, // violin
|
Chris@220
|
195 "String quartet",
|
Chris@176
|
196 stringTemplates);
|
Chris@183
|
197 strings.maxPolyphony = 5;
|
Chris@183
|
198 strings.levelThreshold = 3;
|
Chris@176
|
199 if (isOK(strings)) {
|
Chris@176
|
200 ii.push_back(strings);
|
Chris@176
|
201 }
|
Chris@176
|
202
|
Chris@176
|
203 InstrumentPack winds(silvet_templates_lowest_note, // basson
|
Chris@176
|
204 silvet_templates_highest_note, // flute
|
Chris@176
|
205 "Wind ensemble",
|
Chris@176
|
206 windTemplates);
|
Chris@183
|
207 winds.maxPolyphony = 5;
|
Chris@183
|
208 winds.levelThreshold = 5;
|
Chris@176
|
209 if (isOK(winds)) {
|
Chris@176
|
210 ii.push_back(winds);
|
Chris@176
|
211 }
|
Chris@176
|
212
|
Chris@161
|
213 return ii;
|
Chris@161
|
214 }
|
Chris@161
|
215
|