1 /* 2 * Copyright (c) 2008-2014 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 17 #include <fcntl.h> 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include <unistd.h> 22 #include "afile.h" 23 #include "utils.h" 24 25 typedef struct { 26 unsigned char ld[4]; 27 } le32_t; 28 29 typedef struct { 30 unsigned char lw[2]; 31 } le16_t; 32 33 typedef struct { 34 unsigned char bd[4]; 35 } be32_t; 36 37 typedef struct { 38 unsigned char bw[2]; 39 } be16_t; 40 41 struct wav_riff { 42 char id[4]; 43 le32_t size; 44 char type[4]; 45 }; 46 47 struct wav_chunk { 48 char id[4]; 49 le32_t size; 50 }; 51 52 struct wav_fmt { 53 #define WAV_FMT_PCM 1 54 #define WAV_FMT_FLOAT 3 55 #define WAV_FMT_ALAW 6 56 #define WAV_FMT_ULAW 7 57 #define WAV_FMT_EXT 0xfffe 58 le16_t fmt; 59 le16_t nch; 60 le32_t rate; 61 le32_t byterate; 62 le16_t blkalign; 63 le16_t bits; 64 #define WAV_FMT_SIZE 16 65 #define WAV_FMT_EXT_SIZE (16 + 24) 66 le16_t extsize; 67 le16_t valbits; 68 le32_t chanmask; 69 le16_t extfmt; 70 char guid[14]; 71 }; 72 73 struct wav_hdr { 74 struct wav_riff riff; /* 00..11 */ 75 struct wav_chunk fmt_hdr; /* 12..20 */ 76 struct wav_fmt fmt; 77 struct wav_chunk data_hdr; 78 }; 79 80 struct aiff_form { 81 char id[4]; 82 be32_t size; 83 char type[4]; 84 }; 85 86 struct aiff_chunk { 87 char id[4]; 88 be32_t size; 89 }; 90 91 struct aiff_comm { 92 struct aiff_commbase { 93 be16_t nch; 94 be32_t nfr; 95 be16_t bits; 96 /* rate in 80-bit floating point */ 97 be16_t rate_ex; 98 be32_t rate_hi; 99 be32_t rate_lo; 100 } base; 101 char comp_id[4]; 102 /* followed by stuff we don't care about */ 103 }; 104 105 struct aiff_data { 106 be32_t offs; 107 be32_t blksz; 108 }; 109 110 struct aiff_hdr { 111 struct aiff_form form; 112 struct aiff_chunk comm_hdr; 113 struct aiff_commbase comm; 114 struct aiff_chunk data_hdr; 115 struct aiff_data data; 116 }; 117 118 struct au_hdr { 119 char id[4]; 120 be32_t offs; 121 be32_t size; 122 #define AU_FMT_PCM8 2 123 #define AU_FMT_PCM16 3 124 #define AU_FMT_PCM24 4 125 #define AU_FMT_PCM32 5 126 #define AU_FMT_FLOAT 6 127 #define AU_FMT_ALAW 0x1b 128 #define AU_FMT_ULAW 1 129 be32_t fmt; 130 be32_t rate; 131 be32_t nch; 132 char desc[8]; 133 /* followed by optional desc[] continuation */ 134 }; 135 136 char wav_id_riff[4] = {'R', 'I', 'F', 'F'}; 137 char wav_id_wave[4] = {'W', 'A', 'V', 'E'}; 138 char wav_id_data[4] = {'d', 'a', 't', 'a'}; 139 char wav_id_fmt[4] = {'f', 'm', 't', ' '}; 140 char wav_guid[14] = { 141 0x00, 0x00, 0x00, 0x00, 142 0x10, 0x00, 0x80, 0x00, 143 0x00, 0xAA, 0x00, 0x38, 144 0x9B, 0x71 145 }; 146 147 char aiff_id_form[4] = {'F', 'O', 'R', 'M'}; 148 char aiff_id_aiff[4] = {'A', 'I', 'F', 'F'}; 149 char aiff_id_aifc[4] = {'A', 'I', 'F', 'C'}; 150 char aiff_id_data[4] = {'S', 'S', 'N', 'D'}; 151 char aiff_id_comm[4] = {'C', 'O', 'M', 'M'}; 152 char aiff_id_none[4] = {'N', 'O', 'N', 'E'}; 153 char aiff_id_fl32[4] = {'f', 'l', '3', '2'}; 154 char aiff_id_ulaw[4] = {'u', 'l', 'a', 'w'}; 155 char aiff_id_alaw[4] = {'a', 'l', 'a', 'w'}; 156 157 char au_id[4] = {'.', 's', 'n', 'd'}; 158 159 static inline unsigned int 160 le16_get(le16_t *p) 161 { 162 return p->lw[0] | p->lw[1] << 8; 163 } 164 165 static inline void 166 le16_set(le16_t *p, unsigned int v) 167 { 168 p->lw[0] = v; 169 p->lw[1] = v >> 8; 170 } 171 172 static inline unsigned int 173 le32_get(le32_t *p) 174 { 175 return p->ld[0] | 176 p->ld[1] << 8 | 177 p->ld[2] << 16 | 178 p->ld[3] << 24; 179 } 180 181 static inline void 182 le32_set(le32_t *p, unsigned int v) 183 { 184 p->ld[0] = v; 185 p->ld[1] = v >> 8; 186 p->ld[2] = v >> 16; 187 p->ld[3] = v >> 24; 188 } 189 190 static inline unsigned int 191 be16_get(be16_t *p) 192 { 193 return p->bw[1] | p->bw[0] << 8; 194 } 195 196 static inline void 197 be16_set(be16_t *p, unsigned int v) 198 { 199 p->bw[1] = v; 200 p->bw[0] = v >> 8; 201 } 202 203 static inline unsigned int 204 be32_get(be32_t *p) 205 { 206 return p->bd[3] | 207 p->bd[2] << 8 | 208 p->bd[1] << 16 | 209 p->bd[0] << 24; 210 } 211 212 static inline void 213 be32_set(be32_t *p, unsigned int v) 214 { 215 p->bd[3] = v; 216 p->bd[2] = v >> 8; 217 p->bd[1] = v >> 16; 218 p->bd[0] = v >> 24; 219 } 220 221 static int 222 afile_readhdr(struct afile *f, void *addr, size_t size) 223 { 224 if (lseek(f->fd, 0, SEEK_SET) < 0) { 225 log_puts(f->path); 226 log_puts(": failed to seek to beginning of file\n"); 227 return 0; 228 } 229 if (read(f->fd, addr, size) != size) { 230 log_puts(f->path); 231 log_puts(": failed to read header\n"); 232 return 0; 233 } 234 return 1; 235 } 236 237 static int 238 afile_writehdr(struct afile *f, void *addr, size_t size) 239 { 240 if (lseek(f->fd, 0, SEEK_SET) < 0) { 241 log_puts(f->path); 242 log_puts(": failed to seek back to header\n"); 243 return 0; 244 } 245 if (write(f->fd, addr, size) != size) { 246 log_puts(f->path); 247 log_puts(": failed to write header\n"); 248 return 0; 249 } 250 f->curpos = f->startpos; 251 return 1; 252 } 253 254 static int 255 afile_checkpar(struct afile *f) 256 { 257 if (f->nch == 0 || f->nch > NCHAN_MAX) { 258 log_puts(f->path); 259 log_puts(": "); 260 log_putu(f->nch); 261 log_puts(": unsupported number of channels\n"); 262 return 0; 263 } 264 if (f->rate < RATE_MIN || f->rate > RATE_MAX) { 265 log_puts(f->path); 266 log_puts(": "); 267 log_putu(f->rate); 268 log_puts(": unsupported rate\n"); 269 return 0; 270 } 271 if (f->par.bits < BITS_MIN || f->par.bits > BITS_MAX) { 272 log_puts(f->path); 273 log_puts(": "); 274 log_putu(f->par.bits); 275 log_puts(": unsupported bits per sample\n"); 276 return 0; 277 } 278 if (f->par.bits > f->par.bps * 8) { 279 log_puts(f->path); 280 log_puts(": bits larger than bytes-per-sample\n"); 281 return 0; 282 } 283 if (f->fmt == AFILE_FMT_FLOAT && f->par.bits != 32) { 284 log_puts(f->path); 285 log_puts(": only 32-bit floating points are supported\n"); 286 return 0; 287 } 288 return 1; 289 } 290 291 static int 292 afile_wav_readfmt(struct afile *f, unsigned int csize) 293 { 294 struct wav_fmt fmt; 295 unsigned int wenc; 296 297 if (csize < WAV_FMT_SIZE) { 298 log_puts(f->path); 299 log_puts(": "); 300 log_putu(csize); 301 log_puts(": bogus format chunk size\n"); 302 return 0; 303 } 304 if (csize > WAV_FMT_EXT_SIZE) 305 csize = WAV_FMT_EXT_SIZE; 306 if (read(f->fd, &fmt, csize) != csize) { 307 log_puts(f->path); 308 log_puts(": failed to read format chunk\n"); 309 return 0; 310 } 311 wenc = le16_get(&fmt.fmt); 312 f->par.bits = le16_get(&fmt.bits); 313 if (wenc == WAV_FMT_EXT) { 314 if (csize != WAV_FMT_EXT_SIZE) { 315 log_puts(f->path); 316 log_puts(": missing extended format chunk\n"); 317 return 0; 318 } 319 if (memcmp(fmt.guid, wav_guid, sizeof(wav_guid)) != 0) { 320 log_puts(f->path); 321 log_puts(": unknown format (GUID)\n"); 322 return 0; 323 } 324 f->par.bps = (f->par.bits + 7) / 8; 325 f->par.bits = le16_get(&fmt.valbits); 326 wenc = le16_get(&fmt.extfmt); 327 } else 328 f->par.bps = (f->par.bits + 7) / 8; 329 f->nch = le16_get(&fmt.nch); 330 f->rate = le32_get(&fmt.rate); 331 f->par.le = 1; 332 f->par.msb = 1; 333 switch (wenc) { 334 case WAV_FMT_PCM: 335 f->fmt = AFILE_FMT_PCM; 336 f->par.sig = (f->par.bits <= 8) ? 0 : 1; 337 break; 338 case WAV_FMT_ALAW: 339 f->fmt = AFILE_FMT_ALAW; 340 f->par.bits = 8; 341 f->par.bps = 1; 342 break; 343 case WAV_FMT_ULAW: 344 f->fmt = AFILE_FMT_ULAW; 345 f->par.bits = 8; 346 f->par.bps = 1; 347 break; 348 case WAV_FMT_FLOAT: 349 f->fmt = AFILE_FMT_FLOAT; 350 break; 351 default: 352 log_putu(wenc); 353 log_puts(": unsupported encoding\n"); 354 return 0; 355 } 356 return afile_checkpar(f); 357 } 358 359 static int 360 afile_wav_readhdr(struct afile *f) 361 { 362 struct wav_riff riff; 363 struct wav_chunk chunk; 364 unsigned int csize, rsize, pos = 0; 365 int fmt_done = 0; 366 367 if (!afile_readhdr(f, &riff, sizeof(struct wav_riff))) 368 return 0; 369 if (memcmp(&riff.id, &wav_id_riff, 4) != 0 || 370 memcmp(&riff.type, &wav_id_wave, 4)) { 371 log_puts(f->path); 372 log_puts(": not a .wav file\n"); 373 return 0; 374 } 375 rsize = le32_get(&riff.size); 376 for (;;) { 377 if (pos + sizeof(struct wav_chunk) > rsize) { 378 log_puts(f->path); 379 log_puts(": missing data chunk\n"); 380 return 0; 381 } 382 if (read(f->fd, &chunk, sizeof(chunk)) != sizeof(chunk)) { 383 log_puts(f->path); 384 log_puts(": failed to read chunk header\n"); 385 return 0; 386 } 387 csize = le32_get(&chunk.size); 388 if (memcmp(chunk.id, wav_id_fmt, 4) == 0) { 389 if (!afile_wav_readfmt(f, csize)) 390 return 0; 391 fmt_done = 1; 392 } else if (memcmp(chunk.id, wav_id_data, 4) == 0) { 393 f->startpos = pos + sizeof(riff) + sizeof(chunk); 394 f->endpos = f->startpos + csize; 395 break; 396 } else { 397 #ifdef DEBUG 398 if (log_level >= 2) { 399 log_puts(f->path); 400 log_puts(": skipped unknown chunk\n"); 401 } 402 #endif 403 } 404 405 /* 406 * next chunk 407 */ 408 pos += sizeof(struct wav_chunk) + csize; 409 if (lseek(f->fd, sizeof(riff) + pos, SEEK_SET) < 0) { 410 log_puts(f->path); 411 log_puts(": filed to seek to chunk\n"); 412 return 0; 413 } 414 } 415 if (!fmt_done) { 416 log_puts(f->path); 417 log_puts(": missing format chunk\n"); 418 return 0; 419 } 420 return 1; 421 } 422 423 /* 424 * Write header and seek to start position 425 */ 426 static int 427 afile_wav_writehdr(struct afile *f) 428 { 429 struct wav_hdr hdr; 430 431 memset(&hdr, 0, sizeof(struct wav_hdr)); 432 memcpy(hdr.riff.id, wav_id_riff, 4); 433 memcpy(hdr.riff.type, wav_id_wave, 4); 434 le32_set(&hdr.riff.size, f->endpos - sizeof(hdr.riff)); 435 memcpy(hdr.fmt_hdr.id, wav_id_fmt, 4); 436 le32_set(&hdr.fmt_hdr.size, sizeof(hdr.fmt)); 437 le16_set(&hdr.fmt.fmt, 1); 438 le16_set(&hdr.fmt.nch, f->nch); 439 le32_set(&hdr.fmt.rate, f->rate); 440 le32_set(&hdr.fmt.byterate, f->rate * f->par.bps * f->nch); 441 le16_set(&hdr.fmt.blkalign, f->par.bps * f->nch); 442 le16_set(&hdr.fmt.bits, f->par.bits); 443 memcpy(hdr.data_hdr.id, wav_id_data, 4); 444 le32_set(&hdr.data_hdr.size, f->endpos - f->startpos); 445 return afile_writehdr(f, &hdr, sizeof(struct wav_hdr)); 446 } 447 448 static int 449 afile_aiff_readcomm(struct afile *f, unsigned int csize, 450 int comp, unsigned int *nfr) 451 { 452 struct aiff_comm comm; 453 unsigned int csize_min; 454 unsigned int e, m; 455 456 csize_min = comp ? 457 sizeof(struct aiff_comm) : sizeof(struct aiff_commbase); 458 if (csize < csize_min) { 459 log_puts(f->path); 460 log_puts(": "); 461 log_putu(csize); 462 log_puts(": bogus comm chunk size\n"); 463 return 0; 464 } 465 if (read(f->fd, &comm, csize_min) != csize_min) { 466 log_puts(f->path); 467 log_puts(": failed to read comm chunk\n"); 468 return 0; 469 } 470 f->nch = be16_get(&comm.base.nch); 471 e = be16_get(&comm.base.rate_ex); 472 m = be32_get(&comm.base.rate_hi); 473 if (e < 0x3fff || e > 0x3fff + 31) { 474 log_puts(f->path); 475 log_puts(": malformed sample rate\n"); 476 return 0; 477 } 478 f->rate = m >> (0x3fff + 31 - e); 479 if (comp) { 480 if (memcmp(comm.comp_id, aiff_id_none, 4) == 0) { 481 f->fmt = AFILE_FMT_PCM; 482 f->par.bits = be16_get(&comm.base.bits); 483 } else if (memcmp(comm.comp_id, aiff_id_fl32, 4) == 0) { 484 f->fmt = AFILE_FMT_FLOAT; 485 f->par.bits = 32; 486 } else if (memcmp(comm.comp_id, aiff_id_ulaw, 4) == 0) { 487 f->fmt = AFILE_FMT_ULAW; 488 f->par.bits = 8; 489 } else if (memcmp(comm.comp_id, aiff_id_alaw, 4) == 0) { 490 f->fmt = AFILE_FMT_ALAW; 491 f->par.bits = 8; 492 } else { 493 log_puts(f->path); 494 log_puts(": unsupported encoding\n"); 495 return 0; 496 } 497 } else { 498 f->fmt = AFILE_FMT_PCM; 499 f->par.bits = be16_get(&comm.base.bits); 500 } 501 f->par.le = 0; 502 f->par.sig = 1; 503 f->par.msb = 1; 504 f->par.bps = (f->par.bits + 7) / 8; 505 *nfr = be32_get(&comm.base.nfr); 506 return afile_checkpar(f); 507 } 508 509 static int 510 afile_aiff_readdata(struct afile *f, unsigned int csize, unsigned int *roffs) 511 { 512 struct aiff_data data; 513 514 if (csize < sizeof(struct aiff_data)) { 515 log_puts(f->path); 516 log_puts(": "); 517 log_putu(csize); 518 log_puts(": bogus data chunk size\n"); 519 return 0; 520 } 521 csize = sizeof(struct aiff_data); 522 if (read(f->fd, &data, csize) != csize) { 523 log_puts(f->path); 524 log_puts(": failed to read data chunk\n"); 525 return 0; 526 } 527 *roffs = csize + be32_get(&data.offs); 528 return 1; 529 } 530 531 static int 532 afile_aiff_readhdr(struct afile *f) 533 { 534 struct aiff_form form; 535 struct aiff_chunk chunk; 536 unsigned int csize, rsize, nfr = 0, pos = 0, offs; 537 int comm_done = 0, comp; 538 539 if (!afile_readhdr(f, &form, sizeof(struct wav_riff))) 540 return 0; 541 if (memcmp(&form.id, &aiff_id_form, 4) != 0) { 542 log_puts(f->path); 543 log_puts(": not an aiff file\n"); 544 return 0; 545 } 546 if (memcmp(&form.type, &aiff_id_aiff, 4) == 0) { 547 comp = 0; 548 } else if (memcmp(&form.type, &aiff_id_aifc, 4) == 0) 549 comp = 1; 550 else { 551 log_puts(f->path); 552 log_puts(": unsupported aiff file sub-type\n"); 553 return 0; 554 } 555 rsize = be32_get(&form.size); 556 for (;;) { 557 if (pos + sizeof(struct aiff_chunk) > rsize) { 558 log_puts(f->path); 559 log_puts(": missing data chunk\n"); 560 return 0; 561 } 562 if (read(f->fd, &chunk, sizeof(chunk)) != sizeof(chunk)) { 563 log_puts(f->path); 564 log_puts(": failed to read chunk header\n"); 565 return 0; 566 } 567 csize = be32_get(&chunk.size); 568 if (memcmp(chunk.id, aiff_id_comm, 4) == 0) { 569 if (!afile_aiff_readcomm(f, csize, comp, &nfr)) 570 return 0; 571 comm_done = 1; 572 } else if (memcmp(chunk.id, aiff_id_data, 4) == 0) { 573 if (!afile_aiff_readdata(f, csize, &offs)) 574 return 0; 575 f->startpos = sizeof(form) + pos + 576 sizeof(chunk) + offs; 577 break; 578 } else { 579 #ifdef DEBUG 580 if (log_level >= 2) { 581 log_puts(f->path); 582 log_puts(": skipped unknown chunk\n"); 583 } 584 #endif 585 } 586 587 /* 588 * The aiff spec says "Each Chunk must contain an even 589 * number of bytes. For those Chunks whose total 590 * contents would yield an odd number of bytes, a zero 591 * pad byte must be added at the end of the Chunk. This 592 * pad byte is not included in ckDataSize, which 593 * indicates the size of the data in the Chunk." 594 */ 595 csize = (csize + 1) & ~1; 596 pos += sizeof(struct aiff_chunk) + csize; 597 598 if (lseek(f->fd, sizeof(form) + pos, SEEK_SET) < 0) { 599 log_puts(f->path); 600 log_puts(": filed to seek to chunk\n"); 601 return 0; 602 } 603 } 604 if (!comm_done) { 605 log_puts(f->path); 606 log_puts(": missing comm chunk\n"); 607 return 0; 608 } 609 f->endpos = f->startpos + f->par.bps * f->nch * nfr; 610 return 1; 611 } 612 613 /* 614 * Write header and seek to start position 615 */ 616 static int 617 afile_aiff_writehdr(struct afile *f) 618 { 619 struct aiff_hdr hdr; 620 unsigned int bpf; 621 unsigned int e, m; 622 623 /* convert rate to 80-bit float (exponent and fraction part) */ 624 m = f->rate; 625 e = 0x3fff + 31; 626 while ((m & 0x80000000) == 0) { 627 e--; 628 m <<= 1; 629 } 630 631 /* bytes per frame */ 632 bpf = f->nch * f->par.bps; 633 634 memset(&hdr, 0, sizeof(struct aiff_hdr)); 635 memcpy(hdr.form.id, aiff_id_form, 4); 636 memcpy(hdr.form.type, aiff_id_aiff, 4); 637 be32_set(&hdr.form.size, f->endpos - sizeof(hdr.form)); 638 639 memcpy(hdr.comm_hdr.id, aiff_id_comm, 4); 640 be32_set(&hdr.comm_hdr.size, sizeof(hdr.comm)); 641 be16_set(&hdr.comm.nch, f->nch); 642 be16_set(&hdr.comm.bits, f->par.bits); 643 be16_set(&hdr.comm.rate_ex, e); 644 be32_set(&hdr.comm.rate_hi, m); 645 be32_set(&hdr.comm.rate_lo, 0); 646 be32_set(&hdr.comm.nfr, (f->endpos - f->startpos) / bpf); 647 648 memcpy(hdr.data_hdr.id, aiff_id_data, 4); 649 be32_set(&hdr.data_hdr.size, f->endpos - f->startpos); 650 be32_set(&hdr.data.offs, 0); 651 be32_set(&hdr.data.blksz, 0); 652 return afile_writehdr(f, &hdr, sizeof(struct aiff_hdr)); 653 } 654 655 static int 656 afile_au_readhdr(struct afile *f) 657 { 658 struct au_hdr hdr; 659 unsigned int fmt; 660 661 if (!afile_readhdr(f, &hdr, sizeof(struct wav_riff))) 662 return 0; 663 if (memcmp(&hdr.id, &au_id, 4) != 0) { 664 log_puts(f->path); 665 log_puts(": not a .au file\n"); 666 return 0; 667 } 668 f->startpos = be32_get(&hdr.offs); 669 f->endpos = f->startpos + be32_get(&hdr.size); 670 fmt = be32_get(&hdr.fmt); 671 switch (fmt) { 672 case AU_FMT_PCM8: 673 f->fmt = AFILE_FMT_PCM; 674 f->par.bits = 8; 675 break; 676 case AU_FMT_PCM16: 677 f->fmt = AFILE_FMT_PCM; 678 f->par.bits = 16; 679 break; 680 case AU_FMT_PCM24: 681 f->fmt = AFILE_FMT_PCM; 682 f->par.bits = 24; 683 break; 684 case AU_FMT_PCM32: 685 f->fmt = AFILE_FMT_PCM; 686 f->par.bits = 32; 687 break; 688 case AU_FMT_ULAW: 689 f->fmt = AFILE_FMT_ULAW; 690 f->par.bits = 8; 691 f->par.bps = 1; 692 break; 693 case AU_FMT_ALAW: 694 f->fmt = AFILE_FMT_ALAW; 695 f->par.bits = 8; 696 f->par.bps = 1; 697 break; 698 case AU_FMT_FLOAT: 699 f->fmt = AFILE_FMT_FLOAT; 700 f->par.bits = 32; 701 f->par.bps = 4; 702 break; 703 default: 704 log_puts(f->path); 705 log_puts(": "); 706 log_putu(fmt); 707 log_puts(": unsupported encoding\n"); 708 return 0; 709 } 710 f->par.le = 0; 711 f->par.sig = 1; 712 f->par.bps = f->par.bits / 8; 713 f->par.msb = 0; 714 f->rate = be32_get(&hdr.rate); 715 f->nch = be32_get(&hdr.nch); 716 if (lseek(f->fd, f->startpos, SEEK_SET) < 0) { 717 log_puts(f->path); 718 log_puts(": "); 719 log_puts("failed to seek to data chunk\n"); 720 return 0; 721 } 722 return afile_checkpar(f); 723 } 724 725 /* 726 * Write header and seek to start position 727 */ 728 static int 729 afile_au_writehdr(struct afile *f) 730 { 731 struct au_hdr hdr; 732 unsigned int fmt; 733 734 memset(&hdr, 0, sizeof(struct au_hdr)); 735 memcpy(hdr.id, au_id, 4); 736 be32_set(&hdr.offs, f->startpos); 737 be32_set(&hdr.size, f->endpos - f->startpos); 738 switch (f->par.bits) { 739 case 8: 740 fmt = AU_FMT_PCM8; 741 break; 742 case 16: 743 fmt = AU_FMT_PCM16; 744 break; 745 case 24: 746 fmt = AU_FMT_PCM24; 747 break; 748 case 32: 749 fmt = AU_FMT_PCM32; 750 break; 751 #ifdef DEBUG 752 default: 753 log_puts(f->path); 754 log_puts(": wrong precision\n"); 755 panic(); 756 return 0; 757 #endif 758 } 759 be32_set(&hdr.fmt, fmt); 760 be32_set(&hdr.rate, f->rate); 761 be32_set(&hdr.nch, f->nch); 762 return afile_writehdr(f, &hdr, sizeof(struct au_hdr)); 763 } 764 765 size_t 766 afile_read(struct afile *f, void *data, size_t count) 767 { 768 off_t maxread; 769 ssize_t n; 770 771 if (f->endpos >= 0) { 772 maxread = f->endpos - f->curpos; 773 if (maxread == 0) { 774 #ifdef DEBUG 775 if (log_level >= 3) { 776 log_puts(f->path); 777 log_puts(": end reached\n"); 778 } 779 #endif 780 return 0; 781 } 782 if (count > maxread) 783 count = maxread; 784 } 785 n = read(f->fd, data, count); 786 if (n < 0) { 787 log_puts(f->path); 788 log_puts(": couldn't read\n"); 789 return 0; 790 } 791 f->curpos += n; 792 return n; 793 } 794 795 size_t 796 afile_write(struct afile *f, void *data, size_t count) 797 { 798 off_t maxwrite; 799 int n; 800 801 if (f->maxpos >= 0) { 802 maxwrite = f->maxpos - f->curpos; 803 if (maxwrite == 0) { 804 #ifdef DEBUG 805 if (log_level >= 3) { 806 log_puts(f->path); 807 log_puts(": max file size reached\n"); 808 } 809 #endif 810 return 0; 811 } 812 if (count > maxwrite) 813 count = maxwrite; 814 } 815 n = write(f->fd, data, count); 816 if (n < 0) { 817 log_puts(f->path); 818 log_puts(": couldn't write\n"); 819 return 0; 820 } 821 f->curpos += n; 822 if (f->endpos < f->curpos) 823 f->endpos = f->curpos; 824 return n; 825 } 826 827 int 828 afile_seek(struct afile *f, off_t pos) 829 { 830 pos += f->startpos; 831 if (f->endpos >= 0 && pos > f->endpos && !f->par.sig) { 832 log_puts(f->path); 833 log_puts(": attempt to seek outside file boundaries\n"); 834 return 0; 835 } 836 837 /* 838 * seek only if needed to avoid errors with pipes & sockets 839 */ 840 if (pos != f->curpos) { 841 if (lseek(f->fd, pos, SEEK_SET) < 0) { 842 log_puts(f->path); 843 log_puts(": couldn't seek\n"); 844 return 0; 845 } 846 f->curpos = pos; 847 } 848 return 1; 849 } 850 851 void 852 afile_close(struct afile *f) 853 { 854 if (f->flags & AFILE_FWRITE) { 855 if (f->hdr == AFILE_HDR_WAV) 856 afile_wav_writehdr(f); 857 else if (f->hdr == AFILE_HDR_AIFF) 858 afile_aiff_writehdr(f); 859 else if (f->hdr == AFILE_HDR_AU) 860 afile_au_writehdr(f); 861 } 862 close(f->fd); 863 } 864 865 int 866 afile_open(struct afile *f, char *path, int hdr, int flags, 867 struct aparams *par, int rate, int nch) 868 { 869 char *ext; 870 static union { 871 struct wav_hdr wav; 872 struct aiff_hdr aiff; 873 struct au_hdr au; 874 } dummy; 875 876 f->par = *par; 877 f->rate = rate; 878 f->nch = nch; 879 f->flags = flags; 880 f->hdr = hdr; 881 if (hdr == AFILE_HDR_AUTO) { 882 f->hdr = AFILE_HDR_RAW; 883 ext = strrchr(path, '.'); 884 if (ext != NULL) { 885 ext++; 886 if (strcasecmp(ext, "aif") == 0 || 887 strcasecmp(ext, "aiff") == 0 || 888 strcasecmp(ext, "aifc") == 0) 889 f->hdr = AFILE_HDR_AIFF; 890 else if (strcasecmp(ext, "au") == 0 || 891 strcasecmp(ext, "snd") == 0) 892 f->hdr = AFILE_HDR_AU; 893 else if (strcasecmp(ext, "wav") == 0) 894 f->hdr = AFILE_HDR_WAV; 895 } 896 } 897 if (f->flags == AFILE_FREAD) { 898 if (strcmp(path, "-") == 0) { 899 f->path = "stdin"; 900 f->fd = STDIN_FILENO; 901 } else { 902 f->path = path; 903 f->fd = open(f->path, O_RDONLY, 0); 904 if (f->fd < 0) { 905 log_puts(f->path); 906 log_puts(": failed to open for reading\n"); 907 return 0; 908 } 909 } 910 if (f->hdr == AFILE_HDR_WAV) { 911 if (!afile_wav_readhdr(f)) 912 goto bad_close; 913 } else if (f->hdr == AFILE_HDR_AIFF) { 914 if (!afile_aiff_readhdr(f)) 915 goto bad_close; 916 } else if (f->hdr == AFILE_HDR_AU) { 917 if (!afile_au_readhdr(f)) 918 goto bad_close; 919 } else { 920 f->startpos = 0; 921 f->endpos = -1; /* read until EOF */ 922 f->fmt = AFILE_FMT_PCM; 923 } 924 f->curpos = f->startpos; 925 } else if (flags == AFILE_FWRITE) { 926 if (strcmp(path, "-") == 0) { 927 f->path = "stdout"; 928 f->fd = STDOUT_FILENO; 929 } else { 930 f->path = path; 931 f->fd = open(f->path, 932 O_WRONLY | O_TRUNC | O_CREAT, 0666); 933 if (f->fd < 0) { 934 log_puts(f->path); 935 log_puts(": failed to create file\n"); 936 return 0; 937 } 938 } 939 if (f->hdr == AFILE_HDR_WAV) { 940 f->par.bps = (f->par.bits + 7) >> 3; 941 if (f->par.bits > 8) { 942 f->par.le = 1; 943 f->par.sig = 1; 944 } else 945 f->par.sig = 0; 946 if (f->par.bits & 7) 947 f->par.msb = 1; 948 f->endpos = f->startpos = sizeof(struct wav_hdr); 949 f->maxpos = 0x7fffffff; 950 if (!afile_writehdr(f, &dummy, sizeof(struct wav_hdr))) 951 goto bad_close; 952 } else if (f->hdr == AFILE_HDR_AIFF) { 953 f->par.bps = (f->par.bits + 7) >> 3; 954 if (f->par.bps > 1) 955 f->par.le = 0; 956 f->par.sig = 1; 957 if (f->par.bits & 7) 958 f->par.msb = 1; 959 f->endpos = f->startpos = sizeof(struct aiff_hdr); 960 f->maxpos = 0x7fffffff; 961 if (!afile_writehdr(f, &dummy, 962 sizeof(struct aiff_hdr))) 963 goto bad_close; 964 } else if (f->hdr == AFILE_HDR_AU) { 965 f->par.bits = (f->par.bits + 7) & ~7; 966 f->par.bps = f->par.bits / 8; 967 f->par.le = 0; 968 f->par.sig = 1; 969 f->par.msb = 1; 970 f->endpos = f->startpos = sizeof(struct au_hdr); 971 f->maxpos = 0x7fffffff; 972 if (!afile_writehdr(f, &dummy, sizeof(struct au_hdr))) 973 goto bad_close; 974 } else { 975 f->endpos = f->startpos = 0; 976 f->maxpos = -1; 977 } 978 f->curpos = f->startpos; 979 } else { 980 #ifdef DEBUG 981 log_puts("afile_open: wrong flags\n"); 982 panic(); 983 #endif 984 } 985 return 1; 986 bad_close: 987 close(f->fd); 988 return 0; 989 } 990