FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/opl.c
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
|