0001
0002
0003
0004
0005
0006
0007
0008 #undef DEBUG_ALLOC
0009 #undef DEBUG_MIDI
0010
0011 #include "opl3_voice.h"
0012 #include <sound/asoundef.h>
0013
0014 static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
0015 struct snd_midi_channel *chan);
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 static const char opl3_volume_table[128] =
0027 {
0028 -63, -48, -40, -35, -32, -29, -27, -26,
0029 -24, -23, -21, -20, -19, -18, -18, -17,
0030 -16, -15, -15, -14, -13, -13, -12, -12,
0031 -11, -11, -10, -10, -10, -9, -9, -8,
0032 -8, -8, -7, -7, -7, -6, -6, -6,
0033 -5, -5, -5, -5, -4, -4, -4, -4,
0034 -3, -3, -3, -3, -2, -2, -2, -2,
0035 -2, -1, -1, -1, -1, 0, 0, 0,
0036 0, 0, 0, 1, 1, 1, 1, 1,
0037 1, 2, 2, 2, 2, 2, 2, 2,
0038 3, 3, 3, 3, 3, 3, 3, 4,
0039 4, 4, 4, 4, 4, 4, 4, 5,
0040 5, 5, 5, 5, 5, 5, 5, 5,
0041 6, 6, 6, 6, 6, 6, 6, 6,
0042 6, 7, 7, 7, 7, 7, 7, 7,
0043 7, 7, 7, 8, 8, 8, 8, 8
0044 };
0045
0046 void snd_opl3_calc_volume(unsigned char *volbyte, int vel,
0047 struct snd_midi_channel *chan)
0048 {
0049 int oldvol, newvol, n;
0050 int volume;
0051
0052 volume = (vel * chan->gm_volume * chan->gm_expression) / (127*127);
0053 if (volume > 127)
0054 volume = 127;
0055
0056 oldvol = OPL3_TOTAL_LEVEL_MASK - (*volbyte & OPL3_TOTAL_LEVEL_MASK);
0057
0058 newvol = opl3_volume_table[volume] + oldvol;
0059 if (newvol > OPL3_TOTAL_LEVEL_MASK)
0060 newvol = OPL3_TOTAL_LEVEL_MASK;
0061 else if (newvol < 0)
0062 newvol = 0;
0063
0064 n = OPL3_TOTAL_LEVEL_MASK - (newvol & OPL3_TOTAL_LEVEL_MASK);
0065
0066 *volbyte = (*volbyte & OPL3_KSL_MASK) | (n & OPL3_TOTAL_LEVEL_MASK);
0067 }
0068
0069
0070
0071
0072 static const short opl3_note_table[16] =
0073 {
0074 305, 323,
0075 343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647,
0076 686, 726
0077 };
0078
0079 static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum,
0080 int note, struct snd_midi_channel *chan)
0081 {
0082 int block = ((note / 12) & 0x07) - 1;
0083 int idx = (note % 12) + 2;
0084 int freq;
0085
0086 if (chan->midi_pitchbend) {
0087 int pitchbend = chan->midi_pitchbend;
0088 int segment;
0089
0090 if (pitchbend < -0x2000)
0091 pitchbend = -0x2000;
0092 if (pitchbend > 0x1FFF)
0093 pitchbend = 0x1FFF;
0094
0095 segment = pitchbend / 0x1000;
0096 freq = opl3_note_table[idx+segment];
0097 freq += ((opl3_note_table[idx+segment+1] - freq) *
0098 (pitchbend % 0x1000)) / 0x1000;
0099 } else {
0100 freq = opl3_note_table[idx];
0101 }
0102
0103 *fnum = (unsigned char) freq;
0104 *blocknum = ((freq >> 8) & OPL3_FNUM_HIGH_MASK) |
0105 ((block << 2) & OPL3_BLOCKNUM_MASK);
0106 }
0107
0108
0109 #ifdef DEBUG_ALLOC
0110 static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) {
0111 int i;
0112 char *str = "x.24";
0113
0114 printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
0115 for (i = 0; i < opl3->max_voices; i++)
0116 printk(KERN_CONT "%c", *(str + opl3->voices[i].state + 1));
0117 printk(KERN_CONT "\n");
0118 }
0119 #endif
0120
0121
0122
0123
0124 static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
0125 struct snd_midi_channel *chan) {
0126 int chan_4op_1;
0127 int chan_4op_2;
0128
0129 struct snd_opl3_voice *vp, *vp2;
0130 unsigned int voice_time;
0131 int i;
0132
0133 #ifdef DEBUG_ALLOC
0134 char *alloc_type[3] = { "FREE ", "CHEAP ", "EXPENSIVE" };
0135 #endif
0136
0137
0138 enum {
0139 FREE = 0, CHEAP, EXPENSIVE, END
0140 };
0141
0142
0143 struct best {
0144 unsigned int time;
0145 int voice;
0146 } best[END];
0147 struct best *bp;
0148
0149 for (i = 0; i < END; i++) {
0150 best[i].time = (unsigned int)(-1);
0151 best[i].voice = -1;
0152 }
0153
0154
0155 for (i = 0; i < opl3->max_voices; i++) {
0156 vp = &opl3->voices[i];
0157
0158 if (vp->state == SNDRV_OPL3_ST_NOT_AVAIL)
0159
0160
0161 continue;
0162
0163 voice_time = vp->time;
0164 bp = best;
0165
0166 chan_4op_1 = ((i < 3) || (i > 8 && i < 12));
0167 chan_4op_2 = ((i > 2 && i < 6) || (i > 11 && i < 15));
0168 if (instr_4op) {
0169
0170
0171 if (!chan_4op_1)
0172 continue;
0173
0174 if (vp->state)
0175
0176 bp++;
0177
0178
0179 vp2 = &opl3->voices[i + 3];
0180 if (vp2->state == SNDRV_OPL3_ST_ON_2OP) {
0181
0182 bp++;
0183 voice_time = max(voice_time, vp2->time);
0184 }
0185 } else {
0186
0187 if ((chan_4op_1) || (chan_4op_2))
0188
0189 bp++;
0190 else if (vp->state)
0191
0192 bp++;
0193
0194 if (vp->state)
0195 bp++;
0196 }
0197 if (voice_time < bp->time) {
0198 bp->time = voice_time;
0199 bp->voice = i;
0200 }
0201 }
0202
0203 for (i = 0; i < END; i++) {
0204 if (best[i].voice >= 0) {
0205 #ifdef DEBUG_ALLOC
0206 printk(KERN_DEBUG "%s %iop allocation on voice %i\n",
0207 alloc_type[i], instr_4op ? 4 : 2,
0208 best[i].voice);
0209 #endif
0210 return best[i].voice;
0211 }
0212 }
0213
0214 return -1;
0215 }
0216
0217
0218
0219
0220
0221
0222 void snd_opl3_timer_func(struct timer_list *t)
0223 {
0224
0225 struct snd_opl3 *opl3 = from_timer(opl3, t, tlist);
0226 unsigned long flags;
0227 int again = 0;
0228 int i;
0229
0230 spin_lock_irqsave(&opl3->voice_lock, flags);
0231 for (i = 0; i < opl3->max_voices; i++) {
0232 struct snd_opl3_voice *vp = &opl3->voices[i];
0233 if (vp->state > 0 && vp->note_off_check) {
0234 if (vp->note_off == jiffies)
0235 snd_opl3_note_off_unsafe(opl3, vp->note, 0,
0236 vp->chan);
0237 else
0238 again++;
0239 }
0240 }
0241 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0242
0243 spin_lock_irqsave(&opl3->sys_timer_lock, flags);
0244 if (again)
0245 mod_timer(&opl3->tlist, jiffies + 1);
0246 else
0247 opl3->sys_timer_status = 0;
0248 spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
0249 }
0250
0251
0252
0253
0254 static void snd_opl3_start_timer(struct snd_opl3 *opl3)
0255 {
0256 unsigned long flags;
0257 spin_lock_irqsave(&opl3->sys_timer_lock, flags);
0258 if (! opl3->sys_timer_status) {
0259 mod_timer(&opl3->tlist, jiffies + 1);
0260 opl3->sys_timer_status = 1;
0261 }
0262 spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
0263 }
0264
0265
0266
0267
0268 static const int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
0269 0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14
0270 };
0271
0272
0273
0274
0275 void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
0276 {
0277 struct snd_opl3 *opl3;
0278 int instr_4op;
0279
0280 int voice;
0281 struct snd_opl3_voice *vp, *vp2;
0282 unsigned short connect_mask;
0283 unsigned char connection;
0284 unsigned char vol_op[4];
0285
0286 int extra_prg = 0;
0287
0288 unsigned short reg_side;
0289 unsigned char op_offset;
0290 unsigned char voice_offset;
0291 unsigned short opl3_reg;
0292 unsigned char reg_val;
0293 unsigned char prg, bank;
0294
0295 int key = note;
0296 unsigned char fnum, blocknum;
0297 int i;
0298
0299 struct fm_patch *patch;
0300 struct fm_instrument *fm;
0301 unsigned long flags;
0302
0303 opl3 = p;
0304
0305 #ifdef DEBUG_MIDI
0306 snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n",
0307 chan->number, chan->midi_program, note, vel);
0308 #endif
0309
0310
0311
0312 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
0313 if (chan->drum_channel) {
0314
0315 bank = 128;
0316 prg = note;
0317 } else {
0318 bank = chan->gm_bank_select;
0319 prg = chan->midi_program;
0320 }
0321 } else {
0322
0323 if (chan->number >= MAX_OPL3_VOICES)
0324 return;
0325
0326
0327 bank = 127;
0328 prg = chan->midi_program;
0329 }
0330
0331 spin_lock_irqsave(&opl3->voice_lock, flags);
0332
0333 if (use_internal_drums) {
0334 snd_opl3_drum_switch(opl3, note, vel, 1, chan);
0335 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0336 return;
0337 }
0338
0339 __extra_prg:
0340 patch = snd_opl3_find_patch(opl3, prg, bank, 0);
0341 if (!patch) {
0342 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0343 return;
0344 }
0345
0346 fm = &patch->inst;
0347 switch (patch->type) {
0348 case FM_PATCH_OPL2:
0349 instr_4op = 0;
0350 break;
0351 case FM_PATCH_OPL3:
0352 if (opl3->hardware >= OPL3_HW_OPL3) {
0353 instr_4op = 1;
0354 break;
0355 }
0356 fallthrough;
0357 default:
0358 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0359 return;
0360 }
0361 #ifdef DEBUG_MIDI
0362 snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n",
0363 instr_4op ? 3 : 2, patch->name);
0364 #endif
0365
0366
0367 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
0368 voice = opl3_get_voice(opl3, instr_4op, chan);
0369 } else {
0370
0371 voice = snd_opl3_oss_map[chan->number];
0372 }
0373
0374 if (voice < 0) {
0375 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0376 return;
0377 }
0378
0379 if (voice < MAX_OPL2_VOICES) {
0380
0381 reg_side = OPL3_LEFT;
0382 voice_offset = voice;
0383 connect_mask = (OPL3_LEFT_4OP_0 << voice_offset) & 0x07;
0384 } else {
0385
0386 reg_side = OPL3_RIGHT;
0387 voice_offset = voice - MAX_OPL2_VOICES;
0388 connect_mask = (OPL3_RIGHT_4OP_0 << voice_offset) & 0x38;
0389 }
0390
0391
0392 vp = &opl3->voices[voice];
0393 if (vp->state > 0) {
0394 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0395 reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
0396 opl3->command(opl3, opl3_reg, reg_val);
0397 }
0398 if (instr_4op) {
0399 vp2 = &opl3->voices[voice + 3];
0400 if (vp2->state > 0) {
0401 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK +
0402 voice_offset + 3);
0403 reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
0404 opl3->command(opl3, opl3_reg, reg_val);
0405 }
0406 }
0407
0408
0409 if (instr_4op) {
0410 if ((opl3->connection_reg ^ connect_mask) & connect_mask) {
0411 opl3->connection_reg |= connect_mask;
0412
0413 opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT;
0414 opl3->command(opl3, opl3_reg, opl3->connection_reg);
0415 }
0416 } else {
0417 if ((opl3->connection_reg ^ ~connect_mask) & connect_mask) {
0418 opl3->connection_reg &= ~connect_mask;
0419
0420 opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT;
0421 opl3->command(opl3, opl3_reg, opl3->connection_reg);
0422 }
0423 }
0424
0425 #ifdef DEBUG_MIDI
0426 snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n",
0427 opl3->connection_reg);
0428 #endif
0429
0430
0431
0432
0433 for (i = 0; i < (instr_4op ? 4 : 2); i++)
0434 vol_op[i] = fm->op[i].ksl_level;
0435
0436 connection = fm->feedback_connection[0] & 0x01;
0437 if (instr_4op) {
0438 connection <<= 1;
0439 connection |= fm->feedback_connection[1] & 0x01;
0440
0441 snd_opl3_calc_volume(&vol_op[3], vel, chan);
0442 switch (connection) {
0443 case 0x03:
0444 snd_opl3_calc_volume(&vol_op[2], vel, chan);
0445 fallthrough;
0446 case 0x02:
0447 snd_opl3_calc_volume(&vol_op[0], vel, chan);
0448 break;
0449 case 0x01:
0450 snd_opl3_calc_volume(&vol_op[1], vel, chan);
0451 }
0452 } else {
0453 snd_opl3_calc_volume(&vol_op[1], vel, chan);
0454 if (connection)
0455 snd_opl3_calc_volume(&vol_op[0], vel, chan);
0456 }
0457
0458
0459 for (i = 0; i < (instr_4op ? 4 : 2); i++) {
0460 #ifdef DEBUG_MIDI
0461 snd_printk(KERN_DEBUG " --> programming operator %i\n", i);
0462 #endif
0463 op_offset = snd_opl3_regmap[voice_offset][i];
0464
0465
0466 reg_val = fm->op[i].am_vib;
0467 opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
0468 opl3->command(opl3, opl3_reg, reg_val);
0469
0470
0471 reg_val = vol_op[i];
0472 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
0473 opl3->command(opl3, opl3_reg, reg_val);
0474
0475
0476 reg_val = fm->op[i].attack_decay;
0477 opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
0478 opl3->command(opl3, opl3_reg, reg_val);
0479
0480
0481 reg_val = fm->op[i].sustain_release;
0482 opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
0483 opl3->command(opl3, opl3_reg, reg_val);
0484
0485
0486 reg_val = fm->op[i].wave_select;
0487 opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset);
0488 opl3->command(opl3, opl3_reg, reg_val);
0489 }
0490
0491
0492 reg_val = fm->feedback_connection[0];
0493
0494 reg_val |= OPL3_STEREO_BITS;
0495 if (chan->gm_pan < 43)
0496 reg_val &= ~OPL3_VOICE_TO_RIGHT;
0497 if (chan->gm_pan > 85)
0498 reg_val &= ~OPL3_VOICE_TO_LEFT;
0499 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
0500 opl3->command(opl3, opl3_reg, reg_val);
0501
0502 if (instr_4op) {
0503
0504 reg_val = fm->feedback_connection[1] & OPL3_CONNECTION_BIT;
0505
0506 reg_val |= OPL3_STEREO_BITS;
0507 if (chan->gm_pan < 43)
0508 reg_val &= ~OPL3_VOICE_TO_RIGHT;
0509 if (chan->gm_pan > 85)
0510 reg_val &= ~OPL3_VOICE_TO_LEFT;
0511 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION +
0512 voice_offset + 3);
0513 opl3->command(opl3, opl3_reg, reg_val);
0514 }
0515
0516
0517
0518
0519
0520
0521 if (fm->fix_key)
0522 note = fm->fix_key;
0523
0524
0525
0526 if (fm->trnsps)
0527 note += (fm->trnsps - 64);
0528
0529 snd_opl3_calc_pitch(&fnum, &blocknum, note, chan);
0530
0531
0532 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
0533 opl3->command(opl3, opl3_reg, fnum);
0534
0535 opl3->voices[voice].keyon_reg = blocknum;
0536
0537
0538 blocknum |= OPL3_KEYON_BIT;
0539
0540 #ifdef DEBUG_MIDI
0541 snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice);
0542 #endif
0543
0544 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0545 opl3->command(opl3, opl3_reg, blocknum);
0546
0547
0548 if (fm->fix_dur) {
0549 opl3->voices[voice].note_off = jiffies +
0550 (fm->fix_dur * HZ) / 100;
0551 snd_opl3_start_timer(opl3);
0552 opl3->voices[voice].note_off_check = 1;
0553 } else
0554 opl3->voices[voice].note_off_check = 0;
0555
0556
0557 extra_prg = (extra_prg) ? 0 : fm->modes;
0558
0559
0560 vp->time = opl3->use_time++;
0561 vp->note = key;
0562 vp->chan = chan;
0563
0564 if (instr_4op) {
0565 vp->state = SNDRV_OPL3_ST_ON_4OP;
0566
0567 vp2 = &opl3->voices[voice + 3];
0568 vp2->time = opl3->use_time++;
0569 vp2->note = key;
0570 vp2->chan = chan;
0571 vp2->state = SNDRV_OPL3_ST_NOT_AVAIL;
0572 } else {
0573 if (vp->state == SNDRV_OPL3_ST_ON_4OP) {
0574
0575 vp2 = &opl3->voices[voice + 3];
0576 vp2->time = opl3->use_time++;
0577 vp2->state = SNDRV_OPL3_ST_OFF;
0578 }
0579 vp->state = SNDRV_OPL3_ST_ON_2OP;
0580 }
0581
0582 #ifdef DEBUG_ALLOC
0583 debug_alloc(opl3, "note on ", voice);
0584 #endif
0585
0586
0587 if (extra_prg) {
0588 if (extra_prg > 128) {
0589 bank = 128;
0590
0591 prg = extra_prg - 128 + 35 - 1;
0592 } else {
0593 bank = 0;
0594 prg = extra_prg - 1;
0595 }
0596 #ifdef DEBUG_MIDI
0597 snd_printk(KERN_DEBUG " *** allocating extra program\n");
0598 #endif
0599 goto __extra_prg;
0600 }
0601 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0602 }
0603
0604 static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice)
0605 {
0606 unsigned short reg_side;
0607 unsigned char voice_offset;
0608 unsigned short opl3_reg;
0609
0610 struct snd_opl3_voice *vp, *vp2;
0611
0612 if (snd_BUG_ON(voice >= MAX_OPL3_VOICES))
0613 return;
0614
0615 vp = &opl3->voices[voice];
0616 if (voice < MAX_OPL2_VOICES) {
0617
0618 reg_side = OPL3_LEFT;
0619 voice_offset = voice;
0620 } else {
0621
0622 reg_side = OPL3_RIGHT;
0623 voice_offset = voice - MAX_OPL2_VOICES;
0624 }
0625
0626
0627 #ifdef DEBUG_MIDI
0628 snd_printk(KERN_DEBUG " --> kill voice %i\n", voice);
0629 #endif
0630 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0631
0632 opl3->command(opl3, opl3_reg, vp->keyon_reg);
0633
0634
0635 vp->time = opl3->use_time++;
0636
0637 if (vp->state == SNDRV_OPL3_ST_ON_4OP) {
0638 vp2 = &opl3->voices[voice + 3];
0639
0640 vp2->time = opl3->use_time++;
0641 vp2->state = SNDRV_OPL3_ST_OFF;
0642 }
0643 vp->state = SNDRV_OPL3_ST_OFF;
0644 #ifdef DEBUG_ALLOC
0645 debug_alloc(opl3, "note off", voice);
0646 #endif
0647
0648 }
0649
0650
0651
0652
0653 static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
0654 struct snd_midi_channel *chan)
0655 {
0656 struct snd_opl3 *opl3;
0657
0658 int voice;
0659 struct snd_opl3_voice *vp;
0660
0661 opl3 = p;
0662
0663 #ifdef DEBUG_MIDI
0664 snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n",
0665 chan->number, chan->midi_program, note);
0666 #endif
0667
0668 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
0669 if (chan->drum_channel && use_internal_drums) {
0670 snd_opl3_drum_switch(opl3, note, vel, 0, chan);
0671 return;
0672 }
0673
0674
0675 for (voice = 0; voice < opl3->max_voices; voice++) {
0676 vp = &opl3->voices[voice];
0677 if (vp->state > 0 && vp->chan == chan && vp->note == note) {
0678 snd_opl3_kill_voice(opl3, voice);
0679 }
0680 }
0681 } else {
0682
0683 if (chan->number < MAX_OPL3_VOICES) {
0684 voice = snd_opl3_oss_map[chan->number];
0685 snd_opl3_kill_voice(opl3, voice);
0686 }
0687 }
0688 }
0689
0690 void snd_opl3_note_off(void *p, int note, int vel,
0691 struct snd_midi_channel *chan)
0692 {
0693 struct snd_opl3 *opl3 = p;
0694 unsigned long flags;
0695
0696 spin_lock_irqsave(&opl3->voice_lock, flags);
0697 snd_opl3_note_off_unsafe(p, note, vel, chan);
0698 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0699 }
0700
0701
0702
0703
0704 void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
0705 {
0706 #ifdef DEBUG_MIDI
0707 snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n",
0708 chan->number, chan->midi_program);
0709 #endif
0710 }
0711
0712
0713
0714
0715 void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan)
0716 {
0717 #ifdef DEBUG_MIDI
0718 snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n",
0719 chan->number, chan->midi_program);
0720 #endif
0721 }
0722
0723 static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice)
0724 {
0725 unsigned short reg_side;
0726 unsigned char voice_offset;
0727 unsigned short opl3_reg;
0728
0729 unsigned char fnum, blocknum;
0730
0731 struct snd_opl3_voice *vp;
0732
0733 if (snd_BUG_ON(voice >= MAX_OPL3_VOICES))
0734 return;
0735
0736 vp = &opl3->voices[voice];
0737 if (vp->chan == NULL)
0738 return;
0739
0740 if (voice < MAX_OPL2_VOICES) {
0741
0742 reg_side = OPL3_LEFT;
0743 voice_offset = voice;
0744 } else {
0745
0746 reg_side = OPL3_RIGHT;
0747 voice_offset = voice - MAX_OPL2_VOICES;
0748 }
0749
0750 snd_opl3_calc_pitch(&fnum, &blocknum, vp->note, vp->chan);
0751
0752
0753 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
0754 opl3->command(opl3, opl3_reg, fnum);
0755
0756 vp->keyon_reg = blocknum;
0757
0758
0759 blocknum |= OPL3_KEYON_BIT;
0760
0761
0762 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0763 opl3->command(opl3, opl3_reg, blocknum);
0764
0765 vp->time = opl3->use_time++;
0766 }
0767
0768
0769
0770
0771 static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel *chan)
0772 {
0773 int voice;
0774 struct snd_opl3_voice *vp;
0775
0776 unsigned long flags;
0777
0778 spin_lock_irqsave(&opl3->voice_lock, flags);
0779
0780 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
0781 for (voice = 0; voice < opl3->max_voices; voice++) {
0782 vp = &opl3->voices[voice];
0783 if (vp->state > 0 && vp->chan == chan) {
0784 snd_opl3_update_pitch(opl3, voice);
0785 }
0786 }
0787 } else {
0788
0789 if (chan->number < MAX_OPL3_VOICES) {
0790 voice = snd_opl3_oss_map[chan->number];
0791 snd_opl3_update_pitch(opl3, voice);
0792 }
0793 }
0794 spin_unlock_irqrestore(&opl3->voice_lock, flags);
0795 }
0796
0797
0798
0799
0800
0801 void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan)
0802 {
0803 struct snd_opl3 *opl3;
0804
0805 opl3 = p;
0806 #ifdef DEBUG_MIDI
0807 snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n",
0808 type, chan->number, chan->midi_program);
0809 #endif
0810
0811 switch (type) {
0812 case MIDI_CTL_MSB_MODWHEEL:
0813 if (chan->control[MIDI_CTL_MSB_MODWHEEL] > 63)
0814 opl3->drum_reg |= OPL3_VIBRATO_DEPTH;
0815 else
0816 opl3->drum_reg &= ~OPL3_VIBRATO_DEPTH;
0817 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
0818 opl3->drum_reg);
0819 break;
0820 case MIDI_CTL_E2_TREMOLO_DEPTH:
0821 if (chan->control[MIDI_CTL_E2_TREMOLO_DEPTH] > 63)
0822 opl3->drum_reg |= OPL3_TREMOLO_DEPTH;
0823 else
0824 opl3->drum_reg &= ~OPL3_TREMOLO_DEPTH;
0825 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
0826 opl3->drum_reg);
0827 break;
0828 case MIDI_CTL_PITCHBEND:
0829 snd_opl3_pitch_ctrl(opl3, chan);
0830 break;
0831 }
0832 }
0833
0834
0835
0836
0837 void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan,
0838 struct snd_midi_channel_set *chset)
0839 {
0840 #ifdef DEBUG_MIDI
0841 snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n",
0842 chan->number, chan->midi_program);
0843 #endif
0844 }
0845
0846
0847
0848
0849 void snd_opl3_sysex(void *p, unsigned char *buf, int len,
0850 int parsed, struct snd_midi_channel_set *chset)
0851 {
0852 #ifdef DEBUG_MIDI
0853 snd_printk(KERN_DEBUG "SYSEX\n");
0854 #endif
0855 }