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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This file contains a set of Very Paranoid routines to convert 29 * audio file headers to in-core audio headers and vice versa. 30 * 31 * They are robust enough to handle any random file input without 32 * crashing miserably. Of course, bad audio headers coming from 33 * the calling program can cause significant problems. 34 */ 35 36 #include <stdlib.h> 37 #include <memory.h> 38 #include <fcntl.h> 39 #include <errno.h> /* needed for large file error checking */ 40 #include <stdio.h> 41 #include <sys/types.h> 42 #include <sys/file.h> 43 #include <sys/stat.h> 44 #include <libintl.h> 45 #include <math.h> 46 47 #include <libaudio_impl.h> /* include other audio hdr's */ 48 49 /* Round up to a double boundary */ 50 #define ROUND_DBL(x) (((x) + 7) & ~7) 51 52 #define HEADER_BUFFER 100 53 54 #define _MGET_(str) (char *)dgettext(TEXT_DOMAIN, str) 55 56 static int audio_encode_aiff(Audio_hdr *, unsigned char *, unsigned int *); 57 static int audio_encode_au(Audio_hdr *, char *, unsigned int, 58 unsigned char *, unsigned int *); 59 static int audio_encode_wav(Audio_hdr *, unsigned char *, unsigned int *); 60 static double convert_from_ieee_extended(unsigned char *); 61 static void convert_to_ieee_extended(double, unsigned char *); 62 63 /* 64 * Write an audio file header to an output stream. 65 * 66 * The file header is encoded from the supplied Audio_hdr structure. 67 * If 'infop' is not NULL, it is the address of a buffer containing 'info' 68 * data. 'ilen' specifies the size of this buffer. 69 * The entire file header will be zero-padded to a double-word boundary. 70 * 71 * Note that the file header is stored on-disk in big-endian format, 72 * regardless of the machine type. 73 * 74 * Note also that the output file descriptor must not have been set up 75 * non-blocking i/o. If non-blocking behavior is desired, set this 76 * flag after writing the file header. 77 */ 78 int 79 audio_write_filehdr(int fd, Audio_hdr *hdrp, int file_type, char *infop, 80 unsigned int ilen) 81 /* file descriptor */ 82 /* audio header */ 83 /* audio header type */ 84 /* info buffer pointer */ 85 /* buffer size */ 86 { 87 int err; 88 unsigned blen; 89 unsigned char *buf; /* temporary buffer */ 90 91 /* create tmp buf for the encoding routines to work with */ 92 blen = HEADER_BUFFER + (infop ? ilen : 0) + 4; 93 blen = ROUND_DBL(blen); 94 95 if (!(buf = (unsigned char *)calloc(1, blen))) { 96 return (AUDIO_UNIXERROR); 97 } 98 99 switch (file_type) { 100 case FILE_AU: 101 err = audio_encode_au(hdrp, infop, ilen, buf, &blen); 102 break; 103 case FILE_WAV: 104 err = audio_encode_wav(hdrp, buf, &blen); 105 break; 106 case FILE_AIFF: 107 err = audio_encode_aiff(hdrp, buf, &blen); 108 break; 109 default: 110 return (AUDIO_ERR_BADFILETYPE); 111 } 112 113 if (err != AUDIO_SUCCESS) { 114 return (err); 115 } 116 117 /* Write and free the holding buffer */ 118 err = write(fd, (char *)buf, (int)blen); 119 (void) free((char *)buf); 120 121 if (err != blen) 122 return ((err < 0) ? AUDIO_UNIXERROR : AUDIO_ERR_BADFILEHDR); 123 124 return (AUDIO_SUCCESS); 125 126 } 127 128 /* 129 * Rewrite the aiff header chunk length and the data chunk length fields. 130 */ 131 static int 132 audio_rewrite_aiff_filesize(int fd, unsigned int size, unsigned int channels, 133 unsigned int bytes_per_sample) 134 { 135 unsigned int offset; 136 unsigned int tmp_uint; 137 unsigned int tmp_uint2; 138 unsigned int total_size; 139 140 /* first fix aiff_hdr_size */ 141 total_size = size + sizeof (aiff_hdr_chunk_t) + 142 AUDIO_AIFF_COMM_CHUNK_SIZE + sizeof (aiff_ssnd_chunk_t); 143 tmp_uint = total_size - (2 * sizeof (int)); 144 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &tmp_uint2); 145 offset = sizeof (int); 146 if (lseek(fd, offset, SEEK_SET) < 0) { 147 return (AUDIO_ERR_NOEFFECT); 148 } 149 if (write(fd, &tmp_uint2, sizeof (tmp_uint2)) != sizeof (tmp_uint2)) { 150 return (AUDIO_ERR_NOEFFECT); 151 } 152 153 /* fix the frame count */ 154 tmp_uint = size / channels / bytes_per_sample; 155 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &tmp_uint2); 156 offset = sizeof (aiff_hdr_chunk_t) + (2 * sizeof (int)) + 157 sizeof (short); 158 if (lseek(fd, offset, SEEK_SET) < 0) { 159 return (AUDIO_ERR_NOEFFECT); 160 } 161 if (write(fd, &tmp_uint2, sizeof (tmp_uint2)) != sizeof (tmp_uint2)) { 162 return (AUDIO_ERR_NOEFFECT); 163 } 164 165 /* fix the data size */ 166 tmp_uint = size + sizeof (aiff_ssnd_chunk_t) - (2 * sizeof (int)); 167 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &tmp_uint2); 168 offset = sizeof (aiff_hdr_chunk_t) + AUDIO_AIFF_COMM_CHUNK_SIZE + 169 sizeof (int); 170 if (lseek(fd, offset, SEEK_SET) < 0) { 171 return (AUDIO_ERR_NOEFFECT); 172 } 173 if (write(fd, &tmp_uint2, sizeof (tmp_uint2)) != sizeof (tmp_uint2)) { 174 return (AUDIO_ERR_NOEFFECT); 175 } 176 177 return (AUDIO_SUCCESS); 178 179 } 180 181 /* 182 * Rewrite the data size field for the .au file format. Rewrite the audio 183 * file header au_data_size field with the supplied value. Otherwise, 184 * return AUDIO_ERR_NOEFFECT. 185 */ 186 static int 187 audio_rewrite_au_filesize(int fd, unsigned int size) 188 { 189 au_filehdr_t fhdr; 190 int err; 191 int data; 192 int offset; 193 194 /* seek to the position of the au_data_size member */ 195 offset = (char *)&fhdr.au_data_size - (char *)&fhdr; 196 if (lseek(fd, offset, SEEK_SET) < 0) { 197 return (AUDIO_ERR_NOEFFECT); 198 } 199 200 /* Encode the 32-bit integer header field */ 201 AUDIO_AU_HOST2FILE(&size, &data); 202 203 /* Write the data */ 204 err = write(fd, (char *)&data, sizeof (fhdr.au_data_size)); 205 if (err != sizeof (fhdr.au_data_size)) 206 return ((err < 0) ? AUDIO_UNIXERROR : AUDIO_ERR_BADFILEHDR); 207 208 return (AUDIO_SUCCESS); 209 210 } 211 212 /* 213 * Rewrite the riff header chunk length and the data chunk length fields. 214 */ 215 static int 216 audio_rewrite_wav_filesize(int fd, unsigned int size) 217 { 218 wav_filehdr_t fhdr; 219 int calc_size; 220 int err; 221 int data; 222 int offset; 223 224 /* seek to the position of the riff header chunk length */ 225 calc_size = size + sizeof (fhdr) - sizeof (fhdr.wav_riff_ID) - 226 sizeof (fhdr.wav_riff_size); 227 AUDIO_WAV_HOST2FILE_INT(&calc_size, &data); 228 offset = (char *)&fhdr.wav_riff_size - (char *)&fhdr; 229 if (lseek(fd, offset, SEEK_SET) < 0) { 230 return (AUDIO_ERR_NOEFFECT); 231 } 232 233 /* Write the data */ 234 err = write(fd, (char *)&data, sizeof (fhdr.wav_riff_size)); 235 if (err != sizeof (fhdr.wav_riff_size)) 236 return ((err < 0) ? AUDIO_UNIXERROR : AUDIO_ERR_BADFILEHDR); 237 238 /* now seek to the position of the data chunk length */ 239 AUDIO_WAV_HOST2FILE_INT(&size, &data); 240 offset = (char *)&fhdr.wav_data_size - (char *)&fhdr; 241 if (lseek(fd, offset, SEEK_SET) < 0) { 242 return (AUDIO_ERR_NOEFFECT); 243 } 244 245 /* Write the data */ 246 err = write(fd, (char *)&data, sizeof (fhdr.wav_data_size)); 247 if (err != sizeof (fhdr.wav_data_size)) 248 return ((err < 0) ? AUDIO_UNIXERROR : AUDIO_ERR_BADFILEHDR); 249 250 return (AUDIO_SUCCESS); 251 252 } 253 254 /* 255 * Rewrite the data size field of an audio header to the output stream if 256 * the output file is capable of seeking. 257 */ 258 int 259 audio_rewrite_filesize(int fd, int file_type, unsigned int size, 260 unsigned int channels, unsigned int bytes_per_sample) 261 /* file descriptor */ 262 /* audio file type */ 263 /* new data size */ 264 /* number of channels */ 265 /* number of bytes per sample */ 266 { 267 int fcntl_err; 268 269 /* Can we seek back in this file and write without appending? */ 270 fcntl_err = fcntl(fd, F_GETFL, 0); 271 if ((fcntl_err < 0) && ((errno == EOVERFLOW) || (errno == EINVAL))) { 272 /* Large file encountered (probably) */ 273 perror("fcntl"); 274 exit(1); 275 } else if ((lseek(fd, (off_t)0, SEEK_SET) < 0) || 276 (fcntl_err & FAPPEND)) { 277 return (AUDIO_ERR_NOEFFECT); 278 } 279 280 switch (file_type) { 281 case FILE_AU: 282 return (audio_rewrite_au_filesize(fd, size)); 283 case FILE_WAV: 284 return (audio_rewrite_wav_filesize(fd, size)); 285 case FILE_AIFF: 286 return (audio_rewrite_aiff_filesize(fd, size, channels, 287 bytes_per_sample)); 288 default: 289 return (AUDIO_ERR_BADFILETYPE); 290 } 291 } 292 293 294 /* 295 * Decode an audio file header from an input stream. 296 * 297 * The file header is decoded into the supplied Audio_hdr structure, regardless 298 * of the file format. Thus .wav and .aiff files look like .au files once the 299 * header is decoded. 300 * 301 * If 'infop' is not NULL, it is the address of a buffer to which the 302 * 'info' portion of the file header will be copied. 'ilen' specifies 303 * the maximum number of bytes to copy. The buffer will be NULL-terminated, 304 * even if it means over-writing the last byte. 305 * 306 * Note that the .au file header is stored on-disk in big-endian format, 307 * regardless of the machine type. This may not have been true if 308 * the file was written on a non-Sun machine. For now, such 309 * files will appear invalid. 310 * 311 * Note also that the input file descriptor must not have been set up 312 * non-blocking i/o. If non-blocking behavior is desired, set this 313 * flag after reading the file header. 314 */ 315 int 316 audio_read_filehdr(int fd, Audio_hdr *hdrp, int *file_type, char *infop, 317 unsigned int ilen) 318 /* input file descriptor */ 319 /* output audio header */ 320 /* audio file type */ 321 /* info buffer pointer */ 322 /* buffer size */ 323 { 324 int err; 325 int dsize; 326 int isize; 327 unsigned resid; 328 unsigned char buf[HEADER_BUFFER]; 329 struct stat st; 330 331 /* decode the file header and fill in the hdrp structure */ 332 if ((err = audio_decode_filehdr(fd, buf, file_type, hdrp, &isize)) != 333 AUDIO_SUCCESS) { 334 goto checkerror; 335 } 336 337 /* Stat the file, to determine if it is a regular file. */ 338 err = fstat(fd, &st); 339 if (err < 0) { 340 return (AUDIO_UNIXERROR); 341 } 342 343 /* 344 * If au_data_size is not indeterminate (i.e., this isn't a pipe), 345 * try to validate the au_offset and au_data_size. 346 */ 347 if (*file_type == FILE_AU && hdrp->data_size != AUDIO_UNKNOWN_SIZE) { 348 /* Only trust the size for regular files */ 349 if (S_ISREG(st.st_mode)) { 350 dsize = isize + hdrp->data_size + sizeof (au_filehdr_t); 351 if (st.st_size < dsize) { 352 (void) fprintf(stderr, 353 _MGET_("Warning: More audio data " 354 "than the file header specifies\n")); 355 } else if (st.st_size > dsize) { 356 (void) fprintf(stderr, 357 _MGET_("Warning: Less audio data " 358 "than the file header specifies\n")); 359 } 360 } 361 } 362 363 resid = isize; 364 /* 365 * Deal with extra header data. 366 */ 367 if ((infop != NULL) && (ilen != 0)) { 368 /* 369 * If infop is non-NULL, try to read in the info data 370 */ 371 if (isize > ilen) 372 isize = ilen; 373 err = read(fd, infop, (int)isize); 374 if (err != isize) 375 goto checkerror; 376 377 /* Zero any residual bytes in the text buffer */ 378 if (isize < ilen) 379 (void) memset(&infop[isize], '\0', 380 (int)(ilen - isize)); 381 else 382 infop[ilen - 1] = '\0'; /* zero-terminate */ 383 384 resid -= err; /* subtract the amount read */ 385 } 386 387 /* 388 * If we truncated the info, seek or read data until info size 389 * is satisfied. If regular file, seek nearly to end and check 390 * for eof. 391 */ 392 if (resid != 0) { 393 if (S_ISREG(st.st_mode)) { 394 err = lseek(fd, (off_t)(resid - 1), SEEK_CUR); 395 if ((err < 0) || 396 ((err = read(fd, (char *)buf, 1)) != 1)) 397 goto checkerror; 398 } else while (resid != 0) { 399 char junk[8192]; /* temporary buffer */ 400 401 isize = (resid > sizeof (junk)) ? 402 sizeof (junk) : resid; 403 err = read(fd, junk, isize); 404 if (err != isize) 405 goto checkerror; 406 resid -= err; 407 } 408 } 409 410 return (AUDIO_SUCCESS); 411 412 checkerror: 413 if ((err < 0) && (errno == EOVERFLOW)) { 414 perror("read"); 415 exit(1); 416 } else { 417 return ((err < 0) ? AUDIO_UNIXERROR : AUDIO_ERR_BADFILEHDR); 418 } 419 return (AUDIO_SUCCESS); 420 } 421 422 /* 423 * Return TRUE if the named file is an audio file. Else, return FALSE. 424 */ 425 int 426 audio_isaudiofile(char *name) 427 { 428 int fd; 429 int err; 430 int file_type; /* ignored */ 431 int isize; 432 Audio_hdr hdr; 433 unsigned char buf[sizeof (au_filehdr_t)]; 434 435 /* Open the file (set O_NONBLOCK in case the name refers to a device) */ 436 fd = open(name, O_RDONLY | O_NONBLOCK); 437 if (fd < 0) { 438 if (errno == EOVERFLOW) { 439 perror("open"); 440 exit(1); 441 } else { 442 return (FALSE); 443 } 444 } 445 446 /* Read the header (but not the text info). */ 447 err = read(fd, (char *)buf, sizeof (buf)); 448 if (err < 0) { 449 if (errno == EOVERFLOW) { 450 perror("open"); 451 exit(1); 452 } else { 453 return (FALSE); 454 } 455 } 456 (void) close(fd); 457 458 if ((err == sizeof (buf)) && 459 (audio_decode_filehdr(fd, buf, &file_type, &hdr, &isize) == 460 AUDIO_SUCCESS)) { 461 return (hdr.encoding); 462 } else { 463 return (FALSE); 464 } 465 } 466 467 /* 468 * audio_endian() 469 * 470 * This routine tests the magic number at the head of a buffer 471 * containing the file header. The first thing in the header 472 * should be the magic number. 473 */ 474 static int 475 audio_endian(unsigned char *buf, int *file_type) 476 { 477 unsigned int magic1; 478 unsigned int magic2; 479 480 /* put the buffer into an int that is aligned properly */ 481 (void) memcpy(&magic1, buf, sizeof (magic1)); 482 483 magic2 = magic1; 484 SWABI(magic2); 485 486 if (magic1 == AUDIO_AU_FILE_MAGIC || magic2 == AUDIO_AU_FILE_MAGIC) { 487 *file_type = FILE_AU; 488 return (AUDIO_ENDIAN_BIG); 489 } else if (magic1 == AUDIO_WAV_RIFF_ID || magic2 == AUDIO_WAV_RIFF_ID) { 490 *file_type = FILE_WAV; 491 return (AUDIO_ENDIAN_SMALL); 492 } else if (magic1 == AUDIO_AIFF_HDR_CHUNK_ID || 493 magic2 == AUDIO_AIFF_HDR_CHUNK_ID) { 494 *file_type = FILE_AIFF; 495 return (AUDIO_ENDIAN_BIG); 496 } 497 498 return (AUDIO_ENDIAN_UNKNOWN); 499 } 500 501 /* 502 * Decode an aiff file header. Unlike .au and .wav, we have to process 503 * by chunk. 504 */ 505 static int 506 decode_aiff(int fd, unsigned char *buf, Audio_hdr *hdrp, int *isize) 507 { 508 aiff_hdr_chunk_t hdr_chunk; 509 aiff_comm_chunk_t comm_chunk; 510 aiff_ssnd_chunk_t ssnd_chunk; 511 uint32_t ID; 512 uint32_t size; 513 uint32_t tmp; 514 int data_type; 515 int hdr_sizes; 516 int sr; 517 short bits_per_sample; 518 short channels; 519 520 /* we've read in 4 bytes, read in the rest of the wav header */ 521 size = sizeof (hdr_chunk) - sizeof (hdr_chunk.aiff_hdr_ID); 522 523 /* read in the rest of the header */ 524 if (read(fd, &hdr_chunk.aiff_hdr_size, size) != size) { 525 return (AUDIO_UNIXERROR); 526 } 527 528 /* see which kind of audio file we have */ 529 AUDIO_AIFF_FILE2HOST_INT(&hdr_chunk.aiff_hdr_data_type, &data_type); 530 if (data_type != AUDIO_AIFF_HDR_FORM_AIFF) { 531 /* we can't play this version of a .aiff file */ 532 return (AUDIO_ERR_BADFILEHDR); 533 } 534 535 hdr_sizes = sizeof (hdr_chunk); 536 537 /* 538 * We don't know what the chunk order will be, so read each, getting 539 * the data we need from each. Eventually we'll get to the end of 540 * the file, in which case we should have all of the info on the 541 * file that we need. We then lseek() back to the data to play. 542 * 543 * We start each loop by reading the chunk ID. 544 */ 545 while (read(fd, &tmp, sizeof (tmp)) == sizeof (tmp)) { 546 AUDIO_AIFF_FILE2HOST_INT(&tmp, &ID); 547 switch (ID) { 548 case AUDIO_AIFF_COMM_ID: 549 /* read in the rest of the COMM chunk */ 550 size = AUDIO_AIFF_COMM_CHUNK_SIZE - 551 sizeof (comm_chunk.aiff_comm_ID); 552 if (read(fd, &comm_chunk.aiff_comm_size, size) != 553 size) { 554 return (AUDIO_UNIXERROR); 555 } 556 557 sr = convert_from_ieee_extended( 558 comm_chunk.aiff_comm_sample_rate); 559 560 hdr_sizes += AUDIO_AIFF_COMM_CHUNK_SIZE; 561 562 break; 563 case AUDIO_AIFF_SSND_ID: 564 /* read in the rest of the INST chunk */ 565 size = sizeof (ssnd_chunk) - 566 sizeof (ssnd_chunk.aiff_ssnd_ID); 567 if (read(fd, &ssnd_chunk.aiff_ssnd_size, size) != 568 size) { 569 return (AUDIO_UNIXERROR); 570 } 571 572 /* 573 * This has to be the last chunk because the audio data 574 * follows. So we should have all we need to tell the 575 * app the format information. 576 */ 577 hdrp->sample_rate = sr; 578 579 AUDIO_AIFF_FILE2HOST_SHORT( 580 &comm_chunk.aiff_comm_channels, 581 &channels); 582 /* use channels to convert from short to int */ 583 hdrp->channels = channels; 584 585 AUDIO_AIFF_FILE2HOST_SHORT( 586 &comm_chunk.aiff_comm_sample_size, 587 &bits_per_sample); 588 switch (bits_per_sample) { 589 case AUDIO_AIFF_COMM_8_BIT_SAMPLE_SIZE: 590 hdrp->encoding = AUDIO_AU_ENCODING_LINEAR_8; 591 break; 592 case AUDIO_AIFF_COMM_16_BIT_SAMPLE_SIZE: 593 hdrp->encoding = AUDIO_AU_ENCODING_LINEAR_16; 594 break; 595 default: 596 return (AUDIO_ERR_BADFILEHDR); 597 } 598 599 AUDIO_AIFF_FILE2HOST_INT(&ssnd_chunk.aiff_ssnd_size, 600 &size); 601 size -= sizeof (ssnd_chunk.aiff_ssnd_offset) + 602 sizeof (ssnd_chunk.aiff_ssnd_block_size); 603 hdrp->data_size = size; 604 605 hdr_sizes += sizeof (ssnd_chunk); 606 607 *isize = hdr_sizes - sizeof (au_filehdr_t); 608 609 return (AUDIO_SUCCESS); 610 default: 611 /* 612 * Unknown chunk. Read the size, which is right after 613 * the ID. Then seek past it to get to the next chunk. 614 */ 615 if (read(fd, &size, sizeof (size)) != sizeof (size)) { 616 return (AUDIO_UNIXERROR); 617 } 618 619 if (lseek(fd, size, SEEK_CUR) < 0) { 620 return (AUDIO_UNIXERROR); 621 } 622 break; 623 } 624 } 625 626 return (AUDIO_SUCCESS); 627 628 } /* decode_aiff() */ 629 630 /* 631 * Decode an au file header. 632 */ 633 static int 634 decode_au(int fd, unsigned char *buf, Audio_hdr *hdrp, int *isize, 635 boolean_t read_info) 636 { 637 au_filehdr_t fhdr; 638 int offset; 639 int size; 640 641 if (read_info) { 642 /* read in the rest of the au header */ 643 size = sizeof (fhdr) - sizeof (int); 644 (void) lseek(fd, (off_t)4, SEEK_SET); 645 if (read(fd, &buf[sizeof (int)], size) != size) { 646 647 return (AUDIO_UNIXERROR); 648 } 649 } 650 651 /* put the buffer into a structure that is aligned properly */ 652 (void) memcpy(&fhdr, buf, sizeof (fhdr)); 653 654 /* Decode the 32-bit integer header fields. */ 655 AUDIO_AU_FILE2HOST(&fhdr.au_offset, &offset); 656 AUDIO_AU_FILE2HOST(&fhdr.au_data_size, &hdrp->data_size); 657 AUDIO_AU_FILE2HOST(&fhdr.au_encoding, &hdrp->encoding); 658 AUDIO_AU_FILE2HOST(&fhdr.au_sample_rate, &hdrp->sample_rate); 659 AUDIO_AU_FILE2HOST(&fhdr.au_channels, &hdrp->channels); 660 661 /* Set the info field size (ie, number of bytes left before data). */ 662 *isize = offset - sizeof (au_filehdr_t); 663 664 return (AUDIO_SUCCESS); 665 666 } /* decode_au() */ 667 668 /* 669 * Decode a wav file header. 670 * 671 * .wav files are stored on-disk in little-endian format. 672 */ 673 static int 674 decode_wav(int fd, unsigned char *buf, Audio_hdr *hdrp, int *isize) 675 { 676 wav_filehdr_t fhdr; 677 uint32_t ID; 678 uint32_t size; 679 short bits_per_sample; 680 short encoding; 681 682 /* we've read in 4 bytes, read in the rest of the wav header */ 683 size = sizeof (fhdr) - sizeof (int); 684 685 /* read in the rest of the header */ 686 if (read(fd, &buf[sizeof (int)], size) != size) { 687 return (AUDIO_UNIXERROR); 688 } 689 690 /* put the buffer into a structure that is aligned properly */ 691 (void) memcpy(&fhdr, buf, sizeof (fhdr)); 692 693 /* make sure we have the correct RIFF type */ 694 AUDIO_WAV_FILE2HOST_INT(&fhdr.wav_type_ID, &ID); 695 if (ID != AUDIO_WAV_TYPE_ID) { 696 /* not a wave file */ 697 return (AUDIO_ERR_BADFILEHDR); 698 } 699 700 /* decode the fields */ 701 AUDIO_WAV_FILE2HOST_INT(&fhdr.wav_fmt_ID, &ID); 702 if (ID != AUDIO_WAV_FORMAT_ID) { 703 /* mangled format */ 704 return (AUDIO_ERR_BADFILEHDR); 705 } 706 707 AUDIO_WAV_FILE2HOST_SHORT(&fhdr.wav_fmt_encoding, &encoding); 708 AUDIO_WAV_FILE2HOST_SHORT(&fhdr.wav_fmt_channels, &hdrp->channels); 709 AUDIO_WAV_FILE2HOST_INT(&fhdr.wav_fmt_sample_rate, &hdrp->sample_rate); 710 AUDIO_WAV_FILE2HOST_SHORT(&fhdr.wav_fmt_bits_per_sample, 711 &bits_per_sample); 712 713 /* convert .wav encodings to .au encodings */ 714 switch (encoding) { 715 case AUDIO_WAV_FMT_ENCODING_PCM: 716 switch (bits_per_sample) { 717 case AUDIO_WAV_FMT_BITS_PER_SAMPLE_8_BITS: 718 hdrp->encoding = AUDIO_AU_ENCODING_LINEAR_8; 719 break; 720 case AUDIO_WAV_FMT_BITS_PER_SAMPLE_16_BITS: 721 hdrp->encoding = AUDIO_AU_ENCODING_LINEAR_16; 722 break; 723 default: 724 return (AUDIO_ERR_BADFILEHDR); 725 } 726 break; 727 case AUDIO_WAV_FMT_ENCODING_ALAW: 728 hdrp->encoding = AUDIO_AU_ENCODING_ALAW; 729 break; 730 case AUDIO_WAV_FMT_ENCODING_MULAW: 731 hdrp->encoding = AUDIO_AU_ENCODING_ULAW; 732 break; 733 default: 734 return (AUDIO_ERR_BADFILEHDR); 735 } 736 737 AUDIO_WAV_FILE2HOST_INT(&fhdr.wav_data_size, &hdrp->data_size); 738 739 *isize = sizeof (wav_filehdr_t) - sizeof (au_filehdr_t); 740 741 return (AUDIO_SUCCESS); 742 743 } /* decode_wav() */ 744 745 /* 746 * Try to decode buffer containing an audio file header into an audio header. 747 */ 748 int 749 audio_decode_filehdr(int fd, unsigned char *buf, int *file_type, 750 Audio_hdr *hdrp, int *isize) 751 /* file descriptor */ 752 /* buffer address */ 753 /* audio file type */ 754 /* output audio header */ 755 /* output size of info */ 756 { 757 int err; 758 struct stat fd_stat; 759 boolean_t read_info; 760 761 /* Test for .au first */ 762 hdrp->endian = audio_endian(buf, file_type); 763 764 /* 765 * When cat'ing a file, audioconvert will read the whole header 766 * trying to figure out the file. audioplay however, does not. 767 * Hence we check if this is a pipe and do not attempt to read 768 * any more header info if the file type is already known. 769 * Otherwise we overwrite the header data already in the buffer. 770 */ 771 if (fstat(fd, &fd_stat) < 0) { 772 return (AUDIO_ERR_BADFILEHDR); 773 } 774 if (S_ISFIFO(fd_stat.st_mode) && (*file_type == FILE_AU)) { 775 read_info = B_FALSE; 776 } else { 777 /* 778 * Not an au file, or file type unknown. Reread the header's 779 * magic number. Fortunately this is always an int. 780 */ 781 (void) lseek(fd, (off_t)0, SEEK_SET); 782 err = read(fd, (char *)buf, sizeof (int)); 783 read_info = B_TRUE; 784 785 /* test the magic number to determine the endian */ 786 if ((hdrp->endian = audio_endian(buf, file_type)) == 787 AUDIO_ENDIAN_UNKNOWN) { 788 789 return (AUDIO_ERR_BADFILEHDR); 790 } 791 } 792 793 /* decode the different file types, putting the data into hdrp */ 794 switch (*file_type) { 795 case FILE_AU: 796 if ((err = decode_au(fd, buf, hdrp, isize, read_info)) != 797 AUDIO_SUCCESS) { 798 return (err); 799 } 800 break; 801 case FILE_WAV: 802 if ((err = decode_wav(fd, buf, hdrp, isize)) != AUDIO_SUCCESS) { 803 return (err); 804 } 805 break; 806 case FILE_AIFF: 807 if ((err = decode_aiff(fd, buf, hdrp, isize)) != 808 AUDIO_SUCCESS) { 809 return (err); 810 } 811 break; 812 default: 813 return (AUDIO_ERR_BADFILEHDR); 814 } 815 816 /* Convert from file format info to audio format info */ 817 switch (hdrp->encoding) { 818 case AUDIO_AU_ENCODING_ULAW: 819 hdrp->encoding = AUDIO_ENCODING_ULAW; 820 hdrp->bytes_per_unit = 1; 821 hdrp->samples_per_unit = 1; 822 break; 823 case AUDIO_AU_ENCODING_ALAW: 824 hdrp->encoding = AUDIO_ENCODING_ALAW; 825 hdrp->bytes_per_unit = 1; 826 hdrp->samples_per_unit = 1; 827 break; 828 case AUDIO_AU_ENCODING_LINEAR_8: 829 if (*file_type == FILE_WAV) { 830 hdrp->encoding = AUDIO_ENCODING_LINEAR8; 831 } else { 832 hdrp->encoding = AUDIO_ENCODING_LINEAR; 833 } 834 hdrp->bytes_per_unit = 1; 835 hdrp->samples_per_unit = 1; 836 break; 837 case AUDIO_AU_ENCODING_LINEAR_16: 838 hdrp->encoding = AUDIO_ENCODING_LINEAR; 839 hdrp->bytes_per_unit = 2; 840 hdrp->samples_per_unit = 1; 841 break; 842 case AUDIO_AU_ENCODING_LINEAR_24: 843 hdrp->encoding = AUDIO_ENCODING_LINEAR; 844 hdrp->bytes_per_unit = 3; 845 hdrp->samples_per_unit = 1; 846 break; 847 case AUDIO_AU_ENCODING_LINEAR_32: 848 hdrp->encoding = AUDIO_ENCODING_LINEAR; 849 hdrp->bytes_per_unit = 4; 850 hdrp->samples_per_unit = 1; 851 break; 852 case AUDIO_AU_ENCODING_FLOAT: 853 hdrp->encoding = AUDIO_ENCODING_FLOAT; 854 hdrp->bytes_per_unit = 4; 855 hdrp->samples_per_unit = 1; 856 break; 857 case AUDIO_AU_ENCODING_DOUBLE: 858 hdrp->encoding = AUDIO_ENCODING_FLOAT; 859 hdrp->bytes_per_unit = 8; 860 hdrp->samples_per_unit = 1; 861 break; 862 case AUDIO_AU_ENCODING_ADPCM_G721: 863 hdrp->encoding = AUDIO_ENCODING_G721; 864 hdrp->bytes_per_unit = 1; 865 hdrp->samples_per_unit = 2; 866 break; 867 case AUDIO_AU_ENCODING_ADPCM_G723_3: 868 hdrp->encoding = AUDIO_ENCODING_G723; 869 hdrp->bytes_per_unit = 3; 870 hdrp->samples_per_unit = 8; 871 break; 872 case AUDIO_AU_ENCODING_ADPCM_G723_5: 873 hdrp->encoding = AUDIO_ENCODING_G723; 874 hdrp->bytes_per_unit = 5; 875 hdrp->samples_per_unit = 8; 876 break; 877 878 default: 879 return (AUDIO_ERR_BADFILEHDR); 880 } 881 return (AUDIO_SUCCESS); 882 } 883 884 /* 885 * Encode a .aiff file header from the supplied Audio_hdr structure and 886 * store in the supplied char* buffer. blen is the size of the buffer to 887 * store the header in. Unlike .au and .wav we can't cast to a data structure. 888 * We have to build it one chunk at a time. 889 * 890 * NOTE: .aiff doesn't support unsigned 8-bit linear PCM. 891 */ 892 static int 893 audio_encode_aiff(Audio_hdr *hdrp, unsigned char *buf, unsigned int *blen) 894 /* audio header */ 895 /* output buffer */ 896 /* output buffer size */ 897 { 898 aiff_comm_chunk_t comm_chunk; 899 aiff_hdr_chunk_t hdr_chunk; 900 aiff_ssnd_chunk_t ssnd_chunk; 901 uint32_t tmp_uint; 902 uint32_t tmp_uint2; 903 int buf_size = 0; 904 int encoding; 905 uint16_t tmp_ushort; 906 907 /* the only encoding we support for .aiff is signed linear PCM */ 908 if (hdrp->encoding != AUDIO_ENCODING_LINEAR) { 909 return (AUDIO_ERR_ENCODING); 910 } 911 912 /* build the header chunk */ 913 tmp_uint = AUDIO_AIFF_HDR_CHUNK_ID; 914 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &hdr_chunk.aiff_hdr_ID); 915 /* needs to be fixed when closed */ 916 tmp_uint = AUDIO_AIFF_UNKNOWN_SIZE; 917 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &hdr_chunk.aiff_hdr_size); 918 tmp_uint = AUDIO_AIFF_HDR_FORM_AIFF; 919 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &hdr_chunk.aiff_hdr_data_type); 920 (void) memcpy(&buf[buf_size], &hdr_chunk, sizeof (hdr_chunk)); 921 buf_size += sizeof (hdr_chunk); 922 923 /* build the COMM chunk */ 924 tmp_uint = AUDIO_AIFF_COMM_ID; 925 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &comm_chunk.aiff_comm_ID); 926 tmp_uint = AUDIO_AIFF_COMM_SIZE; 927 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &comm_chunk.aiff_comm_size); 928 tmp_ushort = hdrp->channels; 929 AUDIO_AIFF_HOST2FILE_SHORT(&tmp_ushort, &comm_chunk.aiff_comm_channels); 930 /* needs to be fixed when closed */ 931 tmp_uint = AUDIO_AIFF_UNKNOWN_SIZE; 932 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &tmp_uint2); 933 AUDIO_AIFF_COMM_INT2FRAMES(comm_chunk.aiff_comm_frames, tmp_uint2); 934 tmp_ushort = hdrp->bytes_per_unit * 8; 935 AUDIO_AIFF_HOST2FILE_SHORT(&tmp_ushort, 936 &comm_chunk.aiff_comm_sample_size); 937 convert_to_ieee_extended((double)hdrp->sample_rate, 938 comm_chunk.aiff_comm_sample_rate); 939 (void) memcpy(&buf[buf_size], &comm_chunk, AUDIO_AIFF_COMM_CHUNK_SIZE); 940 buf_size += AUDIO_AIFF_COMM_CHUNK_SIZE; 941 942 /* build the SSND chunk */ 943 tmp_uint = AUDIO_AIFF_SSND_ID; 944 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &ssnd_chunk.aiff_ssnd_ID); 945 /* needs to be fixed when closed */ 946 tmp_uint = AUDIO_AIFF_UNKNOWN_SIZE; 947 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &ssnd_chunk.aiff_ssnd_size); 948 ssnd_chunk.aiff_ssnd_offset = 0; 949 ssnd_chunk.aiff_ssnd_block_size = 0; 950 (void) memcpy(&buf[buf_size], &ssnd_chunk, sizeof (ssnd_chunk)); 951 buf_size += sizeof (ssnd_chunk); 952 953 *blen = buf_size; 954 955 return (AUDIO_SUCCESS); 956 957 } /* audio_encode_aiff() */ 958 959 /* 960 * Encode a .au file header from the supplied Audio_hdr structure and 961 * store in the supplied char* buffer. blen is the size of the buffer to 962 * store the header in. If 'infop' is not NULL, it is the address of a 963 * buffer containing 'info' data. 'ilen' specifies the size of this buffer. 964 * The entire file header will be zero-padded to a double-word boundary. 965 * 966 * NOTE: .au doesn't support unsigned 8-bit linear PCM. 967 */ 968 static int 969 audio_encode_au(Audio_hdr *hdrp, char *infop, unsigned int ilen, 970 unsigned char *buf, unsigned int *blen) 971 /* audio header */ 972 /* info buffer pointer */ 973 /* info buffer size */ 974 /* output buffer */ 975 /* output buffer size */ 976 { 977 au_filehdr_t fhdr; 978 int encoding; 979 int hdrsize; 980 int magic; 981 int offset; 982 983 /* 984 * Set the size of the real header (hdr size + info size). 985 * If no supplied info, make sure a minimum size is accounted for. 986 * Also, round the whole thing up to double-word alignment. 987 */ 988 if ((infop == NULL) || (ilen == 0)) { 989 infop = NULL; 990 ilen = 4; 991 } 992 hdrsize = sizeof (fhdr) + ilen; 993 offset = ROUND_DBL(hdrsize); 994 995 /* Check the data encoding. */ 996 switch (hdrp->encoding) { 997 case AUDIO_ENCODING_LINEAR8: 998 return (AUDIO_ERR_ENCODING); /* we don't support ulinear */ 999 case AUDIO_ENCODING_ULAW: 1000 if (hdrp->samples_per_unit != 1) 1001 return (AUDIO_ERR_BADHDR); 1002 1003 switch (hdrp->bytes_per_unit) { 1004 case 1: 1005 encoding = AUDIO_AU_ENCODING_ULAW; 1006 break; 1007 default: 1008 return (AUDIO_ERR_BADHDR); 1009 } 1010 break; 1011 case AUDIO_ENCODING_ALAW: 1012 if (hdrp->samples_per_unit != 1) 1013 return (AUDIO_ERR_BADHDR); 1014 1015 switch (hdrp->bytes_per_unit) { 1016 case 1: 1017 encoding = AUDIO_AU_ENCODING_ALAW; 1018 break; 1019 default: 1020 return (AUDIO_ERR_BADHDR); 1021 } 1022 break; 1023 case AUDIO_ENCODING_LINEAR: 1024 if (hdrp->samples_per_unit != 1) 1025 return (AUDIO_ERR_BADHDR); 1026 1027 switch (hdrp->bytes_per_unit) { 1028 case 1: 1029 encoding = AUDIO_AU_ENCODING_LINEAR_8; 1030 break; 1031 case 2: 1032 encoding = AUDIO_AU_ENCODING_LINEAR_16; 1033 break; 1034 case 3: 1035 encoding = AUDIO_AU_ENCODING_LINEAR_24; 1036 break; 1037 case 4: 1038 encoding = AUDIO_AU_ENCODING_LINEAR_32; 1039 break; 1040 default: 1041 return (AUDIO_ERR_BADHDR); 1042 } 1043 break; 1044 case AUDIO_ENCODING_FLOAT: 1045 if (hdrp->samples_per_unit != 1) 1046 return (AUDIO_ERR_BADHDR); 1047 1048 switch (hdrp->bytes_per_unit) { 1049 case 4: 1050 encoding = AUDIO_AU_ENCODING_FLOAT; 1051 break; 1052 case 8: 1053 encoding = AUDIO_AU_ENCODING_DOUBLE; 1054 break; 1055 default: 1056 return (AUDIO_ERR_BADHDR); 1057 } 1058 break; 1059 case AUDIO_ENCODING_G721: 1060 if (hdrp->bytes_per_unit != 1) 1061 return (AUDIO_ERR_BADHDR); 1062 else if (hdrp->samples_per_unit != 2) 1063 return (AUDIO_ERR_BADHDR); 1064 else 1065 encoding = AUDIO_AU_ENCODING_ADPCM_G721; 1066 break; 1067 case AUDIO_ENCODING_G723: 1068 if (hdrp->samples_per_unit != 8) 1069 return (AUDIO_ERR_BADHDR); 1070 else if (hdrp->bytes_per_unit == 3) 1071 encoding = AUDIO_AU_ENCODING_ADPCM_G723_3; 1072 else if (hdrp->bytes_per_unit == 5) 1073 encoding = AUDIO_AU_ENCODING_ADPCM_G723_5; 1074 else 1075 return (AUDIO_ERR_BADHDR); 1076 break; 1077 default: 1078 return (AUDIO_ERR_BADHDR); 1079 } 1080 1081 /* copy the fhdr into the supplied buffer - make sure it'll fit */ 1082 if (*blen < offset) { 1083 /* XXX - is this apropriate? */ 1084 return (AUDIO_EOF); 1085 } 1086 1087 /* reset blen to actual size of hdr data */ 1088 *blen = (unsigned)offset; 1089 1090 magic = AUDIO_AU_FILE_MAGIC; /* set the magic number */ 1091 1092 /* Encode the audio header structure. */ 1093 AUDIO_AU_HOST2FILE(&magic, &fhdr.au_magic); 1094 AUDIO_AU_HOST2FILE(&offset, &fhdr.au_offset); 1095 AUDIO_AU_HOST2FILE(&hdrp->data_size, &fhdr.au_data_size); 1096 AUDIO_AU_HOST2FILE(&encoding, &fhdr.au_encoding); 1097 AUDIO_AU_HOST2FILE(&hdrp->sample_rate, &fhdr.au_sample_rate); 1098 AUDIO_AU_HOST2FILE(&hdrp->channels, &fhdr.au_channels); 1099 1100 /* Copy to the buffer */ 1101 (void) memcpy(buf, &fhdr, sizeof (fhdr)); 1102 1103 /* Copy the info data, if present */ 1104 if (infop != NULL) { 1105 (void) memcpy(&buf[sizeof (fhdr)], infop, (int)ilen); 1106 buf += ilen; 1107 } 1108 1109 if (offset > hdrsize) { 1110 (void) memset(&buf[hdrsize], '\0', (size_t)(offset - hdrsize)); 1111 } 1112 1113 /* buf now has the data, just return ... */ 1114 1115 return (AUDIO_SUCCESS); 1116 1117 } /* audio_encode_au() */ 1118 1119 /* 1120 * Encode a .wav file header from the supplied Audio_hdr structure and 1121 * store in the supplied char* buffer. blen is the size of the buffer to 1122 * store the header in. .wav doesn't support an information string like 1123 * .au does. 1124 * 1125 * NOTE: .wav only supports a few encoding methods. 1126 */ 1127 static int 1128 audio_encode_wav(Audio_hdr *hdrp, unsigned char *buf, unsigned int *blen) 1129 /* audio header */ 1130 /* output buffer */ 1131 /* output buffer size */ 1132 { 1133 wav_filehdr_t fhdr; 1134 int bytes_per_second; 1135 int bytes_per_sample; 1136 int bits_per_sample; 1137 int id; 1138 int length; 1139 int type; 1140 short encoding; 1141 1142 /* make sure we've got valid encoding and precision settings for .wav */ 1143 switch (hdrp->encoding) { 1144 case AUDIO_ENCODING_LINEAR8: 1145 if (hdrp->bytes_per_unit != 1) { 1146 return (AUDIO_ERR_ENCODING); 1147 } 1148 encoding = AUDIO_WAV_FMT_ENCODING_PCM; 1149 break; 1150 case AUDIO_ENCODING_ULAW: 1151 if (hdrp->bytes_per_unit != 1) { 1152 return (AUDIO_ERR_ENCODING); 1153 } 1154 encoding = AUDIO_WAV_FMT_ENCODING_MULAW; 1155 break; 1156 case AUDIO_ENCODING_ALAW: 1157 if (hdrp->bytes_per_unit != 1) { 1158 return (AUDIO_ERR_ENCODING); 1159 } 1160 encoding = AUDIO_WAV_FMT_ENCODING_ALAW; 1161 break; 1162 case AUDIO_ENCODING_LINEAR: 1163 if (hdrp->bytes_per_unit != 2) { 1164 return (AUDIO_ERR_ENCODING); 1165 } 1166 encoding = AUDIO_WAV_FMT_ENCODING_PCM; 1167 break; 1168 default: 1169 return (AUDIO_ERR_ENCODING); 1170 } 1171 1172 /* fill in the riff chunk */ 1173 id = AUDIO_WAV_RIFF_ID; 1174 length = AUDIO_WAV_UNKNOWN_SIZE; 1175 AUDIO_WAV_HOST2FILE_INT(&id, &fhdr.wav_riff_ID); 1176 AUDIO_WAV_HOST2FILE_INT(&length, &fhdr.wav_riff_size); 1177 1178 /* fill in the type chunk */ 1179 type = AUDIO_WAV_TYPE_ID; 1180 AUDIO_WAV_HOST2FILE_INT(&type, &fhdr.wav_type_ID); 1181 1182 1183 /* fill in the format chunk */ 1184 id = AUDIO_WAV_FORMAT_ID; 1185 length = AUDIO_WAV_FORMAT_SIZE; 1186 bytes_per_second = hdrp->sample_rate * hdrp->channels * 1187 hdrp->bytes_per_unit; 1188 bytes_per_sample = hdrp->channels * hdrp->bytes_per_unit; 1189 bits_per_sample = hdrp->bytes_per_unit * 8; 1190 1191 AUDIO_WAV_HOST2FILE_INT(&id, &fhdr.wav_fmt_ID); 1192 AUDIO_WAV_HOST2FILE_INT(&length, &fhdr.wav_fmt_size); 1193 AUDIO_WAV_HOST2FILE_SHORT(&encoding, &fhdr.wav_fmt_encoding); 1194 AUDIO_WAV_HOST2FILE_SHORT(&hdrp->channels, &fhdr.wav_fmt_channels); 1195 AUDIO_WAV_HOST2FILE_INT(&hdrp->sample_rate, &fhdr.wav_fmt_sample_rate); 1196 AUDIO_WAV_HOST2FILE_INT(&bytes_per_second, 1197 &fhdr.wav_fmt_bytes_per_second); 1198 AUDIO_WAV_HOST2FILE_SHORT(&bytes_per_sample, 1199 &fhdr.wav_fmt_bytes_per_sample); 1200 AUDIO_WAV_HOST2FILE_SHORT(&bits_per_sample, 1201 &fhdr.wav_fmt_bits_per_sample); 1202 1203 /* fill in the data chunk */ 1204 id = AUDIO_WAV_DATA_ID_LC; 1205 length = AUDIO_WAV_UNKNOWN_SIZE; 1206 AUDIO_WAV_HOST2FILE_INT(&id, &fhdr.wav_data_ID); 1207 AUDIO_WAV_HOST2FILE_INT(&length, &fhdr.wav_data_size); 1208 1209 *blen = sizeof (fhdr); 1210 1211 /* copy to the buffer */ 1212 (void) memcpy(buf, &fhdr, sizeof (fhdr)); 1213 1214 return (AUDIO_SUCCESS); 1215 1216 } /* audio_encode_wav() */ 1217 1218 /* 1219 * Utility routine used to convert 10 byte IEEE extended float into 1220 * a regular double. Raw data arrives in an unsigned char array. Because 1221 * this is for sample rate, which is always positive, we don't worry 1222 * about the sign. 1223 */ 1224 static double 1225 convert_from_ieee_extended(unsigned char *data) 1226 { 1227 double value = 0.0; 1228 unsigned long high_mantissa; 1229 unsigned long low_mantissa; 1230 int exponent; 1231 1232 /* first 2 bytes are the exponent */ 1233 exponent = ((data[0] & 0x7f) << 8) | data[1]; 1234 1235 high_mantissa = ((unsigned long)data[2] << 24) | 1236 ((unsigned long)data[3] << 16) | 1237 ((unsigned long)data[4] << 8) | 1238 (unsigned long)data[5]; 1239 low_mantissa = ((unsigned long)data[6] << 24) | 1240 ((unsigned long)data[7] << 16) | 1241 ((unsigned long)data[8] << 8) | 1242 (unsigned long)data[9]; 1243 1244 /* convert exponent and mantissas into a real double */ 1245 if (exponent == 0 && high_mantissa == 0 && low_mantissa == 0) { 1246 /* everything is 0, so we're done */ 1247 value = 0.0; 1248 } else { 1249 if (exponent == 0x7fff) { /* infinity */ 1250 value = MAXFLOAT; 1251 } else { 1252 /* convert exponent from being unsigned to signed */ 1253 exponent -= 0x3fff; 1254 1255 exponent -= 31; 1256 value = ldexp((double)high_mantissa, exponent); 1257 1258 exponent -= 32; 1259 value += ldexp((double)low_mantissa, exponent); 1260 } 1261 } 1262 1263 return (value); 1264 1265 } 1266 1267 /* 1268 * Utility routine to convert a double into 10 byte IEEE extended floating 1269 * point. The new number is placed into the unsigned char array. This is a 1270 * very brain dead convesion routine. It only supports integers, but then 1271 * that should be all we need for sample rate. 1272 */ 1273 static void 1274 convert_to_ieee_extended(double value, unsigned char *data) 1275 { 1276 double fmantissa; 1277 int exponent; 1278 int mantissa; 1279 1280 exponent = 16398; 1281 fmantissa = value; 1282 1283 while (fmantissa < 44000) { 1284 fmantissa *= 2; 1285 exponent--; 1286 } 1287 1288 mantissa = (int)fmantissa << 16; 1289 1290 data[0] = exponent >> 8; 1291 data[1] = exponent; 1292 data[2] = mantissa >> 24; 1293 data[3] = mantissa >> 16; 1294 data[4] = mantissa >> 8; 1295 data[5] = mantissa; 1296 data[6] = 0; 1297 data[7] = 0; 1298 data[8] = 0; 1299 data[9] = 0; 1300 1301 } 1302