/[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 2106 - (hide annotations) (download)
Sun Jul 4 12:50:51 2010 UTC (13 years, 8 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 persson 2106 /***************************************************************************
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