Annotation of src/usr.bin/aucat/aucat.c, Revision 1.150
1.1 kstailey 1: /*
1.146 ratchov 2: * Copyright (c) 2008-2014 Alexandre Ratchov <alex@caoua.org>
1.1 kstailey 3: *
1.15 ratchov 4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15: */
1.145 deraadt 16:
1.146 ratchov 17: #include <fcntl.h>
1.55 ratchov 18: #include <errno.h>
1.146 ratchov 19: #include <poll.h>
1.15 ratchov 20: #include <signal.h>
1.135 ratchov 21: #include <sndio.h>
1.1 kstailey 22: #include <stdio.h>
1.4 millert 23: #include <stdlib.h>
1.8 david 24: #include <string.h>
1.1 kstailey 25: #include <unistd.h>
1.146 ratchov 26: #include "abuf.h"
27: #include "afile.h"
28: #include "dsp.h"
29: #include "sysex.h"
30: #include "utils.h"
31:
32: /*
33: * masks to extract command and channel of status byte
34: */
35: #define MIDI_CMDMASK 0xf0
36: #define MIDI_CHANMASK 0x0f
37:
38: /*
39: * MIDI status bytes of voice messages
40: */
41: #define MIDI_NOFF 0x80 /* note off */
42: #define MIDI_NON 0x90 /* note on */
43: #define MIDI_KAT 0xa0 /* key after touch */
44: #define MIDI_CTL 0xb0 /* controller */
45: #define MIDI_PC 0xc0 /* program change */
46: #define MIDI_CAT 0xd0 /* channel after touch */
47: #define MIDI_BEND 0xe0 /* pitch bend */
48: #define MIDI_ACK 0xfe /* active sensing message */
49:
50: /*
51: * MIDI controller numbers
52: */
53: #define MIDI_CTL_VOL 7
54:
55: /*
56: * Max coarse value
57: */
58: #define MIDI_MAXCTL 127
59:
60: /*
61: * MIDI status bytes for sysex
62: */
63: #define MIDI_SX_START 0xf0
64: #define MIDI_SX_STOP 0xf7
65:
66: /*
67: * audio device defaults
68: */
69: #define DEFAULT_RATE 48000
70: #define DEFAULT_BUFSZ_MS 200
71:
72: struct slot {
1.149 ratchov 73: struct slot *next; /* next on the play/rec list */
1.146 ratchov 74: int vol; /* dynamic range */
75: int volctl; /* volume in the 0..127 range */
76: struct abuf buf; /* file i/o buffer */
77: int bpf; /* bytes per frame */
78: int cmin, cmax; /* file channel range */
79: struct cmap cmap; /* channel mapper state */
80: struct resamp resamp; /* resampler state */
81: struct conv conv; /* format encoder state */
82: int join; /* channel join factor */
83: int expand; /* channel expand factor */
84: void *resampbuf, *convbuf; /* conversion tmp buffers */
85: int dup; /* mono-to-stereo and alike */
86: int round; /* slot-side block size */
87: int mode; /* MODE_{PLAY,REC} */
88: #define SLOT_CFG 0 /* buffers not allocated yet */
89: #define SLOT_INIT 1 /* not trying to do anything */
90: #define SLOT_RUN 2 /* playing/recording */
91: #define SLOT_STOP 3 /* draining (play only) */
92: int pstate; /* one of above */
1.149 ratchov 93: struct afile afile; /* file desc & friends */
1.146 ratchov 94: };
95:
96: /*
97: * device properties
98: */
99: unsigned int dev_mode; /* bitmap of SIO_{PLAY,REC} */
100: unsigned int dev_bufsz; /* device buffer size */
101: unsigned int dev_round; /* device block size */
102: int dev_rate; /* device sample rate (Hz) */
103: unsigned int dev_pchan, dev_rchan; /* play & rec channels count */
104: adata_t *dev_pbuf, *dev_rbuf; /* play & rec buffers */
105: unsigned int dev_mmcpos; /* last MMC position */
106: #define DEV_STOP 0 /* stopped */
107: #define DEV_START 1 /* started */
108: unsigned int dev_pstate; /* one of above */
109: char *dev_name; /* device sndio(7) name */
110: char *dev_port; /* control port sndio(7) name */
111: struct sio_hdl *dev_sh; /* device handle */
112: struct mio_hdl *dev_mh; /* MIDI control port handle */
113: unsigned int dev_volctl = MIDI_MAXCTL; /* master volume */
114:
115: /*
116: * MIDI parser state
117: */
118: #define MIDI_MSGMAX 32 /* max size of MIDI msg */
119: unsigned char dev_msg[MIDI_MSGMAX]; /* parsed input message */
120: unsigned int dev_mst; /* input MIDI running status */
121: unsigned int dev_mused; /* bytes used in ``msg'' */
122: unsigned int dev_midx; /* current ``msg'' size */
123: unsigned int dev_mlen; /* expected ``msg'' length */
124: unsigned int dev_prime; /* blocks to write to start */
125:
126: unsigned int log_level = 1;
127: volatile sig_atomic_t quit_flag = 0;
128: struct slot *slot_list = NULL;
129:
130: /*
131: * length of voice and common MIDI messages (status byte included)
132: */
133: unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 };
134: unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 };
135:
1.147 jmc 136: char usagestr[] = "usage: aucat [-dn] [-b size] "
137: "[-c min:max] [-e enc] [-f device] [-h fmt]\n\t"
138: "[-i file] [-j flag] [-o file] [-q port] [-r rate] [-v volume]\n";
1.146 ratchov 139:
140: static void
141: slot_log(struct slot *s)
142: {
143: #ifdef DEBUG
144: static char *pstates[] = {
145: "cfg", "ini", "run", "stp"
146: };
147: #endif
148: log_puts(s->afile.path);
149: #ifdef DEBUG
150: if (log_level >= 3) {
151: log_puts(",pst=");
152: log_puts(pstates[s->pstate]);
153: }
154: #endif
155: }
156:
157: static void
158: slot_flush(struct slot *s)
159: {
160: int todo, count, n;
161: unsigned char *data;
162:
163: todo = s->buf.used;
164: while (todo > 0) {
165: data = abuf_rgetblk(&s->buf, &count);
166: if (count > todo)
167: count = todo;
168: n = afile_write(&s->afile, data, count);
169: if (n == 0) {
170: slot_log(s);
171: log_puts(": can't write, disabled\n");
172: s->pstate = SLOT_INIT;
173: return;
174: }
175: abuf_rdiscard(&s->buf, n);
176: todo -= n;
177: }
178: }
179:
180: static void
181: slot_fill(struct slot *s)
182: {
183: int todo, count, n;
184: unsigned char *data;
185:
186: todo = s->buf.len;
187: while (todo > 0) {
188: data = abuf_wgetblk(&s->buf, &count);
189: if (count > todo)
190: count = todo;
191: n = afile_read(&s->afile, data, count);
192: if (n == 0) {
193: #ifdef DEBUG
194: if (log_level >= 3) {
195: slot_log(s);
196: log_puts(": eof reached, stopping\n");
197: }
198: #endif
199: s->pstate = SLOT_STOP;
200: break;
201: }
202: abuf_wcommit(&s->buf, n);
203: todo -= n;
204: }
205: }
206:
207: static int
208: slot_new(char *path, int mode, struct aparams *par, int hdr,
209: int cmin, int cmax, int rate, int dup, int vol)
210: {
211: struct slot *s;
212:
213: s = xmalloc(sizeof(struct slot));
214: if (!afile_open(&s->afile, path, hdr,
215: mode == SIO_PLAY ? AFILE_FREAD : AFILE_FWRITE,
216: par, rate, cmax - cmin + 1)) {
1.150 ! mmcc 217: free(s);
1.146 ratchov 218: return 0;
219: }
220: s->cmin = cmin;
221: s->cmax = cmin + s->afile.nch - 1;
222: s->dup = dup;
223: s->vol = MIDI_TO_ADATA(vol);
224: s->mode = mode;
225: s->pstate = SLOT_CFG;
226: if (log_level >= 2) {
227: slot_log(s);
228: log_puts(": ");
229: log_puts(s->mode == SIO_PLAY ? "play" : "rec");
230: log_puts(", chan ");
231: log_putu(s->cmin);
232: log_puts(":");
233: log_putu(s->cmax);
234: log_puts(", ");
235: log_putu(s->afile.rate);
236: log_puts("Hz, ");
237: switch (s->afile.fmt) {
238: case AFILE_FMT_PCM:
239: aparams_log(&s->afile.par);
240: break;
241: case AFILE_FMT_ULAW:
242: log_puts("ulaw");
243: break;
244: case AFILE_FMT_ALAW:
245: log_puts("alaw");
246: break;
247: case AFILE_FMT_FLOAT:
248: log_puts("f32le");
249: break;
250: }
251: if (s->mode == SIO_PLAY && s->afile.endpos >= 0) {
252: log_puts(", bytes ");
253: log_puti(s->afile.startpos);
254: log_puts("..");
255: log_puti(s->afile.endpos);
256: }
257: log_puts("\n");
258: }
259: s->next = slot_list;
260: slot_list = s;
261: return 1;
262: }
263:
264: static void
265: slot_init(struct slot *s)
266: {
267: unsigned int slot_nch, bufsz;
268:
269: #ifdef DEBUG
270: if (s->pstate != SLOT_CFG) {
271: slot_log(s);
272: log_puts(": slot_init: wrong state\n");
273: panic();
274: }
275: #endif
276: s->bpf = s->afile.par.bps * (s->cmax - s->cmin + 1);
277: s->round = (dev_round * s->afile.rate + dev_rate / 2) / dev_rate;
278:
279: bufsz = s->round * (dev_bufsz / dev_round);
280: bufsz -= bufsz % s->round;
281: if (bufsz == 0)
282: bufsz = s->round;
283: abuf_init(&s->buf, bufsz * s->bpf);
284: #ifdef DEBUG
285: if (log_level >= 3) {
286: slot_log(s);
287: log_puts(": allocated ");
288: log_putu(bufsz);
289: log_puts(" frame buffer\n");
290: }
291: #endif
292:
293: slot_nch = s->cmax - s->cmin + 1;
294: s->convbuf = NULL;
295: s->resampbuf = NULL;
296: s->join = 1;
297: s->expand = 1;
298: if (s->mode & SIO_PLAY) {
299: if (s->dup) {
300: if (dev_pchan > slot_nch)
301: s->expand = dev_pchan / slot_nch;
302: else if (dev_pchan < slot_nch)
303: s->join = slot_nch / dev_pchan;
304: }
305: cmap_init(&s->cmap,
306: s->cmin, s->cmax,
307: s->cmin, s->cmax,
308: 0, dev_pchan - 1,
309: 0, dev_pchan - 1);
310: if (s->afile.fmt != AFILE_FMT_PCM || !aparams_native(&s->afile.par)) {
311: dec_init(&s->conv, &s->afile.par, slot_nch);
312: s->convbuf =
313: xmalloc(s->round * slot_nch * sizeof(adata_t));
314: }
315: if (s->afile.rate != dev_rate) {
316: resamp_init(&s->resamp, s->round, dev_round,
317: slot_nch);
318: s->resampbuf =
319: xmalloc(dev_round * slot_nch * sizeof(adata_t));
320: }
321: }
322: if (s->mode & SIO_REC) {
323: if (s->dup) {
324: if (dev_rchan > slot_nch)
325: s->join = dev_rchan / slot_nch;
326: else if (dev_rchan < slot_nch)
327: s->expand = slot_nch / dev_rchan;
328: }
329: cmap_init(&s->cmap,
330: 0, dev_rchan - 1,
331: 0, dev_rchan - 1,
332: s->cmin, s->cmax,
333: s->cmin, s->cmax);
334: if (s->afile.rate != dev_rate) {
335: resamp_init(&s->resamp, dev_round, s->round,
336: slot_nch);
337: s->resampbuf =
338: xmalloc(dev_round * slot_nch * sizeof(adata_t));
339: }
340: if (!aparams_native(&s->afile.par)) {
341: enc_init(&s->conv, &s->afile.par, slot_nch);
342: s->convbuf =
343: xmalloc(s->round * slot_nch * sizeof(adata_t));
344: }
345: }
346: s->pstate = SLOT_INIT;
347: #ifdef DEBUG
348: if (log_level >= 3) {
349: slot_log(s);
350: log_puts(": chain initialized\n");
351: }
352: #endif
353: }
354:
355: static void
356: slot_start(struct slot *s, unsigned int mmc)
357: {
358: off_t mmcpos;
359:
360: #ifdef DEBUG
361: if (s->pstate != SLOT_INIT) {
362: slot_log(s);
363: log_puts(": slot_start: wrong state\n");
364: panic();
365: }
366: #endif
367: mmcpos = ((off_t)mmc * s->afile.rate / MTC_SEC) * s->bpf;
368: if (!afile_seek(&s->afile, mmcpos)) {
369: s->pstate = SLOT_INIT;
370: return;
371: }
372: s->pstate = SLOT_RUN;
373: if (s->mode & SIO_PLAY)
374: slot_fill(s);
375: #ifdef DEBUG
376: if (log_level >= 2) {
377: slot_log(s);
378: log_puts(": started\n");
379: }
380: #endif
381: }
1.1 kstailey 382:
1.146 ratchov 383: static void
384: slot_stop(struct slot *s)
385: {
386: if (s->pstate == SLOT_INIT)
387: return;
388: if (s->mode & SIO_REC)
389: slot_flush(s);
390: if (s->mode & SIO_PLAY)
391: s->buf.used = s->buf.start = 0;
392: s->pstate = SLOT_INIT;
1.78 ratchov 393: #ifdef DEBUG
1.146 ratchov 394: if (log_level >= 2) {
395: slot_log(s);
396: log_puts(": stopped\n");
397: }
1.78 ratchov 398: #endif
1.146 ratchov 399: }
1.11 jaredy 400:
1.146 ratchov 401: static void
402: slot_del(struct slot *s)
403: {
404: struct slot **ps;
1.61 ratchov 405:
1.146 ratchov 406: if (s->pstate != SLOT_CFG) {
407: slot_stop(s);
408: afile_close(&s->afile);
409: #ifdef DEBUG
410: if (log_level >= 3) {
411: slot_log(s);
412: log_puts(": closed\n");
413: }
1.108 ratchov 414: #endif
1.146 ratchov 415: abuf_done(&s->buf);
1.150 ! mmcc 416: free(s->resampbuf);
! 417: free(s->convbuf);
1.146 ratchov 418: }
419: for (ps = &slot_list; *ps != s; ps = &(*ps)->next)
420: ; /* nothing */
421: *ps = s->next;
1.150 ! mmcc 422: free(s);
1.146 ratchov 423: }
424:
425: static int
426: play_filt_resamp(struct slot *s, void *res_in, void *out, int todo)
427: {
428: int i, offs, vol, nch;
429: void *in;
430:
431: if (s->resampbuf) {
432: todo = resamp_do(&s->resamp,
433: res_in, s->resampbuf, todo);
434: in = s->resampbuf;
435: } else
436: in = res_in;
437:
438: nch = s->cmap.nch;
439: vol = s->vol / s->join; /* XXX */
440: cmap_add(&s->cmap, in, out, vol, todo);
441:
442: offs = 0;
443: for (i = s->join - 1; i > 0; i--) {
444: offs += nch;
445: cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, todo);
446: }
447: offs = 0;
448: for (i = s->expand - 1; i > 0; i--) {
449: offs += nch;
450: cmap_add(&s->cmap, in, (adata_t *)out + offs, vol, todo);
451: }
452: return todo;
453: }
454:
455: static int
456: play_filt_dec(struct slot *s, void *in, void *out, int todo)
457: {
458: void *tmp;
459:
460: tmp = s->convbuf;
461: if (tmp) {
462: switch (s->afile.fmt) {
463: case AFILE_FMT_PCM:
464: dec_do(&s->conv, in, tmp, todo);
465: break;
466: case AFILE_FMT_ULAW:
467: dec_do_ulaw(&s->conv, in, tmp, todo, 0);
468: break;
469: case AFILE_FMT_ALAW:
470: dec_do_ulaw(&s->conv, in, tmp, todo, 1);
471: break;
472: case AFILE_FMT_FLOAT:
473: dec_do_float(&s->conv, in, tmp, todo);
474: break;
475: }
476: }
477: return play_filt_resamp(s, tmp ? tmp : in, out, todo);
478: }
1.108 ratchov 479:
1.120 ratchov 480: /*
1.146 ratchov 481: * Mix as many as possible frames (but not more than a block) from the
482: * slot buffer to the given location. Return the number of frames mixed
483: * in the output buffer
1.120 ratchov 484: */
1.146 ratchov 485: static int
486: slot_mix_badd(struct slot *s, adata_t *odata)
487: {
488: adata_t *idata;
489: int icount, todo, done;
490:
491: idata = (adata_t *)abuf_rgetblk(&s->buf, &icount);
492: todo = icount / s->bpf;
493: if (todo > s->round)
494: todo = s->round;
495: #ifdef DEBUG
496: if (todo == 0) {
497: log_puts("slot_mix_badd: not enough data\n");
498: panic();
499: }
1.133 ratchov 500: #endif
1.146 ratchov 501: done = play_filt_dec(s, idata, odata, todo);
502: abuf_rdiscard(&s->buf, todo * s->bpf);
503: return done;
504: }
505:
506: static int
507: rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo)
508: {
509: int i, vol, offs, nch;
510: void *out = res_out;
511:
512: out = (s->resampbuf) ? s->resampbuf : res_out;
513:
514: nch = s->cmap.nch;
515: vol = ADATA_UNIT / s->join;
516: cmap_copy(&s->cmap, in, out, vol, todo);
517:
518: offs = 0;
519: for (i = s->join - 1; i > 0; i--) {
520: offs += nch;
521: cmap_add(&s->cmap, (adata_t *)in + offs, out, vol, todo);
522: }
523: offs = 0;
524: for (i = s->expand - 1; i > 0; i--) {
525: offs += nch;
526: cmap_copy(&s->cmap, in, (adata_t *)out + offs, vol, todo);
527: }
528: if (s->resampbuf) {
529: todo = resamp_do(&s->resamp,
530: s->resampbuf, res_out, todo);
531: }
532: return todo;
533: }
534:
535: static int
536: rec_filt_enc(struct slot *s, void *in, void *out, int todo)
537: {
538: void *tmp;
539:
540: tmp = s->convbuf;
541: todo = rec_filt_resamp(s, in, tmp ? tmp : out, todo);
542: if (tmp)
543: enc_do(&s->conv, tmp, out, todo);
544: return todo;
545: }
1.133 ratchov 546:
547: /*
1.146 ratchov 548: * Copy "todo" frames from the given buffer to the slot buffer,
549: * but not more than a block.
1.133 ratchov 550: */
1.146 ratchov 551: static void
552: slot_sub_bcopy(struct slot *s, adata_t *idata, int todo)
553: {
554: adata_t *odata;
555: int ocount;
556:
557: odata = (adata_t *)abuf_wgetblk(&s->buf, &ocount);
558: #ifdef DEBUG
559: if (ocount < s->round * s->bpf) {
560: log_puts("slot_sub_bcopy: not enough space\n");
561: panic();
562: }
1.120 ratchov 563: #endif
1.146 ratchov 564: ocount = rec_filt_enc(s, idata, odata, todo);
565: abuf_wcommit(&s->buf, ocount * s->bpf);
566: }
567:
568: static int
569: dev_open(char *dev, int mode, int bufsz, char *port)
570: {
571: int rate, pmax, rmax;
572: struct sio_par par;
573: struct slot *s;
574:
575: if (port) {
576: dev_port = port;
577: dev_mh = mio_open(dev_port, MIO_IN, 0);
578: if (dev_mh == NULL) {
579: log_puts(port);
580: log_puts(": couldn't open midi port\n");
581: return 0;
582: }
583: } else
584: dev_mh = NULL;
585:
586: dev_name = dev;
587: dev_sh = sio_open(dev, mode, 0);
588: if (dev_sh == NULL) {
589: log_puts(dev_name);
590: log_puts(": couldn't open audio device\n");
591: return 0;
592: }
593:
594: rate = pmax = rmax = 0;
595: for (s = slot_list; s != NULL; s = s->next) {
596: if (s->afile.rate > rate)
597: rate = s->afile.rate;
598: if (s->mode == SIO_PLAY) {
599: if (s->cmax > pmax)
600: pmax = s->cmax;
601: }
602: if (s->mode == SIO_REC) {
603: if (s->cmax > rmax)
604: rmax = s->cmax;
605: }
606: }
607: sio_initpar(&par);
608: par.bits = ADATA_BITS;
609: par.bps = sizeof(adata_t);
610: par.msb = 0;
611: par.le = SIO_LE_NATIVE;
612: if (mode & SIO_PLAY)
613: par.pchan = pmax + 1;
614: if (mode & SIO_REC)
615: par.rchan = rmax + 1;
616: par.appbufsz = bufsz > 0 ? bufsz : rate * DEFAULT_BUFSZ_MS / 1000;
617: if (!sio_setpar(dev_sh, &par) || !sio_getpar(dev_sh, &par)) {
618: log_puts(dev_name);
619: log_puts(": couldn't set audio params\n");
620: return 0;
621: }
622: if (par.bits != ADATA_BITS ||
623: par.bps != sizeof(adata_t) ||
624: par.le != SIO_LE_NATIVE ||
625: (par.bps != SIO_BPS(par.bits) && par.msb)) {
626: log_puts(dev_name);
627: log_puts(": unsupported audio params\n");
628: return 0;
629: }
630: dev_mode = mode;
631: dev_rate = par.rate;
632: dev_bufsz = par.bufsz;
633: dev_round = par.round;
634: if (mode & SIO_PLAY) {
635: dev_pchan = par.pchan;
636: dev_pbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round);
637: }
638: if (mode & SIO_REC) {
639: dev_rchan = par.rchan;
640: dev_rbuf = xmalloc(sizeof(adata_t) * dev_rchan * dev_round);
641: }
642: dev_mmcpos = 0;
643: dev_pstate = DEV_STOP;
644: if (log_level >= 2) {
645: log_puts(dev_name);
646: log_puts(": ");
647: log_putu(dev_rate);
648: log_puts("Hz");
649: if (dev_mode & SIO_PLAY) {
650: log_puts(", play 0:");
651: log_puti(dev_pchan - 1);
652: }
653: if (dev_mode & SIO_REC) {
654: log_puts(", rec 0:");
655: log_puti(dev_rchan - 1);
656: }
657: log_puts(", ");
658: log_putu(dev_bufsz / dev_round);
659: log_puts(" blocks of ");
660: log_putu(dev_round);
661: log_puts(" frames\n");
662: }
663: return 1;
664: }
1.120 ratchov 665:
1.146 ratchov 666: static void
667: dev_close(void)
668: {
669: sio_close(dev_sh);
670: if (dev_mh)
671: mio_close(dev_mh);
672: if (dev_mode & SIO_PLAY)
1.150 ! mmcc 673: free(dev_pbuf);
1.146 ratchov 674: if (dev_mode & SIO_REC)
1.150 ! mmcc 675: free(dev_rbuf);
1.146 ratchov 676: }
677:
678: static void
679: dev_master(int val)
680: {
681: struct slot *s;
682: int mastervol, slotvol;
1.143 ratchov 683:
1.146 ratchov 684: mastervol = MIDI_TO_ADATA(dev_volctl);
685: for (s = slot_list; s != NULL; s = s->next) {
686: slotvol = MIDI_TO_ADATA(val);
687: s->vol = ADATA_MUL(mastervol, slotvol);
688: }
1.78 ratchov 689: #ifdef DEBUG
1.146 ratchov 690: if (log_level >= 3) {
691: log_puts("master volume set to ");
692: log_putu(val);
693: log_puts("\n");
694: }
1.78 ratchov 695: #endif
1.146 ratchov 696: }
1.7 deraadt 697:
1.146 ratchov 698: static void
699: dev_slotvol(int midich, int val)
700: {
701: struct slot *s;
702: int mastervol, slotvol;
703:
704: for (s = slot_list; s != NULL; s = s->next) {
705: if (midich == 0) {
706: mastervol = MIDI_TO_ADATA(dev_volctl);
707: slotvol = MIDI_TO_ADATA(val);
708: s->vol = ADATA_MUL(mastervol, slotvol);
709: #ifdef DEBUG
710: if (log_level >= 3) {
711: slot_log(s);
712: log_puts(": volume set to ");
713: log_putu(val);
714: log_puts("\n");
715: }
716: #endif
717: break;
718: }
719: }
720: }
1.129 ratchov 721:
1.28 ratchov 722: /*
1.146 ratchov 723: * start all slots simultaneously
1.28 ratchov 724: */
1.146 ratchov 725: static void
726: dev_mmcstart(void)
1.28 ratchov 727: {
1.146 ratchov 728: struct slot *s;
729:
730: if (dev_pstate == DEV_STOP) {
731: dev_pstate = DEV_START;
732: for (s = slot_list; s != NULL; s = s->next)
733: slot_start(s, dev_mmcpos);
734: dev_prime = (dev_mode & SIO_PLAY) ? dev_bufsz / dev_round : 0;
735: sio_start(dev_sh);
736: if (log_level >= 2)
737: log_puts("started\n");
738: } else {
739: #ifdef DEBUG
740: if (log_level >= 3)
741: log_puts("ignoring mmc start\n");
742: #endif
743: }
1.28 ratchov 744: }
1.22 ratchov 745:
1.146 ratchov 746: /*
747: * stop all slots simultaneously
748: */
749: static void
750: dev_mmcstop(void)
751: {
752: struct slot *s;
753:
754: if (dev_pstate == DEV_START) {
755: dev_pstate = DEV_STOP;
756: for (s = slot_list; s != NULL; s = s->next)
757: slot_stop(s);
758: sio_stop(dev_sh);
759: if (log_level >= 2)
760: log_puts("stopped\n");
761: } else {
1.78 ratchov 762: #ifdef DEBUG
1.146 ratchov 763: if (log_level >= 3)
764: log_puts("ignored mmc stop\n");
765: #endif
766: }
767: }
768:
1.78 ratchov 769: /*
1.146 ratchov 770: * relocate all slots simultaneously
1.78 ratchov 771: */
1.146 ratchov 772: static void
773: dev_mmcloc(unsigned int mmc)
1.78 ratchov 774: {
1.146 ratchov 775: if (dev_mmcpos == mmc)
776: return;
777: dev_mmcpos = mmc;
778: if (log_level >= 2) {
779: log_puts("relocated to ");
780: log_putu((dev_mmcpos / (MTC_SEC * 3600)) % 24);
781: log_puts(":");
782: log_putu((dev_mmcpos / (MTC_SEC * 60)) % 60);
783: log_puts(":");
784: log_putu((dev_mmcpos / (MTC_SEC)) % 60);
785: log_puts(".");
786: log_putu((dev_mmcpos / (MTC_SEC / 100)) % 100);
787: log_puts("\n");
788: }
789: if (dev_pstate == DEV_START) {
790: dev_mmcstop();
791: dev_mmcstart();
792: }
793: }
794:
795: static void
796: dev_imsg(unsigned char *msg, unsigned int len)
797: {
798: struct sysex *x;
799: unsigned int fps, chan;
800:
801: if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
802: chan = msg[0] & MIDI_CHANMASK;
803: dev_slotvol(chan, msg[2]);
804: return;
805: }
806: x = (struct sysex *)msg;
807: if (x->start != SYSEX_START)
808: return;
809: if (len < SYSEX_SIZE(empty))
810: return;
811: if (x->type != SYSEX_TYPE_RT)
812: return;
813: if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
814: if (len == SYSEX_SIZE(master))
815: dev_master(x->u.master.coarse);
816: return;
817: }
818: if (x->id0 != SYSEX_MMC)
819: return;
820: switch (x->id1) {
821: case SYSEX_MMC_STOP:
822: if (len != SYSEX_SIZE(stop))
823: return;
824: dev_mmcstop();
825: break;
826: case SYSEX_MMC_START:
827: if (len != SYSEX_SIZE(start))
828: return;
829: dev_mmcstart();
830: break;
831: case SYSEX_MMC_LOC:
832: if (len != SYSEX_SIZE(loc) ||
833: x->u.loc.len != SYSEX_MMC_LOC_LEN ||
834: x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
835: return;
836: switch (x->u.loc.hr >> 5) {
837: case MTC_FPS_24:
838: fps = 24;
839: break;
840: case MTC_FPS_25:
841: fps = 25;
842: break;
843: case MTC_FPS_30:
844: fps = 30;
845: break;
846: default:
847: dev_mmcstop();
848: return;
849: }
850: dev_mmcloc((x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
851: x->u.loc.min * 60 * MTC_SEC +
852: x->u.loc.sec * MTC_SEC +
853: x->u.loc.fr * (MTC_SEC / fps) +
854: x->u.loc.cent * (MTC_SEC / 100 / fps));
855: break;
856: }
1.78 ratchov 857: }
858:
859: /*
1.149 ratchov 860: * parse the given data chunk and call imsg() for each message
1.78 ratchov 861: */
1.146 ratchov 862: static void
863: midi_in(unsigned char *idata, int icount)
1.78 ratchov 864: {
1.146 ratchov 865: int i;
866: unsigned char c;
867:
868: for (i = 0; i < icount; i++) {
869: c = *idata++;
870: if (c >= 0xf8) {
1.149 ratchov 871: /* we don't use real-time events */
1.146 ratchov 872: } else if (c == SYSEX_END) {
873: if (dev_mst == SYSEX_START) {
874: dev_msg[dev_midx++] = c;
875: dev_imsg(dev_msg, dev_midx);
876: }
877: dev_mst = 0;
878: dev_midx = 0;
879: } else if (c >= 0xf0) {
880: dev_msg[0] = c;
881: dev_mlen = common_len[c & 7];
882: dev_mst = c;
883: dev_midx = 1;
884: } else if (c >= 0x80) {
885: dev_msg[0] = c;
886: dev_mlen = voice_len[(c >> 4) & 7];
887: dev_mst = c;
888: dev_midx = 1;
889: } else if (dev_mst) {
890: if (dev_midx == 0 && dev_mst != SYSEX_START)
891: dev_msg[dev_midx++] = dev_mst;
892: dev_msg[dev_midx++] = c;
893: if (dev_midx == dev_mlen) {
894: dev_imsg(dev_msg, dev_midx);
895: if (dev_mst >= 0xf0)
896: dev_mst = 0;
897: dev_midx = 0;
898: } else if (dev_midx == MIDI_MSGMAX) {
899: /* sysex too long */
900: dev_mst = 0;
901: }
902: }
903: }
1.78 ratchov 904: }
1.15 ratchov 905:
1.146 ratchov 906: static int
907: slot_list_mix(unsigned int round, unsigned int pchan, adata_t *pbuf)
1.15 ratchov 908: {
1.146 ratchov 909: unsigned int done, n;
910: struct slot *s;
1.13 uwe 911:
1.146 ratchov 912: memset(pbuf, 0, pchan * round * sizeof(adata_t));
913: done = 0;
914: for (s = slot_list; s != NULL; s = s->next) {
915: if (s->pstate == SLOT_INIT || !(s->mode & SIO_PLAY))
916: continue;
917: if (s->pstate == SLOT_STOP && s->buf.used < s->bpf) {
918: #ifdef DEBUG
919: if (log_level >= 3) {
920: slot_log(s);
921: log_puts(": drained, done\n");
922: }
923: #endif
1.148 ratchov 924: slot_stop(s);
1.146 ratchov 925: continue;
926: }
927: n = slot_mix_badd(s, dev_pbuf);
928: if (n > done)
929: done = n;
930: }
931: return done;
1.15 ratchov 932: }
1.13 uwe 933:
1.146 ratchov 934: static int
935: slot_list_copy(unsigned int count, unsigned int rchan, adata_t *rbuf)
1.15 ratchov 936: {
1.146 ratchov 937: unsigned int done;
938: struct slot *s;
1.28 ratchov 939:
1.146 ratchov 940: done = 0;
941: for (s = slot_list; s != NULL; s = s->next) {
942: if (s->pstate == SLOT_INIT || !(s->mode & SIO_REC))
943: continue;
944: slot_sub_bcopy(s, rbuf, count);
945: done = count;
946: }
947: return done;
1.15 ratchov 948: }
1.4 millert 949:
1.146 ratchov 950: static void
951: slot_list_iodo(void)
1.15 ratchov 952: {
1.146 ratchov 953: struct slot *s;
954:
955: for (s = slot_list; s != NULL; s = s->next) {
956: if (s->pstate != SLOT_RUN)
957: continue;
958: if ((s->mode & SIO_PLAY) && (s->buf.used == 0))
959: slot_fill(s);
960: if ((s->mode & SIO_REC) && (s->buf.used == s->buf.len))
961: slot_flush(s);
962: }
1.1 kstailey 963: }
964:
1.146 ratchov 965: static int
966: offline(void)
1.74 ratchov 967: {
1.146 ratchov 968: unsigned int todo;
969: int rate, cmax;
970: struct slot *s;
971:
972: rate = cmax = 0;
973: for (s = slot_list; s != NULL; s = s->next) {
974: if (s->afile.rate > rate)
975: rate = s->afile.rate;
976: if (s->cmax > cmax)
977: cmax = s->cmax;
978: }
979: dev_sh = NULL;
980: dev_name = "offline";
981: dev_mode = SIO_PLAY | SIO_REC;
982: dev_rate = rate;
983: dev_bufsz = rate;
984: dev_round = rate;
985: dev_pchan = dev_rchan = cmax + 1;
986: dev_pbuf = dev_rbuf = xmalloc(sizeof(adata_t) * dev_pchan * dev_round);
987: dev_pstate = DEV_STOP;
988: dev_mmcpos = 0;
989: for (s = slot_list; s != NULL; s = s->next)
990: slot_init(s);
991: for (s = slot_list; s != NULL; s = s->next)
992: slot_start(s, 0);
993: for (;;) {
994: todo = slot_list_mix(dev_round, dev_pchan, dev_pbuf);
995: if (todo == 0)
996: break;
997: slot_list_copy(todo, dev_pchan, dev_pbuf);
998: slot_list_iodo();
999: }
1.150 ! mmcc 1000: free(dev_pbuf);
1.146 ratchov 1001: while (slot_list)
1002: slot_del(slot_list);
1003: return 1;
1.74 ratchov 1004: }
1005:
1.146 ratchov 1006: static int
1007: playrec_cycle(void)
1.84 ratchov 1008: {
1.146 ratchov 1009: unsigned int n, todo;
1010: unsigned char *p;
1011: int pcnt, rcnt;
1012:
1013: #ifdef DEBUG
1014: if (log_level >= 4) {
1015: log_puts(dev_name);
1016: log_puts(": cycle, prime = ");
1017: log_putu(dev_prime);
1018: log_puts("\n");
1019: }
1020: #endif
1021: pcnt = rcnt = 0;
1022: if (dev_mode & SIO_REC) {
1023: if (dev_prime > 0)
1024: dev_prime--;
1025: else {
1026: todo = dev_round * dev_rchan * sizeof(adata_t);
1027: p = (unsigned char *)dev_rbuf;
1028: while (todo > 0) {
1029: n = sio_read(dev_sh, p, todo);
1030: if (n == 0) {
1031: log_puts(dev_name);
1032: log_puts(": failed to read from device\n");
1033: return 0;
1034: }
1035: p += n;
1036: todo -= n;
1037: }
1038: rcnt = slot_list_copy(dev_round, dev_rchan, dev_rbuf);
1039: }
1040: }
1041: if (dev_mode & SIO_PLAY) {
1042: pcnt = slot_list_mix(dev_round, dev_pchan, dev_pbuf);
1043: todo = sizeof(adata_t) * dev_pchan * dev_round;
1044: n = sio_write(dev_sh, dev_pbuf, todo);
1045: if (n == 0) {
1046: log_puts(dev_name);
1047: log_puts(": failed to write to device\n");
1048: return 0;
1049: }
1050: }
1051: slot_list_iodo();
1052: return pcnt > 0 || rcnt > 0;
1.84 ratchov 1053: }
1054:
1.146 ratchov 1055: static void
1056: sigint(int s)
1.22 ratchov 1057: {
1.146 ratchov 1058: if (quit_flag)
1059: _exit(1);
1060: quit_flag = 1;
1.22 ratchov 1061: }
1062:
1.146 ratchov 1063: static int
1064: playrec(char *dev, int mode, int bufsz, char *port)
1.61 ratchov 1065: {
1.146 ratchov 1066: #define MIDIBUFSZ 0x100
1067: unsigned char mbuf[MIDIBUFSZ];
1.61 ratchov 1068: struct sigaction sa;
1.146 ratchov 1069: struct pollfd *pfds;
1070: struct slot *s;
1071: int n, ns, nm, ev;
1072:
1073: if (!dev_open(dev, mode, bufsz, port))
1074: return 0;
1075: n = sio_nfds(dev_sh);
1076: if (dev_mh)
1077: n += mio_nfds(dev_mh);
1078: pfds = xmalloc(n * sizeof(struct pollfd));
1079: for (s = slot_list; s != NULL; s = s->next)
1080: slot_init(s);
1081: if (dev_mh == NULL)
1082: dev_mmcstart();
1083: else {
1084: if (log_level >= 2)
1085: log_puts("ready, waiting for mmc messages\n");
1086: }
1.61 ratchov 1087:
1088: quit_flag = 0;
1089: sigfillset(&sa.sa_mask);
1090: sa.sa_flags = SA_RESTART;
1091: sa.sa_handler = sigint;
1.146 ratchov 1092: sigaction(SIGINT, &sa, NULL);
1093: sigaction(SIGTERM, &sa, NULL);
1094: sigaction(SIGHUP, &sa, NULL);
1095: while (!quit_flag) {
1096: if (dev_pstate == DEV_START) {
1097: ev = 0;
1098: if (mode & SIO_PLAY)
1099: ev |= POLLOUT;
1100: if (mode & SIO_REC)
1101: ev |= POLLIN;
1102: ns = sio_pollfd(dev_sh, pfds, ev);
1103: } else
1104: ns = 0;
1105: if (dev_mh)
1106: nm = mio_pollfd(dev_mh, pfds + ns, POLLIN);
1107: else
1108: nm = 0;
1109: if (poll(pfds, ns + nm, -1) < 0) {
1110: if (errno == EINTR)
1111: continue;
1112: log_puts("poll failed\n");
1113: panic();
1114: }
1115: if (dev_pstate == DEV_START) {
1116: ev = sio_revents(dev_sh, pfds);
1117: if (ev & POLLHUP) {
1118: log_puts(dev);
1119: log_puts(": audio device gone, stopping\n");
1120: break;
1121: }
1122: if (ev & (POLLIN | POLLOUT)) {
1123: if (!playrec_cycle() && dev_mh == NULL)
1124: break;
1125: }
1126: }
1127: if (dev_mh) {
1128: ev = mio_revents(dev_mh, pfds + ns);
1129: if (ev & POLLHUP) {
1130: log_puts(dev_port);
1131: log_puts(": midi port gone, stopping\n");
1132: break;
1133: }
1134: if (ev & POLLIN) {
1135: n = mio_read(dev_mh, mbuf, MIDIBUFSZ);
1136: midi_in(mbuf, n);
1137: }
1138: }
1139: }
1140: sigfillset(&sa.sa_mask);
1141: sa.sa_flags = SA_RESTART;
1142: sa.sa_handler = SIG_DFL;
1143: sigaction(SIGINT, &sa, NULL);
1144: sigaction(SIGTERM, &sa, NULL);
1145: sigaction(SIGHUP, &sa, NULL);
1146:
1147: if (dev_pstate == DEV_START)
1148: dev_mmcstop();
1.150 ! mmcc 1149: free(pfds);
1.146 ratchov 1150: dev_close();
1151: while (slot_list)
1152: slot_del(slot_list);
1153: return 1;
1154: }
1155:
1156: static int
1157: opt_onoff(char *s, int *flag)
1158: {
1159: if (strcmp("off", s) == 0) {
1160: *flag = 0;
1161: return 1;
1162: }
1163: if (strcmp("on", s) == 0) {
1164: *flag = 1;
1165: return 1;
1166: }
1167: log_puts(s);
1168: log_puts(": on/off expected\n");
1169: return 0;
1170: }
1171:
1172: static int
1173: opt_enc(char *s, struct aparams *par)
1174: {
1175: int len;
1176:
1177: len = aparams_strtoenc(par, s);
1178: if (len == 0 || s[len] != '\0') {
1179: log_puts(s);
1180: log_puts(": bad encoding\n");
1181: return 0;
1182: }
1183: return 1;
1184: }
1185:
1186: static int
1187: opt_hdr(char *s, int *hdr)
1188: {
1189: if (strcmp("auto", s) == 0) {
1190: *hdr = AFILE_HDR_AUTO;
1191: return 1;
1192: }
1193: if (strcmp("raw", s) == 0) {
1194: *hdr = AFILE_HDR_RAW;
1195: return 1;
1196: }
1197: if (strcmp("wav", s) == 0) {
1198: *hdr = AFILE_HDR_WAV;
1199: return 1;
1200: }
1201: if (strcmp("aiff", s) == 0) {
1202: *hdr = AFILE_HDR_AIFF;
1203: return 1;
1204: }
1205: if (strcmp("au", s) == 0) {
1206: *hdr = AFILE_HDR_AU;
1207: return 1;
1208: }
1209: log_puts(s);
1210: log_puts(": bad header type\n");
1211: return 0;
1212: }
1213:
1214: static int
1215: opt_ch(char *s, int *rcmin, int *rcmax)
1216: {
1217: char *next, *end;
1218: long cmin, cmax;
1219:
1220: errno = 0;
1221: cmin = strtol(s, &next, 10);
1222: if (next == s || *next != ':')
1223: goto failed;
1224: cmax = strtol(++next, &end, 10);
1225: if (end == next || *end != '\0')
1226: goto failed;
1227: if (cmin < 0 || cmax < cmin || cmax >= NCHAN_MAX)
1228: goto failed;
1229: *rcmin = cmin;
1230: *rcmax = cmax;
1231: return 1;
1232: failed:
1233: log_puts(s);
1234: log_puts(": channel range expected\n");
1235: return 0;
1.61 ratchov 1236: }
1237:
1.146 ratchov 1238: static int
1239: opt_num(char *s, int min, int max, int *num)
1.61 ratchov 1240: {
1.146 ratchov 1241: const char *errstr;
1.61 ratchov 1242:
1.146 ratchov 1243: *num = strtonum(s, min, max, &errstr);
1244: if (errstr) {
1245: log_puts(s);
1246: log_puts(": expected integer between ");
1247: log_puti(min);
1248: log_puts(" and ");
1249: log_puti(max);
1250: log_puts("\n");
1251: return 0;
1252: }
1253: return 1;
1.120 ratchov 1254: }
1255:
1.1 kstailey 1256: int
1.120 ratchov 1257: main(int argc, char **argv)
1.1 kstailey 1258: {
1.146 ratchov 1259: int dup, cmin, cmax, rate, vol, bufsz, hdr, mode;
1260: char *port, *dev;
1261: struct aparams par;
1262: int n_flag, c;
1263:
1264: vol = 127;
1265: dup = 0;
1.120 ratchov 1266: bufsz = 0;
1.146 ratchov 1267: rate = DEFAULT_RATE;
1268: cmin = 0;
1269: cmax = 1;
1270: aparams_init(&par);
1271: hdr = AFILE_HDR_AUTO;
1272: n_flag = 0;
1273: port = NULL;
1274: dev = NULL;
1275: mode = 0;
1276:
1277: while ((c = getopt(argc, argv, "b:c:de:f:h:i:j:no:q:r:t:v:")) != -1) {
1.15 ratchov 1278: switch (c) {
1.146 ratchov 1279: case 'b':
1280: if (!opt_num(optarg, 1, RATE_MAX, &bufsz))
1281: return 1;
1.74 ratchov 1282: break;
1.15 ratchov 1283: case 'c':
1.146 ratchov 1284: if (!opt_ch(optarg, &cmin, &cmax))
1285: return 1;
1.15 ratchov 1286: break;
1.146 ratchov 1287: case 'd':
1288: log_level++;
1.15 ratchov 1289: break;
1290: case 'e':
1.146 ratchov 1291: if (!opt_enc(optarg, &par))
1292: return 1;
1.15 ratchov 1293: break;
1.146 ratchov 1294: case 'f':
1295: dev = optarg;
1.15 ratchov 1296: break;
1.146 ratchov 1297: case 'h':
1298: if (!opt_hdr(optarg, &hdr))
1299: return 1;
1.35 ratchov 1300: break;
1.15 ratchov 1301: case 'i':
1.146 ratchov 1302: if (!slot_new(optarg, SIO_PLAY,
1303: &par, hdr, cmin, cmax, rate, dup, vol))
1304: return 1;
1305: mode |= SIO_PLAY;
1.15 ratchov 1306: break;
1.146 ratchov 1307: case 'j':
1308: if (!opt_onoff(optarg, &dup))
1309: return 1;
1.92 ratchov 1310: break;
1.146 ratchov 1311: case 'n':
1312: n_flag = 1;
1.4 millert 1313: break;
1.146 ratchov 1314: case 'o':
1315: if (!slot_new(optarg, SIO_REC,
1316: &par, hdr, cmin, cmax, rate, dup, 0))
1317: return 1;
1318: mode |= SIO_REC;
1.74 ratchov 1319: break;
1.146 ratchov 1320: case 'q':
1321: port = optarg;
1.120 ratchov 1322: break;
1.146 ratchov 1323: case 'r':
1324: if (!opt_num(optarg, RATE_MIN, RATE_MAX, &rate))
1325: return 1;
1.120 ratchov 1326: break;
1.146 ratchov 1327: case 'v':
1328: if (!opt_num(optarg, 0, MIDI_MAXCTL, &vol))
1329: return 1;
1.92 ratchov 1330: break;
1.11 jaredy 1331: default:
1.146 ratchov 1332: goto bad_usage;
1.4 millert 1333: }
1334: }
1335: argc -= optind;
1336: argv += optind;
1.146 ratchov 1337: if (argc != 0) {
1338: bad_usage:
1339: log_puts(usagestr);
1340: return 1;
1341: }
1342: if (n_flag) {
1343: if (dev != NULL || port != NULL) {
1344: log_puts("-f and -q make no sense in off-line mode\n");
1345: return 1;
1.125 ratchov 1346: }
1.146 ratchov 1347: if (mode != (SIO_PLAY | SIO_REC)) {
1348: log_puts("both -i and -o required\n");
1349: return 0;
1350: }
1351: if (!offline())
1352: return 1;
1.125 ratchov 1353: } else {
1.146 ratchov 1354: if (dev == NULL)
1355: dev = SIO_DEVANY;
1356: if (mode == 0) {
1.149 ratchov 1357: log_puts("at least -i or -o required\n");
1.146 ratchov 1358: return 1;
1359: }
1360: if (!playrec(dev, mode, bufsz, port))
1361: return 1;
1.120 ratchov 1362: }
1.61 ratchov 1363: return 0;
1.1 kstailey 1364: }