1 1.64 mrg /* $NetBSD: play.c,v 1.64 2024/03/04 06:29:35 mrg Exp $ */ 2 1.3 mrg 3 1.3 mrg /* 4 1.61 mrg * Copyright (c) 1999, 2000, 2001, 2002, 2010, 2015, 2019, 2021 Matthew R. Green 5 1.3 mrg * All rights reserved. 6 1.3 mrg * 7 1.3 mrg * Redistribution and use in source and binary forms, with or without 8 1.3 mrg * modification, are permitted provided that the following conditions 9 1.3 mrg * are met: 10 1.3 mrg * 1. Redistributions of source code must retain the above copyright 11 1.3 mrg * notice, this list of conditions and the following disclaimer. 12 1.3 mrg * 2. Redistributions in binary form must reproduce the above copyright 13 1.3 mrg * notice, this list of conditions and the following disclaimer in the 14 1.3 mrg * documentation and/or other materials provided with the distribution. 15 1.3 mrg * 16 1.3 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.3 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.3 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.3 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.3 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.3 mrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.3 mrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.3 mrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.3 mrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.3 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.3 mrg * SUCH DAMAGE. 27 1.3 mrg */ 28 1.42 agc #include <sys/cdefs.h> 29 1.42 agc 30 1.42 agc #ifndef lint 31 1.64 mrg __RCSID("$NetBSD: play.c,v 1.64 2024/03/04 06:29:35 mrg Exp $"); 32 1.42 agc #endif 33 1.42 agc 34 1.1 mrg #include <sys/param.h> 35 1.1 mrg #include <sys/audioio.h> 36 1.1 mrg #include <sys/ioctl.h> 37 1.1 mrg #include <sys/mman.h> 38 1.1 mrg #include <sys/stat.h> 39 1.1 mrg 40 1.1 mrg #include <err.h> 41 1.1 mrg #include <fcntl.h> 42 1.30 mrg #include <signal.h> 43 1.1 mrg #include <stdio.h> 44 1.1 mrg #include <stdlib.h> 45 1.1 mrg #include <string.h> 46 1.1 mrg #include <unistd.h> 47 1.47 lukem #include <util.h> 48 1.1 mrg 49 1.1 mrg #include <paths.h> 50 1.1 mrg 51 1.1 mrg #include "libaudio.h" 52 1.1 mrg 53 1.58 mrg typedef size_t (*convert)(void *inbuf, void *outbuf, size_t len); 54 1.58 mrg 55 1.54 joerg static void usage(void) __dead; 56 1.54 joerg static void play(char *); 57 1.54 joerg static void play_fd(const char *, int); 58 1.58 mrg static ssize_t audioctl_write_fromhdr(void *, size_t, int, 59 1.58 mrg off_t *, const char *, 60 1.58 mrg convert *); 61 1.54 joerg static void cleanup(int) __dead; 62 1.54 joerg 63 1.54 joerg static audio_info_t info; 64 1.54 joerg static int volume; 65 1.54 joerg static int balance; 66 1.54 joerg static int port; 67 1.54 joerg static int fflag; 68 1.64 mrg static int nflag; 69 1.54 joerg static int qflag; 70 1.33 augustss int verbose; 71 1.54 joerg static int sample_rate; 72 1.54 joerg static int encoding; 73 1.54 joerg static char *encoding_str; 74 1.54 joerg static int precision; 75 1.54 joerg static int channels; 76 1.54 joerg 77 1.54 joerg static char const *play_errstring = NULL; 78 1.54 joerg static size_t bufsize; 79 1.64 mrg static int audiofd = -1; 80 1.54 joerg static int exitstatus = EXIT_SUCCESS; 81 1.1 mrg 82 1.1 mrg int 83 1.54 joerg main(int argc, char *argv[]) 84 1.1 mrg { 85 1.9 mrg size_t len; 86 1.9 mrg int ch; 87 1.1 mrg int iflag = 0; 88 1.35 augustss const char *defdevice = _PATH_SOUND; 89 1.32 augustss const char *device = NULL; 90 1.1 mrg 91 1.64 mrg while ((ch = getopt(argc, argv, "b:B:C:c:d:e:fhinp:P:qs:Vv:")) != -1) { 92 1.1 mrg switch (ch) { 93 1.1 mrg case 'b': 94 1.1 mrg decode_int(optarg, &balance); 95 1.1 mrg if (balance < 0 || balance > 64) 96 1.41 mrg errx(1, "balance must be between 0 and 63"); 97 1.1 mrg break; 98 1.51 mrg case 'B': 99 1.51 mrg bufsize = strsuftoll("write buffer size", optarg, 100 1.51 mrg 1, UINT_MAX); 101 1.51 mrg break; 102 1.6 mrg case 'c': 103 1.6 mrg decode_int(optarg, &channels); 104 1.6 mrg if (channels < 0) 105 1.6 mrg errx(1, "channels must be positive"); 106 1.10 jtk break; 107 1.1 mrg case 'C': 108 1.34 jdolecek /* Ignore, compatibility */ 109 1.1 mrg break; 110 1.1 mrg case 'd': 111 1.1 mrg device = optarg; 112 1.1 mrg break; 113 1.6 mrg case 'e': 114 1.6 mrg encoding_str = optarg; 115 1.6 mrg break; 116 1.6 mrg case 'f': 117 1.6 mrg fflag = 1; 118 1.6 mrg break; 119 1.1 mrg case 'i': 120 1.1 mrg iflag++; 121 1.1 mrg break; 122 1.64 mrg case 'n': 123 1.64 mrg nflag++; 124 1.64 mrg break; 125 1.1 mrg case 'q': 126 1.1 mrg qflag++; 127 1.1 mrg break; 128 1.6 mrg case 'P': 129 1.6 mrg decode_int(optarg, &precision); 130 1.26 minoura if (precision != 4 && precision != 8 && 131 1.26 minoura precision != 16 && precision != 24 && 132 1.26 minoura precision != 32) 133 1.26 minoura errx(1, "precision must be between 4, 8, 16, 24 or 32"); 134 1.6 mrg break; 135 1.1 mrg case 'p': 136 1.1 mrg len = strlen(optarg); 137 1.1 mrg 138 1.1 mrg if (strncmp(optarg, "speaker", len) == 0) 139 1.1 mrg port |= AUDIO_SPEAKER; 140 1.1 mrg else if (strncmp(optarg, "headphone", len) == 0) 141 1.1 mrg port |= AUDIO_HEADPHONE; 142 1.1 mrg else if (strncmp(optarg, "line", len) == 0) 143 1.1 mrg port |= AUDIO_LINE_OUT; 144 1.1 mrg else 145 1.1 mrg errx(1, 146 1.1 mrg "port must be `speaker', `headphone', or `line'"); 147 1.1 mrg break; 148 1.6 mrg case 's': 149 1.6 mrg decode_int(optarg, &sample_rate); 150 1.6 mrg if (sample_rate < 0 || sample_rate > 48000 * 2) /* XXX */ 151 1.37 grant errx(1, "sample rate must be between 0 and 96000"); 152 1.6 mrg break; 153 1.1 mrg case 'V': 154 1.1 mrg verbose++; 155 1.1 mrg break; 156 1.1 mrg case 'v': 157 1.1 mrg volume = atoi(optarg); 158 1.1 mrg if (volume < 0 || volume > 255) 159 1.37 grant errx(1, "volume must be between 0 and 255"); 160 1.1 mrg break; 161 1.1 mrg /* case 'h': */ 162 1.1 mrg default: 163 1.1 mrg usage(); 164 1.1 mrg /* NOTREACHED */ 165 1.1 mrg } 166 1.1 mrg } 167 1.1 mrg argc -= optind; 168 1.1 mrg argv += optind; 169 1.1 mrg 170 1.6 mrg if (encoding_str) { 171 1.6 mrg encoding = audio_enc_to_val(encoding_str); 172 1.6 mrg if (encoding == -1) 173 1.6 mrg errx(1, "unknown encoding, bailing..."); 174 1.6 mrg } 175 1.6 mrg 176 1.11 kleink if (device == NULL && (device = getenv("AUDIODEVICE")) == NULL && 177 1.11 kleink (device = getenv("AUDIODEV")) == NULL) /* Sun compatibility */ 178 1.35 augustss device = defdevice; 179 1.1 mrg 180 1.64 mrg if (!nflag) { 181 1.9 mrg audiofd = open(device, O_WRONLY); 182 1.64 mrg if (audiofd < 0 && device == defdevice) { 183 1.64 mrg device = _PATH_SOUND0; 184 1.64 mrg audiofd = open(device, O_WRONLY); 185 1.64 mrg } 186 1.64 mrg if (audiofd < 0) 187 1.64 mrg err(1, "failed to open %s", device); 188 1.32 augustss 189 1.64 mrg if (ioctl(audiofd, AUDIO_GETINFO, &info) < 0) 190 1.64 mrg err(1, "failed to get audio info"); 191 1.64 mrg if (bufsize == 0) 192 1.64 mrg bufsize = info.play.buffer_size; 193 1.52 jmcneill } 194 1.64 mrg if (bufsize == 0) 195 1.64 mrg bufsize = 32 * 1024; 196 1.1 mrg 197 1.30 mrg signal(SIGINT, cleanup); 198 1.30 mrg signal(SIGTERM, cleanup); 199 1.30 mrg signal(SIGHUP, cleanup); 200 1.30 mrg 201 1.20 mrg if (*argv) 202 1.20 mrg do 203 1.20 mrg play(*argv++); 204 1.20 mrg while (*argv); 205 1.20 mrg else 206 1.20 mrg play_fd("standard input", STDIN_FILENO); 207 1.4 mrg 208 1.30 mrg cleanup(0); 209 1.30 mrg } 210 1.30 mrg 211 1.54 joerg static void 212 1.54 joerg cleanup(int signo) 213 1.30 mrg { 214 1.30 mrg 215 1.64 mrg if (audiofd != -1) { 216 1.64 mrg (void)ioctl(audiofd, AUDIO_FLUSH, NULL); 217 1.64 mrg (void)ioctl(audiofd, AUDIO_SETINFO, &info); 218 1.64 mrg close(audiofd); 219 1.64 mrg audiofd = -1; 220 1.64 mrg } 221 1.47 lukem if (signo != 0) { 222 1.47 lukem (void)raise_default_signal(signo); 223 1.47 lukem } 224 1.15 kleink exit(exitstatus); 225 1.9 mrg } 226 1.4 mrg 227 1.58 mrg #ifndef __vax__ 228 1.58 mrg static size_t 229 1.58 mrg float32_to_linear32(void *inbuf, void *outbuf, size_t len) 230 1.58 mrg { 231 1.58 mrg uint8_t *inbuf8 = inbuf, *end = inbuf8 + len; 232 1.58 mrg uint8_t *outbuf8 = outbuf; 233 1.58 mrg float f; 234 1.58 mrg int32_t i; 235 1.58 mrg 236 1.58 mrg while (inbuf8 + sizeof f <= end) { 237 1.58 mrg memcpy(&f, inbuf8, sizeof f); 238 1.58 mrg 239 1.58 mrg /* saturate */ 240 1.58 mrg if (f < -1.0) 241 1.58 mrg f = -1.0; 242 1.58 mrg if (f > 1.0) 243 1.58 mrg f = 1.0; 244 1.58 mrg 245 1.58 mrg /* Convert -1.0 to +1.0 into a 32 bit signed value */ 246 1.60 joerg i = f * (float)INT32_MAX; 247 1.58 mrg 248 1.58 mrg memcpy(outbuf8, &i, sizeof i); 249 1.58 mrg 250 1.58 mrg inbuf8 += sizeof f; 251 1.58 mrg outbuf8 += sizeof i; 252 1.58 mrg } 253 1.58 mrg 254 1.58 mrg return len; 255 1.58 mrg } 256 1.58 mrg 257 1.58 mrg static size_t 258 1.58 mrg float64_to_linear32(void *inbuf, void *outbuf, size_t len) 259 1.58 mrg { 260 1.58 mrg uint8_t *inbuf8 = inbuf, *end = inbuf8 + len; 261 1.58 mrg uint8_t *outbuf8 = outbuf; 262 1.58 mrg double f; 263 1.58 mrg int32_t i; 264 1.58 mrg 265 1.58 mrg while (inbuf8 + sizeof f <= end) { 266 1.58 mrg memcpy(&f, inbuf8, sizeof f); 267 1.58 mrg 268 1.58 mrg /* saturate */ 269 1.58 mrg if (f < -1.0) 270 1.58 mrg f = -1.0; 271 1.58 mrg if (f > 1.0) 272 1.58 mrg f = 1.0; 273 1.58 mrg 274 1.58 mrg /* Convert -1.0 to +1.0 into a 32 bit signed value */ 275 1.58 mrg i = f * ((1u << 31) - 1); 276 1.58 mrg 277 1.58 mrg memcpy(outbuf8, &i, sizeof i); 278 1.58 mrg 279 1.58 mrg inbuf8 += sizeof f; 280 1.58 mrg outbuf8 += sizeof i; 281 1.58 mrg } 282 1.58 mrg 283 1.58 mrg return len / 2; 284 1.58 mrg } 285 1.58 mrg #endif /* __vax__ */ 286 1.58 mrg 287 1.58 mrg static size_t 288 1.58 mrg audio_write(int fd, void *buf, size_t len, convert conv) 289 1.58 mrg { 290 1.58 mrg static void *convert_buffer; 291 1.58 mrg static size_t convert_buffer_size; 292 1.58 mrg 293 1.64 mrg if (nflag) 294 1.64 mrg return len; 295 1.64 mrg 296 1.58 mrg if (conv == NULL) 297 1.58 mrg return write(fd, buf, len); 298 1.58 mrg 299 1.58 mrg if (convert_buffer == NULL || convert_buffer_size < len) { 300 1.58 mrg free(convert_buffer); 301 1.58 mrg convert_buffer = malloc(len); 302 1.58 mrg if (convert_buffer == NULL) 303 1.58 mrg err(1, "malloc of convert buffer failed"); 304 1.58 mrg convert_buffer_size = len; 305 1.58 mrg } 306 1.58 mrg len = conv(buf, convert_buffer, len); 307 1.58 mrg return write(fd, convert_buffer, len); 308 1.58 mrg } 309 1.58 mrg 310 1.54 joerg static void 311 1.54 joerg play(char *file) 312 1.20 mrg { 313 1.58 mrg convert conv = NULL; 314 1.20 mrg struct stat sb; 315 1.20 mrg void *addr, *oaddr; 316 1.20 mrg off_t filesize; 317 1.40 mrg size_t sizet_filesize; 318 1.63 mlelstv off_t datasize = 0; 319 1.20 mrg ssize_t hdrlen; 320 1.20 mrg int fd; 321 1.57 isaki int nw; 322 1.20 mrg 323 1.29 mrg if (file[0] == '-' && file[1] == 0) { 324 1.29 mrg play_fd("standard input", STDIN_FILENO); 325 1.29 mrg return; 326 1.29 mrg } 327 1.29 mrg 328 1.20 mrg fd = open(file, O_RDONLY); 329 1.20 mrg if (fd < 0) { 330 1.64 mrg warn("could not open %s", file); 331 1.20 mrg exitstatus = EXIT_FAILURE; 332 1.20 mrg return; 333 1.20 mrg } 334 1.20 mrg 335 1.20 mrg if (fstat(fd, &sb) < 0) 336 1.20 mrg err(1, "could not fstat %s", file); 337 1.20 mrg filesize = sb.st_size; 338 1.40 mrg sizet_filesize = (size_t)filesize; 339 1.20 mrg 340 1.20 mrg /* 341 1.40 mrg * if the file is not a regular file, doesn't fit in a size_t, 342 1.40 mrg * or if we failed to mmap the file, try to read it instead, so 343 1.40 mrg * that filesystems, etc, that do not support mmap() work 344 1.20 mrg */ 345 1.56 mlelstv if (!S_ISREG(sb.st_mode) || 346 1.40 mrg ((off_t)sizet_filesize != filesize) || 347 1.40 mrg (oaddr = addr = mmap(0, sizet_filesize, PROT_READ, 348 1.40 mrg MAP_SHARED, fd, 0)) == MAP_FAILED) { 349 1.20 mrg play_fd(file, fd); 350 1.20 mrg close(fd); 351 1.20 mrg return; 352 1.20 mrg } 353 1.20 mrg 354 1.20 mrg /* 355 1.20 mrg * give the VM system a bit of a hint about the type 356 1.51 mrg * of accesses we will make. we don't care about errors. 357 1.20 mrg */ 358 1.51 mrg madvise(addr, sizet_filesize, MADV_SEQUENTIAL); 359 1.20 mrg 360 1.20 mrg /* 361 1.58 mrg * get the header length and set up the audio device, and 362 1.58 mrg * determine any conversion needed. 363 1.20 mrg */ 364 1.20 mrg if ((hdrlen = audioctl_write_fromhdr(addr, 365 1.58 mrg sizet_filesize, audiofd, &datasize, file, &conv)) < 0) { 366 1.20 mrg if (play_errstring) 367 1.20 mrg errx(1, "%s: %s", play_errstring, file); 368 1.20 mrg else 369 1.20 mrg errx(1, "unknown audio file: %s", file); 370 1.20 mrg } 371 1.64 mrg if (verbose) 372 1.64 mrg printf("header length: %zd\n", hdrlen); 373 1.20 mrg 374 1.20 mrg filesize -= hdrlen; 375 1.20 mrg addr = (char *)addr + hdrlen; 376 1.55 mrg if (filesize < datasize || datasize == 0) { 377 1.55 mrg if (filesize < datasize) 378 1.36 mrg warnx("bogus datasize: %ld", (u_long)datasize); 379 1.23 hubertf datasize = filesize; 380 1.23 hubertf } 381 1.20 mrg 382 1.55 mrg while ((uint64_t)datasize > bufsize) { 383 1.58 mrg nw = audio_write(audiofd, addr, bufsize, conv); 384 1.57 isaki if (nw == -1) 385 1.20 mrg err(1, "write failed"); 386 1.57 isaki if ((size_t)nw != bufsize) 387 1.57 isaki errx(1, "write failed"); 388 1.20 mrg addr = (char *)addr + bufsize; 389 1.23 hubertf datasize -= bufsize; 390 1.20 mrg } 391 1.58 mrg nw = audio_write(audiofd, addr, datasize, conv); 392 1.57 isaki if (nw == -1) 393 1.20 mrg err(1, "final write failed"); 394 1.57 isaki if ((off_t)nw != datasize) 395 1.57 isaki errx(1, "final write failed"); 396 1.20 mrg 397 1.64 mrg if (!nflag && ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag) 398 1.20 mrg warn("audio drain ioctl failed"); 399 1.40 mrg if (munmap(oaddr, sizet_filesize) < 0) 400 1.20 mrg err(1, "munmap failed"); 401 1.20 mrg 402 1.20 mrg close(fd); 403 1.20 mrg } 404 1.25 simonb 405 1.9 mrg /* 406 1.39 wiz * play the file on the file descriptor fd 407 1.9 mrg */ 408 1.54 joerg static void 409 1.54 joerg play_fd(const char *file, int fd) 410 1.9 mrg { 411 1.58 mrg convert conv = NULL; 412 1.9 mrg char *buffer = malloc(bufsize); 413 1.9 mrg ssize_t hdrlen; 414 1.27 ross int nr, nw; 415 1.63 mlelstv off_t datasize = 0; 416 1.55 mrg off_t dataout = 0; 417 1.9 mrg 418 1.9 mrg if (buffer == NULL) 419 1.9 mrg err(1, "malloc of read buffer failed"); 420 1.29 mrg 421 1.27 ross nr = read(fd, buffer, bufsize); 422 1.27 ross if (nr < 0) 423 1.27 ross goto read_error; 424 1.27 ross if (nr == 0) { 425 1.46 christos if (fflag) { 426 1.46 christos free(buffer); 427 1.27 ross return; 428 1.46 christos } 429 1.31 mrg err(1, "unexpected EOF"); 430 1.27 ross } 431 1.58 mrg hdrlen = audioctl_write_fromhdr(buffer, nr, audiofd, &datasize, file, &conv); 432 1.9 mrg if (hdrlen < 0) { 433 1.9 mrg if (play_errstring) 434 1.9 mrg errx(1, "%s: %s", play_errstring, file); 435 1.9 mrg else 436 1.9 mrg errx(1, "unknown audio file: %s", file); 437 1.9 mrg } 438 1.9 mrg if (hdrlen > 0) { 439 1.45 mrg if (hdrlen > nr) /* shouldn't happen */ 440 1.45 mrg errx(1, "header seems really large: %lld", (long long)hdrlen); 441 1.27 ross memmove(buffer, buffer + hdrlen, nr - hdrlen); 442 1.27 ross nr -= hdrlen; 443 1.27 ross } 444 1.29 mrg while (datasize == 0 || dataout < datasize) { 445 1.27 ross if (datasize != 0 && dataout + nr > datasize) 446 1.27 ross nr = datasize - dataout; 447 1.58 mrg nw = audio_write(audiofd, buffer, nr, conv); 448 1.57 isaki if (nw == -1) 449 1.57 isaki err(1, "audio device write failed"); 450 1.27 ross if (nw != nr) 451 1.57 isaki errx(1, "audio device write failed"); 452 1.27 ross dataout += nw; 453 1.27 ross nr = read(fd, buffer, bufsize); 454 1.27 ross if (nr == -1) 455 1.27 ross goto read_error; 456 1.27 ross if (nr == 0) 457 1.27 ross break; 458 1.23 hubertf } 459 1.27 ross /* something to think about: no message given for dataout < datasize */ 460 1.64 mrg if (!nflag && ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag) 461 1.9 mrg warn("audio drain ioctl failed"); 462 1.27 ross return; 463 1.27 ross read_error: 464 1.27 ross err(1, "read of standard input failed"); 465 1.1 mrg } 466 1.1 mrg 467 1.1 mrg /* 468 1.1 mrg * only support sun and wav audio files so far ... 469 1.1 mrg * 470 1.1 mrg * XXX this should probably be mostly part of libaudio, but it 471 1.1 mrg * uses the local "info" variable. blah... fix me! 472 1.1 mrg */ 473 1.54 joerg static ssize_t 474 1.58 mrg audioctl_write_fromhdr(void *hdr, size_t fsz, int fd, off_t *datasize, const char *file, convert *conv) 475 1.1 mrg { 476 1.1 mrg sun_audioheader *sunhdr; 477 1.44 lukem ssize_t hdr_len = 0; 478 1.1 mrg 479 1.58 mrg *conv = NULL; 480 1.58 mrg 481 1.1 mrg AUDIO_INITINFO(&info); 482 1.1 mrg sunhdr = hdr; 483 1.1 mrg if (ntohl(sunhdr->magic) == AUDIO_FILE_MAGIC) { 484 1.25 simonb if (audio_sun_to_encoding(ntohl(sunhdr->encoding), 485 1.1 mrg &info.play.encoding, &info.play.precision)) { 486 1.20 mrg if (!qflag) 487 1.20 mrg warnx("unknown unsupported Sun audio encoding" 488 1.20 mrg " format %d", ntohl(sunhdr->encoding)); 489 1.13 mrg if (fflag) 490 1.13 mrg goto set_audio_mode; 491 1.1 mrg return (-1); 492 1.1 mrg } 493 1.1 mrg 494 1.8 augustss info.play.sample_rate = ntohl(sunhdr->sample_rate); 495 1.8 augustss info.play.channels = ntohl(sunhdr->channels); 496 1.25 simonb hdr_len = ntohl(sunhdr->hdr_size); 497 1.1 mrg 498 1.55 mrg *datasize = (off_t)ntohl(sunhdr->data_size); 499 1.6 mrg goto set_audio_mode; 500 1.1 mrg } 501 1.1 mrg 502 1.29 mrg hdr_len = audio_wav_parse_hdr(hdr, fsz, &info.play.encoding, 503 1.29 mrg &info.play.precision, &info.play.sample_rate, &info.play.channels, 504 1.29 mrg datasize); 505 1.1 mrg 506 1.1 mrg switch (hdr_len) { 507 1.1 mrg case AUDIO_ESHORTHDR: 508 1.1 mrg case AUDIO_EWAVUNSUPP: 509 1.1 mrg case AUDIO_EWAVBADPCM: 510 1.1 mrg case AUDIO_EWAVNODATA: 511 1.6 mrg play_errstring = audio_errstring(hdr_len); 512 1.1 mrg /* FALL THROUGH */ 513 1.1 mrg case AUDIO_ENOENT: 514 1.1 mrg break; 515 1.1 mrg default: 516 1.1 mrg if (hdr_len < 1) 517 1.1 mrg break; 518 1.6 mrg goto set_audio_mode; 519 1.6 mrg } 520 1.6 mrg /* 521 1.6 mrg * if we don't know it, bail unless we are forcing. 522 1.6 mrg */ 523 1.6 mrg if (fflag == 0) 524 1.6 mrg return (-1); 525 1.6 mrg set_audio_mode: 526 1.6 mrg if (port) 527 1.6 mrg info.play.port = port; 528 1.6 mrg if (volume) 529 1.6 mrg info.play.gain = volume; 530 1.6 mrg if (balance) 531 1.6 mrg info.play.balance = balance; 532 1.6 mrg if (fflag) { 533 1.6 mrg if (sample_rate) 534 1.8 augustss info.play.sample_rate = sample_rate; 535 1.6 mrg if (channels) 536 1.8 augustss info.play.channels = channels; 537 1.6 mrg if (encoding) 538 1.6 mrg info.play.encoding = encoding; 539 1.6 mrg if (precision) 540 1.12 tron info.play.precision = precision; 541 1.14 mrg hdr_len = 0; 542 1.6 mrg } 543 1.6 mrg info.mode = AUMODE_PLAY_ALL; 544 1.33 augustss 545 1.38 mrg if (verbose) { 546 1.38 mrg const char *enc = audio_enc_from_val(info.play.encoding); 547 1.38 mrg 548 1.38 mrg printf("%s: sample_rate=%d channels=%d " 549 1.45 mrg "datasize=%lld " 550 1.38 mrg "precision=%d%s%s\n", file, 551 1.38 mrg info.play.sample_rate, 552 1.38 mrg info.play.channels, 553 1.45 mrg (long long)*datasize, 554 1.38 mrg info.play.precision, 555 1.38 mrg enc ? " encoding=" : "", 556 1.38 mrg enc ? enc : ""); 557 1.38 mrg } 558 1.1 mrg 559 1.58 mrg #ifndef __vax__ 560 1.58 mrg if (info.play.encoding == AUDIO_ENCODING_LIBAUDIO_FLOAT32 || 561 1.58 mrg info.play.encoding == AUDIO_ENCODING_LIBAUDIO_FLOAT64) { 562 1.58 mrg const char *msg; 563 1.58 mrg 564 1.58 mrg if (info.play.encoding == AUDIO_ENCODING_LIBAUDIO_FLOAT32) { 565 1.58 mrg if (sizeof(float) * CHAR_BIT != 32) 566 1.58 mrg return -1; 567 1.58 mrg *conv = float32_to_linear32; 568 1.58 mrg msg = "32"; 569 1.58 mrg } else { 570 1.58 mrg if (sizeof(double) * CHAR_BIT != 64) 571 1.58 mrg return -1; 572 1.58 mrg *conv = float64_to_linear32; 573 1.61 mrg msg = "64"; 574 1.58 mrg } 575 1.58 mrg info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; 576 1.58 mrg info.play.precision = 32; 577 1.58 mrg if (verbose) 578 1.58 mrg printf("%s: converting IEEE float%s to precision=%d " 579 1.58 mrg "encoding=%s\n", file, msg, 580 1.58 mrg info.play.precision, 581 1.58 mrg audio_enc_from_val(info.play.encoding)); 582 1.58 mrg } 583 1.58 mrg #endif /* __vax__ */ 584 1.58 mrg 585 1.64 mrg if (!nflag && ioctl(fd, AUDIO_SETINFO, &info) < 0) 586 1.6 mrg err(1, "failed to set audio info"); 587 1.25 simonb 588 1.14 mrg return (hdr_len); 589 1.1 mrg } 590 1.1 mrg 591 1.54 joerg static void 592 1.54 joerg usage(void) 593 1.1 mrg { 594 1.22 cgd 595 1.64 mrg fprintf(stderr, "Usage: %s [-hinqV] [options] files\n", getprogname()); 596 1.5 mrg fprintf(stderr, "Options:\n\t" 597 1.53 wiz "-B buffer size\n\t" 598 1.5 mrg "-b balance (0-63)\n\t" 599 1.5 mrg "-d audio device\n\t" 600 1.6 mrg "-f force settings\n\t" 601 1.6 mrg "\t-c forced channels\n\t" 602 1.6 mrg "\t-e forced encoding\n\t" 603 1.6 mrg "\t-P forced precision\n\t" 604 1.6 mrg "\t-s forced sample rate\n\t" 605 1.5 mrg "-i header information\n\t" 606 1.5 mrg "-p output port\n\t" 607 1.5 mrg "-v volume\n"); 608 1.16 kleink exit(EXIT_FAILURE); 609 1.1 mrg } 610