diff options
Diffstat (limited to 'modules/sound/macros/auread.sci')
-rwxr-xr-x | modules/sound/macros/auread.sci | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/modules/sound/macros/auread.sci b/modules/sound/macros/auread.sci new file mode 100755 index 000000000..5be614f5c --- /dev/null +++ b/modules/sound/macros/auread.sci @@ -0,0 +1,216 @@ +// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab +// Copyright (C) ???? - INRIA - Scilab +// +// This file must be used under the terms of the CeCILL. +// This source file is licensed as described in the file COPYING, which +// you should have received as part of this distribution. The terms +// are also available at +// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + +function [y,Fs,bits]=auread(aufile,ext) + + //Utility fct: reads .au sound file. + //auread(aufile) loads a sound file specified by the string aufile, + //returning the sampled data in y. The .au extension is appended + //if no extension is given. Amplitude values are in the range [-1,+1]. + //Supports multi-channel data in the following formats: + //8-bit mu-law, 8-, 16-, and 32-bit linear, and floating point. + + // [y,Fs,bits]=auread(aufile) returns the sample rate (Fs) in Hertz + // and the number of bits per sample used to encode the + // data in the file. + + // auread(aufile,n) returns the first n samples from each + // channel in the file. + // auread(aufile,[n1,n2]) returns samples n1 through n2 from + // each channel in the file. + // siz=auread(aufile,'size') returns the size of the audio data contained + // in the file in place of the actual audio data, returning the + // vector siz=[samples channels]. + + [nargout,nargin] = argn(0); + + if nargin>2 then + error(msprintf(gettext("%s: Wrong number of input arguments: %d to %d expected.\n"),"auread",1,2)); + end + // Append .au extension if it's missing: + if strindex(aufile,".")==[] then + aufile = aufile+".au"; + end + + [fid,junk] = mopen(aufile,"rb",0); + if junk<0 then + error(msprintf(gettext("%s: Cannot open file %s.\n"),"auread",aufile)); + end + + snd = read_sndhdr(fid); + + Fs = snd("rate")*snd("chans"); + bits = snd("bits"); + + // Determine if caller wants data: + if nargin<2 then + ext = []; + end + // Default - read all samples + exts = prod(size(ext)); + + if ext <> [] then + if convstr(ext)=="size" then + // Caller doesn't want data - just data size: + mclose(fid); + y = [snd("samples"),snd("chans")]; + return + elseif exts>2 then + error(msprintf(gettext("%s: An error occurred: %s\n"),"auread",gettext("Index range must be specified as a scalar or a 2 elements vector."))); + elseif exts==1 then + ext = [1,ext]; + end + end + + // Read data: + + snd = read_sndata(fid,snd,ext); + y = snd("data"); + mclose(fid); + +endfunction + + +function [new_snd]=read_sndata(fid,snd,ext) + new_snd=[]; + SamplesPerChannel = snd("samples"); + BytesPerSample = snd("bits")/8; + // format: + if snd("format")==1 then + dtype = "ucb"; // 8-bit mu-law + elseif snd("format")==2 then + dtype = "cb"; // 8-bit linear + elseif snd("format")==3 then + dtype = "sb"; // 16-bit linear + elseif snd("format")==5 then + dtype = "ib"; // 32-bit linear + elseif snd("format")==6 then + dtype = "fb"; // Single precision + elseif snd("format")==7 then + dtype = "db"; // Double-precision + else + error("Unrecognized data format.") + end + + // sample range to read: + if ext==[] then + ext = [1,SamplesPerChannel]; + // all samples + else + if prod(size(ext))~=2 then + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndata",gettext("Sample limit vector must have 2 elements."))); + end + if ext(1)<1|ext(2)>SamplesPerChannel then + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndata",gettext("Sample limits out of range."))); + end + if ext(1)>ext(2) then + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndata",gettext("Sample limits must be given in ascending order."))); + end + end + // Skip over leading samples: + if ext(1)>1 then + // Skip over leading samples, if specified: + mseek(BytesPerSample*(ext(1)-1)*snd("chans"),fid,"cur"); + if (merror(fid) <> 0) then + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndata",gettext("Error in file format."))); + end + end + + // Read desired data: + nSPCext = ext(2)-ext(1)+1; + // # samples per channel in extraction range + extSamples = snd("chans")*nSPCext; + data=mget(snd("chans")*nSPCext,dtype,fid); + // Rearrange data into a matrix with one channel per column: + // XXXX A finir + data = matrix(data,snd("chans"),nSPCext); + // Convert and normalize data range: + if snd("format")==1 then + // 8-bit mu-law + data = mu2lin(data); + elseif snd("format")==2 then + // 8-bit linear + data = data*(2^(-7)); + elseif snd("format")==3 then + // 16-bit linear + data = data*(2^(-15)); + elseif snd("format")==5 then + // 32-bit linear + data = data*(2^(-31)); + elseif snd("format")==6|snd("format")==7 then + // Float/Double + //a = min(data); + //b = max(data); + //data = (data-a)/(b-a)*2-1; + end + new_snd = snd; + new_snd("data")=data + return +endfunction + +function [snd]=read_sndhdr(fid) + // Read file header: + snd=tlist(["snd","offset","databytes","format","rate","chans","data","info","bits","samples","magic"]) + + snd.magic = ascii(mget(4,"c",fid)) + if snd.magic~=".snd", + error("Not a .au sound file.") + end + + snd("offset")=mget(1,"uib",fid) + snd("databytes")=mget(1,"uib",fid) + snd("format")=mget(1,"uib",fid) + snd("rate")=mget(1,"uib",fid) + snd("chans")=mget(1,"uib",fid) + + // Directly determine how long info string is: + info_len = snd("offset")-24; + [info,cnt] = mtlb_fread(fid,info_len,"char"); + snd("info")=stripblanks(ascii(info')) + if cnt~=info_len then + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndhdr",gettext("Error while reading sound file."))); + end + + // Determine file length + mseek(0,fid,"end"); + // Go to end of file + file_len = mtell(fid); + // Get position in bytes + mseek(snd("offset"),fid,"set"); + // Reposition file pointer + snd("databytes")=file_len-snd("offset") + + // Interpret format: + if snd("format")==1 then + snd("bits")=8 + // 8-bit mu-law + elseif snd("format")==2 then + snd("bits")=8 + // 8-bit linear + elseif snd("format")==3 then + snd("bits")=16 + // 16-bit linear + elseif snd("format")==5 then + snd("bits")=32 + // 32-bit linear + elseif snd("format")==6 then + snd("bits")=32 + // Single precision + elseif snd("format")==7 then + snd("bits")=64 + // Double-precision + else + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndhdr",gettext("Unrecognized data format."))); + end + // Determine # of samples per channel: + snd("samples")=snd("databytes")*8/snd("bits")/snd("chans") + if snd("samples")~=fix(snd("samples")) then + error(msprintf(gettext("%s: An error occurred: %s\n"),"read_sndhdr",gettext("Truncated data file."))); + end +endfunction |