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