Updating osxbuild to work with OS X 10.7+/XCode 4.x.
[sox.git] / src / sphere.c
blob479a552c0d37ed0c23b8eba6aa98d69f6a3e9c68
1 /* libSoX NIST Sphere file format handler.
3 * August 7, 2000
5 * Copyright (C) 2000 Chris Bagwell (cbagwell@sprynet.com)
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15 * General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "sox_i.h"
23 #include <string.h>
25 static int start_read(sox_format_t * ft)
27 unsigned long header_size_ul = 0, num_samples_ul = 0;
28 sox_encoding_t encoding = SOX_ENCODING_SIGN2;
29 size_t header_size, bytes_read;
30 size_t num_samples = 0;
31 unsigned bytes_per_sample = 0;
32 unsigned channels = 1;
33 unsigned rate = 16000;
34 char fldname[64], fldtype[16], fldsval[128];
35 char * buf;
37 /* Magic header */
38 if (lsx_reads(ft, fldname, (size_t)8) || strncmp(fldname, "NIST_1A", (size_t)7) != 0) {
39 lsx_fail_errno(ft, SOX_EHDR, "Sphere header does not begin with magic word `NIST_1A'");
40 return (SOX_EOF);
43 if (lsx_reads(ft, fldsval, (size_t)8)) {
44 lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
45 return (SOX_EOF);
48 /* Determine header size, and allocate a buffer large enough to hold it. */
49 sscanf(fldsval, "%lu", &header_size_ul);
50 buf = lsx_malloc(header_size = header_size_ul);
52 /* Skip what we have read so far */
53 header_size -= 16;
55 if (lsx_reads(ft, buf, header_size) == SOX_EOF) {
56 lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
57 free(buf);
58 return (SOX_EOF);
61 header_size -= (strlen(buf) + 1);
63 while (strncmp(buf, "end_head", (size_t)8) != 0) {
64 if (strncmp(buf, "sample_n_bytes", (size_t)14) == 0)
65 sscanf(buf, "%63s %15s %u", fldname, fldtype, &bytes_per_sample);
66 else if (strncmp(buf, "channel_count", (size_t)13) == 0)
67 sscanf(buf, "%63s %15s %u", fldname, fldtype, &channels);
68 else if (strncmp(buf, "sample_count ", (size_t)13) == 0)
69 sscanf(buf, "%53s %15s %lu", fldname, fldtype, &num_samples_ul);
70 else if (strncmp(buf, "sample_rate ", (size_t)12) == 0)
71 sscanf(buf, "%53s %15s %u", fldname, fldtype, &rate);
72 else if (strncmp(buf, "sample_coding", (size_t)13) == 0) {
73 sscanf(buf, "%63s %15s %127s", fldname, fldtype, fldsval);
74 if (!strcasecmp(fldsval, "ulaw") || !strcasecmp(fldsval, "mu-law"))
75 encoding = SOX_ENCODING_ULAW;
76 else if (!strcasecmp(fldsval, "pcm"))
77 encoding = SOX_ENCODING_SIGN2;
78 else {
79 lsx_fail_errno(ft, SOX_EFMT, "sph: unsupported coding `%s'", fldsval);
80 free(buf);
81 return SOX_EOF;
84 else if (strncmp(buf, "sample_byte_format", (size_t)18) == 0) {
85 sscanf(buf, "%53s %15s %127s", fldname, fldtype, fldsval);
86 if (strcmp(fldsval, "01") == 0) /* Data is little endian. */
87 ft->encoding.reverse_bytes = MACHINE_IS_BIGENDIAN;
88 else if (strcmp(fldsval, "10") == 0) /* Data is big endian. */
89 ft->encoding.reverse_bytes = MACHINE_IS_LITTLEENDIAN;
90 else if (strcmp(fldsval, "1")) {
91 lsx_fail_errno(ft, SOX_EFMT, "sph: unsupported coding `%s'", fldsval);
92 free(buf);
93 return SOX_EOF;
97 if (lsx_reads(ft, buf, header_size) == SOX_EOF) {
98 lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
99 free(buf);
100 return (SOX_EOF);
103 header_size -= (strlen(buf) + 1);
106 if (!bytes_per_sample)
107 bytes_per_sample = encoding == SOX_ENCODING_ULAW? 1 : 2;
109 while (header_size) {
110 bytes_read = lsx_readbuf(ft, buf, header_size);
111 if (bytes_read == 0) {
112 free(buf);
113 return (SOX_EOF);
115 header_size -= bytes_read;
117 free(buf);
119 if (ft->seekable) {
120 /* Check first four bytes of data to see if it's shorten compressed. */
121 char shorten_check[4];
123 if (lsx_readchars(ft, shorten_check, sizeof(shorten_check)))
124 return SOX_EOF;
125 lsx_seeki(ft, -(off_t)sizeof(shorten_check), SEEK_CUR);
127 if (!memcmp(shorten_check, "ajkg", sizeof(shorten_check))) {
128 lsx_fail_errno(ft, SOX_EFMT,
129 "File uses shorten compression, cannot handle this.");
130 return (SOX_EOF);
134 num_samples = num_samples_ul;
135 return lsx_check_read_params(ft, channels, (sox_rate_t)rate, encoding,
136 bytes_per_sample << 3, (uint64_t)num_samples * channels, sox_true);
139 static int write_header(sox_format_t * ft)
141 char buf[128];
142 uint64_t samples = (ft->olength ? ft->olength : ft->signal.length) / ft->signal.channels;
144 lsx_writes(ft, "NIST_1A\n");
145 lsx_writes(ft, " 1024\n");
147 if (samples) {
148 sprintf(buf, "sample_count -i %" PRIu64 "\n", samples);
149 lsx_writes(ft, buf);
152 sprintf(buf, "sample_n_bytes -i %d\n", ft->encoding.bits_per_sample >> 3);
153 lsx_writes(ft, buf);
155 sprintf(buf, "channel_count -i %d\n", ft->signal.channels);
156 lsx_writes(ft, buf);
158 if (ft->encoding.bits_per_sample == 8)
159 sprintf(buf, "sample_byte_format -s1 1\n");
160 else
161 sprintf(buf, "sample_byte_format -s2 %s\n",
162 ft->encoding.reverse_bytes != MACHINE_IS_BIGENDIAN ? "10" : "01");
163 lsx_writes(ft, buf);
165 sprintf(buf, "sample_rate -i %u\n", (unsigned) (ft->signal.rate + .5));
166 lsx_writes(ft, buf);
168 if (ft->encoding.encoding == SOX_ENCODING_ULAW)
169 lsx_writes(ft, "sample_coding -s4 ulaw\n");
170 else
171 lsx_writes(ft, "sample_coding -s3 pcm\n");
173 lsx_writes(ft, "end_head\n");
175 lsx_padbytes(ft, 1024 - (size_t)lsx_tell(ft));
176 return SOX_SUCCESS;
179 LSX_FORMAT_HANDLER(sphere)
181 static char const *const names[] = {"sph", "nist", NULL};
182 static unsigned const write_encodings[] = {
183 SOX_ENCODING_SIGN2, 8, 16, 24, 32, 0,
184 SOX_ENCODING_ULAW, 8, 0,
187 static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
188 "SPeech HEader Resources; defined by NIST", names, SOX_FILE_REWIND,
189 start_read, lsx_rawread, NULL,
190 write_header, lsx_rawwrite, NULL,
191 lsx_rawseek, write_encodings, NULL, 0
193 return &handler;