10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*1009Smathue * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <string.h> 310Sstevel@tonic-gate #include <ctype.h> 320Sstevel@tonic-gate #include <math.h> 330Sstevel@tonic-gate #include <AudioHdr.h> 340Sstevel@tonic-gate 35*1009Smathue #define irint(d) ((int)(d)) 360Sstevel@tonic-gate 370Sstevel@tonic-gate // Convert a string to lowercase and return an allocated copy of it. 380Sstevel@tonic-gate // XXX - There really should be a string-insensitive 8-bit compare routine. 390Sstevel@tonic-gate static char * 400Sstevel@tonic-gate to_lowercase( 410Sstevel@tonic-gate char *str) 420Sstevel@tonic-gate { 430Sstevel@tonic-gate unsigned char *oldstr; 440Sstevel@tonic-gate unsigned char *newstr; 450Sstevel@tonic-gate int i; 460Sstevel@tonic-gate 470Sstevel@tonic-gate oldstr = (unsigned char *) str; 480Sstevel@tonic-gate newstr = new unsigned char [strlen(str) + 1]; 490Sstevel@tonic-gate for (i = 0; ; i++) { 500Sstevel@tonic-gate if (isupper(oldstr[i])) 510Sstevel@tonic-gate newstr[i] = tolower(oldstr[i]); 520Sstevel@tonic-gate else 530Sstevel@tonic-gate newstr[i] = oldstr[i]; 540Sstevel@tonic-gate if (oldstr[i] == '\0') 550Sstevel@tonic-gate break; 560Sstevel@tonic-gate } 570Sstevel@tonic-gate return ((char *)newstr); 580Sstevel@tonic-gate } 590Sstevel@tonic-gate 600Sstevel@tonic-gate 610Sstevel@tonic-gate 620Sstevel@tonic-gate // class AudioHdr parsing methods 630Sstevel@tonic-gate 640Sstevel@tonic-gate 650Sstevel@tonic-gate // Return a string containing the sample rate 660Sstevel@tonic-gate char *AudioHdr:: 670Sstevel@tonic-gate RateString() const 680Sstevel@tonic-gate { 690Sstevel@tonic-gate char *str; 700Sstevel@tonic-gate int ratek; 710Sstevel@tonic-gate int rateh; 720Sstevel@tonic-gate int prec; 730Sstevel@tonic-gate 740Sstevel@tonic-gate str = new char[32]; 750Sstevel@tonic-gate ratek = sample_rate / 1000; 760Sstevel@tonic-gate rateh = sample_rate % 1000; 770Sstevel@tonic-gate if (rateh == 0) { 780Sstevel@tonic-gate (void) sprintf(str, "%dkHz", ratek); 790Sstevel@tonic-gate } else { 800Sstevel@tonic-gate // scale down to print minimum digits after the decimal point 810Sstevel@tonic-gate prec = 3; 820Sstevel@tonic-gate if ((rateh % 10) == 0) { 830Sstevel@tonic-gate prec--; 840Sstevel@tonic-gate rateh /= 10; 850Sstevel@tonic-gate } 860Sstevel@tonic-gate if ((rateh % 10) == 0) { 870Sstevel@tonic-gate prec--; 880Sstevel@tonic-gate rateh /= 10; 890Sstevel@tonic-gate } 900Sstevel@tonic-gate (void) sprintf(str, "%d.%0*dkHz", ratek, prec, rateh); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate return (str); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate // Return a string containing the number of channels 960Sstevel@tonic-gate char *AudioHdr:: 970Sstevel@tonic-gate ChannelString() const 980Sstevel@tonic-gate { 990Sstevel@tonic-gate char *str; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate str = new char[32]; 1020Sstevel@tonic-gate switch (channels) { 1030Sstevel@tonic-gate case 1: 1040Sstevel@tonic-gate (void) sprintf(str, "mono"); 1050Sstevel@tonic-gate break; 1060Sstevel@tonic-gate case 2: 1070Sstevel@tonic-gate (void) sprintf(str, "stereo"); 1080Sstevel@tonic-gate break; 1090Sstevel@tonic-gate case 4: 1100Sstevel@tonic-gate (void) sprintf(str, "quad"); 1110Sstevel@tonic-gate break; 1120Sstevel@tonic-gate default: 1130Sstevel@tonic-gate (void) sprintf(str, "%d-channel", channels); 1140Sstevel@tonic-gate break; 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate return (str); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate // Return a string containing the encoding 1200Sstevel@tonic-gate char *AudioHdr:: 1210Sstevel@tonic-gate EncodingString() const 1220Sstevel@tonic-gate { 1230Sstevel@tonic-gate char *str; 1240Sstevel@tonic-gate Double prec; 1250Sstevel@tonic-gate int iprec; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate str = new char[64]; 1280Sstevel@tonic-gate if ((samples_per_unit == 0) || (bytes_per_unit == 0) || 1290Sstevel@tonic-gate (encoding == NONE)) { 1300Sstevel@tonic-gate (void) sprintf(str, "???"); 1310Sstevel@tonic-gate } else { 1320Sstevel@tonic-gate // First encode precision 1330Sstevel@tonic-gate iprec = (bytes_per_unit * 8) / samples_per_unit; 1340Sstevel@tonic-gate prec = ((Double)bytes_per_unit * 8.) / (Double)samples_per_unit; 1350Sstevel@tonic-gate if (prec == (Double) iprec) { 1360Sstevel@tonic-gate (void) sprintf(str, "%d-bit ", iprec); 1370Sstevel@tonic-gate } else { 1380Sstevel@tonic-gate (void) sprintf(str, "%.1f-bit ", double(prec)); 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate // Then encode format 1420Sstevel@tonic-gate switch (encoding) { 1430Sstevel@tonic-gate case ULAW: 1440Sstevel@tonic-gate // XXX - See bug 1121000 1450Sstevel@tonic-gate // XXX - (void) strcat(str, "�-law"); 1460Sstevel@tonic-gate (void) strcat(str, "u-law"); 1470Sstevel@tonic-gate break; 1480Sstevel@tonic-gate case ALAW: 1490Sstevel@tonic-gate (void) strcat(str, "A-law"); 1500Sstevel@tonic-gate break; 1510Sstevel@tonic-gate case LINEAR: 1520Sstevel@tonic-gate (void) strcat(str, "linear"); 1530Sstevel@tonic-gate break; 1540Sstevel@tonic-gate case FLOAT: 1550Sstevel@tonic-gate (void) strcat(str, "float"); 1560Sstevel@tonic-gate break; 1570Sstevel@tonic-gate case G721: 1580Sstevel@tonic-gate (void) strcat(str, "G.721 ADPCM"); 1590Sstevel@tonic-gate break; 1600Sstevel@tonic-gate case G722: 1610Sstevel@tonic-gate (void) strcat(str, "G.722 ADPCM"); 1620Sstevel@tonic-gate break; 1630Sstevel@tonic-gate case G723: 1640Sstevel@tonic-gate (void) strcat(str, "G.723 ADPCM"); 1650Sstevel@tonic-gate break; 1660Sstevel@tonic-gate case DVI: 1670Sstevel@tonic-gate (void) strcat(str, "DVI ADPCM"); 1680Sstevel@tonic-gate break; 1690Sstevel@tonic-gate default: 1700Sstevel@tonic-gate (void) strcat(str, "???"); 1710Sstevel@tonic-gate break; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate return (str); 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate // Return a string containing the entire audio encoding 1780Sstevel@tonic-gate char *AudioHdr:: 1790Sstevel@tonic-gate FormatString() const 1800Sstevel@tonic-gate { 1810Sstevel@tonic-gate char *str; 1820Sstevel@tonic-gate char *rate; 1830Sstevel@tonic-gate char *chan; 1840Sstevel@tonic-gate char *enc; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate str = new char[4 * 32]; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate enc = EncodingString(); 1890Sstevel@tonic-gate rate = RateString(); 1900Sstevel@tonic-gate chan = ChannelString(); 1910Sstevel@tonic-gate (void) sprintf(str, "%s, %s, %s", enc, rate, chan); 1920Sstevel@tonic-gate delete rate; 1930Sstevel@tonic-gate delete chan; 1940Sstevel@tonic-gate delete enc; 1950Sstevel@tonic-gate return (str); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate // Parse a string containing the sample rate 1990Sstevel@tonic-gate AudioError AudioHdr:: 2000Sstevel@tonic-gate RateParse( 2010Sstevel@tonic-gate char *str) 2020Sstevel@tonic-gate { 2030Sstevel@tonic-gate static char *lib_khz = NULL; 2040Sstevel@tonic-gate static char *lib_hz = NULL; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate double r; 2070Sstevel@tonic-gate int rate; 2080Sstevel@tonic-gate char khzbuf[16]; 2090Sstevel@tonic-gate char *khz; 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate if (str == NULL) 2120Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate // Init i18n string translations 2150Sstevel@tonic-gate if (lib_khz == NULL) { 2160Sstevel@tonic-gate lib_khz = to_lowercase(_MGET_("khz")); 2170Sstevel@tonic-gate lib_hz = to_lowercase(_MGET_("hz")); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate // Scan for a number followed by an optional khz designator 2210Sstevel@tonic-gate switch (sscanf(str, " %lf %15s", &r, khzbuf)) { 2220Sstevel@tonic-gate case 2: 2230Sstevel@tonic-gate // Process 'khz', if present, and fall through 2240Sstevel@tonic-gate khz = to_lowercase(khzbuf); 2250Sstevel@tonic-gate if ((strcmp(khz, "khz") == 0) || 2260Sstevel@tonic-gate (strcmp(khz, "khertz") == 0) || 2270Sstevel@tonic-gate (strcmp(khz, "kilohertz") == 0) || 2280Sstevel@tonic-gate (strcmp(khz, "k") == 0) || 2290Sstevel@tonic-gate (strcoll(khz, lib_khz) == 0)) { 2300Sstevel@tonic-gate r *= 1000.; 2310Sstevel@tonic-gate } else if ((strcmp(khz, "hz") != 0) && 2320Sstevel@tonic-gate (strcmp(khz, "hertz") != 0) && 2330Sstevel@tonic-gate (strcoll(khz, lib_hz) != 0)) { 2340Sstevel@tonic-gate delete khz; 2350Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate delete khz; 2380Sstevel@tonic-gate case 1: 2390Sstevel@tonic-gate rate = irint(r); 2400Sstevel@tonic-gate break; 2410Sstevel@tonic-gate default: 2420Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate // Check for reasonable bounds 2450Sstevel@tonic-gate if ((rate <= 0) || (rate > 500000)) { 2460Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate sample_rate = (unsigned int) rate; 2490Sstevel@tonic-gate return (AUDIO_SUCCESS); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate // Parse a string containing the number of channels 2530Sstevel@tonic-gate AudioError AudioHdr:: 2540Sstevel@tonic-gate ChannelParse( 2550Sstevel@tonic-gate char *str) 2560Sstevel@tonic-gate { 2570Sstevel@tonic-gate static char *lib_chan = NULL; 2580Sstevel@tonic-gate static char *lib_mono = NULL; 2590Sstevel@tonic-gate static char *lib_stereo = NULL; 2600Sstevel@tonic-gate char cstrbuf[16]; 2610Sstevel@tonic-gate char *cstr; 2620Sstevel@tonic-gate char xtra[4]; 2630Sstevel@tonic-gate int chan; 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate // Init i18n string translations 2660Sstevel@tonic-gate if (lib_chan == NULL) { 2670Sstevel@tonic-gate lib_chan = to_lowercase(_MGET_("channel")); 2680Sstevel@tonic-gate lib_mono = to_lowercase(_MGET_("mono")); 2690Sstevel@tonic-gate lib_stereo = to_lowercase(_MGET_("stereo")); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate // Parse a number, followed by optional "-channel" 2730Sstevel@tonic-gate switch (sscanf(str, " %d %15s", &chan, cstrbuf)) { 2740Sstevel@tonic-gate case 2: 2750Sstevel@tonic-gate cstr = to_lowercase(cstrbuf); 2760Sstevel@tonic-gate if ((strcmp(cstr, "-channel") != 0) && 2770Sstevel@tonic-gate (strcmp(cstr, "-chan") != 0) && 2780Sstevel@tonic-gate (strcoll(cstr, lib_chan) != 0)) { 2790Sstevel@tonic-gate delete cstr; 2800Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate delete cstr; 2830Sstevel@tonic-gate case 1: 2840Sstevel@tonic-gate break; 2850Sstevel@tonic-gate default: 2860Sstevel@tonic-gate // If no number, look for reasonable keywords 2870Sstevel@tonic-gate if (sscanf(str, " %15s %1s", cstrbuf, xtra) != 1) { 2880Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate cstr = to_lowercase(cstrbuf); 2910Sstevel@tonic-gate if ((strcmp(cstr, "mono") == 0) || 2920Sstevel@tonic-gate (strcmp(cstr, "monaural") == 0) || 2930Sstevel@tonic-gate (strcoll(cstr, lib_mono) == 0)) { 2940Sstevel@tonic-gate chan = 1; 2950Sstevel@tonic-gate } else if ((strcmp(cstr, "stereo") == 0) || 2960Sstevel@tonic-gate (strcmp(cstr, "dual") == 0) || 2970Sstevel@tonic-gate (strcoll(cstr, lib_stereo) == 0)) { 2980Sstevel@tonic-gate chan = 2; 2990Sstevel@tonic-gate } else if ((strcmp(cstr, "quad") == 0) || 3000Sstevel@tonic-gate (strcmp(cstr, "quadrophonic") == 0)) { 3010Sstevel@tonic-gate chan = 4; 3020Sstevel@tonic-gate } else { 3030Sstevel@tonic-gate delete cstr; 3040Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate delete cstr; 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate if ((chan <= 0) || (chan > 256)) { 3090Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate channels = (unsigned int) chan; 3120Sstevel@tonic-gate return (AUDIO_SUCCESS); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate // Parse a string containing the audio encoding 3160Sstevel@tonic-gate AudioError AudioHdr:: 3170Sstevel@tonic-gate EncodingParse( 3180Sstevel@tonic-gate char *str) 3190Sstevel@tonic-gate { 3200Sstevel@tonic-gate static char *lib_bit = NULL; 3210Sstevel@tonic-gate static char *lib_ulaw = NULL; 3220Sstevel@tonic-gate static char *lib_Alaw = NULL; 3230Sstevel@tonic-gate static char *lib_linear = NULL; 3240Sstevel@tonic-gate int i; 3250Sstevel@tonic-gate char *p; 3260Sstevel@tonic-gate char estrbuf[64]; 3270Sstevel@tonic-gate char *estr; 3280Sstevel@tonic-gate char xtrabuf[32]; 3290Sstevel@tonic-gate char *xtra; 3300Sstevel@tonic-gate char *xp; 3310Sstevel@tonic-gate char buf[BUFSIZ]; 3320Sstevel@tonic-gate char *cp; 3330Sstevel@tonic-gate double prec; 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate // Init i18n string translations 3360Sstevel@tonic-gate if (lib_bit == NULL) { 3370Sstevel@tonic-gate lib_bit = to_lowercase(_MGET_("bit")); 3380Sstevel@tonic-gate lib_ulaw = to_lowercase(_MGET_("u-law")); 3390Sstevel@tonic-gate lib_Alaw = to_lowercase(_MGET_("A-law")); 3400Sstevel@tonic-gate lib_linear = to_lowercase(_MGET_("linear8")); 3410Sstevel@tonic-gate lib_linear = to_lowercase(_MGET_("linear")); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate // first copy and remove leading spaces 3450Sstevel@tonic-gate (void) strncpy(buf, str, BUFSIZ); 3460Sstevel@tonic-gate for (cp = buf; *cp == ' '; cp++) 3470Sstevel@tonic-gate continue; 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate // Delimit the precision. If there is one, parse it. 3500Sstevel@tonic-gate prec = 0.; 3510Sstevel@tonic-gate p = strchr(cp, ' '); 3520Sstevel@tonic-gate if (p != NULL) { 3530Sstevel@tonic-gate *p++ = '\0'; 3540Sstevel@tonic-gate i = sscanf(cp, " %lf %15s", &prec, xtrabuf); 3550Sstevel@tonic-gate if (i == 0) { 3560Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate if (i == 2) { 3590Sstevel@tonic-gate // convert to lowercase and skip leading "-", if any 3600Sstevel@tonic-gate xtra = to_lowercase(xtrabuf); 3610Sstevel@tonic-gate xp = (xtra[0] == '-') ? &xtra[1] : &xtra[0]; 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate if ((strcmp(xp, "bit") != 0) && 3640Sstevel@tonic-gate (strcoll(xp, lib_bit) != 0)) { 3650Sstevel@tonic-gate delete xtra; 3660Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate delete xtra; 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate if ((prec <= 0.) || (prec > 512.)) { 3710Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate // Don't be fooled by "8 bit" 3750Sstevel@tonic-gate i = sscanf(p, " %15s", xtrabuf); 3760Sstevel@tonic-gate if (i == 1) { 3770Sstevel@tonic-gate // convert to lowercase and skip leading "-", if any 3780Sstevel@tonic-gate xtra = to_lowercase(xtrabuf); 3790Sstevel@tonic-gate xp = (xtra[0] == '-') ? &xtra[1] : &xtra[0]; 3800Sstevel@tonic-gate if ((strcmp(xp, "bit") == 0) || 3810Sstevel@tonic-gate (strcoll(xp, lib_bit) == 0)) { 3820Sstevel@tonic-gate xp = strchr(p, ' '); 3830Sstevel@tonic-gate if (xp != NULL) 3840Sstevel@tonic-gate p = xp; 3850Sstevel@tonic-gate else 3860Sstevel@tonic-gate p += strlen(xtrabuf); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate delete xtra; 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate } else { 3910Sstevel@tonic-gate p = cp; 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate i = sscanf(p, " %31s %31s", estrbuf, xtrabuf); 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate // If "adpcm" appended with a space, concatenate it 3970Sstevel@tonic-gate if (i == 2) { 3980Sstevel@tonic-gate xtra = to_lowercase(xtrabuf); 3990Sstevel@tonic-gate if (strcmp(xtra, "adpcm") == 0) { 4000Sstevel@tonic-gate (void) strcat(estrbuf, xtra); 4010Sstevel@tonic-gate i = 1; 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate delete xtra; 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate if (i == 1) { 4060Sstevel@tonic-gate estr = to_lowercase(estrbuf); 4070Sstevel@tonic-gate if ((strcmp(estr, "ulaw") == 0) || 4080Sstevel@tonic-gate (strcmp(estr, "u-law") == 0) || 4090Sstevel@tonic-gate (strcmp(estr, "�law") == 0) || 4100Sstevel@tonic-gate (strcmp(estr, "�-law") == 0) || 4110Sstevel@tonic-gate (strcmp(estr, "mulaw") == 0) || 4120Sstevel@tonic-gate (strcmp(estr, "mu-law") == 0) || 4130Sstevel@tonic-gate (strcoll(estr, lib_ulaw) == 0)) { 4140Sstevel@tonic-gate if ((prec != 0.) && (prec != 8.)) 4150Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4160Sstevel@tonic-gate encoding = ULAW; 4170Sstevel@tonic-gate samples_per_unit = 1; 4180Sstevel@tonic-gate bytes_per_unit = 1; 4190Sstevel@tonic-gate } else if ((strcmp(estr, "alaw") == 0) || 4200Sstevel@tonic-gate (strcmp(estr, "a-law") == 0) || 4210Sstevel@tonic-gate (strcoll(estr, lib_Alaw) == 0)) { 4220Sstevel@tonic-gate if ((prec != 0.) && (prec != 8.)) 4230Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4240Sstevel@tonic-gate encoding = ALAW; 4250Sstevel@tonic-gate samples_per_unit = 1; 4260Sstevel@tonic-gate bytes_per_unit = 1; 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate } else if ((strcmp(estr, "linear") == 0) || 4290Sstevel@tonic-gate (strcmp(estr, "lin") == 0) || 4300Sstevel@tonic-gate (strcmp(estr, "pcm") == 0) || 4310Sstevel@tonic-gate (strcoll(estr, lib_linear) == 0)) { 4320Sstevel@tonic-gate if ((prec != 0.) && (prec != 8.) && (prec != 16.) && 4330Sstevel@tonic-gate (prec != 24.) && (prec != 32.)) 4340Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4350Sstevel@tonic-gate if (prec == 0.) 4360Sstevel@tonic-gate prec = 16.; 4370Sstevel@tonic-gate encoding = LINEAR; 4380Sstevel@tonic-gate samples_per_unit = 1; 4390Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate } else if ((strcmp(estr, "linear8") == 0) || 4420Sstevel@tonic-gate (strcmp(estr, "lin8") == 0) || 4430Sstevel@tonic-gate (strcmp(estr, "pcm8") == 0)) { 4440Sstevel@tonic-gate if ((prec != 0.) && (prec != 8.)) 4450Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4460Sstevel@tonic-gate prec = 8.; 4470Sstevel@tonic-gate encoding = LINEAR; 4480Sstevel@tonic-gate samples_per_unit = 1; 4490Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate } else if ((strcmp(estr, "linear16") == 0) || 4520Sstevel@tonic-gate (strcmp(estr, "lin16") == 0) || 4530Sstevel@tonic-gate (strcmp(estr, "pcm16") == 0)) { 4540Sstevel@tonic-gate if ((prec != 0.) && (prec != 16.)) 4550Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4560Sstevel@tonic-gate prec = 16.; 4570Sstevel@tonic-gate encoding = LINEAR; 4580Sstevel@tonic-gate samples_per_unit = 1; 4590Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate } else if ((strcmp(estr, "linear24") == 0) || 4620Sstevel@tonic-gate (strcmp(estr, "lin24") == 0) || 4630Sstevel@tonic-gate (strcmp(estr, "pcm24") == 0)) { 4640Sstevel@tonic-gate if ((prec != 0.) && (prec != 24.)) 4650Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4660Sstevel@tonic-gate prec = 24.; 4670Sstevel@tonic-gate encoding = LINEAR; 4680Sstevel@tonic-gate samples_per_unit = 1; 4690Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate } else if ((strcmp(estr, "linear32") == 0) || 4720Sstevel@tonic-gate (strcmp(estr, "lin32") == 0) || 4730Sstevel@tonic-gate (strcmp(estr, "pcm32") == 0)) { 4740Sstevel@tonic-gate if ((prec != 0.) && (prec != 32.)) 4750Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4760Sstevel@tonic-gate prec = 32.; 4770Sstevel@tonic-gate encoding = LINEAR; 4780Sstevel@tonic-gate samples_per_unit = 1; 4790Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate } else if ((strcmp(estr, "float") == 0) || 4820Sstevel@tonic-gate (strcmp(estr, "floatingpoint") == 0) || 4830Sstevel@tonic-gate (strcmp(estr, "floating-point") == 0)) { 4840Sstevel@tonic-gate if ((prec != 0.) && (prec != 32.) && (prec != 64.)) 4850Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4860Sstevel@tonic-gate if (prec == 0.) 4870Sstevel@tonic-gate prec = 64.; 4880Sstevel@tonic-gate encoding = FLOAT; 4890Sstevel@tonic-gate samples_per_unit = 1; 4900Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate } else if ((strcmp(estr, "float32") == 0) || 4930Sstevel@tonic-gate (strcmp(estr, "floatingpoint32") == 0) || 4940Sstevel@tonic-gate (strcmp(estr, "floating-point32") == 0)) { 4950Sstevel@tonic-gate if ((prec != 0.) && (prec != 32.)) 4960Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 4970Sstevel@tonic-gate prec = 32.; 4980Sstevel@tonic-gate encoding = FLOAT; 4990Sstevel@tonic-gate samples_per_unit = 1; 5000Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate } else if ((strcmp(estr, "float64") == 0) || 5030Sstevel@tonic-gate (strcmp(estr, "double") == 0) || 5040Sstevel@tonic-gate (strcmp(estr, "floatingpoint64") == 0) || 5050Sstevel@tonic-gate (strcmp(estr, "floating-point64") == 0)) { 5060Sstevel@tonic-gate if ((prec != 0.) && (prec != 64.)) 5070Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5080Sstevel@tonic-gate prec = 64.; 5090Sstevel@tonic-gate encoding = FLOAT; 5100Sstevel@tonic-gate samples_per_unit = 1; 5110Sstevel@tonic-gate bytes_per_unit = irint(prec / 8.); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate } else if ((strcmp(estr, "g.721") == 0) || 5140Sstevel@tonic-gate (strcmp(estr, "g721") == 0) || 5150Sstevel@tonic-gate (strcmp(estr, "g.721adpcm") == 0) || 5160Sstevel@tonic-gate (strcmp(estr, "g721adpcm") == 0)) { 5170Sstevel@tonic-gate if ((prec != 0.) && (prec != 4.)) 5180Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5190Sstevel@tonic-gate encoding = G721; 5200Sstevel@tonic-gate samples_per_unit = 2; 5210Sstevel@tonic-gate bytes_per_unit = 1; 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate } else if ((strcmp(estr, "g.722") == 0) || 5240Sstevel@tonic-gate (strcmp(estr, "g722") == 0) || 5250Sstevel@tonic-gate (strcmp(estr, "g.722adpcm") == 0) || 5260Sstevel@tonic-gate (strcmp(estr, "g722adpcm") == 0)) { 5270Sstevel@tonic-gate if ((prec != 0.) && (prec != 8.)) 5280Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5290Sstevel@tonic-gate encoding = G722; 5300Sstevel@tonic-gate samples_per_unit = 1; 5310Sstevel@tonic-gate bytes_per_unit = 1; 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate } else if ((strcmp(estr, "g.723") == 0) || 5340Sstevel@tonic-gate (strcmp(estr, "g723") == 0) || 5350Sstevel@tonic-gate (strcmp(estr, "g.723adpcm") == 0) || 5360Sstevel@tonic-gate (strcmp(estr, "g723adpcm") == 0)) { 5370Sstevel@tonic-gate if ((prec != 0.) && (prec != 3.) && (prec != 5.)) 5380Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5390Sstevel@tonic-gate if (prec == 0.) 5400Sstevel@tonic-gate prec = 3.; 5410Sstevel@tonic-gate encoding = G723; 5420Sstevel@tonic-gate samples_per_unit = 8; 5430Sstevel@tonic-gate bytes_per_unit = irint(prec); 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate } else if ((strcmp(estr, "g.723-3") == 0) || 5460Sstevel@tonic-gate (strcmp(estr, "g.723_3") == 0) || 5470Sstevel@tonic-gate (strcmp(estr, "g.723.3") == 0) || 5480Sstevel@tonic-gate (strcmp(estr, "g723-3") == 0) || 5490Sstevel@tonic-gate (strcmp(estr, "g723_3") == 0) || 5500Sstevel@tonic-gate (strcmp(estr, "g723.3") == 0)) { 5510Sstevel@tonic-gate if ((prec != 0.) && (prec != 3.)) 5520Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5530Sstevel@tonic-gate prec = 3.; 5540Sstevel@tonic-gate encoding = G723; 5550Sstevel@tonic-gate samples_per_unit = 8; 5560Sstevel@tonic-gate bytes_per_unit = irint(prec); 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate } else if ((strcmp(estr, "g.723-5") == 0) || 5590Sstevel@tonic-gate (strcmp(estr, "g.723_5") == 0) || 5600Sstevel@tonic-gate (strcmp(estr, "g.723.5") == 0) || 5610Sstevel@tonic-gate (strcmp(estr, "g723-5") == 0) || 5620Sstevel@tonic-gate (strcmp(estr, "g723_5") == 0) || 5630Sstevel@tonic-gate (strcmp(estr, "g723.5") == 0)) { 5640Sstevel@tonic-gate if ((prec != 0.) && (prec != 5.)) 5650Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5660Sstevel@tonic-gate prec = 5.; 5670Sstevel@tonic-gate encoding = G723; 5680Sstevel@tonic-gate samples_per_unit = 8; 5690Sstevel@tonic-gate bytes_per_unit = irint(prec); 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate } else if ((strcmp(estr, "dvi") == 0) || 5720Sstevel@tonic-gate (strcmp(estr, "dviadpcm") == 0)) { 5730Sstevel@tonic-gate if ((prec != 0.) && (prec != 4.)) 5740Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5750Sstevel@tonic-gate encoding = DVI; 5760Sstevel@tonic-gate samples_per_unit = 2; 5770Sstevel@tonic-gate bytes_per_unit = 1; 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate } else { 5800Sstevel@tonic-gate delete estr; 5810Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate delete estr; 5840Sstevel@tonic-gate } else { 5850Sstevel@tonic-gate return (AUDIO_ERR_BADARG); 5860Sstevel@tonic-gate } 5870Sstevel@tonic-gate return (AUDIO_SUCCESS); 5880Sstevel@tonic-gate } 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate // Parse a string containing the comma-separated audio encoding 5910Sstevel@tonic-gate // Format is: "enc, chan, rate" 5920Sstevel@tonic-gate // XXX - some countries use comma instead of decimal point 5930Sstevel@tonic-gate // so there may be a problem with "44,1 khz" 5940Sstevel@tonic-gate AudioError AudioHdr:: 5950Sstevel@tonic-gate FormatParse( 5960Sstevel@tonic-gate char *str) 5970Sstevel@tonic-gate { 5980Sstevel@tonic-gate char *pstr; 5990Sstevel@tonic-gate char *ptr; 6000Sstevel@tonic-gate char *p; 6010Sstevel@tonic-gate AudioHdr newhdr; 6020Sstevel@tonic-gate AudioError err; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate pstr = new char[strlen(str) + 1]; 6050Sstevel@tonic-gate (void) strcpy(pstr, str); 6060Sstevel@tonic-gate ptr = pstr; 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate // Delimit and parse the precision string 6090Sstevel@tonic-gate p = strchr(ptr, ','); 6100Sstevel@tonic-gate if (p == NULL) 6110Sstevel@tonic-gate p = strchr(ptr, ' '); 6120Sstevel@tonic-gate if (p == NULL) { 6130Sstevel@tonic-gate err = AUDIO_ERR_BADARG; 6140Sstevel@tonic-gate goto errret; 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate *p++ = '\0'; 6170Sstevel@tonic-gate err = newhdr.EncodingParse(ptr); 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate // Delimit and parse the sample rate string 6200Sstevel@tonic-gate if (!err) { 6210Sstevel@tonic-gate ptr = p; 6220Sstevel@tonic-gate p = strchr(ptr, ','); 6230Sstevel@tonic-gate if (p == NULL) 6240Sstevel@tonic-gate p = strchr(ptr, ' '); 6250Sstevel@tonic-gate if (p == NULL) { 6260Sstevel@tonic-gate err = AUDIO_ERR_BADARG; 6270Sstevel@tonic-gate goto errret; 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate *p++ = '\0'; 6300Sstevel@tonic-gate err = newhdr.RateParse(ptr); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate // Finally, parse the channels string 6340Sstevel@tonic-gate if (!err) { 6350Sstevel@tonic-gate err = newhdr.ChannelParse(p); 6360Sstevel@tonic-gate } 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate // Validate the resulting header 6390Sstevel@tonic-gate if (!err) 6400Sstevel@tonic-gate err = newhdr.Validate(); 6410Sstevel@tonic-gate if (!err) 6420Sstevel@tonic-gate *this = newhdr; 6430Sstevel@tonic-gate errret: 6440Sstevel@tonic-gate delete pstr; 6450Sstevel@tonic-gate return (err); 6460Sstevel@tonic-gate } 647