www.gusucode.com > 语音信号处理工具箱 - Voicebox源码程序 > Voicebox\writewav.m
function fidx=wwav(d,fs,filename,mode,nskip) %WRITEWAV Creates .WAV format sound files FIDX=(D,FS,FILENAME,MODE,NSKIP) % % The input arguments for WRITEWAV are as follows: % % D The sampled data to save % FS The rate at which the data was sampled % FILENAME A string containing the name of the .WAV file to create or % alternatively the FIDX output from a previous writewav call % MODE String containing any reasonable mixture of the following (*=default): % % Precision: 'a' for 8-bit A-law PCM % 'u' for 8-bit mu-law PCM % '16' * for 16 bit PCM data % '8' for 8 bit PCM data % ... any number in the range 2 to 32 for PCM % % 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 % Offset: 'y' * Correct for offset in <=8 bit PCM data % 'z' No offset correction % File I/O: 'f' Do not close file on exit % NSKIP Number of samples to skip before writing or -1[default] to continue from previous write % Only valid if FIDX is specified for FILENAME % % Output Parameter: % % 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 % (9) fs sample frequency % % Note: WRITEWAV will create an 16-bit PCM, auto-scaled wave file by default. % For stereo data, d(:,1) is the left channel and d(:,2) the right % % See also READWAV % Copyright (C) Mike Brookes 1998 % % Last modified Tue May 12 16:11:10 1998 % % VOICEBOX home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You can obtain a copy of the GNU General Public License from % ftp://prep.ai.mit.edu/pub/gnu/COPYING-2.0 or by writing to % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if nargin<3 error('Usage: WRITEWAV(data,fs,filename,mode,nskip)'); end info=zeros(1,9); info(9)=fs; if nargin<4 mode='s'; else mode = [mode(:).' 's']; end info(7)=16; info(8)=1; hi=32767; lo=-32768; pk=32767.5; if nargin>3 k=find((mode>='0') & (mode<='9')); if k info(7)=str2num(mode(k)); hi=pow2(0.5,info(7))-1; lo=-1-hi; pk=hi+0.5; end if any(mode=='a') info(8)=6; pk=4096; info(7)=8; end if any(mode=='u') info(8)=7; pk=8159; info(7)=8; end % pk value wrong end k=find((mode>='p') & (mode<='s')); sc=mode(k(1)); z=128*all(mode~='z'); info(6)=ceil(info(7)/8); [n,nc]=size(d); if n==1 n=nc; nc=1; else d = d.'; end; if nc>10 error('WRITEWAV: attempt to write a sound file with >10 channels'); end nc=max(nc,1); ncy=nc*info(6); nyd=n*ncy; if ischar(filename) nskip=0; ny=nyd; if isempty(findstr(filename,'.')) filename=[filename,'.wav']; end fid=fopen(filename,'wb+','l'); if fid == -1 error(sprintf('Can''t open %s for output',filename)); end info(1)=fid; fwrite(fid,'RIFF','uchar'); fwrite(fid,36+ny,'ulong'); fwrite(fid,'WAVEfmt ','uchar'); fwrite(fid,[16 0 info(8) nc],'ushort'); fwrite(fid,[fs fs*ncy],'ulong'); fwrite(fid,[ncy info(7)],'ushort'); fwrite(fid,'data','uchar'); fwrite(fid,ny,'ulong'); info(3)=44; info(4)=n+nskip; info(2)=info(4); else info=filename; fid=info(1); fseek(fid,0,1); if nargin<5 nskip=info(2); elseif nskip<0 nskip=info(2); end info(2)=n+nskip; ny=nyd+nskip*ncy; if n & (info(2)>info(4)) if ~info(4) fseek(fid,22,-1); fwrite(fid,nc,'ushort'); fseek(fid,28,-1); fwrite(fid,fs*ncy,'ulong'); fwrite(fid,ncy,'ushort'); end fseek(fid,4,-1); fwrite(fid,36+ny,'ulong'); fseek(fid,40,-1); fwrite(fid,ny,'ulong'); info(4)=info(2); end end info(5)=nc; if n st=fseek(fid,info(3)+nskip*nc*info(6),-1); if st error(sprintf('Cannot seek to %d in output file',info(3)+nskip*nc*info(6))); end if sc~='r' if sc=='s' pd=max(abs(d(:))); pd=pd+(pd==0); elseif sc=='p' pd=1; else if info(8)==7 pd=2.03761563; else pd=2.03033976; end end d=pk/pd*d; end if info(8)<6 d=round(0.5*(lo+hi+abs(d-lo)-abs(d-hi)))*pow2(1,8*info(6)-info(7)); else z=0; if info(8) < 7 d=lin2pcma(d,213,1); else d=lin2pcmu(d,1); end end if info(6)<3 if info(6)<2 fwrite(fid,d+z,'uchar'); else fwrite(fid,d,'short'); end else if info(6)<4 d=d(:)'; d2=floor(d/65536); d=d-65536*d2; fwrite(fid,[rem(d,256); floor(d/256); d2],'uchar'); else fwrite(fid,d,'long'); end end if rem(ny,2) fwrite(fid,0,'uchar'); end end if all(mode~='f') fclose(fid); end if nargout fidx=info; end