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.22 2005/02/04 02:10:37 perry 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.22 2005/02/04 02:10:37 perry 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(midisyn *ms, int);
  117 void oplsyn_close(midisyn *);
  118 void oplsyn_reset(void *);
  119 void oplsyn_noteon(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  120 void oplsyn_noteoff(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  121 void oplsyn_keypressure(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  122 void oplsyn_ctlchange(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  123 void oplsyn_programchange(midisyn *, u_int32_t, u_int32_t);
  124 void oplsyn_pitchbend(midisyn *, u_int32_t, u_int32_t, u_int32_t);
  125 void oplsyn_loadpatch(midisyn *, struct sysex_info *, struct uio *);
  126 
  127 
  128 void opl_set_op_reg(struct opl_softc *, int, int, int, u_char);
  129 void opl_set_ch_reg(struct opl_softc *, int, int, u_char);
  130 void opl_load_patch(struct opl_softc *, int);
  131 u_int32_t opl_get_block_fnum(int freq);
  132 int opl_calc_vol(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         snprintf(sc->syn.name, sizeof(sc->syn.name), "%sYamaha OPL%d",
  162             sc->syn.name, sc->model);
  163         sc->syn.data = sc;
  164         sc->syn.nvoice = sc->model == OPL_2 ? OPL2_NVOICE : OPL3_NVOICE;
  165         sc->syn.flags =  MS_DOALLOC | MS_FREQXLATE;
  166         midisyn_attach(&sc->mididev, &sc->syn);
  167 
  168         /* Set up voice table */
  169         for (i = 0; i < OPL3_NVOICE; i++)
  170                 sc->voices[i] = voicetab[i];
  171 
  172         opl_reset(sc);
  173 
  174         printf(": model OPL%d", sc->model);
  175 
  176         /* Set up panpot */
  177         sc->panl = OPL_VOICE_TO_LEFT;
  178         sc->panr = OPL_VOICE_TO_RIGHT;
  179         if (sc->model == OPL_3 &&
  180             sc->mididev.dev.dv_cfdata->cf_flags & OPL_FLAGS_SWAP_LR) {
  181                 sc->panl = OPL_VOICE_TO_RIGHT;
  182                 sc->panr = OPL_VOICE_TO_LEFT;
  183                 printf(": LR swapped");
  184         }
  185 
  186         printf("\n");
  187 
  188         sc->sc_mididev =
  189             midi_attach_mi(&midisyn_hw_if, &sc->syn, &sc->mididev.dev);
  190 }
  191 
  192 int
  193 opl_detach(sc, flags)
  194         struct opl_softc *sc;
  195         int flags;
  196 {
  197         int rv = 0;
  198 
  199         if (sc->sc_mididev != NULL)
  200                 rv = config_detach(sc->sc_mididev, flags);
  201 
  202         return(rv);
  203 }
  204 
  205 static void
  206 opl_command(sc, offs, addr, data)
  207         struct opl_softc *sc;
  208         int offs;
  209         int addr, data;
  210 {
  211         DPRINTFN(4, ("opl_command: sc=%p, offs=%d addr=0x%02x data=0x%02x\n",
  212                      sc, offs, addr, data));
  213         offs += sc->offs;
  214         bus_space_write_1(sc->iot, sc->ioh, OPL_ADDR+offs, addr);
  215         if (sc->model == OPL_2)
  216                 delay(10);
  217         else
  218                 delay(6);
  219         bus_space_write_1(sc->iot, sc->ioh, OPL_DATA+offs, data);
  220         if (sc->model == OPL_2)
  221                 delay(30);
  222         else
  223                 delay(6);
  224 }
  225 
  226 int
  227 opl_find(sc)
  228         struct opl_softc *sc;
  229 {
  230         u_int8_t status1, status2;
  231 
  232         DPRINTFN(2,("opl_find: ioh=0x%x\n", (int)sc->ioh));
  233         sc->model = OPL_2;      /* worst case assumption */
  234 
  235         /* Reset timers 1 and 2 */
  236         opl_command(sc, OPL_L, OPL_TIMER_CONTROL,
  237                     OPL_TIMER1_MASK | OPL_TIMER2_MASK);
  238         /* Reset the IRQ of the FM chip */
  239         opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
  240 
  241         /* get status bits */
  242         status1 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs);
  243 
  244         opl_command(sc, OPL_L, OPL_TIMER1, -2); /* wait 2 ticks */
  245         opl_command(sc, OPL_L, OPL_TIMER_CONTROL, /* start timer1 */
  246                     OPL_TIMER1_START | OPL_TIMER2_MASK);
  247         delay(1000);            /* wait for timer to expire */
  248 
  249         /* get status bits again */
  250         status2 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs);
  251 
  252         opl_command(sc, OPL_L, OPL_TIMER_CONTROL,
  253                     OPL_TIMER1_MASK | OPL_TIMER2_MASK);
  254         opl_command(sc, OPL_L, 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                 sc->model = OPL_3;
  266                 break;
  267         case 0x06:
  268                 sc->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                     sc->model, (int)sc->ioh));
  276         return (1);
  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         for (i = 0; i < MIDI_MAX_CHANS; i++)
  362                 sc->pan[i] = OPL_VOICE_TO_LEFT | OPL_VOICE_TO_RIGHT;
  363 }
  364 
  365 int
  366 oplsyn_open(ms, flags)
  367         midisyn *ms;
  368         int flags;
  369 {
  370         struct opl_softc *sc = ms->data;
  371 
  372         DPRINTFN(2, ("oplsyn_open: %d\n", flags));
  373 
  374 #ifndef AUDIO_NO_POWER_CTL
  375         if (sc->powerctl)
  376                 sc->powerctl(sc->powerarg, 1);
  377 #endif
  378         opl_reset(ms->data);
  379         if (sc->spkrctl)
  380                 sc->spkrctl(sc->spkrarg, 1);
  381         return (0);
  382 }
  383 
  384 void
  385 oplsyn_close(ms)
  386         midisyn *ms;
  387 {
  388         struct opl_softc *sc = ms->data;
  389 
  390         DPRINTFN(2, ("oplsyn_close:\n"));
  391 
  392         /*opl_reset(ms->data);*/
  393         if (sc->spkrctl)
  394                 sc->spkrctl(sc->spkrarg, 0);
  395 #ifndef AUDIO_NO_POWER_CTL
  396         if (sc->powerctl)
  397                 sc->powerctl(sc->powerarg, 0);
  398 #endif
  399 }
  400 
  401 #if 0
  402 void
  403 oplsyn_getinfo(addr, sd)
  404         void *addr;
  405         struct synth_dev *sd;
  406 {
  407         struct opl_softc *sc = addr;
  408 
  409         sd->name = sc->model == OPL_2 ? "Yamaha OPL2" : "Yamaha OPL3";
  410         sd->type = SYNTH_TYPE_FM;
  411         sd->subtype = sc->model == OPL_2 ? SYNTH_SUB_FM_TYPE_ADLIB
  412                 : SYNTH_SUB_FM_TYPE_OPL3;
  413         sd->capabilities = 0;
  414 }
  415 #endif
  416 
  417 void
  418 oplsyn_reset(addr)
  419         void *addr;
  420 {
  421         struct opl_softc *sc = addr;
  422         DPRINTFN(3, ("oplsyn_reset:\n"));
  423         opl_reset(sc);
  424 }
  425 
  426 const int8_t opl_volume_table[128] =
  427     {-64, -48, -40, -35, -32, -29, -27, -26,
  428      -24, -23, -21, -20, -19, -18, -18, -17,
  429      -16, -15, -15, -14, -13, -13, -12, -12,
  430      -11, -11, -10, -10, -10, -9, -9, -8,
  431      -8, -8, -7, -7, -7, -6, -6, -6,
  432      -5, -5, -5, -5, -4, -4, -4, -4,
  433      -3, -3, -3, -3, -2, -2, -2, -2,
  434      -2, -1, -1, -1, -1, 0, 0, 0,
  435      0, 0, 0, 1, 1, 1, 1, 1,
  436      1, 2, 2, 2, 2, 2, 2, 2,
  437      3, 3, 3, 3, 3, 3, 3, 4,
  438      4, 4, 4, 4, 4, 4, 4, 5,
  439      5, 5, 5, 5, 5, 5, 5, 5,
  440      6, 6, 6, 6, 6, 6, 6, 6,
  441      6, 7, 7, 7, 7, 7, 7, 7,
  442      7, 7, 7, 8, 8, 8, 8, 8};
  443 
  444 int
  445 opl_calc_vol(regbyte, volume, mainvol)
  446         int regbyte;
  447         int volume;
  448         int mainvol;
  449 {
  450         int level = ~regbyte & OPL_TOTAL_LEVEL_MASK;
  451 
  452         if (mainvol > 127)
  453                 mainvol = 127;
  454 
  455         volume = (volume * mainvol) / 127;
  456 
  457         if (level)
  458                 level += opl_volume_table[volume];
  459 
  460         if (level > OPL_TOTAL_LEVEL_MASK)
  461                 level = OPL_TOTAL_LEVEL_MASK;
  462         if (level < 0)
  463                 level = 0;
  464 
  465         return (~level & OPL_TOTAL_LEVEL_MASK);
  466 }
  467 
  468 void
  469 oplsyn_noteon(ms, voice, freq, vel)
  470         midisyn *ms;
  471         u_int32_t voice, freq, vel;
  472 {
  473         struct opl_softc *sc = ms->data;
  474         struct opl_voice *v;
  475         const struct opl_operators *p;
  476         u_int32_t block_fnum;
  477         int mult;
  478         int c_mult, m_mult;
  479         u_int32_t chan;
  480         u_int8_t chars0, chars1, ksl0, ksl1, fbc;
  481         u_int8_t r20m, r20c, r40m, r40c, rA0, rB0;
  482         u_int8_t vol0, vol1;
  483 
  484         DPRINTFN(3, ("oplsyn_noteon: %p %d %d\n", sc, voice,
  485                      MIDISYN_FREQ_TO_HZ(freq)));
  486 
  487 #ifdef DIAGNOSTIC
  488         if (voice < 0 || voice >= sc->syn.nvoice) {
  489                 printf("oplsyn_noteon: bad voice %d\n", voice);
  490                 return;
  491         }
  492 #endif
  493         /* Turn off old note */
  494         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, 0xff);
  495         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, 0xff);
  496         opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    0);
  497 
  498         v = &sc->voices[voice];
  499 
  500         chan = MS_GETCHAN(&ms->voices[voice]);
  501         p = &opl2_instrs[ms->pgms[chan]];
  502         v->patch = p;
  503         opl_load_patch(sc, voice);
  504 
  505         mult = 1;
  506         for (;;) {
  507                 block_fnum = opl_get_block_fnum(freq / mult);
  508                 if (block_fnum != OPL_FNUM_FAIL)
  509                         break;
  510                 mult *= 2;
  511                 if (mult == 16)
  512                         mult = 15;
  513         }
  514 
  515         chars0 = p->ops[OO_CHARS+0];
  516         chars1 = p->ops[OO_CHARS+1];
  517         m_mult = (chars0 & OPL_MULTIPLE_MASK) * mult;
  518         c_mult = (chars1 & OPL_MULTIPLE_MASK) * mult;
  519         if ((block_fnum == OPL_FNUM_FAIL) || (m_mult > 15) || (c_mult > 15)) {
  520                 printf("oplsyn_noteon: frequency out of range %d\n",
  521                        MIDISYN_FREQ_TO_HZ(freq));
  522                 return;
  523         }
  524         r20m = (chars0 &~ OPL_MULTIPLE_MASK) | m_mult;
  525         r20c = (chars1 &~ OPL_MULTIPLE_MASK) | c_mult;
  526 
  527         /* 2 voice */
  528         ksl0 = p->ops[OO_KSL_LEV+0];
  529         ksl1 = p->ops[OO_KSL_LEV+1];
  530         if (p->ops[OO_FB_CONN] & 0x01) {
  531                 vol0 = opl_calc_vol(ksl0, vel, sc->volume);
  532                 vol1 = opl_calc_vol(ksl1, vel, sc->volume);
  533         } else {
  534                 vol0 = ksl0;
  535                 vol1 = opl_calc_vol(ksl1, vel, sc->volume);
  536         }
  537         r40m = (ksl0 & OPL_KSL_MASK) | vol0;
  538         r40c = (ksl1 & OPL_KSL_MASK) | vol1;
  539 
  540         rA0  = block_fnum & 0xFF;
  541         rB0  = (block_fnum >> 8) | OPL_KEYON_BIT;
  542 
  543         v->rB0 = rB0;
  544 
  545         fbc = p->ops[OO_FB_CONN];
  546         if (sc->model == OPL_3) {
  547                 fbc &= ~OPL_STEREO_BITS;
  548                 fbc |= sc->pan[chan];
  549         }
  550         opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, voice, fbc);
  551 
  552         opl_set_op_reg(sc, OPL_AM_VIB,      voice, 0, r20m);
  553         opl_set_op_reg(sc, OPL_AM_VIB,      voice, 1, r20c);
  554         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, r40m);
  555         opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, r40c);
  556         opl_set_ch_reg(sc, OPL_FNUM_LOW,    voice,    rA0);
  557         opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    rB0);
  558 }
  559 
  560 void
  561 oplsyn_noteoff(ms, voice, note, vel)
  562         midisyn *ms;
  563         u_int32_t voice, note, vel;
  564 {
  565         struct opl_softc *sc = ms->data;
  566         struct opl_voice *v;
  567 
  568         DPRINTFN(3, ("oplsyn_noteoff: %p %d %d\n", sc, voice,
  569                      MIDISYN_FREQ_TO_HZ(note)));
  570 
  571 #ifdef DIAGNOSTIC
  572         if (voice < 0 || voice >= sc->syn.nvoice) {
  573                 printf("oplsyn_noteoff: bad voice %d\n", voice);
  574                 return;
  575         }
  576 #endif
  577         v = &sc->voices[voice];
  578         opl_set_ch_reg(sc, 0xB0, voice, v->rB0 & ~OPL_KEYON_BIT);
  579 }
  580 
  581 void
  582 oplsyn_keypressure(ms, voice, note, vel)
  583         midisyn *ms;
  584         u_int32_t voice, note, vel;
  585 {
  586 #ifdef AUDIO_DEBUG
  587         struct opl_softc *sc = ms->data;
  588         DPRINTFN(1, ("oplsyn_keypressure: %p %d\n", sc, note));
  589 #endif
  590 }
  591 
  592 void
  593 oplsyn_ctlchange(ms, chan, parm, w14)
  594         midisyn *ms;
  595         u_int32_t chan, parm, w14;
  596 {
  597         struct opl_softc *sc = ms->data;
  598 
  599         DPRINTFN(1, ("oplsyn_ctlchange: %p %d\n", sc, chan));
  600         switch (parm) {
  601         case MIDI_CTRL_PAN_MSB:
  602                 sc->pan[chan] =
  603                     (w14 <= OPL_MIDI_CENTER_MAX ? sc->panl : 0) |
  604                     (w14 >= OPL_MIDI_CENTER_MIN ? sc->panr : 0);
  605                 break;
  606         }
  607 }
  608 
  609 /* PROGRAM CHANGE midi event: */
  610 void
  611 oplsyn_programchange(ms, chan, prog)
  612         midisyn *ms;
  613         u_int32_t chan;
  614         u_int32_t prog;
  615 {
  616         /* sanity checks */
  617         if (chan >= MIDI_MAX_CHANS || prog >= OPL_NINSTR)
  618                 return;
  619 
  620         ms->pgms[chan] = prog;
  621 }
  622 
  623 void
  624 oplsyn_pitchbend(ms, voice, parm, x)
  625         midisyn *ms;
  626         u_int32_t voice, parm, x;
  627 {
  628 #ifdef AUDIO_DEBUG
  629         struct opl_softc *sc = ms->data;
  630         DPRINTFN(1, ("oplsyn_pitchbend: %p %d\n", sc, voice));
  631 #endif
  632 }
  633 
  634 void
  635 oplsyn_loadpatch(ms, sysex, uio)
  636         midisyn *ms;
  637         struct sysex_info *sysex;
  638         struct uio *uio;
  639 {
  640 #if 0
  641         struct opl_softc *sc = ms->data;
  642         struct sbi_instrument ins;
  643 
  644         DPRINTFN(1, ("oplsyn_loadpatch: %p\n", sc));
  645 
  646         memcpy(&ins, sysex, sizeof *sysex);
  647         if (uio->uio_resid >= sizeof ins - sizeof *sysex)
  648                 return EINVAL;
  649         uiomove((char *)&ins + sizeof *sysex, sizeof ins - sizeof *sysex, uio);
  650         /* XXX */
  651 #endif
  652 }

Cache object: 8bc7d4bc842c9a3d0f03f6756e46f849


[ 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.