V_READAIF Read a .AIF format sound file [Y,FS,WMODE,FIDX]=(FILENAME,MODE,NMAX,NSKIP) Input Parameters: FILENAME gives the name of the file (with optional .AIF extension) or alternatively can be the FIDX output from a previous call to READAIF MODE specifies the following (*=default): Scaling: 's' Auto scale to make data peak = +-1 'r' Raw unscaled data (integer values) 'q' Scaled to make 0dBm0 be unity mean square 'p' * Scaled to make +-1 equal full scale 'o' Scale to bin centre rather than bin edge (e.g. 127 rather than 127.5 for 8 bit values) (can be combined with n+p,r,s modes) 'n' Scale to negative peak rather than positive peak (e.g. 128.5 rather than 127.5 for 8 bit values) (can be combined with o+p,r,s modes) File I/O: 'f' Do not close file on exit 'd' Look in data directory: v_voicebox('dir_data') NMAX maximum number of samples to read (or -1 for unlimited [default]) NSKIP number of samples to skip from start of file (or -1 to continue from previous read when FIDX is given instead of FILENAME [default]) Output Parameters: Y data matrix of dimension (samples,channels) FS sample frequency in Hz WMODE mode string needed to recreate the data file FIDX Information row vector containing the element listed below. (1) file id (2) current position in file (3) dataoff byte offset in file to start of data (4) nsamp number of samples (5) nchan number of channels (6) nbyte bytes per data value (7) bits number of bits of precision (8) code Data format: 1=PCM, 2=ADPCM, 6=A-law, 7=Mu-law (always 1 for AIFF) (9) fs sample frequency (10) offset (11) block size If no output parameters are specified, header information will be printed. For stereo data, y(:,1) is the left channel and y(:,2) the right
0001 function [y,fs,wmode,fidx]=v_readaif(filename,mode,nmax,nskip) 0002 %V_READAIF Read a .AIF format sound file [Y,FS,WMODE,FIDX]=(FILENAME,MODE,NMAX,NSKIP) 0003 % 0004 % Input Parameters: 0005 % 0006 % FILENAME gives the name of the file (with optional .AIF extension) or alternatively 0007 % can be the FIDX output from a previous call to READAIF 0008 % MODE specifies the following (*=default): 0009 % 0010 % Scaling: 's' Auto scale to make data peak = +-1 0011 % 'r' Raw unscaled data (integer values) 0012 % 'q' Scaled to make 0dBm0 be unity mean square 0013 % 'p' * Scaled to make +-1 equal full scale 0014 % 'o' Scale to bin centre rather than bin edge (e.g. 127 rather than 127.5 for 8 bit values) 0015 % (can be combined with n+p,r,s modes) 0016 % 'n' Scale to negative peak rather than positive peak (e.g. 128.5 rather than 127.5 for 8 bit values) 0017 % (can be combined with o+p,r,s modes) 0018 % File I/O: 'f' Do not close file on exit 0019 % 'd' Look in data directory: v_voicebox('dir_data') 0020 % 0021 % NMAX maximum number of samples to read (or -1 for unlimited [default]) 0022 % NSKIP number of samples to skip from start of file 0023 % (or -1 to continue from previous read when FIDX is given instead of FILENAME [default]) 0024 % 0025 % Output Parameters: 0026 % 0027 % Y data matrix of dimension (samples,channels) 0028 % FS sample frequency in Hz 0029 % WMODE mode string needed to recreate the data file 0030 % FIDX Information row vector containing the element listed below. 0031 % 0032 % (1) file id 0033 % (2) current position in file 0034 % (3) dataoff byte offset in file to start of data 0035 % (4) nsamp number of samples 0036 % (5) nchan number of channels 0037 % (6) nbyte bytes per data value 0038 % (7) bits number of bits of precision 0039 % (8) code Data format: 1=PCM, 2=ADPCM, 6=A-law, 7=Mu-law (always 1 for AIFF) 0040 % (9) fs sample frequency 0041 % (10) offset 0042 % (11) block size 0043 % 0044 % If no output parameters are specified, header information will be printed. 0045 % 0046 % For stereo data, y(:,1) is the left channel and y(:,2) the right 0047 0048 % future enhancements: (1) handle LIST and CAT files as well 0049 % (2) deal with offset and blocksize properly 0050 % (3) handle other chunk types sensibly 0051 0052 % Copyright (C) Mike Brookes 1998 0053 % Version: $Id: v_readaif.m 10865 2018-09-21 17:22:45Z dmb $ 0054 % 0055 % VOICEBOX is a MATLAB toolbox for speech processing. 0056 % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 0057 % 0058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0059 % This program is free software; you can redistribute it and/or modify 0060 % it under the terms of the GNU General Public License as published by 0061 % the Free Software Foundation; either version 2 of the License, or 0062 % (at your option) any later version. 0063 % 0064 % This program is distributed in the hope that it will be useful, 0065 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0066 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0067 % GNU General Public License for more details. 0068 % 0069 % You can obtain a copy of the GNU General Public License from 0070 % http://www.gnu.org/copyleft/gpl.html or by writing to 0071 % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. 0072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0073 0074 if nargin<1 error('Usage: [y,fs,wmode,fidx]=READAIFF(filename,mode,nmax,nskip)'); end 0075 0076 if nargin<2 mode='p'; 0077 else mode = [mode(:).' 'p']; 0078 end 0079 k=find((mode>='p') & (mode<='s')); 0080 mno=all(mode~='o'); % scale to input limits not output limits 0081 sc=mode(k(1)); 0082 0083 0084 info=zeros(1,11); 0085 if ischar(filename) 0086 if any(mode=='d') 0087 filename=fullfile(v_voicebox('dir_data'),filename); 0088 end 0089 fid=fopen(filename,'rb','b'); 0090 if fid == -1 0091 fn=[filename,'.aif']; 0092 fid=fopen(fn,'rb','b'); 0093 if fid ~= -1 filename=fn; end 0094 end 0095 if fid == -1 error(sprintf('Can''t open %s for input',filename)); end 0096 info(1)=fid; 0097 else 0098 info=filename; 0099 fid=info(1); 0100 end 0101 0102 if ~info(3) 0103 fseek(fid,0,-1); % read file header 0104 header=fread(fid,4,'uchar'); 0105 if header' ~= 'FORM' fclose(fid); error(sprintf('File %s does not begin with a FORM group ID',filename)); end 0106 filen=fread(fid,1,'ulong')-4; 0107 header=fread(fid,4,'uchar'); 0108 if header' ~= 'AIFF' fclose(fid); error(sprintf('File %s does not begin with a AIFF type ID',filename)); end 0109 0110 0111 fmt=0; 0112 data=0; 0113 while filen>=8 % loop to read all chunks 0114 header=fread(fid,4,'char'); 0115 len=fread(fid,1,'ulong'); 0116 lenx=len+rem(len,2); % round up to an even number 0117 filen=filen-lenx-8; 0118 %fprintf(1,'%s chunk, %d bytes, %d bytes remaining\n',char(header'),len,filen); 0119 if header' == 'COMM' % ******* found COMM chunk ********* 0120 fmt=1; 0121 info(5)=fread(fid,1,'ushort'); %number of channels 0122 info(4)=fread(fid,1,'ulong'); %number of samples 0123 info(7)=fread(fid,1,'ushort'); % bits per sample 0124 info(6)=ceil(info(7)/8); % bytes per sample 0125 info(8)=1; 0126 ieeex=fread(fid,5,'ushort'); % read a 10-byte extended ieee format number 0127 fsign=ieeex(1)>32767; 0128 ieeex(1)=ieeex(1)-32768*fsign; 0129 if ~ieeex info(9)=0; 0130 elseif ieeex(1)==32767 info(9)=nan; 0131 else 0132 info(9)=(1-2*fsign)*sum(pow2(ieeex(2:5)',ieeex(1)-(16398:16:16446))); 0133 end 0134 fseek(fid,lenx-18,0); % skip to end of header 0135 elseif header' == 'SSND' % ******* found DATA chunk ********* 0136 info(10)=fread(fid,1,'ulong'); %number of channels 0137 info(11)=fread(fid,1,'ulong'); %number of channels 0138 info(3)=ftell(fid); 0139 data=1; 0140 fseek(fid,lenx-8,0); % skip to end of chunk 0141 else % ******* found unwanted chunk ********* 0142 fseek(fid,lenx,0); 0143 end 0144 end 0145 if filen~=0 0146 fprintf(2,'READAIF warning: Inconsistent file length - %d extra bytes\n',filen); 0147 end 0148 end 0149 fs=info(9); 0150 if ~fmt | ~data fclose(fid); error(sprintf('File %s does not contain COMM and SSND chunks',filename)); end 0151 0152 0153 if nargin<4 nskip=info(2); 0154 elseif nskip<0 nskip=info(2); 0155 end 0156 0157 ksamples=info(4)-nskip; 0158 if nargin>2 0159 if nmax>=0 0160 ksamples=min(nmax,ksamples); 0161 end 0162 elseif ~nargout 0163 ksamples=min(5,ksamples); 0164 end 0165 if ksamples>0 0166 info(2)=nskip+ksamples; 0167 pk=pow2(0.5,8*info(6))*(1+(mno/2-all(mode~='n'))/pow2(0.5,info(7))); % use modes o and n to determine effective peak 0168 fseek(fid,info(3)+info(6)*info(5)*nskip,-1); 0169 nsamples=info(5)*ksamples; 0170 if info(6)<3 0171 if info(6)<2 0172 y=fread(fid,nsamples,'schar'); 0173 else 0174 y=fread(fid,nsamples,'short'); 0175 end 0176 else 0177 if info(6)<4 0178 y=fread(fid,3*nsamples,'uchar'); 0179 y=reshape(y,3,nsamples); 0180 y=[1 256 65536]*y-pow2(fix(pow2(y(3,:),-7)),24); 0181 else 0182 y=fread(fid,nsamples,'long'); 0183 end 0184 end 0185 if sc ~= 'r' 0186 if sc=='s' sf=1/max(max(abs(y)),1); 0187 elseif sc=='p' sf=1/pk; 0188 else sf=2.03033976/pk; 0189 end 0190 y=sf*y; 0191 else 0192 y=y*pow2(1,info(7)-8*info(6)); % shift to get the data into the LSB end 0193 end 0194 0195 if info(5)>1 y = reshape(y,info(5),ksamples).'; end 0196 else 0197 y=[]; 0198 end 0199 0200 if all(mode~='f') fclose(fid); end 0201 0202 if nargout>2 0203 if ~mno wmode=[wmode 'o']; end 0204 if any(mode=='n') wmode=[wmode 'n']; end 0205 wmode=[sc num2str(info(7))]; 0206 fidx=info; 0207 elseif ~nargout 0208 fprintf(1,'\n%d Hz sample rate\n%d channel x %d samples x %d bit = %.3g seconds\n',info([9 5 4]), info(7),info(4)/info(9)); 0209 end 0210 0211 0212