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
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.
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]
23 * Copyright 1989-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Miscellaneous audio-related operations.
37 #include <libaudio_impl.h>
38 #include <audio_errno.h>
39 #include <audio_hdr.h>
42 * Convert a byte count into a floating-point time value, in seconds,
43 * using the encoding specified in the given audio header structure.
44 * Note that the byte count is not the same as the offset in an audio file,
45 * since the size of the audio file header is not taken into account.
48 audio_bytes_to_secs(Audio_hdr
*hp
, unsigned int cnt
)
51 ((double)(hp
->channels
* hp
->bytes_per_unit
* hp
->sample_rate
) /
52 (double)hp
->samples_per_unit
));
56 * Convert a floating-point time value, in seconds, to a byte count for
57 * the audio encoding in the given audio header. Note that the byte count
58 * is not the same as the offset in an audio file, since the size of the
59 * audio file header is not taken into account.
62 audio_secs_to_bytes(Audio_hdr
*hp
, double sec
)
66 offset
= (unsigned)(0.5 + (sec
*
67 ((double)(hp
->channels
* hp
->bytes_per_unit
* hp
->sample_rate
) /
68 (double)hp
->samples_per_unit
)));
70 /* Round down to the start of the nearest sample frame */
71 offset
-= (offset
% (hp
->bytes_per_unit
* hp
->channels
));
76 * Convert an ASCII time value (hh:mm:ss.dd) into floating-point seconds.
77 * Returns value if successfully converted. Otherwise, returns HUGE_VAL.
79 * XXX - currently allows the ridiculous construct: 5.3E3:-47.3E-1:17.3
82 audio_str_to_secs(char *str
)
87 val
= strtod(str
, &str2
); /* get first numeric field */
91 if (*str2
== ':') { /* that was hours (or minutes) */
94 val
+= strtod(str
, &str2
); /* another field is required */
99 if (*str2
== ':') { /* converted hours and minutes */
102 val
+= strtod(str
, &str2
); /* another field is required */
113 * Convert floating-point seconds into an ASCII time value (hh:mm:ss.dd).
115 * HUGE_VAL is converted to 0:00. 'Precision' specifies the maximum
116 * number of digits after the decimal point (-1 allows the max).
118 * Store the resulting string in the specified buffer (must be at least
119 * AUDIO_MAX_TIMEVAL bytes long). The string address is returned.
122 audio_secs_to_str(double sec
, char *str
, int precision
)
130 if (sec
== HUGE_VAL
) {
131 (void) strcpy(str
, "0:00");
135 /* Limit precision arg to reasonable value */
136 if ((precision
> 10) || (precision
< 0))
139 /* If negative, write a minus sign and get on with it. */
144 /* Round off within precision to avoid -.01 printing as -0:00 */
145 (void) sprintf(buf
, "%.*f", precision
, sec
);
146 (void) sscanf(buf
, "%lf", &sec
);
151 /* Round off within precision to avoid 1:59.999 printing as 1:60.00 */
154 (void) sprintf(buf
, "%.*f", precision
, x
);
155 (void) sscanf(buf
, "%lf", &x
);
159 /* Extract minutes */
160 ovflow
= ((unsigned)sec
) / 60;
161 sec
-= (double)(ovflow
* 60);
162 hours
= (ovflow
>= 60);
165 (void) sprintf(p
, "%d:", ovflow
/ 60);
169 /* convert minutes (use two digits if hours printed) */
170 (void) sprintf(p
, "%0*d:", (hours
? 2 : 1), ovflow
);
179 (void) sprintf(p
, "%.*f", precision
, sec
);
184 * Compare the encoding fields of two audio headers.
185 * Return 0 if they are the same, 1 if they are the same except for
186 * sample rate, else -1.
189 audio_cmp_hdr(Audio_hdr
*h1
, Audio_hdr
*h2
)
191 if ((h1
->encoding
!= h2
->encoding
) ||
192 (h1
->bytes_per_unit
!= h2
->bytes_per_unit
) ||
193 (h1
->channels
!= h2
->channels
) ||
194 (h1
->samples_per_unit
!= h2
->samples_per_unit
))
197 if (h1
->sample_rate
!= h2
->sample_rate
)
204 * Interpret the encoding information in the specified header
205 * and return an appropriate string in the supplied buffer.
206 * The buffer should contain at least AUDIO_MAX_ENCODE_INFO bytes.
207 * The returned string is something like:
208 * "stereo 16-bit linear PCM @ 44.1kHz"
210 * Returns AUDIO_ERR_BADHDR if the header cannot be interpreted.
213 audio_enc_to_str(Audio_hdr
*hdrp
, char *str
)
218 char cbuf
[AUDIO_MAX_ENCODE_INFO
];
219 char pbuf
[AUDIO_MAX_ENCODE_INFO
];
220 char sbuf
[AUDIO_MAX_ENCODE_INFO
];
225 switch (hdrp
->channels
) {
227 chan
= "(zero channels?)";
228 err
= AUDIO_ERR_BADHDR
;
231 chan
= "mono"; break;
233 chan
= "stereo"; break;
235 chan
= "quad"; break;
238 (void) sprintf(cbuf
, "%u-channel", hdrp
->channels
); break;
241 switch (hdrp
->encoding
) {
242 case AUDIO_ENCODING_ULAW
:
245 case AUDIO_ENCODING_ALAW
:
248 case AUDIO_ENCODING_LINEAR
:
251 case AUDIO_ENCODING_FLOAT
:
252 enc
= "floating-point";
254 if (hdrp
->samples_per_unit
!= 1)
257 (void) sprintf(pbuf
, "%u-bit", hdrp
->bytes_per_unit
* 8);
262 err
= AUDIO_ERR_ENCODING
;
263 enc
= "(unknown encoding?)";
264 if (hdrp
->samples_per_unit
!= 0) {
266 (void) sprintf(pbuf
, "%f-bit",
267 (double)(hdrp
->bytes_per_unit
* 8) /
268 (double)hdrp
->samples_per_unit
);
270 prec
= "(unknown precision?)";
271 err
= AUDIO_ERR_BADHDR
;
275 (void) sprintf(sbuf
, "%.3fkHz", ((double)hdrp
->sample_rate
/ 1000.));
276 (void) sprintf(str
, "%s %s %s @ %s", chan
, prec
, enc
, sbuf
);