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