1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 	a_control.c - Group/Channel/Voice 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 /*
23  *	The control routing model:
24  *
25  *		         Group
26  *		         ^   |
27  *		         |   V
28  *		MIDI -> Channel -> Patch ---> Voice
29  *		 |                        |-> Voice
30  *		 V                        ...  ...
31  *		Bus Control               '-> Voice
32  *
33  *	Groups are used by Channels, to transform some of the control
34  *	data sent to them, before passing it on to the current Patch.
35  *	That is, they would effectively fit in in between Channels
36  *	and Patches, from the data flow POV.
37  *
38  *	Note that while Groups act as passive data containers most of
39  *	the time, they *can* become active, and force Channels to
40  *	refresh some Controls. This can happen when changing the
41  *	"music volume" in an application, for example.
42 FIXME: What about busses with non-linear insert effects? Looks like
43 FIXME: at least *some* Group Controls should not be applied on the
44 FIXME: Channel or Patch level, but rather on the Busses... Maybe
45 FIXME: Busses should have 'group' fields? That way, one can still
46 FIXME: use them as with the current design, although for example
47 FIXME: ACC_VOLUME would be sent off to the bus send that acts as
48 FIXME: master volume for all Voices of the Group.
49 FIXME:   Then again, this may result in general confusion! It's
50 FIXME: theoretically possible to select busses on a *per-Voice
51 FIXME: basis* (via Patches), and quite easy to select busses
52 FIXME: directly using MIDI CCs. Good bye to application control
53 FIXME: over the mixing...!
54 FIXME:   The only simple solution I can see is to prevent sending
55 FIXME: between busses across group boundaries.
56  */
57 
58 #include "a_globals.h"
59 #include "a_control.h"
60 #include "a_tools.h"
61 
62 const int addtrans_min[2] = {	-65536,	0	};
63 const int addtrans_max[2] = {	65536,	128<<16	};
64 const int addtrans_bias[2] = {	0,	60<<16	};
65 
66 
67 /*----------------------------------------------------------
68 	Group Control
69 ----------------------------------------------------------*/
70 
acc_group_set(unsigned gid,unsigned ctl,int arg)71 void acc_group_set(unsigned gid, unsigned ctl, int arg)
72 {
73 	int i;
74 	audio_group_t *g = grouptab + gid;
75 	g->ctl[ctl] = arg;
76 
77 	if(!_audio_running)
78 		return;
79 
80 	/* Update all channels of the group */
81 	for(i = 0; i < AUDIO_MAX_CHANNELS; ++i)
82 	{
83 		audio_channel_t *c = channeltab + i;
84 		if((unsigned)c->ctl[ACC_GROUP] != gid)
85 			continue;
86 		(void)ce_control_i(c, 0, -1, ctl, c->rctl[ctl]);
87 	}
88 }
89 
90 
91 static int _is_open = 0;
92 
audio_group_open(void)93 void audio_group_open(void)
94 {
95 	int i;
96 	if(_is_open)
97 		return;
98 
99 	memset(grouptab, 0, sizeof(grouptab));
100 	for(i = 0; i < AUDIO_MAX_GROUPS; ++i)
101 		acc_copya(&grouptab[i].ctl, &a_group_def_ctl);
102 	_is_open = 1;
103 }
104 
105 
audio_group_close(void)106 void audio_group_close(void)
107 {
108 	if(!_is_open)
109 		return;
110 
111 	memset(grouptab, 0, sizeof(grouptab));
112 	_is_open = 0;
113 }
114