1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 a_midicon.c - Engine MIDI Control Implementation
4 ---------------------------------------------------------------------------
5 * Copyright (C) 2001, 2002, David Olofson
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "kobolog.h"
23 #include "a_midicon.h"
24 #include "a_control.h"
25 #include "a_math.h"
26 #include "a_sequencer.h"
27
28
29 static int first_channel = 0;
30
31 #define MIDI_MAP_CH(x) ((x)+first_channel)
32 #define CH_MAP_MIDI(x) ((x)-first_channel)
33
34 static float fs = 44100;
35
36 /* Exponential table which maps [0, 127] ==> [0, 65535] */
37 static unsigned short explut[128];
38
39 typedef struct midi_channel_t
40 {
41 /* Volume & velocity */
42 int volume; /* Linear [0, 65535] */
43 int pan; /* Linear [-65536, 65535] */
44 int velocity[128]; /* For each key, linear [0, 65535] */
45
46 /* Send control */
47 int send; /* Linear [0, 65535+] */
48
49 /* Pitch */
50 int bend_depth;
51 int bend;
52 int f_pitch;
53 /* Key Management */
54 int last;
55 signed char next[128]; /* Index-linked list :-) */
56 signed char prev[128]; /* Index-linked list :-) */
57
58 /* Voice Management */
59 int poly;
60 int tag[128]; /* To keep track of individual notes */
61
62 /* Modulation */
63 unsigned mod;
64
65 /* Bus Control */
66 unsigned ifx_slot;
67 } midi_channel_t;
68
69 static midi_channel_t m[16];
70
__init(void)71 static void __init(void)
72 {
73 int i, j;
74 for(i = 0; i < 16; ++i)
75 {
76 m[i].volume = 100*512;
77 for(j = 0; j < 128; ++j)
78 m[i].velocity[j] = 0;
79 m[i].bend_depth = 12;
80 m[i].bend = 0;
81 m[i].f_pitch = 0;
82 m[i].last = -1;
83 memset(m[i].next, -1, sizeof(m[i].next));
84 memset(m[i].prev, -1, sizeof(m[i].prev));
85 m[i].poly = 1;
86 memset(m[i].tag, -1, sizeof(m[i].tag));
87 m[i].mod = 0;
88 }
89 for(i = 0; i < 128; ++i)
90 {
91 float linear = (float)(i+1) / 128;
92 explut[i] = (unsigned short)((0.25*linear + 0.5*linear*linear +
93 0.25*linear*linear*linear) * 65535.0);
94 }
95 #if 0
96 for(i = 0; i < 128; ++i)
97 {
98 int j;
99 for(j=0; j < (explut[i]>>9); ++j)
100 log_printf(D3LOG, "#");
101 log_printf(D3LOG, "\n");
102 }
103 for(i = 0; i < 128; ++i)
104 log_printf(D3LOG, "%d ==> %f\n", i, (float)explut[i]/65536.0);
105 #endif
106 }
107
108
__poly(unsigned ch,unsigned on)109 static inline void __poly(unsigned ch, unsigned on)
110 {
111 m[ch].poly = (int)on;
112 /*
113 FIXME: Maybe reimplement this somehow...?
114 FIXME: acc_set(MIDI_MAP_CH(ch), ACC_DETACH, on ? ADM_POLY : ADM_MONO);
115 */
116 }
117
118
__press(unsigned ch,unsigned key)119 static inline void __press(unsigned ch, unsigned key)
120 {
121 m[ch].next[key] = -1;
122 m[ch].prev[key] = m[ch].last;
123 m[ch].next[m[ch].last] = (char)key;
124 m[ch].last = (char)key;
125 }
126
127
128 /*
129 * Returns the new last key (-1 if none),
130 * or -2 if there's no change.
131 */
__release(unsigned ch,unsigned key)132 static inline int __release(unsigned ch, unsigned key)
133 {
134 if(m[ch].prev[key] != -1)
135 m[ch].next[m[ch].prev[key]] = m[ch].next[key];
136 if(m[ch].next[key] != -1)
137 {
138 m[ch].prev[m[ch].next[key]] = m[ch].prev[key];
139 m[ch].next[key] = m[ch].prev[key] = -1;
140 return -2;
141 }
142 else
143 {
144 m[ch].last = m[ch].prev[key];
145 m[ch].next[key] = m[ch].prev[key] = -1;
146 return m[ch].last;
147 }
148 }
149
150
151 /* Returns 1 if the specified key on the specified channel is down. */
__is_down(unsigned ch,int key)152 static inline int __is_down(unsigned ch, int key)
153 {
154 return (m[ch].tag[key] != -1);
155 }
156
157
midicon_note_off(unsigned ch,unsigned pitch,unsigned vel)158 static void midicon_note_off(unsigned ch, unsigned pitch, unsigned vel)
159 {
160 __release(ch, pitch);
161 (void)ce_stop(channeltab + MIDI_MAP_CH(ch), 0,
162 (int)pitch, (int)explut[vel]);
163 }
164
165
midicon_note_on(unsigned ch,unsigned pitch,unsigned vel)166 static void midicon_note_on(unsigned ch, unsigned pitch, unsigned vel)
167 {
168 if(!vel)
169 {
170 midicon_note_off(ch, pitch, 64);
171 return;
172 }
173 m[ch].velocity[pitch] = (int)explut[vel];
174 (void)ce_start(channeltab + MIDI_MAP_CH(ch), 0, (int)pitch,
175 (int)pitch << 16, m[ch].velocity[pitch]);
176 __press(ch, pitch);
177 }
178
179
midicon_pitch_bend(unsigned ch,int bend)180 static void midicon_pitch_bend(unsigned ch, int bend)
181 {
182 m[ch].bend = bend << 3;
183 m[ch].bend *= m[ch].bend_depth;
184 (void)ce_control(channeltab + MIDI_MAP_CH(ch), 0,
185 -1, ACC_PITCH, m[ch].bend + (60<<16));
186 }
187
188
189
midicon_control_change(unsigned ch,unsigned ctrl,unsigned amt)190 static void midicon_control_change(unsigned ch, unsigned ctrl, unsigned amt)
191 {
192 audio_channel_t *c = channeltab + MIDI_MAP_CH(ch);
193 switch (ctrl)
194 {
195 case 1:
196 m[ch].mod = amt;
197 break;
198 case 7:
199 m[ch].volume = (int)explut[amt];
200 (void)ce_control(c, 0, -1, ACC_VOLUME, m[ch].volume);
201 break;
202 case 10:
203 m[ch].pan = (amt << 10) - 65536;
204 (void)ce_control(c, 0, -1, ACC_PAN, m[ch].pan);
205 break;
206
207 /* Bus Control */
208 case 39: /* Select IFX Slot */
209 m[ch].ifx_slot = (unsigned)amt;
210 break;
211
212 case 40: /* IFX Type */
213 if(ch >= AUDIO_MAX_BUSSES)
214 break;
215 if(m[ch].ifx_slot > AUDIO_MAX_INSERTS-1)
216 break;
217 bus_ctl_set(ch, m[ch].ifx_slot, ABC_FX_TYPE, (int)amt);
218 break;
219 case 41: /* IFX P1 (Time 1) */
220 case 42: /* IFX P2 (Time 2) */
221 case 43: /* IFX P3 (Depth 1) */
222 case 44: /* IFX P4 (Depth 2)*/
223 case 45: /* IFX P5 (Rate) */
224 case 46: /* IFX P6 (Mode/Special) */
225 if(ch >= AUDIO_MAX_BUSSES)
226 break;
227 if(m[ch].ifx_slot > AUDIO_MAX_INSERTS-1)
228 break;
229 if(ctrl != 46)
230 amt = (unsigned)(explut[amt]) << 1;
231 bus_ctl_set(ch, m[ch].ifx_slot, ctrl - 41 + ABC_FX_PARAM_1,
232 (int)amt);
233 break;
234
235 case 47: /* IFX Wet -> master */
236 if(ch >= AUDIO_MAX_BUSSES)
237 break;
238 if(m[ch].ifx_slot > AUDIO_MAX_INSERTS-1)
239 break;
240 bus_ctl_set(ch, m[ch].ifx_slot, ABC_SEND_MASTER,
241 explut[amt] << 1);
242 break;
243
244 case 48: /* Sends to other busses */
245 case 49:
246 case 50:
247 case 51:
248 case 52:
249 case 53:
250 case 54:
251 case 55:
252 if(ch >= AUDIO_MAX_BUSSES)
253 break;
254 if(m[ch].ifx_slot > AUDIO_MAX_INSERTS-1)
255 break;
256 bus_ctl_set(ch, m[ch].ifx_slot, ABC_SEND_BUS_0 + ctrl-48,
257 explut[amt] << 1);
258 break;
259
260 case 88: /* Primary output bus */
261 (void)ce_control(c, 0, -1, ACC_PRIM_BUS, amt-1);
262 break;
263 case 89: /* Send bus */
264 (void)ce_control(c, 0, -1, ACC_SEND_BUS, amt-1);
265 break;
266 case 91: /* Send Level ("Reverb") */
267 m[ch].send = (int)explut[amt] << 1;
268 (void)ce_control(c, 0, -1, ACC_SEND, m[ch].send);
269 break;
270
271 case 120: /* All Sound Off */
272 case 123: /* All Notes Off */
273 if(m[ch].poly)
274 {
275 int note = m[ch].last;
276 while(note >= 0)
277 {
278 int n = note;
279 note = m[ch].prev[note];
280 midicon_note_off(ch, (unsigned)n, 64);
281 }
282 }
283 else
284 midicon_note_off(ch, (unsigned)m[ch].last, 64);
285 break;
286 case 121: /* Reset All Controllers */
287 __poly(ch, 1);
288 m[ch].mod = 0;
289 m[ch].volume = 100*512;
290 m[ch].send = 0;
291 m[ch].pan = 0;
292 (void)ce_control(c, 0, -1, ACC_VOLUME, m[ch].volume);
293 (void)ce_control(c, 0, -1, ACC_SEND, m[ch].send);
294 (void)ce_control(c, 0, -1, ACC_PAN, m[ch].pan);
295 midicon_pitch_bend(ch, 0);
296 break;
297 case 126: /* Mono */
298 __poly(ch, 0);
299 break;
300 case 127: /* Poly */
301 __poly(ch, 1);
302 break;
303 default:
304 break;
305 }
306 }
307
308
midicon_program_change(unsigned ch,unsigned prog)309 static void midicon_program_change(unsigned ch, unsigned prog)
310 {
311 (void)ce_control(channeltab + MIDI_MAP_CH(ch), 0, -2, ACC_PATCH, (int)prog);
312 }
313
314
315 midisock_t midicon_midisock = {
316 midicon_note_off,
317 midicon_note_on,
318 NULL, /* poly_pressure */
319 midicon_control_change,
320 midicon_program_change,
321 NULL, /* channel_pressure */
322 midicon_pitch_bend
323 };
324
325
midicon_open(float framerate,int first_ch)326 int midicon_open(float framerate, int first_ch)
327 {
328 unsigned i;
329 aev_client("midicon_open()");
330 fs = framerate;
331 first_channel = first_ch;
332 __init();
333 for(i = 0; i < 16; ++i)
334 __poly(i, 1);
335 return 0;
336 }
337
338
midicon_close(void)339 void midicon_close(void)
340 {
341 aev_client("midicon_close()");
342 }
343
344
midicon_process(unsigned frames)345 void midicon_process(unsigned frames)
346 {
347 aev_client("midicon_process()");
348 /*
349 * This is where MIDI clock and stuff goes.
350 */
351 }
352