


READWAV Read a .WAV format sound file [Y,FS,WMODE,FIDX]=(FILENAME,MODE,NMAX,NSKIP)
Input Parameters:
FILENAME gives the name of the file (with optional .WAV extension) or alternatively
can be the FIDX output from a previous call to READWAV
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)
'g' Scale by the gain written by the "g" option in "writewav" to restore original level
Offset: 'y' * Correct for offset in <=8 bit PCM data
'z' No offset correction
File I/O: 'f' Do not close file on exit
'd' Look in data directory: voicebox('dir_data')
Display; 'h' Print header information
'w' Plot waveform
'W' Plot spectrogram
'a' play audio (max 10 seconds)
'A' play all audio even if very long
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 for WRITEWAV 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, 3=floating point, 6=A-law, 7=Mu-law
(9) fs sample frequency
(10) mask channel mask
(11) gain gain factor in dB
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
The mask, if specified, is a bit field giving the channels present in the following order:
0=FL, 1=FR, 2=FC, 3=W, 4=BL, 5=BR, 6=FLC, 7=FRC, 8=BC, 9=SL, 10=SR, 11=TC, 12=TFL, 13=TFC, 14=TFR, 15=TBL, 16=TBC, 17=TBR
where F=front, L=left, C=centre, W=woofer (low frequency), B=back, LC=left of centre, RC=right of centre, S=side, T=top
See also WRITEWAV.

0001 function [y,fs,wmode,fidx]=readwav(filename,mode,nmax,nskip) 0002 %READWAV Read a .WAV 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 .WAV extension) or alternatively 0007 % can be the FIDX output from a previous call to READWAV 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 % 'g' Scale by the gain written by the "g" option in "writewav" to restore original level 0019 % Offset: 'y' * Correct for offset in <=8 bit PCM data 0020 % 'z' No offset correction 0021 % File I/O: 'f' Do not close file on exit 0022 % 'd' Look in data directory: voicebox('dir_data') 0023 % Display; 'h' Print header information 0024 % 'w' Plot waveform 0025 % 'W' Plot spectrogram 0026 % 'a' play audio (max 10 seconds) 0027 % 'A' play all audio even if very long 0028 % 0029 % NMAX maximum number of samples to read (or -1 for unlimited [default]) 0030 % NSKIP number of samples to skip from start of file 0031 % (or -1 to continue from previous read when FIDX is given instead of FILENAME [default]) 0032 % 0033 % Output Parameters: 0034 % 0035 % Y data matrix of dimension (samples,channels) 0036 % FS sample frequency in Hz 0037 % WMODE mode string needed for WRITEWAV to recreate the data file 0038 % FIDX Information row vector containing the element listed below. 0039 % 0040 % (1) file id 0041 % (2) current position in file 0042 % (3) dataoff byte offset in file to start of data 0043 % (4) nsamp number of samples 0044 % (5) nchan number of channels 0045 % (6) nbyte bytes per data value 0046 % (7) bits number of bits of precision 0047 % (8) code Data format: 1=PCM, 2=ADPCM, 3=floating point, 6=A-law, 7=Mu-law 0048 % (9) fs sample frequency 0049 % (10) mask channel mask 0050 % (11) gain gain factor in dB 0051 % 0052 % If no output parameters are specified, header information will be printed. 0053 % 0054 % For stereo data, y(:,1) is the left channel and y(:,2) the right 0055 % The mask, if specified, is a bit field giving the channels present in the following order: 0056 % 0=FL, 1=FR, 2=FC, 3=W, 4=BL, 5=BR, 6=FLC, 7=FRC, 8=BC, 9=SL, 10=SR, 11=TC, 12=TFL, 13=TFC, 14=TFR, 15=TBL, 16=TBC, 17=TBR 0057 % where F=front, L=left, C=centre, W=woofer (low frequency), B=back, LC=left of centre, RC=right of centre, S=side, T=top 0058 % 0059 % See also WRITEWAV. 0060 0061 % *** Note on scaling *** 0062 % If we want to scale signal values in the range +-1 to an integer in the 0063 % range [-128,127] then we have four plausible choices corresponding to 0064 % scale factors of (a) 127, (b) 127.5, (c) 128 or (d) 128.5 but each choice 0065 % has disadvantages. 0066 % For forward scaling: (c) and (d) cause clipping on inputs of +1. 0067 % For reverse scaling: (a) and (b) can generate output values < -1. 0068 % Any of these scalings can be selected via the mode input: (a) 'o', (b) default, (c) 'on', (d) 'n' 0069 0070 % Copyright (C) Mike Brookes 1998-2011 0071 % Version: $Id: readwav.m 713 2011-10-16 14:45:43Z dmb $ 0072 % 0073 % VOICEBOX is a MATLAB toolbox for speech processing. 0074 % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 0075 % 0076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0077 % This program is free software; you can redistribute it and/or modify 0078 % it under the terms of the GNU General Public License as published by 0079 % the Free Software Foundation; either version 2 of the License, or 0080 % (at your option) any later version. 0081 % 0082 % This program is distributed in the hope that it will be useful, 0083 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0084 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0085 % GNU General Public License for more details. 0086 % 0087 % You can obtain a copy of the GNU General Public License from 0088 % http://www.gnu.org/copyleft/gpl.html or by writing to 0089 % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. 0090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0091 0092 % Bugs/suggestions: 0093 0094 0095 if nargin<1 0096 error('Usage: [y,fs,wmode,fidx]=READWAV(filename,mode,nmax,nskip)'); end 0097 if nargin<2 0098 mode='p'; 0099 else 0100 mode = [mode(:).' 'p']; 0101 end 0102 k=find((mode>='p') & (mode<='s')); 0103 mno=all(mode~='o'); % scale to input limits not output limits 0104 sc=mode(k(1)); 0105 z=128*all(mode~='z'); 0106 info=zeros(1,11); 0107 if ischar(filename) 0108 if any(mode=='d') 0109 filename=fullfile(voicebox('dir_data'),filename); 0110 end 0111 fid=fopen(filename,'rb','l'); 0112 if fid == -1 0113 fn=[filename,'.wav']; 0114 fid=fopen(fn,'rb','l'); 0115 if fid ~= -1 0116 filename=fn; 0117 end 0118 end 0119 if fid == -1 0120 error('Can''t open %s for input',filename); 0121 end 0122 info(1)=fid; 0123 else 0124 info=filename; 0125 fid=info(1); 0126 end 0127 getdat= nargout>0 || any(lower(mode)=='w') || any(lower(mode)=='a'); 0128 mh=any(mode=='h') || ~getdat; 0129 if ~info(3) 0130 fseek(fid,8,-1); % read riff chunk 0131 header=fread(fid,4,'*char')'; 0132 if ~strcmp(header,'WAVE') 0133 fclose(fid); 0134 error('File does not begin with a WAVE chunck'); 0135 end 0136 if mh 0137 fprintf('\nWAVE file: %s\n',filename); 0138 end 0139 fmtlen=-1; 0140 datalen=-1; 0141 instlen=-1; 0142 factlen=-1; 0143 riffmt='e'; % default is original wave file format 0144 while datalen<0 % loop until FMT and DATA chuncks both found 0145 header=fread(fid,4,'*char'); 0146 len=fread(fid,1,'ulong'); 0147 if mh 0148 fprintf(' %s chunk: %d bytes\n',header,len); 0149 end 0150 if strcmp(header','fmt ') % ******* found FMT chunk ********* 0151 fmtlen=len; % remember the length 0152 if len>16 0153 riffmt='x'; % might be WAVEFORMATEX format 0154 end 0155 wavfmt=fread(fid,1,'short'); % format: 1=PCM, 6=A-law, 7-Mu-law 0156 info(8)=wavfmt; 0157 info(5)=fread(fid,1,'ushort'); % number of channels 0158 fs=fread(fid,1,'ulong'); % sample rate in Hz 0159 info(9)=fs; % sample rate in Hz 0160 rate=fread(fid,1,'ulong'); % average bytes per second (ignore) 0161 align=fread(fid,1,'ushort'); % block alignment in bytes (container size * #channels) 0162 bps=fread(fid,1,'ushort'); % bits per sample 0163 info(7)=bps; 0164 % info(6)=ceil(info(7)/8); % round up to a byte count 0165 info(6)=floor(align/info(5)); % assume block size/channels = container size 0166 if info(8)==-2 % wave format extensible 0167 cb=fread(fid,1,'ushort'); % extra bytes must be >=22 0168 riffmt='X'; % WAVEFORMATEXTENSIBLE format 0169 wfxsamp=fread(fid,1,'ushort'); % samples union 0170 if wfxsamp>0 0171 info(7)=wfxsamp; % valid bits per sample 0172 end 0173 info(10)=fread(fid,1,'ulong'); % channel mask 0174 wfxguida=fread(fid,1,'ulong'); % GUID 0175 wfxguidb=fread(fid,2,'ushort'); % GUID 0176 wfxguidc=fread(fid,8,'uchar'); % GUID 0177 if wfxguida<65536 0178 info(8)=wfxguida; % turn it into normal wav format 0179 end 0180 fseek(fid,len-40,0); % skip to end of header 0181 else 0182 if align>0 && align<(info(6)+4)*info(5) 0183 info(6)=ceil(align/info(5)); 0184 end 0185 fseek(fid,len-16,0); % skip to end of header 0186 end 0187 if mh 0188 fmttypes={'?' 'PCM' 'ADPCM' 'IEEE-float' '?' '?' 'A-law' 'µ-law' '?'}; 0189 fprintf(' Format: %d = %s',info(8),fmttypes{1+max(min(info(8),8),0)}); 0190 if wavfmt==-2 0191 fprintf(' (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n',wfxguida,wfxguidb,wfxguidc); 0192 else 0193 fprintf('\n'); 0194 end 0195 fprintf(' %d channels at %g kHz sample rate (%d kbytes/s)\n',info(5),fs/1000,rate/1000); 0196 fprintf(' Mask=%x:',info(10)); 0197 spkpos={'FL' 'FR' 'FC' 'W' 'BL' 'BR' 'FLC' 'FRC' 'BC' 'SL' 'SR' 'TC' 'TFL' 'TFC' 'TFR' 'TBL' 'TBC' 'TBR'}; 0198 for i=1:18 0199 if mod(floor(info(10)*pow2(1-i)),2) 0200 fprintf([' ' spkpos{i}]); 0201 end 0202 end 0203 fprintf('\n %d valid bits of %d per sample (%d byte block size)\n',info(7),bps,align); 0204 end 0205 elseif strcmp(header','fact') % ******* found FACT chunk ********* 0206 factlen=len; 0207 if len<4 0208 error('FACT chunk too short'); 0209 end 0210 nsamp=fread(fid,1,'ulong'); % number of samples 0211 fseek(fid,len-4,0); % skip to end of header 0212 if mh 0213 fprintf(' %d samples = %.3g seconds\n',nsamp,nsamp/fs); 0214 end 0215 elseif strcmp(header','inst') % ******* found INST chunk ********* 0216 instlen=len; 0217 if len<7 0218 error('INST chunk too short'); 0219 end 0220 inst=fread(fid,3,'schar'); 0221 info(11)=double(inst(3)); % gain in dB 0222 if mh 0223 fprintf(' Gain = %d dB\n',info(11)); 0224 end 0225 fseek(fid,len-3,0); % skip to end of header 0226 elseif strcmp(header','data') % ******* found DATA chunk ********* 0227 if fmtlen<0 0228 fclose(fid); 0229 error('File %s does not contain a FMT chunck',filename); 0230 end 0231 if factlen>3 && nsamp >0 0232 info(4)=nsamp; % take data length from FACT chunk 0233 else 0234 info(4) = fix(len/(info(6)*info(5))); % number of samples 0235 end 0236 info(3)=ftell(fid); % start of data 0237 datalen=len; 0238 if mh 0239 fprintf(' %d samples x %d channels x %d bytes/samp',info(4:6)); 0240 if prod(info(4:6))~=len 0241 fprintf(' + %d padding bytes',len-prod(info(4:6))); 0242 end 0243 fprintf(' = %g sec\n',info(4)/fs); 0244 end 0245 else % ******* found unwanted chunk ********* 0246 fseek(fid,len,0); 0247 end 0248 end 0249 else 0250 fs=info(9); 0251 end 0252 if nargin<4 || nskip<0 0253 nskip=info(2); % resume at current file position 0254 end 0255 0256 ksamples=info(4)-nskip; % number of samples remaining 0257 if nargin>2 0258 if nmax>=0 0259 ksamples=min(nmax,ksamples); 0260 end 0261 elseif ~getdat 0262 ksamples=min(5,ksamples); % just read 5 samples so we can print the first few data values 0263 end 0264 if ksamples>0 0265 info(2)=nskip+ksamples; 0266 fseek(fid,info(3)+info(6)*info(5)*nskip,-1); 0267 nsamples=info(5)*ksamples; 0268 if any(info(8)==3) % floating point format 0269 pk=1; % peak is 1 0270 switch info(6) 0271 case 4 0272 y=fread(fid,nsamples,'float32'); 0273 case 8 0274 y=fread(fid,nsamples,'float64'); 0275 otherwise 0276 error('cannot read %d-byte floating point numbers',info(6)); 0277 end 0278 else 0279 if ~any(info(8)==[1 6 7]) 0280 sc='r'; % read strange formats in raw integer mode 0281 end 0282 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 0283 switch info(6) 0284 case 1 0285 y=fread(fid,nsamples,'uchar'); 0286 if info(8)==1 0287 y=y-z; 0288 elseif info(8)==6 0289 y=pcma2lin(y,213,1); 0290 pk=4032+mno*64; 0291 elseif info(8)==7 0292 y=pcmu2lin(y,1); 0293 pk=8031+mno*128; 0294 end 0295 case 2 0296 y=fread(fid,nsamples,'short'); 0297 case 3 0298 y=fread(fid,3*nsamples,'uchar'); 0299 y=reshape(y,3,nsamples); 0300 y=([1 256 65536]*y-pow2(fix(pow2(y(3,:),-7)),24)).'; 0301 case 4 0302 y=fread(fid,nsamples,'long'); 0303 otherwise 0304 error('cannot read %d-byte integers',info(6)); 0305 end 0306 end 0307 if sc ~= 'r' 0308 if sc=='s' 0309 sf=1/max(abs(y(:))); 0310 elseif sc=='p' 0311 sf=1/pk; 0312 else 0313 if info(8)==7 0314 sf=2.03761563/pk; 0315 else 0316 sf=2.03033976/pk; 0317 end 0318 end 0319 y=sf*y; 0320 else % mode = 'r' - output raw values 0321 if info(8)==1 0322 y=y*pow2(1,info(7)-8*info(6)); % shift to get the bits correct 0323 end 0324 end 0325 if any(mode=='g') && info(11)~=0 0326 y=y*10^(info(11)/20); % scale by the gain 0327 end 0328 if info(5)>1 0329 y = reshape(y,info(5),ksamples).'; 0330 end 0331 else 0332 y=[]; 0333 end 0334 if all(mode~='f') 0335 fclose(fid); 0336 end 0337 if nargout>2 % sort out the mode input for writing this format 0338 wmode=char([riffmt sc 'z'-z/128]); 0339 if factlen>0 0340 wmode=[wmode 'E']; 0341 end 0342 if info(6)>1 && info(6)<5 0343 cszc=' cCL'; 0344 wmode=[wmode cszc(info(6))]; 0345 end 0346 switch info(8) 0347 case 1 % PCM modes 0348 if ~mno 0349 wmode=[wmode 'o']; 0350 end 0351 if any(mode=='n') 0352 wmode=[wmode 'n']; 0353 end 0354 wmode=[wmode num2str(info(7))]; 0355 case 3 0356 if info(7)<=32 0357 wmode = [wmode 'v']; 0358 else 0359 wmode = [wmode 'V']; 0360 end 0361 case 6 0362 wmode = [wmode 'a']; 0363 case 7 0364 wmode = [wmode 'u']; 0365 end 0366 fidx=info; 0367 end 0368 [ns,nchan]=size(y); 0369 if mh && ns>0 0370 nsh=min(ns,5); % print first few samples 0371 for i=1:nsh 0372 fprintf(' %d:',i); 0373 fprintf(' %.3g',y(i,:)); 0374 fprintf('\n'); 0375 end 0376 end 0377 0378 if ns>0.01*fs 0379 if any(lower(mode)=='a') 0380 nsh=min(ns,10*fs+ns*any(mode=='A')); 0381 soundsc(y(1:nsh,1:min(nchan,2)),fs); 0382 end 0383 if any(mode=='W') 0384 spm='pJcbf '; 0385 if any(mode=='w') 0386 spm(end)='w'; 0387 end 0388 clf; 0389 if nchan>1 0390 for i=nchan:-1:1 0391 subplot(nchan,1,i) 0392 spgrambw(y(:,i),fs,spm); 0393 end 0394 else 0395 spgrambw(y,fs,spm); 0396 end 0397 elseif any(mode=='w') 0398 clf; 0399 if nchan>1 0400 for i=nchan:-1:1 0401 subplot(nchan,1,i) 0402 plot((1:ns)/fs,y(:,i)); 0403 ylabel(['Chan ' num2str(i)]); 0404 if i==nchan 0405 xlabel('Time (s)'); 0406 end 0407 end 0408 else 0409 plot((1:ns)/fs,y); 0410 xlabel('Time (s)'); 0411 end 0412 0413 end 0414 end 0415 0416 0417 0418