Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) by Uros Bizjak <uros@kss-loka.si>
0004  *
0005  *  Midi synth routines for OPL2/OPL3/OPL4 FM
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  * The next table looks magical, but it certainly is not. Its values have
0018  * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception
0019  * for i=0. This log-table converts a linear volume-scaling (0..127) to a
0020  * logarithmic scaling as present in the FM-synthesizer chips. so :    Volume
0021  * 64 =  0 db = relative volume  0 and:    Volume 32 = -6 db = relative
0022  * volume -8 it was implemented as a table because it is only 128 bytes and
0023  * it saves a lot of log() calculations. (Rob Hooft <hooft@chem.ruu.nl>)
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  * Converts the note frequency to block and fnum values for the FM chip
0071  */
0072 static const short opl3_note_table[16] =
0073 {
0074     305, 323,   /* for pitch bending, -2 semitones */
0075     343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647,
0076     686, 726    /* for pitch bending, +2 semitones */
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  * Get a FM voice (channel) to play a note on.
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;     /* first voice for 4op instrument */
0127     int chan_4op_2;     /* second voice for 4op instrument */
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     /* This is our "allocation cost" table */
0138     enum {
0139         FREE = 0, CHEAP, EXPENSIVE, END
0140     };
0141 
0142     /* Keeps track of what we are finding */
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); /* XXX MAX_?INT really */
0151         best[i].voice = -1;
0152     }
0153 
0154     /* Look through all the channels for the most suitable. */
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           /* skip unavailable channels, allocated by
0160              drum voices or by bounded 4op voices) */
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             /* allocate 4op voice */
0170             /* skip channels unavailable to 4op instrument */
0171             if (!chan_4op_1)
0172                 continue;
0173 
0174             if (vp->state)
0175                 /* kill one voice, CHEAP */
0176                 bp++;
0177             /* get state of bounded 2op channel
0178                to be allocated for 4op instrument */
0179             vp2 = &opl3->voices[i + 3];
0180             if (vp2->state == SNDRV_OPL3_ST_ON_2OP) {
0181                 /* kill two voices, EXPENSIVE */
0182                 bp++;
0183                 voice_time = max(voice_time, vp2->time);
0184             }
0185         } else {
0186             /* allocate 2op voice */
0187             if ((chan_4op_1) || (chan_4op_2))
0188                 /* use bounded channels for 2op, CHEAP */
0189                 bp++;
0190             else if (vp->state)
0191                 /* kill one voice on 2op channel, CHEAP */
0192                 bp++;
0193             /* raise kill cost to EXPENSIVE for all channels */
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     /* not found */
0214     return -1;
0215 }
0216 
0217 /* ------------------------------ */
0218 
0219 /*
0220  * System timer interrupt function
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);   /* invoke again */
0246     else
0247         opl3->sys_timer_status = 0;
0248     spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
0249 }
0250 
0251 /*
0252  * Start system timer
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  * Start a note.
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     /* in SYNTH mode, application takes care of voices */
0311     /* in SEQ mode, drum voice numbers are notes on drum channel */
0312     if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
0313         if (chan->drum_channel) {
0314             /* percussion instruments are located in bank 128 */
0315             bank = 128;
0316             prg = note;
0317         } else {
0318             bank = chan->gm_bank_select;
0319             prg = chan->midi_program;
0320         }
0321     } else {
0322         /* Prepare for OSS mode */
0323         if (chan->number >= MAX_OPL3_VOICES)
0324             return;
0325 
0326         /* OSS instruments are located in bank 127 */
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     /* in SYNTH mode, application takes care of voices */
0366     /* in SEQ mode, allocate voice on free OPL3 channel */
0367     if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
0368         voice = opl3_get_voice(opl3, instr_4op, chan);
0369     } else {
0370         /* remap OSS voice */
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         /* Left register block for voices 0 .. 8 */
0381         reg_side = OPL3_LEFT;
0382         voice_offset = voice;
0383         connect_mask = (OPL3_LEFT_4OP_0 << voice_offset) & 0x07;
0384     } else {
0385         /* Right register block for voices 9 .. 17 */
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     /* kill voice on channel */
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     /* set connection register */
0409     if (instr_4op) {
0410         if ((opl3->connection_reg ^ connect_mask) & connect_mask) {
0411             opl3->connection_reg |= connect_mask;
0412             /* set connection bit */
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             /* clear connection bit */
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      * calculate volume depending on connection
0431      * between FM operators (see include/opl3.h)
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     /* Program the FM voice characteristics */
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         /* Set OPL3 AM_VIB register of requested voice/operator */ 
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         /* Set OPL3 KSL_LEVEL register of requested voice/operator */ 
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         /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ 
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         /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ 
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         /* Select waveform */
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     /* Set operator feedback and 2op inter-operator connection */
0492     reg_val = fm->feedback_connection[0];
0493     /* Set output voice connection */
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         /* Set 4op inter-operator connection */
0504         reg_val = fm->feedback_connection[1] & OPL3_CONNECTION_BIT;
0505         /* Set output voice connection */
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      * Special treatment of percussion notes for fm:
0518      * Requested pitch is really program, and pitch for
0519      * device is whatever was specified in the patch library.
0520      */
0521     if (fm->fix_key)
0522         note = fm->fix_key;
0523     /*
0524      * use transpose if defined in patch library
0525      */
0526     if (fm->trnsps)
0527         note += (fm->trnsps - 64);
0528 
0529     snd_opl3_calc_pitch(&fnum, &blocknum, note, chan);
0530 
0531     /* Set OPL3 FNUM_LOW register of requested voice */
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     /* Set output sound flag */
0538     blocknum |= OPL3_KEYON_BIT;
0539 
0540 #ifdef DEBUG_MIDI
0541     snd_printk(KERN_DEBUG "  --> trigger voice %i\n", voice);
0542 #endif
0543     /* Set OPL3 KEYON_BLOCK register of requested voice */ 
0544     opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0545     opl3->command(opl3, opl3_reg, blocknum);
0546 
0547     /* kill note after fixed duration (in centiseconds) */
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     /* get extra pgm, but avoid possible loops */
0557     extra_prg = (extra_prg) ? 0 : fm->modes;
0558 
0559     /* do the bookkeeping */
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             /* 4op killed by 2op, release bounded voice */
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     /* allocate extra program if specified in patch library */
0587     if (extra_prg) {
0588         if (extra_prg > 128) {
0589             bank = 128;
0590             /* percussions start at 35 */
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         /* Left register block for voices 0 .. 8 */
0618         reg_side = OPL3_LEFT;
0619         voice_offset = voice;
0620     } else {
0621         /* Right register block for voices 9 .. 17 */
0622         reg_side = OPL3_RIGHT;
0623         voice_offset = voice - MAX_OPL2_VOICES;
0624     }
0625 
0626     /* kill voice */
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     /* clear Key ON bit */
0632     opl3->command(opl3, opl3_reg, vp->keyon_reg);
0633 
0634     /* do the bookkeeping */
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  * Release a note in response to a midi note off.
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         /* this loop will hopefully kill all extra voices, because
0674            they are grouped by the same channel and note values */
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         /* remap OSS voices */
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  * key pressure change
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  * terminate note
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; /* not allocated? */
0739 
0740     if (voice < MAX_OPL2_VOICES) {
0741         /* Left register block for voices 0 .. 8 */
0742         reg_side = OPL3_LEFT;
0743         voice_offset = voice;
0744     } else {
0745         /* Right register block for voices 9 .. 17 */
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     /* Set OPL3 FNUM_LOW register of requested voice */
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     /* Set output sound flag */
0759     blocknum |= OPL3_KEYON_BIT;
0760 
0761     /* Set OPL3 KEYON_BLOCK register of requested voice */ 
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  * Update voice pitch controller
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         /* remap OSS voices */
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  * Deal with a controller type event.  This includes all types of
0799  * control events, not just the midi controllers
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  * NRPN events
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  * receive sysex
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 }