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 uint16_t tmp_ushort; 905 906 /* the only encoding we support for .aiff is signed linear PCM */ 907 if (hdrp->encoding != AUDIO_ENCODING_LINEAR) { 908 return (AUDIO_ERR_ENCODING); 909 } 910 911 /* build the header chunk */ 912 tmp_uint = AUDIO_AIFF_HDR_CHUNK_ID; 913 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &hdr_chunk.aiff_hdr_ID); 914 /* needs to be fixed when closed */ 915 tmp_uint = AUDIO_AIFF_UNKNOWN_SIZE; 916 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &hdr_chunk.aiff_hdr_size); 917 tmp_uint = AUDIO_AIFF_HDR_FORM_AIFF; 918 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &hdr_chunk.aiff_hdr_data_type); 919 (void) memcpy(&buf[buf_size], &hdr_chunk, sizeof (hdr_chunk)); 920 buf_size += sizeof (hdr_chunk); 921 922 /* build the COMM chunk */ 923 tmp_uint = AUDIO_AIFF_COMM_ID; 924 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &comm_chunk.aiff_comm_ID); 925 tmp_uint = AUDIO_AIFF_COMM_SIZE; 926 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &comm_chunk.aiff_comm_size); 927 tmp_ushort = hdrp->channels; 928 AUDIO_AIFF_HOST2FILE_SHORT(&tmp_ushort, &comm_chunk.aiff_comm_channels); 929 /* needs to be fixed when closed */ 930 tmp_uint = AUDIO_AIFF_UNKNOWN_SIZE; 931 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &tmp_uint2); 932 AUDIO_AIFF_COMM_INT2FRAMES(comm_chunk.aiff_comm_frames, tmp_uint2); 933 tmp_ushort = hdrp->bytes_per_unit * 8; 934 AUDIO_AIFF_HOST2FILE_SHORT(&tmp_ushort, 935 &comm_chunk.aiff_comm_sample_size); 936 convert_to_ieee_extended((double)hdrp->sample_rate, 937 comm_chunk.aiff_comm_sample_rate); 938 (void) memcpy(&buf[buf_size], &comm_chunk, AUDIO_AIFF_COMM_CHUNK_SIZE); 939 buf_size += AUDIO_AIFF_COMM_CHUNK_SIZE; 940 941 /* build the SSND chunk */ 942 tmp_uint = AUDIO_AIFF_SSND_ID; 943 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &ssnd_chunk.aiff_ssnd_ID); 944 /* needs to be fixed when closed */ 945 tmp_uint = AUDIO_AIFF_UNKNOWN_SIZE; 946 AUDIO_AIFF_HOST2FILE_INT(&tmp_uint, &ssnd_chunk.aiff_ssnd_size); 947 ssnd_chunk.aiff_ssnd_offset = 0; 948 ssnd_chunk.aiff_ssnd_block_size = 0; 949 (void) memcpy(&buf[buf_size], &ssnd_chunk, sizeof (ssnd_chunk)); 950 buf_size += sizeof (ssnd_chunk); 951 952 *blen = buf_size; 953 954 return (AUDIO_SUCCESS); 955 956 } /* audio_encode_aiff() */ 957 958 /* 959 * Encode a .au file header from the supplied Audio_hdr structure and 960 * store in the supplied char* buffer. blen is the size of the buffer to 961 * store the header in. If 'infop' is not NULL, it is the address of a 962 * buffer containing 'info' data. 'ilen' specifies the size of this buffer. 963 * The entire file header will be zero-padded to a double-word boundary. 964 * 965 * NOTE: .au doesn't support unsigned 8-bit linear PCM. 966 */ 967 static int 968 audio_encode_au(Audio_hdr *hdrp, char *infop, unsigned int ilen, 969 unsigned char *buf, unsigned int *blen) 970 /* audio header */ 971 /* info buffer pointer */ 972 /* info buffer size */ 973 /* output buffer */ 974 /* output buffer size */ 975 { 976 au_filehdr_t fhdr; 977 int encoding; 978 int hdrsize; 979 int magic; 980 int offset; 981 982 /* 983 * Set the size of the real header (hdr size + info size). 984 * If no supplied info, make sure a minimum size is accounted for. 985 * Also, round the whole thing up to double-word alignment. 986 */ 987 if ((infop == NULL) || (ilen == 0)) { 988 infop = NULL; 989 ilen = 4; 990 } 991 hdrsize = sizeof (fhdr) + ilen; 992 offset = ROUND_DBL(hdrsize); 993 994 /* Check the data encoding. */ 995 switch (hdrp->encoding) { 996 case AUDIO_ENCODING_LINEAR8: 997 return (AUDIO_ERR_ENCODING); /* we don't support ulinear */ 998 case AUDIO_ENCODING_ULAW: 999 if (hdrp->samples_per_unit != 1) 1000 return (AUDIO_ERR_BADHDR); 1001 1002 switch (hdrp->bytes_per_unit) { 1003 case 1: 1004 encoding = AUDIO_AU_ENCODING_ULAW; 1005 break; 1006 default: 1007 return (AUDIO_ERR_BADHDR); 1008 } 1009 break; 1010 case AUDIO_ENCODING_ALAW: 1011 if (hdrp->samples_per_unit != 1) 1012 return (AUDIO_ERR_BADHDR); 1013 1014 switch (hdrp->bytes_per_unit) { 1015 case 1: 1016 encoding = AUDIO_AU_ENCODING_ALAW; 1017 break; 1018 default: 1019 return (AUDIO_ERR_BADHDR); 1020 } 1021 break; 1022 case AUDIO_ENCODING_LINEAR: 1023 if (hdrp->samples_per_unit != 1) 1024 return (AUDIO_ERR_BADHDR); 1025 1026 switch (hdrp->bytes_per_unit) { 1027 case 1: 1028 encoding = AUDIO_AU_ENCODING_LINEAR_8; 1029 break; 1030 case 2: 1031 encoding = AUDIO_AU_ENCODING_LINEAR_16; 1032 break; 1033 case 3: 1034 encoding = AUDIO_AU_ENCODING_LINEAR_24; 1035 break; 1036 case 4: 1037 encoding = AUDIO_AU_ENCODING_LINEAR_32; 1038 break; 1039 default: 1040 return (AUDIO_ERR_BADHDR); 1041 } 1042 break; 1043 case AUDIO_ENCODING_FLOAT: 1044 if (hdrp->samples_per_unit != 1) 1045 return (AUDIO_ERR_BADHDR); 1046 1047 switch (hdrp->bytes_per_unit) { 1048 case 4: 1049 encoding = AUDIO_AU_ENCODING_FLOAT; 1050 break; 1051 case 8: 1052 encoding = AUDIO_AU_ENCODING_DOUBLE; 1053 break; 1054 default: 1055 return (AUDIO_ERR_BADHDR); 1056 } 1057 break; 1058 case AUDIO_ENCODING_G721: 1059 if (hdrp->bytes_per_unit != 1) 1060 return (AUDIO_ERR_BADHDR); 1061 else if (hdrp->samples_per_unit != 2) 1062 return (AUDIO_ERR_BADHDR); 1063 else 1064 encoding = AUDIO_AU_ENCODING_ADPCM_G721; 1065 break; 1066 case AUDIO_ENCODING_G723: 1067 if (hdrp->samples_per_unit != 8) 1068 return (AUDIO_ERR_BADHDR); 1069 else if (hdrp->bytes_per_unit == 3) 1070 encoding = AUDIO_AU_ENCODING_ADPCM_G723_3; 1071 else if (hdrp->bytes_per_unit == 5) 1072 encoding = AUDIO_AU_ENCODING_ADPCM_G723_5; 1073 else 1074 return (AUDIO_ERR_BADHDR); 1075 break; 1076 default: 1077 return (AUDIO_ERR_BADHDR); 1078 } 1079 1080 /* copy the fhdr into the supplied buffer - make sure it'll fit */ 1081 if (*blen < offset) { 1082 /* XXX - is this apropriate? */ 1083 return (AUDIO_EOF); 1084 } 1085 1086 /* reset blen to actual size of hdr data */ 1087 *blen = (unsigned)offset; 1088 1089 magic = AUDIO_AU_FILE_MAGIC; /* set the magic number */ 1090 1091 /* Encode the audio header structure. */ 1092 AUDIO_AU_HOST2FILE(&magic, &fhdr.au_magic); 1093 AUDIO_AU_HOST2FILE(&offset, &fhdr.au_offset); 1094 AUDIO_AU_HOST2FILE(&hdrp->data_size, &fhdr.au_data_size); 1095 AUDIO_AU_HOST2FILE(&encoding, &fhdr.au_encoding); 1096 AUDIO_AU_HOST2FILE(&hdrp->sample_rate, &fhdr.au_sample_rate); 1097 AUDIO_AU_HOST2FILE(&hdrp->channels, &fhdr.au_channels); 1098 1099 /* Copy to the buffer */ 1100 (void) memcpy(buf, &fhdr, sizeof (fhdr)); 1101 1102 /* Copy the info data, if present */ 1103 if (infop != NULL) { 1104 (void) memcpy(&buf[sizeof (fhdr)], infop, (int)ilen); 1105 buf += ilen; 1106 } 1107 1108 if (offset > hdrsize) { 1109 (void) memset(&buf[hdrsize], '\0', (size_t)(offset - hdrsize)); 1110 } 1111 1112 /* buf now has the data, just return ... */ 1113 1114 return (AUDIO_SUCCESS); 1115 1116 } /* audio_encode_au() */ 1117 1118 /* 1119 * Encode a .wav file header from the supplied Audio_hdr structure and 1120 * store in the supplied char* buffer. blen is the size of the buffer to 1121 * store the header in. .wav doesn't support an information string like 1122 * .au does. 1123 * 1124 * NOTE: .wav only supports a few encoding methods. 1125 */ 1126 static int 1127 audio_encode_wav(Audio_hdr *hdrp, unsigned char *buf, unsigned int *blen) 1128 /* audio header */ 1129 /* output buffer */ 1130 /* output buffer size */ 1131 { 1132 wav_filehdr_t fhdr; 1133 int bytes_per_second; 1134 int bytes_per_sample; 1135 int bits_per_sample; 1136 int id; 1137 int length; 1138 int type; 1139 short encoding; 1140 1141 /* make sure we've got valid encoding and precision settings for .wav */ 1142 switch (hdrp->encoding) { 1143 case AUDIO_ENCODING_LINEAR8: 1144 if (hdrp->bytes_per_unit != 1) { 1145 return (AUDIO_ERR_ENCODING); 1146 } 1147 encoding = AUDIO_WAV_FMT_ENCODING_PCM; 1148 break; 1149 case AUDIO_ENCODING_ULAW: 1150 if (hdrp->bytes_per_unit != 1) { 1151 return (AUDIO_ERR_ENCODING); 1152 } 1153 encoding = AUDIO_WAV_FMT_ENCODING_MULAW; 1154 break; 1155 case AUDIO_ENCODING_ALAW: 1156 if (hdrp->bytes_per_unit != 1) { 1157 return (AUDIO_ERR_ENCODING); 1158 } 1159 encoding = AUDIO_WAV_FMT_ENCODING_ALAW; 1160 break; 1161 case AUDIO_ENCODING_LINEAR: 1162 if (hdrp->bytes_per_unit != 2) { 1163 return (AUDIO_ERR_ENCODING); 1164 } 1165 encoding = AUDIO_WAV_FMT_ENCODING_PCM; 1166 break; 1167 default: 1168 return (AUDIO_ERR_ENCODING); 1169 } 1170 1171 /* fill in the riff chunk */ 1172 id = AUDIO_WAV_RIFF_ID; 1173 length = AUDIO_WAV_UNKNOWN_SIZE; 1174 AUDIO_WAV_HOST2FILE_INT(&id, &fhdr.wav_riff_ID); 1175 AUDIO_WAV_HOST2FILE_INT(&length, &fhdr.wav_riff_size); 1176 1177 /* fill in the type chunk */ 1178 type = AUDIO_WAV_TYPE_ID; 1179 AUDIO_WAV_HOST2FILE_INT(&type, &fhdr.wav_type_ID); 1180 1181 1182 /* fill in the format chunk */ 1183 id = AUDIO_WAV_FORMAT_ID; 1184 length = AUDIO_WAV_FORMAT_SIZE; 1185 bytes_per_second = hdrp->sample_rate * hdrp->channels * 1186 hdrp->bytes_per_unit; 1187 bytes_per_sample = hdrp->channels * hdrp->bytes_per_unit; 1188 bits_per_sample = hdrp->bytes_per_unit * 8; 1189 1190 AUDIO_WAV_HOST2FILE_INT(&id, &fhdr.wav_fmt_ID); 1191 AUDIO_WAV_HOST2FILE_INT(&length, &fhdr.wav_fmt_size); 1192 AUDIO_WAV_HOST2FILE_SHORT(&encoding, &fhdr.wav_fmt_encoding); 1193 AUDIO_WAV_HOST2FILE_SHORT(&hdrp->channels, &fhdr.wav_fmt_channels); 1194 AUDIO_WAV_HOST2FILE_INT(&hdrp->sample_rate, &fhdr.wav_fmt_sample_rate); 1195 AUDIO_WAV_HOST2FILE_INT(&bytes_per_second, 1196 &fhdr.wav_fmt_bytes_per_second); 1197 AUDIO_WAV_HOST2FILE_SHORT(&bytes_per_sample, 1198 &fhdr.wav_fmt_bytes_per_sample); 1199 AUDIO_WAV_HOST2FILE_SHORT(&bits_per_sample, 1200 &fhdr.wav_fmt_bits_per_sample); 1201 1202 /* fill in the data chunk */ 1203 id = AUDIO_WAV_DATA_ID_LC; 1204 length = AUDIO_WAV_UNKNOWN_SIZE; 1205 AUDIO_WAV_HOST2FILE_INT(&id, &fhdr.wav_data_ID); 1206 AUDIO_WAV_HOST2FILE_INT(&length, &fhdr.wav_data_size); 1207 1208 *blen = sizeof (fhdr); 1209 1210 /* copy to the buffer */ 1211 (void) memcpy(buf, &fhdr, sizeof (fhdr)); 1212 1213 return (AUDIO_SUCCESS); 1214 1215 } /* audio_encode_wav() */ 1216 1217 /* 1218 * Utility routine used to convert 10 byte IEEE extended float into 1219 * a regular double. Raw data arrives in an unsigned char array. Because 1220 * this is for sample rate, which is always positive, we don't worry 1221 * about the sign. 1222 */ 1223 static double 1224 convert_from_ieee_extended(unsigned char *data) 1225 { 1226 double value = 0.0; 1227 unsigned long high_mantissa; 1228 unsigned long low_mantissa; 1229 int exponent; 1230 1231 /* first 2 bytes are the exponent */ 1232 exponent = ((data[0] & 0x7f) << 8) | data[1]; 1233 1234 high_mantissa = ((unsigned long)data[2] << 24) | 1235 ((unsigned long)data[3] << 16) | 1236 ((unsigned long)data[4] << 8) | 1237 (unsigned long)data[5]; 1238 low_mantissa = ((unsigned long)data[6] << 24) | 1239 ((unsigned long)data[7] << 16) | 1240 ((unsigned long)data[8] << 8) | 1241 (unsigned long)data[9]; 1242 1243 /* convert exponent and mantissas into a real double */ 1244 if (exponent == 0 && high_mantissa == 0 && low_mantissa == 0) { 1245 /* everything is 0, so we're done */ 1246 value = 0.0; 1247 } else { 1248 if (exponent == 0x7fff) { /* infinity */ 1249 value = MAXFLOAT; 1250 } else { 1251 /* convert exponent from being unsigned to signed */ 1252 exponent -= 0x3fff; 1253 1254 exponent -= 31; 1255 value = ldexp((double)high_mantissa, exponent); 1256 1257 exponent -= 32; 1258 value += ldexp((double)low_mantissa, exponent); 1259 } 1260 } 1261 1262 return (value); 1263 1264 } 1265 1266 /* 1267 * Utility routine to convert a double into 10 byte IEEE extended floating 1268 * point. The new number is placed into the unsigned char array. This is a 1269 * very brain dead convesion routine. It only supports integers, but then 1270 * that should be all we need for sample rate. 1271 */ 1272 static void 1273 convert_to_ieee_extended(double value, unsigned char *data) 1274 { 1275 double fmantissa; 1276 int exponent; 1277 int mantissa; 1278 1279 exponent = 16398; 1280 fmantissa = value; 1281 1282 while (fmantissa < 44000) { 1283 fmantissa *= 2; 1284 exponent--; 1285 } 1286 1287 mantissa = (int)fmantissa << 16; 1288 1289 data[0] = exponent >> 8; 1290 data[1] = exponent; 1291 data[2] = mantissa >> 24; 1292 data[3] = mantissa >> 16; 1293 data[4] = mantissa >> 8; 1294 data[5] = mantissa; 1295 data[6] = 0; 1296 data[7] = 0; 1297 data[8] = 0; 1298 data[9] = 0; 1299 1300 } 1301