0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/init.h>
0019 #include <linux/slab.h>
0020 #include <linux/string.h>
0021 #include <linux/module.h>
0022 #include <sound/core.h>
0023 #include <sound/seq_kernel.h>
0024 #include <sound/seq_midi_emul.h>
0025 #include <sound/initval.h>
0026 #include <sound/asoundef.h>
0027
0028 MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe");
0029 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation.");
0030 MODULE_LICENSE("GPL");
0031
0032
0033 static void note_off(const struct snd_midi_op *ops, void *drv,
0034 struct snd_midi_channel *chan,
0035 int note, int vel);
0036 static void do_control(const struct snd_midi_op *ops, void *private,
0037 struct snd_midi_channel_set *chset,
0038 struct snd_midi_channel *chan,
0039 int control, int value);
0040 static void rpn(const struct snd_midi_op *ops, void *drv,
0041 struct snd_midi_channel *chan,
0042 struct snd_midi_channel_set *chset);
0043 static void nrpn(const struct snd_midi_op *ops, void *drv,
0044 struct snd_midi_channel *chan,
0045 struct snd_midi_channel_set *chset);
0046 static void sysex(const struct snd_midi_op *ops, void *private,
0047 unsigned char *sysex,
0048 int len, struct snd_midi_channel_set *chset);
0049 static void all_sounds_off(const struct snd_midi_op *ops, void *private,
0050 struct snd_midi_channel *chan);
0051 static void all_notes_off(const struct snd_midi_op *ops, void *private,
0052 struct snd_midi_channel *chan);
0053 static void snd_midi_reset_controllers(struct snd_midi_channel *chan);
0054 static void reset_all_channels(struct snd_midi_channel_set *chset);
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 void
0072 snd_midi_process_event(const struct snd_midi_op *ops,
0073 struct snd_seq_event *ev,
0074 struct snd_midi_channel_set *chanset)
0075 {
0076 struct snd_midi_channel *chan;
0077 void *drv;
0078 int dest_channel = 0;
0079
0080 if (ev == NULL || chanset == NULL) {
0081 pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n");
0082 return;
0083 }
0084 if (chanset->channels == NULL)
0085 return;
0086
0087 if (snd_seq_ev_is_channel_type(ev)) {
0088 dest_channel = ev->data.note.channel;
0089 if (dest_channel >= chanset->max_channels) {
0090 pr_debug("ALSA: seq_midi_emul: dest channel is %d, max is %d\n",
0091 dest_channel, chanset->max_channels);
0092 return;
0093 }
0094 }
0095
0096 chan = chanset->channels + dest_channel;
0097 drv = chanset->private_data;
0098
0099
0100 if (ev->type == SNDRV_SEQ_EVENT_NOTE)
0101 return;
0102
0103
0104
0105 if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0)
0106 ev->type = SNDRV_SEQ_EVENT_NOTEOFF;
0107
0108
0109 if (ev->type == SNDRV_SEQ_EVENT_NOTEON ||
0110 ev->type == SNDRV_SEQ_EVENT_NOTEOFF ||
0111 ev->type == SNDRV_SEQ_EVENT_KEYPRESS) {
0112 if (ev->data.note.note >= 128)
0113 return;
0114 }
0115
0116 switch (ev->type) {
0117 case SNDRV_SEQ_EVENT_NOTEON:
0118 if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) {
0119 if (ops->note_off)
0120 ops->note_off(drv, ev->data.note.note, 0, chan);
0121 }
0122 chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON;
0123 if (ops->note_on)
0124 ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan);
0125 break;
0126 case SNDRV_SEQ_EVENT_NOTEOFF:
0127 if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON))
0128 break;
0129 if (ops->note_off)
0130 note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity);
0131 break;
0132 case SNDRV_SEQ_EVENT_KEYPRESS:
0133 if (ops->key_press)
0134 ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan);
0135 break;
0136 case SNDRV_SEQ_EVENT_CONTROLLER:
0137 do_control(ops, drv, chanset, chan,
0138 ev->data.control.param, ev->data.control.value);
0139 break;
0140 case SNDRV_SEQ_EVENT_PGMCHANGE:
0141 chan->midi_program = ev->data.control.value;
0142 break;
0143 case SNDRV_SEQ_EVENT_PITCHBEND:
0144 chan->midi_pitchbend = ev->data.control.value;
0145 if (ops->control)
0146 ops->control(drv, MIDI_CTL_PITCHBEND, chan);
0147 break;
0148 case SNDRV_SEQ_EVENT_CHANPRESS:
0149 chan->midi_pressure = ev->data.control.value;
0150 if (ops->control)
0151 ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan);
0152 break;
0153 case SNDRV_SEQ_EVENT_CONTROL14:
0154
0155 if (ev->data.control.param < 32) {
0156
0157 chan->control[ev->data.control.param + 32] =
0158 ev->data.control.value & 0x7f;
0159 do_control(ops, drv, chanset, chan,
0160 ev->data.control.param,
0161 ((ev->data.control.value>>7) & 0x7f));
0162 } else
0163 do_control(ops, drv, chanset, chan,
0164 ev->data.control.param,
0165 ev->data.control.value);
0166 break;
0167 case SNDRV_SEQ_EVENT_NONREGPARAM:
0168
0169 chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
0170 chan->control[MIDI_CTL_MSB_DATA_ENTRY]
0171 = (ev->data.control.value >> 7) & 0x7f;
0172 chan->control[MIDI_CTL_LSB_DATA_ENTRY]
0173 = ev->data.control.value & 0x7f;
0174 chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB]
0175 = (ev->data.control.param >> 7) & 0x7f;
0176 chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB]
0177 = ev->data.control.param & 0x7f;
0178 nrpn(ops, drv, chan, chanset);
0179 break;
0180 case SNDRV_SEQ_EVENT_REGPARAM:
0181
0182 chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
0183 chan->control[MIDI_CTL_MSB_DATA_ENTRY]
0184 = (ev->data.control.value >> 7) & 0x7f;
0185 chan->control[MIDI_CTL_LSB_DATA_ENTRY]
0186 = ev->data.control.value & 0x7f;
0187 chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB]
0188 = (ev->data.control.param >> 7) & 0x7f;
0189 chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB]
0190 = ev->data.control.param & 0x7f;
0191 rpn(ops, drv, chan, chanset);
0192 break;
0193 case SNDRV_SEQ_EVENT_SYSEX:
0194 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) {
0195 unsigned char sysexbuf[64];
0196 int len;
0197 len = snd_seq_expand_var_event(ev, sizeof(sysexbuf), sysexbuf, 1, 0);
0198 if (len > 0)
0199 sysex(ops, drv, sysexbuf, len, chanset);
0200 }
0201 break;
0202 case SNDRV_SEQ_EVENT_SONGPOS:
0203 case SNDRV_SEQ_EVENT_SONGSEL:
0204 case SNDRV_SEQ_EVENT_CLOCK:
0205 case SNDRV_SEQ_EVENT_START:
0206 case SNDRV_SEQ_EVENT_CONTINUE:
0207 case SNDRV_SEQ_EVENT_STOP:
0208 case SNDRV_SEQ_EVENT_QFRAME:
0209 case SNDRV_SEQ_EVENT_TEMPO:
0210 case SNDRV_SEQ_EVENT_TIMESIGN:
0211 case SNDRV_SEQ_EVENT_KEYSIGN:
0212 goto not_yet;
0213 case SNDRV_SEQ_EVENT_SENSING:
0214 break;
0215 case SNDRV_SEQ_EVENT_CLIENT_START:
0216 case SNDRV_SEQ_EVENT_CLIENT_EXIT:
0217 case SNDRV_SEQ_EVENT_CLIENT_CHANGE:
0218 case SNDRV_SEQ_EVENT_PORT_START:
0219 case SNDRV_SEQ_EVENT_PORT_EXIT:
0220 case SNDRV_SEQ_EVENT_PORT_CHANGE:
0221 case SNDRV_SEQ_EVENT_ECHO:
0222 not_yet:
0223 default:
0224
0225 break;
0226 }
0227 }
0228 EXPORT_SYMBOL(snd_midi_process_event);
0229
0230
0231
0232
0233
0234 static void
0235 note_off(const struct snd_midi_op *ops, void *drv,
0236 struct snd_midi_channel *chan,
0237 int note, int vel)
0238 {
0239 if (chan->gm_hold) {
0240
0241 chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
0242 } else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) {
0243
0244
0245 chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
0246 } else {
0247 chan->note[note] = 0;
0248 if (ops->note_off)
0249 ops->note_off(drv, note, vel, chan);
0250 }
0251 }
0252
0253
0254
0255
0256
0257 static void
0258 do_control(const struct snd_midi_op *ops, void *drv,
0259 struct snd_midi_channel_set *chset,
0260 struct snd_midi_channel *chan, int control, int value)
0261 {
0262 int i;
0263
0264 if (control >= ARRAY_SIZE(chan->control))
0265 return;
0266
0267
0268 if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) {
0269
0270 value = (value >= 64)? 127: 0;
0271 }
0272 chan->control[control] = value;
0273
0274 switch (control) {
0275 case MIDI_CTL_SUSTAIN:
0276 if (value == 0) {
0277
0278 for (i = 0; i < 128; i++) {
0279 if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
0280 chan->note[i] = SNDRV_MIDI_NOTE_OFF;
0281 if (ops->note_off)
0282 ops->note_off(drv, i, 0, chan);
0283 }
0284 }
0285 }
0286 break;
0287 case MIDI_CTL_PORTAMENTO:
0288 break;
0289 case MIDI_CTL_SOSTENUTO:
0290 if (value) {
0291
0292 for (i = 0; i < 128; i++) {
0293 if (chan->note[i] & SNDRV_MIDI_NOTE_ON)
0294 chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO;
0295 }
0296 } else {
0297
0298 for (i = 0; i < 128; i++) {
0299 if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) {
0300 chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO;
0301 if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
0302 chan->note[i] = SNDRV_MIDI_NOTE_OFF;
0303 if (ops->note_off)
0304 ops->note_off(drv, i, 0, chan);
0305 }
0306 }
0307 }
0308 }
0309 break;
0310 case MIDI_CTL_MSB_DATA_ENTRY:
0311 chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0;
0312 fallthrough;
0313 case MIDI_CTL_LSB_DATA_ENTRY:
0314 if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED)
0315 rpn(ops, drv, chan, chset);
0316 else
0317 nrpn(ops, drv, chan, chset);
0318 break;
0319 case MIDI_CTL_REGIST_PARM_NUM_LSB:
0320 case MIDI_CTL_REGIST_PARM_NUM_MSB:
0321 chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED;
0322 break;
0323 case MIDI_CTL_NONREG_PARM_NUM_LSB:
0324 case MIDI_CTL_NONREG_PARM_NUM_MSB:
0325 chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED;
0326 break;
0327
0328 case MIDI_CTL_ALL_SOUNDS_OFF:
0329 all_sounds_off(ops, drv, chan);
0330 break;
0331
0332 case MIDI_CTL_ALL_NOTES_OFF:
0333 all_notes_off(ops, drv, chan);
0334 break;
0335
0336 case MIDI_CTL_MSB_BANK:
0337 if (chset->midi_mode == SNDRV_MIDI_MODE_XG) {
0338 if (value == 127)
0339 chan->drum_channel = 1;
0340 else
0341 chan->drum_channel = 0;
0342 }
0343 break;
0344 case MIDI_CTL_LSB_BANK:
0345 break;
0346
0347 case MIDI_CTL_RESET_CONTROLLERS:
0348 snd_midi_reset_controllers(chan);
0349 break;
0350
0351 case MIDI_CTL_SOFT_PEDAL:
0352 case MIDI_CTL_LEGATO_FOOTSWITCH:
0353 case MIDI_CTL_HOLD2:
0354 case MIDI_CTL_SC1_SOUND_VARIATION:
0355 case MIDI_CTL_SC2_TIMBRE:
0356 case MIDI_CTL_SC3_RELEASE_TIME:
0357 case MIDI_CTL_SC4_ATTACK_TIME:
0358 case MIDI_CTL_SC5_BRIGHTNESS:
0359 case MIDI_CTL_E1_REVERB_DEPTH:
0360 case MIDI_CTL_E2_TREMOLO_DEPTH:
0361 case MIDI_CTL_E3_CHORUS_DEPTH:
0362 case MIDI_CTL_E4_DETUNE_DEPTH:
0363 case MIDI_CTL_E5_PHASER_DEPTH:
0364 goto notyet;
0365 notyet:
0366 default:
0367 if (ops->control)
0368 ops->control(drv, control, chan);
0369 break;
0370 }
0371 }
0372
0373
0374
0375
0376
0377 void
0378 snd_midi_channel_set_clear(struct snd_midi_channel_set *chset)
0379 {
0380 int i;
0381
0382 chset->midi_mode = SNDRV_MIDI_MODE_GM;
0383 chset->gs_master_volume = 127;
0384
0385 for (i = 0; i < chset->max_channels; i++) {
0386 struct snd_midi_channel *chan = chset->channels + i;
0387 memset(chan->note, 0, sizeof(chan->note));
0388
0389 chan->midi_aftertouch = 0;
0390 chan->midi_pressure = 0;
0391 chan->midi_program = 0;
0392 chan->midi_pitchbend = 0;
0393 snd_midi_reset_controllers(chan);
0394 chan->gm_rpn_pitch_bend_range = 256;
0395 chan->gm_rpn_fine_tuning = 0;
0396 chan->gm_rpn_coarse_tuning = 0;
0397
0398 if (i == 9)
0399 chan->drum_channel = 1;
0400 else
0401 chan->drum_channel = 0;
0402 }
0403 }
0404 EXPORT_SYMBOL(snd_midi_channel_set_clear);
0405
0406
0407
0408
0409 static void
0410 rpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
0411 struct snd_midi_channel_set *chset)
0412 {
0413 int type;
0414 int val;
0415
0416 if (chset->midi_mode != SNDRV_MIDI_MODE_NONE) {
0417 type = (chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] << 8) |
0418 chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB];
0419 val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |
0420 chan->control[MIDI_CTL_LSB_DATA_ENTRY];
0421
0422 switch (type) {
0423 case 0x0000:
0424
0425 chan->gm_rpn_pitch_bend_range = val;
0426 break;
0427
0428 case 0x0001:
0429
0430 chan->gm_rpn_fine_tuning = val - 8192;
0431 break;
0432
0433 case 0x0002:
0434
0435 chan->gm_rpn_coarse_tuning = val - 8192;
0436 break;
0437
0438 case 0x7F7F:
0439
0440 break;
0441 }
0442 }
0443
0444 }
0445
0446
0447
0448
0449 static void
0450 nrpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
0451 struct snd_midi_channel_set *chset)
0452 {
0453
0454 if (ops->nrpn)
0455 ops->nrpn(drv, chan, chset);
0456 }
0457
0458
0459
0460
0461
0462 static int
0463 get_channel(unsigned char cmd)
0464 {
0465 int p = cmd & 0x0f;
0466 if (p == 0)
0467 p = 9;
0468 else if (p < 10)
0469 p--;
0470 return p;
0471 }
0472
0473
0474
0475
0476
0477 static void
0478 sysex(const struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
0479 struct snd_midi_channel_set *chset)
0480 {
0481
0482 static const unsigned char gm_on_macro[] = {
0483 0x7e,0x7f,0x09,0x01,
0484 };
0485
0486 static const unsigned char xg_on_macro[] = {
0487 0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
0488 };
0489
0490
0491
0492
0493
0494
0495 static const unsigned char gs_pfx_macro[] = {
0496 0x41,0x10,0x42,0x12,0x40,
0497 };
0498
0499 int parsed = SNDRV_MIDI_SYSEX_NOT_PARSED;
0500
0501 if (len <= 0 || buf[0] != 0xf0)
0502 return;
0503
0504 buf++;
0505 len--;
0506
0507
0508 if (len >= (int)sizeof(gm_on_macro) &&
0509 memcmp(buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
0510 if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&
0511 chset->midi_mode != SNDRV_MIDI_MODE_XG) {
0512 chset->midi_mode = SNDRV_MIDI_MODE_GM;
0513 reset_all_channels(chset);
0514 parsed = SNDRV_MIDI_SYSEX_GM_ON;
0515 }
0516 }
0517
0518
0519 else if (len >= 8 &&
0520 memcmp(buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
0521 if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&
0522 chset->midi_mode != SNDRV_MIDI_MODE_XG)
0523 chset->midi_mode = SNDRV_MIDI_MODE_GS;
0524
0525 if (buf[5] == 0x00 && buf[6] == 0x7f && buf[7] == 0x00) {
0526
0527 parsed = SNDRV_MIDI_SYSEX_GS_RESET;
0528 reset_all_channels(chset);
0529 }
0530
0531 else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x15) {
0532
0533 int p = get_channel(buf[5]);
0534 if (p < chset->max_channels) {
0535 parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;
0536 if (buf[7])
0537 chset->channels[p].drum_channel = 1;
0538 else
0539 chset->channels[p].drum_channel = 0;
0540 }
0541
0542 } else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x21) {
0543
0544 int p = get_channel(buf[5]);
0545 if (p < chset->max_channels &&
0546 ! chset->channels[p].drum_channel) {
0547 parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;
0548 chset->channels[p].midi_program = buf[7];
0549 }
0550
0551 } else if (buf[5] == 0x01 && buf[6] == 0x30) {
0552
0553 parsed = SNDRV_MIDI_SYSEX_GS_REVERB_MODE;
0554 chset->gs_reverb_mode = buf[7];
0555
0556 } else if (buf[5] == 0x01 && buf[6] == 0x38) {
0557
0558 parsed = SNDRV_MIDI_SYSEX_GS_CHORUS_MODE;
0559 chset->gs_chorus_mode = buf[7];
0560
0561 } else if (buf[5] == 0x00 && buf[6] == 0x04) {
0562
0563 parsed = SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME;
0564 chset->gs_master_volume = buf[7];
0565
0566 }
0567 }
0568
0569
0570 else if (len >= (int)sizeof(xg_on_macro) &&
0571 memcmp(buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
0572 int i;
0573 chset->midi_mode = SNDRV_MIDI_MODE_XG;
0574 parsed = SNDRV_MIDI_SYSEX_XG_ON;
0575
0576 for (i = 0; i < chset->max_channels; i++) {
0577 if (chset->channels[i].drum_channel)
0578 chset->channels[i].control[MIDI_CTL_MSB_BANK] = 127;
0579 else
0580 chset->channels[i].control[MIDI_CTL_MSB_BANK] = 0;
0581 }
0582 }
0583
0584 if (ops->sysex)
0585 ops->sysex(private, buf - 1, len + 1, parsed, chset);
0586 }
0587
0588
0589
0590
0591 static void
0592 all_sounds_off(const struct snd_midi_op *ops, void *drv,
0593 struct snd_midi_channel *chan)
0594 {
0595 int n;
0596
0597 if (! ops->note_terminate)
0598 return;
0599 for (n = 0; n < 128; n++) {
0600 if (chan->note[n]) {
0601 ops->note_terminate(drv, n, chan);
0602 chan->note[n] = 0;
0603 }
0604 }
0605 }
0606
0607
0608
0609
0610 static void
0611 all_notes_off(const struct snd_midi_op *ops, void *drv,
0612 struct snd_midi_channel *chan)
0613 {
0614 int n;
0615
0616 if (! ops->note_off)
0617 return;
0618 for (n = 0; n < 128; n++) {
0619 if (chan->note[n] == SNDRV_MIDI_NOTE_ON)
0620 note_off(ops, drv, chan, n, 0);
0621 }
0622 }
0623
0624
0625
0626
0627 static void snd_midi_channel_init(struct snd_midi_channel *p, int n)
0628 {
0629 if (p == NULL)
0630 return;
0631
0632 memset(p, 0, sizeof(struct snd_midi_channel));
0633 p->private = NULL;
0634 p->number = n;
0635
0636 snd_midi_reset_controllers(p);
0637 p->gm_rpn_pitch_bend_range = 256;
0638 p->gm_rpn_fine_tuning = 0;
0639 p->gm_rpn_coarse_tuning = 0;
0640
0641 if (n == 9)
0642 p->drum_channel = 1;
0643 }
0644
0645
0646
0647
0648 static struct snd_midi_channel *snd_midi_channel_init_set(int n)
0649 {
0650 struct snd_midi_channel *chan;
0651 int i;
0652
0653 chan = kmalloc_array(n, sizeof(struct snd_midi_channel), GFP_KERNEL);
0654 if (chan) {
0655 for (i = 0; i < n; i++)
0656 snd_midi_channel_init(chan+i, i);
0657 }
0658
0659 return chan;
0660 }
0661
0662
0663
0664
0665 static void
0666 reset_all_channels(struct snd_midi_channel_set *chset)
0667 {
0668 int ch;
0669 for (ch = 0; ch < chset->max_channels; ch++) {
0670 struct snd_midi_channel *chan = chset->channels + ch;
0671 snd_midi_reset_controllers(chan);
0672 chan->gm_rpn_pitch_bend_range = 256;
0673 chan->gm_rpn_fine_tuning = 0;
0674 chan->gm_rpn_coarse_tuning = 0;
0675
0676 if (ch == 9)
0677 chan->drum_channel = 1;
0678 else
0679 chan->drum_channel = 0;
0680 }
0681 }
0682
0683
0684
0685
0686
0687 struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
0688 {
0689 struct snd_midi_channel_set *chset;
0690
0691 chset = kmalloc(sizeof(*chset), GFP_KERNEL);
0692 if (chset) {
0693 chset->channels = snd_midi_channel_init_set(n);
0694 chset->private_data = NULL;
0695 chset->max_channels = n;
0696 }
0697 return chset;
0698 }
0699 EXPORT_SYMBOL(snd_midi_channel_alloc_set);
0700
0701
0702
0703
0704 static void snd_midi_reset_controllers(struct snd_midi_channel *chan)
0705 {
0706 memset(chan->control, 0, sizeof(chan->control));
0707 chan->gm_volume = 127;
0708 chan->gm_expression = 127;
0709 chan->gm_pan = 64;
0710 }
0711
0712
0713
0714
0715
0716 void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
0717 {
0718 if (chset == NULL)
0719 return;
0720 kfree(chset->channels);
0721 kfree(chset);
0722 }
0723 EXPORT_SYMBOL(snd_midi_channel_free_set);