1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 2018, Joyent, Inc. 28 */ 29 30 /* Command-line audio play utility */ 31 32 #include <stdio.h> 33 #include <errno.h> 34 #include <ctype.h> 35 #include <string.h> 36 #include <stdlib.h> 37 #include <fcntl.h> 38 #include <signal.h> 39 #include <locale.h> 40 #include <limits.h> /* All occurances of INT_MAX used to be ~0 (by MCA) */ 41 #include <unistd.h> 42 #include <stropts.h> 43 #include <sys/types.h> 44 #include <sys/file.h> 45 #include <sys/stat.h> 46 #include <sys/param.h> 47 #include <sys/ioctl.h> 48 #include <sys/mman.h> 49 #include <netinet/in.h> 50 51 #include <libaudio.h> 52 #include <audio_device.h> 53 #include <audio_encode.h> 54 55 /* localization stuff */ 56 #define MGET(s) (char *)gettext(s) 57 58 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 59 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 60 #endif 61 62 #define Error (void) fprintf 63 64 65 /* Local variables */ 66 static char *prog; 67 68 static char prog_opts[] = "VEiv:d:?"; /* getopt() flags */ 69 70 static char *Stdin; 71 72 #define MAX_GAIN (100) /* maximum gain */ 73 74 /* 75 * This defines the tolerable sample rate error as a ratio between the 76 * sample rates of the audio data and the audio device. 77 */ 78 #define SAMPLE_RATE_THRESHOLD (.01) 79 80 #define BUFFER_LEN 10 /* seconds - for file i/o */ 81 #define ADPCM_SIZE (1000*8) /* adpcm conversion output buf size */ 82 #define SWAP_SIZE (8192) 83 /* swap bytes conversion output buf size */ 84 85 static unsigned Volume = INT_MAX; /* output volume */ 86 static double Savevol; /* saved volume level */ 87 88 static int Verbose = FALSE; /* verbose messages */ 89 static int Immediate = FALSE; 90 /* don't hang waiting for device */ 91 static int Errdetect = FALSE; /* don't worry about underrun */ 92 static char *Audio_dev = "/dev/audio"; 93 94 static int NetEndian = TRUE; /* endian nature of the machine */ 95 96 static int Audio_fd = -1; 97 /* file descriptor for audio device */ 98 static int Audio_ctlfd = -1; 99 /* file descriptor for control device */ 100 static Audio_hdr Save_hdr; 101 /* saved audio header for device */ 102 static Audio_hdr Dev_hdr; /* audio header for device */ 103 static char *Ifile; /* current filename */ 104 static Audio_hdr File_hdr; /* audio header for file */ 105 static unsigned Decode = AUDIO_ENCODING_NONE; 106 /* decode type, if any */ 107 108 static unsigned char *buf = NULL; /* dynamically alloc'd */ 109 static unsigned bufsiz = 0; /* size of output buffer */ 110 static unsigned char adpcm_buf[ADPCM_SIZE + 32]; 111 /* for adpcm conversion */ 112 static unsigned char swap_buf[SWAP_SIZE + 32]; 113 /* for byte swap conversion */ 114 static unsigned char *inbuf; 115 /* current input buffer pointer */ 116 static unsigned insiz; /* current input buffer size */ 117 118 /* 119 * The decode_g72x() function is capable of decoding only one channel 120 * at a time and so multichannel data must be decomposed (using demux() 121 * function below ) into its constituent channels and each passed 122 * separately to the decode_g72x() function. Encoded input channels are 123 * stored in **in_ch_data and decoded output channels in **out_ch_data. 124 * Once each channel has been decoded they are recombined (see mux() 125 * function below) before being written to the audio device. For each 126 * channel and adpcm state structure is created. 127 */ 128 129 /* adpcm state structures */ 130 static struct audio_g72x_state *adpcm_state = NULL; 131 static unsigned char **in_ch_data = NULL; /* input channels */ 132 static unsigned char **out_ch_data = NULL; /* output channels */ 133 static int out_ch_size; /* output channel size */ 134 135 static char *Audio_path = NULL; 136 /* path to search for audio files */ 137 138 /* Global variables */ 139 extern int getopt(int, char *const *, const char *); 140 extern int optind; 141 extern char *optarg; 142 143 /* Local functions */ 144 static void usage(void); 145 static void sigint(int sig); 146 static void open_audio(void); 147 static int path_open(char *fname, int flags, mode_t mode, char *path); 148 static int parse_unsigned(char *str, unsigned *dst, char *flag); 149 static int reconfig(void); 150 static void initmux(int unitsz, int unitsp); 151 static void demux(int unitsz, int cnt); 152 static void mux(char *); 153 static void freemux(void); 154 155 156 static void 157 usage(void) 158 { 159 Error(stderr, MGET("Play an audio file -- usage:\n" 160 "\t%s [-iV] [-v vol] [-d dev] [file ...]\n" 161 "where:\n" 162 "\t-i\tDon't hang if audio device is busy\n" 163 "\t-V\tPrint verbose warning messages\n" 164 "\t-v\tSet output volume (0 - %d)\n" 165 "\t-d\tSpecify audio device (default: /dev/audio)\n" 166 "\tfile\tList of files to play\n" 167 "\t\tIf no files specified, read stdin\n"), 168 prog, MAX_GAIN); 169 exit(1); 170 } 171 172 static void 173 sigint(int sig) 174 { 175 /* flush output queues before exiting */ 176 if (Audio_fd >= 0) { 177 (void) audio_flush_play(Audio_fd); 178 179 /* restore saved parameters */ 180 if (Volume != INT_MAX) 181 (void) audio_set_play_gain(Audio_fd, &Savevol); 182 if ((Audio_ctlfd >= 0) && 183 (audio_cmp_hdr(&Save_hdr, &Dev_hdr) != 0)) { 184 (void) audio_set_play_config(Audio_fd, &Save_hdr); 185 } 186 } 187 exit(1); 188 } 189 190 /* Open the audio device and initalize it. */ 191 static void 192 open_audio(void) 193 { 194 int err; 195 double vol; 196 197 /* Return if already open */ 198 if (Audio_fd >= 0) 199 return; 200 201 /* Try opening without waiting, first */ 202 Audio_fd = open(Audio_dev, O_WRONLY | O_NONBLOCK); 203 if ((Audio_fd < 0) && (errno == EBUSY)) { 204 if (Immediate) { 205 Error(stderr, MGET("%s: %s is busy\n"), 206 prog, Audio_dev); 207 exit(1); 208 } 209 if (Verbose) { 210 Error(stderr, MGET("%s: waiting for %s..."), 211 prog, Audio_dev); 212 (void) fflush(stderr); 213 } 214 /* Now hang until it's open */ 215 Audio_fd = open(Audio_dev, O_WRONLY); 216 if (Verbose) 217 Error(stderr, (Audio_fd < 0) ? "\n" : MGET("open\n")); 218 } 219 if (Audio_fd < 0) { 220 Error(stderr, MGET("%s: error opening "), prog); 221 perror(Audio_dev); 222 exit(1); 223 } 224 225 /* Clear the non-blocking flag (in System V it persists after open) */ 226 (void) fcntl(Audio_fd, F_SETFL, 227 (fcntl(Audio_fd, F_GETFL, 0) & ~(O_NDELAY | O_NONBLOCK))); 228 229 /* Get the device output encoding configuration */ 230 if (audio_get_play_config(Audio_fd, &Dev_hdr) != AUDIO_SUCCESS) { 231 Error(stderr, MGET("%s: %s is not an audio device\n"), 232 prog, Audio_dev); 233 exit(1); 234 } 235 236 /* If -v flag, set the output volume now */ 237 if (Volume != INT_MAX) { 238 vol = (double)Volume / (double)MAX_GAIN; 239 (void) audio_get_play_gain(Audio_fd, &Savevol); 240 err = audio_set_play_gain(Audio_fd, &vol); 241 if (err != AUDIO_SUCCESS) { 242 Error(stderr, 243 MGET("%s: could not set output volume for %s\n"), 244 prog, Audio_dev); 245 exit(1); 246 } 247 } 248 } 249 250 /* Play a list of audio files. */ 251 int 252 main(int argc, char **argv) 253 { 254 int errorStatus = 0; 255 int i; 256 int c; 257 int cnt; 258 int file_type; 259 int rem; 260 int outsiz; 261 int tsize; 262 int len; 263 int err; 264 int ifd; 265 int stdinseen; 266 int regular; 267 int swapBytes; 268 int frame; 269 char *outbuf; 270 caddr_t mapaddr; 271 struct stat st; 272 char *cp; 273 char ctldev[MAXPATHLEN]; 274 275 (void) setlocale(LC_ALL, ""); 276 (void) textdomain(TEXT_DOMAIN); 277 278 /* Get the program name */ 279 prog = strrchr(argv[0], '/'); 280 if (prog == NULL) 281 prog = argv[0]; 282 else 283 prog++; 284 Stdin = MGET("(stdin)"); 285 286 /* Check AUDIODEV environment for audio device name */ 287 if (cp = getenv("AUDIODEV")) { 288 Audio_dev = cp; 289 } 290 291 /* Parse the command line arguments */ 292 err = 0; 293 while ((i = getopt(argc, argv, prog_opts)) != EOF) { 294 switch (i) { 295 case 'v': 296 if (parse_unsigned(optarg, &Volume, "-v")) { 297 err++; 298 } else if (Volume > MAX_GAIN) { 299 Error(stderr, MGET("%s: invalid value " 300 "for -v\n"), prog); 301 err++; 302 } 303 break; 304 case 'd': 305 Audio_dev = optarg; 306 break; 307 case 'V': 308 Verbose = TRUE; 309 break; 310 case 'E': 311 Errdetect = TRUE; 312 break; 313 case 'i': 314 Immediate = TRUE; 315 break; 316 case '?': 317 usage(); 318 /*NOTREACHED*/ 319 } 320 } 321 if (err > 0) 322 exit(1); 323 324 argc -= optind; /* update arg pointers */ 325 argv += optind; 326 327 /* Validate and open the audio device */ 328 err = stat(Audio_dev, &st); 329 if (err < 0) { 330 Error(stderr, MGET("%s: cannot stat "), prog); 331 perror(Audio_dev); 332 exit(1); 333 } 334 if (!S_ISCHR(st.st_mode)) { 335 Error(stderr, MGET("%s: %s is not an audio device\n"), prog, 336 Audio_dev); 337 exit(1); 338 } 339 340 /* This should probably use audio_cntl instead of open_audio */ 341 if ((argc <= 0) && isatty(fileno(stdin))) { 342 Error(stderr, MGET("%s: No files and stdin is a tty.\n"), prog); 343 exit(1); 344 } 345 346 /* Check on the -i status now. */ 347 Audio_fd = open(Audio_dev, O_WRONLY | O_NONBLOCK); 348 if ((Audio_fd < 0) && (errno == EBUSY)) { 349 if (Immediate) { 350 Error(stderr, MGET("%s: %s is busy\n"), prog, 351 Audio_dev); 352 exit(1); 353 } 354 } 355 (void) close(Audio_fd); 356 Audio_fd = -1; 357 358 /* Try to open the control device and save the current format */ 359 (void) snprintf(ctldev, sizeof (ctldev), "%sctl", Audio_dev); 360 Audio_ctlfd = open(ctldev, O_RDWR); 361 if (Audio_ctlfd >= 0) { 362 /* 363 * wait for the device to become available then get the 364 * controls. We want to save the format that is left when the 365 * device is in a quiescent state. So wait until then. 366 */ 367 Audio_fd = open(Audio_dev, O_WRONLY); 368 (void) close(Audio_fd); 369 Audio_fd = -1; 370 if (audio_get_play_config(Audio_ctlfd, &Save_hdr) 371 != AUDIO_SUCCESS) { 372 (void) close(Audio_ctlfd); 373 Audio_ctlfd = -1; 374 } 375 } 376 377 /* store AUDIOPATH so we don't keep doing getenv() */ 378 Audio_path = getenv("AUDIOPATH"); 379 380 /* Set up SIGINT handler to flush output */ 381 (void) signal(SIGINT, sigint); 382 383 /* Set the endian nature of the machine. */ 384 if ((ulong_t)1 != htonl((ulong_t)1)) { 385 NetEndian = FALSE; 386 } 387 388 /* If no filenames, read stdin */ 389 stdinseen = FALSE; 390 if (argc <= 0) { 391 Ifile = Stdin; 392 } else { 393 Ifile = *argv++; 394 argc--; 395 } 396 397 /* Loop through all filenames */ 398 do { 399 /* Interpret "-" filename to mean stdin */ 400 if (strcmp(Ifile, "-") == 0) 401 Ifile = Stdin; 402 403 if (Ifile == Stdin) { 404 if (stdinseen) { 405 Error(stderr, 406 MGET("%s: stdin already processed\n"), 407 prog); 408 goto nextfile; 409 } 410 stdinseen = TRUE; 411 ifd = fileno(stdin); 412 } else { 413 if ((ifd = path_open(Ifile, O_RDONLY, 0, Audio_path)) 414 < 0) { 415 Error(stderr, MGET("%s: cannot open "), prog); 416 perror(Ifile); 417 errorStatus++; 418 goto nextfile; 419 } 420 } 421 422 /* Check to make sure this is an audio file */ 423 err = audio_read_filehdr(ifd, &File_hdr, &file_type, 424 (char *)NULL, 0); 425 if (err != AUDIO_SUCCESS) { 426 Error(stderr, 427 MGET("%s: %s is not a valid audio file\n"), 428 prog, Ifile); 429 errorStatus++; 430 goto closeinput; 431 } 432 433 /* If G.72X adpcm, set flags for conversion */ 434 if ((File_hdr.encoding == AUDIO_ENCODING_G721) && 435 (File_hdr.samples_per_unit == 2) && 436 (File_hdr.bytes_per_unit == 1)) { 437 Decode = AUDIO_ENCODING_G721; 438 File_hdr.encoding = AUDIO_ENCODING_ULAW; 439 File_hdr.samples_per_unit = 1; 440 File_hdr.bytes_per_unit = 1; 441 adpcm_state = (struct audio_g72x_state *)malloc 442 (sizeof (*adpcm_state) * File_hdr.channels); 443 for (i = 0; i < File_hdr.channels; i++) { 444 g721_init_state(&adpcm_state[i]); 445 } 446 } else if ((File_hdr.encoding == AUDIO_ENCODING_G723) && 447 (File_hdr.samples_per_unit == 8) && 448 (File_hdr.bytes_per_unit == 3)) { 449 Decode = AUDIO_ENCODING_G723; 450 File_hdr.encoding = AUDIO_ENCODING_ULAW; 451 File_hdr.samples_per_unit = 1; 452 File_hdr.bytes_per_unit = 1; 453 adpcm_state = (struct audio_g72x_state *)malloc 454 (sizeof (*adpcm_state) * File_hdr.channels); 455 for (i = 0; i < File_hdr.channels; i++) { 456 g723_init_state(&adpcm_state[i]); 457 } 458 } else { 459 Decode = AUDIO_ENCODING_NONE; 460 } 461 462 /* Check the device configuration */ 463 open_audio(); 464 if (audio_cmp_hdr(&Dev_hdr, &File_hdr) != 0) { 465 /* 466 * The device does not match the input file. 467 * Wait for any old output to drain, then attempt 468 * to reconfigure the audio device to match the 469 * input data. 470 */ 471 if (audio_drain(Audio_fd, FALSE) != AUDIO_SUCCESS) { 472 /* Flush any remaining audio */ 473 (void) ioctl(Audio_fd, I_FLUSH, FLUSHW); 474 475 Error(stderr, MGET("%s: "), prog); 476 perror(MGET("AUDIO_DRAIN error")); 477 exit(1); 478 } 479 480 /* Flush any remaining audio */ 481 (void) ioctl(Audio_fd, I_FLUSH, FLUSHW); 482 483 if (!reconfig()) { 484 errorStatus++; 485 goto closeinput; 486 } 487 } 488 489 490 /* try to do the mmaping - for regular files only ... */ 491 err = fstat(ifd, &st); 492 if (err < 0) { 493 Error(stderr, MGET("%s: cannot stat "), prog); 494 perror(Ifile); 495 exit(1); 496 } 497 regular = (S_ISREG(st.st_mode)); 498 499 500 /* If regular file, map it. Else, allocate a buffer */ 501 mapaddr = 0; 502 503 /* 504 * This should compare to MAP_FAILED not -1, can't 505 * find MAP_FAILED 506 */ 507 if (regular && ((mapaddr = mmap(0, st.st_size, PROT_READ, 508 MAP_SHARED, ifd, 0)) != MAP_FAILED)) { 509 510 (void) madvise(mapaddr, st.st_size, MADV_SEQUENTIAL); 511 512 /* Skip the file header and set the proper size */ 513 cnt = lseek(ifd, 0, SEEK_CUR); 514 if (cnt < 0) { 515 perror("lseek"); 516 exit(1); 517 } 518 inbuf = (unsigned char *) mapaddr + cnt; 519 len = cnt = st.st_size - cnt; 520 } else { /* Not a regular file, or map failed */ 521 522 /* mark is so. */ 523 mapaddr = 0; 524 525 /* Allocate buffer to hold 10 seconds of data */ 526 cnt = BUFFER_LEN * File_hdr.sample_rate * 527 File_hdr.bytes_per_unit * File_hdr.channels; 528 if (bufsiz != cnt) { 529 if (buf != NULL) { 530 (void) free(buf); 531 } 532 buf = (unsigned char *) malloc(cnt); 533 if (buf == NULL) { 534 Error(stderr, 535 MGET("%s: couldn't allocate %dK " 536 "buf\n"), prog, bufsiz / 1000); 537 exit(1); 538 } 539 inbuf = buf; 540 bufsiz = cnt; 541 } 542 } 543 544 /* Set buffer sizes and pointers for conversion, if any */ 545 switch (Decode) { 546 default: 547 case AUDIO_ENCODING_NONE: 548 insiz = bufsiz; 549 outbuf = (char *)buf; 550 break; 551 case AUDIO_ENCODING_G721: 552 insiz = ADPCM_SIZE / 2; 553 outbuf = (char *)adpcm_buf; 554 initmux(1, 2); 555 break; 556 case AUDIO_ENCODING_G723: 557 insiz = (ADPCM_SIZE * 3) / 8; 558 outbuf = (char *)adpcm_buf; 559 initmux(3, 8); 560 break; 561 } 562 563 /* 564 * 8-bit audio isn't a problem, however 16-bit audio is. 565 * If the file is an endian that is different from the machine 566 * then the bytes will need to be swapped. 567 * 568 * Note: Because the G.72X conversions produce 8bit output, 569 * they don't require a byte swap before display and so 570 * this scheme works just fine. If a conversion is added 571 * that produces a 16 bit result and therefore requires 572 * byte swapping before output, then a mechanism 573 * for chaining the two conversions will have to be built. 574 * 575 * Note: The following if() could be simplified, but then 576 * it gets to be very hard to read. So it's left as is. 577 */ 578 579 if (File_hdr.bytes_per_unit == 2 && 580 ((!NetEndian && file_type == FILE_AIFF) || 581 (!NetEndian && file_type == FILE_AU) || 582 (NetEndian && file_type == FILE_WAV))) { 583 swapBytes = TRUE; 584 } else { 585 swapBytes = FALSE; 586 } 587 588 if (swapBytes) { 589 /* Read in interal number of sample frames. */ 590 frame = File_hdr.bytes_per_unit * File_hdr.channels; 591 insiz = (SWAP_SIZE / frame) * frame; 592 /* make the output buffer the swap buffer. */ 593 outbuf = (char *)swap_buf; 594 } 595 596 /* 597 * At this point, we're all ready to copy the data. 598 */ 599 if (mapaddr == 0) { /* Not mmapped, do it a buffer at a time. */ 600 inbuf = buf; 601 frame = File_hdr.bytes_per_unit * File_hdr.channels; 602 rem = 0; 603 while ((cnt = read(ifd, inbuf+rem, insiz-rem)) >= 0) { 604 /* 605 * We need to ensure only an integral number of 606 * samples is ever written to the audio device. 607 */ 608 cnt = cnt + rem; 609 rem = cnt % frame; 610 cnt = cnt - rem; 611 612 /* 613 * If decoding adpcm, or swapping bytes do it 614 * now. 615 * 616 * We treat the swapping like a separate 617 * encoding here because the G.72X encodings 618 * decode to single byte output samples. If 619 * another encoding is added and it produces 620 * multi-byte output samples this will have to 621 * be changed. 622 */ 623 if (Decode == AUDIO_ENCODING_G721) { 624 outsiz = 0; 625 demux(1, cnt / File_hdr.channels); 626 for (c = 0; c < File_hdr.channels; c++) { 627 err = g721_decode(in_ch_data[c], 628 cnt / File_hdr.channels, 629 &File_hdr, 630 (void*)out_ch_data[c], 631 &tsize, 632 &adpcm_state[c]); 633 outsiz = outsiz + tsize; 634 if (err != AUDIO_SUCCESS) { 635 Error(stderr, MGET( 636 "%s: error decoding g721\n"), 637 prog); 638 errorStatus++; 639 break; 640 } 641 } 642 mux(outbuf); 643 cnt = outsiz; 644 } else if (Decode == AUDIO_ENCODING_G723) { 645 outsiz = 0; 646 demux(3, cnt / File_hdr.channels); 647 for (c = 0; c < File_hdr.channels; c++) { 648 err = g723_decode(in_ch_data[c], 649 cnt / File_hdr.channels, 650 &File_hdr, 651 (void*)out_ch_data[c], 652 &tsize, 653 &adpcm_state[c]); 654 outsiz = outsiz + tsize; 655 if (err != AUDIO_SUCCESS) { 656 Error(stderr, MGET( 657 "%s: error decoding g723\n"), 658 prog); 659 errorStatus++; 660 break; 661 } 662 } 663 mux(outbuf); 664 cnt = outsiz; 665 } else if (swapBytes) { 666 swab((char *)inbuf, outbuf, cnt); 667 } 668 669 /* If input EOF, write an eof marker */ 670 err = write(Audio_fd, outbuf, cnt); 671 672 if (err < 0) { 673 perror("write"); 674 errorStatus++; 675 break; 676 } else if (err != cnt) { 677 Error(stderr, 678 MGET("%s: output error: "), prog); 679 perror(""); 680 errorStatus++; 681 break; 682 } 683 if (cnt == 0) { 684 break; 685 } 686 /* Move remainder to the front of the buffer */ 687 if (rem != 0) { 688 (void) memcpy(inbuf, inbuf + cnt, rem); 689 } 690 691 } 692 if (cnt < 0) { 693 Error(stderr, MGET("%s: error reading "), prog); 694 perror(Ifile); 695 errorStatus++; 696 } 697 } else { /* We're mmaped */ 698 if ((Decode != AUDIO_ENCODING_NONE) || swapBytes) { 699 700 /* Transform data if we have to. */ 701 for (i = 0; i <= len; i += cnt) { 702 cnt = insiz; 703 if ((i + cnt) > len) { 704 cnt = len - i; 705 } 706 if (Decode == AUDIO_ENCODING_G721) { 707 outsiz = 0; 708 demux(1, cnt / File_hdr.channels); 709 for (c = 0; c < File_hdr.channels; 710 c++) { 711 err = g721_decode( 712 in_ch_data[c], 713 cnt / File_hdr.channels, 714 &File_hdr, 715 (void*)out_ch_data[c], 716 &tsize, 717 &adpcm_state[c]); 718 outsiz = outsiz + tsize; 719 if (err != AUDIO_SUCCESS) { 720 Error(stderr, MGET( 721 "%s: error decoding " 722 "g721\n"), prog); 723 errorStatus++; 724 break; 725 } 726 } 727 mux(outbuf); 728 } else if 729 (Decode == AUDIO_ENCODING_G723) { 730 outsiz = 0; 731 demux(3, 732 cnt / File_hdr.channels); 733 for (c = 0; 734 c < File_hdr.channels; 735 c++) { 736 err = g723_decode( 737 in_ch_data[c], 738 cnt / 739 File_hdr.channels, 740 &File_hdr, 741 (void*)out_ch_data[c], 742 &tsize, 743 &adpcm_state[c]); 744 outsiz = outsiz + tsize; 745 if (err != AUDIO_SUCCESS) { 746 Error(stderr, MGET( 747 "%s: error " 748 "decoding g723\n"), 749 prog); 750 errorStatus++; 751 break; 752 } 753 } 754 mux(outbuf); 755 } else if (swapBytes) { 756 swab((char *)inbuf, outbuf, 757 cnt); 758 outsiz = cnt; 759 } 760 inbuf += cnt; 761 762 /* If input EOF, write an eof marker */ 763 err = write(Audio_fd, (char *)outbuf, 764 outsiz); 765 if (err < 0) { 766 perror("write"); 767 errorStatus++; 768 } else if (outsiz == 0) { 769 break; 770 } 771 772 } 773 } else { 774 /* write the whole thing at once! */ 775 err = write(Audio_fd, inbuf, len); 776 if (err < 0) { 777 perror("write"); 778 errorStatus++; 779 } 780 if (err != len) { 781 Error(stderr, 782 MGET("%s: output error: "), prog); 783 perror(""); 784 errorStatus++; 785 } 786 err = write(Audio_fd, inbuf, 0); 787 if (err < 0) { 788 perror("write"); 789 errorStatus++; 790 } 791 } 792 } 793 794 /* Free memory if decoding ADPCM */ 795 switch (Decode) { 796 case AUDIO_ENCODING_G721: 797 case AUDIO_ENCODING_G723: 798 freemux(); 799 break; 800 default: 801 break; 802 } 803 804 closeinput:; 805 if (mapaddr != 0) 806 (void) munmap(mapaddr, st.st_size); 807 (void) close(ifd); /* close input file */ 808 if (Errdetect) { 809 cnt = 0; 810 (void) audio_set_play_error(Audio_fd, 811 (unsigned int *)&cnt); 812 if (cnt) { 813 Error(stderr, 814 MGET("%s: output underflow in %s\n"), 815 Ifile, prog); 816 errorStatus++; 817 } 818 } 819 nextfile:; 820 } while ((argc > 0) && (argc--, (Ifile = *argv++) != NULL)); 821 822 /* 823 * Though drain is implicit on close(), it's performed here 824 * to ensure that the volume is reset after all output is complete. 825 */ 826 (void) audio_drain(Audio_fd, FALSE); 827 828 /* Flush any remaining audio */ 829 (void) ioctl(Audio_fd, I_FLUSH, FLUSHW); 830 831 if (Volume != INT_MAX) 832 (void) audio_set_play_gain(Audio_fd, &Savevol); 833 if ((Audio_ctlfd >= 0) && (audio_cmp_hdr(&Save_hdr, &Dev_hdr) != 0)) { 834 (void) audio_set_play_config(Audio_fd, &Save_hdr); 835 } 836 (void) close(Audio_fd); /* close output */ 837 return (errorStatus); 838 } 839 840 841 /* 842 * Try to reconfigure the audio device to match the file encoding. 843 * If this fails, we should attempt to make the input data match the 844 * device encoding. For now, we give up on this file. 845 * 846 * Returns TRUE if successful. Returns FALSE if not. 847 */ 848 static int 849 reconfig(void) 850 { 851 int err; 852 char msg[AUDIO_MAX_ENCODE_INFO]; 853 854 Dev_hdr = File_hdr; 855 err = audio_set_play_config(Audio_fd, &Dev_hdr); 856 857 switch (err) { 858 case AUDIO_SUCCESS: 859 return (TRUE); 860 861 case AUDIO_ERR_NOEFFECT: 862 /* 863 * Couldn't change the device. 864 * Check to see if we're nearly compatible. 865 * audio_cmp_hdr() returns >0 if only sample rate difference. 866 */ 867 if (audio_cmp_hdr(&Dev_hdr, &File_hdr) > 0) { 868 double ratio; 869 870 ratio = (double)abs((int) 871 (Dev_hdr.sample_rate - File_hdr.sample_rate)) / 872 (double)File_hdr.sample_rate; 873 if (ratio <= SAMPLE_RATE_THRESHOLD) { 874 if (Verbose) { 875 Error(stderr, 876 MGET("%s: WARNING: %s sampled at " 877 "%d, playing at %d\n"), 878 prog, Ifile, File_hdr.sample_rate, 879 Dev_hdr.sample_rate); 880 } 881 return (TRUE); 882 } 883 Error(stderr, 884 MGET("%s: %s sample rate %d not available\n"), 885 prog, Ifile, File_hdr.sample_rate); 886 return (FALSE); 887 } 888 (void) audio_enc_to_str(&File_hdr, msg); 889 Error(stderr, MGET("%s: %s encoding not available: %s\n"), 890 prog, Ifile, msg); 891 return (FALSE); 892 893 default: 894 Error(stderr, 895 MGET("%s: %s audio encoding type not available\n"), 896 prog, Ifile); 897 exit(1); 898 } 899 return (TRUE); 900 } 901 902 903 /* Parse an unsigned integer */ 904 static int 905 parse_unsigned(char *str, unsigned *dst, char *flag) 906 { 907 char x; 908 909 if (sscanf(str, "%u%c", dst, &x) != 1) { 910 Error(stderr, MGET("%s: invalid value for %s\n"), prog, flag); 911 return (1); 912 } 913 return (0); 914 } 915 916 /* 917 * Search for fname in path and open. Ignore path not opened O_RDONLY. 918 * Note: in general path can be a list of ':' separated paths to search 919 * through. 920 */ 921 static int 922 path_open(char *fname, int flags, mode_t mode, char *path) 923 { 924 char fullpath[MAXPATHLEN]; /* full path of file */ 925 char *buf; /* malloc off the tmp buff */ 926 char *cp; 927 struct stat st; 928 929 if (!fname) { /* bogus */ 930 return (-1); 931 } 932 933 /* 934 * cases where we don't bother checking path: 935 * - no path 936 * - file not opened O_RDONLY 937 * - not a relative path (i.e. starts with /, ./, or ../). 938 */ 939 940 if ((!path) || (flags != O_RDONLY) || (*fname == '/') || 941 (strncmp(fname, "./", strlen("./")) == 0) || 942 (strncmp(fname, "../", strlen("../")) == 0)) { 943 return (open(fname, flags, mode)); 944 } 945 946 /* 947 * Malloc off a buffer to hold the path variable. 948 * This is NOT limited to MAXPATHLEN characters as 949 * it may contain multiple paths. 950 */ 951 buf = malloc(strlen(path) + 1); 952 953 /* 954 * if first character is ':', but not the one following it, 955 * skip over it - or it'll be interpreted as "./". it's OK 956 * to have "::" since that does mean "./". 957 */ 958 959 if ((path[0] == ':') && (path[1] != ':')) { 960 (void) strncpy(buf, path+1, strlen(path)); 961 } else { 962 (void) strncpy(buf, path, strlen(path)); 963 } 964 965 for (path = buf; path && *path; ) { 966 if (cp = strchr(path, ':')) { 967 *cp++ = '\0'; /* now pts to next path element */ 968 } 969 970 /* the safest way to create the path string :-) */ 971 if (*path) { 972 (void) strncpy(fullpath, path, MAXPATHLEN); 973 (void) strncat(fullpath, "/", MAXPATHLEN); 974 } else { 975 /* a NULL path element means "./" */ 976 (void) strncpy(fullpath, "./", MAXPATHLEN); 977 } 978 (void) strncat(fullpath, fname, MAXPATHLEN); 979 980 /* see if there's a match */ 981 if (stat(fullpath, &st) >= 0) { 982 if (S_ISREG(st.st_mode)) { 983 /* got a match! */ 984 if (Verbose) { 985 Error(stderr, 986 MGET("%s: Found %s in path " 987 "at %s\n"), 988 prog, fname, fullpath); 989 } 990 return (open(fullpath, flags, mode)); 991 } 992 } 993 994 /* go on to the next one */ 995 path = cp; 996 } 997 998 /* 999 * if we fall through with no match, just do a normal file open 1000 */ 1001 return (open(fname, flags, mode)); 1002 } 1003 1004 1005 /* 1006 * initmux() 1007 * 1008 * Description: 1009 * Allocates memory for carrying out demultiplexing/multiplexing. 1010 * 1011 * Arguments: 1012 * int unitsz Bytes per unit 1013 * int unitsp Samples per unit 1014 * 1015 * Returns: 1016 * void 1017 */ 1018 static void 1019 initmux(int unitsz, int unitsp) 1020 { 1021 int c; /* Channel */ 1022 int in_ch_size; /* Input channel size */ 1023 1024 /* Size of each input channel */ 1025 in_ch_size = insiz / File_hdr.channels; 1026 1027 /* Size of each output channel */ 1028 out_ch_size = in_ch_size * unitsp / unitsz; 1029 1030 /* Allocate pointers to input channels */ 1031 in_ch_data = malloc(sizeof (unsigned char *) * File_hdr.channels); 1032 1033 if (in_ch_data == NULL) { 1034 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"), 1035 prog, sizeof (unsigned char *) * File_hdr.channels / 1000); 1036 exit(1); 1037 } 1038 1039 /* Allocate input channels */ 1040 for (c = 0; c < File_hdr.channels; c++) { 1041 in_ch_data[c] = malloc(sizeof (unsigned char) * in_ch_size); 1042 1043 if (in_ch_data[c] == NULL) { 1044 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"), 1045 prog, in_ch_size / 1000); 1046 exit(1); 1047 } 1048 } 1049 1050 /* Allocate pointers to output channels */ 1051 out_ch_data = malloc(sizeof (unsigned char *) * File_hdr.channels); 1052 1053 if (out_ch_data == NULL) { 1054 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"), 1055 prog, sizeof (unsigned char *) * File_hdr.channels / 1000); 1056 exit(1); 1057 } 1058 1059 /* Allocate output channels */ 1060 for (c = 0; c < File_hdr.channels; c++) { 1061 out_ch_data[c] = malloc(sizeof (unsigned char) * out_ch_size); 1062 1063 if (out_ch_data[c] == NULL) { 1064 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"), 1065 prog, out_ch_size / 1000); 1066 exit(1); 1067 } 1068 } 1069 } 1070 1071 /* 1072 * demux() 1073 * 1074 * Description: 1075 * Split a multichannel signal into separate channels. 1076 * 1077 * Arguments: 1078 * int unitsz Bytes per unit 1079 * int cnt Bytes to process 1080 * 1081 * Returns: 1082 * void 1083 */ 1084 static void 1085 demux(int unitsz, int cnt) 1086 { 1087 int c; /* Channel */ 1088 int s; /* Sample */ 1089 int b; /* Byte */ 1090 int tp; /* Pointer into current data */ 1091 int dp; /* Pointer into target data */ 1092 1093 /* Split */ 1094 for (c = 0; c < File_hdr.channels; c++) { 1095 for (s = 0; s < cnt / unitsz; s++) { 1096 tp = s * unitsz; 1097 dp = (s * File_hdr.channels + c) * unitsz; 1098 for (b = 0; b < unitsz; b++) { 1099 in_ch_data[c][tp + b] = inbuf[dp + b]; 1100 } 1101 } 1102 } 1103 } 1104 1105 /* 1106 * mux() 1107 * 1108 * Description: 1109 * Combine separate channels to produce a multichannel signal. 1110 * 1111 * Arguments: 1112 * char *outbuf Combined signal 1113 * 1114 * Returns: 1115 * void 1116 */ 1117 static void 1118 mux(char *outbuf) 1119 { 1120 int c; /* Channel */ 1121 int s; /* Sample */ 1122 1123 /* Combine */ 1124 for (c = 0; c < File_hdr.channels; c++) { 1125 for (s = 0; s < out_ch_size; s++) { 1126 outbuf[File_hdr.channels * s + c] = out_ch_data[c][s]; 1127 } 1128 } 1129 } 1130 1131 /* 1132 * freemux() 1133 * 1134 * Description: 1135 * Free memory used in multiplexing/demultiplexing. 1136 * 1137 * Arguments: 1138 * void 1139 * 1140 * Returns: 1141 * void 1142 */ 1143 static void 1144 freemux(void) 1145 { 1146 int c; /* Channel */ 1147 1148 /* Free */ 1149 for (c = 0; c < File_hdr.channels; c++) { 1150 free(in_ch_data[c]); 1151 free(out_ch_data[c]); 1152 free(&adpcm_state[c]); 1153 } 1154 1155 free(in_ch_data); 1156 free(out_ch_data); 1157 } 1158