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