1 /*(LGPL) 2 --------------------------------------------------------------------------- 3 a_voice.h - Audio Engine low level mixer voices 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 * How To Keep Track Of Your Voices (for patch programmers): 24 * Before doing anything with a Voice, first check that it 25 * still actually *is* your voice, and hasn't been stolen 26 * by some one else. The 'channel' field will indicate this, 27 * of course, but that's actually only half a solution! 28 * 29 * Why? Well, if you're doing somethingn polyphonic, the 30 * Voice allocator may steal *your* voices, just as any other 31 * voices, which is why it's quite possible to lose voices to 32 * your own channel. 33 * 34 * To deal with this, each Voice has a 'tag' field that you 35 * may use in any way you see fit. The idea is to write a 36 * "locally unique" code into the 'tag' field whenever you 37 * get a "new" voice from the allocator. That way, you can 38 * just check that value later on, to see whether or not the 39 * channel is still doing what you told it to, or if you or 40 * someone else has started a new job on it. 41 * 42 * As an example, MIDI code may store MIDI pitch in the 43 * 'tag' field upon NoteOn, as there can usually only be one 44 * "voice context" (one or more voices) active for each MIDI 45 * key of each MIDI channel. When receiving other messages, 46 * just check for each voice before you touch, that 1) it's 47 * still owned by the engine Channel the MIDI channel is 48 * mapped to. When you eventually get the NoteOff, 2) check 49 * that the 'tag' fields of voices match the MIDI pitch of 50 * the NoteOff message. 51 * 52 * Note that as long as everyone sticks with their own 53 * Channels, it's ok to use the 'tag' fields in different 54 * ways in the same engine, at the same time. Checking 55 * 'channel' fields *first* will avoid any confusion. 56 */ 57 58 #ifndef _A_VOICE_H_ 59 #define _A_VOICE_H_ 60 61 #include "a_globals.h" 62 #include "a_types.h" 63 #include "a_events.h" 64 #include "a_patch.h" 65 66 67 typedef enum voice_states_t 68 { 69 VS_STOPPED = 0, /* "Detached" from the mixer */ 70 VS_RESERVED, /* Just allocated; pending events */ 71 VS_PLAYING /* Playing! */ 72 } voice_states_t; 73 74 75 typedef enum voice_events_t 76 { 77 VE_START = 0, /* Start playing waveform <arg1>. */ 78 VE_STOP, /* Stop and free voice, flush events. 79 * This *will* click unless you fade out first! 80 * NOTE: The voice disappears in a puff of 81 * violet smoke after receiving this 82 * event! Any subsequent events will 83 * be deleted and IGNORED. 84 */ 85 VE_SET, /* Set control <index> to <arg1>. */ 86 // VE_ISET, /* Set interpolated control <index> to <arg1>. */ 87 VE_IRAMP /* Ramp interpolated control <index> to <arg1> 88 * over <arg2> frames. 89 */ 90 } voice_events_t; 91 92 93 /* Voice Controls that are *not* interpolated. */ 94 typedef enum voice_controls_t 95 { 96 VC_WAVE = 0, /* (int) Waveform index (latched on loop) */ 97 VC_LOOP, /* (boolean) */ 98 99 VC_PITCH, /* (fixp) linear frequency; int <==> MIDI */ 100 101 VC_RETRIG, /* (int) retrig after N samples */ 102 VC_RANDTRIG, /* (fixp[0, 1]) random mod. to RETRIG */ 103 104 VC_PRIM_BUS, /* (int) target bus for ACC_VOLUME */ 105 VC_SEND_BUS, /* (int) target bus for ACC_SEND */ 106 107 VC_RESAMPLE, /* (enum) Resampling mode */ 108 109 VC_COUNT 110 } voice_controls_t; 111 112 /* Voice Controls that *are* interpolated. */ 113 typedef enum voice_icontrols_t 114 { 115 VIC_LVOL = 0, /* (fixp) Left volume */ 116 VIC_RVOL, /* (fixp) Right volume */ 117 VIC_LSEND, /* (fixp) Left send */ 118 VIC_RSEND, /* (fixp) Right send */ 119 120 VIC_COUNT 121 } voice_icontrols_t; 122 123 124 /* Voice control interpolator */ 125 typedef struct voice_ci_t 126 { 127 int v; 128 int dv; 129 } voice_ci_t; 130 131 132 struct audio_channel_t; 133 134 typedef struct audio_voice_t 135 { 136 /* Voice Management */ 137 struct audio_voice_t *next; /* For channel voice list */ 138 struct audio_voice_t *prev; 139 struct audio_channel_t *channel; 140 int tag; /* tag from patch */ 141 int priority; /* Stealing priority (from owner) */ 142 143 /* Non-interpolated Controls */ 144 int c[VC_COUNT]; 145 146 /* Interpolated Controls */ 147 voice_ci_t ic[VIC_COUNT]; 148 149 /* Event Control */ 150 aev_port_t port; /* Event input port */ 151 152 /* Oscillator */ 153 voice_states_t state; 154 int wave; 155 unsigned int section_end; /* index of section end point */ 156 unsigned int position; /* current pos, integer part */ 157 unsigned int position_frac; /* current pos, fractional part */ 158 unsigned int step; /* position inc per output frame */ 159 #ifdef AUDIO_USE_VU 160 int vu; /* Pre-volume, linear peak, [0, 65535]. 161 * Reset or fade after reading! 162 */ 163 #endif 164 /* Output routing control */ 165 int use_double; /* Use double output mixers */ 166 int fx1, fx2; /* FX send bus indices */ 167 168 patch_closure_t closure; /* Per-voice data for patch */ 169 } audio_voice_t; 170 171 /* Get a free voice, or steal one if necessary. */ 172 int voice_alloc(struct audio_channel_t *c); 173 174 /* 175 * The *real*, brutal stop action. 176 * No mercy. No click elimination. 177 * Use only in case of emergency. 178 */ 179 void voice_kill(audio_voice_t *v); 180 181 /* Dirty crap function used to "wake a voice up" if needed... */ 182 void voice_check_retrig(audio_voice_t *v); 183 184 /* 185 * Mix 'frames' stereo samples into one or more of the 'busses', 186 * as specified by the voice's output controls. 187 * 188 * (Can be driven directly "from outside" the engine. The Waveform 189 * Construction API does this for resampling/conversion, for example.) 190 */ 191 void voice_process_mix(audio_voice_t *v, int *busses[], unsigned frames); 192 193 /* Process all voices. Simple, eh? */ 194 void voice_process_all(int *busses[], unsigned frames); 195 196 void audio_voice_open(void); 197 void audio_voice_close(void); 198 199 #endif /*_A_VOICE_H_*/ 200