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