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