comparison Code/Descriptors/yin/private/sf_format.m @ 0:ea0c737c6323

first commit
author Dawn Black <dawn.black@eecs.qmul.ac.uk>
date Thu, 26 Jul 2012 14:46:25 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:ea0c737c6323
1 function i = sf_format(i)
2 % i=sf_format(i) - try to guess file format from
3 % magic words or file suffix
4
5 % Alain de Cheveigné, CNRS/Ircam, 2002.
6 % Copyright (c) 2002 Centre National de la Recherche Scientifique.
7 %
8 % Permission to use, copy, modify, and distribute this software without
9 % fee is hereby granted FOR RESEARCH PURPOSES only, provided that this
10 % copyright notice appears in all copies and in all supporting
11 % documentation, and that the software is not redistributed for any
12 % fee (except for a nominal shipping charge).
13 %
14 % For any other uses of this software, in original or modified form,
15 % including but not limited to consulting, production or distribution
16 % in whole or in part, specific prior permission must be obtained from CNRS.
17 % Algorithms implemented by this software may be claimed by patents owned
18 % by CNRS, France Telecom, Ircam or others.
19 %
20 % The CNRS makes no representations about the suitability of this
21 % software for any purpose. It is provided "as is" without express
22 % or implied warranty. Beware of the bugs.
23
24 if ~nargin; error('no argument'); end
25 if ~isa(i, 'struct')
26 i.fname=i;
27 i=sf_format(i);
28 return
29 end
30 if ~isfield(i, 'fname'); error('no fname field'); end
31
32 if isa(i.fname, 'double')
33 i.format = 'matrix'; return
34 end
35
36 if isa(i.fname, 'char')
37 disp(['guessing format of ', i.fname, '...']);
38 else
39 disp('guessing format...');
40 end
41
42 % Well-known file extensions
43 a = findstr('.', i.fname);
44 if a
45 suff = i.fname( a(size(a,2))+1 : size(i.fname,2));
46 suff = lower(suff);
47 switch suff
48 case {'short', 'long', 'float', 'double', 'ascii', 'mat'}
49 i.format = suff;
50 return
51 % the following are commented out to exercise header magic
52 % case {'aiff'}
53 % i.format = 'AIFF';
54 % return
55 % case {'aifc'}
56 % i.format = 'AIFC';
57 % return
58 % case 'wav'
59 % i.format = 'WAV';
60 % return
61 % case 'au'
62 % i.format = 'AU';
63 % case 'sdif'
64 % i.format = 'sdif';
65 % others ?
66 end
67 end
68
69 % close file if open
70 if exist('i.fd') & fopen(i.fd)
71 fclose(i.fd);
72 end
73
74
75 % open little-endian, check for .wav magic
76 [i.fd, msg] = fopen(i.fname, 'r', 'l');
77 if i.fd == -1
78 error(['could not open: >', i.fname, '<']);
79 if ~isempty(msg)
80 error(msg);
81 end
82 end
83
84 % file size in bytes
85 if (-1 == fseek(i.fd, 0, 1)) ; error ('fseek failed'); end;
86 i.nbytes = ftell(i.fd);
87 if i.nbytes == 0 & strcmp(computer, 'MAC2')
88 disp('file is empty: perhaps its a macintosh SND resource?');
89 i.format = 'MACSND'; % macintosh sound resource (maybe...)
90 return
91 end
92 if i.nbytes < 4; error('file is less than 4 bytes long'); end;
93 fseek(i.fd, 0, -1);
94 magic = char(fread(i.fd, 4, 'uchar'))';
95 if strcmp(magic, 'RIFF') & i.nbytes >=12
96 dummy = fread(i.fd, 1, 'ulong'); % chunk size
97 magic = char(fread(i.fd, 4, 'uchar'))';
98 if strcmp(magic, 'WAVE');
99 i.format='WAV';
100 return
101 end
102 end
103
104 % reopen for standard binary, look for magic
105 fclose(i.fd);
106 i.fd = fopen(i.fname, 'r');
107 if (-1 == fseek(i.fd, 0, 1)) ; error ('fseek failed'); end;
108 i.nbytes = ftell(i.fd);
109 fseek(i.fd, 0, -1);
110 % magic strings?
111 magic = char(fread(i.fd, 4, 'uchar'))';
112 switch magic
113 case '.snd'
114 i.format = 'AU';
115 return;
116 case 'FORM'
117 fseek(i.fd, 8, -1);
118 i.format = char(fread(i.fd, 4, 'uchar'))';
119 if ~strcmp(i.format, 'AIFF') & ~strcmp(char(i.format),'AIFC')
120 error (['expected AIFF or AIFC, found ' i.format]);
121 end;
122 return;
123 case 'NIST'
124 fseek(i.fd, 0, -1);
125 line = fscanf(i.fd, '%s' , 1);
126 if ~strcmp(line, 'NIST_1A');
127 error(['expected NIST_1A, found ', magic]);
128 end;
129 disp(i.format);
130 return;
131 case 'SDIF'
132 i.format = 'SDIF';
133 return;
134 end
135 % wff magic number?
136 wff_magic = 195894762;
137 fseek(i.fd, 0, -1);
138 magic = fread(i.fd, 1, 'long');
139 if magic == wff_magic
140 i.format = 'wff'; % Nottingham IHR wff format
141 return
142 end
143 % ESPS?
144 esps_min_size = 333; esps_magic = 27162;
145 if i.nbytes > esps_min_size
146 fseek(i.fd, 16, -1);
147 magic = fread(i.fd, 1, 'uint');
148 if magic == esps_magic
149 i.format = 'ESPS';
150 return
151 end
152 end
153
154
155 % Magic didn't succeed, try to determine type based on file name
156 a = findstr('.', i.fname);
157 if a
158 suff = i.fname( a(size(a,2))+1 : size(i.fname,2));
159 switch suff
160 case 's'
161 i.format = 'short';
162 return
163 case 'f'
164 i.format = 'float';
165 return
166 % others ?
167 end
168 end
169
170
171 % Ascii formats
172 fclose(i.fd);
173 i.fd = fopen(i.fname, 'rt');
174 line = fscanf(i.fd, '%s' , 1);
175 if strcmp(line, '|WAVE');
176 i.format = 'iwave'; % Nottingham IHR |WAVE format
177 return;
178 end
179
180 % plain ascii ?
181 limit = 2048; % test only this many bytes
182 hunk = char(fread(i.fd, min(limit, i.nbytes)));
183 chars = unique(hunk);
184 if isempty(setdiff(chars, [9, 10, 13, ...
185 double(' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-_.,:;')]))
186 % ascii
187 if ~isempty(setdiff(chars, [9, 10, 13, double(' 1234567890eE+-.,')]))
188 % not just numerical: try removing first line
189 fseek(i.fd, 0, -1);
190 line = fgets(i.fd);
191 if -1 == line; return ; end % line too long
192 i.bytes_to_data = ftell(i.fd);
193 hunk = char(fread(i.fd, min(limit, i.nbytes-ftell(i.fd))));
194 chars = unique(hunk);
195 warning('skipping first line of what seems like an ascii file');
196 end
197 if isempty(setdiff(chars, [9, 10, 13, double(' 1234567890eE+-.')]))
198 i.format = 'ascii';
199 return
200 end
201 if isempty(setdiff(chars, [9, 10, 13, double(' 1234567890eE+-.,')]))
202 w.format = 'csv';
203 return
204 end
205 end
206
207 % Default
208 if i.nbytes == 2 * round(i.nbytes/2); % even number of bytes
209 i.format = 'short';
210 else
211 i.format = 'uchar';
212 end
213