1 /*
2  * libInstPatch
3  * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; version 2.1
8  * of the License only.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA or on the web at http://www.gnu.org.
19  */
20 #include <stdio.h>
21 #include <string.h>
22 #include <glib.h>
23 #include <glib-object.h>
24 
25 #include "IpatchSF2VoiceCache_DLS.h"
26 #include "IpatchConverter.h"
27 #include "IpatchConverterSF2VoiceCache.h"
28 #include "IpatchConverter_priv.h"
29 
30 #include "IpatchDLS2Inst.h"
31 #include "IpatchDLS2Region.h"
32 #include "IpatchDLS2Sample.h"
33 #include "IpatchSF2VoiceCache.h"
34 #include "IpatchSample.h"
35 
36 /**
37  * _ipatch_sf2_voice_cache_init_DLS: (skip)
38  */
39 void
_ipatch_sf2_voice_cache_init_DLS(void)40 _ipatch_sf2_voice_cache_init_DLS(void)
41 {
42     g_type_class_ref(IPATCH_TYPE_CONVERTER_DLS2_INST_TO_SF2_VOICE_CACHE);
43     g_type_class_ref(IPATCH_TYPE_CONVERTER_DLS2_REGION_TO_SF2_VOICE_CACHE);
44     g_type_class_ref(IPATCH_TYPE_CONVERTER_DLS2_SAMPLE_TO_SF2_VOICE_CACHE);
45 
46     ipatch_register_converter_map
47     (IPATCH_TYPE_CONVERTER_DLS2_INST_TO_SF2_VOICE_CACHE, 0, 0,
48      IPATCH_TYPE_DLS2_INST, 0, 1, IPATCH_TYPE_SF2_VOICE_CACHE, 0, 1);
49     ipatch_register_converter_map
50     (IPATCH_TYPE_CONVERTER_DLS2_REGION_TO_SF2_VOICE_CACHE, 0, 0,
51      IPATCH_TYPE_DLS2_REGION, 0, 1, IPATCH_TYPE_SF2_VOICE_CACHE, 0, 1);
52     ipatch_register_converter_map
53     (IPATCH_TYPE_CONVERTER_DLS2_SAMPLE_TO_SF2_VOICE_CACHE, 0, 0,
54      IPATCH_TYPE_DLS2_SAMPLE, 0, 1, IPATCH_TYPE_SF2_VOICE_CACHE, 0, 1);
55 }
56 
57 static gboolean
_dls2_inst_to_sf2_voice_cache_convert(IpatchConverter * converter,GError ** err)58 _dls2_inst_to_sf2_voice_cache_convert(IpatchConverter *converter, GError **err)
59 {
60     IpatchDLS2Inst *inst;
61     IpatchSF2VoiceCache *cache;
62     IpatchSF2Voice *voice;
63     IpatchDLS2Region *region;
64     IpatchDLS2Sample *sample;
65     IpatchDLS2SampleInfo *sample_info;
66     IpatchItem *solo_item;
67     GObject *obj;
68     GSList *p;
69     int looptype;
70 
71     obj = IPATCH_CONVERTER_INPUT(converter);
72     cache = IPATCH_SF2_VOICE_CACHE(IPATCH_CONVERTER_OUTPUT(converter));
73     solo_item = ((IpatchConverterSF2VoiceCache *)converter)->solo_item;
74 
75     /* check if its an instrument or a region */
76     if(IPATCH_IS_DLS2_REGION(obj))        /* ++ ref parent instrument */
77     {
78         inst = IPATCH_DLS2_INST(ipatch_item_get_parent(IPATCH_ITEM(obj)));
79     }
80     else
81     {
82         inst = IPATCH_DLS2_INST(obj);
83     }
84 
85     ipatch_sf2_voice_cache_declare_item(cache, (GObject *)inst);
86 
87     IPATCH_ITEM_RLOCK(inst);	/* ++ LOCK instrument */
88 
89     for(p = inst->regions; p; p = p->next)
90     {
91         region = (IpatchDLS2Region *)(p->data);
92 
93         if(solo_item && (IpatchItem *)region != solo_item)
94         {
95             continue;
96         }
97 
98         ipatch_sf2_voice_cache_declare_item(cache, (GObject *)region);
99 
100         voice = ipatch_sf2_voice_cache_add_voice(cache);
101 
102         IPATCH_ITEM_RLOCK(region);  /* ++ LOCK region */
103 
104         /* convert DLS parameters to SoundFont generator array and modulators */
105 //      ipatch_dls2_region_load_sf2_gen_mods (region, &voice->gen_array,
106 //                                            &voice->mod_list);
107 
108         voice->mod_list = ipatch_sf2_mod_list_override(cache->default_mods,
109                           cache->override_mods, TRUE);
110 
111         /* set MIDI note and velocity ranges */
112         ipatch_sf2_voice_cache_set_voice_range(cache, voice, 0,
113                                                region->note_range_low, region->note_range_high);
114         ipatch_sf2_voice_cache_set_voice_range(cache, voice, 1,
115                                                region->velocity_range_low, region->velocity_range_high);
116 
117         sample = (IpatchDLS2Sample *)(region->sample);
118         ipatch_sf2_voice_cache_declare_item(cache, (GObject *)sample);
119 
120         ipatch_sf2_voice_set_sample_data(voice, sample->sample_data);
121 
122         voice->rate = sample->rate;
123 
124         if(region->sample_info)
125         {
126             sample_info = region->sample_info;
127         }
128         else
129         {
130             sample_info = sample->sample_info;
131         }
132 
133         if(sample_info)
134         {
135             voice->loop_start = sample_info->loop_start;
136             voice->loop_end = sample_info->loop_end;
137             voice->root_note = sample_info->root_note;
138             voice->fine_tune = (guint8)sample_info->fine_tune;
139 
140             switch(sample_info->options & IPATCH_DLS2_SAMPLE_LOOP_MASK)
141             {
142             case IPATCH_SAMPLE_LOOP_NONE:
143                 looptype = IPATCH_SF2_GEN_SAMPLE_MODE_NOLOOP;
144                 break;
145 
146             case IPATCH_SAMPLE_LOOP_RELEASE:
147                 looptype = IPATCH_SF2_GEN_SAMPLE_MODE_LOOP_RELEASE;
148                 break;
149 
150             default:	/* default to standard loop */
151                 looptype = IPATCH_SF2_GEN_SAMPLE_MODE_LOOP;
152                 break;
153             }
154 
155             /* set loop mode */
156             voice->gen_array.values[IPATCH_SF2_GEN_SAMPLE_MODES].sword = looptype;
157             IPATCH_SF2_GEN_ARRAY_SET_FLAG(&voice->gen_array,
158                                           IPATCH_SF2_GEN_SAMPLE_MODES);
159         }
160 
161         IPATCH_ITEM_RUNLOCK(region);  /* -- UNLOCK region */
162     }
163 
164     IPATCH_ITEM_RUNLOCK(inst);  /* -- UNLOCK instrument */
165 
166     /* if convert object was region, unref parent instrument */
167     if((void *)obj != (void *)inst)
168     {
169         g_object_unref(inst);    /* -- unref parent instrument */
170     }
171 
172     return (TRUE);
173 }
174 
175 /* use the instrument converter for regions also */
176 #define _dls2_region_to_sf2_voice_cache_convert \
177     _dls2_inst_to_sf2_voice_cache_convert
178 
179 /**
180  * _dls2_sample_to_sf2_voice_cache_convert: (skip)
181  *
182  * DLS2Sample voice cache converter - Not declared static, since used by
183  * IpatchSF2VoiceCache_Gig.c
184  */
185 gboolean
_dls2_sample_to_sf2_voice_cache_convert(IpatchConverter * converter,GError ** err)186 _dls2_sample_to_sf2_voice_cache_convert(IpatchConverter *converter,
187                                         GError **err)
188 {
189     IpatchDLS2Sample *sample;
190     IpatchSF2VoiceCache *cache;
191     IpatchSF2Voice *voice;
192     IpatchSF2GenAmount *amt;
193     int loopmode;
194 
195     sample = IPATCH_DLS2_SAMPLE(IPATCH_CONVERTER_INPUT(converter));
196     cache = IPATCH_SF2_VOICE_CACHE(IPATCH_CONVERTER_OUTPUT(converter));
197 
198     ipatch_sf2_voice_cache_declare_item(cache, (GObject *)sample);
199 
200     voice = ipatch_sf2_voice_cache_add_voice(cache);
201     voice->mod_list = ipatch_sf2_mod_list_duplicate(cache->default_mods);
202 
203     /* set MIDI note and velocity ranges */
204     amt = &voice->gen_array.values[IPATCH_SF2_GEN_NOTE_RANGE];
205     ipatch_sf2_voice_cache_set_voice_range(cache, voice, 0,
206                                            amt->range.low, amt->range.high);
207     amt = &voice->gen_array.values[IPATCH_SF2_GEN_VELOCITY_RANGE];
208     ipatch_sf2_voice_cache_set_voice_range(cache, voice, 1,
209                                            amt->range.low, amt->range.high);
210 
211     voice->mod_list = ipatch_sf2_mod_list_override(cache->default_mods,
212                       cache->override_mods, TRUE);
213 
214     ipatch_sf2_voice_set_sample_data(voice, sample->sample_data);
215 
216     voice->rate = sample->rate;
217 
218     if(sample->sample_info)
219     {
220         voice->loop_start = sample->sample_info->loop_start;
221         voice->loop_end = sample->sample_info->loop_end;
222         voice->root_note = sample->sample_info->root_note;
223         voice->fine_tune = (guint8)sample->sample_info->fine_tune;
224 
225         switch(sample->sample_info->options & IPATCH_DLS2_SAMPLE_LOOP_MASK)
226         {
227         case IPATCH_SAMPLE_LOOP_NONE:
228             loopmode = IPATCH_SF2_GEN_SAMPLE_MODE_NOLOOP;
229             break;
230 
231         case IPATCH_SAMPLE_LOOP_RELEASE:
232             loopmode = IPATCH_SF2_GEN_SAMPLE_MODE_LOOP_RELEASE;
233             break;
234 
235         default:	/* default to standard loop */
236             loopmode = IPATCH_SF2_GEN_SAMPLE_MODE_LOOP;
237             break;
238         }
239 
240         /* set loop mode */
241         voice->gen_array.values[IPATCH_SF2_GEN_SAMPLE_MODES].sword = loopmode;
242         IPATCH_SF2_GEN_ARRAY_SET_FLAG(&voice->gen_array,
243                                       IPATCH_SF2_GEN_SAMPLE_MODES);
244     }
245 
246     return (TRUE);
247 }
248 
249 CONVERTER_CLASS_INIT(dls2_inst_to_sf2_voice_cache)
250 CONVERTER_CLASS_INIT(dls2_region_to_sf2_voice_cache)
251 CONVERTER_CLASS_INIT(dls2_sample_to_sf2_voice_cache)
252 
253 CONVERTER_SF2_VOICE_CACHE_GET_TYPE(dls2_inst_to_sf2_voice_cache, DLS2InstToSF2VoiceCache)
254 CONVERTER_SF2_VOICE_CACHE_GET_TYPE(dls2_region_to_sf2_voice_cache, DLS2RegionToSF2VoiceCache)
255 CONVERTER_SF2_VOICE_CACHE_GET_TYPE(dls2_sample_to_sf2_voice_cache, DLS2SampleToSF2VoiceCache)
256