1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * GM/GS/XG midi module. 4 * 5 * Copyright (C) 1999 Steve Ratcliffe 6 * 7 * Based on awe_wave.c by Takashi Iwai 8 */ 9 /* 10 * This module is used to keep track of the current midi state. 11 * It can be used for drivers that are required to emulate midi when 12 * the hardware doesn't. 13 * 14 * It was written for a AWE64 driver, but there should be no AWE specific 15 * code in here. If there is it should be reported as a bug. 16 */ 17 18 #include <linux/init.h> 19 #include <linux/slab.h> 20 #include <linux/string.h> 21 #include <linux/module.h> 22 #include <sound/core.h> 23 #include <sound/seq_kernel.h> 24 #include <sound/seq_midi_emul.h> 25 #include <sound/initval.h> 26 #include <sound/asoundef.h> 27 28 MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe"); 29 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation."); 30 MODULE_LICENSE("GPL"); 31 32 /* Prototypes for static functions */ 33 static void note_off(struct snd_midi_op *ops, void *drv, 34 struct snd_midi_channel *chan, 35 int note, int vel); 36 static void do_control(struct snd_midi_op *ops, void *private, 37 struct snd_midi_channel_set *chset, 38 struct snd_midi_channel *chan, 39 int control, int value); 40 static void rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, 41 struct snd_midi_channel_set *chset); 42 static void nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, 43 struct snd_midi_channel_set *chset); 44 static void sysex(struct snd_midi_op *ops, void *private, unsigned char *sysex, 45 int len, struct snd_midi_channel_set *chset); 46 static void all_sounds_off(struct snd_midi_op *ops, void *private, 47 struct snd_midi_channel *chan); 48 static void all_notes_off(struct snd_midi_op *ops, void *private, 49 struct snd_midi_channel *chan); 50 static void snd_midi_reset_controllers(struct snd_midi_channel *chan); 51 static void reset_all_channels(struct snd_midi_channel_set *chset); 52 53 54 /* 55 * Process an event in a driver independent way. This means dealing 56 * with RPN, NRPN, SysEx etc that are defined for common midi applications 57 * such as GM, GS and XG. 58 * There modes that this module will run in are: 59 * Generic MIDI - no interpretation at all, it will just save current values 60 * of controllers etc. 61 * GM - You can use all gm_ prefixed elements of chan. Controls, RPN, NRPN, 62 * SysEx will be interpreded as defined in General Midi. 63 * GS - You can use all gs_ prefixed elements of chan. Codes for GS will be 64 * interpreted. 65 * XG - You can use all xg_ prefixed elements of chan. Codes for XG will 66 * be interpreted. 67 */ 68 void 69 snd_midi_process_event(struct snd_midi_op *ops, 70 struct snd_seq_event *ev, 71 struct snd_midi_channel_set *chanset) 72 { 73 struct snd_midi_channel *chan; 74 void *drv; 75 int dest_channel = 0; 76 77 if (ev == NULL || chanset == NULL) { 78 pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n"); 79 return; 80 } 81 if (chanset->channels == NULL) 82 return; 83 84 if (snd_seq_ev_is_channel_type(ev)) { 85 dest_channel = ev->data.note.channel; 86 if (dest_channel >= chanset->max_channels) { 87 pr_debug("ALSA: seq_midi_emul: dest channel is %d, max is %d\n", 88 dest_channel, chanset->max_channels); 89 return; 90 } 91 } 92 93 chan = chanset->channels + dest_channel; 94 drv = chanset->private_data; 95 96 /* EVENT_NOTE should be processed before queued */ 97 if (ev->type == SNDRV_SEQ_EVENT_NOTE) 98 return; 99 100 /* Make sure that we don't have a note on that should really be 101 * a note off */ 102 if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) 103 ev->type = SNDRV_SEQ_EVENT_NOTEOFF; 104 105 /* Make sure the note is within array range */ 106 if (ev->type == SNDRV_SEQ_EVENT_NOTEON || 107 ev->type == SNDRV_SEQ_EVENT_NOTEOFF || 108 ev->type == SNDRV_SEQ_EVENT_KEYPRESS) { 109 if (ev->data.note.note >= 128) 110 return; 111 } 112 113 switch (ev->type) { 114 case SNDRV_SEQ_EVENT_NOTEON: 115 if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) { 116 if (ops->note_off) 117 ops->note_off(drv, ev->data.note.note, 0, chan); 118 } 119 chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON; 120 if (ops->note_on) 121 ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan); 122 break; 123 case SNDRV_SEQ_EVENT_NOTEOFF: 124 if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON)) 125 break; 126 if (ops->note_off) 127 note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity); 128 break; 129 case SNDRV_SEQ_EVENT_KEYPRESS: 130 if (ops->key_press) 131 ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan); 132 break; 133 case SNDRV_SEQ_EVENT_CONTROLLER: 134 do_control(ops, drv, chanset, chan, 135 ev->data.control.param, ev->data.control.value); 136 break; 137 case SNDRV_SEQ_EVENT_PGMCHANGE: 138 chan->midi_program = ev->data.control.value; 139 break; 140 case SNDRV_SEQ_EVENT_PITCHBEND: 141 chan->midi_pitchbend = ev->data.control.value; 142 if (ops->control) 143 ops->control(drv, MIDI_CTL_PITCHBEND, chan); 144 break; 145 case SNDRV_SEQ_EVENT_CHANPRESS: 146 chan->midi_pressure = ev->data.control.value; 147 if (ops->control) 148 ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan); 149 break; 150 case SNDRV_SEQ_EVENT_CONTROL14: 151 /* Best guess is that this is any of the 14 bit controller values */ 152 if (ev->data.control.param < 32) { 153 /* set low part first */ 154 chan->control[ev->data.control.param + 32] = 155 ev->data.control.value & 0x7f; 156 do_control(ops, drv, chanset, chan, 157 ev->data.control.param, 158 ((ev->data.control.value>>7) & 0x7f)); 159 } else 160 do_control(ops, drv, chanset, chan, 161 ev->data.control.param, 162 ev->data.control.value); 163 break; 164 case SNDRV_SEQ_EVENT_NONREGPARAM: 165 /* Break it back into its controller values */ 166 chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED; 167 chan->control[MIDI_CTL_MSB_DATA_ENTRY] 168 = (ev->data.control.value >> 7) & 0x7f; 169 chan->control[MIDI_CTL_LSB_DATA_ENTRY] 170 = ev->data.control.value & 0x7f; 171 chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] 172 = (ev->data.control.param >> 7) & 0x7f; 173 chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] 174 = ev->data.control.param & 0x7f; 175 nrpn(ops, drv, chan, chanset); 176 break; 177 case SNDRV_SEQ_EVENT_REGPARAM: 178 /* Break it back into its controller values */ 179 chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED; 180 chan->control[MIDI_CTL_MSB_DATA_ENTRY] 181 = (ev->data.control.value >> 7) & 0x7f; 182 chan->control[MIDI_CTL_LSB_DATA_ENTRY] 183 = ev->data.control.value & 0x7f; 184 chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] 185 = (ev->data.control.param >> 7) & 0x7f; 186 chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB] 187 = ev->data.control.param & 0x7f; 188 rpn(ops, drv, chan, chanset); 189 break; 190 case SNDRV_SEQ_EVENT_SYSEX: 191 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { 192 unsigned char sysexbuf[64]; 193 int len; 194 len = snd_seq_expand_var_event(ev, sizeof(sysexbuf), sysexbuf, 1, 0); 195 if (len > 0) 196 sysex(ops, drv, sysexbuf, len, chanset); 197 } 198 break; 199 case SNDRV_SEQ_EVENT_SONGPOS: 200 case SNDRV_SEQ_EVENT_SONGSEL: 201 case SNDRV_SEQ_EVENT_CLOCK: 202 case SNDRV_SEQ_EVENT_START: 203 case SNDRV_SEQ_EVENT_CONTINUE: 204 case SNDRV_SEQ_EVENT_STOP: 205 case SNDRV_SEQ_EVENT_QFRAME: 206 case SNDRV_SEQ_EVENT_TEMPO: 207 case SNDRV_SEQ_EVENT_TIMESIGN: 208 case SNDRV_SEQ_EVENT_KEYSIGN: 209 goto not_yet; 210 case SNDRV_SEQ_EVENT_SENSING: 211 break; 212 case SNDRV_SEQ_EVENT_CLIENT_START: 213 case SNDRV_SEQ_EVENT_CLIENT_EXIT: 214 case SNDRV_SEQ_EVENT_CLIENT_CHANGE: 215 case SNDRV_SEQ_EVENT_PORT_START: 216 case SNDRV_SEQ_EVENT_PORT_EXIT: 217 case SNDRV_SEQ_EVENT_PORT_CHANGE: 218 case SNDRV_SEQ_EVENT_ECHO: 219 not_yet: 220 default: 221 /*pr_debug("ALSA: seq_midi_emul: Unimplemented event %d\n", ev->type);*/ 222 break; 223 } 224 } 225 EXPORT_SYMBOL(snd_midi_process_event); 226 227 228 /* 229 * release note 230 */ 231 static void 232 note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, 233 int note, int vel) 234 { 235 if (chan->gm_hold) { 236 /* Hold this note until pedal is turned off */ 237 chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED; 238 } else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) { 239 /* Mark this note as release; it will be turned off when sostenuto 240 * is turned off */ 241 chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED; 242 } else { 243 chan->note[note] = 0; 244 if (ops->note_off) 245 ops->note_off(drv, note, vel, chan); 246 } 247 } 248 249 /* 250 * Do all driver independent operations for this controller and pass 251 * events that need to take place immediately to the driver. 252 */ 253 static void 254 do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chset, 255 struct snd_midi_channel *chan, int control, int value) 256 { 257 int i; 258 259 if (control >= ARRAY_SIZE(chan->control)) 260 return; 261 262 /* Switches */ 263 if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) { 264 /* These are all switches; either off or on so set to 0 or 127 */ 265 value = (value >= 64)? 127: 0; 266 } 267 chan->control[control] = value; 268 269 switch (control) { 270 case MIDI_CTL_SUSTAIN: 271 if (value == 0) { 272 /* Sustain has been released, turn off held notes */ 273 for (i = 0; i < 128; i++) { 274 if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) { 275 chan->note[i] = SNDRV_MIDI_NOTE_OFF; 276 if (ops->note_off) 277 ops->note_off(drv, i, 0, chan); 278 } 279 } 280 } 281 break; 282 case MIDI_CTL_PORTAMENTO: 283 break; 284 case MIDI_CTL_SOSTENUTO: 285 if (value) { 286 /* Mark each note that is currently held down */ 287 for (i = 0; i < 128; i++) { 288 if (chan->note[i] & SNDRV_MIDI_NOTE_ON) 289 chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO; 290 } 291 } else { 292 /* release all notes that were held */ 293 for (i = 0; i < 128; i++) { 294 if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) { 295 chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO; 296 if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) { 297 chan->note[i] = SNDRV_MIDI_NOTE_OFF; 298 if (ops->note_off) 299 ops->note_off(drv, i, 0, chan); 300 } 301 } 302 } 303 } 304 break; 305 case MIDI_CTL_MSB_DATA_ENTRY: 306 chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0; 307 /* fall through */ 308 case MIDI_CTL_LSB_DATA_ENTRY: 309 if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED) 310 rpn(ops, drv, chan, chset); 311 else 312 nrpn(ops, drv, chan, chset); 313 break; 314 case MIDI_CTL_REGIST_PARM_NUM_LSB: 315 case MIDI_CTL_REGIST_PARM_NUM_MSB: 316 chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED; 317 break; 318 case MIDI_CTL_NONREG_PARM_NUM_LSB: 319 case MIDI_CTL_NONREG_PARM_NUM_MSB: 320 chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED; 321 break; 322 323 case MIDI_CTL_ALL_SOUNDS_OFF: 324 all_sounds_off(ops, drv, chan); 325 break; 326 327 case MIDI_CTL_ALL_NOTES_OFF: 328 all_notes_off(ops, drv, chan); 329 break; 330 331 case MIDI_CTL_MSB_BANK: 332 if (chset->midi_mode == SNDRV_MIDI_MODE_XG) { 333 if (value == 127) 334 chan->drum_channel = 1; 335 else 336 chan->drum_channel = 0; 337 } 338 break; 339 case MIDI_CTL_LSB_BANK: 340 break; 341 342 case MIDI_CTL_RESET_CONTROLLERS: 343 snd_midi_reset_controllers(chan); 344 break; 345 346 case MIDI_CTL_SOFT_PEDAL: 347 case MIDI_CTL_LEGATO_FOOTSWITCH: 348 case MIDI_CTL_HOLD2: 349 case MIDI_CTL_SC1_SOUND_VARIATION: 350 case MIDI_CTL_SC2_TIMBRE: 351 case MIDI_CTL_SC3_RELEASE_TIME: 352 case MIDI_CTL_SC4_ATTACK_TIME: 353 case MIDI_CTL_SC5_BRIGHTNESS: 354 case MIDI_CTL_E1_REVERB_DEPTH: 355 case MIDI_CTL_E2_TREMOLO_DEPTH: 356 case MIDI_CTL_E3_CHORUS_DEPTH: 357 case MIDI_CTL_E4_DETUNE_DEPTH: 358 case MIDI_CTL_E5_PHASER_DEPTH: 359 goto notyet; 360 notyet: 361 default: 362 if (ops->control) 363 ops->control(drv, control, chan); 364 break; 365 } 366 } 367 368 369 /* 370 * initialize the MIDI status 371 */ 372 void 373 snd_midi_channel_set_clear(struct snd_midi_channel_set *chset) 374 { 375 int i; 376 377 chset->midi_mode = SNDRV_MIDI_MODE_GM; 378 chset->gs_master_volume = 127; 379 380 for (i = 0; i < chset->max_channels; i++) { 381 struct snd_midi_channel *chan = chset->channels + i; 382 memset(chan->note, 0, sizeof(chan->note)); 383 384 chan->midi_aftertouch = 0; 385 chan->midi_pressure = 0; 386 chan->midi_program = 0; 387 chan->midi_pitchbend = 0; 388 snd_midi_reset_controllers(chan); 389 chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */ 390 chan->gm_rpn_fine_tuning = 0; 391 chan->gm_rpn_coarse_tuning = 0; 392 393 if (i == 9) 394 chan->drum_channel = 1; 395 else 396 chan->drum_channel = 0; 397 } 398 } 399 EXPORT_SYMBOL(snd_midi_channel_set_clear); 400 401 /* 402 * Process a rpn message. 403 */ 404 static void 405 rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, 406 struct snd_midi_channel_set *chset) 407 { 408 int type; 409 int val; 410 411 if (chset->midi_mode != SNDRV_MIDI_MODE_NONE) { 412 type = (chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] << 8) | 413 chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB]; 414 val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) | 415 chan->control[MIDI_CTL_LSB_DATA_ENTRY]; 416 417 switch (type) { 418 case 0x0000: /* Pitch bend sensitivity */ 419 /* MSB only / 1 semitone per 128 */ 420 chan->gm_rpn_pitch_bend_range = val; 421 break; 422 423 case 0x0001: /* fine tuning: */ 424 /* MSB/LSB, 8192=center, 100/8192 cent step */ 425 chan->gm_rpn_fine_tuning = val - 8192; 426 break; 427 428 case 0x0002: /* coarse tuning */ 429 /* MSB only / 8192=center, 1 semitone per 128 */ 430 chan->gm_rpn_coarse_tuning = val - 8192; 431 break; 432 433 case 0x7F7F: /* "lock-in" RPN */ 434 /* ignored */ 435 break; 436 } 437 } 438 /* should call nrpn or rpn callback here.. */ 439 } 440 441 /* 442 * Process an nrpn message. 443 */ 444 static void 445 nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, 446 struct snd_midi_channel_set *chset) 447 { 448 /* parse XG NRPNs here if possible */ 449 if (ops->nrpn) 450 ops->nrpn(drv, chan, chset); 451 } 452 453 454 /* 455 * convert channel parameter in GS sysex 456 */ 457 static int 458 get_channel(unsigned char cmd) 459 { 460 int p = cmd & 0x0f; 461 if (p == 0) 462 p = 9; 463 else if (p < 10) 464 p--; 465 return p; 466 } 467 468 469 /* 470 * Process a sysex message. 471 */ 472 static void 473 sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len, 474 struct snd_midi_channel_set *chset) 475 { 476 /* GM on */ 477 static unsigned char gm_on_macro[] = { 478 0x7e,0x7f,0x09,0x01, 479 }; 480 /* XG on */ 481 static unsigned char xg_on_macro[] = { 482 0x43,0x10,0x4c,0x00,0x00,0x7e,0x00, 483 }; 484 /* GS prefix 485 * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off 486 * reverb mode: XX=0x01, YY=0x30, ZZ=0-7 487 * chorus mode: XX=0x01, YY=0x38, ZZ=0-7 488 * master vol: XX=0x00, YY=0x04, ZZ=0-127 489 */ 490 static unsigned char gs_pfx_macro[] = { 491 0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/ 492 }; 493 494 int parsed = SNDRV_MIDI_SYSEX_NOT_PARSED; 495 496 if (len <= 0 || buf[0] != 0xf0) 497 return; 498 /* skip first byte */ 499 buf++; 500 len--; 501 502 /* GM on */ 503 if (len >= (int)sizeof(gm_on_macro) && 504 memcmp(buf, gm_on_macro, sizeof(gm_on_macro)) == 0) { 505 if (chset->midi_mode != SNDRV_MIDI_MODE_GS && 506 chset->midi_mode != SNDRV_MIDI_MODE_XG) { 507 chset->midi_mode = SNDRV_MIDI_MODE_GM; 508 reset_all_channels(chset); 509 parsed = SNDRV_MIDI_SYSEX_GM_ON; 510 } 511 } 512 513 /* GS macros */ 514 else if (len >= 8 && 515 memcmp(buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) { 516 if (chset->midi_mode != SNDRV_MIDI_MODE_GS && 517 chset->midi_mode != SNDRV_MIDI_MODE_XG) 518 chset->midi_mode = SNDRV_MIDI_MODE_GS; 519 520 if (buf[5] == 0x00 && buf[6] == 0x7f && buf[7] == 0x00) { 521 /* GS reset */ 522 parsed = SNDRV_MIDI_SYSEX_GS_RESET; 523 reset_all_channels(chset); 524 } 525 526 else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x15) { 527 /* drum pattern */ 528 int p = get_channel(buf[5]); 529 if (p < chset->max_channels) { 530 parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL; 531 if (buf[7]) 532 chset->channels[p].drum_channel = 1; 533 else 534 chset->channels[p].drum_channel = 0; 535 } 536 537 } else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x21) { 538 /* program */ 539 int p = get_channel(buf[5]); 540 if (p < chset->max_channels && 541 ! chset->channels[p].drum_channel) { 542 parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL; 543 chset->channels[p].midi_program = buf[7]; 544 } 545 546 } else if (buf[5] == 0x01 && buf[6] == 0x30) { 547 /* reverb mode */ 548 parsed = SNDRV_MIDI_SYSEX_GS_REVERB_MODE; 549 chset->gs_reverb_mode = buf[7]; 550 551 } else if (buf[5] == 0x01 && buf[6] == 0x38) { 552 /* chorus mode */ 553 parsed = SNDRV_MIDI_SYSEX_GS_CHORUS_MODE; 554 chset->gs_chorus_mode = buf[7]; 555 556 } else if (buf[5] == 0x00 && buf[6] == 0x04) { 557 /* master volume */ 558 parsed = SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME; 559 chset->gs_master_volume = buf[7]; 560 561 } 562 } 563 564 /* XG on */ 565 else if (len >= (int)sizeof(xg_on_macro) && 566 memcmp(buf, xg_on_macro, sizeof(xg_on_macro)) == 0) { 567 int i; 568 chset->midi_mode = SNDRV_MIDI_MODE_XG; 569 parsed = SNDRV_MIDI_SYSEX_XG_ON; 570 /* reset CC#0 for drums */ 571 for (i = 0; i < chset->max_channels; i++) { 572 if (chset->channels[i].drum_channel) 573 chset->channels[i].control[MIDI_CTL_MSB_BANK] = 127; 574 else 575 chset->channels[i].control[MIDI_CTL_MSB_BANK] = 0; 576 } 577 } 578 579 if (ops->sysex) 580 ops->sysex(private, buf - 1, len + 1, parsed, chset); 581 } 582 583 /* 584 * all sound off 585 */ 586 static void 587 all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan) 588 { 589 int n; 590 591 if (! ops->note_terminate) 592 return; 593 for (n = 0; n < 128; n++) { 594 if (chan->note[n]) { 595 ops->note_terminate(drv, n, chan); 596 chan->note[n] = 0; 597 } 598 } 599 } 600 601 /* 602 * all notes off 603 */ 604 static void 605 all_notes_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan) 606 { 607 int n; 608 609 if (! ops->note_off) 610 return; 611 for (n = 0; n < 128; n++) { 612 if (chan->note[n] == SNDRV_MIDI_NOTE_ON) 613 note_off(ops, drv, chan, n, 0); 614 } 615 } 616 617 /* 618 * Initialise a single midi channel control block. 619 */ 620 static void snd_midi_channel_init(struct snd_midi_channel *p, int n) 621 { 622 if (p == NULL) 623 return; 624 625 memset(p, 0, sizeof(struct snd_midi_channel)); 626 p->private = NULL; 627 p->number = n; 628 629 snd_midi_reset_controllers(p); 630 p->gm_rpn_pitch_bend_range = 256; /* 2 semitones */ 631 p->gm_rpn_fine_tuning = 0; 632 p->gm_rpn_coarse_tuning = 0; 633 634 if (n == 9) 635 p->drum_channel = 1; /* Default ch 10 as drums */ 636 } 637 638 /* 639 * Allocate and initialise a set of midi channel control blocks. 640 */ 641 static struct snd_midi_channel *snd_midi_channel_init_set(int n) 642 { 643 struct snd_midi_channel *chan; 644 int i; 645 646 chan = kmalloc_array(n, sizeof(struct snd_midi_channel), GFP_KERNEL); 647 if (chan) { 648 for (i = 0; i < n; i++) 649 snd_midi_channel_init(chan+i, i); 650 } 651 652 return chan; 653 } 654 655 /* 656 * reset all midi channels 657 */ 658 static void 659 reset_all_channels(struct snd_midi_channel_set *chset) 660 { 661 int ch; 662 for (ch = 0; ch < chset->max_channels; ch++) { 663 struct snd_midi_channel *chan = chset->channels + ch; 664 snd_midi_reset_controllers(chan); 665 chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */ 666 chan->gm_rpn_fine_tuning = 0; 667 chan->gm_rpn_coarse_tuning = 0; 668 669 if (ch == 9) 670 chan->drum_channel = 1; 671 else 672 chan->drum_channel = 0; 673 } 674 } 675 676 677 /* 678 * Allocate and initialise a midi channel set. 679 */ 680 struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n) 681 { 682 struct snd_midi_channel_set *chset; 683 684 chset = kmalloc(sizeof(*chset), GFP_KERNEL); 685 if (chset) { 686 chset->channels = snd_midi_channel_init_set(n); 687 chset->private_data = NULL; 688 chset->max_channels = n; 689 } 690 return chset; 691 } 692 EXPORT_SYMBOL(snd_midi_channel_alloc_set); 693 694 /* 695 * Reset the midi controllers on a particular channel to default values. 696 */ 697 static void snd_midi_reset_controllers(struct snd_midi_channel *chan) 698 { 699 memset(chan->control, 0, sizeof(chan->control)); 700 chan->gm_volume = 127; 701 chan->gm_expression = 127; 702 chan->gm_pan = 64; 703 } 704 705 706 /* 707 * Free a midi channel set. 708 */ 709 void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) 710 { 711 if (chset == NULL) 712 return; 713 kfree(chset->channels); 714 kfree(chset); 715 } 716 EXPORT_SYMBOL(snd_midi_channel_free_set); 717