/src/libsndfile/src/mat5.c
Line | Count | Source |
1 | | /* |
2 | | ** Copyright (C) 2002-2017 Erik de Castro Lopo <erikd@mega-nerd.com> |
3 | | ** |
4 | | ** This program is free software; you can redistribute it and/or modify |
5 | | ** it under the terms of the GNU Lesser General Public License as published by |
6 | | ** the Free Software Foundation; either version 2.1 of the License, or |
7 | | ** (at your option) any later version. |
8 | | ** |
9 | | ** This program is distributed in the hope that it will be useful, |
10 | | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | ** GNU Lesser General Public License for more details. |
13 | | ** |
14 | | ** You should have received a copy of the GNU Lesser General Public License |
15 | | ** along with this program; if not, write to the Free Software |
16 | | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | | */ |
18 | | |
19 | | #include "sfconfig.h" |
20 | | |
21 | | #include <stdio.h> |
22 | | #include <fcntl.h> |
23 | | #include <string.h> |
24 | | #include <ctype.h> |
25 | | #include <math.h> |
26 | | |
27 | | #include "sndfile.h" |
28 | | #include "sfendian.h" |
29 | | #include "common.h" |
30 | | |
31 | | /*------------------------------------------------------------------------------ |
32 | | ** Information on how to decode and encode this file was obtained in a PDF |
33 | | ** file which I found on http://www.wotsit.org/. |
34 | | ** Also did a lot of testing with GNU Octave but do not have access to |
35 | | ** Matlab (tm) and so could not test it there. |
36 | | */ |
37 | | |
38 | | /*------------------------------------------------------------------------------ |
39 | | ** Macros to handle big/little endian issues. |
40 | | */ |
41 | | |
42 | | #define MATL_MARKER (MAKE_MARKER ('M', 'A', 'T', 'L')) |
43 | | |
44 | 503 | #define IM_MARKER (('I' << 8) + 'M') |
45 | 260 | #define MI_MARKER (('M' << 8) + 'I') |
46 | | |
47 | | /*------------------------------------------------------------------------------ |
48 | | ** Enums and typedefs. |
49 | | */ |
50 | | |
51 | | enum |
52 | | { MAT5_TYPE_SCHAR = 0x1, |
53 | | MAT5_TYPE_UCHAR = 0x2, |
54 | | MAT5_TYPE_INT16 = 0x3, |
55 | | MAT5_TYPE_UINT16 = 0x4, |
56 | | MAT5_TYPE_INT32 = 0x5, |
57 | | MAT5_TYPE_UINT32 = 0x6, |
58 | | MAT5_TYPE_FLOAT = 0x7, |
59 | | MAT5_TYPE_DOUBLE = 0x9, |
60 | | MAT5_TYPE_ARRAY = 0xE, |
61 | | |
62 | | MAT5_TYPE_COMP_USHORT = 0x00020004, |
63 | | MAT5_TYPE_COMP_UINT = 0x00040006 |
64 | | } ; |
65 | | |
66 | | typedef struct |
67 | | { sf_count_t size ; |
68 | | int rows, cols ; |
69 | | char name [32] ; |
70 | | } MAT5_MATRIX ; |
71 | | |
72 | | /*------------------------------------------------------------------------------ |
73 | | ** Private static functions. |
74 | | */ |
75 | | |
76 | | static int mat5_close (SF_PRIVATE *psf) ; |
77 | | |
78 | | static int mat5_write_header (SF_PRIVATE *psf, int calc_length) ; |
79 | | static int mat5_read_header (SF_PRIVATE *psf) ; |
80 | | |
81 | | /*------------------------------------------------------------------------------ |
82 | | ** Public function. |
83 | | */ |
84 | | |
85 | | int |
86 | | mat5_open (SF_PRIVATE *psf) |
87 | 261 | { int subformat, error = 0 ; |
88 | | |
89 | 261 | if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0)) |
90 | 261 | { if ((error = mat5_read_header (psf))) |
91 | 237 | return error ; |
92 | 261 | } ; |
93 | | |
94 | 24 | if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_MAT5) |
95 | 0 | return SFE_BAD_OPEN_FORMAT ; |
96 | | |
97 | 24 | subformat = SF_CODEC (psf->sf.format) ; |
98 | | |
99 | 24 | if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) |
100 | 0 | { if (psf->is_pipe) |
101 | 0 | return SFE_NO_PIPE_WRITE ; |
102 | | |
103 | 0 | psf->endian = SF_ENDIAN (psf->sf.format) ; |
104 | 0 | if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) |
105 | 0 | psf->endian = SF_ENDIAN_LITTLE ; |
106 | 0 | else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) |
107 | 0 | psf->endian = SF_ENDIAN_BIG ; |
108 | |
|
109 | 0 | if ((error = mat5_write_header (psf, SF_FALSE))) |
110 | 0 | return error ; |
111 | | |
112 | 0 | psf->write_header = mat5_write_header ; |
113 | 24 | } ; |
114 | | |
115 | 24 | psf->container_close = mat5_close ; |
116 | | |
117 | 24 | psf->blockwidth = (sf_count_t) psf->bytewidth * psf->sf.channels ; |
118 | | |
119 | 24 | switch (subformat) |
120 | 24 | { case SF_FORMAT_PCM_U8 : |
121 | 2 | case SF_FORMAT_PCM_16 : |
122 | 3 | case SF_FORMAT_PCM_32 : |
123 | 3 | error = pcm_init (psf) ; |
124 | 3 | break ; |
125 | | |
126 | 5 | case SF_FORMAT_FLOAT : |
127 | 5 | error = float32_init (psf) ; |
128 | 5 | break ; |
129 | | |
130 | 16 | case SF_FORMAT_DOUBLE : |
131 | 16 | error = double64_init (psf) ; |
132 | 16 | break ; |
133 | | |
134 | 0 | default : break ; |
135 | 24 | } ; |
136 | | |
137 | 24 | return error ; |
138 | 24 | } /* mat5_open */ |
139 | | |
140 | | /*------------------------------------------------------------------------------ |
141 | | */ |
142 | | |
143 | | static int |
144 | | mat5_close (SF_PRIVATE *psf) |
145 | 24 | { |
146 | 24 | if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) |
147 | 0 | mat5_write_header (psf, SF_TRUE) ; |
148 | | |
149 | 24 | return 0 ; |
150 | 24 | } /* mat5_close */ |
151 | | |
152 | | /*------------------------------------------------------------------------------ |
153 | | */ |
154 | | |
155 | | static int |
156 | | mat5_write_header (SF_PRIVATE *psf, int calc_length) |
157 | 0 | { static const char *filename = "MATLAB 5.0 MAT-file, written by " PACKAGE_NAME "-" PACKAGE_VERSION ", " ; |
158 | 0 | static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ; |
159 | 0 | static const char *wd_name = "wavedata\0" ; |
160 | 0 | char buffer [256] ; |
161 | 0 | sf_count_t current, datasize ; |
162 | 0 | int encoding ; |
163 | |
|
164 | 0 | current = psf_ftell (psf) ; |
165 | |
|
166 | 0 | if (calc_length) |
167 | 0 | { psf_fseek (psf, 0, SEEK_END) ; |
168 | 0 | psf->filelength = psf_ftell (psf) ; |
169 | 0 | psf_fseek (psf, 0, SEEK_SET) ; |
170 | |
|
171 | 0 | psf->datalength = psf->filelength - psf->dataoffset ; |
172 | 0 | if (psf->dataend) |
173 | 0 | psf->datalength -= psf->filelength - psf->dataend ; |
174 | |
|
175 | 0 | psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; |
176 | 0 | } ; |
177 | |
|
178 | 0 | switch (SF_CODEC (psf->sf.format)) |
179 | 0 | { case SF_FORMAT_PCM_U8 : |
180 | 0 | encoding = MAT5_TYPE_UCHAR ; |
181 | 0 | break ; |
182 | | |
183 | 0 | case SF_FORMAT_PCM_16 : |
184 | 0 | encoding = MAT5_TYPE_INT16 ; |
185 | 0 | break ; |
186 | | |
187 | 0 | case SF_FORMAT_PCM_32 : |
188 | 0 | encoding = MAT5_TYPE_INT32 ; |
189 | 0 | break ; |
190 | | |
191 | 0 | case SF_FORMAT_FLOAT : |
192 | 0 | encoding = MAT5_TYPE_FLOAT ; |
193 | 0 | break ; |
194 | | |
195 | 0 | case SF_FORMAT_DOUBLE : |
196 | 0 | encoding = MAT5_TYPE_DOUBLE ; |
197 | 0 | break ; |
198 | | |
199 | 0 | default : |
200 | 0 | return SFE_BAD_OPEN_FORMAT ; |
201 | 0 | } ; |
202 | | |
203 | | /* Reset the current header length to zero. */ |
204 | 0 | psf->header.ptr [0] = 0 ; |
205 | 0 | psf->header.indx = 0 ; |
206 | 0 | psf_fseek (psf, 0, SEEK_SET) ; |
207 | |
|
208 | 0 | psf_get_date_str (buffer, sizeof (buffer)) ; |
209 | 0 | psf_binheader_writef (psf, "bb", BHWv (filename), BHWz (strlen (filename)), BHWv (buffer), BHWz (strlen (buffer) + 1)) ; |
210 | |
|
211 | 0 | memset (buffer, ' ', 124 - psf->header.indx) ; |
212 | 0 | psf_binheader_writef (psf, "b", BHWv (buffer), BHWz (124 - psf->header.indx)) ; |
213 | |
|
214 | 0 | psf->rwf_endian = psf->endian ; |
215 | |
|
216 | 0 | if (psf->rwf_endian == SF_ENDIAN_BIG) |
217 | 0 | psf_binheader_writef (psf, "2b", BHW2 (0x0100), BHWv ("MI"), BHWz (2)) ; |
218 | 0 | else |
219 | 0 | psf_binheader_writef (psf, "2b", BHW2 (0x0100), BHWv ("IM"), BHWz (2)) ; |
220 | |
|
221 | 0 | psf_binheader_writef (psf, "444444", BHW4 (MAT5_TYPE_ARRAY), BHW4 (64), BHW4 (MAT5_TYPE_UINT32), BHW4 (8), BHW4 (6), BHW4 (0)) ; |
222 | 0 | psf_binheader_writef (psf, "4444", BHW4 (MAT5_TYPE_INT32), BHW4 (8), BHW4 (1), BHW4 (1)) ; |
223 | 0 | psf_binheader_writef (psf, "44b", BHW4 (MAT5_TYPE_SCHAR), BHW4 (strlen (sr_name)), BHWv (sr_name), BHWz (16)) ; |
224 | |
|
225 | 0 | if (psf->sf.samplerate > 0xFFFF) |
226 | 0 | psf_binheader_writef (psf, "44", BHW4 (MAT5_TYPE_COMP_UINT), BHW4 (psf->sf.samplerate)) ; |
227 | 0 | else |
228 | 0 | { unsigned short samplerate = psf->sf.samplerate ; |
229 | |
|
230 | 0 | psf_binheader_writef (psf, "422", BHW4 (MAT5_TYPE_COMP_USHORT), BHW2 (samplerate), BHW2 (0)) ; |
231 | 0 | } ; |
232 | |
|
233 | 0 | datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; |
234 | |
|
235 | 0 | psf_binheader_writef (psf, "t484444", BHW4 (MAT5_TYPE_ARRAY), BHW8 (datasize + 64), BHW4 (MAT5_TYPE_UINT32), BHW4 (8), BHW4 (6), BHW4 (0)) ; |
236 | 0 | psf_binheader_writef (psf, "t4448", BHW4 (MAT5_TYPE_INT32), BHW4 (8), BHW4 (psf->sf.channels), BHW8 (psf->sf.frames)) ; |
237 | 0 | psf_binheader_writef (psf, "44b", BHW4 (MAT5_TYPE_SCHAR), BHW4 (strlen (wd_name)), BHWv (wd_name), BHWz (strlen (wd_name))) ; |
238 | |
|
239 | 0 | datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; |
240 | 0 | if (datasize > 0x7FFFFFFF) |
241 | 0 | datasize = 0x7FFFFFFF ; |
242 | |
|
243 | 0 | psf_binheader_writef (psf, "t48", BHW4 (encoding), BHW8 (datasize)) ; |
244 | | |
245 | | /* Header construction complete so write it out. */ |
246 | 0 | psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; |
247 | |
|
248 | 0 | if (psf->error) |
249 | 0 | return psf->error ; |
250 | | |
251 | 0 | psf->dataoffset = psf->header.indx ; |
252 | |
|
253 | 0 | if (current > 0) |
254 | 0 | psf_fseek (psf, current, SEEK_SET) ; |
255 | |
|
256 | 0 | return psf->error ; |
257 | 0 | } /* mat5_write_header */ |
258 | | |
259 | | static int |
260 | | mat5_read_header (SF_PRIVATE *psf) |
261 | 261 | { char buffer [256], name [32] ; |
262 | 261 | short version, endian ; |
263 | 261 | int type, flags1, flags2, rows, cols ; |
264 | 261 | unsigned size ; |
265 | 261 | int have_samplerate = 1 ; |
266 | | |
267 | 261 | psf_binheader_readf (psf, "pb", 0, buffer, 124) ; |
268 | | |
269 | 261 | buffer [125] = 0 ; |
270 | | |
271 | 261 | if (strlen (buffer) >= 124) |
272 | 1 | return SFE_UNIMPLEMENTED ; |
273 | | |
274 | 260 | if (strstr (buffer, "MATLAB 5.0 MAT-file") == buffer) |
275 | 4 | psf_log_printf (psf, "%s\n", buffer) ; |
276 | | |
277 | | |
278 | 260 | psf_binheader_readf (psf, "E22", &version, &endian) ; |
279 | | |
280 | 260 | if (endian == MI_MARKER) |
281 | 1 | { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; |
282 | 1 | if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_16 (version) ; |
283 | 1 | } |
284 | 259 | else if (endian == IM_MARKER) |
285 | 243 | { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; |
286 | 243 | if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_16 (version) ; |
287 | 243 | } |
288 | 16 | else |
289 | 16 | return SFE_MAT5_BAD_ENDIAN ; |
290 | | |
291 | 244 | if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) || |
292 | 0 | (CPU_IS_BIG_ENDIAN && endian == MI_MARKER)) |
293 | 243 | version = ENDSWAP_16 (version) ; |
294 | | |
295 | 244 | psf_log_printf (psf, "Version : 0x%04X\n", version) ; |
296 | 244 | psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian, |
297 | 244 | (psf->endian == SF_ENDIAN_LITTLE) ? "Little" : "Big") ; |
298 | | |
299 | | /*========================================================*/ |
300 | 244 | psf_binheader_readf (psf, "44", &type, &size) ; |
301 | 244 | psf_log_printf (psf, "Block\n Type : %X Size : %d\n", type, size) ; |
302 | | |
303 | 244 | if (type != MAT5_TYPE_ARRAY) |
304 | 2 | return SFE_MAT5_NO_BLOCK ; |
305 | | |
306 | 242 | psf_binheader_readf (psf, "44", &type, &size) ; |
307 | 242 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
308 | | |
309 | 242 | if (type != MAT5_TYPE_UINT32) |
310 | 31 | return SFE_MAT5_NO_BLOCK ; |
311 | | |
312 | 211 | psf_binheader_readf (psf, "44", &flags1, &flags2) ; |
313 | 211 | psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; |
314 | | |
315 | 211 | psf_binheader_readf (psf, "44", &type, &size) ; |
316 | 211 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
317 | | |
318 | 211 | if (type != MAT5_TYPE_INT32) |
319 | 1 | return SFE_MAT5_NO_BLOCK ; |
320 | | |
321 | 210 | psf_binheader_readf (psf, "44", &rows, &cols) ; |
322 | 210 | psf_log_printf (psf, " Rows : %d Cols : %d\n", rows, cols) ; |
323 | | |
324 | 210 | if (rows != 1 || cols != 1) |
325 | 133 | { if (psf->sf.samplerate == 0) |
326 | 133 | psf->sf.samplerate = 44100 ; |
327 | 133 | have_samplerate = 0 ; |
328 | 133 | } |
329 | 210 | psf_binheader_readf (psf, "4", &type) ; |
330 | | |
331 | 210 | if (type == MAT5_TYPE_SCHAR) |
332 | 41 | { psf_binheader_readf (psf, "4", &size) ; |
333 | 41 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
334 | 41 | if (size > SIGNED_SIZEOF (name) - 1) |
335 | 32 | { psf_log_printf (psf, "Error : Bad name length.\n") ; |
336 | 32 | return SFE_MAT5_NO_BLOCK ; |
337 | 32 | } ; |
338 | | |
339 | 9 | psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; |
340 | 9 | name [size] = 0 ; |
341 | 9 | } |
342 | 169 | else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) |
343 | 112 | { size = type >> 16 ; |
344 | 112 | if (size > 4) |
345 | 5 | { psf_log_printf (psf, "Error : Bad name length.\n") ; |
346 | 5 | return SFE_MAT5_NO_BLOCK ; |
347 | 107 | } ; |
348 | | |
349 | 107 | psf_log_printf (psf, " Type : %X\n", type) ; |
350 | 107 | psf_binheader_readf (psf, "4", &name) ; |
351 | 107 | name [size] = 0 ; |
352 | 107 | } |
353 | 57 | else |
354 | 57 | return SFE_MAT5_NO_BLOCK ; |
355 | | |
356 | 116 | psf_log_printf (psf, " Name : %s\n", name) ; |
357 | | |
358 | | /*-----------------------------------------*/ |
359 | | |
360 | 116 | psf_binheader_readf (psf, "44", &type, &size) ; |
361 | | |
362 | 116 | if (!have_samplerate) |
363 | 49 | goto skip_samplerate ; |
364 | | |
365 | 67 | switch (type) |
366 | 67 | { case MAT5_TYPE_DOUBLE : |
367 | 1 | { double samplerate ; |
368 | | |
369 | 1 | psf_binheader_readf (psf, "d", &samplerate) ; |
370 | 1 | snprintf (name, sizeof (name), "%f\n", samplerate) ; |
371 | 1 | psf_log_printf (psf, " Val : %s\n", name) ; |
372 | | |
373 | 1 | psf->sf.samplerate = psf_lrint (samplerate) ; |
374 | 1 | } ; |
375 | 1 | break ; |
376 | | |
377 | 61 | case MAT5_TYPE_COMP_USHORT : |
378 | 61 | { unsigned short samplerate ; |
379 | | |
380 | 61 | psf_binheader_readf (psf, "j2j", -4, &samplerate, 2) ; |
381 | 61 | psf_log_printf (psf, " Val : %u\n", samplerate) ; |
382 | 61 | psf->sf.samplerate = samplerate ; |
383 | 61 | } |
384 | 61 | break ; |
385 | | |
386 | 1 | case MAT5_TYPE_COMP_UINT : |
387 | 1 | psf_log_printf (psf, " Val : %u\n", size) ; |
388 | 1 | psf->sf.samplerate = size ; |
389 | 1 | break ; |
390 | | |
391 | 4 | default : |
392 | 4 | psf_log_printf (psf, " Type : %X Size : %d ***\n", type, size) ; |
393 | 4 | return SFE_MAT5_SAMPLE_RATE ; |
394 | 67 | } ; |
395 | | |
396 | | /*-----------------------------------------*/ |
397 | | |
398 | | |
399 | 63 | psf_binheader_readf (psf, "44", &type, &size) ; |
400 | 63 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
401 | | |
402 | 63 | if (type != MAT5_TYPE_ARRAY) |
403 | 3 | return SFE_MAT5_NO_BLOCK ; |
404 | | |
405 | 60 | psf_binheader_readf (psf, "44", &type, &size) ; |
406 | 60 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
407 | | |
408 | 60 | if (type != MAT5_TYPE_UINT32) |
409 | 5 | return SFE_MAT5_NO_BLOCK ; |
410 | | |
411 | 55 | psf_binheader_readf (psf, "44", &flags1, &flags2) ; |
412 | 55 | psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; |
413 | | |
414 | 55 | psf_binheader_readf (psf, "44", &type, &size) ; |
415 | 55 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
416 | | |
417 | 55 | if (type != MAT5_TYPE_INT32) |
418 | 38 | return SFE_MAT5_NO_BLOCK ; |
419 | | |
420 | 17 | psf_binheader_readf (psf, "44", &rows, &cols) ; |
421 | 17 | psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ; |
422 | | |
423 | 17 | psf_binheader_readf (psf, "4", &type) ; |
424 | | |
425 | 17 | if (type == MAT5_TYPE_SCHAR) |
426 | 14 | { psf_binheader_readf (psf, "4", &size) ; |
427 | 14 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
428 | 14 | if (size > SIGNED_SIZEOF (name) - 1) |
429 | 8 | { psf_log_printf (psf, "Error : Bad name length.\n") ; |
430 | 8 | return SFE_MAT5_NO_BLOCK ; |
431 | 8 | } ; |
432 | | |
433 | 6 | psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; |
434 | 6 | name [size] = 0 ; |
435 | 6 | } |
436 | 3 | else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) |
437 | 2 | { size = type >> 16 ; |
438 | 2 | if (size > 4) |
439 | 1 | { psf_log_printf (psf, "Error : Bad name length.\n") ; |
440 | 1 | return SFE_MAT5_NO_BLOCK ; |
441 | 1 | } ; |
442 | | |
443 | 1 | psf_log_printf (psf, " Type : %X\n", type) ; |
444 | 1 | psf_binheader_readf (psf, "4", &name) ; |
445 | 1 | name [size] = 0 ; |
446 | 1 | } |
447 | 1 | else |
448 | 1 | return SFE_MAT5_NO_BLOCK ; |
449 | | |
450 | 7 | psf_log_printf (psf, " Name : %s\n", name) ; |
451 | | |
452 | 7 | psf_binheader_readf (psf, "44", &type, &size) ; |
453 | 7 | psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; |
454 | | |
455 | 56 | skip_samplerate : |
456 | | /*++++++++++++++++++++++++++++++++++++++++++++++++++*/ |
457 | | |
458 | 56 | if (rows == 0 && cols == 0) |
459 | 1 | { psf_log_printf (psf, "*** Error : zero channel count.\n") ; |
460 | 1 | return SFE_CHANNEL_COUNT_ZERO ; |
461 | 55 | } ; |
462 | | |
463 | 55 | psf->sf.channels = rows ; |
464 | 55 | psf->sf.frames = cols ; |
465 | | |
466 | 55 | psf->sf.format = psf->endian | SF_FORMAT_MAT5 ; |
467 | | |
468 | 55 | switch (type) |
469 | 55 | { case MAT5_TYPE_DOUBLE : |
470 | 16 | psf_log_printf (psf, "Data type : double\n") ; |
471 | 16 | psf->sf.format |= SF_FORMAT_DOUBLE ; |
472 | 16 | psf->bytewidth = 8 ; |
473 | 16 | break ; |
474 | | |
475 | 5 | case MAT5_TYPE_FLOAT : |
476 | 5 | psf_log_printf (psf, "Data type : float\n") ; |
477 | 5 | psf->sf.format |= SF_FORMAT_FLOAT ; |
478 | 5 | psf->bytewidth = 4 ; |
479 | 5 | break ; |
480 | | |
481 | 1 | case MAT5_TYPE_INT32 : |
482 | 1 | psf_log_printf (psf, "Data type : 32 bit PCM\n") ; |
483 | 1 | psf->sf.format |= SF_FORMAT_PCM_32 ; |
484 | 1 | psf->bytewidth = 4 ; |
485 | 1 | break ; |
486 | | |
487 | 1 | case MAT5_TYPE_INT16 : |
488 | 1 | psf_log_printf (psf, "Data type : 16 bit PCM\n") ; |
489 | 1 | psf->sf.format |= SF_FORMAT_PCM_16 ; |
490 | 1 | psf->bytewidth = 2 ; |
491 | 1 | break ; |
492 | | |
493 | 1 | case MAT5_TYPE_UCHAR : |
494 | 1 | psf_log_printf (psf, "Data type : unsigned 8 bit PCM\n") ; |
495 | 1 | psf->sf.format |= SF_FORMAT_PCM_U8 ; |
496 | 1 | psf->bytewidth = 1 ; |
497 | 1 | break ; |
498 | | |
499 | 31 | default : |
500 | 31 | psf_log_printf (psf, "*** Error : Bad marker %08X\n", type) ; |
501 | 31 | return SFE_UNIMPLEMENTED ; |
502 | 55 | } ; |
503 | | |
504 | 24 | psf->dataoffset = psf_ftell (psf) ; |
505 | 24 | psf->datalength = psf->filelength - psf->dataoffset ; |
506 | | |
507 | 24 | return 0 ; |
508 | 55 | } /* mat5_read_header */ |
509 | | |