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