1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1992-2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <AudioHdr.h> 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate // class AudioHdr basic methods 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate // This routine uses the byteorder network utilities to tell whether the 34*7c478bd9Sstevel@tonic-gate // current process uses network byte order or not. 35*7c478bd9Sstevel@tonic-gate AudioEndian AudioHdr::localByteOrder() const 36*7c478bd9Sstevel@tonic-gate { 37*7c478bd9Sstevel@tonic-gate short sTestHost; 38*7c478bd9Sstevel@tonic-gate short sTestNetwork; 39*7c478bd9Sstevel@tonic-gate static AudioEndian ae = UNDEFINED_ENDIAN; 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate if (ae == UNDEFINED_ENDIAN) { 42*7c478bd9Sstevel@tonic-gate sTestHost = MAXSHORT; 43*7c478bd9Sstevel@tonic-gate sTestNetwork = htons(sTestHost); 44*7c478bd9Sstevel@tonic-gate if (sTestNetwork != sTestHost) { 45*7c478bd9Sstevel@tonic-gate ae = LITTLE_ENDIAN; 46*7c478bd9Sstevel@tonic-gate } else { 47*7c478bd9Sstevel@tonic-gate ae = BIG_ENDIAN; 48*7c478bd9Sstevel@tonic-gate } 49*7c478bd9Sstevel@tonic-gate } 50*7c478bd9Sstevel@tonic-gate return (ae); 51*7c478bd9Sstevel@tonic-gate } 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate // Clear a header structure 54*7c478bd9Sstevel@tonic-gate void AudioHdr:: 55*7c478bd9Sstevel@tonic-gate Clear() 56*7c478bd9Sstevel@tonic-gate { 57*7c478bd9Sstevel@tonic-gate sample_rate = 0; 58*7c478bd9Sstevel@tonic-gate samples_per_unit = 0; 59*7c478bd9Sstevel@tonic-gate bytes_per_unit = 0; 60*7c478bd9Sstevel@tonic-gate channels = 0; 61*7c478bd9Sstevel@tonic-gate encoding = NONE; 62*7c478bd9Sstevel@tonic-gate } 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate // Return error code (TRUE) if header is inconsistent or unrecognizable 65*7c478bd9Sstevel@tonic-gate // XXX - how do we support extensions? 66*7c478bd9Sstevel@tonic-gate AudioError AudioHdr:: 67*7c478bd9Sstevel@tonic-gate Validate() const 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate // Check for uninitialized fields 70*7c478bd9Sstevel@tonic-gate if ((bytes_per_unit < 1) || (samples_per_unit < 1) || 71*7c478bd9Sstevel@tonic-gate (sample_rate < 1) || (channels < 1)) 72*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_BADHDR); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate switch (encoding) { 75*7c478bd9Sstevel@tonic-gate case NONE: 76*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_BADHDR); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate case LINEAR: 79*7c478bd9Sstevel@tonic-gate if (bytes_per_unit > 4) 80*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_PRECISION); 81*7c478bd9Sstevel@tonic-gate if (samples_per_unit != 1) 82*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_HDRINVAL); 83*7c478bd9Sstevel@tonic-gate break; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate case FLOAT: 86*7c478bd9Sstevel@tonic-gate if ((bytes_per_unit != 4) && (bytes_per_unit != 8)) 87*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_PRECISION); 88*7c478bd9Sstevel@tonic-gate if (samples_per_unit != 1) 89*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_HDRINVAL); 90*7c478bd9Sstevel@tonic-gate break; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate case ULAW: 93*7c478bd9Sstevel@tonic-gate case ALAW: 94*7c478bd9Sstevel@tonic-gate case G722: 95*7c478bd9Sstevel@tonic-gate if (bytes_per_unit != 1) 96*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_PRECISION); 97*7c478bd9Sstevel@tonic-gate if (samples_per_unit != 1) 98*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_HDRINVAL); 99*7c478bd9Sstevel@tonic-gate break; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate case G721: 102*7c478bd9Sstevel@tonic-gate case DVI: 103*7c478bd9Sstevel@tonic-gate // G.721 is a 4-bit encoding 104*7c478bd9Sstevel@tonic-gate if ((bytes_per_unit != 1) || (samples_per_unit != 2)) 105*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_PRECISION); 106*7c478bd9Sstevel@tonic-gate break; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate case G723: 109*7c478bd9Sstevel@tonic-gate // G.723 has 3-bit and 5-bit flavors 110*7c478bd9Sstevel@tonic-gate // 5-bit is currently unsupported 111*7c478bd9Sstevel@tonic-gate if ((bytes_per_unit != 3) || (samples_per_unit != 8)) 112*7c478bd9Sstevel@tonic-gate return (AUDIO_ERR_PRECISION); 113*7c478bd9Sstevel@tonic-gate break; 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate // Convert a byte count into a floating-point time value, in seconds, 120*7c478bd9Sstevel@tonic-gate // using the encoding specified in the audio header. 121*7c478bd9Sstevel@tonic-gate Double AudioHdr:: 122*7c478bd9Sstevel@tonic-gate Bytes_to_Time( 123*7c478bd9Sstevel@tonic-gate off_t cnt) const // byte count 124*7c478bd9Sstevel@tonic-gate { 125*7c478bd9Sstevel@tonic-gate if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS)) 126*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_TIME); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate // round off to nearest sample frame! 129*7c478bd9Sstevel@tonic-gate cnt -= (cnt % (bytes_per_unit * channels)); 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate return (Double) ((double)cnt / 132*7c478bd9Sstevel@tonic-gate ((double)(channels * bytes_per_unit * sample_rate) / 133*7c478bd9Sstevel@tonic-gate (double)samples_per_unit)); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate // Convert a floating-point time value, in seconds, to a byte count for 137*7c478bd9Sstevel@tonic-gate // the audio encoding in the audio header. Make sure that the byte count 138*7c478bd9Sstevel@tonic-gate // or offset does not span a sample frame. 139*7c478bd9Sstevel@tonic-gate off_t AudioHdr:: 140*7c478bd9Sstevel@tonic-gate Time_to_Bytes( 141*7c478bd9Sstevel@tonic-gate Double sec) const // time, in seconds 142*7c478bd9Sstevel@tonic-gate { 143*7c478bd9Sstevel@tonic-gate off_t offset; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate if (Undefined(sec) || (Validate() != AUDIO_SUCCESS)) 146*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_SIZE); 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate offset = (off_t)(0.5 + (sec * 149*7c478bd9Sstevel@tonic-gate ((double)(channels * bytes_per_unit * sample_rate) / 150*7c478bd9Sstevel@tonic-gate (double)samples_per_unit))); 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate // Round down to the start of the nearest sample frame 153*7c478bd9Sstevel@tonic-gate offset -= (offset % (bytes_per_unit * channels)); 154*7c478bd9Sstevel@tonic-gate return (offset); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate // Round a byte count down to a sample frame boundary. 158*7c478bd9Sstevel@tonic-gate off_t AudioHdr:: 159*7c478bd9Sstevel@tonic-gate Bytes_to_Bytes( 160*7c478bd9Sstevel@tonic-gate off_t& cnt) const 161*7c478bd9Sstevel@tonic-gate { 162*7c478bd9Sstevel@tonic-gate if (Validate() != AUDIO_SUCCESS) 163*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_SIZE); 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate // Round down to the start of the nearest sample frame 166*7c478bd9Sstevel@tonic-gate cnt -= (cnt % (bytes_per_unit * channels)); 167*7c478bd9Sstevel@tonic-gate return (cnt); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate // Round a byte count down to a sample frame boundary. 171*7c478bd9Sstevel@tonic-gate size_t AudioHdr:: 172*7c478bd9Sstevel@tonic-gate Bytes_to_Bytes( 173*7c478bd9Sstevel@tonic-gate size_t& cnt) const 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate if (Validate() != AUDIO_SUCCESS) 176*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_SIZE); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate // Round down to the start of the nearest sample frame 179*7c478bd9Sstevel@tonic-gate cnt -= (cnt % (bytes_per_unit * channels)); 180*7c478bd9Sstevel@tonic-gate return (cnt); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate // Convert a count of sample frames into a floating-point time value, 184*7c478bd9Sstevel@tonic-gate // in seconds, using the encoding specified in the audio header. 185*7c478bd9Sstevel@tonic-gate Double AudioHdr:: 186*7c478bd9Sstevel@tonic-gate Samples_to_Time( 187*7c478bd9Sstevel@tonic-gate unsigned long cnt) const // sample frame count 188*7c478bd9Sstevel@tonic-gate { 189*7c478bd9Sstevel@tonic-gate if ((cnt == AUDIO_UNKNOWN_SIZE) || (Validate() != AUDIO_SUCCESS)) 190*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_TIME); 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate return ((Double)(((double)cnt * (double)samples_per_unit) / 193*7c478bd9Sstevel@tonic-gate (double)sample_rate)); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate // Convert a floating-point time value, in seconds, to a count of sample frames 197*7c478bd9Sstevel@tonic-gate // for the audio encoding in the audio header. 198*7c478bd9Sstevel@tonic-gate unsigned long AudioHdr:: 199*7c478bd9Sstevel@tonic-gate Time_to_Samples( 200*7c478bd9Sstevel@tonic-gate Double sec) const // time, in seconds 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate if (Undefined(sec) || (Validate() != AUDIO_SUCCESS)) 203*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_SIZE); 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate // Round down to sample frame boundary 206*7c478bd9Sstevel@tonic-gate return ((unsigned long) (AUDIO_MINFLOAT + 207*7c478bd9Sstevel@tonic-gate (((double)sec * (double)sample_rate) / (double)samples_per_unit))); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate // Return the number of bytes in a sample frame for the audio encoding. 211*7c478bd9Sstevel@tonic-gate unsigned int AudioHdr:: 212*7c478bd9Sstevel@tonic-gate FrameLength() const 213*7c478bd9Sstevel@tonic-gate { 214*7c478bd9Sstevel@tonic-gate return (bytes_per_unit * channels); 215*7c478bd9Sstevel@tonic-gate } 216