diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Code/Descriptors/yin/private/sf_format.m	Thu Jul 26 14:46:25 2012 +0100
@@ -0,0 +1,213 @@
+function i = sf_format(i)
+% i=sf_format(i) - try to guess file format from 
+% magic words or file suffix
+
+% Alain de Cheveigné, CNRS/Ircam, 2002.
+% Copyright (c) 2002 Centre National de la Recherche Scientifique.
+%
+% Permission to use, copy, modify, and distribute this software without 
+% fee is hereby granted FOR RESEARCH PURPOSES only, provided that this
+% copyright notice appears in all copies and in all supporting 
+% documentation, and that the software is not redistributed for any 
+% fee (except for a nominal shipping charge). 
+%
+% For any other uses of this software, in original or modified form, 
+% including but not limited to consulting, production or distribution
+% in whole or in part, specific prior permission must be obtained from CNRS.
+% Algorithms implemented by this software may be claimed by patents owned 
+% by CNRS, France Telecom, Ircam or others.
+%
+% The CNRS makes no representations about the suitability of this 
+% software for any purpose.  It is provided "as is" without express
+% or implied warranty.  Beware of the bugs.
+
+if ~nargin; error('no argument'); end
+if ~isa(i, 'struct')
+	i.fname=i;
+	i=sf_format(i);
+	return
+end
+if ~isfield(i, 'fname'); error('no fname field'); end
+
+if isa(i.fname, 'double')
+	i.format = 'matrix'; return
+end
+
+if isa(i.fname, 'char')  
+	disp(['guessing format of ', i.fname, '...']);
+else 
+	disp('guessing format...');
+end
+
+% Well-known file extensions
+a = findstr('.', i.fname);
+if a
+	suff = i.fname( a(size(a,2))+1 : size(i.fname,2));
+	suff = lower(suff);
+	switch suff
+	case {'short', 'long', 'float', 'double', 'ascii', 'mat'}
+		i.format = suff;
+		return
+% the following are commented out to exercise header magic
+% 	case {'aiff'}
+% 		i.format = 'AIFF';
+% 		return
+% 	case {'aifc'}
+% 		i.format = 'AIFC';
+% 		return
+% 	case 'wav'
+% 		i.format = 'WAV';
+% 		return
+% 	case 'au'
+% 		i.format = 'AU';
+% 	case 'sdif'
+% 		i.format = 'sdif';
+	% others ?
+	end
+end
+
+% close file if open
+if exist('i.fd') & fopen(i.fd)
+	fclose(i.fd);
+end
+
+
+% open little-endian, check for .wav magic
+[i.fd, msg] = fopen(i.fname, 'r', 'l');
+if i.fd == -1
+	error(['could not open: >', i.fname, '<']);
+	if ~isempty(msg)
+		error(msg);
+	end
+end
+
+% file size in bytes
+if (-1 == fseek(i.fd, 0, 1)) ; error ('fseek failed');  end;	
+i.nbytes = ftell(i.fd);
+if i.nbytes == 0 & strcmp(computer, 'MAC2')
+    disp('file is empty: perhaps its a macintosh SND resource?');
+	i.format = 'MACSND';	% macintosh sound resource (maybe...)
+	return
+end
+if i.nbytes < 4; error('file is less than 4 bytes long'); end;	
+fseek(i.fd, 0, -1);			
+magic = char(fread(i.fd, 4, 'uchar'))';
+if strcmp(magic, 'RIFF') & i.nbytes >=12
+	dummy = fread(i.fd, 1, 'ulong');	% chunk size
+	magic = char(fread(i.fd, 4, 'uchar'))';
+	if strcmp(magic, 'WAVE');
+		i.format='WAV';
+		return
+	end
+end
+
+% reopen for standard binary, look for magic
+fclose(i.fd);
+i.fd = fopen(i.fname, 'r');
+if (-1 == fseek(i.fd, 0, 1)) ; error ('fseek failed');  end;	
+i.nbytes = ftell(i.fd);
+fseek(i.fd, 0, -1);	
+% magic strings?
+magic = char(fread(i.fd, 4, 'uchar'))';
+switch magic
+case '.snd'
+	i.format = 'AU';
+	return;	
+case 'FORM'
+	fseek(i.fd, 8, -1);
+	i.format = char(fread(i.fd, 4, 'uchar'))';
+	if ~strcmp(i.format, 'AIFF') & ~strcmp(char(i.format),'AIFC')
+		error (['expected AIFF or AIFC, found ' i.format]); 
+	end;
+	return;
+case 'NIST'
+	fseek(i.fd, 0, -1);
+	line = fscanf(i.fd, '%s' , 1);
+	if ~strcmp(line, 'NIST_1A'); 
+		error(['expected NIST_1A, found ', magic]); 
+	end;
+	disp(i.format);	
+	return;
+case 'SDIF'
+	i.format = 'SDIF';
+	return;
+end
+% wff magic number?
+wff_magic =  195894762;
+fseek(i.fd, 0, -1);
+magic = fread(i.fd, 1, 'long');
+if magic == wff_magic
+	i.format = 'wff';	% Nottingham IHR wff format
+	return
+end
+% ESPS?
+esps_min_size = 333; esps_magic = 27162;
+if i.nbytes > esps_min_size	
+	fseek(i.fd, 16, -1);
+	magic = fread(i.fd, 1, 'uint');
+	if magic == esps_magic
+		i.format = 'ESPS';
+		return
+	end
+end
+
+
+% Magic didn't succeed, try to determine type based on file name
+a = findstr('.', i.fname);
+if a
+	suff = i.fname( a(size(a,2))+1 : size(i.fname,2));
+	switch suff
+	case 's'
+		i.format = 'short';
+		return
+	case 'f'
+		i.format = 'float';
+		return
+		% others ?
+	end
+end
+
+
+% Ascii formats
+fclose(i.fd);
+i.fd = fopen(i.fname, 'rt');
+line = fscanf(i.fd, '%s' , 1);
+if strcmp(line, '|WAVE'); 
+	i.format = 'iwave';			% Nottingham IHR |WAVE format
+	return;
+end
+
+% plain ascii ?
+limit = 2048;	% test only this many bytes
+hunk = char(fread(i.fd, min(limit, i.nbytes)));
+chars = unique(hunk);
+if isempty(setdiff(chars, [9, 10, 13, ...
+	double(' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-_.,:;')]))
+	% ascii
+	if ~isempty(setdiff(chars, [9, 10, 13, double(' 1234567890eE+-.,')]))
+		% not just numerical: try removing first line
+		fseek(i.fd, 0, -1);
+		line = fgets(i.fd);
+		if -1 == line; return ; end	% line too long 
+		i.bytes_to_data = ftell(i.fd);
+		hunk = char(fread(i.fd, min(limit, i.nbytes-ftell(i.fd))));
+		chars = unique(hunk);
+		warning('skipping first line of what seems like an ascii file');
+	end 
+	if isempty(setdiff(chars, [9, 10, 13, double(' 1234567890eE+-.')]))
+		i.format = 'ascii';
+		return
+	end
+	if isempty(setdiff(chars, [9, 10, 13, double(' 1234567890eE+-.,')]))
+		w.format = 'csv';
+		return
+	end
+end
+
+% Default
+if i.nbytes == 2 * round(i.nbytes/2);	% even number of bytes
+	i.format = 'short';
+else
+	i.format = 'uchar';
+end
+