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