/[svn]/linuxsampler/trunk/src/engines/sfz/LookupTable.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/sfz/LookupTable.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2106 - (show annotations) (download)
Sun Jul 4 12:50:51 2010 UTC (13 years, 9 months ago) by persson
File size: 11225 byte(s)
* sfz engine: optimized sample lookup
* sfz engine: fixed bug introduced in previous commit: sample lookup
  returned wrong sample

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2010 Andreas Persson *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
20 * MA 02110-1301 USA *
21 ***************************************************************************/
22
23 #include "LookupTable.h"
24 #include <cstdio>
25 #include <set>
26 #include "../../common/global_private.h"
27
28 namespace sfz {
29
30 struct LookupTable::DimDef {
31 const int Definition::* lo;
32 const int Definition::* hi;
33 const uint8_t Query::* qarg;
34 int min;
35 int max;
36 const char* str;
37 };
38
39 // List of all dimensions handled by the lookup table, except
40 // control change. Only uint8_t types are currently supported.
41 const LookupTable::DimDef LookupTable::dimDefs[] = {
42 { &Region::lochan, &Region::hichan,
43 &Query::chan, 1, 16, "chan" },
44 { &Region::lokey, &Region::hikey,
45 &Query::key, 0, 127, "key" },
46 { &Region::lovel, &Region::hivel,
47 &Query::vel, 0, 127, "vel" },
48 { &Region::lochanaft, &Region::hichanaft,
49 &Query::chanaft, 0, 127, "chanaft" },
50 { &Region::lopolyaft, &Region::hipolyaft,
51 &Query::polyaft, 0, 127, "polyaft" },
52 { &Region::loprog, &Region::hiprog,
53 &Query::prog, 0, 127, "prog" },
54 { &Region::sw_previous, &Region::sw_previous,
55 &Query::prev_sw_key, -1, -1, "sw_previous" },
56 { 0, 0, 0, 0 }
57 };
58
59 // fills a mapping array for a given dimension
60 int LookupTable::fillMapArr(const std::vector<Region*>& regions,
61 const int Definition::* lo,
62 const int Definition::* hi,
63 int min, int max, int* a) {
64 std::set<int> s;
65 s.insert(min);
66 s.insert(max + 1);
67 for (std::vector<Region*>::const_iterator i = regions.begin() ;
68 i != regions.end() ; ++i) {
69 s.insert((*i)->*lo);
70 s.insert((*i)->*hi + 1);
71 }
72
73 int j = min;
74 int l = -1;
75 for (std::set<int>::const_iterator i = s.begin() ;
76 i != s.end() ; ++i) {
77 dmsg(2,(" %d", *i));
78 for ( ; j < *i ; j++) {
79 a[j] = l;
80 }
81 l++;
82 }
83 dmsg(2,("\n"));
84 return l;
85 }
86
87 // fills a mapping array for a given control change number
88 int LookupTable::fillMapArr(const std::vector<Region*>& regions,
89 int cc, int* a) {
90 std::set<int> s;
91 s.insert(0);
92 s.insert(128);
93 for (std::vector<Region*>::const_iterator i = regions.begin() ;
94 i != regions.end() ; ++i) {
95 s.insert((*i)->locc[cc]);
96 s.insert((*i)->hicc[cc] + 1);
97 }
98
99 int j = 0;
100 int l = -1;
101 for (std::set<int>::const_iterator i = s.begin() ;
102 i != s.end() ; ++i) {
103 dmsg(2,(" %d", *i));
104 for ( ; j < *i ; j++) {
105 a[j] = l;
106 }
107 l++;
108 }
109 dmsg(2,("\n"));
110 return l;
111 }
112
113 LinuxSampler::ArrayList<Region*>&
114 LookupTable::query(const Query& q) const {
115 int offset = 0;
116 int dim;
117 for (dim = 0 ; qargs[dim] ; dim++) {
118 offset += mapArr[dim][q.*qargs[dim]];
119 }
120 for (int cc = 0 ; ccargs[cc] >= 0 ; cc++, dim++) {
121 offset += mapArr[dim][q.cc[ccargs[cc]]];
122 }
123 return regionArr[offset];
124 }
125
126 // recursively fills the region array with regions
127 void LookupTable::fillRegionArr(const int* len, Region* region,
128 std::vector<int>::size_type dim, int j) {
129 if (dim == dims.size() + ccs.size()) {
130 regionArr[j].add(region);
131 } else if (dim < dims.size()) {
132 int d = dims[dim];
133 int hi = region->*dimDefs[d].hi;
134 // special case for sw_previous
135 if (hi == -1) hi = 127;
136 for (int l = mapArr[dim][region->*dimDefs[d].lo] ;
137 l <= mapArr[dim][hi] ; l++) {
138 fillRegionArr(len, region, dim + 1, j * len[dim] + l);
139 }
140 } else {
141 int cc = ccs[dim - dims.size()];
142 for (int l = mapArr[dim][region->locc[cc]] ;
143 l <= mapArr[dim][region->hicc[cc]] ; l++) {
144 fillRegionArr(len, region, dim + 1, j * len[dim] + l);
145 }
146 }
147 }
148
149
150 LookupTable::LookupTable(const Instrument* instrument) {
151 const std::vector<Region*>& regions = instrument->regions;
152
153 // find dimensions used by the instrument
154 for (int dim = 0 ; dimDefs[dim].lo ; dim++) {
155 for (std::vector<Region*>::const_iterator i = regions.begin() ;
156 i != regions.end() ; ++i) {
157 if ((*i)->*dimDefs[dim].lo != dimDefs[dim].min ||
158 (*i)->*dimDefs[dim].hi != dimDefs[dim].max) {
159 dims.push_back(dim);
160 break;
161 }
162 }
163 }
164
165 dmsg(2,("\n"));
166
167 // create and fill the qargs array with pointers to Query
168 // members
169 qargs = new const uint8_t Query::*[dims.size() + 1];
170 for (std::vector<int>::size_type i = 0 ; i < dims.size() ; i++) {
171 dmsg(2,("qargs %d: %s\n", i, dimDefs[dims[i]].str));
172 qargs[i] = dimDefs[dims[i]].qarg;
173 }
174 qargs[dims.size()] = 0;
175
176 // find CC dimensions used by the instrument
177 for (int cc = 0 ; cc < 128 ; cc++) {
178 for (std::vector<Region*>::const_iterator i = regions.begin() ;
179 i != regions.end() ; ++i) {
180 if ((*i)->locc[cc] > 0 ||
181 ((*i)->hicc[cc] != 127 && (*i)->hicc[cc] != -1)) {
182 ccs.push_back(cc);
183 break;
184 }
185 }
186 }
187
188 // copy ccs vector to ccargs array
189 ccargs = new int[ccs.size() + 1];
190 for (std::vector<int>::size_type i = 0 ; i < ccs.size() ; ++i) {
191 dmsg(2,("ccargs %d: %d\n", i, ccs[i]));
192 ccargs[i] = ccs[i];
193 }
194 ccargs[ccs.size()] = -1;
195
196 int nbDimensions = dims.size() + ccs.size();
197 int* len = new int[nbDimensions];
198 mapArr = new int*[nbDimensions];
199
200 int size = 1;
201 int dim = 0;
202
203 // create and fill the dimension mapping arrays
204
205 for (std::vector<int>::const_iterator dimi = dims.begin() ;
206 dimi != dims.end() ; ++dimi) {
207 int min = dimDefs[*dimi].min;
208 int max = dimDefs[*dimi].max == -1 ? 127 : dimDefs[*dimi].max;
209 mapArr[dim] = new int[max - min + 1] - min;
210 len[dim] = fillMapArr(regions, dimDefs[*dimi].lo, dimDefs[*dimi].hi,
211 min, max, mapArr[dim]);
212 size *= len[dim];
213 dim++;
214 }
215
216 for (std::vector<int>::const_iterator cci = ccs.begin() ;
217 cci != ccs.end() ; ++cci) {
218 mapArr[dim] = new int[128];
219 len[dim] = fillMapArr(regions, *cci, mapArr[dim]);
220 size *= len[dim];
221 dim++;
222 }
223
224
225 dmsg(2,("-------------------------------\n"));
226 dmsg(2,("nbDimensions=%d size=%d\n", nbDimensions, size));
227
228 // create and fill the region array
229 regionArr = new LinuxSampler::ArrayList<Region*>[size];
230
231 for (std::vector<Region*>::const_iterator i = regions.begin() ;
232 i != regions.end() ; ++i) {
233 fillRegionArr(len, *i, 0, 0);
234 }
235
236 // multiply the offsets in the mapping arrays so simple
237 // addition can be used in the query method
238 if (nbDimensions) {
239 int c = len[nbDimensions - 1];
240 for (dim = nbDimensions - 2 ; dim >= 0 ; dim--) {
241 for (int i = 0 ; i < 128 ; i++) mapArr[dim][i] *= c;
242 c *= len[dim];
243 }
244 }
245
246 #if CONFIG_DEBUG_LEVEL >= 2
247 // print the dimension mapping arrays
248
249 dmsg(2,("-------------------------------\n"));
250 dim = 0;
251 for (std::vector<int>::const_iterator dimi = dims.begin() ;
252 dimi != dims.end() ; ++dimi) {
253 dmsg(2,("%d: len=%d dim=%s\n", dim, len[dim], dimDefs[*dimi].str));
254
255 int max = dimDefs[*dimi].max == -1 ? 127 : dimDefs[*dimi].max;
256 for (int i = dimDefs[*dimi].min ; i <= max ; i++) {
257 dmsg(2,(" %d", mapArr[dim][i]));
258 }
259 dmsg(2,("\n"));
260
261 dim++;
262 }
263 for (std::vector<int>::const_iterator cci = ccs.begin() ;
264 cci != ccs.end() ; ++cci) {
265 dmsg(2,("%d: len=%d cc=%d\n", dim, len[dim], *cci));
266
267 for (int i = 0 ; i < 128 ; i++) {
268 dmsg(2,(" %d", mapArr[dim][i]));
269 }
270 dmsg(2,("\n"));
271
272 dim++;
273 }
274 #endif
275 delete[] len;
276
277 #if CONFIG_DEBUG_LEVEL >= 3
278 // print the region array
279
280 int tot = 0;
281 for (int i = 0 ; i < size ; i++) {
282 dmsg(3,("%d:", i));
283 for (int j = 0 ; j < regionArr[i].size() ; j++) {
284 dmsg(3,(" %s", regionArr[i][j]->sample.c_str()));
285 tot++;
286 }
287 dmsg(3,("\n"));
288 }
289 dmsg(3,("tot=%d\n", tot));
290 #endif
291 }
292
293 LookupTable::~LookupTable() {
294 delete[] qargs;
295 delete[] ccargs;
296 delete[] regionArr;
297
298 int dim = 0;
299 for (std::vector<int>::const_iterator dimi = dims.begin() ;
300 dimi != dims.end() ; ++dimi) {
301 delete[] (mapArr[dim] + dimDefs[*dimi].min);
302 dim++;
303 }
304 for (std::vector<int>::const_iterator cci = ccs.begin() ;
305 cci != ccs.end() ; ++cci) {
306 delete[] mapArr[dim];
307 dim++;
308 }
309 delete[] mapArr;
310 }
311 }

  ViewVC Help
Powered by ViewVC