[BACK]Return to opl.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/opl.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb