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 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
35 #define irint(d) ((int)(d))
37 // Convert a string to lowercase and return an allocated copy of it.
38 // XXX - There really should be a string-insensitive 8-bit compare routine.
43 unsigned char *oldstr
;
44 unsigned char *newstr
;
47 oldstr
= (unsigned char *) str
;
48 newstr
= new unsigned char [strlen(str
) + 1];
50 if (isupper(oldstr
[i
]))
51 newstr
[i
] = tolower(oldstr
[i
]);
53 newstr
[i
] = oldstr
[i
];
54 if (oldstr
[i
] == '\0')
57 return ((char *)newstr
);
62 // class AudioHdr parsing methods
65 // Return a string containing the sample rate
75 ratek
= sample_rate
/ 1000;
76 rateh
= sample_rate
% 1000;
78 (void) sprintf(str
, "%dkHz", ratek
);
80 // scale down to print minimum digits after the decimal point
82 if ((rateh
% 10) == 0) {
86 if ((rateh
% 10) == 0) {
90 (void) sprintf(str
, "%d.%0*dkHz", ratek
, prec
, rateh
);
95 // Return a string containing the number of channels
104 (void) sprintf(str
, "mono");
107 (void) sprintf(str
, "stereo");
110 (void) sprintf(str
, "quad");
113 (void) sprintf(str
, "%d-channel", channels
);
119 // Return a string containing the encoding
121 EncodingString() const
128 if ((samples_per_unit
== 0) || (bytes_per_unit
== 0) ||
129 (encoding
== NONE
)) {
130 (void) sprintf(str
, "???");
132 // First encode precision
133 iprec
= (bytes_per_unit
* 8) / samples_per_unit
;
134 prec
= ((Double
)bytes_per_unit
* 8.) / (Double
)samples_per_unit
;
135 if (prec
== (Double
) iprec
) {
136 (void) sprintf(str
, "%d-bit ", iprec
);
138 (void) sprintf(str
, "%.1f-bit ", double(prec
));
141 // Then encode format
144 // XXX - See bug 1121000
145 // XXX - (void) strcat(str, "ยต-law");
146 (void) strcat(str
, "u-law");
149 (void) strcat(str
, "A-law");
152 (void) strcat(str
, "linear");
155 (void) strcat(str
, "float");
158 (void) strcat(str
, "G.721 ADPCM");
161 (void) strcat(str
, "G.722 ADPCM");
164 (void) strcat(str
, "G.723 ADPCM");
167 (void) strcat(str
, "DVI ADPCM");
170 (void) strcat(str
, "???");
177 // Return a string containing the entire audio encoding
186 str
= new char[4 * 32];
188 enc
= EncodingString();
190 chan
= ChannelString();
191 (void) sprintf(str
, "%s, %s, %s", enc
, rate
, chan
);
198 // Parse a string containing the sample rate
199 AudioError
AudioHdr::
203 static char *lib_khz
= NULL
;
204 static char *lib_hz
= NULL
;
212 return (AUDIO_ERR_BADARG
);
214 // Init i18n string translations
215 if (lib_khz
== NULL
) {
216 lib_khz
= to_lowercase(_MGET_("khz"));
217 lib_hz
= to_lowercase(_MGET_("hz"));
220 // Scan for a number followed by an optional khz designator
221 switch (sscanf(str
, " %lf %15s", &r
, khzbuf
)) {
223 // Process 'khz', if present, and fall through
224 khz
= to_lowercase(khzbuf
);
225 if ((strcmp(khz
, "khz") == 0) ||
226 (strcmp(khz
, "khertz") == 0) ||
227 (strcmp(khz
, "kilohertz") == 0) ||
228 (strcmp(khz
, "k") == 0) ||
229 (strcoll(khz
, lib_khz
) == 0)) {
231 } else if ((strcmp(khz
, "hz") != 0) &&
232 (strcmp(khz
, "hertz") != 0) &&
233 (strcoll(khz
, lib_hz
) != 0)) {
235 return (AUDIO_ERR_BADARG
);
242 return (AUDIO_ERR_BADARG
);
244 // Check for reasonable bounds
245 if ((rate
<= 0) || (rate
> 500000)) {
246 return (AUDIO_ERR_BADARG
);
248 sample_rate
= (unsigned int) rate
;
249 return (AUDIO_SUCCESS
);
252 // Parse a string containing the number of channels
253 AudioError
AudioHdr::
257 static char *lib_chan
= NULL
;
258 static char *lib_mono
= NULL
;
259 static char *lib_stereo
= NULL
;
265 // Init i18n string translations
266 if (lib_chan
== NULL
) {
267 lib_chan
= to_lowercase(_MGET_("channel"));
268 lib_mono
= to_lowercase(_MGET_("mono"));
269 lib_stereo
= to_lowercase(_MGET_("stereo"));
272 // Parse a number, followed by optional "-channel"
273 switch (sscanf(str
, " %d %15s", &chan
, cstrbuf
)) {
275 cstr
= to_lowercase(cstrbuf
);
276 if ((strcmp(cstr
, "-channel") != 0) &&
277 (strcmp(cstr
, "-chan") != 0) &&
278 (strcoll(cstr
, lib_chan
) != 0)) {
280 return (AUDIO_ERR_BADARG
);
286 // If no number, look for reasonable keywords
287 if (sscanf(str
, " %15s %1s", cstrbuf
, xtra
) != 1) {
288 return (AUDIO_ERR_BADARG
);
290 cstr
= to_lowercase(cstrbuf
);
291 if ((strcmp(cstr
, "mono") == 0) ||
292 (strcmp(cstr
, "monaural") == 0) ||
293 (strcoll(cstr
, lib_mono
) == 0)) {
295 } else if ((strcmp(cstr
, "stereo") == 0) ||
296 (strcmp(cstr
, "dual") == 0) ||
297 (strcoll(cstr
, lib_stereo
) == 0)) {
299 } else if ((strcmp(cstr
, "quad") == 0) ||
300 (strcmp(cstr
, "quadrophonic") == 0)) {
304 return (AUDIO_ERR_BADARG
);
308 if ((chan
<= 0) || (chan
> 256)) {
309 return (AUDIO_ERR_BADARG
);
311 channels
= (unsigned int) chan
;
312 return (AUDIO_SUCCESS
);
315 // Parse a string containing the audio encoding
316 AudioError
AudioHdr::
320 static char *lib_bit
= NULL
;
321 static char *lib_ulaw
= NULL
;
322 static char *lib_Alaw
= NULL
;
323 static char *lib_linear
= NULL
;
335 // Init i18n string translations
336 if (lib_bit
== NULL
) {
337 lib_bit
= to_lowercase(_MGET_("bit"));
338 lib_ulaw
= to_lowercase(_MGET_("u-law"));
339 lib_Alaw
= to_lowercase(_MGET_("A-law"));
340 lib_linear
= to_lowercase(_MGET_("linear8"));
341 lib_linear
= to_lowercase(_MGET_("linear"));
344 // first copy and remove leading spaces
345 (void) strncpy(buf
, str
, BUFSIZ
);
346 for (cp
= buf
; *cp
== ' '; cp
++)
349 // Delimit the precision. If there is one, parse it.
354 i
= sscanf(cp
, " %lf %15s", &prec
, xtrabuf
);
356 return (AUDIO_ERR_BADARG
);
359 // convert to lowercase and skip leading "-", if any
360 xtra
= to_lowercase(xtrabuf
);
361 xp
= (xtra
[0] == '-') ? &xtra
[1] : &xtra
[0];
363 if ((strcmp(xp
, "bit") != 0) &&
364 (strcoll(xp
, lib_bit
) != 0)) {
366 return (AUDIO_ERR_BADARG
);
370 if ((prec
<= 0.) || (prec
> 512.)) {
371 return (AUDIO_ERR_BADARG
);
374 // Don't be fooled by "8 bit"
375 i
= sscanf(p
, " %15s", xtrabuf
);
377 // convert to lowercase and skip leading "-", if any
378 xtra
= to_lowercase(xtrabuf
);
379 xp
= (xtra
[0] == '-') ? &xtra
[1] : &xtra
[0];
380 if ((strcmp(xp
, "bit") == 0) ||
381 (strcoll(xp
, lib_bit
) == 0)) {
386 p
+= strlen(xtrabuf
);
394 i
= sscanf(p
, " %31s %31s", estrbuf
, xtrabuf
);
396 // If "adpcm" appended with a space, concatenate it
398 xtra
= to_lowercase(xtrabuf
);
399 if (strcmp(xtra
, "adpcm") == 0) {
400 (void) strcat(estrbuf
, xtra
);
406 estr
= to_lowercase(estrbuf
);
407 if ((strcmp(estr
, "ulaw") == 0) ||
408 (strcmp(estr
, "u-law") == 0) ||
409 (strcmp(estr
, "ยตlaw") == 0) ||
410 (strcmp(estr
, "ยต-law") == 0) ||
411 (strcmp(estr
, "mulaw") == 0) ||
412 (strcmp(estr
, "mu-law") == 0) ||
413 (strcoll(estr
, lib_ulaw
) == 0)) {
414 if ((prec
!= 0.) && (prec
!= 8.))
415 return (AUDIO_ERR_BADARG
);
417 samples_per_unit
= 1;
419 } else if ((strcmp(estr
, "alaw") == 0) ||
420 (strcmp(estr
, "a-law") == 0) ||
421 (strcoll(estr
, lib_Alaw
) == 0)) {
422 if ((prec
!= 0.) && (prec
!= 8.))
423 return (AUDIO_ERR_BADARG
);
425 samples_per_unit
= 1;
428 } else if ((strcmp(estr
, "linear") == 0) ||
429 (strcmp(estr
, "lin") == 0) ||
430 (strcmp(estr
, "pcm") == 0) ||
431 (strcoll(estr
, lib_linear
) == 0)) {
432 if ((prec
!= 0.) && (prec
!= 8.) && (prec
!= 16.) &&
433 (prec
!= 24.) && (prec
!= 32.))
434 return (AUDIO_ERR_BADARG
);
438 samples_per_unit
= 1;
439 bytes_per_unit
= irint(prec
/ 8.);
441 } else if ((strcmp(estr
, "linear8") == 0) ||
442 (strcmp(estr
, "lin8") == 0) ||
443 (strcmp(estr
, "pcm8") == 0)) {
444 if ((prec
!= 0.) && (prec
!= 8.))
445 return (AUDIO_ERR_BADARG
);
448 samples_per_unit
= 1;
449 bytes_per_unit
= irint(prec
/ 8.);
451 } else if ((strcmp(estr
, "linear16") == 0) ||
452 (strcmp(estr
, "lin16") == 0) ||
453 (strcmp(estr
, "pcm16") == 0)) {
454 if ((prec
!= 0.) && (prec
!= 16.))
455 return (AUDIO_ERR_BADARG
);
458 samples_per_unit
= 1;
459 bytes_per_unit
= irint(prec
/ 8.);
461 } else if ((strcmp(estr
, "linear24") == 0) ||
462 (strcmp(estr
, "lin24") == 0) ||
463 (strcmp(estr
, "pcm24") == 0)) {
464 if ((prec
!= 0.) && (prec
!= 24.))
465 return (AUDIO_ERR_BADARG
);
468 samples_per_unit
= 1;
469 bytes_per_unit
= irint(prec
/ 8.);
471 } else if ((strcmp(estr
, "linear32") == 0) ||
472 (strcmp(estr
, "lin32") == 0) ||
473 (strcmp(estr
, "pcm32") == 0)) {
474 if ((prec
!= 0.) && (prec
!= 32.))
475 return (AUDIO_ERR_BADARG
);
478 samples_per_unit
= 1;
479 bytes_per_unit
= irint(prec
/ 8.);
481 } else if ((strcmp(estr
, "float") == 0) ||
482 (strcmp(estr
, "floatingpoint") == 0) ||
483 (strcmp(estr
, "floating-point") == 0)) {
484 if ((prec
!= 0.) && (prec
!= 32.) && (prec
!= 64.))
485 return (AUDIO_ERR_BADARG
);
489 samples_per_unit
= 1;
490 bytes_per_unit
= irint(prec
/ 8.);
492 } else if ((strcmp(estr
, "float32") == 0) ||
493 (strcmp(estr
, "floatingpoint32") == 0) ||
494 (strcmp(estr
, "floating-point32") == 0)) {
495 if ((prec
!= 0.) && (prec
!= 32.))
496 return (AUDIO_ERR_BADARG
);
499 samples_per_unit
= 1;
500 bytes_per_unit
= irint(prec
/ 8.);
502 } else if ((strcmp(estr
, "float64") == 0) ||
503 (strcmp(estr
, "double") == 0) ||
504 (strcmp(estr
, "floatingpoint64") == 0) ||
505 (strcmp(estr
, "floating-point64") == 0)) {
506 if ((prec
!= 0.) && (prec
!= 64.))
507 return (AUDIO_ERR_BADARG
);
510 samples_per_unit
= 1;
511 bytes_per_unit
= irint(prec
/ 8.);
513 } else if ((strcmp(estr
, "g.721") == 0) ||
514 (strcmp(estr
, "g721") == 0) ||
515 (strcmp(estr
, "g.721adpcm") == 0) ||
516 (strcmp(estr
, "g721adpcm") == 0)) {
517 if ((prec
!= 0.) && (prec
!= 4.))
518 return (AUDIO_ERR_BADARG
);
520 samples_per_unit
= 2;
523 } else if ((strcmp(estr
, "g.722") == 0) ||
524 (strcmp(estr
, "g722") == 0) ||
525 (strcmp(estr
, "g.722adpcm") == 0) ||
526 (strcmp(estr
, "g722adpcm") == 0)) {
527 if ((prec
!= 0.) && (prec
!= 8.))
528 return (AUDIO_ERR_BADARG
);
530 samples_per_unit
= 1;
533 } else if ((strcmp(estr
, "g.723") == 0) ||
534 (strcmp(estr
, "g723") == 0) ||
535 (strcmp(estr
, "g.723adpcm") == 0) ||
536 (strcmp(estr
, "g723adpcm") == 0)) {
537 if ((prec
!= 0.) && (prec
!= 3.) && (prec
!= 5.))
538 return (AUDIO_ERR_BADARG
);
542 samples_per_unit
= 8;
543 bytes_per_unit
= irint(prec
);
545 } else if ((strcmp(estr
, "g.723-3") == 0) ||
546 (strcmp(estr
, "g.723_3") == 0) ||
547 (strcmp(estr
, "g.723.3") == 0) ||
548 (strcmp(estr
, "g723-3") == 0) ||
549 (strcmp(estr
, "g723_3") == 0) ||
550 (strcmp(estr
, "g723.3") == 0)) {
551 if ((prec
!= 0.) && (prec
!= 3.))
552 return (AUDIO_ERR_BADARG
);
555 samples_per_unit
= 8;
556 bytes_per_unit
= irint(prec
);
558 } else if ((strcmp(estr
, "g.723-5") == 0) ||
559 (strcmp(estr
, "g.723_5") == 0) ||
560 (strcmp(estr
, "g.723.5") == 0) ||
561 (strcmp(estr
, "g723-5") == 0) ||
562 (strcmp(estr
, "g723_5") == 0) ||
563 (strcmp(estr
, "g723.5") == 0)) {
564 if ((prec
!= 0.) && (prec
!= 5.))
565 return (AUDIO_ERR_BADARG
);
568 samples_per_unit
= 8;
569 bytes_per_unit
= irint(prec
);
571 } else if ((strcmp(estr
, "dvi") == 0) ||
572 (strcmp(estr
, "dviadpcm") == 0)) {
573 if ((prec
!= 0.) && (prec
!= 4.))
574 return (AUDIO_ERR_BADARG
);
576 samples_per_unit
= 2;
581 return (AUDIO_ERR_BADARG
);
585 return (AUDIO_ERR_BADARG
);
587 return (AUDIO_SUCCESS
);
590 // Parse a string containing the comma-separated audio encoding
591 // Format is: "enc, chan, rate"
592 // XXX - some countries use comma instead of decimal point
593 // so there may be a problem with "44,1 khz"
594 AudioError
AudioHdr::
604 pstr
= new char[strlen(str
) + 1];
605 (void) strcpy(pstr
, str
);
608 // Delimit and parse the precision string
609 p
= strchr(ptr
, ',');
611 p
= strchr(ptr
, ' ');
613 err
= AUDIO_ERR_BADARG
;
617 err
= newhdr
.EncodingParse(ptr
);
619 // Delimit and parse the sample rate string
622 p
= strchr(ptr
, ',');
624 p
= strchr(ptr
, ' ');
626 err
= AUDIO_ERR_BADARG
;
630 err
= newhdr
.RateParse(ptr
);
633 // Finally, parse the channels string
635 err
= newhdr
.ChannelParse(p
);
638 // Validate the resulting header
640 err
= newhdr
.Validate();