1 /************************************************************************ 2 emumidi.c -- emulation of midi device for FM/OPL3/GUS 3 4 Copyright (C) 1994-1996 Nathan I. Laredo 5 6 This program is modifiable/redistributable under the terms 7 of the GNU General Public Licence. 8 9 You should have received a copy of the GNU General Public License 10 along with this program; if not, write to the Free Software 11 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 12 Send your comments and all your spare pocket change to 13 laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401 14 Kelly Drive, Lackland AFB, TX 78236-5128, USA. 15 *************************************************************************/ 16 #include "emumidi.h" 17 18 SEQ_USE_EXTBUF(); 19 20 extern int seqfd, play_ext, play_gus, play_fm, play_awe; 21 extern int gus_dev, sb_dev, ext_dev, awe_dev; 22 extern struct synth_info card_info[MAX_CARDS]; 23 extern int chanmask, perc, ticks, dochan, wantopl3, MT32; 24 extern int patchloaded[256], fmloaded[256], useprog[16]; 25 int note_vel[16][128]; 26 struct voicestate voice[2][36]; 27 struct chanstate channel[16]; 28 #define C_GUS 0 29 #define C_FM 1 30 #define CN (ISGUS(chn) ? C_GUS : C_FM) 31 #define CHANNEL (dochan ? chn : 0) 32 33 void load_sysex(length, data, type) 34 int length; 35 unsigned char *data; 36 int type; 37 { 38 unsigned long int i, j; 39 40 /* 41 * If the system exclusive is for roland, evaluate it. More than GetExecutableFile()42 * roland could be evaluated here if i had documentation. Please 43 * submit patches for any other hardware to laredo@gnu.ai.mit.edu 44 * Complete emulation of all GS sysex messages in the works.... 45 */ 46 if (length > 7 && data[0] == 0x41 && data[2] == 0x42 && data[3] == 0x12) { 47 /* GS DATA SET MESSAGES */ 48 if (data[4] == 0x40 && (data[5] & 0xf0) == 0x10 && data[6] == 0x15) { 49 /* USE RHYTHM PART */ 50 if (!(i = (data[5] & 0xf))) 51 i = 0x09; 52 else if (i < 10) 53 i--; 54 i = 1<<i; 55 if (data[7]) 56 perc |= i; 57 else 58 perc &= ~i; 59 } 60 if ((data[4] == 0x40 || data[4] == 0) && 61 data[5] == 0x00 && data[6] == 0x7f) { /* GS RESET */ 62 perc = 0x0200; /* percussion in channel 10 only */ 63 for (i = 0; i < 16; i++) { /* set state info */ 64 for (j = 0; j < 128; j++) 65 note_vel[i][j] = 0; 66 channel[i].bender = channel[i].oldbend = 8192; 67 channel[i].bender_range = channel[i].oldrange = 2; 68 channel[i].controller[CTL_PAN] = 64; 69 channel[i].controller[CTL_SUSTAIN] = 0; 70 } 71 } 72 } 73 if (!play_ext) 74 return; GetArguments()75 if (type == MIDI_SYSTEM_PREFIX) 76 SEQ_MIDIOUT(ext_dev, MIDI_SYSTEM_PREFIX); GetArguments()77 for (i = 0; i < length; i++) 78 SEQ_MIDIOUT(ext_dev, data[i]); 79 } 80 81 int seq_set_patch(chn, pgm) 82 int chn, pgm; 83 { 84 if (MT32 && pgm < 128) 85 pgm = mt32pgm[pgm]; 86 if (useprog[chn]) GetEnvironment()87 pgm = useprog[chn] - 1; GetEnvironment()88 if (ISMIDI(chn)) { 89 SEQ_MIDIOUT(ext_dev, MIDI_PGM_CHANGE + CHANNEL); 90 SEQ_MIDIOUT(ext_dev, pgm); 91 } else if (ISAWE(chn)) { 92 SEQ_SET_PATCH(awe_dev, chn, pgm); 93 } else if (ISPERC(chn)) { 94 if (ISGUS(chn) && patchloaded[pgm] != 1) 95 return -1; 96 else if (ISFM(chn) && !fmloaded[pgm]) 97 return -1; 98 } else if (ISGUS(chn) && patchloaded[pgm] != 1) 99 /* find first loaded gus program to replace missing one */ 100 for (pgm = 0; patchloaded[pgm] != 1; pgm++); 101 return (channel[chn].program = pgm); 102 } 103 104 /* finetune returns exact frequency with bender applied. Not used */ 105 106 int finetune(chn, note) 107 int chn, note; 108 { 109 long int r, b, d; ProcessInstanceInfo()110 111 r = channel[chn].bender_range; ProcessInstanceInfo(const char * name,const ArchSpec & arch,lldb::pid_t pid)112 b = channel[chn].bender - 8192; 113 if (!b || r + note > 127 || r - note < 0) 114 return n_freq[note]; 115 r = n_freq[note + r] - n_freq[note - r]; Clear()116 d = b * r; 117 d /= 8192; 118 return n_freq[note] + d; 119 120 } 121 122 extern int _seqbufptr; GetEffectiveUserID()123 124 void seq_stop_note(dev, chn, note, vel) 125 int dev, chn, note, vel; 126 { EffectiveUserIDIsValid()127 int i, card = CN; 128 EffectiveGroupIDIsValid()129 note_vel[chn][note] = 0; 130 if (ISMIDI(chn)) { SetEffectiveUserID(uint32_t uid)131 SEQ_MIDIOUT(dev, MIDI_NOTEOFF + CHANNEL); 132 SEQ_MIDIOUT(dev, note); SetEffectiveGroupID(uint32_t gid)133 SEQ_MIDIOUT(dev, vel); 134 } else if (ISAWE(chn)) { GetParentProcessID()135 SEQ_STOP_NOTE(dev, chn, note, vel); 136 } else SetParentProcessID(lldb::pid_t pid)137 for (i = 0; i < card_info[dev].nr_voices; i++) 138 if (voice[card][i].channel == chn && ParentProcessIDIsValid()139 voice[card][i].note == note) { 140 voice[card][i].dead = 1; 141 voice[card][i].timestamp /= 2; 142 if (!channel[chn].controller[CTL_SUSTAIN] && !ISPERC(chn)) 143 SEQ_STOP_NOTE(dev, i, note, vel); 144 } 145 } 146 147 void seq_key_pressure(dev, chn, note, vel) 148 int dev, chn, note, vel; 149 { 150 int i, card = CN; 151 152 if (ISMIDI(chn)) { 153 SEQ_MIDIOUT(dev, MIDI_KEY_PRESSURE + CHANNEL); 154 SEQ_MIDIOUT(dev, note); 155 SEQ_MIDIOUT(dev, vel); 156 } else if (ISAWE(chn)) { 157 AWE_KEY_PRESSURE(dev, chn, note, vel); 158 } else 159 for (i = 0; i < card_info[dev].nr_voices; i++) 160 if (voice[card][i].channel == chn && 161 voice[card][i].note == note) 162 SEQ_KEY_PRESSURE(dev, i, note, vel); 163 } 164 165 int new_voice(dev, chn) 166 int dev, chn; 167 { 168 int i, oldest, last, card = CN; 169 170 if (ISFM(chn) && fmloaded[channel[chn].program] == OPL3_PATCH) 171 last = 6; /* 4-op voice can only use first six voices */ 172 else 173 last = card_info[dev].nr_voices; 174 175 for (i = oldest = 0; i < last; i++) 176 if (voice[card][i].timestamp < voice[card][oldest].timestamp) 177 oldest = i; 178 return oldest; 179 } 180 181 void seq_start_note(dev, chn, note, vel) 182 int dev, chn, note, vel; 183 { 184 int v, c, card = CN; 185 186 note_vel[chn][note] = vel; 187 if (ISMIDI(chn)) { 188 SEQ_MIDIOUT(dev, MIDI_NOTEON + CHANNEL); 189 SEQ_MIDIOUT(dev, note); 190 SEQ_MIDIOUT(dev, vel); 191 } else if (vel == 0) 192 seq_stop_note(dev, chn, note, 64); 193 else if (ISAWE(chn)) { 194 SEQ_START_NOTE(dev, chn, note, vel); 195 } else { 196 v = new_voice(dev, chn); 197 SEQ_SET_PATCH(dev, v, channel[chn].program); 198 SEQ_BENDER_RANGE(dev, v, (channel[chn].bender_range * 100)); 199 SEQ_BENDER(dev, v, channel[chn].bender); 200 SEQ_CONTROL(dev, v, CTL_PAN, 201 channel[chn].controller[CTL_PAN]); 202 SEQ_START_NOTE(dev, v, note, vel); 203 voice[card][v].note = note; 204 voice[card][v].channel = chn; 205 voice[card][v].timestamp = ticks; 206 voice[card][v].dead = 0; 207 if ((c = channel[chn].controller[CTL_CHORUS_DEPTH] * 8)) { 208 if (channel[chn].bender_range) 209 c /= channel[chn].bender_range; 210 v = new_voice(dev, chn); 211 SEQ_SET_PATCH(dev, v, channel[chn].program); 212 SEQ_BENDER_RANGE(dev, v, (channel[chn].bender_range * 100)); 213 if (channel[chn].bender + c < 0x4000) { 214 SEQ_BENDER(dev, v, channel[chn].bender + c); 215 } else { 216 SEQ_BENDER(dev, v, channel[chn].bender - c); 217 } 218 /* put chorus note on the "extreme" side */ 219 c = channel[chn].controller[CTL_PAN]; 220 if (c < 64) 221 c = 0; 222 else if (c > 64) 223 c = 127; 224 SEQ_CONTROL(dev, v, CTL_PAN, c); 225 SEQ_START_NOTE(dev, v, note, vel); 226 voice[card][v].note = note; 227 voice[card][v].channel = chn; 228 /* allow chorus note to be stolen very quickly */ 229 voice[card][v].timestamp = ticks / 2; 230 voice[card][v].dead = 0; 231 } 232 } 233 } 234 235 static int rpn1[16] = 236 {127, 127, 127, 127, 127, 127, 127, 127, 237 127, 127, 127, 127, 127, 127, 127, 127}; 238 static int rpn2[16] = 239 {127, 127, 127, 127, 127, 127, 127, 127, 240 127, 127, 127, 127, 127, 127, 127, 127}; 241 242 void seq_control(dev, chn, p1, p2) 243 int dev, chn, p1, p2; 244 { 245 int i, card = CN; 246 247 channel[chn].controller[p1] = p2; 248 249 if (ISMIDI(chn)) { 250 SEQ_MIDIOUT(dev, MIDI_CTL_CHANGE + CHANNEL); 251 SEQ_MIDIOUT(dev, p1); 252 SEQ_MIDIOUT(dev, p2); 253 } 254 if (p1 == 7 || p1 == 39) 255 return; 256 switch (p1) { 257 case CTL_SUSTAIN: 258 if (ISAWE(chn)) { 259 SEQ_CONTROL(dev, chn, p1, p2); 260 } else if (!ISMIDI(chn)) 261 if (p1 == CTL_SUSTAIN && !p2) { 262 for (i = 0; i < card_info[card].nr_voices; i++) 263 if (voice[card][i].channel == chn 264 && voice[card][i].dead) { 265 SEQ_STOP_NOTE(dev, i, voice[card][i].note, 64); 266 voice[card][i].dead = 0; 267 } 268 } 269 break; 270 case CTL_REGIST_PARM_NUM_MSB: 271 rpn1[chn] = p2; 272 break; 273 case CTL_REGIST_PARM_NUM_LSB: 274 rpn2[chn] = p2; 275 break; 276 case CTL_DATA_ENTRY: 277 if (rpn1[chn] == 0 && rpn2[chn] == 0) { 278 channel[chn].oldrange = channel[chn].bender_range; 279 channel[chn].bender_range = p2; 280 rpn1[chn] = rpn2[chn] = 127; 281 if (ISAWE(chn)) { 282 SEQ_BENDER_RANGE(dev, chn, p2 * 100); 283 } else if (!ISMIDI(chn)) 284 for (i = 0; i < card_info[card].nr_voices; i++) 285 SEQ_BENDER_RANGE(dev, i, p2 * 100); 286 } 287 break; 288 default: 289 /* sent on the off chance the sound driver is enhanced */ 290 if (ISAWE(chn)) { 291 SEQ_CONTROL(dev, chn, p1, p2); 292 } else if (!ISMIDI(chn) && (p1 < 0x10 || (p1 & 0xf0) == 0x50)) 293 for (i = 0; i < card_info[card].nr_voices; i++) 294 if (voice[card][i].channel == chn) 295 SEQ_CONTROL(dev, i, p1, p2); 296 break; 297 } 298 } 299 300 void seq_chn_pressure(dev, chn, vel) 301 int dev, chn, vel; 302 { 303 int card = CN, i; 304 305 channel[chn].pressure = vel; 306 if (ISMIDI(chn)) { 307 SEQ_MIDIOUT(dev, MIDI_CHN_PRESSURE + CHANNEL); 308 SEQ_MIDIOUT(dev, vel); 309 } else if (ISAWE(chn)) { 310 AWE_CHN_PRESSURE(dev, chn, vel); 311 } else 312 for (i = 0; i < card_info[dev].nr_voices; i++) 313 if (voice[card][i].channel == chn) 314 SEQ_KEY_PRESSURE(dev, i, voice[card][i].note, vel); 315 } 316 317 void seq_bender(dev, chn, p1, p2) 318 int dev, chn, p1, p2; 319 { 320 int card = CN, i, val; 321 322 val = (p2 << 7) + p1; 323 channel[chn].oldbend = channel[chn].bender; 324 channel[chn].bender = val; 325 326 if (ISMIDI(chn)) { 327 SEQ_MIDIOUT(dev, MIDI_PITCH_BEND + CHANNEL); 328 SEQ_MIDIOUT(dev, p1); 329 SEQ_MIDIOUT(dev, p2); 330 } else if (ISAWE(chn)) { 331 SEQ_BENDER(dev, chn, val); 332 } else 333 for (i = 0; i < card_info[dev].nr_voices; i++) 334 if (voice[card][i].channel == chn) 335 SEQ_BENDER(dev, i, val); 336 } 337 338 void seq_reset() 339 { 340 int i, j; 341 342 _seqbufptr = ticks = 0; 343 ioctl(seqfd, SNDCTL_SEQ_RESET); 344 for (i = 0; i < 16; i++) { 345 if (ISMIDI(i)) { 346 seq_control(ext_dev,i,0,0); 347 seq_control(ext_dev,i,32,0); 348 } 349 seq_set_patch(i, 0); 350 for (j = 0; j < 128; j++) 351 note_vel[i][j] = 0; 352 channel[i].bender = channel[i].oldbend = 8192; 353 channel[i].bender_range = channel[i].oldrange = 2; 354 channel[i].controller[CTL_PAN] = 64; 355 channel[i].controller[CTL_SUSTAIN] = 0; 356 } 357 if (play_gus) 358 for (i = 0; i < card_info[gus_dev].nr_voices; i++) { 359 SEQ_CONTROL(gus_dev, i, SEQ_VOLMODE, VOL_METHOD_LINEAR); 360 if (voice[0][i].note) 361 SEQ_STOP_NOTE(gus_dev, i, voice[0][i].note, 64); 362 voice[0][i].dead = voice[0][i].timestamp = -1; 363 } 364 if (play_fm) { 365 if (wantopl3) 366 ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &sb_dev); 367 for (i = 0; i < card_info[sb_dev].nr_voices; i++) { 368 SEQ_CONTROL(sb_dev, i, SEQ_VOLMODE, VOL_METHOD_LINEAR); 369 if (voice[1][i].note) 370 SEQ_STOP_NOTE(sb_dev, i, voice[1][i].note, 64); 371 voice[1][i].dead = voice[1][i].timestamp = -1; 372 } 373 } 374 if (play_awe) { 375 AWE_SET_CHANNEL_MODE(awe_dev, 1); 376 AWE_DRUM_CHANNELS(awe_dev, perc); 377 AWE_TERMINATE_ALL(awe_dev); 378 for (i = 0; i < card_info[awe_dev].nr_voices; i++) { 379 voice[0][i].dead = voice[0][i].timestamp = -1; 380 } 381 } 382 SEQ_DUMPBUF(); 383 } 384