diff Code/Descriptors/yin/private/src/sf_info.m @ 4:92ca03a8fa99 tip

Update to ICASSP 2013 benchmark
author Dawn Black
date Wed, 13 Feb 2013 11:02:39 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Code/Descriptors/yin/private/src/sf_info.m	Wed Feb 13 11:02:39 2013 +0000
@@ -0,0 +1,438 @@
+function i = sf_info(i)
+% i=sf_info(i) - extract useful info from file
+
+% 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('sf_info: no input arguement'); end
+if ~isa(i, 'struct')
+	j.fname=i;
+    i=j;
+	i=sf_info(i);
+	return
+end
+if ~isfield(i, 'fname'); error('sf_info: no fname field'); end
+
+% guess format only if unknown
+if ~isfield(i, 'format') | isempty(i.format);
+	i = sf_format(i);
+	if ~strcmp(i.format, 'matrix') disp(i.format); end	
+end
+
+% handle workspace matrices as if they were files
+if strcmp(i.format, 'matrix')
+	[nrows, ncols] = size(i.fname);
+	i.nchans=ncols;
+	i.nsamples=nrows;
+	i.totalsamples = i.nsamples*i.nchans;
+    i.sr=[];
+	return;
+end
+
+% close file if open
+if exist('i.fd') & fopen(i.fd)
+	fclose(i.fd);
+end
+
+% use standard matlab functions for AU and WAV and MACSND
+if strcmp(i.format, 'AU')
+	if isempty(findstr('.', i.fname))
+		disp(['WARNING: matlab function AUREAD requires '...
+		'.au or .snd suffix on file name: ' i.fname]);
+	end
+	sz = auread(i.fname, 'size');
+	i.nsamples=sz(1);
+	i.nchans=sz(2);
+	i.totalsamples = i.nsamples*i.nchans;
+	[dummy, i.sr, i.samplebits] = auread(i.fname, 1);
+	return;
+end
+if strcmp(i.format, 'WAV')
+	if isempty(findstr('.wav', i.fname)) & isempty(findstr('.WAV', i.fname))
+		disp(['WARNING: matlab function WAVREAD requires '...
+		'.wav suffix on file name: ' i.fname]);
+	end
+	sz = wavread(i.fname, 'size');
+	i.nsamples=sz(1);
+	i.nchans=sz(2);
+	i.totalsamples = i.nsamples*i.nchans;
+	[dummy, i.sr, i.samplebits] = wavread(i.fname, 1);
+	return;
+end
+if strcmp(i.format, 'MACSND')
+	% must load the data to get info - this is stupid
+	if ~isempty(findstr(':', i.fname))
+		disp(['matlab function READSND cannot handle an '...
+		'indirect path: ' i.fname]);
+	end
+	if 3==exist('readsnd')		
+		[data, i.sr] = eval('readsnd(i.fname)');
+	else
+		error('cannot read MACSND on this platform');
+	end
+	i.nsamples = size(data,2);
+	i.nchans = size(data,1);
+	i.totalsamples = i.nsamples*i.nchans;
+	return
+end
+
+% reopen file
+if strcmp(i.format, 'ascii') ...
+	| strcmp(i.format, 'csv') | strcmp(i.format, '|WAVE')
+	[i.fd, msg] = fopen(i.fname, 'rt');
+else
+	[i.fd, msg] = fopen(i.fname, 'r', 'ieee-be.l64');
+end
+if i.fd == -1
+	if isempty(msg)
+		error(['could not open: ', i.fname]);
+	else
+		error(msg)
+	end
+end
+fd = i.fd;
+if ~isfield(i, 'nbytes')
+	if (-1 == fseek(i.fd, 0, 1)) ; error ('fseek failed');  end;	
+	i.nbytes = ftell(i.fd);
+end
+fseek(fd, 0, -1);	% rewind
+
+
+switch i.format
+%%%%%%%%%%%%%%%%%%% AIFF %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case {'AIFF','AIFC'}
+	fseek(fd, 12, 0); % skip container chunk
+	% skip over spurious chunks
+        idx=ftell(fd);
+	while 1
+        	magic=char(fread(fd,4,'uchar'))';
+                if strcmp(magic,'COMM'); break; end;
+                idx = idx+1;
+                status = fseek(fd,idx,-1);
+		if status == -1
+			error('expected COMM magic word, found eof');
+		end;
+	end;
+
+        %ckSize=fread(fd,1,'int32');
+	%status = fseek(fd, ckSize, 0);		% skip to end of chunk
+        %if status == -1
+        %      error('unexpected eof');
+        %end
+
+	%while (1) 
+	%	magic = char(fread(fd, 4, 'char'))';
+	%	if ~strcmp(magic, 'SSND')
+	%		fseek(fd, -4, 0);	% skip back
+	%		break;
+	%	end
+	%	ckSize = fread(fd, 1, 'long');
+	%	fseek(fd, ckSize, 0);	% skip to end of sound chunk
+	%end
+	%magic = char(fread (fd, 4, 'char'))';
+	%if ~strcmp(magic, 'COMM'); error(['expected COMM, found ', magic]) ; end
+	commsz = fread(fd, 1, 'int32'); 
+	i.nchans = fread(fd, 1, 'int16');
+	i.nsamples = fread(fd, 1, 'uint32');
+	i.totalsamples = i.nsamples*i.nchans;
+	i.samplebits = fread(fd, 1, 'int16');
+	switch i.samplebits
+	case 16
+		i.sample_bytes = 2;
+		i.sample_type = 'int16';
+	case 32
+		i.sample_bytes = 4;
+		i.sample_type = 'int32';	% or float?
+	otherwise
+		error(['unexpected samplebits: ' num2str(i.samplebits) ]);
+	end
+	% read sampling rate using Hideki Kawahara's code:
+	srex1=fread(fd,1,'uint16');
+	srex2=fread(fd,1,'uint64');
+	if strcmp(char(i.format),'AIFC')
+	    compress=fread(fd,4,'uchar');
+		if ~strcmp(char(compress),'NONE')
+		    error('Compression is not supported.');
+		end;
+	    	fseek(fd, commsz-22, 0);
+	end;
+	i.sr = 2^(srex1-16383)*srex2/hex2dec('8000000000000000');
+	%fseek(fd, 12, -1);	% skip back to end of container chunk
+	% skip over eventual common chunk
+	%while(1)
+	%	magic = char(fread(fd, 4, 'char'))';
+	%	if ~strcmp(magic, 'COMM')
+	%		fseek(fd, -4, 0);	% skip back
+	%		break;
+	%	end
+	%	ckSize = fread(fd, 1, 'long');
+	%	fseek(fd, ckSize, 0);	% skip over chunk
+	%end
+	magic=char(fread(fd,4,'uchar'))';
+	while ~strcmp(char(magic),'SSND')
+		[ckSize, count]=fread(fd,1,'int32');
+		if ~count; 			
+			error('expected chunk size field, found eof');
+			return
+		end
+		status = fseek(fd, ckSize, 0);		% skip to end of chunk
+		if status == -1
+			error('expected SSND magic word, found eof');
+			return
+		end;
+		magic=char(fread(fd,4,'uchar'))';
+	end;
+
+	%magic = char(fread(fd, 4, 'char'))';
+	%if ~strcmp(magic, 'SSND')
+	%	error (['expected SSND, found' magic]);
+	%end
+	fseek(fd, 12, 0);	% skip over ckSize, offset and blocksize fields
+	i.bytes_to_data = ftell(fd);
+	if i.totalsamples*i.sample_bytes ~= i.nbytes-i.bytes_to_data
+		disp(['WARNING: header fields sample_bytes: ' ...
+		num2str(i.sample_bytes)]); 
+		disp (['and sample and channel count: ' num2str(i.nsamples) ...
+		', ' num2str(i.nchans)]);
+		disp(['are inconsistent with offset to data: ' ...
+		num2str(i.bytes_to_data) ' and file size: ' ...
+		num2str(i.nbytes)]);
+		disp (['(' num2str(i.totalsamples*i.sample_bytes) ...
+		' ~= ' num2str(i.nbytes-i.bytes_to_data) ')']);
+	end
+	
+	return
+%%%%%%%%%%%%%%%%%%% NIST %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case 'NIST'
+%	fseek(fd, 0, -1);
+%	line = fscanf(fd, '%s' , 1);
+%	if ~strcmp(line, 'NIST_1A'); error(['expected NIST_1A, found ', magic]); end
+	fseek(fd, 8, 0);	% skip over magic string
+	i.bytes_to_data = fscanf(fd, '%d', 1);
+	while (1)
+		key = fscanf(fd, '%s', 1);
+		if strcmp(key, 'end_head'); break; end;
+		% read third field according to spec in second field (type)
+		% this may need refining...
+		type = fscanf(fd, '%s', 1);
+		if strcmp(type(1:2), '-s')
+			bytes_to_read = sscanf(type(3:end), '%d', 1);
+			fseek(fd, 1, 0);	% skip blank
+			value = char(fread(fd, bytes_to_read, 'char'))';
+		else 
+			value = fscanf(fd, '%f', 1);
+		end
+		i = setfield(i, key, value);
+	end
+	% give standard names to useful fields
+	if isfield(i, 'channel_count'); i.nchans = i.channel_count; end
+	if isfield(i, 'sample_count'); i.nsamples = i.sample_count; end
+	i.totalsamples = i.nsamples*i.nchans;
+	if isfield(i, 'sample_rate'); 
+		i.sr = i.sample_rate; 
+		i.xunits = 's';
+	end
+	if ~isfield(i, 'sample_coding'); i.sample_coding = 'pcm'; end
+	i.bytes_to_data = 1024; 	% needs checking
+	i.sample_bytes=2;
+	i.sample_type='int16';
+	return
+%%%%%%%%%%%%%%%%%%% |WAVE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case '|WAV'
+	line = fscanf(fd, '%s' , 1);	% skip first line
+	i.nsamples = fscanf(fd, '%d', 1);
+	i.nchans = fscanf(fd, '%d', 1);
+	i.totalsamples = i.nsamples*i.nchans;
+	i.bytes_to_data = ftell(fd);
+	% channel info handled during data read
+	i.totalsamples = i.nsamples * i.nchans;
+	return
+%%%%%%%%%%%%%%%%%%% WFF %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case 'wff'
+	fseek(fd, 4, 0);	% skip magic number
+	i.version = fread(fd, 1, 'long');
+	i.type_code = fread(fd, 1, 'long');
+	i.nchans = fread(fd, 1, 'long');
+	i.info.channel_flags = fread(fd, 1, 'long');
+	i.bytes_to_data = fread(fd, 1, 'long');
+	fseek(fd, 40, 0);
+	i.gen_prog_name = fread(fd, 32, 'char');
+	i.comment = fread(fd, 32, 'char');
+	i.sample_bytes = 2;
+	i.sample_type = 'int16';
+	return;
+% channel info handled later during channel read
+%%%%%%%%%%%%%%%%%%% ESPS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case 'ESPS'
+% Based on Peter Kabal's afsp package.
+% This handles at least one kind of ESPS waveform file.  Others?
+	i.machine_code = fread(fd, 1, 'uint');
+	i.version_check_code = fread(fd, 1, 'uint');
+	i.bytes_to_data = fread(fd, 1, 'uint');
+	i.record_size = fread(fd, 1, 'uint');
+	fseek(fd, 20, -1);
+	i.EDR_ESPS_flag = fread(fd, 1, 'uint');
+	i.align_pad_size = fread(fd, 1, 'uint');
+	fseek(fd, 32, -1);
+	i.file_type = fread(fd, 1, 'uint16');
+	fseek(fd, 40, -1);
+	i.file_creation_date_time = char(fread(fd, 26, 'char'))';
+	i.header_version = char(fread(fd, 8, 'char'))';
+	i.program_name = char(fread(fd, 16, 'char'))';
+	i.program_version = char(fread(fd, 8, 'char'))';
+	i.compile_date = char(fread(fd, 26, 'char'))';
+	i.tag = fread(fd, 1, 'uint');
+	fseek(fd, 132, -1);
+	i.ndoubles = fread(fd, 1, 'uint');
+	i.nfloats = fread(fd, 1, 'uint');
+	i.nlongs = fread(fd, 1, 'uint');
+	i.nshorts = fread(fd, 1, 'uint');
+	i.nchars = fread(fd, 1, 'uint');
+	i.fixed_header_size = fread(fd, 1, 'uint');
+	i.var_header_size = fread(fd, 1, 'uint');
+	%w.dunno_what = fread(fd, 1, 'uint');
+	fseek(fd, 160, -1);
+	i.user = char(fread(fd, 8, 'char'))';
+	% scan the rest of the header to find sampling rate
+	a = ftell(fd);
+	bytes_left_in_header = i.bytes_to_data - ftell(fd);
+	hunk = char(fread(fd, bytes_left_in_header, 'uchar'))';
+	b = findstr(hunk, 'record_freq');
+	%fseek(fd, a+b-1, -1);
+	%w.xxxx = char(fread(fd, 12, 'char'))';
+	%w.count = fread(fd, 1, 'uint');
+	%w.data_code = fread(fd, 1, 'ushort');
+	fseek(fd, a+b-1+12+2+4, -1);
+	i.sr = fread(fd, 1, 'double');
+	i.nchans = i.ndoubles+i.nfloats+i.nlongs ...
+		+i.nshorts+i.nchars;
+	recordsize = i.ndoubles*8 + i.nfloats*4 + i.nlongs*4 ...
+		+i.nshorts*2+i.nchars;
+	i.nsamples = (i.nbytes - i.bytes_to_data) / recordsize;
+	i.totalsamples = i.nsamples * i.nchans;
+	i.sample_bytes = 2;			% bug
+	i.sample_type = 'int16'; 	% bug
+	return;
+%%%%%%%%%%%%% PLAIN ASCII %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case 'ascii'
+	if isfield(i, 'bytes_to_data')
+		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	line = fgetl(fd);
+	i.nchans = size(sscanf(line, '%f'), 1);
+	nlines = 1;
+	while (1)
+		line = fgets(i.fd);
+		if isa(line, 'double') & -1 == line; break; end
+		nlines = nlines+1;
+	end
+	i.nsamples = nlines;
+	i.totalsamples = i.nsamples*i.nchans;
+    i.sr=1;
+	return
+%%%%%%%%%%%%% COMMA-SEPARATED VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case 'csv';
+	if isfield(i, 'bytes_to_data')
+		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	% todo
+	return
+%%%%%%%%%%%%% Binary  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+case {'uchar'}; % should take care of signed/unsigned
+	i.sample_bytes = 1;
+	i.sample_type = 'uchar';	
+	if isfield(i, 'bytes_to_data')
+		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	if ~isfield(i, 'nchans')	
+		i.nchans = 1;
+	end
+	i.nsamples = (i.nbytes-i.bytes_to_data)/i.sample_bytes;
+	i.totalsamples = i.nsamples * i.nchans;
+    i.sr=1;
+	return
+case {'short', 'int16'};
+	i.sample_bytes = 2;
+	i.sample_type = 'int16';	
+	if isfield(i, 'bytes_to_data')
+		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	if ~isfield(i, 'nchans')	
+		i.nchans = 1;
+	end
+	i.nsamples = (i.nbytes-i.bytes_to_data)/i.sample_bytes;
+	i.totalsamples = i.nsamples * i.nchans;
+    i.sr=1;
+	return
+case {'long', 'int32'};
+	i.sample_bytes = 4;
+	i.sample_type = 'int32';	
+	if isfield(i, 'bytes_to_data')
+		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	if ~isfield(i, 'nchans')	
+		i.nchans = 1;
+	end
+	i.nsamples = (i.nbytes-i.bytes_to_data)/i.sample_bytes;
+	i.totalsamples = i.nsamples * i.nchans;
+    i.sr=1;
+	return
+case {'float', 'float32'};
+	i.sample_bytes = 4;
+	i.sample_type = 'float32';	
+	if isfield(i, 'bytes_to_data')
+		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	if ~isfield(i, 'nchans')	
+		i.nchans = 1;
+	end
+	i.nsamples = (i.nbytes-i.bytes_to_data)/i.sample_bytes;
+	i.totalsamples = i.nsamples * i.nchans;
+    i.sr=1;
+	return
+case {'double', 'float64'};
+	i.sample_bytes = 8;
+	i.sample_type = 'float64';	
+	if isfield(i, 'bytes_to_data')
+ 		fseek(fd, i.bytes_to_data, 0);
+	else 
+		i.bytes_to_data = 0;
+	end
+	if ~isfield(i, 'nchans')	
+		i.nchans = 1;
+	end
+	i.nsamples = (i.nbytes-i.bytes_to_data)/i.sample_bytes;
+	i.totalsamples = i.nsamples * i.nchans;
+    i.sr=1;
+	return
+otherwise
+	error(['unknown format: >' i.format '<']);
+end