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 #ifndef __IPATCH_SF2_VOICE_CACHE_H__
21 #define __IPATCH_SF2_VOICE_CACHE_H__
22 
23 #include <stdarg.h>
24 #include <glib.h>
25 #include <glib-object.h>
26 
27 #include <libinstpatch/IpatchSampleData.h>
28 #include <libinstpatch/IpatchSF2Gen.h>
29 #include <libinstpatch/IpatchSF2Mod.h>
30 #include <libinstpatch/IpatchSample.h>
31 
32 /* forward type declarations */
33 
34 typedef struct _IpatchSF2VoiceCache IpatchSF2VoiceCache;
35 typedef struct _IpatchSF2VoiceCacheClass IpatchSF2VoiceCacheClass;
36 typedef struct _IpatchSF2Voice IpatchSF2Voice;
37 typedef struct _IpatchSF2VoiceUpdate IpatchSF2VoiceUpdate;
38 typedef struct _IpatchSF2VoiceSelInfo IpatchSF2VoiceSelInfo;
39 
40 #define IPATCH_TYPE_SF2_VOICE_CACHE   (ipatch_sf2_voice_cache_get_type ())
41 #define IPATCH_SF2_VOICE_CACHE(obj) \
42   (G_TYPE_CHECK_INSTANCE_CAST ((obj), IPATCH_TYPE_SF2_VOICE_CACHE, \
43   IpatchSF2VoiceCache))
44 #define IPATCH_SF2_VOICE_CACHE_CLASS(klass) \
45   (G_TYPE_CHECK_CLASS_CAST ((klass), IPATCH_TYPE_SF2_VOICE_CACHE, \
46   IpatchSF2VoiceCacheClass))
47 #define IPATCH_IS_SF2_VOICE_CACHE(obj) \
48   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IPATCH_TYPE_SF2_VOICE_CACHE))
49 #define IPATCH_IS_SF2_VOICE_CACHE_CLASS(klass) \
50   (G_TYPE_CHECK_CLASS_TYPE ((klass), IPATCH_TYPE_SF2_VOICE_CACHE))
51 
52 /**
53  * IpatchSF2VoiceCacheItemFunc:
54  * @cache: Voice cache
55  * @item: Item which voice cache is dependent on
56  *
57  * A callback function type which is called during voice cache population
58  * for each item which the voice cache is dependent on. This can be useful
59  * for determining when a voice cache needs to be updated or for real time
60  * effects.
61  */
62 typedef void (*IpatchSF2VoiceCacheItemFunc)(IpatchSF2VoiceCache *cache,
63         GObject *item);
64 
65 /* SoundFont voice cache object */
66 struct _IpatchSF2VoiceCache
67 {
68     GObject parent_instance;
69 
70     IpatchSF2VoiceSelInfo *sel_info;	/* array of selection criteria info */
71     int sel_count;    /* count of selection ranges per voice (integer pairs) */
72 
73     GArray *voices;	/* array of IpatchSF2Voice structures */
74     GArray *ranges;	/* array of selection integer pairs for each voice */
75 
76     GSList *default_mods;		/* default modulators */
77 
78     /* default loop type which can be used for objects that don't define it */
79     IpatchSampleLoopType default_loop_type;
80 
81     /* dependent item callback function */
82     IpatchSF2VoiceCacheItemFunc item_func;
83     gpointer item_func_data;	/* user defined data used by item_func */
84 
85     /* IpatchSF2VoiceCache user defined */
86     gpointer user_data;           /* Arbitrary data defined by IpatchSF2VoiceCache user */
87     GDestroyNotify user_data_destroy; /* Optional callback to destroy user_data */
88     GDestroyNotify voice_user_data_destroy; /* Optional callback to destroy user_data in each voice */
89 
90     /* Added with version 1.1.0 */
91     GSList *override_mods;        /* override modulators (added with libInstPatch version 1.1.0) */
92 };
93 
94 struct _IpatchSF2VoiceCacheClass
95 {
96     GObjectClass parent_class;
97 };
98 
99 /* a SoundFont voice */
100 struct _IpatchSF2Voice
101 {
102     /* Set by SF2VoiceCache converter via ipatch_sf2_voice_set_sample_data() */
103     IpatchSampleData *sample_data;	/* sample data for voice */
104     IpatchSampleStore *sample_store;	/* Cached store */
105     guint32 sample_size;			/* size of sample in frames */
106 
107     /* Set by SF2VoiceCache converter */
108     guint32 loop_start;		/* loop start offset (in samples) */
109     guint32 loop_end;   /* loop end offset (in samples, 1st sample after loop) */
110     guint32 rate;			/* sample rate */
111     guint8 root_note;		/* MIDI root note of sample */
112     gint8 fine_tune;		/* fine tune (in cents, -99 - 99) */
113     guint16 reserved;		/* reserved (should be 0) */
114 
115     IpatchSF2GenArray gen_array;	/* generator effect values */
116     GSList *mod_list;		/* modulator list */
117 
118     /* IpatchSF2VoiceCache user defined */
119     gpointer user_data;           /* Arbitrary data defined by IpatchSF2VoiceCache user */
120 
121     /* Set internally */
122     int range_index;  /* index in ranges array (int *) to first selection range */
123 };
124 
125 /* a voice parameter update (used for realtime effects) */
126 struct _IpatchSF2VoiceUpdate
127 {
128     guint16 voice;	/* index of voice with parameter to update */
129 
130     union			/* new value for parameter */
131     {
132         gint16 ival;
133         guint16 uval;
134     };
135 
136     guint8 genid;		/* if type == IPATCH_SF2_VOICE_UPDATE_GEN: id of gen */
137     guint8 reserved[3];	/* padding to 4 bytes */
138 };
139 
140 /**
141  * IpatchSF2VoiceCacheUpdateHandler:
142  * @cache: Voice cache to get updates for
143  * @select_values: The voice selection criteria to use, should be the same
144  *   number of select values as in @cache
145  * @cache_item: Original item @cache was created from
146  * @item: Object for which a property changed
147  * @pspec: Parameter specification of property which changed
148  * @value: The new value of the property
149  * @updates: Output array to store updates to
150  * @max_updates: Size of @updates array (max possible update values).
151  *
152  * Function prototype used to re-calculate SoundFont effect generators for a
153  * single object property change.  Useful for real time effect changes.
154  *
155  * Returns: Should return number of updates stored to @updates array.
156  *   Will be 0 if no updates required.
157  */
158 typedef int (*IpatchSF2VoiceCacheUpdateHandler)(IpatchSF2VoiceCache *cache,
159         int *select_values,
160         GObject *cache_item,
161         GObject *item, GParamSpec *pspec,
162         const GValue *value,
163         IpatchSF2VoiceUpdate *updates,
164         guint max_updates);
165 /* voice selection type */
166 typedef enum
167 {
168     IPATCH_SF2_VOICE_SEL_NOTE,		/* MIDI note range */
169     IPATCH_SF2_VOICE_SEL_VELOCITY,	/* MIDI velocity range */
170     IPATCH_SF2_VOICE_SEL_AFTER_TOUCH,	/* MIDI aftertouch range */
171     IPATCH_SF2_VOICE_SEL_MIDI_CC	/* MIDI custom controller (param1: ctrlnum) */
172 } IpatchSF2VoiceSelType;
173 
174 /* selection info structure */
175 struct _IpatchSF2VoiceSelInfo
176 {
177     IpatchSF2VoiceSelType type;
178     int param1;
179     int param2;				/* currently not used */
180 };
181 
182 /* maximum allowed voice selection criteria (MIDI note, velocity, etc) */
183 #define IPATCH_SF2_VOICE_CACHE_MAX_SEL_VALUES   32
184 
185 /* value used for wildcard selection */
186 #define IPATCH_SF2_VOICE_SEL_WILDCARD (G_MININT)
187 
188 /* For voice cache propagation methods to declare dependent items */
189 #define ipatch_sf2_voice_cache_declare_item(cache, item) \
190   if (cache->item_func) cache->item_func (cache, item)
191 
192 /* Macro for retrieving a voice pointer from a cache */
193 #define IPATCH_SF2_VOICE_CACHE_GET_VOICE(cache, index) \
194   (&g_array_index (cache->voices, IpatchSF2Voice, index))
195 
196 GType ipatch_sf2_voice_cache_get_type(void);
197 IpatchSF2VoiceCache *ipatch_sf2_voice_cache_new(IpatchSF2VoiceSelInfo *info,
198         int sel_count);
199 void ipatch_sf2_voice_cache_set_default_mods(IpatchSF2VoiceCache *cache,
200         GSList *mods);
201 void ipatch_sf2_voice_cache_set_override_mods(IpatchSF2VoiceCache *cache,
202         GSList *mods);
203 
204 IpatchSF2Voice *ipatch_sf2_voice_cache_add_voice(IpatchSF2VoiceCache *cache);
205 void ipatch_sf2_voice_cache_set_voice_range(IpatchSF2VoiceCache *cache,
206         IpatchSF2Voice *voice, guint sel_index, int low, int high);
207 void ipatch_sf2_voice_set_sample_data(IpatchSF2Voice *voice,
208                                       IpatchSampleData *sample_data);
209 gboolean ipatch_sf2_voice_cache_sample_data(IpatchSF2Voice *voice, GError **err);
210 void ipatch_sf2_voice_copy(IpatchSF2Voice *dest, IpatchSF2Voice *src);
211 void ipatch_sf2_voice_cache_optimize(IpatchSF2VoiceCache *cache);
212 int ipatch_sf2_voice_cache_select(IpatchSF2VoiceCache *cache,
213                                   int *select_values,
214                                   guint16 *index_array,
215                                   guint16 max_indexes);
216 int ipatch_sf2_voice_cache_update(IpatchSF2VoiceCache *cache,
217                                   int *select_values,
218                                   GObject *cache_item,
219                                   GObject *item, GParamSpec *pspec,
220                                   const GValue *value,
221                                   IpatchSF2VoiceUpdate *updates,
222                                   guint max_updates);
223 #endif
224