(Metux) autogen.sh: not running ./configure anymore (breaks certain distro builders)
[mirror-ossqm-audiofile.git] / libaudiofile / nist.c
blob991dd2dd0569b708814486b087f583ccdcf4c558
1 /*
2 Audio File Library
3 Copyright (C) 2004, Michael Pruett <michael@68k.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307 USA.
22 nist.c
24 This file contains code for reading NIST SPHERE files.
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
31 #include <assert.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
37 #include "afinternal.h"
38 #include "audiofile.h"
39 #include "util.h"
40 #include "byteorder.h"
41 #include "setup.h"
42 #include "track.h"
44 #include "nist.h"
46 _AFfilesetup _af_nist_default_filesetup =
48 _AF_VALID_FILESETUP, /* valid */
49 AF_FILE_NIST_SPHERE, /* fileFormat */
50 true, /* trackSet */
51 true, /* instrumentSet */
52 true, /* miscellaneousSet */
53 1, /* trackCount */
54 NULL, /* tracks */
55 0, /* instrumentCount */
56 NULL, /* instruments */
57 0, /* miscellaneousCount */
58 NULL /* miscellaneous */
61 bool _af_nist_recognize (AFvirtualfile *fh)
63 uint8_t buffer[16];
65 af_fseek(fh, 0, SEEK_SET);
67 if (af_fread(buffer, 16, 1, fh) != 1)
68 return false;
70 /* Check to see if the file's magic number matches. */
71 if (memcmp(buffer, "NIST_1A\n 1024\n", 16) == 0)
72 return true;
74 return false;
77 AFfilesetup _af_nist_complete_setup (AFfilesetup setup)
79 _TrackSetup *track;
81 if (setup->trackSet && setup->trackCount != 1)
83 _af_error(AF_BAD_NUMTRACKS, "NIST SPHERE file must have 1 track");
84 return AF_NULL_FILESETUP;
87 track = &setup->tracks[0];
89 if (track->sampleFormatSet)
91 /* XXXmpruett: Currently we allow only 1-16 bit sample width. */
92 if (track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP &&
93 (track->f.sampleWidth < 1 || track->f.sampleWidth > 16))
95 _af_error(AF_BAD_WIDTH,
96 "invalid sample width %d bits for NIST SPHERE format");
97 return AF_NULL_FILESETUP;
99 else if (track->f.sampleFormat == AF_SAMPFMT_UNSIGNED)
101 _af_error(AF_BAD_SAMPFMT,
102 "NIST SPHERE format does not support unsigned data");
103 return AF_NULL_FILESETUP;
105 else if (track->f.sampleFormat == AF_SAMPFMT_FLOAT ||
106 track->f.sampleFormat == AF_SAMPFMT_DOUBLE)
108 _af_error(AF_BAD_SAMPFMT,
109 "NIST SPHERE format does not support floating-point data");
110 return AF_NULL_FILESETUP;
114 if (track->rateSet && track->f.sampleRate <= 0.0)
116 _af_error(AF_BAD_RATE,
117 "invalid sample rate %.30g for NIST SPHERE file",
118 track->f.sampleRate);
119 return AF_NULL_FILESETUP;
122 if (track->channelCountSet && track->f.channelCount < 1)
124 _af_error(AF_BAD_CHANNELS,
125 "invalid channel count (%d) for NIST SPHERE format",
126 track->f.channelCount);
127 return AF_NULL_FILESETUP;
130 if (track->compressionSet && track->f.compressionType != AF_COMPRESSION_NONE &&
131 track->f.compressionType != AF_COMPRESSION_G711_ULAW &&
132 track->f.compressionType != AF_COMPRESSION_G711_ALAW)
134 _af_error(AF_BAD_NOT_IMPLEMENTED,
135 "NIST SPHERE format supports only G.711 u-law or A-law compression");
136 return AF_NULL_FILESETUP;
139 if (track->aesDataSet)
141 _af_error(AF_BAD_FILESETUP, "NIST SPHERE file cannot have AES data");
142 return AF_NULL_FILESETUP;
145 if (track->markersSet && track->markerCount != 0)
147 _af_error(AF_BAD_NUMMARKS, "NIST SPHERE format does not support markers");
148 return AF_NULL_FILESETUP;
151 if (setup->instrumentSet && setup->instrumentCount != 0)
153 _af_error(AF_BAD_NUMINSTS, "NIST SPHERE format does not support instruments");
154 return AF_NULL_FILESETUP;
157 /* XXXmpruett: We don't support miscellaneous chunks for now. */
158 if (setup->miscellaneousSet && setup->miscellaneousCount != 0)
160 _af_error(AF_BAD_NOT_IMPLEMENTED, "NIST SPHERE format does not currently support miscellaneous chunks");
161 return AF_NULL_FILESETUP;
164 return _af_filesetup_copy(setup, &_af_nist_default_filesetup, true);
167 static bool nist_header_read_int (char *header, char *key, int *val)
169 char *cp;
170 char keystring[256], scanstring[256];
172 snprintf(keystring, 256, "\n%s -i", key);
174 if ((cp = strstr(header, keystring)) != NULL)
176 snprintf(scanstring, 256, "\n%s -i %%d", key);
177 sscanf(cp, scanstring, val);
178 return true;
181 return false;
184 static bool nist_header_read_string (char *header, char *key, int *length, char *val)
186 char *cp;
187 char keystring[256], scanstring[256];
189 snprintf(keystring, 256, "\n%s -s", key);
191 if ((cp = strstr(header, keystring)) != NULL)
193 snprintf(scanstring, 256, "\n%s -s%%d %%79s", key);
194 sscanf(cp, scanstring, length, val);
195 return true;
198 return false;
201 status _af_nist_read_init (AFfilesetup setup, AFfilehandle handle)
203 _Track *track;
204 char header[NIST_SPHERE_HEADER_LENGTH + 1];
205 int intval;
206 char strval[NIST_SPHERE_MAX_FIELD_LENGTH];
207 int sample_n_bytes;
209 handle->instruments = NULL;
210 handle->instrumentCount = 0 ;
211 handle->miscellaneous = NULL;
212 handle->miscellaneousCount = 0;
214 handle->tracks = NULL;
215 handle->trackCount = 1;
217 af_fseek(handle->fh, 0, SEEK_SET);
219 if (af_fread(header, NIST_SPHERE_HEADER_LENGTH, 1, handle->fh) != 1)
221 _af_error(AF_BAD_READ, "Could not read NIST SPHERE file header");
222 return AF_FAIL;
225 header[NIST_SPHERE_HEADER_LENGTH] = '\0';
227 if (memcmp(header, "NIST_1A\n 1024\n", 16) != 0)
229 _af_error(AF_BAD_FILEFMT, "Bad NIST SPHERE file header");
230 return AF_FAIL;
233 if ((handle->tracks = _af_track_new()) == NULL)
234 return AF_FAIL;
235 track = &handle->tracks[0];
237 /* Read number of bytes per sample. */
238 if (!nist_header_read_int(header, "sample_n_bytes", &sample_n_bytes))
240 _af_error(AF_BAD_HEADER, "bytes per sample not specified");
241 return AF_FAIL;
245 Since some older NIST SPHERE files lack a sample_coding
246 field, if sample_n_bytes is 1, assume mu-law;
247 otherwise assume linear PCM.
249 track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
250 if (sample_n_bytes == 1)
252 track->f.compressionType = AF_COMPRESSION_G711_ULAW;
253 track->f.sampleWidth = 16;
255 else
257 track->f.compressionType = AF_COMPRESSION_NONE;
258 track->f.sampleWidth = sample_n_bytes * 8;
261 if (nist_header_read_string(header, "sample_coding", &intval, strval))
263 if (strcmp(strval, "pcm") == 0)
265 else if (strcmp(strval, "ulaw") == 0 || strcmp(strval, "mu-law") == 0)
267 track->f.compressionType = AF_COMPRESSION_G711_ULAW;
268 track->f.sampleWidth = 16;
270 else if (strcmp(strval, "alaw") == 0)
272 track->f.compressionType = AF_COMPRESSION_G711_ALAW;
273 track->f.sampleWidth = 16;
275 else
277 _af_error(AF_BAD_SAMPFMT,
278 "unrecognized NIST SPHERE sample format %s", strval);
279 return AF_FAIL;
283 /* Read channel count. */
284 if (nist_header_read_int(header, "channel_count", &intval))
286 if (intval < 1)
288 _af_error(AF_BAD_CHANNELS, "invalid number of channels %d",
289 intval);
290 return AF_FAIL;
292 track->f.channelCount = intval;
294 else
296 _af_error(AF_BAD_HEADER, "number of channels not specified");
297 return AF_FAIL;
300 /* Read string representing byte order. */
301 if (nist_header_read_string(header, "sample_byte_format", &intval, strval))
303 if (intval > 1)
305 if (strncmp(strval, "01", 2) == 0)
306 track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN;
307 else
308 track->f.byteOrder = AF_BYTEORDER_BIGENDIAN;
310 else
311 track->f.byteOrder = _AF_BYTEORDER_NATIVE;
313 else
316 Fail if this field is not present and sample
317 width is more than one byte.
319 if (track->f.compressionType == AF_COMPRESSION_NONE &&
320 track->f.sampleWidth > 8)
322 _af_error(AF_BAD_HEADER, "sample byte order not specified");
323 return AF_FAIL;
327 /* Read significant bits per sample. */
328 if (nist_header_read_int(header, "sample_sig_bits", &intval))
330 if (intval < 1 || intval > 32)
332 _af_error(AF_BAD_WIDTH, "invalid sample width %d bits\n",
333 intval);
334 return AF_FAIL;
338 Use specified significant bits value as the
339 sample width for uncompressed data as long
340 as the number of bytes per sample remains
341 unchanged.
343 if (track->f.compressionType == AF_COMPRESSION_NONE &&
344 (intval + 7) / 8 == sample_n_bytes)
346 track->f.sampleWidth = intval;
350 /* Read sample rate. */
351 if (nist_header_read_int(header, "sample_rate", &intval))
353 if (intval <= 0)
355 _af_error(AF_BAD_RATE, "invalid sample rate %d Hz\n", intval);
356 return AF_FAIL;
358 track->f.sampleRate = intval;
360 else
362 _af_error(AF_BAD_HEADER, "sample rate not specified");
363 return AF_FAIL;
366 /* Read sample count. */
367 if (nist_header_read_int(header, "sample_count", &intval))
369 track->totalfframes = intval / track->f.channelCount;
371 else
373 _af_error(AF_BAD_HEADER, "number of samples not specified");
374 return AF_FAIL;
377 if (_af_set_sample_format(&track->f, track->f.sampleFormat,
378 track->f.sampleWidth) == AF_FAIL)
380 return AF_FAIL;
383 track->fpos_first_frame = NIST_SPHERE_HEADER_LENGTH;
384 track->data_size = af_flength(handle->fh) - NIST_SPHERE_HEADER_LENGTH;
385 track->nextfframe = 0;
386 track->fpos_next_frame = track->fpos_first_frame;
388 handle->formatSpecific = NULL;
390 return AF_SUCCEED;