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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2361 - (hide annotations) (download)
Sun Aug 26 07:31:12 2012 UTC (11 years, 7 months ago) by persson
File size: 12910 byte(s)
* sfz engine: fixed crash when using lochan/hichan opcodes (#187)

1 persson 2106 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 persson 2361 * Copyright (C) 2010 - 2012 Andreas Persson *
6 persson 2106 * *
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 persson 2115 int cc, int* a, int triggercc) {
90 persson 2106 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 persson 2115 int lo = (*i)->locc[cc];
96     int hi = (*i)->hicc[cc];
97     if (cc == triggercc) {
98     lo = std::max(lo, (*i)->on_locc[cc]);
99     hi = std::min(hi, (*i)->on_hicc[cc]);
100     }
101    
102     s.insert(lo);
103     s.insert(hi + 1);
104 persson 2106 }
105    
106     int j = 0;
107     int l = -1;
108     for (std::set<int>::const_iterator i = s.begin() ;
109     i != s.end() ; ++i) {
110     dmsg(2,(" %d", *i));
111     for ( ; j < *i ; j++) {
112     a[j] = l;
113     }
114     l++;
115     }
116     dmsg(2,("\n"));
117     return l;
118     }
119    
120     LinuxSampler::ArrayList<Region*>&
121     LookupTable::query(const Query& q) const {
122     int offset = 0;
123     int dim;
124     for (dim = 0 ; qargs[dim] ; dim++) {
125 persson 2115 offset += mapArr[dim][int8_t(q.*qargs[dim])];
126 persson 2106 }
127     for (int cc = 0 ; ccargs[cc] >= 0 ; cc++, dim++) {
128     offset += mapArr[dim][q.cc[ccargs[cc]]];
129     }
130     return regionArr[offset];
131     }
132    
133     // recursively fills the region array with regions
134     void LookupTable::fillRegionArr(const int* len, Region* region,
135 persson 2115 std::vector<int>::size_type dim, int j,
136     int triggercc) {
137 persson 2106 if (dim == dims.size() + ccs.size()) {
138     regionArr[j].add(region);
139     } else if (dim < dims.size()) {
140     int d = dims[dim];
141     int hi = region->*dimDefs[d].hi;
142     // special case for sw_previous
143     if (hi == -1) hi = 127;
144     for (int l = mapArr[dim][region->*dimDefs[d].lo] ;
145     l <= mapArr[dim][hi] ; l++) {
146 persson 2115 fillRegionArr(len, region, dim + 1, j * len[dim] + l,
147     triggercc);
148 persson 2106 }
149     } else {
150     int cc = ccs[dim - dims.size()];
151 persson 2115 int lo = region->locc[cc];
152     int hi = region->hicc[cc];
153     if (cc == triggercc) {
154     lo = std::max(lo, region->on_locc[cc]);
155     hi = std::min(hi, region->on_hicc[cc]);
156 persson 2106 }
157 persson 2115 for (int l = mapArr[dim][lo] ; l <= mapArr[dim][hi] ; l++) {
158     fillRegionArr(len, region, dim + 1, j * len[dim] + l,
159     triggercc);
160     }
161 persson 2106 }
162     }
163    
164    
165 persson 2115 LookupTable::LookupTable(const Instrument* instrument, int triggercc) {
166     std::vector<Region*> regions;
167 persson 2106
168 persson 2115 // copy the interesting regions
169     for (std::vector<Region*>::const_iterator i =
170     instrument->regions.begin() ;
171     i != instrument->regions.end() ; ++i) {
172    
173     if (triggercc == -1) {
174     if ((*i)->lokey >= 0) {
175     regions.push_back(*i);
176     }
177     } else {
178     if ((*i)->hikey < 0 &&
179     (*i)->on_locc[triggercc] >= 0 &&
180     (*i)->on_hicc[triggercc] >= 0) {
181     regions.push_back(*i);
182     }
183     }
184     }
185    
186     dmsg(2,("\nregions before filter: %d, after: %d\n",
187     instrument->regions.size(), regions.size()));
188    
189 persson 2106 // find dimensions used by the instrument
190     for (int dim = 0 ; dimDefs[dim].lo ; dim++) {
191     for (std::vector<Region*>::const_iterator i = regions.begin() ;
192     i != regions.end() ; ++i) {
193 persson 2115
194     if ((triggercc == -1 || dimDefs[dim].lo != &Region::lokey) &&
195     ((*i)->*dimDefs[dim].lo != dimDefs[dim].min ||
196     (*i)->*dimDefs[dim].hi != dimDefs[dim].max)) {
197 persson 2106 dims.push_back(dim);
198     break;
199     }
200     }
201     }
202    
203     // create and fill the qargs array with pointers to Query
204     // members
205     qargs = new const uint8_t Query::*[dims.size() + 1];
206     for (std::vector<int>::size_type i = 0 ; i < dims.size() ; i++) {
207     dmsg(2,("qargs %d: %s\n", i, dimDefs[dims[i]].str));
208     qargs[i] = dimDefs[dims[i]].qarg;
209     }
210     qargs[dims.size()] = 0;
211    
212     // find CC dimensions used by the instrument
213     for (int cc = 0 ; cc < 128 ; cc++) {
214     for (std::vector<Region*>::const_iterator i = regions.begin() ;
215     i != regions.end() ; ++i) {
216 persson 2115 int lo = (*i)->locc[cc];
217     int hi = (*i)->hicc[cc]; // TODO == -1 ? 127 : (*i)->hicc[cc];
218     if (cc == triggercc) {
219     lo = std::max(lo, (*i)->on_locc[cc]);
220     hi = std::min(hi, (*i)->on_hicc[cc]);
221     }
222     if (lo > 0 || hi != 127) {
223 persson 2106 ccs.push_back(cc);
224     break;
225     }
226     }
227     }
228    
229     // copy ccs vector to ccargs array
230     ccargs = new int[ccs.size() + 1];
231     for (std::vector<int>::size_type i = 0 ; i < ccs.size() ; ++i) {
232     dmsg(2,("ccargs %d: %d\n", i, ccs[i]));
233     ccargs[i] = ccs[i];
234     }
235     ccargs[ccs.size()] = -1;
236    
237     int nbDimensions = dims.size() + ccs.size();
238     int* len = new int[nbDimensions];
239     mapArr = new int*[nbDimensions];
240    
241     int size = 1;
242     int dim = 0;
243    
244     // create and fill the dimension mapping arrays
245    
246     for (std::vector<int>::const_iterator dimi = dims.begin() ;
247     dimi != dims.end() ; ++dimi) {
248     int min = dimDefs[*dimi].min;
249     int max = dimDefs[*dimi].max == -1 ? 127 : dimDefs[*dimi].max;
250     mapArr[dim] = new int[max - min + 1] - min;
251     len[dim] = fillMapArr(regions, dimDefs[*dimi].lo, dimDefs[*dimi].hi,
252 persson 2115 min, max, mapArr[dim]);
253 persson 2106 size *= len[dim];
254     dim++;
255     }
256    
257     for (std::vector<int>::const_iterator cci = ccs.begin() ;
258     cci != ccs.end() ; ++cci) {
259     mapArr[dim] = new int[128];
260 persson 2115 len[dim] = fillMapArr(regions, *cci, mapArr[dim], triggercc);
261 persson 2106 size *= len[dim];
262     dim++;
263     }
264    
265    
266     dmsg(2,("-------------------------------\n"));
267     dmsg(2,("nbDimensions=%d size=%d\n", nbDimensions, size));
268    
269     // create and fill the region array
270     regionArr = new LinuxSampler::ArrayList<Region*>[size];
271    
272     for (std::vector<Region*>::const_iterator i = regions.begin() ;
273     i != regions.end() ; ++i) {
274 persson 2115 fillRegionArr(len, *i, 0, 0, triggercc);
275 persson 2106 }
276    
277     // multiply the offsets in the mapping arrays so simple
278     // addition can be used in the query method
279     if (nbDimensions) {
280     int c = len[nbDimensions - 1];
281     for (dim = nbDimensions - 2 ; dim >= 0 ; dim--) {
282 persson 2361 const DimDef& dimDef = dimDefs[dims[dim]];
283     int max = dimDef.max == -1 ? 127 : dimDef.max;
284     for (int i = dimDef.min ; i <= max ; i++) mapArr[dim][i] *= c;
285 persson 2106 c *= len[dim];
286     }
287     }
288    
289     #if CONFIG_DEBUG_LEVEL >= 2
290     // print the dimension mapping arrays
291    
292     dmsg(2,("-------------------------------\n"));
293     dim = 0;
294     for (std::vector<int>::const_iterator dimi = dims.begin() ;
295     dimi != dims.end() ; ++dimi) {
296     dmsg(2,("%d: len=%d dim=%s\n", dim, len[dim], dimDefs[*dimi].str));
297    
298     int max = dimDefs[*dimi].max == -1 ? 127 : dimDefs[*dimi].max;
299     for (int i = dimDefs[*dimi].min ; i <= max ; i++) {
300     dmsg(2,(" %d", mapArr[dim][i]));
301     }
302     dmsg(2,("\n"));
303    
304     dim++;
305     }
306     for (std::vector<int>::const_iterator cci = ccs.begin() ;
307     cci != ccs.end() ; ++cci) {
308     dmsg(2,("%d: len=%d cc=%d\n", dim, len[dim], *cci));
309    
310     for (int i = 0 ; i < 128 ; i++) {
311     dmsg(2,(" %d", mapArr[dim][i]));
312     }
313     dmsg(2,("\n"));
314    
315     dim++;
316     }
317     #endif
318     delete[] len;
319    
320     #if CONFIG_DEBUG_LEVEL >= 3
321     // print the region array
322    
323     int tot = 0;
324     for (int i = 0 ; i < size ; i++) {
325     dmsg(3,("%d:", i));
326     for (int j = 0 ; j < regionArr[i].size() ; j++) {
327     dmsg(3,(" %s", regionArr[i][j]->sample.c_str()));
328     tot++;
329     }
330     dmsg(3,("\n"));
331     }
332     dmsg(3,("tot=%d\n", tot));
333     #endif
334     }
335    
336     LookupTable::~LookupTable() {
337     delete[] qargs;
338     delete[] ccargs;
339     delete[] regionArr;
340    
341     int dim = 0;
342     for (std::vector<int>::const_iterator dimi = dims.begin() ;
343     dimi != dims.end() ; ++dimi) {
344     delete[] (mapArr[dim] + dimDefs[*dimi].min);
345     dim++;
346     }
347     for (std::vector<int>::const_iterator cci = ccs.begin() ;
348     cci != ccs.end() ; ++cci) {
349     delete[] mapArr[dim];
350     dim++;
351     }
352     delete[] mapArr;
353     }
354     }

  ViewVC Help
Powered by ViewVC