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@161
|
37 "Cello", "cello",
|
Chris@161
|
38 "Horn", "horn",
|
Chris@161
|
39 "Flute", "flute",
|
Chris@161
|
40 "Oboe", "oboe",
|
Chris@161
|
41 "Clarinet", "clarinet",
|
Chris@161
|
42 "Tenor Sax", "tenorsax",
|
Chris@161
|
43 "Bassoon", "bassoon",
|
Chris@161
|
44 };
|
Chris@161
|
45
|
Chris@176
|
46 static bool
|
Chris@176
|
47 isString(int i)
|
Chris@176
|
48 {
|
Chris@176
|
49 string tname(simpleInstruments[i+1]);
|
Chris@176
|
50 return tname == "violin"
|
Chris@176
|
51 || tname == "cello"
|
Chris@176
|
52 ;
|
Chris@176
|
53 }
|
Chris@176
|
54
|
Chris@176
|
55 static bool
|
Chris@176
|
56 isWind(int i)
|
Chris@176
|
57 {
|
Chris@176
|
58 string tname(simpleInstruments[i+1]);
|
Chris@176
|
59 return tname == "horn"
|
Chris@176
|
60 || tname == "flute"
|
Chris@176
|
61 || tname == "oboe"
|
Chris@176
|
62 || tname == "clarinet"
|
Chris@176
|
63 || tname == "tenorsax"
|
Chris@176
|
64 || tname == "bassoon"
|
Chris@176
|
65 ;
|
Chris@176
|
66 }
|
Chris@176
|
67
|
Chris@161
|
68 static InstrumentPack::Templates
|
Chris@161
|
69 templatesFor(string name)
|
Chris@161
|
70 {
|
Chris@161
|
71 for (int i = 0; i < SILVET_TEMPLATE_COUNT; ++i) {
|
Chris@161
|
72
|
Chris@161
|
73 if (string(silvet_templates[i].name) == name) {
|
Chris@161
|
74
|
Chris@161
|
75 silvet_template_t *t = &silvet_templates[i];
|
Chris@161
|
76
|
Chris@161
|
77 InstrumentPack::Templates rt;
|
Chris@161
|
78 rt.lowestNote = t->lowest;
|
Chris@161
|
79 rt.highestNote = t->highest;
|
Chris@161
|
80 rt.data = vector<vector<float> >
|
Chris@161
|
81 (SILVET_TEMPLATE_NOTE_COUNT,
|
Chris@161
|
82 vector<float>(SILVET_TEMPLATE_SIZE, 0.f));
|
Chris@161
|
83
|
Chris@161
|
84 for (int j = 0; j < SILVET_TEMPLATE_NOTE_COUNT; ++j) {
|
Chris@161
|
85 for (int k = 0; k < SILVET_TEMPLATE_SIZE; ++k) {
|
Chris@161
|
86 rt.data[j][k] = t->data[j][k];
|
Chris@161
|
87 }
|
Chris@161
|
88 }
|
Chris@161
|
89
|
Chris@161
|
90 return rt;
|
Chris@161
|
91 }
|
Chris@161
|
92 }
|
Chris@161
|
93
|
Chris@161
|
94 return InstrumentPack::Templates();
|
Chris@161
|
95 }
|
Chris@161
|
96
|
Chris@161
|
97 static bool
|
Chris@161
|
98 isOK(InstrumentPack &d)
|
Chris@161
|
99 {
|
Chris@161
|
100 if (d.name == "") {
|
Chris@161
|
101 cerr << "ERROR: Silvet::InstrumentPack: Empty name in instrument definition" << endl;
|
Chris@161
|
102 return false;
|
Chris@161
|
103 }
|
Chris@161
|
104 if (d.templates.empty()) {
|
Chris@161
|
105 cerr << "ERROR: Silvet::InstrumentPack: Instrument definition \"" << d.name << "\" contains no templates!" << endl;
|
Chris@161
|
106 return false;
|
Chris@161
|
107 }
|
Chris@161
|
108 for (int i = 0; i < int(d.templates.size()); ++i) {
|
Chris@161
|
109 if (d.templates[i].data.empty()) {
|
Chris@161
|
110 cerr << "ERROR: Silvet::InstrumentPack: Instrument definition \"" << d.name << "\" contains one or more empty templates!" << endl;
|
Chris@161
|
111 return false;
|
Chris@161
|
112 }
|
Chris@161
|
113 }
|
Chris@161
|
114 return true;
|
Chris@161
|
115 }
|
Chris@161
|
116
|
Chris@161
|
117 vector<InstrumentPack>
|
Chris@161
|
118 InstrumentPack::listInstrumentPacks()
|
Chris@161
|
119 {
|
Chris@161
|
120 vector<InstrumentPack> ii;
|
Chris@161
|
121
|
Chris@161
|
122 vector<Templates> allTemplates;
|
Chris@161
|
123 //!!! is piano-maps-SptkBGCl the same as one of piano1, piano2, piano3?
|
Chris@161
|
124 allTemplates.push_back(templatesFor("piano1"));
|
Chris@161
|
125
|
Chris@161
|
126 vector<Templates> pianoTemplates;
|
Chris@161
|
127 pianoTemplates.push_back(templatesFor("piano1"));
|
Chris@161
|
128 pianoTemplates.push_back(templatesFor("piano2"));
|
Chris@161
|
129 pianoTemplates.push_back(templatesFor("piano3"));
|
Chris@161
|
130 InstrumentPack piano(silvet_templates_lowest_note,
|
Chris@161
|
131 silvet_templates_highest_note,
|
Chris@161
|
132 "Piano",
|
Chris@161
|
133 pianoTemplates);
|
Chris@200
|
134 // piano.maxPolyphony = 8;
|
Chris@200
|
135 // piano.levelThreshold = 3;
|
Chris@200
|
136 piano.maxPolyphony = 5;
|
Chris@200
|
137 piano.levelThreshold = 6;
|
Chris@161
|
138 if (isOK(piano)) {
|
Chris@161
|
139 ii.push_back(piano);
|
Chris@161
|
140 }
|
Chris@161
|
141
|
Chris@176
|
142 vector<Templates> stringTemplates;
|
Chris@176
|
143 vector<Templates> windTemplates;
|
Chris@176
|
144
|
Chris@161
|
145 for (int i = 0;
|
Chris@161
|
146 i < int(sizeof(simpleInstruments)/sizeof(simpleInstruments[0]));
|
Chris@161
|
147 i += 2) {
|
Chris@161
|
148 vector<Templates> tt;
|
Chris@161
|
149 Templates t = templatesFor(simpleInstruments[i+1]);
|
Chris@161
|
150 tt.push_back(t);
|
Chris@161
|
151 allTemplates.push_back(t);
|
Chris@161
|
152 InstrumentPack instr(t.lowestNote,
|
Chris@161
|
153 t.highestNote,
|
Chris@161
|
154 simpleInstruments[i],
|
Chris@161
|
155 tt);
|
Chris@200
|
156 // instr.pitchSparsity = 1.5;
|
Chris@200
|
157 instr.maxPolyphony = 5;
|
Chris@200
|
158 instr.levelThreshold = 6;
|
Chris@183
|
159 if (isString(i)) {
|
Chris@200
|
160 // instr.maxPolyphony = 2;
|
Chris@200
|
161 // instr.levelThreshold = 3;
|
Chris@183
|
162 stringTemplates.push_back(t);
|
Chris@183
|
163 }
|
Chris@183
|
164 if (isWind(i)) {
|
Chris@200
|
165 // instr.maxPolyphony = 1;
|
Chris@200
|
166 // instr.levelThreshold = 5;
|
Chris@183
|
167 windTemplates.push_back(t);
|
Chris@183
|
168 }
|
Chris@161
|
169 if (isOK(instr)) {
|
Chris@161
|
170 ii.push_back(instr);
|
Chris@161
|
171 }
|
Chris@161
|
172 }
|
Chris@161
|
173
|
Chris@161
|
174 InstrumentPack all(silvet_templates_lowest_note,
|
Chris@161
|
175 silvet_templates_highest_note,
|
Chris@161
|
176 "Multiple or unknown instruments",
|
Chris@161
|
177 allTemplates);
|
Chris@183
|
178 all.maxPolyphony = 5;
|
Chris@183
|
179 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
|
180 if (isOK(all)) {
|
Chris@161
|
181 ii.insert(ii.begin(), all);
|
Chris@161
|
182 }
|
Chris@161
|
183
|
Chris@176
|
184 InstrumentPack strings(silvet_templates_lowest_note, // cello
|
Chris@176
|
185 silvet_templates_highest_note, // violin
|
Chris@176
|
186 "String ensemble",
|
Chris@176
|
187 stringTemplates);
|
Chris@183
|
188 strings.maxPolyphony = 5;
|
Chris@183
|
189 strings.levelThreshold = 3;
|
Chris@176
|
190 if (isOK(strings)) {
|
Chris@176
|
191 ii.push_back(strings);
|
Chris@176
|
192 }
|
Chris@176
|
193
|
Chris@176
|
194 InstrumentPack winds(silvet_templates_lowest_note, // basson
|
Chris@176
|
195 silvet_templates_highest_note, // flute
|
Chris@176
|
196 "Wind ensemble",
|
Chris@176
|
197 windTemplates);
|
Chris@183
|
198 winds.maxPolyphony = 5;
|
Chris@183
|
199 winds.levelThreshold = 5;
|
Chris@176
|
200 if (isOK(winds)) {
|
Chris@176
|
201 ii.push_back(winds);
|
Chris@176
|
202 }
|
Chris@176
|
203
|
Chris@161
|
204 return ii;
|
Chris@161
|
205 }
|
Chris@161
|
206
|