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