Annotation of src/usr.bin/aucat/wav.c, Revision 1.17
1.7 ratchov 1: /*
2: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
3: *
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: */
16:
1.1 ratchov 17: #include <stdlib.h>
1.10 ratchov 18: #include <stdio.h>
19: #include <fcntl.h>
20: #include <unistd.h>
1.1 ratchov 21:
1.10 ratchov 22: #include "abuf.h"
23: #include "aproc.h"
1.1 ratchov 24: #include "conf.h"
1.10 ratchov 25: #include "dev.h"
1.15 ratchov 26: #include "midi.h"
1.1 ratchov 27: #include "wav.h"
1.15 ratchov 28: #include "opt.h"
1.11 ratchov 29: #ifdef DEBUG
30: #include "dbg.h"
31: #endif
1.1 ratchov 32:
1.6 ratchov 33: short wav_ulawmap[256] = {
34: -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
35: -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
36: -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
37: -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
38: -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
39: -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
40: -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
41: -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
42: -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
43: -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
44: -876, -844, -812, -780, -748, -716, -684, -652,
45: -620, -588, -556, -524, -492, -460, -428, -396,
46: -372, -356, -340, -324, -308, -292, -276, -260,
47: -244, -228, -212, -196, -180, -164, -148, -132,
48: -120, -112, -104, -96, -88, -80, -72, -64,
49: -56, -48, -40, -32, -24, -16, -8, 0,
50: 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
51: 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
52: 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
53: 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
54: 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
55: 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
56: 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
57: 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
58: 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
59: 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
60: 876, 844, 812, 780, 748, 716, 684, 652,
61: 620, 588, 556, 524, 492, 460, 428, 396,
62: 372, 356, 340, 324, 308, 292, 276, 260,
63: 244, 228, 212, 196, 180, 164, 148, 132,
64: 120, 112, 104, 96, 88, 80, 72, 64,
65: 56, 48, 40, 32, 24, 16, 8, 0
66: };
67:
68: short wav_alawmap[256] = {
69: -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
70: -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
71: -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
72: -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
73: -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
74: -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
75: -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
76: -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
77: -344, -328, -376, -360, -280, -264, -312, -296,
78: -472, -456, -504, -488, -408, -392, -440, -424,
79: -88, -72, -120, -104, -24, -8, -56, -40,
80: -216, -200, -248, -232, -152, -136, -184, -168,
81: -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
82: -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
83: -688, -656, -752, -720, -560, -528, -624, -592,
84: -944, -912, -1008, -976, -816, -784, -880, -848,
85: 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
86: 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
87: 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
88: 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
89: 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
90: 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
91: 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
92: 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
93: 344, 328, 376, 360, 280, 264, 312, 296,
94: 472, 456, 504, 488, 408, 392, 440, 424,
95: 88, 72, 120, 104, 24, 8, 56, 40,
96: 216, 200, 248, 232, 152, 136, 184, 168,
97: 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
98: 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
99: 688, 656, 752, 720, 560, 528, 624, 592,
100: 944, 912, 1008, 976, 816, 784, 880, 848
101: };
102:
1.1 ratchov 103: /*
1.7 ratchov 104: * Max data of a .wav file. The total file size must be smaller than
1.1 ratchov 105: * 2^31, and we also have to leave some space for the headers (around 40
1.7 ratchov 106: * bytes).
1.3 ratchov 107: */
1.1 ratchov 108: #define WAV_DATAMAX (0x7fff0000)
109:
110: struct fileops wav_ops = {
111: "wav",
112: sizeof(struct wav),
113: wav_close,
114: wav_read,
115: wav_write,
116: NULL, /* start */
117: NULL, /* stop */
118: pipe_nfds,
119: pipe_pollfd,
120: pipe_revents
121: };
122:
1.10 ratchov 123: int rwav_in(struct aproc *, struct abuf *);
124: int rwav_out(struct aproc *, struct abuf *);
125: void rwav_eof(struct aproc *, struct abuf *);
126: void rwav_hup(struct aproc *, struct abuf *);
127: void rwav_done(struct aproc *);
1.15 ratchov 128: struct aproc *rwav_new(struct file *);
1.10 ratchov 129:
130: int wwav_in(struct aproc *, struct abuf *);
131: int wwav_out(struct aproc *, struct abuf *);
132: void wwav_eof(struct aproc *, struct abuf *);
133: void wwav_hup(struct aproc *, struct abuf *);
134: void wwav_done(struct aproc *);
1.15 ratchov 135: struct aproc *wwav_new(struct file *);
136:
137: void wav_setvol(void *, unsigned);
138: void wav_startreq(void *);
139: void wav_stopreq(void *);
140: void wav_locreq(void *, unsigned);
141:
142: struct ctl_ops ctl_wavops = {
143: wav_setvol,
144: wav_startreq,
145: wav_stopreq,
146: wav_locreq
147: };
1.10 ratchov 148:
149: struct aproc_ops rwav_ops = {
150: "rwav",
151: rwav_in,
152: rwav_out,
1.15 ratchov 153: rfile_eof,
154: rfile_hup,
1.10 ratchov 155: NULL, /* newin */
156: NULL, /* newout */
157: NULL, /* ipos */
158: NULL, /* opos */
159: rwav_done
160: };
161:
162: struct aproc_ops wwav_ops = {
163: "wwav",
164: wwav_in,
165: wwav_out,
1.15 ratchov 166: wfile_eof,
167: wfile_hup,
1.10 ratchov 168: NULL, /* newin */
169: NULL, /* newout */
170: NULL, /* ipos */
171: NULL, /* opos */
172: wwav_done
173: };
174:
1.15 ratchov 175: #ifdef DEBUG
176: /*
177: * print the given wav structure
178: */
179: void
180: wav_dbg(struct wav *f)
181: {
182: static char *pstates[] = { "ini", "sta", "rdy", "run", "fai" };
183:
184: dbg_puts("wav(");
185: if (f->slot >= 0 && APROC_OK(dev_midi)) {
186: dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
187: dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
188: } else
189: dbg_puts(f->pipe.file.name);
190: dbg_puts(")/");
191: dbg_puts(pstates[f->pstate]);
192: }
193: #endif
194:
195: /*
196: * convert ``count'' samples using the given char->short map
197: */
198: void
199: wav_conv(unsigned char *data, unsigned count, short *map)
1.13 ratchov 200: {
1.15 ratchov 201: unsigned i;
202: unsigned char *iptr;
203: short *optr;
1.13 ratchov 204:
1.15 ratchov 205: iptr = data + count;
206: optr = (short *)data + count;
207: for (i = count; i > 0; i--) {
208: --optr;
209: --iptr;
210: *optr = map[*iptr];
211: }
1.13 ratchov 212: }
213:
1.15 ratchov 214: /*
215: * read method of the file structure
216: */
217: unsigned
218: wav_read(struct file *file, unsigned char *data, unsigned count)
1.10 ratchov 219: {
1.15 ratchov 220: struct wav *f = (struct wav *)file;
221: unsigned n;
222:
223: if (f->map)
224: count /= sizeof(short);
225: if (f->rbytes >= 0 && count > f->rbytes) {
226: count = f->rbytes; /* file->rbytes fits in count */
227: if (count == 0) {
228: #ifdef DEBUG
229: if (debug_level >= 3) {
230: wav_dbg(f);
231: dbg_puts(": read complete\n");
232: }
233: #endif
234: if (!f->tr)
235: file_eof(&f->pipe.file);
236: return 0;
237: }
238: }
239: n = pipe_read(file, data, count);
240: if (n == 0)
1.14 ratchov 241: return 0;
1.15 ratchov 242: if (f->rbytes >= 0)
243: f->rbytes -= n;
244: if (f->map) {
245: wav_conv(data, n, f->map);
246: n *= sizeof(short);
247: }
248: return n;
249: }
250:
251: /*
252: * write method of the file structure
253: */
254: unsigned
255: wav_write(struct file *file, unsigned char *data, unsigned count)
256: {
257: struct wav *f = (struct wav *)file;
258: unsigned n;
259:
260: if (f->wbytes >= 0 && count > f->wbytes) {
261: count = f->wbytes; /* wbytes fits in count */
262: if (count == 0) {
263: #ifdef DEBUG
264: if (debug_level >= 3) {
265: wav_dbg(f);
266: dbg_puts(": write complete\n");
267: }
268: #endif
269: file_hup(&f->pipe.file);
270: return 0;
271: }
272: }
273: n = pipe_write(file, data, count);
274: if (f->wbytes >= 0)
275: f->wbytes -= n;
276: f->endpos += n;
277: return n;
278: }
279:
280: /*
281: * close method of the file structure
282: */
283: void
284: wav_close(struct file *file)
285: {
286: struct wav *f = (struct wav *)file;
287:
288: if (f->mode & MODE_RECMASK) {
289: pipe_trunc(&f->pipe.file, f->endpos);
290: if (f->hdr == HDR_WAV) {
291: wav_writehdr(f->pipe.fd,
292: &f->hpar,
293: &f->startpos,
294: f->endpos - f->startpos);
295: }
296: }
297: pipe_close(file);
1.10 ratchov 298: }
299:
1.15 ratchov 300: /*
301: * attach play (rec) abuf structure to the device and
302: * switch to the ``RUN'' state; the play abug must not be empty
303: */
1.14 ratchov 304: int
1.15 ratchov 305: wav_attach(struct wav *f, int force)
1.10 ratchov 306: {
1.15 ratchov 307: struct abuf *rbuf = NULL, *wbuf = NULL;
1.13 ratchov 308:
1.15 ratchov 309: if (f->mode & MODE_PLAY)
1.17 ! ratchov 310: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 311: if (f->mode & MODE_RECMASK)
1.17 ! ratchov 312: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15 ratchov 313: f->pstate = WAV_RUN;
314: #ifdef DEBUG
315: if (debug_level >= 3) {
316: wav_dbg(f);
317: dbg_puts(": attaching\n");
318: }
319: #endif
320: dev_attach(f->pipe.file.name, f->mode,
1.16 ratchov 321: rbuf, &f->hpar, f->join ? dev_opar.cmax - dev_opar.cmin + 1 : 0,
322: wbuf, &f->hpar, f->join ? dev_ipar.cmax - dev_ipar.cmin + 1 : 0,
323: f->xrun, f->maxweight);
1.15 ratchov 324: if (f->mode & MODE_PLAY)
325: dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
1.14 ratchov 326: return 1;
1.13 ratchov 327: }
328:
1.15 ratchov 329: /*
330: * allocate the play (rec) abuf structure; if this is a
331: * file to record, then attach it to the device
332: *
333: * XXX: buffer size should be larger than dev_bufsz, because
334: * in non-server mode we don't prime play buffers with
335: * silence
336: */
1.14 ratchov 337: void
1.15 ratchov 338: wav_allocbuf(struct wav *f)
1.13 ratchov 339: {
1.15 ratchov 340: struct abuf *buf;
341: unsigned nfr;
1.13 ratchov 342:
1.15 ratchov 343: f->pstate = WAV_START;
344: if (f->mode & MODE_PLAY) {
345: nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
346: buf = abuf_new(nfr, &f->hpar);
347: aproc_setout(f->pipe.file.rproc, buf);
348: abuf_fill(buf);
349: if (!ABUF_WOK(buf) || (f->pipe.file.state & FILE_EOF))
350: f->pstate = WAV_READY;
351: }
352: if (f->mode & MODE_RECMASK) {
353: nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate;
354: buf = abuf_new(nfr, &f->hpar);
355: aproc_setin(f->pipe.file.wproc, buf);
356: f->pstate = WAV_READY;
357: }
358: #ifdef DEBUG
359: if (debug_level >= 3) {
360: wav_dbg(f);
361: dbg_puts(": allocating buffers\n");
362: }
363: #endif
364: if (f->pstate == WAV_READY && ctl_slotstart(dev_midi, f->slot))
365: (void)wav_attach(f, 0);
1.13 ratchov 366: }
367:
1.15 ratchov 368: /*
369: * free abuf structure and switch to the ``INIT'' state
370: */
1.13 ratchov 371: void
1.15 ratchov 372: wav_freebuf(struct wav *f)
1.10 ratchov 373: {
1.15 ratchov 374: struct abuf *rbuf = NULL, *wbuf = NULL;
375:
376: if (f->mode & MODE_PLAY)
1.17 ! ratchov 377: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 378: if (f->mode & MODE_RECMASK)
1.17 ! ratchov 379: wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.15 ratchov 380: f->pstate = WAV_INIT;
381: #ifdef DEBUG
382: if (debug_level >= 3) {
383: wav_dbg(f);
384: dbg_puts(": freeing buffers\n");
385: }
386: #endif
387: if (rbuf || wbuf)
388: ctl_slotstop(dev_midi, f->slot);
389: if (rbuf)
390: abuf_eof(rbuf);
391: if (wbuf)
392: abuf_hup(wbuf);
1.10 ratchov 393: }
394:
1.15 ratchov 395: /*
396: * switch to the ``INIT'' state performing
397: * necessary actions to reach it
398: */
1.10 ratchov 399: void
1.15 ratchov 400: wav_reset(struct wav *f)
1.10 ratchov 401: {
1.15 ratchov 402: switch (f->pstate) {
403: case WAV_START:
404: case WAV_READY:
405: if (ctl_slotstart(dev_midi, f->slot))
406: (void)wav_attach(f, 1);
407: /* PASSTHROUGH */
408: case WAV_RUN:
409: wav_freebuf(f);
410: f->pstate = WAV_INIT;
411: /* PASSTHROUGH */
412: case WAV_INIT:
413: case WAV_FAILED:
414: /* nothing yet */
415: break;
416: }
1.10 ratchov 417: }
418:
1.15 ratchov 419: /*
420: * terminate the wav reader/writer
421: */
422: void
423: wav_exit(struct wav *f)
1.10 ratchov 424: {
1.15 ratchov 425: if (f->mode & MODE_PLAY) {
426: aproc_del(f->pipe.file.rproc);
427: } else if (f->mode & MODE_RECMASK) {
428: aproc_del(f->pipe.file.wproc);
429: }
1.10 ratchov 430: }
431:
1.15 ratchov 432: /*
433: * seek to f->mmcpos and prepare to start, close
434: * the file on error.
435: */
436: int
437: wav_seekmmc(struct wav *f)
1.10 ratchov 438: {
439: /*
1.15 ratchov 440: * don't go beyond the end-of-file, if so
441: * put it in INIT state so it dosn't start
1.10 ratchov 442: */
1.15 ratchov 443: if (f->mmcpos > f->endpos) {
444: wav_reset(f);
445: f->pstate = WAV_FAILED;
446: /*
447: * don't make other stream wait for us
448: */
449: if (f->slot >= 0)
450: ctl_slotstart(dev_midi, f->slot);
451: return 0;
452: }
453: if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
454: wav_exit(f);
455: return 0;
456: }
457: if (f->hdr == HDR_WAV)
458: f->wbytes = WAV_DATAMAX - f->mmcpos;
459: f->rbytes = f->endpos - f->mmcpos;
460: wav_reset(f);
461: wav_allocbuf(f);
462: return 1;
1.10 ratchov 463: }
464:
1.15 ratchov 465: /*
466: * read samples from the file and possibly start it
467: */
1.10 ratchov 468: int
1.15 ratchov 469: wav_rdata(struct wav *f)
1.10 ratchov 470: {
1.15 ratchov 471: struct aproc *p;
472: struct abuf *obuf;
1.10 ratchov 473:
1.15 ratchov 474: p = f->pipe.file.rproc;
1.17 ! ratchov 475: obuf = LIST_FIRST(&p->outs);
1.15 ratchov 476: if (obuf == NULL)
1.10 ratchov 477: return 0;
1.15 ratchov 478: if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.10 ratchov 479: return 0;
1.15 ratchov 480: if (!rfile_do(p, obuf->len, NULL))
1.10 ratchov 481: return 0;
1.15 ratchov 482: switch (f->pstate) {
483: case WAV_START:
484: if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
485: f->pstate = WAV_READY;
486: /* PASSTHROUGH */
487: case WAV_READY:
488: if (ctl_slotstart(dev_midi, f->slot))
489: (void)wav_attach(f, 0);
490: break;
491: #ifdef DEBUG
492: case WAV_RUN:
493: break;
494: default:
495: wav_dbg(f);
496: dbg_puts(": bad state\n");
497: dbg_panic();
498: #endif
499: }
500: if (f->rbytes == 0 && f->tr) {
501: #ifdef DEBUG
502: if (debug_level >= 3) {
503: wav_dbg(f);
504: dbg_puts(": trying to restart\n");
505: }
506: #endif
507: if (!wav_seekmmc(f))
508: return 0;
509: }
1.10 ratchov 510: return 1;
511: }
512:
513: int
1.15 ratchov 514: wav_wdata(struct wav *f)
1.10 ratchov 515: {
1.15 ratchov 516: struct aproc *p;
517: struct abuf *ibuf;
1.10 ratchov 518:
1.15 ratchov 519: if (!(f->pipe.file.state & FILE_WOK))
1.10 ratchov 520: return 0;
1.15 ratchov 521: p = f->pipe.file.wproc;
1.17 ! ratchov 522: ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 523: if (ibuf == NULL)
1.10 ratchov 524: return 0;
1.15 ratchov 525: if (!ABUF_ROK(ibuf))
1.10 ratchov 526: return 0;
1.15 ratchov 527: if (!wfile_do(p, ibuf->len, NULL))
1.10 ratchov 528: return 0;
529: return 1;
530: }
531:
1.15 ratchov 532: /*
533: * callback to set the volume, invoked by the MIDI control code
534: */
535: void
536: wav_setvol(void *arg, unsigned vol)
537: {
538: struct wav *f = (struct wav *)arg;
539: struct abuf *rbuf;
540:
541: f->vol = vol;
542: if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) {
1.17 ! ratchov 543: rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.15 ratchov 544: dev_setvol(rbuf, MIDI_TO_ADATA(vol));
545: }
546: }
547:
548: /*
549: * callback to start the stream, invoked by the MIDI control code
550: */
551: void
552: wav_startreq(void *arg)
553: {
554: struct wav *f = (struct wav *)arg;
555:
556: switch (f->pstate) {
557: case WAV_FAILED:
558: #ifdef DEBUG
559: if (debug_level >= 2) {
560: wav_dbg(f);
561: dbg_puts(": skipped (failed to seek)\n");
562: }
563: #endif
564: return;
565: case WAV_READY:
566: if (f->mode & MODE_RECMASK)
567: f->endpos = f->startpos;
568: (void)wav_attach(f, 0);
569: break;
570: #ifdef DEBUG
571: default:
572: wav_dbg(f);
573: dbg_puts(": not in READY state\n");
574: dbg_panic();
575: break;
576: #endif
577: }
578: }
579:
580: /*
581: * callback to stop the stream, invoked by the MIDI control code
582: */
1.10 ratchov 583: void
1.15 ratchov 584: wav_stopreq(void *arg)
1.10 ratchov 585: {
1.15 ratchov 586: struct wav *f = (struct wav *)arg;
587:
588: #ifdef DEBUG
589: if (debug_level >= 2) {
590: wav_dbg(f);
591: dbg_puts(": stopping");
592: if (f->pstate != WAV_FAILED && (f->mode & MODE_RECMASK)) {
593: dbg_puts(", ");
594: dbg_putu(f->endpos);
595: dbg_puts(" bytes recorded");
596: }
597: dbg_puts("\n");
598: }
599: #endif
600: if (!f->tr) {
601: wav_exit(f);
602: return;
603: }
604: (void)wav_seekmmc(f);
1.10 ratchov 605: }
606:
1.15 ratchov 607: /*
608: * callback to relocate the stream, invoked by the MIDI control code
609: * on a stopped stream
610: */
1.10 ratchov 611: void
1.15 ratchov 612: wav_locreq(void *arg, unsigned mmc)
1.10 ratchov 613: {
1.15 ratchov 614: struct wav *f = (struct wav *)arg;
615:
616: #ifdef DEBUG
617: if (f->pstate == WAV_RUN) {
618: wav_dbg(f);
619: dbg_puts(": in RUN state\n");
620: dbg_panic();
621: }
622: #endif
623: f->mmcpos = f->startpos +
624: ((off_t)mmc * f->hpar.rate / MTC_SEC) * aparams_bpf(&f->hpar);
625: (void)wav_seekmmc(f);
1.10 ratchov 626: }
627:
1.15 ratchov 628: /*
629: * create a file reader in the ``INIT'' state
630: */
1.1 ratchov 631: struct wav *
1.15 ratchov 632: wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
1.16 ratchov 633: struct aparams *par, unsigned xrun, unsigned volctl, int tr, int join)
1.1 ratchov 634: {
1.10 ratchov 635: int fd;
1.1 ratchov 636: struct wav *f;
1.10 ratchov 637:
638: if (name != NULL) {
639: fd = open(name, O_RDONLY | O_NONBLOCK, 0666);
640: if (fd < 0) {
641: perror(name);
642: return NULL;
643: }
644: } else {
645: name = "stdin";
646: fd = STDIN_FILENO;
647: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
648: perror(name);
649: }
1.1 ratchov 650: f = (struct wav *)pipe_new(ops, fd, name);
1.4 ratchov 651: if (f == NULL)
652: return NULL;
1.1 ratchov 653: if (hdr == HDR_WAV) {
1.15 ratchov 654: if (!wav_readhdr(f->pipe.fd, par, &f->startpos, &f->rbytes, &f->map)) {
1.10 ratchov 655: file_del((struct file *)f);
656: return NULL;
657: }
1.15 ratchov 658: f->endpos = f->startpos + f->rbytes;
1.6 ratchov 659: } else {
1.15 ratchov 660: f->startpos = 0;
661: f->endpos = pipe_endpos(&f->pipe.file);
662: if (f->endpos > 0) {
663: if (!pipe_seek(&f->pipe.file, 0)) {
664: file_del((struct file *)f);
665: return NULL;
666: }
667: f->rbytes = f->endpos;
668: } else
669: f->rbytes = -1;
1.6 ratchov 670: f->map = NULL;
671: }
1.15 ratchov 672: f->tr = tr;
1.16 ratchov 673: f->join = join;
1.15 ratchov 674: f->mode = mode;
675: f->hpar = *par;
1.1 ratchov 676: f->hdr = 0;
1.15 ratchov 677: f->xrun = xrun;
678: f->maxweight = MIDI_TO_ADATA(volctl);
679: f->slot = ctl_slotnew(dev_midi, "play", &ctl_wavops, f, 1);
680: rwav_new((struct file *)f);
681: wav_allocbuf(f);
1.12 ratchov 682: #ifdef DEBUG
683: if (debug_level >= 2) {
684: dbg_puts(name);
685: dbg_puts(": playing ");
1.15 ratchov 686: dbg_putu(f->startpos);
687: dbg_puts("..");
688: dbg_putu(f->endpos);
689: dbg_puts(": playing ");
1.12 ratchov 690: aparams_dbg(par);
1.15 ratchov 691: if (f->tr)
692: dbg_puts(", mmc");
1.12 ratchov 693: dbg_puts("\n");
694: }
695: #endif
1.1 ratchov 696: return f;
697: }
698:
1.15 ratchov 699: /*
700: * create a file writer in the ``INIT'' state
701: */
1.1 ratchov 702: struct wav *
1.15 ratchov 703: wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr,
1.16 ratchov 704: struct aparams *par, unsigned xrun, int tr, int join)
1.1 ratchov 705: {
1.10 ratchov 706: int fd;
1.1 ratchov 707: struct wav *f;
1.10 ratchov 708:
709: if (name == NULL) {
710: name = "stdout";
711: fd = STDOUT_FILENO;
712: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
713: perror(name);
714: } else {
715: fd = open(name,
716: O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
717: if (fd < 0) {
718: perror(name);
719: return NULL;
720: }
721: }
1.1 ratchov 722: f = (struct wav *)pipe_new(ops, fd, name);
1.4 ratchov 723: if (f == NULL)
724: return NULL;
1.1 ratchov 725: if (hdr == HDR_WAV) {
1.2 ratchov 726: par->le = 1;
1.3 ratchov 727: par->sig = (par->bits <= 8) ? 0 : 1;
1.2 ratchov 728: par->bps = (par->bits + 7) / 8;
1.15 ratchov 729: if (!wav_writehdr(f->pipe.fd, par, &f->startpos, 0)) {
1.10 ratchov 730: file_del((struct file *)f);
731: return NULL;
732: }
1.1 ratchov 733: f->wbytes = WAV_DATAMAX;
1.15 ratchov 734: f->endpos = f->startpos;
735: } else {
1.1 ratchov 736: f->wbytes = -1;
1.15 ratchov 737: f->startpos = f->endpos = 0;
738: }
739: f->tr = tr;
1.16 ratchov 740: f->join = join;
1.15 ratchov 741: f->mode = mode;
742: f->hpar = *par;
1.1 ratchov 743: f->hdr = hdr;
1.15 ratchov 744: f->xrun = xrun;
745: f->slot = ctl_slotnew(dev_midi, "rec", &ctl_wavops, f, 1);
746: wwav_new((struct file *)f);
747: wav_allocbuf(f);
1.12 ratchov 748: #ifdef DEBUG
749: if (debug_level >= 2) {
750: dbg_puts(name);
751: dbg_puts(": recording ");
752: aparams_dbg(par);
753: dbg_puts("\n");
754: }
755: #endif
1.1 ratchov 756: return f;
757: }
758:
1.6 ratchov 759: void
1.15 ratchov 760: rwav_done(struct aproc *p)
761: {
762: struct wav *f = (struct wav *)p->u.io.file;
763:
764: if (f->slot >= 0)
765: ctl_slotdel(dev_midi, f->slot);
766: f->slot = -1;
767: rfile_done(p);
768: }
769:
770: int
771: rwav_in(struct aproc *p, struct abuf *ibuf_dummy)
1.13 ratchov 772: {
1.15 ratchov 773: struct wav *f = (struct wav *)p->u.io.file;
774: struct abuf *obuf;
1.13 ratchov 775:
1.15 ratchov 776: if (!wav_rdata(f))
777: return 0;
1.17 ! ratchov 778: obuf = LIST_FIRST(&p->outs);
1.15 ratchov 779: if (obuf && f->pstate >= WAV_RUN) {
780: if (!abuf_flush(obuf))
781: return 0;
1.6 ratchov 782: }
1.15 ratchov 783: return 1;
1.6 ratchov 784: }
785:
1.15 ratchov 786: int
787: rwav_out(struct aproc *p, struct abuf *obuf)
1.1 ratchov 788: {
1.15 ratchov 789: struct wav *f = (struct wav *)p->u.io.file;
1.1 ratchov 790:
1.15 ratchov 791: if (f->pipe.file.state & FILE_RINUSE)
792: return 0;
793: for (;;) {
794: if (!wav_rdata(f))
1.1 ratchov 795: return 0;
796: }
1.15 ratchov 797: return 1;
798: }
799:
800: struct aproc *
801: rwav_new(struct file *f)
802: {
803: struct aproc *p;
804:
805: p = aproc_new(&rwav_ops, f->name);
806: p->u.io.file = f;
807: p->u.io.partial = 0;;
808: f->rproc = p;
809: return p;
810: }
811:
812: void
813: wwav_done(struct aproc *p)
814: {
815: struct wav *f = (struct wav *)p->u.io.file;
816:
817: if (f->slot >= 0)
818: ctl_slotdel(dev_midi, f->slot);
819: f->slot = -1;
820: wfile_done(p);
821: }
822:
823: int
824: wwav_in(struct aproc *p, struct abuf *ibuf)
825: {
826: struct wav *f = (struct wav *)p->u.io.file;
827:
828: if (f->pipe.file.state & FILE_WINUSE)
1.8 jakemsr 829: return 0;
1.15 ratchov 830: for (;;) {
831: if (!wav_wdata(f))
832: return 0;
1.6 ratchov 833: }
1.15 ratchov 834: return 1;
1.1 ratchov 835: }
836:
1.15 ratchov 837: int
838: wwav_out(struct aproc *p, struct abuf *obuf_dummy)
1.1 ratchov 839: {
1.17 ! ratchov 840: struct abuf *ibuf = LIST_FIRST(&p->ins);
1.15 ratchov 841: struct wav *f = (struct wav *)p->u.io.file;
1.3 ratchov 842:
1.15 ratchov 843: if (ibuf && f->pstate == WAV_RUN) {
844: if (!abuf_fill(ibuf))
1.1 ratchov 845: return 0;
846: }
1.15 ratchov 847: if (!wav_wdata(f))
848: return 0;
849: return 1;
1.1 ratchov 850: }
851:
1.15 ratchov 852: struct aproc *
853: wwav_new(struct file *f)
1.1 ratchov 854: {
1.15 ratchov 855: struct aproc *p;
1.1 ratchov 856:
1.15 ratchov 857: p = aproc_new(&wwav_ops, f->name);
858: p->u.io.file = f;
859: p->u.io.partial = 0;;
860: f->wproc = p;
861: return p;
1.1 ratchov 862: }
1.10 ratchov 863: