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