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