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 + sizeof(chunk) + offs; 576 break; 577 } else { 578 #ifdef DEBUG 579 if (log_level >= 2) { 580 log_puts(f->path); 581 log_puts(": skipped unknown chunk\n"); 582 } 583 #endif 584 } 585 586 /* 587 * The aiff spec says "Each Chunk must contain an even 588 * number of bytes. For those Chunks whose total 589 * contents would yield an odd number of bytes, a zero 590 * pad byte must be added at the end of the Chunk. This 591 * pad byte is not included in ckDataSize, which 592 * indicates the size of the data in the Chunk." 593 */ 594 csize = (csize + 1) & ~1; 595 pos += sizeof(struct aiff_chunk) + csize; 596 597 if (lseek(f->fd, sizeof(form) + pos, SEEK_SET) < 0) { 598 log_puts(f->path); 599 log_puts(": filed to seek to chunk\n"); 600 return 0; 601 } 602 } 603 if (!comm_done) { 604 log_puts(f->path); 605 log_puts(": missing comm chunk\n"); 606 return 0; 607 } 608 f->endpos = f->startpos + f->par.bps * f->nch * nfr; 609 return 1; 610 } 611 612 /* 613 * Write header and seek to start position 614 */ 615 static int 616 afile_aiff_writehdr(struct afile *f) 617 { 618 struct aiff_hdr hdr; 619 unsigned int bpf; 620 unsigned int e, m; 621 622 /* convert rate to 80-bit float (exponent and fraction part) */ 623 m = f->rate; 624 e = 0x3fff + 31; 625 while ((m & 0x80000000) == 0) { 626 e--; 627 m <<= 1; 628 } 629 630 /* bytes per frame */ 631 bpf = f->nch * f->par.bps; 632 633 memset(&hdr, 0, sizeof(struct aiff_hdr)); 634 memcpy(hdr.form.id, aiff_id_form, 4); 635 memcpy(hdr.form.type, aiff_id_aiff, 4); 636 be32_set(&hdr.form.size, f->endpos - sizeof(hdr.form)); 637 638 memcpy(hdr.comm_hdr.id, aiff_id_comm, 4); 639 be32_set(&hdr.comm_hdr.size, sizeof(hdr.comm)); 640 be16_set(&hdr.comm.nch, f->nch); 641 be16_set(&hdr.comm.bits, f->par.bits); 642 be16_set(&hdr.comm.rate_ex, e); 643 be32_set(&hdr.comm.rate_hi, m); 644 be32_set(&hdr.comm.rate_lo, 0); 645 be32_set(&hdr.comm.nfr, (f->endpos - f->startpos) / bpf); 646 647 memcpy(hdr.data_hdr.id, aiff_id_data, 4); 648 be32_set(&hdr.data_hdr.size, f->endpos - f->startpos); 649 be32_set(&hdr.data.offs, 0); 650 be32_set(&hdr.data.blksz, 0); 651 return afile_writehdr(f, &hdr, sizeof(struct aiff_hdr)); 652 } 653 654 static int 655 afile_au_readhdr(struct afile *f) 656 { 657 struct au_hdr hdr; 658 unsigned int fmt; 659 660 if (!afile_readhdr(f, &hdr, sizeof(struct wav_riff))) 661 return 0; 662 if (memcmp(&hdr.id, &au_id, 4) != 0) { 663 log_puts(f->path); 664 log_puts(": not a .au file\n"); 665 return 0; 666 } 667 f->startpos = be32_get(&hdr.offs); 668 f->endpos = f->startpos + be32_get(&hdr.size); 669 fmt = be32_get(&hdr.fmt); 670 switch (fmt) { 671 case AU_FMT_PCM8: 672 f->fmt = AFILE_FMT_PCM; 673 f->par.bits = 8; 674 break; 675 case AU_FMT_PCM16: 676 f->fmt = AFILE_FMT_PCM; 677 f->par.bits = 16; 678 break; 679 case AU_FMT_PCM24: 680 f->fmt = AFILE_FMT_PCM; 681 f->par.bits = 24; 682 break; 683 case AU_FMT_PCM32: 684 f->fmt = AFILE_FMT_PCM; 685 f->par.bits = 32; 686 break; 687 case AU_FMT_ULAW: 688 f->fmt = AFILE_FMT_ULAW; 689 f->par.bits = 8; 690 f->par.bps = 1; 691 break; 692 case AU_FMT_ALAW: 693 f->fmt = AFILE_FMT_ALAW; 694 f->par.bits = 8; 695 f->par.bps = 1; 696 break; 697 case AU_FMT_FLOAT: 698 f->fmt = AFILE_FMT_FLOAT; 699 f->par.bits = 32; 700 f->par.bps = 4; 701 break; 702 default: 703 log_puts(f->path); 704 log_puts(": "); 705 log_putu(fmt); 706 log_puts(": unsupported encoding\n"); 707 return 0; 708 } 709 f->par.le = 0; 710 f->par.sig = 1; 711 f->par.bps = f->par.bits / 8; 712 f->par.msb = 0; 713 f->rate = be32_get(&hdr.rate); 714 f->nch = be32_get(&hdr.nch); 715 if (lseek(f->fd, f->startpos, SEEK_SET) < 0) { 716 log_puts(f->path); 717 log_puts(": "); 718 log_puts("failed to seek to data chunk\n"); 719 return 0; 720 } 721 return afile_checkpar(f); 722 } 723 724 /* 725 * Write header and seek to start position 726 */ 727 static int 728 afile_au_writehdr(struct afile *f) 729 { 730 struct au_hdr hdr; 731 unsigned int fmt; 732 733 memset(&hdr, 0, sizeof(struct au_hdr)); 734 memcpy(hdr.id, au_id, 4); 735 be32_set(&hdr.offs, f->startpos); 736 be32_set(&hdr.size, f->endpos - f->startpos); 737 switch (f->par.bits) { 738 case 8: 739 fmt = AU_FMT_PCM8; 740 break; 741 case 16: 742 fmt = AU_FMT_PCM16; 743 break; 744 case 24: 745 fmt = AU_FMT_PCM24; 746 break; 747 case 32: 748 fmt = AU_FMT_PCM32; 749 break; 750 #ifdef DEBUG 751 default: 752 log_puts(f->path); 753 log_puts(": wrong precision\n"); 754 panic(); 755 return 0; 756 #endif 757 } 758 be32_set(&hdr.fmt, fmt); 759 be32_set(&hdr.rate, f->rate); 760 be32_set(&hdr.nch, f->nch); 761 return afile_writehdr(f, &hdr, sizeof(struct au_hdr)); 762 } 763 764 size_t 765 afile_read(struct afile *f, void *data, size_t count) 766 { 767 off_t maxread; 768 ssize_t n; 769 770 if (f->endpos >= 0) { 771 maxread = f->endpos - f->curpos; 772 if (maxread == 0) { 773 #ifdef DEBUG 774 if (log_level >= 3) { 775 log_puts(f->path); 776 log_puts(": end reached\n"); 777 } 778 #endif 779 return 0; 780 } 781 if (count > maxread) 782 count = maxread; 783 } 784 n = read(f->fd, data, count); 785 if (n < 0) { 786 log_puts(f->path); 787 log_puts(": couldn't read\n"); 788 return 0; 789 } 790 f->curpos += n; 791 return n; 792 } 793 794 size_t 795 afile_write(struct afile *f, void *data, size_t count) 796 { 797 off_t maxwrite; 798 int n; 799 800 if (f->maxpos >= 0) { 801 maxwrite = f->maxpos - f->curpos; 802 if (maxwrite == 0) { 803 #ifdef DEBUG 804 if (log_level >= 3) { 805 log_puts(f->path); 806 log_puts(": max file size reached\n"); 807 } 808 #endif 809 return 0; 810 } 811 if (count > maxwrite) 812 count = maxwrite; 813 } 814 n = write(f->fd, data, count); 815 if (n < 0) { 816 log_puts(f->path); 817 log_puts(": couldn't write\n"); 818 return 0; 819 } 820 f->curpos += n; 821 if (f->endpos < f->curpos) 822 f->endpos = f->curpos; 823 return n; 824 } 825 826 int 827 afile_seek(struct afile *f, off_t pos) 828 { 829 pos += f->startpos; 830 if (f->endpos >= 0 && pos > f->endpos) { 831 log_puts(f->path); 832 log_puts(": attempt to seek outside file boundaries\n"); 833 return 0; 834 } 835 836 /* 837 * seek only if needed to avoid errors with pipes & sockets 838 */ 839 if (pos != f->curpos) { 840 if (lseek(f->fd, pos, SEEK_SET) < 0) { 841 log_puts(f->path); 842 log_puts(": couldn't seek\n"); 843 return 0; 844 } 845 f->curpos = pos; 846 } 847 return 1; 848 } 849 850 void 851 afile_close(struct afile *f) 852 { 853 if (f->flags & AFILE_FWRITE) { 854 if (f->hdr == AFILE_HDR_WAV) 855 afile_wav_writehdr(f); 856 else if (f->hdr == AFILE_HDR_AIFF) 857 afile_aiff_writehdr(f); 858 else if (f->hdr == AFILE_HDR_AU) 859 afile_au_writehdr(f); 860 } 861 close(f->fd); 862 } 863 864 int 865 afile_open(struct afile *f, char *path, int hdr, int flags, 866 struct aparams *par, int rate, int nch) 867 { 868 char *ext; 869 static union { 870 struct wav_hdr wav; 871 struct aiff_hdr aiff; 872 struct au_hdr au; 873 } dummy; 874 875 f->par = *par; 876 f->rate = rate; 877 f->nch = nch; 878 f->flags = flags; 879 f->hdr = hdr; 880 if (hdr == AFILE_HDR_AUTO) { 881 f->hdr = AFILE_HDR_RAW; 882 ext = strrchr(path, '.'); 883 if (ext != NULL) { 884 ext++; 885 if (strcasecmp(ext, "aif") == 0 || 886 strcasecmp(ext, "aiff") == 0 || 887 strcasecmp(ext, "aifc") == 0) 888 f->hdr = AFILE_HDR_AIFF; 889 else if (strcasecmp(ext, "au") == 0 || 890 strcasecmp(ext, "snd") == 0) 891 f->hdr = AFILE_HDR_AU; 892 else if (strcasecmp(ext, "wav") == 0) 893 f->hdr = AFILE_HDR_WAV; 894 } 895 } 896 if (f->flags == AFILE_FREAD) { 897 if (strcmp(path, "-") == 0) { 898 f->path = "stdin"; 899 f->fd = STDIN_FILENO; 900 } else { 901 f->path = path; 902 f->fd = open(f->path, O_RDONLY, 0); 903 if (f->fd < 0) { 904 log_puts(f->path); 905 log_puts(": failed to open for reading\n"); 906 return 0; 907 } 908 } 909 if (f->hdr == AFILE_HDR_WAV) { 910 if (!afile_wav_readhdr(f)) 911 goto bad_close; 912 } else if (f->hdr == AFILE_HDR_AIFF) { 913 if (!afile_aiff_readhdr(f)) 914 goto bad_close; 915 } else if (f->hdr == AFILE_HDR_AU) { 916 if (!afile_au_readhdr(f)) 917 goto bad_close; 918 } else { 919 f->startpos = 0; 920 f->endpos = -1; /* read until EOF */ 921 f->fmt = AFILE_FMT_PCM; 922 } 923 f->curpos = f->startpos; 924 } else if (flags == AFILE_FWRITE) { 925 if (strcmp(path, "-") == 0) { 926 f->path = "stdout"; 927 f->fd = STDOUT_FILENO; 928 } else { 929 f->path = path; 930 f->fd = open(f->path, O_WRONLY | O_TRUNC | O_CREAT, 0666); 931 if (f->fd < 0) { 932 log_puts(f->path); 933 log_puts(": failed to create file\n"); 934 return 0; 935 } 936 } 937 if (f->hdr == AFILE_HDR_WAV) { 938 f->par.bps = (f->par.bits + 7) >> 3; 939 if (f->par.bits > 8) { 940 f->par.le = 1; 941 f->par.sig = 1; 942 } else 943 f->par.sig = 0; 944 if (f->par.bits & 7) 945 f->par.msb = 1; 946 f->endpos = f->startpos = sizeof(struct wav_hdr); 947 f->maxpos = 0x7fffffff; 948 if (!afile_writehdr(f, &dummy, sizeof(struct wav_hdr))) 949 goto bad_close; 950 } else if (f->hdr == AFILE_HDR_AIFF) { 951 f->par.bps = (f->par.bits + 7) >> 3; 952 if (f->par.bps > 1) 953 f->par.le = 0; 954 f->par.sig = 1; 955 if (f->par.bits & 7) 956 f->par.msb = 1; 957 f->endpos = f->startpos = sizeof(struct aiff_hdr); 958 f->maxpos = 0x7fffffff; 959 if (!afile_writehdr(f, &dummy, sizeof(struct aiff_hdr))) 960 goto bad_close; 961 } else if (f->hdr == AFILE_HDR_AU) { 962 f->par.bits = (f->par.bits + 7) & ~7; 963 f->par.bps = f->par.bits / 8; 964 f->par.le = 0; 965 f->par.sig = 1; 966 f->par.msb = 1; 967 f->endpos = f->startpos = sizeof(struct au_hdr); 968 f->maxpos = 0x7fffffff; 969 if (!afile_writehdr(f, &dummy, sizeof(struct au_hdr))) 970 goto bad_close; 971 } else { 972 f->endpos = f->startpos = 0; 973 f->maxpos = -1; 974 } 975 f->curpos = f->startpos; 976 } else { 977 #ifdef DEBUG 978 log_puts("afile_open: wrong flags\n"); 979 panic(); 980 #endif 981 } 982 return 1; 983 bad_close: 984 close(f->fd); 985 return 0; 986 } 987