root/dev/ic/opl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opl_attach
  2. opl_probe_command
  3. opl_command
  4. opl_find
  5. opl_set_op_reg
  6. opl_set_ch_reg
  7. opl_load_patch
  8. opl_get_block_fnum
  9. opl_reset
  10. oplsyn_open
  11. oplsyn_close
  12. oplsyn_getinfo
  13. oplsyn_reset
  14. opl_calc_vol
  15. oplsyn_noteon
  16. oplsyn_noteoff
  17. oplsyn_keypressure
  18. oplsyn_ctlchange
  19. oplsyn_pitchbend
  20. oplsyn_loadpatch

    1 /*      $OpenBSD: opl.c,v 1.8 2006/07/27 05:55:00 miod Exp $    */
    2 /*      $NetBSD: opl.c,v 1.7 1998/12/08 14:26:56 augustss Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (augustss@netbsd.org).
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * The OPL3 (YMF262) manual can be found at
   42  * ftp://ftp.yamahayst.com/pub/Fax_Back_Doc/Sound/YMF262.PDF
   43  */
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/errno.h>
   48 #include <sys/ioctl.h>
   49 #include <sys/syslog.h>
   50 #include <sys/device.h>
   51 #include <sys/selinfo.h>
   52 
   53 #include <machine/cpu.h>
   54 #include <machine/bus.h>
   55 
   56 #include <sys/audioio.h>
   57 #include <sys/midiio.h>
   58 #include <dev/audio_if.h>
   59 
   60 #include <dev/midi_if.h>
   61 #include <dev/midivar.h>
   62 #include <dev/midisynvar.h>
   63 
   64 #include <dev/ic/oplreg.h>
   65 #include <dev/ic/oplvar.h>
   66 
   67 #ifdef AUDIO_DEBUG
   68 #define DPRINTF(x)      if (opldebug) printf x
   69 #define DPRINTFN(n,x)   if (opldebug >= (n)) printf x
   70 int     opldebug = 0;
   71 #else
   72 #define DPRINTF(x)
   73 #define DPRINTFN(n,x)
   74 #endif
   75 
   76 struct real_voice {
   77         u_int8_t voice_num;
   78         u_int8_t voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
   79         u_int8_t iooffs; /* I/O port (left or right side) */
   80         u_int8_t op[4]; /* Operator offsets */
   81 };
   82 
   83 const struct opl_voice voicetab[] = {
   84 /*       No    I/O offs         OP1     OP2     OP3   OP4       */
   85 /*      ---------------------------------------------------     */
   86         { 0,   OPL_L,   {0x00,  0x03,   0x08, 0x0b}},
   87         { 1,   OPL_L,   {0x01,  0x04,   0x09, 0x0c}},
   88         { 2,   OPL_L,   {0x02,  0x05,   0x0a, 0x0d}},
   89 
   90         { 3,   OPL_L,   {0x08,  0x0b,   0x00, 0x00}},
   91         { 4,   OPL_L,   {0x09,  0x0c,   0x00, 0x00}},
   92         { 5,   OPL_L,   {0x0a,  0x0d,   0x00, 0x00}},
   93 
   94         { 6,   OPL_L,   {0x10,  0x13,   0x00, 0x00}},
   95         { 7,   OPL_L,   {0x11,  0x14,   0x00, 0x00}},
   96         { 8,   OPL_L,   {0x12,  0x15,   0x00, 0x00}},
   97 
   98         { 0,   OPL_R,   {0x00,  0x03,   0x08, 0x0b}},
   99         { 1,   OPL_R,   {0x01,  0x04,   0x09, 0x0c}},
  100         { 2,   OPL_R,   {0x02,  0x05,   0x0a, 0x0d}},
  101         { 3,   OPL_R,   {0x08,  0x0b,   0x00, 0x00}},
  102         { 4,   OPL_R,   {0x09,  0x0c,   0x00, 0x00}},
  103         { 5,   OPL_R,   {0x0a,  0x0d,   0x00, 0x00}},
  104 
  105         { 6,   OPL_R,   {0x10,  0x13,   0x00, 0x00}},
  106         { 7,   OPL_R,   {0x11,  0x14,   0x00, 0x00}},
  107         { 8,   OPL_R,   {0x12,  0x15,   0x00, 0x00}}
  108 };
  109 
  110 static void opl_probe_command(struct opl_attach_arg *, int, int);
  111 static void opl_command(struct opl_softc *, int, int, int);
  112 void opl_reset(struct opl_softc *);
  113 void opl_freq_to_fnum (int freq, int *block, int *fnum);
  114 
  115 int oplsyn_open(midisyn *ms, int);
  116 void oplsyn_close(midisyn *);
  117 void oplsyn_reset(void *);
  118 void oplsyn_noteon(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  119 void oplsyn_noteoff(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  120 void oplsyn_keypressure(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  121 void oplsyn_ctlchange(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  122 void oplsyn_pitchbend(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  123 void oplsyn_loadpatch(midisyn *, struct sysex_info *, struct uio *);
  124 
  125 
  126 void opl_set_op_reg(struct opl_softc *, int, int, int, u_char);
  127 void opl_set_ch_reg(struct opl_softc *, int, int, u_char);
  128 void opl_load_patch(struct opl_softc *, int);
  129 u_int32_t opl_get_block_fnum(int freq);
  130 int opl_calc_vol(int regbyte, int volume, int main_vol);
  131 
  132 struct cfdriver opl_cd = {
  133         NULL, "opl", DV_DULL
  134 };
  135 
  136 struct midisyn_methods opl3_midi = {
  137         oplsyn_open,
  138         oplsyn_close,
  139         0,
  140         0,
  141         oplsyn_noteon,
  142         oplsyn_noteoff,
  143         oplsyn_keypressure,
  144         oplsyn_ctlchange,
  145         0,
  146         0,
  147         oplsyn_pitchbend,
  148         0
  149 };
  150         
  151 void
  152 opl_attach(sc)
  153         struct opl_softc *sc;
  154 {
  155         int i;
  156         struct opl_attach_arg oaa;
  157 
  158         oaa.iot = sc->iot;
  159         oaa.ioh = sc->ioh;
  160         oaa.offs = sc->offs;
  161         oaa.done = 0;
  162 
  163         if ((sc->model = opl_find(&oaa)) == 0) {
  164                 printf("\nopl: find failed\n");
  165                 return;
  166         }
  167 
  168         sc->syn.mets = &opl3_midi;
  169         snprintf(sc->syn.name, sizeof sc->syn.name, "%sYamaha OPL%d",
  170             sc->syn.name, sc->model);
  171         sc->syn.data = sc;
  172         sc->syn.nvoice = sc->model == OPL_2 ? OPL2_NVOICE : OPL3_NVOICE;
  173         sc->syn.flags =  MS_DOALLOC | MS_FREQXLATE;
  174         midisyn_attach(&sc->mididev, &sc->syn);
  175         
  176         /* Set up voice table */
  177         for (i = 0; i < OPL3_NVOICE; i++)
  178                 sc->voices[i] = voicetab[i];
  179 
  180         opl_reset(sc);
  181 
  182         printf(": model OPL%d\n", sc->model);
  183 
  184         midi_attach_mi(&midisyn_hw_if, &sc->syn, &sc->mididev.dev);
  185 }
  186 
  187 static void
  188 opl_probe_command(oaa, addr, data)
  189         struct opl_attach_arg *oaa;
  190         int addr, data;
  191 {
  192         DPRINTFN(4, ("opl_probe_command: addr=0x%02x data=0x%02x\n", 
  193                      addr, data));
  194         bus_space_write_1(oaa->iot, oaa->ioh, OPL_ADDR + OPL_L + oaa->offs,
  195             addr);
  196         delay(10);
  197         bus_space_write_1(oaa->iot, oaa->ioh, OPL_DATA + OPL_L + oaa->offs,
  198             data);
  199         delay(30);
  200 }
  201 
  202 static void
  203 opl_command(sc, offs, addr, data)
  204         struct opl_softc *sc;
  205         int offs;
  206         int addr, data;
  207 {
  208         DPRINTFN(4, ("opl_command: sc=%p, offs=%d addr=0x%02x data=0x%02x\n", 
  209                      sc, offs, addr, data));
  210         offs += sc->offs;
  211         bus_space_write_1(sc->iot, sc->ioh, OPL_ADDR+offs, addr);
  212         if (sc->model == OPL_2)
  213                 delay(10);
  214         else
  215                 delay(6);
  216         bus_space_write_1(sc->iot, sc->ioh, OPL_DATA+offs, data);
  217         if (sc->model == OPL_2)
  218                 delay(30);
  219         else
  220                 delay(6);
  221 }
  222 
  223 int
  224 opl_find(oaa)
  225         struct opl_attach_arg *oaa;
  226 {
  227         u_int8_t status1, status2;
  228         int model;
  229 
  230         DPRINTFN(2,("opl_find: ioh=0x%x\n", (int)oaa->ioh));
  231         model = OPL_2;  /* worst case assumption */
  232 
  233         /* Reset timers 1 and 2 */
  234         opl_probe_command(oaa, OPL_TIMER_CONTROL, 
  235                     OPL_TIMER1_MASK | OPL_TIMER2_MASK);
  236         /* Reset the IRQ of the FM chip */
  237         opl_probe_command(oaa, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
  238 
  239         /* get status bits */
  240         status1 = bus_space_read_1(oaa->iot, oaa->ioh,
  241             OPL_STATUS + OPL_L + oaa->offs);
  242 
  243         opl_probe_command(oaa, OPL_TIMER1, -2); /* wait 2 ticks */
  244         opl_probe_command(oaa, OPL_TIMER_CONTROL, /* start timer1 */
  245                     OPL_TIMER1_START | OPL_TIMER2_MASK);
  246         delay(1000);            /* wait for timer to expire */
  247 
  248         /* get status bits again */
  249         status2 = bus_space_read_1(oaa->iot, oaa->ioh,
  250             OPL_STATUS + OPL_L + oaa->offs);
  251 
  252         opl_probe_command(oaa, OPL_TIMER_CONTROL, 
  253                     OPL_TIMER1_MASK | OPL_TIMER2_MASK);
  254         opl_probe_command(oaa, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
  255 
  256         DPRINTFN(2,("opl_find: %02x %02x\n", status1, status2));
  257 
  258         if ((status1 & OPL_STATUS_MASK) != 0 ||
  259             (status2 & OPL_STATUS_MASK) != (OPL_STATUS_IRQ | OPL_STATUS_FT1))
  260                 return (0);
  261 
  262         switch(status1) {
  263         case 0x00:
  264         case 0x0f:
  265                 model = OPL_3;
  266                 break;
  267         case 0x06:
  268                 model = OPL_2;
  269                 break;
  270         default:
  271                 return 0;
  272         }
  273 
  274         DPRINTFN(2,("opl_find: OPL%d at 0x%x detected\n", 
  275             model, (int)oaa->ioh));
  276         return (model);
  277 }
  278 
  279 void 
  280 opl_set_op_reg(sc, base, voice, op, value)
  281         struct opl_softc *sc;
  282         int base;
  283         int voice;
  284         int op;
  285         u_char value;
  286 {
  287         struct opl_voice *v = &sc->voices[voice];
  288         opl_command(sc, v->iooffs, base + v->op[op], value);
  289 }
  290 
  291 void 
  292 opl_set_ch_reg(sc, base, voice, value)
  293         struct opl_softc *sc;
  294         int base;
  295         int voice;
  296         u_char value;
  297 {
  298         struct opl_voice *v = &sc->voices[voice];
  299         opl_command(sc, v->iooffs, base + v->voiceno, value);
  300 }
  301 
  302 
  303 void 
  304 opl_load_patch(sc, v)
  305         struct opl_softc *sc;
  306         int v;
  307 {
  308         const struct opl_operators *p = sc->voices[v].patch;
  309 
  310         opl_set_op_reg(sc, OPL_AM_VIB,          v, 0, p->ops[OO_CHARS+0]);
  311         opl_set_op_reg(sc, OPL_AM_VIB,          v, 1, p->ops[OO_CHARS+1]);
  312         opl_set_op_reg(sc, OPL_KSL_LEVEL,       v, 0, p->ops[OO_KSL_LEV+0]);
  313         opl_set_op_reg(sc, OPL_KSL_LEVEL,       v, 1, p->ops[OO_KSL_LEV+1]);
  314         opl_set_op_reg(sc, OPL_ATTACK_DECAY,    v, 0, p->ops[OO_ATT_DEC+0]);
  315         opl_set_op_reg(sc, OPL_ATTACK_DECAY,    v, 1, p->ops[OO_ATT_DEC+1]);
  316         opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 0, p->ops[OO_SUS_REL+0]);
  317         opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 1, p->ops[OO_SUS_REL+1]);
  318         opl_set_op_reg(sc, OPL_WAVE_SELECT,     v, 0, p->ops[OO_WAV_SEL+0]);
  319         opl_set_op_reg(sc, OPL_WAVE_SELECT,     v, 1, p->ops[OO_WAV_SEL+1]);
  320         opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, v, p->ops[OO_FB_CONN]);
  321 }
  322 
  323 #define OPL_FNUM_FAIL 0xffff
  324 u_int32_t
  325 opl_get_block_fnum(freq)
  326         int freq;
  327 {
  328         u_int32_t f_num = freq / 3125;
  329         u_int32_t  block = 0;
  330 
  331         while (f_num > 0x3FF && block < 8) {
  332                 block++;
  333                 f_num >>= 1;
  334         }
  335 
  336         if (block > 7)
  337                 return (OPL_FNUM_FAIL);
  338         else
  339                 return ((block << 10) | f_num);
  340   }
  341 
  342 
  343 void
  344 opl_reset(sc)
  345         struct opl_softc *sc;
  346 {
  347         int i;
  348 
  349         for (i = 1; i <= OPL_MAXREG; i++)
  350                 opl_command(sc, OPL_L, OPL_KEYON_BLOCK + i, 0);
  351 
  352         opl_command(sc, OPL_L, OPL_TEST, OPL_ENABLE_WAVE_SELECT);
  353         opl_command(sc, OPL_L, OPL_PERCUSSION, 0);
  354         if (sc->model == OPL_3) {
  355                 opl_command(sc, OPL_R, OPL_MODE, OPL3_ENABLE);
  356                 opl_command(sc, OPL_R,OPL_CONNECTION_SELECT,OPL_NOCONNECTION);
  357         }
  358 
  359         sc->volume = 64;
  360 }
  361 
  362 int
  363 oplsyn_open(ms, flags)
  364         midisyn *ms;
  365         int flags;
  366 {
  367         struct opl_softc *sc = ms->data;
  368 
  369         DPRINTFN(2, ("oplsyn_open: %d\n", flags));
  370 
  371         opl_reset(ms->data);
  372         if (sc->spkrctl)
  373                 sc->spkrctl(sc->spkrarg, 1);
  374         return (0);
  375 }
  376 
  377 void
  378 oplsyn_close(ms)
  379         midisyn *ms;
  380 {
  381         struct opl_softc *sc = ms->data;
  382 
  383         DPRINTFN(2, ("oplsyn_close:\n"));
  384 
  385         /*opl_reset(ms->data);*/
  386         if (sc->spkrctl)
  387                 sc->spkrctl(sc->spkrarg, 0);
  388 }
  389 
  390 #if 0
  391 void
  392 oplsyn_getinfo(addr, sd)
  393         void *addr;
  394         struct synth_dev *sd;
  395 {
  396         struct opl_softc *sc = addr;
  397 
  398         sd->name = sc->model == OPL_2 ? "Yamaha OPL2" : "Yamaha OPL3";
  399         sd->type = SYNTH_TYPE_FM;
  400         sd->subtype = sc->model == OPL_2 ? SYNTH_SUB_FM_TYPE_ADLIB 
  401                 : SYNTH_SUB_FM_TYPE_OPL3;
  402         sd->capabilities = 0;
  403 }
  404 #endif
  405 
  406 void
  407 oplsyn_reset(addr)
  408         void *addr;
  409 {
  410         struct opl_softc *sc = addr;
  411         DPRINTFN(3, ("oplsyn_reset:\n"));
  412         opl_reset(sc);
  413 }
  414 
  415 int8_t opl_volume_table[128] =
  416     {-64, -48, -40, -35, -32, -29, -27, -26,
  417      -24, -23, -21, -20, -19, -18, -18, -17,
  418      -16, -15, -15, -14, -13, -13, -12, -12,
  419      -11, -11, -10, -10, -10, -9, -9, -8,
  420      -8, -8, -7, -7, -7, -6, -6, -6,
  421      -5, -5, -5, -5, -4, -4, -4, -4,
  422      -3, -3, -3, -3, -2, -2, -2, -2,
  423      -2, -1, -1, -1, -1, 0, 0, 0,
  424      0, 0, 0, 1, 1, 1, 1, 1,
  425      1, 2, 2, 2, 2, 2, 2, 2,
  426      3, 3, 3, 3, 3, 3, 3, 4,
  427      4, 4, 4, 4, 4, 4, 4, 5,
  428      5, 5, 5, 5, 5, 5, 5, 5,
  429      6, 6, 6, 6, 6, 6, 6, 6,
  430      6, 7, 7, 7, 7, 7, 7, 7,
  431      7, 7, 7, 8, 8, 8, 8, 8};
  432 
  433 int
  434 opl_calc_vol(regbyte, volume, mainvol)
  435         int regbyte; 
  436         int volume;
  437         int mainvol;
  438 {
  439         int level = ~regbyte & OPL_TOTAL_LEVEL_MASK;
  440 
  441         if (mainvol > 127)
  442                 mainvol = 127;
  443 
  444         volume = (volume * mainvol) / 127;
  445 
  446         if (level)
  447                 level += opl_volume_table[volume];
  448 
  449         if (level > OPL_TOTAL_LEVEL_MASK)
  450                 level = OPL_TOTAL_LEVEL_MASK;
  451         if (level < 0)
  452                 level = 0;
  453 
  454         return (~level & OPL_TOTAL_LEVEL_MASK);
  455 }
  456 
  457 void
  458 oplsyn_noteon(ms, voice, freq, vel)
  459         midisyn *ms;
  460         u_int32_t voice, freq, vel;
  461 {
  462         struct opl_softc *sc = ms->data;
  463         struct opl_voice *v;
  464         const struct opl_operators *p;
  465         u_int32_t block_fnum;
  466         int mult;
  467         int c_mult, m_mult;
  468         u_int8_t chars0, chars1, ksl0, ksl1, fbc;
  469         u_int8_t r20m, r20c, r40m, r40c, rA0, rB0;
  470         u_int8_t vol0, vol1;
  471 
  472         DPRINTFN(3, ("oplsyn_noteon: %p %d %d\n", sc, voice, 
  473                      MIDISYN_FREQ_TO_HZ(freq)));
  474 
  475 #ifdef DIAGNOSTIC
  476         if (voice < 0 || voice >= sc->syn.nvoice) {
  477                 printf("oplsyn_noteon: bad voice %d\n", voice);
  478                 return;
  479         }
  480 #endif
  481         /* Turn off old note */
  482         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, 0xff);
  483         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, 0xff);
  484         opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    0);
  485 
  486         v = &sc->voices[voice];
  487         
  488         p = &opl2_instrs[MS_GETPGM(ms, voice)];
  489         v->patch = p;
  490         opl_load_patch(sc, voice);
  491 
  492         mult = 1;
  493         for (;;) {
  494                 block_fnum = opl_get_block_fnum(freq / mult);
  495                 if (block_fnum != OPL_FNUM_FAIL)
  496                         break;
  497                 mult *= 2;
  498                 if (mult == 16)
  499                         mult = 15;
  500         }
  501 
  502         chars0 = p->ops[OO_CHARS+0];
  503         chars1 = p->ops[OO_CHARS+1];
  504         m_mult = (chars0 & OPL_MULTIPLE_MASK) * mult;
  505         c_mult = (chars1 & OPL_MULTIPLE_MASK) * mult;
  506         if ((block_fnum == OPL_FNUM_FAIL) || (m_mult > 15) || (c_mult > 15)) {
  507                 printf("oplsyn_noteon: frequence out of range %d\n",
  508                        MIDISYN_FREQ_TO_HZ(freq));
  509                 return;
  510         }
  511         r20m = (chars0 &~ OPL_MULTIPLE_MASK) | m_mult;
  512         r20c = (chars1 &~ OPL_MULTIPLE_MASK) | c_mult;
  513 
  514         /* 2 voice */
  515         ksl0 = p->ops[OO_KSL_LEV+0];
  516         ksl1 = p->ops[OO_KSL_LEV+1];
  517         if (p->ops[OO_FB_CONN] & 0x01) {
  518                 vol0 = opl_calc_vol(ksl0, vel, sc->volume);
  519                 vol1 = opl_calc_vol(ksl1, vel, sc->volume);
  520         } else {
  521                 vol0 = ksl0;
  522                 vol1 = opl_calc_vol(ksl1, vel, sc->volume);
  523         }
  524         r40m = (ksl0 & OPL_KSL_MASK) | vol0;
  525         r40c = (ksl1 & OPL_KSL_MASK) | vol1;
  526 
  527         rA0  = block_fnum & 0xFF;
  528         rB0  = (block_fnum >> 8) | OPL_KEYON_BIT;
  529 
  530         v->rB0 = rB0;
  531 
  532         fbc = p->ops[OO_FB_CONN];
  533         if (sc->model == OPL_3) {
  534                 fbc &= ~OPL_STEREO_BITS;
  535                 /* XXX use pan */
  536                 fbc |= OPL_VOICE_TO_LEFT | OPL_VOICE_TO_RIGHT;
  537         }
  538         opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, voice, fbc);
  539 
  540         opl_set_op_reg(sc, OPL_AM_VIB,      voice, 0, r20m);
  541         opl_set_op_reg(sc, OPL_AM_VIB,      voice, 1, r20c);
  542         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, r40m);
  543         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, r40c);
  544         opl_set_ch_reg(sc, OPL_FNUM_LOW,    voice,    rA0);
  545         opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    rB0);
  546 }
  547 
  548 void
  549 oplsyn_noteoff(ms, voice, note, vel)
  550         midisyn *ms;
  551         u_int32_t voice, note, vel;
  552 {
  553         struct opl_softc *sc = ms->data;
  554         struct opl_voice *v;
  555 
  556         DPRINTFN(3, ("oplsyn_noteoff: %p %d %d\n", sc, voice, 
  557                      MIDISYN_FREQ_TO_HZ(note)));
  558 
  559 #ifdef DIAGNOSTIC
  560         if (voice < 0 || voice >= sc->syn.nvoice) {
  561                 printf("oplsyn_noteoff: bad voice %d\n", voice);
  562                 return;
  563         }
  564 #endif
  565         v = &sc->voices[voice];
  566         opl_set_ch_reg(sc, 0xB0, voice, v->rB0 & ~OPL_KEYON_BIT);
  567 }
  568 
  569 void
  570 oplsyn_keypressure(ms, voice, note, vel)
  571         midisyn *ms;
  572         u_int32_t voice, note, vel;
  573 {
  574 #ifdef AUDIO_DEBUG
  575         struct opl_softc *sc = ms->data;
  576         DPRINTFN(1, ("oplsyn_keypressure: %p %d\n", sc, note));
  577 #endif
  578 }
  579 
  580 void
  581 oplsyn_ctlchange(ms, voice, parm, w14)
  582         midisyn *ms;
  583         u_int32_t voice, parm, w14;
  584 {
  585 #ifdef AUDIO_DEBUG
  586         struct opl_softc *sc = ms->data;
  587         DPRINTFN(1, ("oplsyn_ctlchange: %p %d\n", sc, voice));
  588 #endif
  589 }
  590 
  591 void
  592 oplsyn_pitchbend(ms, voice, parm, x)
  593         midisyn *ms;
  594         u_int32_t voice, parm, x;
  595 {
  596 #ifdef AUDIO_DEBUG
  597         struct opl_softc *sc = ms->data;
  598         DPRINTFN(1, ("oplsyn_pitchbend: %p %d\n", sc, voice));
  599 #endif
  600 }
  601 
  602 void
  603 oplsyn_loadpatch(ms, sysex, uio)
  604         midisyn *ms;
  605         struct sysex_info *sysex;
  606         struct uio *uio;
  607 {
  608 #if 0
  609         struct opl_softc *sc = ms->data;
  610         struct sbi_instrument ins;
  611 
  612         DPRINTFN(1, ("oplsyn_loadpatch: %p\n", sc));
  613 
  614         memcpy(&ins, sysex, sizeof *sysex);
  615         if (uio->uio_resid >= sizeof ins - sizeof *sysex)
  616                 return EINVAL;
  617         uiomove((char *)&ins + sizeof *sysex, sizeof ins - sizeof *sysex, uio);
  618         /* XXX */
  619 #endif
  620 }

/* [<][>][^][v][top][bottom][index][help] */