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