1 /* DSSI Plugin Framework
2  *
3  * Copyright (C) 2005-2007, 2010 Sean Bolton and others.
4  *
5  * Portions of this file may have come from Peter Hanappe's
6  * Fluidsynth, copyright (C) 2003 Peter Hanappe and others.
7  * Portions of this file may have come from Chris Cannam and Steve
8  * Harris's public domain DSSI example code.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be
16  * useful, but WITHOUT ANY WARRANTY; without even the implied
17  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
18  * PURPOSE.  See the GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this program; if not, write to the Free
22  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301 USA.
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #  include <config.h>
28 #endif
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <unistd.h>
35 #include <pthread.h>
36 
37 #include <ladspa.h>
38 #include <dssi.h>
39 
40 #include "whysynth_types.h"
41 #include "whysynth.h"
42 #include "whysynth_ports.h"
43 #include "dssp_event.h"
44 #include "common_data.h"
45 #include "whysynth_voice.h"
46 #include "agran_oscillator.h"
47 #include "wave_tables.h"
48 #include "sampleset.h"
49 #include "effects.h"
50 
51 static pthread_mutex_t global_mutex;
52 y_global_t             global;
53 
54 static LADSPA_Descriptor *y_LADSPA_descriptor = NULL;
55 static DSSI_Descriptor   *y_DSSI_descriptor = NULL;
56 
57 static void y_cleanup(LADSPA_Handle instance);
58 static void y_run_synth(LADSPA_Handle instance, unsigned long sample_count,
59                              snd_seq_event_t *events, unsigned long event_count);
60 
61 /* ---- mutual exclusion ---- */
62 
63 static inline int
dssp_voicelist_mutex_trylock(y_synth_t * synth)64 dssp_voicelist_mutex_trylock(y_synth_t *synth)
65 {
66     int rc;
67 
68     /* Attempt the mutex lock */
69     rc = pthread_mutex_trylock(&synth->voicelist_mutex);
70     if (rc) {
71         synth->voicelist_mutex_grab_failed = 1;
72         return rc;
73     }
74     /* Clean up if a previous mutex grab failed */
75     if (synth->voicelist_mutex_grab_failed) {
76         y_synth_all_voices_off(synth);
77         synth->voicelist_mutex_grab_failed = 0;
78     }
79     return 0;
80 }
81 
82 inline int
dssp_voicelist_mutex_lock(y_synth_t * synth)83 dssp_voicelist_mutex_lock(y_synth_t *synth)
84 {
85     return pthread_mutex_lock(&synth->voicelist_mutex);
86 }
87 
88 inline int
dssp_voicelist_mutex_unlock(y_synth_t * synth)89 dssp_voicelist_mutex_unlock(y_synth_t *synth)
90 {
91     return pthread_mutex_unlock(&synth->voicelist_mutex);
92 }
93 
94 /* ---- LADSPA interface ---- */
95 
96 /*
97  * y_instantiate
98  *
99  * implements LADSPA (*instantiate)()
100  */
101 static LADSPA_Handle
y_instantiate(const LADSPA_Descriptor * descriptor,unsigned long sample_rate)102 y_instantiate(const LADSPA_Descriptor *descriptor, unsigned long sample_rate)
103 {
104     y_synth_t *synth = (y_synth_t *)calloc(1, sizeof(y_synth_t));
105     int i;
106     static float static_zero = 0.0f;
107 
108     if (!synth) return NULL;
109 
110     pthread_mutex_lock(&global_mutex);
111 
112     if (global.initialized) {
113 
114         if (sample_rate != global.sample_rate) {
115             /* all instances must share same sample rate */
116             pthread_mutex_unlock(&global_mutex);
117             free(synth);
118             return NULL;
119         }
120 
121         global.instance_count++;
122 
123     } else {
124 
125         global.sample_rate = sample_rate;
126         global.grain_envelope = create_grain_envelopes(sample_rate);
127         if (!global.grain_envelope) {
128             YDB_MESSAGE(-1, " y_instantiate: out of memory!\n");
129             free(synth);
130             return NULL;
131         }
132         if (!sampleset_init()) {
133             YDB_MESSAGE(-1, " y_instantiate: sampleset_setup() failed!\n");
134             free(synth);
135             return NULL;
136         }
137         global.instance_count = 1;
138         global.initialized = 1;
139     }
140 
141     pthread_mutex_unlock(&global_mutex);
142 
143     /* do any per-instance one-time initialization here */
144     for (i = 0; i < Y_MAX_POLYPHONY; i++) {
145         synth->voice[i] = y_voice_new(synth);
146         if (!synth->voice[i]) {
147             // YDB_MESSAGE(-1, " y_instantiate: out of memory!\n");
148             y_cleanup(synth);
149             return NULL;
150         }
151     }
152 
153     if (!new_grain_array(synth, AG_DEFAULT_GRAIN_COUNT)) {
154         YDB_MESSAGE(-1, " y_instantiate: out of memory!\n");
155         y_cleanup(synth);
156         return NULL;
157     }
158 
159     if (!sampleset_instantiate(synth)) {
160         YDB_MESSAGE(-1, " y_instantiate: out of memory!\n");
161         y_cleanup(synth);
162         return NULL;
163     }
164 
165     synth->sample_rate = (float)sample_rate;
166     synth->control_rate = (float)sample_rate / (float)Y_CONTROL_PERIOD;
167     synth->deltat = 1.0f / synth->sample_rate;
168 
169     if (!effects_setup(synth)) {
170         YDB_MESSAGE(-1, " y_instantiate: out of memory!\n");
171         y_cleanup(synth);
172         return NULL;
173     }
174 
175     synth->polyphony = Y_DEFAULT_POLYPHONY;
176     synth->voices = Y_DEFAULT_POLYPHONY;
177     synth->monophonic = 0;
178     synth->glide = 0;
179     synth->last_noteon_pitch = 0.0f;
180     pthread_mutex_init(&synth->voicelist_mutex, NULL);
181     synth->voicelist_mutex_grab_failed = 0;
182     pthread_mutex_init(&synth->patches_mutex, NULL);
183     synth->patch_count = 0;
184     synth->patches_allocated = 0;
185     synth->patches = NULL;
186     synth->pending_patch_change = -1;
187     synth->program_cancel = 1;
188     synth->project_dir = NULL;
189     synth->osc1.sampleset = NULL;
190     synth->osc2.sampleset = NULL;
191     synth->osc3.sampleset = NULL;
192     synth->osc4.sampleset = NULL;
193     synth->glfo.delay = &static_zero;
194     synth->ego.level[3] = &static_zero;
195     synth->eg1.level[3] = &static_zero;
196     synth->eg2.level[3] = &static_zero;
197     synth->eg3.level[3] = &static_zero;
198     synth->eg4.level[3] = &static_zero;
199     synth->mod[Y_MOD_ONE].value = 1.0f;
200     synth->mod[Y_MOD_ONE].next_value = 1.0f;
201     synth->mod[Y_MOD_ONE].delta = 0.0f;
202     synth->dc_block_r = 1.0f - (2.0f * 3.141593f * 20.0f/* Hz */ / (float)sample_rate); /* DC blocker cutoff */
203     y_data_friendly_patches(synth);
204     y_synth_init_controls(synth);
205 
206     return (LADSPA_Handle)synth;
207 }
208 
209 /*
210  * y_connect_port
211  *
212  * implements LADSPA (*connect_port)()
213  */
214 static void
y_connect_port(LADSPA_Handle instance,unsigned long port,LADSPA_Data * data)215 y_connect_port(LADSPA_Handle instance, unsigned long port, LADSPA_Data *data)
216 {
217     y_synth_t *synth = (y_synth_t *)instance;
218 
219     switch (port) {
220       /* -PORTS- */
221       case Y_PORT_OUTPUT_LEFT:        synth->output_left        = data;  break;
222       case Y_PORT_OUTPUT_RIGHT:       synth->output_right       = data;  break;
223 
224       case Y_PORT_OSC1_MODE:          synth->osc1.mode          = data;  break;
225       case Y_PORT_OSC1_WAVEFORM:      synth->osc1.waveform      = data;  break;
226       case Y_PORT_OSC1_PITCH:         synth->osc1.pitch         = data;  break;
227       case Y_PORT_OSC1_DETUNE:        synth->osc1.detune        = data;  break;
228       case Y_PORT_OSC1_PITCH_MOD_SRC: synth->osc1.pitch_mod_src = data;  break;
229       case Y_PORT_OSC1_PITCH_MOD_AMT: synth->osc1.pitch_mod_amt = data;  break;
230       case Y_PORT_OSC1_MPARAM1:       synth->osc1.mparam1       = data;  break;
231       case Y_PORT_OSC1_MPARAM2:       synth->osc1.mparam2       = data;  break;
232       case Y_PORT_OSC1_MMOD_SRC:      synth->osc1.mmod_src      = data;  break;
233       case Y_PORT_OSC1_MMOD_AMT:      synth->osc1.mmod_amt      = data;  break;
234       case Y_PORT_OSC1_AMP_MOD_SRC:   synth->osc1.amp_mod_src   = data;  break;
235       case Y_PORT_OSC1_AMP_MOD_AMT:   synth->osc1.amp_mod_amt   = data;  break;
236       case Y_PORT_OSC1_LEVEL_A:       synth->osc1.level_a       = data;  break;
237       case Y_PORT_OSC1_LEVEL_B:       synth->osc1.level_b       = data;  break;
238 
239       case Y_PORT_OSC2_MODE:          synth->osc2.mode          = data;  break;
240       case Y_PORT_OSC2_WAVEFORM:      synth->osc2.waveform      = data;  break;
241       case Y_PORT_OSC2_PITCH:         synth->osc2.pitch         = data;  break;
242       case Y_PORT_OSC2_DETUNE:        synth->osc2.detune        = data;  break;
243       case Y_PORT_OSC2_PITCH_MOD_SRC: synth->osc2.pitch_mod_src = data;  break;
244       case Y_PORT_OSC2_PITCH_MOD_AMT: synth->osc2.pitch_mod_amt = data;  break;
245       case Y_PORT_OSC2_MPARAM1:       synth->osc2.mparam1       = data;  break;
246       case Y_PORT_OSC2_MPARAM2:       synth->osc2.mparam2       = data;  break;
247       case Y_PORT_OSC2_MMOD_SRC:      synth->osc2.mmod_src      = data;  break;
248       case Y_PORT_OSC2_MMOD_AMT:      synth->osc2.mmod_amt      = data;  break;
249       case Y_PORT_OSC2_AMP_MOD_SRC:   synth->osc2.amp_mod_src   = data;  break;
250       case Y_PORT_OSC2_AMP_MOD_AMT:   synth->osc2.amp_mod_amt   = data;  break;
251       case Y_PORT_OSC2_LEVEL_A:       synth->osc2.level_a       = data;  break;
252       case Y_PORT_OSC2_LEVEL_B:       synth->osc2.level_b       = data;  break;
253 
254       case Y_PORT_OSC3_MODE:          synth->osc3.mode          = data;  break;
255       case Y_PORT_OSC3_WAVEFORM:      synth->osc3.waveform      = data;  break;
256       case Y_PORT_OSC3_PITCH:         synth->osc3.pitch         = data;  break;
257       case Y_PORT_OSC3_DETUNE:        synth->osc3.detune        = data;  break;
258       case Y_PORT_OSC3_PITCH_MOD_SRC: synth->osc3.pitch_mod_src = data;  break;
259       case Y_PORT_OSC3_PITCH_MOD_AMT: synth->osc3.pitch_mod_amt = data;  break;
260       case Y_PORT_OSC3_MPARAM1:       synth->osc3.mparam1       = data;  break;
261       case Y_PORT_OSC3_MPARAM2:       synth->osc3.mparam2       = data;  break;
262       case Y_PORT_OSC3_MMOD_SRC:      synth->osc3.mmod_src      = data;  break;
263       case Y_PORT_OSC3_MMOD_AMT:      synth->osc3.mmod_amt      = data;  break;
264       case Y_PORT_OSC3_AMP_MOD_SRC:   synth->osc3.amp_mod_src   = data;  break;
265       case Y_PORT_OSC3_AMP_MOD_AMT:   synth->osc3.amp_mod_amt   = data;  break;
266       case Y_PORT_OSC3_LEVEL_A:       synth->osc3.level_a       = data;  break;
267       case Y_PORT_OSC3_LEVEL_B:       synth->osc3.level_b       = data;  break;
268 
269       case Y_PORT_OSC4_MODE:          synth->osc4.mode          = data;  break;
270       case Y_PORT_OSC4_WAVEFORM:      synth->osc4.waveform      = data;  break;
271       case Y_PORT_OSC4_PITCH:         synth->osc4.pitch         = data;  break;
272       case Y_PORT_OSC4_DETUNE:        synth->osc4.detune        = data;  break;
273       case Y_PORT_OSC4_PITCH_MOD_SRC: synth->osc4.pitch_mod_src = data;  break;
274       case Y_PORT_OSC4_PITCH_MOD_AMT: synth->osc4.pitch_mod_amt = data;  break;
275       case Y_PORT_OSC4_MPARAM1:       synth->osc4.mparam1       = data;  break;
276       case Y_PORT_OSC4_MPARAM2:       synth->osc4.mparam2       = data;  break;
277       case Y_PORT_OSC4_MMOD_SRC:      synth->osc4.mmod_src      = data;  break;
278       case Y_PORT_OSC4_MMOD_AMT:      synth->osc4.mmod_amt      = data;  break;
279       case Y_PORT_OSC4_AMP_MOD_SRC:   synth->osc4.amp_mod_src   = data;  break;
280       case Y_PORT_OSC4_AMP_MOD_AMT:   synth->osc4.amp_mod_amt   = data;  break;
281       case Y_PORT_OSC4_LEVEL_A:       synth->osc4.level_a       = data;  break;
282       case Y_PORT_OSC4_LEVEL_B:       synth->osc4.level_b       = data;  break;
283 
284       case Y_PORT_VCF1_MODE:          synth->vcf1.mode          = data;  break;
285       case Y_PORT_VCF1_SOURCE:        synth->vcf1.source        = data;  break;
286       case Y_PORT_VCF1_FREQUENCY:     synth->vcf1.frequency     = data;  break;
287       case Y_PORT_VCF1_FREQ_MOD_SRC:  synth->vcf1.freq_mod_src  = data;  break;
288       case Y_PORT_VCF1_FREQ_MOD_AMT:  synth->vcf1.freq_mod_amt  = data;  break;
289       case Y_PORT_VCF1_QRES:          synth->vcf1.qres          = data;  break;
290       case Y_PORT_VCF1_MPARAM:        synth->vcf1.mparam        = data;  break;
291 
292       case Y_PORT_VCF2_MODE:          synth->vcf2.mode          = data;  break;
293       case Y_PORT_VCF2_SOURCE:        synth->vcf2.source        = data;  break;
294       case Y_PORT_VCF2_FREQUENCY:     synth->vcf2.frequency     = data;  break;
295       case Y_PORT_VCF2_FREQ_MOD_SRC:  synth->vcf2.freq_mod_src  = data;  break;
296       case Y_PORT_VCF2_FREQ_MOD_AMT:  synth->vcf2.freq_mod_amt  = data;  break;
297       case Y_PORT_VCF2_QRES:          synth->vcf2.qres          = data;  break;
298       case Y_PORT_VCF2_MPARAM:        synth->vcf2.mparam        = data;  break;
299 
300       case Y_PORT_BUSA_LEVEL:         synth->busa_level         = data;  break;
301       case Y_PORT_BUSA_PAN:           synth->busa_pan           = data;  break;
302       case Y_PORT_BUSB_LEVEL:         synth->busb_level         = data;  break;
303       case Y_PORT_BUSB_PAN:           synth->busb_pan           = data;  break;
304       case Y_PORT_VCF1_LEVEL:         synth->vcf1_level         = data;  break;
305       case Y_PORT_VCF1_PAN:           synth->vcf1_pan           = data;  break;
306       case Y_PORT_VCF2_LEVEL:         synth->vcf2_level         = data;  break;
307       case Y_PORT_VCF2_PAN:           synth->vcf2_pan           = data;  break;
308       case Y_PORT_VOLUME:             synth->volume             = data;  break;
309 
310       case Y_PORT_EFFECT_MODE:        synth->effect_mode        = data;  break;
311       case Y_PORT_EFFECT_PARAM1:      synth->effect_param1      = data;  break;
312       case Y_PORT_EFFECT_PARAM2:      synth->effect_param2      = data;  break;
313       case Y_PORT_EFFECT_PARAM3:      synth->effect_param3      = data;  break;
314       case Y_PORT_EFFECT_PARAM4:      synth->effect_param4      = data;  break;
315       case Y_PORT_EFFECT_PARAM5:      synth->effect_param5      = data;  break;
316       case Y_PORT_EFFECT_PARAM6:      synth->effect_param6      = data;  break;
317       case Y_PORT_EFFECT_MIX:         synth->effect_mix         = data;  break;
318 
319       case Y_PORT_GLIDE_TIME:         synth->glide_time         = data;  break;
320       case Y_PORT_BEND_RANGE:         synth->bend_range         = data;  break;
321 
322       case Y_PORT_GLFO_FREQUENCY:     synth->glfo.frequency     = data;  break;
323       case Y_PORT_GLFO_WAVEFORM:      synth->glfo.waveform      = data;  break;
324       /* synth->glfo.delay always points to a 0.0f */
325       case Y_PORT_GLFO_AMP_MOD_SRC:   synth->glfo.amp_mod_src   = data;  break;
326       case Y_PORT_GLFO_AMP_MOD_AMT:   synth->glfo.amp_mod_amt   = data;  break;
327 
328       case Y_PORT_VLFO_FREQUENCY:     synth->vlfo.frequency     = data;  break;
329       case Y_PORT_VLFO_WAVEFORM:      synth->vlfo.waveform      = data;  break;
330       case Y_PORT_VLFO_DELAY:         synth->vlfo.delay         = data;  break;
331       case Y_PORT_VLFO_AMP_MOD_SRC:   synth->vlfo.amp_mod_src   = data;  break;
332       case Y_PORT_VLFO_AMP_MOD_AMT:   synth->vlfo.amp_mod_amt   = data;  break;
333 
334       case Y_PORT_MLFO_FREQUENCY:     synth->mlfo.frequency     = data;  break;
335       case Y_PORT_MLFO_WAVEFORM:      synth->mlfo.waveform      = data;  break;
336       case Y_PORT_MLFO_DELAY:         synth->mlfo.delay         = data;  break;
337       case Y_PORT_MLFO_AMP_MOD_SRC:   synth->mlfo.amp_mod_src   = data;  break;
338       case Y_PORT_MLFO_AMP_MOD_AMT:   synth->mlfo.amp_mod_amt   = data;  break;
339       case Y_PORT_MLFO_PHASE_SPREAD:  synth->mlfo_phase_spread  = data;  break;
340       case Y_PORT_MLFO_RANDOM_FREQ:   synth->mlfo_random_freq   = data;  break;
341 
342       case Y_PORT_EGO_MODE:           synth->ego.mode           = data;  break;
343       case Y_PORT_EGO_SHAPE1:         synth->ego.shape[0]       = data;  break;
344       case Y_PORT_EGO_TIME1:          synth->ego.time[0]        = data;  break;
345       case Y_PORT_EGO_LEVEL1:         synth->ego.level[0]       = data;  break;
346       case Y_PORT_EGO_SHAPE2:         synth->ego.shape[1]       = data;  break;
347       case Y_PORT_EGO_TIME2:          synth->ego.time[1]        = data;  break;
348       case Y_PORT_EGO_LEVEL2:         synth->ego.level[1]       = data;  break;
349       case Y_PORT_EGO_SHAPE3:         synth->ego.shape[2]       = data;  break;
350       case Y_PORT_EGO_TIME3:          synth->ego.time[2]        = data;  break;
351       case Y_PORT_EGO_LEVEL3:         synth->ego.level[2]       = data;  break;
352       case Y_PORT_EGO_SHAPE4:         synth->ego.shape[3]       = data;  break;
353       case Y_PORT_EGO_TIME4:          synth->ego.time[3]        = data;  break;
354       /* synth->ego.level[3] always points to a 0.0f */
355       case Y_PORT_EGO_VEL_LEVEL_SENS: synth->ego.vel_level_sens = data;  break;
356       case Y_PORT_EGO_VEL_TIME_SCALE: synth->ego.vel_time_scale = data;  break;
357       case Y_PORT_EGO_KBD_TIME_SCALE: synth->ego.kbd_time_scale = data;  break;
358       case Y_PORT_EGO_AMP_MOD_SRC:    synth->ego.amp_mod_src    = data;  break;
359       case Y_PORT_EGO_AMP_MOD_AMT:    synth->ego.amp_mod_amt    = data;  break;
360 
361       case Y_PORT_EG1_MODE:           synth->eg1.mode           = data;  break;
362       case Y_PORT_EG1_SHAPE1:         synth->eg1.shape[0]       = data;  break;
363       case Y_PORT_EG1_TIME1:          synth->eg1.time[0]        = data;  break;
364       case Y_PORT_EG1_LEVEL1:         synth->eg1.level[0]       = data;  break;
365       case Y_PORT_EG1_SHAPE2:         synth->eg1.shape[1]       = data;  break;
366       case Y_PORT_EG1_TIME2:          synth->eg1.time[1]        = data;  break;
367       case Y_PORT_EG1_LEVEL2:         synth->eg1.level[1]       = data;  break;
368       case Y_PORT_EG1_SHAPE3:         synth->eg1.shape[2]       = data;  break;
369       case Y_PORT_EG1_TIME3:          synth->eg1.time[2]        = data;  break;
370       case Y_PORT_EG1_LEVEL3:         synth->eg1.level[2]       = data;  break;
371       case Y_PORT_EG1_SHAPE4:         synth->eg1.shape[3]       = data;  break;
372       case Y_PORT_EG1_TIME4:          synth->eg1.time[3]        = data;  break;
373       /* synth->eg1.level[3] always points to a 0.0f */
374       case Y_PORT_EG1_VEL_LEVEL_SENS: synth->eg1.vel_level_sens = data;  break;
375       case Y_PORT_EG1_VEL_TIME_SCALE: synth->eg1.vel_time_scale = data;  break;
376       case Y_PORT_EG1_KBD_TIME_SCALE: synth->eg1.kbd_time_scale = data;  break;
377       case Y_PORT_EG1_AMP_MOD_SRC:    synth->eg1.amp_mod_src    = data;  break;
378       case Y_PORT_EG1_AMP_MOD_AMT:    synth->eg1.amp_mod_amt    = data;  break;
379 
380       case Y_PORT_EG2_MODE:           synth->eg2.mode           = data;  break;
381       case Y_PORT_EG2_SHAPE1:         synth->eg2.shape[0]       = data;  break;
382       case Y_PORT_EG2_TIME1:          synth->eg2.time[0]        = data;  break;
383       case Y_PORT_EG2_LEVEL1:         synth->eg2.level[0]       = data;  break;
384       case Y_PORT_EG2_SHAPE2:         synth->eg2.shape[1]       = data;  break;
385       case Y_PORT_EG2_TIME2:          synth->eg2.time[1]        = data;  break;
386       case Y_PORT_EG2_LEVEL2:         synth->eg2.level[1]       = data;  break;
387       case Y_PORT_EG2_SHAPE3:         synth->eg2.shape[2]       = data;  break;
388       case Y_PORT_EG2_TIME3:          synth->eg2.time[2]        = data;  break;
389       case Y_PORT_EG2_LEVEL3:         synth->eg2.level[2]       = data;  break;
390       case Y_PORT_EG2_SHAPE4:         synth->eg2.shape[3]       = data;  break;
391       case Y_PORT_EG2_TIME4:          synth->eg2.time[3]        = data;  break;
392       /* synth->eg2.level[3] always points to a 0.0f */
393       case Y_PORT_EG2_VEL_LEVEL_SENS: synth->eg2.vel_level_sens = data;  break;
394       case Y_PORT_EG2_VEL_TIME_SCALE: synth->eg2.vel_time_scale = data;  break;
395       case Y_PORT_EG2_KBD_TIME_SCALE: synth->eg2.kbd_time_scale = data;  break;
396       case Y_PORT_EG2_AMP_MOD_SRC:    synth->eg2.amp_mod_src    = data;  break;
397       case Y_PORT_EG2_AMP_MOD_AMT:    synth->eg2.amp_mod_amt    = data;  break;
398 
399       case Y_PORT_EG3_MODE:           synth->eg3.mode           = data;  break;
400       case Y_PORT_EG3_SHAPE1:         synth->eg3.shape[0]       = data;  break;
401       case Y_PORT_EG3_TIME1:          synth->eg3.time[0]        = data;  break;
402       case Y_PORT_EG3_LEVEL1:         synth->eg3.level[0]       = data;  break;
403       case Y_PORT_EG3_SHAPE2:         synth->eg3.shape[1]       = data;  break;
404       case Y_PORT_EG3_TIME2:          synth->eg3.time[1]        = data;  break;
405       case Y_PORT_EG3_LEVEL2:         synth->eg3.level[1]       = data;  break;
406       case Y_PORT_EG3_SHAPE3:         synth->eg3.shape[2]       = data;  break;
407       case Y_PORT_EG3_TIME3:          synth->eg3.time[2]        = data;  break;
408       case Y_PORT_EG3_LEVEL3:         synth->eg3.level[2]       = data;  break;
409       case Y_PORT_EG3_SHAPE4:         synth->eg3.shape[3]       = data;  break;
410       case Y_PORT_EG3_TIME4:          synth->eg3.time[3]        = data;  break;
411       /* synth->eg3.level[3] always points to a 0.0f */
412       case Y_PORT_EG3_VEL_LEVEL_SENS: synth->eg3.vel_level_sens = data;  break;
413       case Y_PORT_EG3_VEL_TIME_SCALE: synth->eg3.vel_time_scale = data;  break;
414       case Y_PORT_EG3_KBD_TIME_SCALE: synth->eg3.kbd_time_scale = data;  break;
415       case Y_PORT_EG3_AMP_MOD_SRC:    synth->eg3.amp_mod_src    = data;  break;
416       case Y_PORT_EG3_AMP_MOD_AMT:    synth->eg3.amp_mod_amt    = data;  break;
417 
418       case Y_PORT_EG4_MODE:           synth->eg4.mode           = data;  break;
419       case Y_PORT_EG4_SHAPE1:         synth->eg4.shape[0]       = data;  break;
420       case Y_PORT_EG4_TIME1:          synth->eg4.time[0]        = data;  break;
421       case Y_PORT_EG4_LEVEL1:         synth->eg4.level[0]       = data;  break;
422       case Y_PORT_EG4_SHAPE2:         synth->eg4.shape[1]       = data;  break;
423       case Y_PORT_EG4_TIME2:          synth->eg4.time[1]        = data;  break;
424       case Y_PORT_EG4_LEVEL2:         synth->eg4.level[1]       = data;  break;
425       case Y_PORT_EG4_SHAPE3:         synth->eg4.shape[2]       = data;  break;
426       case Y_PORT_EG4_TIME3:          synth->eg4.time[2]        = data;  break;
427       case Y_PORT_EG4_LEVEL3:         synth->eg4.level[2]       = data;  break;
428       case Y_PORT_EG4_SHAPE4:         synth->eg4.shape[3]       = data;  break;
429       case Y_PORT_EG4_TIME4:          synth->eg4.time[3]        = data;  break;
430       /* synth->eg4.level[3] always points to a 0.0f */
431       case Y_PORT_EG4_VEL_LEVEL_SENS: synth->eg4.vel_level_sens = data;  break;
432       case Y_PORT_EG4_VEL_TIME_SCALE: synth->eg4.vel_time_scale = data;  break;
433       case Y_PORT_EG4_KBD_TIME_SCALE: synth->eg4.kbd_time_scale = data;  break;
434       case Y_PORT_EG4_AMP_MOD_SRC:    synth->eg4.amp_mod_src    = data;  break;
435       case Y_PORT_EG4_AMP_MOD_AMT:    synth->eg4.amp_mod_amt    = data;  break;
436 
437       case Y_PORT_MODMIX_BIAS:        synth->modmix_bias        = data;  break;
438       case Y_PORT_MODMIX_MOD1_SRC:    synth->modmix_mod1_src    = data;  break;
439       case Y_PORT_MODMIX_MOD1_AMT:    synth->modmix_mod1_amt    = data;  break;
440       case Y_PORT_MODMIX_MOD2_SRC:    synth->modmix_mod2_src    = data;  break;
441       case Y_PORT_MODMIX_MOD2_AMT:    synth->modmix_mod2_amt    = data;  break;
442 
443       case Y_PORT_TUNING:             synth->tuning             = data;  break;
444 
445       default:
446         break;
447     }
448 }
449 
450 /*
451  * y_activate
452  *
453  * implements LADSPA (*activate)()
454  */
455 static void
y_activate(LADSPA_Handle instance)456 y_activate(LADSPA_Handle instance)
457 {
458     y_synth_t *synth = (y_synth_t *)instance;
459 
460     synth->control_remains = 0;
461     synth->note_id = 0;
462     y_voice_setup_lfo(synth, &synth->glfo, &synth->glfo_vlfo, 0.0f, 0.0f,
463                       synth->mod, &synth->mod[Y_GLOBAL_MOD_GLFO]);
464     y_synth_all_voices_off(synth);
465 }
466 
467 /*
468  * y_ladspa_run_wrapper
469  *
470  * implements LADSPA (*run)() by calling y_run_synth() with no events
471  */
472 static void
y_ladspa_run_wrapper(LADSPA_Handle instance,unsigned long sample_count)473 y_ladspa_run_wrapper(LADSPA_Handle instance, unsigned long sample_count)
474 {
475     y_run_synth(instance, sample_count, NULL, 0);
476 }
477 
478 // optional:
479 //  void (*run_adding)(LADSPA_Handle Instance,
480 //                     unsigned long SampleCount);
481 //  void (*set_run_adding_gain)(LADSPA_Handle Instance,
482 //                              LADSPA_Data   Gain);
483 
484 /*
485  * y_deactivate
486  *
487  * implements LADSPA (*deactivate)()
488  */
489 void
y_deactivate(LADSPA_Handle instance)490 y_deactivate(LADSPA_Handle instance)
491 {
492     y_synth_t *synth = (y_synth_t *)instance;
493 
494     y_synth_all_voices_off(synth);  /* stop all sounds immediately */
495 }
496 
497 /*
498  * y_cleanup
499  *
500  * implements LADSPA (*cleanup)()
501  */
502 static void
y_cleanup(LADSPA_Handle instance)503 y_cleanup(LADSPA_Handle instance)
504 {
505     y_synth_t *synth = (y_synth_t *)instance;
506     int i;
507 
508     for (i = 0; i < Y_MAX_POLYPHONY; i++)
509         if (synth->voice[i]) free(synth->voice[i]);
510     if (synth->patches) free(synth->patches);
511     if (synth->grains) free(synth->grains);
512     if (synth->project_dir) free(synth->project_dir);
513     sampleset_cleanup(synth);
514     effects_cleanup(synth);
515     free(synth);
516     pthread_mutex_lock(&global_mutex);
517     if (--global.instance_count == 0) {
518         sampleset_fini();
519         free_grain_envelopes(global.grain_envelope);
520         global.initialized = 0;
521     }
522     pthread_mutex_unlock(&global_mutex);
523 }
524 
525 /* ---- DSSI interface ---- */
526 
527 /*
528  * dssi_configure_message
529  */
530 char *
dssi_configure_message(const char * fmt,...)531 dssi_configure_message(const char *fmt, ...)
532 {
533     va_list args;
534     char buffer[256];
535 
536     va_start(args, fmt);
537     vsnprintf(buffer, 256, fmt, args);
538     va_end(args);
539     return strdup(buffer);
540 }
541 
542 /*
543  * y_configure
544  *
545  * implements DSSI (*configure)()
546  */
547 char *
y_configure(LADSPA_Handle instance,const char * key,const char * value)548 y_configure(LADSPA_Handle instance, const char *key, const char *value)
549 {
550     YDB_MESSAGE(YDB_DSSI, " y_configure called with '%s' and '%s'\n", key, value);
551 
552     if (!strcmp(key, "load")) {
553 
554         return y_synth_handle_load((y_synth_t *)instance, value);
555 
556     } else if (!strcmp(key, "polyphony")) {
557 
558         return y_synth_handle_polyphony((y_synth_t *)instance, value);
559 
560     } else if (!strcmp(key, "monophonic")) {
561 
562         return y_synth_handle_monophonic((y_synth_t *)instance, value);
563 
564     } else if (!strcmp(key, "glide")) {
565 
566         return y_synth_handle_glide((y_synth_t *)instance, value);
567 
568     } else if (!strcmp(key, "program_cancel")) {
569 
570         return y_synth_handle_program_cancel((y_synth_t *)instance, value);
571 
572     } else if (!strcmp(key, DSSI_PROJECT_DIRECTORY_KEY)) {
573 
574         return y_synth_handle_project_dir((y_synth_t *)instance, value);
575 
576     }
577     return strdup("error: unrecognized configure key");
578 }
579 
580 /*
581  * y_get_program
582  *
583  * implements DSSI (*get_program)()
584  */
585 const DSSI_Program_Descriptor *
y_get_program(LADSPA_Handle instance,unsigned long index)586 y_get_program(LADSPA_Handle instance, unsigned long index)
587 {
588     y_synth_t *synth = (y_synth_t *)instance;
589     static DSSI_Program_Descriptor pd;
590 
591     YDB_MESSAGE(YDB_DSSI, " y_get_program called with %lu\n", index);
592 
593     if (index < synth->patch_count) {
594         y_synth_set_program_descriptor(synth, &pd, index);
595         pd.Bank = index / 128;
596         pd.Program = index % 128;
597         return &pd;
598     }
599     return NULL;
600 }
601 
602 /*
603  * y_select_program
604  *
605  * implements DSSI (*select_program)()
606  */
607 void
y_select_program(LADSPA_Handle handle,unsigned long bank,unsigned long program)608 y_select_program(LADSPA_Handle handle, unsigned long bank,
609                       unsigned long program)
610 {
611     y_synth_t *synth = (y_synth_t *)handle;
612 
613     YDB_MESSAGE(YDB_DSSI, " y_select_program called with %lu and %lu\n", bank, program);
614 
615     /* ignore invalid program requests */
616     if (program >= 128)
617         return;
618     program = bank * 128 + program;
619     if (program >= synth->patch_count)
620         return;
621 
622     /* Attempt the patch mutex, return if lock fails. */
623     if (pthread_mutex_trylock(&synth->patches_mutex)) {
624         synth->pending_patch_change = program;
625         return;
626     }
627 
628     y_synth_select_patch(synth, program);
629 
630     pthread_mutex_unlock(&synth->patches_mutex);
631 }
632 
633 /*
634  * dssp_handle_pending_patch_change
635  */
636 static inline void
dssp_handle_pending_patch_change(y_synth_t * synth)637 dssp_handle_pending_patch_change(y_synth_t *synth)
638 {
639     /* Attempt the patch mutex, return if lock fails. */
640     if (pthread_mutex_trylock(&synth->patches_mutex))
641         return;
642 
643     if (synth->pending_patch_change < synth->patch_count)
644         y_synth_select_patch(synth, synth->pending_patch_change);
645     synth->pending_patch_change = -1;
646 
647     pthread_mutex_unlock(&synth->patches_mutex);
648 }
649 
650 /*
651  * y_get_midi_controller
652  *
653  * implements DSSI (*get_midi_controller_for_port)()
654  */
655 int
y_get_midi_controller(LADSPA_Handle instance,unsigned long port)656 y_get_midi_controller(LADSPA_Handle instance, unsigned long port)
657 {
658     YDB_MESSAGE(YDB_DSSI, " y_get_midi_controller called for port %lu\n", port);
659     switch (port) {
660       case Y_PORT_GLIDE_TIME:
661         return DSSI_CC(MIDI_CTL_MSB_PORTAMENTO_TIME);
662 #ifdef USE_GARETTS_CONTROLLER_ASSIGNMENTS
663       /* Ideally, MIDI controller assignments will someday be run-time
664        * configurable.  Until then, you have to roll your own.  Here's
665        * a setup that Garett Shulman uses with a Doepfer Pocket Fader
666        * to sort-of emulate a Juno 106: */
667       case Y_PORT_OSC1_LEVEL_A:
668         return DSSI_CC(0x30);  /* General Purpose Controller #1 */
669       case Y_PORT_OSC2_LEVEL_A:
670         return DSSI_CC(0x32);  /* General Purpose Controller #3 */
671       case Y_PORT_OSC2_MPARAM2:
672         return DSSI_CC(0x33);  /* General Purpose Controller #4 */
673       case Y_PORT_OSC2_MMOD_AMT:
674         return DSSI_CC(0x34);  /* Undefined */
675       case Y_PORT_OSC3_LEVEL_A:
676         return DSSI_CC(0x31);  /* General Purpose Controller #2 */
677       /* case amp mod source amount for all OSC:
678        *   return DSSI_CC(0x35);
679        * case frequency for all OSC
680        *   return DSSI_CC(0x36); */
681       case Y_PORT_VCF1_FREQUENCY:
682         return DSSI_CC(0x37);
683       /* case Y_PORT_VCF1_FREQ_MOD_AMT:
684        *   return DSSI_CC(0x37); */
685       case Y_PORT_VCF1_QRES:
686         return DSSI_CC(0x38);
687       /* case Y_PORT_VCF1_MPARAM:
688        *   return DSSI_CC(0x39); */
689       case Y_PORT_GLFO_FREQUENCY:
690         return DSSI_CC(0x3b);
691       case Y_PORT_EG1_TIME1:
692         return DSSI_CC(0x3c);
693       case Y_PORT_EG1_TIME3:
694         return DSSI_CC(0x3d);
695       case Y_PORT_EG1_LEVEL3:
696         return DSSI_CC(0x3e);
697       case Y_PORT_EG1_TIME4:
698         return DSSI_CC(0x3f);
699       case Y_PORT_MODMIX_MOD1_AMT:
700         return DSSI_CC(0x39);
701       case Y_PORT_MODMIX_MOD2_AMT:
702         return DSSI_CC(0x3a);
703 #endif
704       default:
705         break;
706     }
707 
708     return DSSI_NONE;
709 }
710 
711 /*
712  * y_handle_event
713  */
714 static inline void
y_handle_event(y_synth_t * synth,snd_seq_event_t * event)715 y_handle_event(y_synth_t *synth, snd_seq_event_t *event)
716 {
717     YDB_MESSAGE(YDB_DSSI, " y_handle_event called with event type %d\n", event->type);
718 
719     switch (event->type) {
720       case SND_SEQ_EVENT_NOTEOFF:
721         y_synth_note_off(synth, event->data.note.note, event->data.note.velocity);
722         break;
723       case SND_SEQ_EVENT_NOTEON:
724         if (event->data.note.velocity > 0)
725            y_synth_note_on(synth, event->data.note.note, event->data.note.velocity);
726         else
727            y_synth_note_off(synth, event->data.note.note, 64); /* shouldn't happen, but... */
728         break;
729       case SND_SEQ_EVENT_KEYPRESS:
730         y_synth_key_pressure(synth, event->data.note.note, event->data.note.velocity);
731         break;
732       case SND_SEQ_EVENT_CONTROLLER:
733         y_synth_control_change(synth, event->data.control.param, event->data.control.value);
734         break;
735       case SND_SEQ_EVENT_CHANPRESS:
736         y_synth_channel_pressure(synth, event->data.control.value);
737         break;
738       case SND_SEQ_EVENT_PITCHBEND:
739         y_synth_pitch_bend(synth, event->data.control.value);
740         break;
741       /* SND_SEQ_EVENT_PGMCHANGE - shouldn't happen */
742       /* SND_SEQ_EVENT_SYSEX - shouldn't happen */
743       /* SND_SEQ_EVENT_CONTROL14? */
744       /* SND_SEQ_EVENT_NONREGPARAM? */
745       /* SND_SEQ_EVENT_REGPARAM? */
746       default:
747         break;
748     }
749 }
750 
751 /*
752  * y_run_synth
753  *
754  * implements DSSI (*run_synth)()
755  */
756 static void
y_run_synth(LADSPA_Handle instance,unsigned long sample_count,snd_seq_event_t * events,unsigned long event_count)757 y_run_synth(LADSPA_Handle instance, unsigned long sample_count,
758                  snd_seq_event_t *events, unsigned long event_count)
759 {
760     y_synth_t *synth = (y_synth_t *)instance;
761     unsigned long samples_done = 0;
762     unsigned long event_index = 0;
763     unsigned long burst_size;
764 
765     /* attempt the mutex, return only silence if lock fails. */
766     if (dssp_voicelist_mutex_trylock(synth)) {
767         memset(synth->output_left,  0, sizeof(LADSPA_Data) * sample_count);
768         memset(synth->output_right, 0, sizeof(LADSPA_Data) * sample_count);
769         return;
770     }
771 
772     if (synth->pending_patch_change > -1)
773         dssp_handle_pending_patch_change(synth);
774 
775     while (samples_done < sample_count) {
776         if (!synth->control_remains)
777             synth->control_remains = Y_CONTROL_PERIOD;
778 
779         /* process any ready events */
780 	while (event_index < event_count
781 	       && samples_done == events[event_index].time.tick) {
782             y_handle_event(synth, &events[event_index]);
783             event_index++;
784         }
785 
786         /* calculate the sample count (burst_size) for the next
787          * y_voice_render() call to be the smallest of:
788          * - control calculation quantization size (Y_CONTROL_PERIOD, in
789          *     samples)
790          * - the number of samples remaining in an already-begun control cycle
791          *     (synth->control_remains)
792          * - the number of samples until the next event is ready
793          * - the number of samples left in this run
794          */
795         burst_size = Y_CONTROL_PERIOD;
796         if (synth->control_remains < burst_size) {
797             /* we're still in the middle of a control cycle, so reduce the
798              * burst size to end when the cycle ends */
799             burst_size = synth->control_remains;
800         }
801         if (event_index < event_count
802             && events[event_index].time.tick - samples_done < burst_size) {
803             /* reduce burst size to end when next event is ready */
804             burst_size = events[event_index].time.tick - samples_done;
805         }
806         if (sample_count - samples_done < burst_size) {
807             /* reduce burst size to end at end of this run */
808             burst_size = sample_count - samples_done;
809         }
810 
811         /* render the burst */
812         y_synth_render_voices(synth, synth->output_left + samples_done,
813                                    synth->output_right + samples_done, burst_size,
814                                    (burst_size == synth->control_remains));
815         samples_done += burst_size;
816         synth->control_remains -= burst_size;
817     }
818 #if defined(Y_DEBUG) && (Y_DEBUG & YDB_AUDIO)
819 *synth->output_left  += 0.10f; /* add a 'buzz' to output so there's something audible even when quiescent */
820 *synth->output_right += 0.10f;
821 #endif /* defined(Y_DEBUG) && (Y_DEBUG & YDB_AUDIO) */
822 
823     dssp_voicelist_mutex_unlock(synth);
824 }
825 
826 // optional:
827 //    void (*run_synth_adding)(LADSPA_Handle    Instance,
828 //                             unsigned long    SampleCount,
829 //                             snd_seq_event_t *Events,
830 //                             unsigned long    EventCount);
831 
832 /* ---- export ---- */
833 
ladspa_descriptor(unsigned long index)834 const LADSPA_Descriptor *ladspa_descriptor(unsigned long index)
835 {
836     switch (index) {
837     case 0:
838         return y_LADSPA_descriptor;
839     default:
840         return NULL;
841     }
842 }
843 
dssi_descriptor(unsigned long index)844 const DSSI_Descriptor *dssi_descriptor(unsigned long index)
845 {
846     switch (index) {
847     case 0:
848         return y_DSSI_descriptor;
849     default:
850         return NULL;
851     }
852 }
853 
854 #ifdef __GNUC__
init()855 __attribute__((constructor)) void init()
856 #else
857 void _init()
858 #endif
859 {
860     int i;
861     char **port_names;
862     LADSPA_PortDescriptor *port_descriptors;
863     LADSPA_PortRangeHint *port_range_hints;
864 
865     Y_DEBUG_INIT("whysynth.so");
866 
867     pthread_mutex_init(&global_mutex, NULL);
868     global.initialized = 0;
869     y_init_tables();
870     wave_tables_set_count();
871 
872     y_LADSPA_descriptor =
873         (LADSPA_Descriptor *) malloc(sizeof(LADSPA_Descriptor));
874     if (y_LADSPA_descriptor) {
875         y_LADSPA_descriptor->UniqueID = 2187;
876         y_LADSPA_descriptor->Label = "WhySynth";
877         y_LADSPA_descriptor->Properties = 0;
878 #ifdef HAVE_CONFIG_H
879         y_LADSPA_descriptor->Name = "WhySynth " VERSION " DSSI plugin";
880 #else
881         y_LADSPA_descriptor->Name = "WhySynth DSSI plugin";
882 #endif
883         y_LADSPA_descriptor->Maker = "Sean Bolton <musound AT jps DOT net>";
884         y_LADSPA_descriptor->Copyright = "GNU General Public License version 2 or later";
885         y_LADSPA_descriptor->PortCount = Y_PORTS_COUNT;
886 
887         port_descriptors = (LADSPA_PortDescriptor *)
888                                 calloc(y_LADSPA_descriptor->PortCount, sizeof
889                                                 (LADSPA_PortDescriptor));
890         y_LADSPA_descriptor->PortDescriptors =
891             (const LADSPA_PortDescriptor *) port_descriptors;
892 
893         port_range_hints = (LADSPA_PortRangeHint *)
894                                 calloc(y_LADSPA_descriptor->PortCount, sizeof
895                                                 (LADSPA_PortRangeHint));
896         y_LADSPA_descriptor->PortRangeHints =
897             (const LADSPA_PortRangeHint *) port_range_hints;
898 
899         port_names = (char **) calloc(y_LADSPA_descriptor->PortCount, sizeof(char *));
900         y_LADSPA_descriptor->PortNames = (const char **) port_names;
901 
902         for (i = 0; i < Y_PORTS_COUNT; i++) {
903             port_descriptors[i] = y_port_description[i].port_descriptor;
904             port_names[i]       = y_port_description[i].name;
905             port_range_hints[i].HintDescriptor = y_port_description[i].hint_descriptor;
906             port_range_hints[i].LowerBound     = y_port_description[i].lower_bound;
907             if (y_port_description[i].type == Y_PORT_TYPE_COMBO &&
908                 (y_port_description[i].subtype == Y_COMBO_TYPE_OSC_WAVEFORM ||
909                  y_port_description[i].subtype == Y_COMBO_TYPE_WT_WAVEFORM)) {
910                 port_range_hints[i].UpperBound = (float)wavetables_count - 1;
911             } else {
912                 port_range_hints[i].UpperBound = y_port_description[i].upper_bound;
913             }
914         }
915 
916         y_LADSPA_descriptor->instantiate = y_instantiate;
917         y_LADSPA_descriptor->connect_port = y_connect_port;
918         y_LADSPA_descriptor->activate = y_activate;
919         y_LADSPA_descriptor->run = y_ladspa_run_wrapper;
920         y_LADSPA_descriptor->run_adding = NULL;
921         y_LADSPA_descriptor->set_run_adding_gain = NULL;
922         y_LADSPA_descriptor->deactivate = y_deactivate;
923         y_LADSPA_descriptor->cleanup = y_cleanup;
924     }
925 
926     y_DSSI_descriptor = (DSSI_Descriptor *) malloc(sizeof(DSSI_Descriptor));
927     if (y_DSSI_descriptor) {
928         y_DSSI_descriptor->DSSI_API_Version = 1;
929         y_DSSI_descriptor->LADSPA_Plugin = y_LADSPA_descriptor;
930         y_DSSI_descriptor->configure = y_configure;
931         y_DSSI_descriptor->get_program = y_get_program;
932         y_DSSI_descriptor->select_program = y_select_program;
933         y_DSSI_descriptor->get_midi_controller_for_port = y_get_midi_controller;
934         y_DSSI_descriptor->run_synth = y_run_synth;
935         y_DSSI_descriptor->run_synth_adding = NULL;
936         y_DSSI_descriptor->run_multiple_synths = NULL;
937         y_DSSI_descriptor->run_multiple_synths_adding = NULL;
938     }
939 }
940 
941 #ifdef __GNUC__
fini()942 __attribute__((destructor)) void fini()
943 #else
944 void _fini()
945 #endif
946 {
947     if (y_LADSPA_descriptor) {
948         free((LADSPA_PortDescriptor *) y_LADSPA_descriptor->PortDescriptors);
949         free((char **) y_LADSPA_descriptor->PortNames);
950         free((LADSPA_PortRangeHint *) y_LADSPA_descriptor->PortRangeHints);
951         free(y_LADSPA_descriptor);
952     }
953     if (y_DSSI_descriptor) {
954         free(y_DSSI_descriptor);
955     }
956 }
957 
958