1 /*-------------- Telecommunications & Signal Processing Lab ---------------
2 McGill University
3
4 Routine:
5 int AOsetDformat (const struct AO_FOpar *FO, AFILE *AFp[], int Nf)
6
7 Purpose:
8 Determine a compatible output data format for the output file type
9
10 Description:
11 This routine determines an output data format compatible with an output
12 file type. If either is explicitly specified, that data format is used.
13 If the output data format is not specified, it is chosen to have the same or
14 greater precision as that of the input data formats.
15
16 For use in error messages, the program name should be set using the routine
17 UTsetProg.
18
19 Parameters:
20 <- int AOsetFormat
21 Output code for the data format
22 -> const struct AO_FOpar *FO
23 Output file parameters. The file type (FO->Ftype) can be FTW_UNDEF.
24 The data format (FO->DFormat.Format) can be FD_UNDEF.
25 -> const AFILE *AFp[]
26 Audio file pointers for the input files (Nf values)
27 -> int Nf
28 Number of input audio file pointers (can be zero)
29
30 Author / revision:
31 P. Kabal Copyright (C) 2003
32 $Revision: 1.1 $ $Date: 2003/05/12 23:52:13 $
33
34 -------------------------------------------------------------------------*/
35
36 #include <stdio.h> /* FILENAME_MAX */
37
38 #include <libtsp.h> /* defines AFILE, used by AFpar.h */
39 #define AF_DATA_TYPE_NAMES
40 #define AF_OUTPUT_FILE_TYPE_NAMES
41 #include <libtsp/AFpar.h>
42 #include <AO.h>
43
44 #define ROUTINE "AOsetFormat"
45 #define PGM ((UTgetProg ())[0] == '\0' ? ROUTINE : UTgetProg ())
46 #define MAXV(a, b) (((a) > (b)) ? (a) : (b))
47
48 /* Resulting precision for mixed data formats */
49 /* 0 - undefined, 1 - 16-bit, 2 - 24-bit, 3 - 32-bit, 4 - float, 5 - double */
50 static const int Prec[NFD] = { 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 1};
51
52 /* Canonical data formats for each of the precisions */
53 static const int DfPrec[6] = {FD_UNDEF, FD_INT16, FD_INT24, FD_INT32,
54 FD_FLOAT32, FD_FLOAT64};
55
56 static const int *
57 AO_Allow (int Ftype);
58
59
60 int
AOsetDformat(const struct AO_FOpar * FO,AFILE * AFp[],int Nf)61 AOsetDformat (const struct AO_FOpar *FO, AFILE *AFp[], int Nf)
62
63 {
64 int i, Ftype, Dformat, Df;
65 const int *Allow;
66
67 /*
68 Format Ftype
69 defined defined Use the combination specified by the user, but give an
70 error if the combination is unsupported.
71 defined undefined If the data format is text, use a noheader file
72 type, otherwise use the file type determined from the
73 file extension.
74 undefined defined Data format from input, modified by allowable output
75 data formats for the given file type.
76 undefined undefined Data format from input, output file type determined from
77 the file extension.
78 */
79
80 /* Set the output file type if not set */
81 Ftype = AOsetFtype (FO);
82 Allow = AO_Allow (Ftype);
83
84 Dformat = FO->DFormat.Format;
85 if (Dformat == FD_UNDEF) {
86
87 /* Data format not defined */
88 /* Choose the output data format based on the input data format
89 Data promotion rules
90 - convert to allowable data formats for the output file type
91 - for mixed input formats, find the resulting precision
92 - find the canonical data format for that precision
93 */
94 if (Nf <= 0)
95 Dformat = Allow[AO_DFORMATO_DEFAULT];
96 else
97 Dformat = Allow[AFp[0]->Format];
98
99 for (i = 1; i < Nf; ++i) {
100 Df = Allow[AFp[i]->Format];
101 if (Df != Dformat)
102 Dformat = DfPrec[MAXV (Prec[Df], Prec[Dformat])];
103 }
104 }
105
106 else {
107
108 /* File type defined, data format now defined (perhaps by default) */
109 /* Check for compatibility of the data format and file type */
110 if (Dformat != Allow[Dformat])
111 UThalt (AOMF_DataFType, PGM, AF_DTN[Dformat], AF_FTWN[Ftype]);
112 }
113
114 return Dformat;
115 }
116
117 static const int *
AO_Allow(int Ftype)118 AO_Allow (int Ftype)
119
120 {
121 const int *Allow;
122
123 /* Conversion tables to allowable data formats for different file types */
124 static const int Allow_AU[NFD] = {
125 FD_UNDEF, FD_MULAW8, FD_ALAW8, FD_INT8, FD_INT8, FD_INT16, FD_INT24,
126 FD_INT32, FD_FLOAT32, FD_FLOAT64, FD_INT16
127 };
128 static const int Allow_WAVE[NFD] = {
129 FD_UNDEF, FD_MULAW8, FD_ALAW8, FD_UINT8, FD_UINT8, FD_INT16, FD_INT24,
130 FD_INT32, FD_FLOAT32, FD_FLOAT64, FD_INT16
131 };
132 static const int Allow_AIFF[NFD] = {
133 FD_UNDEF, FD_INT16, FD_INT16, FD_INT8, FD_INT8, FD_INT16, FD_INT24,
134 FD_INT32, FD_INT16, FD_INT16, FD_INT16
135 };
136 static const int Allow_AIFF_C[NFD] = {
137 FD_UNDEF, FD_MULAW8, FD_ALAW8, FD_INT8, FD_INT8, FD_INT16, FD_INT24,
138 FD_INT32, FD_FLOAT32, FD_FLOAT64, FD_INT16
139 };
140 static const int Allow_NH[NFD] = {
141 FD_UNDEF, FD_MULAW8, FD_ALAW8, FD_UINT8, FD_INT8, FD_INT16, FD_INT24,
142 FD_INT32, FD_FLOAT32, FD_FLOAT64, FD_TEXT
143 };
144
145 switch (Ftype) {
146 case FTW_AU:
147 Allow = Allow_AU;
148 break;
149 case FTW_WAVE:
150 case FTW_WAVE_NOEX:
151 Allow = Allow_WAVE;
152 break;
153 case FTW_AIFF:
154 Allow = Allow_AIFF;
155 break;
156 case FTW_AIFF_C:
157 Allow = Allow_AIFF_C;
158 break;
159 case FTW_NH_EB:
160 case FTW_NH_EL:
161 case FTW_NH_NATIVE:
162 case FTW_NH_SWAP:
163 Allow = Allow_NH;
164 break;
165 default:
166 Allow = NULL;
167 UThalt ("%s: %s", PGM, AOM_InvFTypeC);
168 }
169
170 return Allow;
171 }
172