1 /*
2     Copyright (C) 2004-2008 Fons Adriaensen  <fons@kokkinizita.net>
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 
20 //-----------------------------------------------------------------------------------
21 // Common definitions
22 //-----------------------------------------------------------------------------------
23 
24 
25 #include "ambisonic1.h"
26 
27 
28 #define NMODS 6
29 #define VERSION "0.6.1"
30 
31 
32 static const char* maker = "Fons Adriaensen <fons@kokkinizita.net>";
33 static const char* copyr = "GPL";
34 
35 
pconnect(LADSPA_Handle H,unsigned long port,LADSPA_Data * data)36 static void pconnect (LADSPA_Handle H, unsigned long port, LADSPA_Data *data)
37 {
38     ((LadspaPlugin *)H)->setport (port, data);
39 }
40 
activate(LADSPA_Handle H)41 static void activate (LADSPA_Handle H)
42 {
43     ((LadspaPlugin *)H)->active (true);
44 }
45 
runplugin(LADSPA_Handle H,unsigned long k)46 static void runplugin (LADSPA_Handle H, unsigned long k)
47 {
48     ((LadspaPlugin *)H)->runproc (k, false);
49 }
50 /*
51 static void runadding (LADSPA_Handle H, unsigned long k)
52 {
53     ((LadspaPlugin *)H)->runproc (k, true);
54 }
55 
56 static void setadding (LADSPA_Handle H, LADSPA_Data gain)
57 {
58     ((LadspaPlugin *)H)->setgain (gain);
59 }
60 */
deactivate(LADSPA_Handle H)61 static void deactivate (LADSPA_Handle H)
62 {
63     ((LadspaPlugin *)H)->active (false);
64 }
65 
cleanup(LADSPA_Handle H)66 static void cleanup (LADSPA_Handle H)
67 {
68     delete (LadspaPlugin *) H;
69 }
70 
71 
72 //-----------------------------------------------------------------------------------
73 // Plugin definitions
74 //-----------------------------------------------------------------------------------
75 
76 
77 static const char* label0 = "Ambisonics-11-mono-panner";
78 static const char* name0  = "AMB order 1,1 mono panner";
79 
80 
instant0(const struct _LADSPA_Descriptor * desc,unsigned long rate)81 static LADSPA_Handle instant0 (const struct _LADSPA_Descriptor *desc, unsigned long rate)
82 {
83     return new Ladspa_Monopan11 (rate);
84 }
85 
86 
87 static const LADSPA_PortDescriptor pdesc0 [Ladspa_Monopan11::NPORT] =
88 {
89     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
90     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
91     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
92     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
93     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
94     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
95     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL
96 };
97 
98 static const char * const pname0 [Ladspa_Monopan11::NPORT] =
99 {
100   "In",
101   "Out-W",
102   "Out-X",
103   "Out-Y",
104   "Out-Z",
105   "Elevation",
106   "Azimuth"
107 };
108 
109 static const LADSPA_PortRangeHint phint0 [Ladspa_Monopan11::NPORT] =
110 {
111   { 0, 0, 0 },
112   { 0, 0, 0 },
113   { 0, 0, 0 },
114   { 0, 0, 0 },
115   { 0, 0, 0 },
116   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -90, 90 },
117   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -180, 180 }
118 };
119 
120 
121 //-----------------------------------------------------------------------------------
122 
123 
124 static const char* label1 = "Ambisonics-11-stereo-panner";
125 static const char* name1  = "AMB order 1,1 stereo panner";
126 
127 
instant1(const struct _LADSPA_Descriptor * desc,unsigned long rate)128 static LADSPA_Handle instant1 (const struct _LADSPA_Descriptor *desc, unsigned long rate)
129 {
130     return new Ladspa_Stereopan11 (rate);
131 }
132 
133 
134 static const LADSPA_PortDescriptor pdesc1 [Ladspa_Stereopan11::NPORT] =
135 {
136     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
137     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
138     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
139     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
140     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
141     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
142     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
143     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
144     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL
145 };
146 
147 static const char * const pname1 [Ladspa_Stereopan11::NPORT] =
148 {
149   "In-L",
150   "In-R",
151   "Out-W",
152   "Out-X",
153   "Out-Y",
154   "Out-Z",
155   "Elevation",
156   "Width",
157   "Azimuth"
158 };
159 
160 static const LADSPA_PortRangeHint phint1 [Ladspa_Stereopan11::NPORT] =
161 {
162   { 0, 0, 0 },
163   { 0, 0, 0 },
164   { 0, 0, 0 },
165   { 0, 0, 0 },
166   { 0, 0, 0 },
167   { 0, 0, 0 },
168   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0,        -90,  90 },
169   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM,  -90,  90 },
170   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0,       -180, 180 }
171 };
172 
173 
174 //-----------------------------------------------------------------------------------
175 
176 
177 static const char* label2 = "Ambisonics-11-rotator";
178 static const char* name2  = "AMB order 1,1 rotator";
179 
180 
instant2(const struct _LADSPA_Descriptor * desc,unsigned long rate)181 static LADSPA_Handle instant2 (const struct _LADSPA_Descriptor *desc, unsigned long rate)
182 {
183     return new Ladspa_Rotator11 (rate);
184 }
185 
186 
187 static const LADSPA_PortDescriptor pdesc2 [Ladspa_Rotator11::NPORT] =
188 {
189     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
190     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
191     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
192     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
193     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
194     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
195     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
196     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
197     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL
198 };
199 
200 static const char * const pname2 [Ladspa_Rotator11::NPORT] =
201 {
202   "In-W",
203   "In-X",
204   "In-Y",
205   "In-Z",
206   "Out-W",
207   "Out-X",
208   "Out-Y",
209   "Out-Z",
210   "Angle"
211 };
212 
213 static const LADSPA_PortRangeHint phint2 [Ladspa_Rotator11::NPORT] =
214 {
215   { 0, 0, 0 },
216   { 0, 0, 0 },
217   { 0, 0, 0 },
218   { 0, 0, 0 },
219   { 0, 0, 0 },
220   { 0, 0, 0 },
221   { 0, 0, 0 },
222   { 0, 0, 0 },
223   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -180, 180 }
224 };
225 
226 
227 //-----------------------------------------------------------------------------------
228 
229 
230 static const char* label3 = "Ambisonics-11-square-decoder";
231 static const char* name3  = "AMB order 1,1 square decoder";
232 
233 
instant3(const struct _LADSPA_Descriptor * desc,unsigned long rate)234 static LADSPA_Handle instant3 (const struct _LADSPA_Descriptor *desc, unsigned long rate)
235 {
236     return new Ladspa_SquareDec11 (rate);
237 }
238 
239 
240 static const LADSPA_PortDescriptor pdesc3 [Ladspa_SquareDec11::NPORT] =
241 {
242     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
243     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
244     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
245     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
246     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
247     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
248     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
249     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
250     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
251     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
252     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
253     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
254     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
255     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL
256 };
257 
258 static const char * const pname3 [Ladspa_SquareDec11::NPORT] =
259 {
260   "In-W",
261   "In-X",
262   "In-Y",
263   "In-Z",
264   "Out-LF/F",
265   "Out-RF/R",
266   "Out-RB/B",
267   "Out-LB/L",
268   "Front spkr",
269   "Shelf filt",
270   "HF XY gain",
271   "LF XY gain",
272   "Shelf freq",
273   "Distance"
274 };
275 
276 static const LADSPA_PortRangeHint phint3 [Ladspa_SquareDec11::NPORT] =
277 {
278   { 0, 0, 0 },
279   { 0, 0, 0 },
280   { 0, 0, 0 },
281   { 0, 0, 0 },
282   { 0, 0, 0 },
283   { 0, 0, 0 },
284   { 0, 0, 0 },
285   { 0, 0, 0 },
286   { LADSPA_HINT_TOGGLED | LADSPA_HINT_DEFAULT_0, 0, 1 },
287   { LADSPA_HINT_TOGGLED | LADSPA_HINT_DEFAULT_0, 0, 1 },
288   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC,  1, 2 },
289   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC,  1, 2 },
290   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE, 200, 800 },
291   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM | LADSPA_HINT_LOGARITHMIC, 1, 30 }
292 };
293 
294 
295 //-----------------------------------------------------------------------------------
296 
297 
298 static const char* label4 = "Ambisonics-11-hexagon-decoder";
299 static const char* name4  = "AMB order 1,1 hexagon decoder";
300 
301 
instant4(const struct _LADSPA_Descriptor * desc,unsigned long rate)302 static LADSPA_Handle instant4 (const struct _LADSPA_Descriptor *desc, unsigned long rate)
303 {
304     return new Ladspa_HexaDec11 (rate);
305 }
306 
307 
308 static const LADSPA_PortDescriptor pdesc4 [Ladspa_HexaDec11::NPORT] =
309 {
310     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
311     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
312     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
313     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
314     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
315     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
316     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
317     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
318     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
319     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
320     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
321     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
322     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
323     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
324     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
325     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL
326 };
327 
328 static const char * const pname4 [Ladspa_HexaDec11::NPORT] =
329 {
330   "In-W",
331   "In-X",
332   "In-Y",
333   "In-Z",
334   "Out-LF/F",
335   "Out-RF/RF",
336   "Out-R/RB",
337   "Out-RB/B",
338   "Out-LB/LB",
339   "Out-L/LF",
340   "Front spkr",
341   "Shelf filt",
342   "HF XY gain",
343   "LF XY gain",
344   "Shelf freq",
345   "Distance"
346 };
347 
348 static const LADSPA_PortRangeHint phint4 [Ladspa_HexaDec11::NPORT] =
349 {
350   { 0, 0, 0 },
351   { 0, 0, 0 },
352   { 0, 0, 0 },
353   { 0, 0, 0 },
354   { 0, 0, 0 },
355   { 0, 0, 0 },
356   { 0, 0, 0 },
357   { 0, 0, 0 },
358   { 0, 0, 0 },
359   { 0, 0, 0 },
360   { LADSPA_HINT_TOGGLED | LADSPA_HINT_DEFAULT_0, 0, 1 },
361   { LADSPA_HINT_TOGGLED | LADSPA_HINT_DEFAULT_0, 0, 1 },
362   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC,  1, 2 },
363   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC,  1, 2 },
364   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE, 200, 800 },
365   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM | LADSPA_HINT_LOGARITHMIC, 1, 30 }
366 };
367 
368 
369 //-----------------------------------------------------------------------------------
370 
371 
372 static const char* label5 = "Ambisonics-11-cube-decoder";
373 static const char* name5  = "AMB order 1,1 cube decoder";
374 
375 
instant5(const struct _LADSPA_Descriptor * desc,unsigned long rate)376 static LADSPA_Handle instant5 (const struct _LADSPA_Descriptor *desc, unsigned long rate)
377 {
378     return new Ladspa_CubeDec11 (rate);
379 }
380 
381 
382 static const LADSPA_PortDescriptor pdesc5 [Ladspa_CubeDec11::NPORT] =
383 {
384     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
385     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
386     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
387     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
388     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
389     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
390     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
391     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
392     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
393     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
394     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
395     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
396     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
397     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
398     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
399     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL,
400     LADSPA_PORT_INPUT  | LADSPA_PORT_CONTROL
401 };
402 
403 static const char * const pname5 [Ladspa_CubeDec11::NPORT] =
404 {
405   "In-W",
406   "In-X",
407   "In-Y",
408   "In-Z",
409   "Out-DLF",
410   "Out-DRF",
411   "Out-DRB",
412   "Out-DLB",
413   "Out-ULF",
414   "Out-URF",
415   "Out-URB",
416   "Out-ULB",
417   "Shelf filt",
418   "HF XYZ gain",
419   "LF XYZ gain",
420   "Shelf freq",
421   "Distance"
422 };
423 
424 static const LADSPA_PortRangeHint phint5 [Ladspa_CubeDec11::NPORT] =
425 {
426   { 0, 0, 0 },
427   { 0, 0, 0 },
428   { 0, 0, 0 },
429   { 0, 0, 0 },
430   { 0, 0, 0 },
431   { 0, 0, 0 },
432   { 0, 0, 0 },
433   { 0, 0, 0 },
434   { 0, 0, 0 },
435   { 0, 0, 0 },
436   { 0, 0, 0 },
437   { 0, 0, 0 },
438   { LADSPA_HINT_TOGGLED | LADSPA_HINT_DEFAULT_0, 0, 1 },
439   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC,  1, 3 },
440   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC,  1, 3 },
441   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE, 200, 800 },
442   { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM | LADSPA_HINT_LOGARITHMIC, 1, 30 }
443 };
444 
445 
446 //-----------------------------------------------------------------------------------
447 //  LADSPA dlsym interface
448 //-----------------------------------------------------------------------------------
449 
450 
451 static const LADSPA_Descriptor moddescr [NMODS] =
452 {
453   {
454     1973,
455     label0,
456     LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
457     name0,
458     maker,
459     copyr,
460     Ladspa_Monopan11::NPORT,
461     pdesc0,
462     pname0,
463     phint0,
464     0,
465     instant0,
466     pconnect,
467     activate,
468     runplugin,
469     0,
470     0,
471     deactivate,
472     cleanup
473   },
474   {
475     1974,
476     label1,
477     LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
478     name1,
479     maker,
480     copyr,
481     Ladspa_Stereopan11::NPORT,
482     pdesc1,
483     pname1,
484     phint1,
485     0,
486     instant1,
487     pconnect,
488     activate,
489     runplugin,
490     0,
491     0,
492     deactivate,
493     cleanup
494   },
495   {
496     1975,
497     label2,
498     LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
499     name2,
500     maker,
501     copyr,
502     Ladspa_Rotator11::NPORT,
503     pdesc2,
504     pname2,
505     phint2,
506     0,
507     instant2,
508     pconnect,
509     activate,
510     runplugin,
511     0,
512     0,
513     deactivate,
514     cleanup
515   },
516   {
517     1976,
518     label3,
519     LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
520     name3,
521     maker,
522     copyr,
523     Ladspa_SquareDec11::NPORT,
524     pdesc3,
525     pname3,
526     phint3,
527     0,
528     instant3,
529     pconnect,
530     activate,
531     runplugin,
532     0,
533     0,
534     deactivate,
535     cleanup
536   },
537   {
538     1977,
539     label4,
540     LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
541     name4,
542     maker,
543     copyr,
544     Ladspa_HexaDec11::NPORT,
545     pdesc4,
546     pname4,
547     phint4,
548     0,
549     instant4,
550     pconnect,
551     activate,
552     runplugin,
553     0,
554     0,
555     deactivate,
556     cleanup
557   },
558   {
559     1978,
560     label5,
561     LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
562     name5,
563     maker,
564     copyr,
565     Ladspa_CubeDec11::NPORT,
566     pdesc5,
567     pname5,
568     phint5,
569     0,
570     instant5,
571     pconnect,
572     activate,
573     runplugin,
574     0,
575     0,
576     deactivate,
577     cleanup
578     }
579 };
580 
581 
ladspa_descriptor(unsigned long i)582 extern "C" const LADSPA_Descriptor *ladspa_descriptor (unsigned long i)
583 {
584   if (i >= NMODS) return 0;
585   return moddescr + i;
586 }
587 
588 
589 //-----------------------------------------------------------------------------------
590