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