This source file includes following definitions.
- midisyn_open
- midisyn_close
- midisyn_getinfo
- midisyn_ioctl
- midisyn_findvoice
- midisyn_attach
- midisyn_freevoice
- midisyn_allocvoice
- midisyn_output
- midisyn_note_to_freq
- midisyn_finetune
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/ioctl.h>
42 #include <sys/fcntl.h>
43 #include <sys/vnode.h>
44 #include <sys/selinfo.h>
45 #include <sys/proc.h>
46 #include <sys/malloc.h>
47 #include <sys/systm.h>
48 #include <sys/syslog.h>
49 #include <sys/kernel.h>
50 #include <sys/conf.h>
51 #include <sys/audioio.h>
52 #include <sys/midiio.h>
53 #include <sys/device.h>
54
55 #include <dev/audio_if.h>
56 #include <dev/midi_if.h>
57 #include <dev/midivar.h>
58 #include <dev/midisynvar.h>
59
60 #ifdef AUDIO_DEBUG
61 #define DPRINTF(x) if (midisyndebug) printf x
62 #define DPRINTFN(n,x) if (midisyndebug >= (n)) printf x
63 int midisyndebug = 0;
64 #else
65 #define DPRINTF(x)
66 #define DPRINTFN(n,x)
67 #endif
68
69 int midisyn_findvoice(midisyn *, int, int);
70 void midisyn_freevoice(midisyn *, int);
71 int midisyn_allocvoice(midisyn *, u_int32_t, u_int32_t);
72 u_int32_t midisyn_note_to_freq(int);
73 u_int32_t midisyn_finetune(u_int32_t, int, int, int);
74
75 int midisyn_open(void *, int,
76 void (*iintr)(void *, int),
77 void (*ointr)(void *), void *arg);
78 void midisyn_close(void *);
79 int midisyn_output(void *, int);
80 void midisyn_getinfo(void *, struct midi_info *);
81 int midisyn_ioctl(void *, u_long, caddr_t, int, struct proc *);
82
83 struct midi_hw_if midisyn_hw_if = {
84 midisyn_open,
85 midisyn_close,
86 midisyn_output,
87 NULL,
88 midisyn_getinfo,
89 midisyn_ioctl,
90 };
91
92 static int midi_lengths[] = { 3,3,3,3,2,2,3,1 };
93
94 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
95
96 int
97 midisyn_open(addr, flags, iintr, ointr, arg)
98 void *addr;
99 int flags;
100 void (*iintr)(void *, int);
101 void (*ointr)(void *);
102 void *arg;
103 {
104 midisyn *ms = addr;
105
106 DPRINTF(("midisyn_open: ms=%p ms->mets=%p\n", ms, ms->mets));
107 if (ms->mets->open)
108 return (ms->mets->open(ms, flags));
109 else
110 return (0);
111 }
112
113 void
114 midisyn_close(addr)
115 void *addr;
116 {
117 midisyn *ms = addr;
118 struct midisyn_methods *fs;
119 int v;
120
121 DPRINTF(("midisyn_close: ms=%p ms->mets=%p\n", ms, ms->mets));
122 fs = ms->mets;
123 for (v = 0; v < ms->nvoice; v++)
124 if (ms->voices[v].inuse) {
125 fs->noteoff(ms, v, 0, 0);
126 midisyn_freevoice(ms, v);
127 }
128 if (fs->close)
129 fs->close(ms);
130 }
131
132 void
133 midisyn_getinfo(addr, mi)
134 void *addr;
135 struct midi_info *mi;
136 {
137 midisyn *ms = addr;
138
139 mi->name = ms->name;
140 mi->props = 0;
141 }
142
143 int
144 midisyn_ioctl(maddr, cmd, addr, flag, p)
145 void *maddr;
146 u_long cmd;
147 caddr_t addr;
148 int flag;
149 struct proc *p;
150 {
151 midisyn *ms = maddr;
152
153 if (ms->mets->ioctl)
154 return (ms->mets->ioctl(ms, cmd, addr, flag, p));
155 else
156 return (EINVAL);
157 }
158
159 int
160 midisyn_findvoice(ms, chan, note)
161 midisyn *ms;
162 int chan, note;
163 {
164 u_int cn;
165 int v;
166
167 if (!(ms->flags & MS_DOALLOC))
168 return (chan);
169 cn = MS_CHANNOTE(chan, note);
170 for (v = 0; v < ms->nvoice; v++)
171 if (ms->voices[v].chan_note == cn && ms->voices[v].inuse)
172 return (v);
173 return (-1);
174 }
175
176 void
177 midisyn_attach(sc, ms)
178 struct midi_softc *sc;
179 midisyn *ms;
180 {
181 if (ms->flags & MS_DOALLOC) {
182 ms->voices = malloc(ms->nvoice * sizeof (struct voice),
183 M_DEVBUF, M_WAITOK);
184 memset(ms->voices, 0, ms->nvoice * sizeof (struct voice));
185 ms->seqno = 1;
186 if (ms->mets->allocv == 0)
187 ms->mets->allocv = &midisyn_allocvoice;
188 }
189 sc->hw_if = &midisyn_hw_if;
190 sc->hw_hdl = ms;
191 DPRINTF(("midisyn_attach: ms=%p\n", sc->hw_hdl));
192 }
193
194 void
195 midisyn_freevoice(ms, voice)
196 midisyn *ms;
197 int voice;
198 {
199 if (!(ms->flags & MS_DOALLOC))
200 return;
201 ms->voices[voice].inuse = 0;
202 }
203
204 int
205 midisyn_allocvoice(ms, chan, note)
206 midisyn *ms;
207 u_int32_t chan, note;
208 {
209 int bestv, v;
210 u_int bestseq, s;
211
212 if (!(ms->flags & MS_DOALLOC))
213 return (chan);
214
215 bestv = 0;
216 bestseq = ms->voices[0].seqno + (ms->voices[0].inuse ? 0x40000000 : 0);
217 for (v = 1; v < ms->nvoice; v++) {
218 s = ms->voices[v].seqno;
219 if (ms->voices[v].inuse)
220 s += 0x40000000;
221 if (s < bestseq) {
222 bestseq = s;
223 bestv = v;
224 }
225 }
226 DPRINTFN(10,("midisyn_allocvoice: v=%d seq=%d cn=%x inuse=%d\n",
227 bestv, ms->voices[bestv].seqno,
228 ms->voices[bestv].chan_note,
229 ms->voices[bestv].inuse));
230 #ifdef AUDIO_DEBUG
231 if (ms->voices[bestv].inuse)
232 DPRINTFN(1,("midisyn_allocvoice: steal %x\n",
233 ms->voices[bestv].chan_note));
234 #endif
235 ms->voices[bestv].chan_note = MS_CHANNOTE(chan, note);
236 ms->voices[bestv].seqno = ms->seqno++;
237 ms->voices[bestv].inuse = 1;
238 return (bestv);
239 }
240
241 int
242 midisyn_output(addr, b)
243 void *addr;
244 int b;
245 {
246 midisyn *ms = addr;
247 u_int8_t status, chan;
248 int voice = 0;
249 struct midisyn_methods *fs;
250 u_int32_t note, vel;
251
252 DPRINTF(("midisyn_output: ms=%p b=0x%02x\n", ms, b));
253 fs = ms->mets;
254 if (ms->pos < 0) {
255
256 DPRINTF(("midisyn_output: sysex 0x%02x\n", b));
257 if (fs->sysex)
258 fs->sysex(ms, b);
259 if (b == MIDI_SYSEX_END)
260 ms->pos = 0;
261 return (0);
262 }
263 if (ms->pos == 0 && !MIDI_IS_STATUS(b))
264 ms->pos++;
265 ms->buf[ms->pos++] = b;
266 status = ms->buf[0];
267 if (ms->pos < MIDI_LENGTH(status))
268 return (0);
269
270 chan = MIDI_GET_CHAN(status);
271 note = ms->buf[1];
272 if (ms->flags & MS_FREQXLATE)
273 note = midisyn_note_to_freq(note);
274 vel = ms->buf[2];
275 switch (MIDI_GET_STATUS(status)) {
276 case MIDI_NOTEOFF:
277 voice = midisyn_findvoice(ms, chan, ms->buf[1]);
278 if (voice >= 0) {
279 fs->noteoff(ms, voice, note, vel);
280 midisyn_freevoice(ms, voice);
281 }
282 break;
283 case MIDI_NOTEON:
284 voice = fs->allocv(ms, chan, ms->buf[1]);
285 fs->noteon(ms, voice, note, vel);
286 break;
287 case MIDI_KEY_PRESSURE:
288 if (fs->keypres) {
289 voice = midisyn_findvoice(ms, voice, ms->buf[1]);
290 if (voice >= 0)
291 fs->keypres(ms, voice, note, vel);
292 }
293 break;
294 case MIDI_CTL_CHANGE:
295 if (fs->ctlchg)
296 fs->ctlchg(ms, chan, ms->buf[1], vel);
297 break;
298 case MIDI_PGM_CHANGE:
299 if (fs->pgmchg)
300 fs->pgmchg(ms, chan, ms->buf[1]);
301 break;
302 case MIDI_CHN_PRESSURE:
303 if (fs->chnpres) {
304 voice = midisyn_findvoice(ms, chan, ms->buf[1]);
305 if (voice >= 0)
306 fs->chnpres(ms, voice, note);
307 }
308 break;
309 case MIDI_PITCH_BEND:
310 if (fs->pitchb) {
311 voice = midisyn_findvoice(ms, chan, ms->buf[1]);
312 if (voice >= 0)
313 fs->pitchb(ms, chan, note, vel);
314 }
315 break;
316 case MIDI_SYSTEM_PREFIX:
317 if (fs->sysex)
318 fs->sysex(ms, status);
319 ms->pos = -1;
320 return (0);
321 }
322 ms->pos = 0;
323 return (0);
324 }
325
326
327
328
329
330 u_int32_t
331 midisyn_note_to_freq(note)
332 int note;
333 {
334 int o, n, f;
335 #define BASE_OCTAVE 5
336 static u_int32_t notes[] = {
337 17145893, 18165441, 19245614, 20390018, 21602472, 22887021,
338 24247954, 25689813, 27217409, 28835840, 30550508, 32367136
339 };
340
341
342 o = note / 12;
343 n = note % 12;
344
345 f = notes[n];
346
347 if (o < BASE_OCTAVE)
348 f >>= (BASE_OCTAVE - o);
349 else if (o > BASE_OCTAVE)
350 f <<= (o - BASE_OCTAVE);
351 return (f);
352 }
353
354 u_int32_t
355 midisyn_finetune(base_freq, bend, range, vibrato_cents)
356 u_int32_t base_freq;
357 int bend;
358 int range;
359 int vibrato_cents;
360 {
361 static u_int16_t semitone_tuning[24] =
362 {
363 10000, 10595, 11225, 11892, 12599, 13348, 14142, 14983,
364 15874, 16818, 17818, 18877, 20000, 21189, 22449, 23784,
365 25198, 26697, 28284, 29966, 31748, 33636, 35636, 37755
366 };
367 static u_int16_t cent_tuning[100] =
368 {
369 10000, 10006, 10012, 10017, 10023, 10029, 10035, 10041,
370 10046, 10052, 10058, 10064, 10070, 10075, 10081, 10087,
371 10093, 10099, 10105, 10110, 10116, 10122, 10128, 10134,
372 10140, 10145, 10151, 10157, 10163, 10169, 10175, 10181,
373 10187, 10192, 10198, 10204, 10210, 10216, 10222, 10228,
374 10234, 10240, 10246, 10251, 10257, 10263, 10269, 10275,
375 10281, 10287, 10293, 10299, 10305, 10311, 10317, 10323,
376 10329, 10335, 10341, 10347, 10353, 10359, 10365, 10371,
377 10377, 10383, 10389, 10395, 10401, 10407, 10413, 10419,
378 10425, 10431, 10437, 10443, 10449, 10455, 10461, 10467,
379 10473, 10479, 10485, 10491, 10497, 10503, 10509, 10515,
380 10521, 10528, 10534, 10540, 10546, 10552, 10558, 10564,
381 10570, 10576, 10582, 10589
382 };
383 u_int32_t amount;
384 int negative, semitones, cents, multiplier;
385
386 if (range == 0)
387 return base_freq;
388
389 if (base_freq == 0)
390 return base_freq;
391
392 if (range >= 8192)
393 range = 8192;
394
395 bend = bend * range / 8192;
396 bend += vibrato_cents;
397
398 if (bend == 0)
399 return base_freq;
400
401 if (bend < 0) {
402 bend = -bend;
403 negative = 1;
404 } else
405 negative = 0;
406
407 if (bend > range)
408 bend = range;
409
410 multiplier = 1;
411 while (bend > 2399) {
412 multiplier *= 4;
413 bend -= 2400;
414 }
415
416 semitones = bend / 100;
417 if (semitones > 23)
418 semitones = 23;
419 cents = bend % 100;
420
421 amount = semitone_tuning[semitones] * multiplier * cent_tuning[cents]
422 / 10000;
423
424 if (negative)
425 return (base_freq * 10000 / amount);
426 else
427 return (base_freq * amount / 10000);
428 }
429