The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/opl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f46f9e2d44d58a7aa2463091e052e8be


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.