Bump version numbers to 6.2.0
[scilab.git] / scilab / modules / sound / macros / auwrite.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) ???? - INRIA - Scilab
3 //
4 // Copyright (C) 2012 - 2016 - Scilab Enterprises
5 //
6 // This file is hereby licensed under the terms of the GNU GPL v2.0,
7 // pursuant to article 5.3.4 of the CeCILL v.2.1.
8 // This file was originally licensed under the terms of the CeCILL v2.1,
9 // and continues to be available under such terms.
10 // For more information, see the COPYING file which you should have received
11 // along with this program.
12
13 function auwrite(y,Fs,nbits,method,aufile)
14     //Write .au sound file.
15     //auwrite(y,aufile) writes a sound file specified by the
16     //string aufile.  The data should be arranged with one channel
17     //per column.  Amplitude values outside the range [-1,+1] are
18     //clipped prior to writing.
19     //
20     //Supports multi-channel data for 8-bit mu-law, and 8- and
21     //16-bit linear formats:
22     //
23     //auwrite(y,Fs,aufile) specifies the sample rate of the data
24     //in Hertz.
25     //
26     //auwrite(y,Fs,bits,aufile) selects the number of bits in
27     //the encoder.  Allowable settings are bits=8 and bits=16.
28     //
29     //auwrite(y,Fs,bits,method,aufile) allows selection of the
30     //encoding method, which can be either 'mu' or 'linear'.
31     //Note that mu-law files must be 8-bit. By default, method='mu'.
32
33     // test :
34     // auwrite(y,44100,8,'mu','poo.au')
35     // aplay -c 1 -f MU_LAW --rate=22050 poo.au
36     //
37
38     // Get default:
39     [nargout,nargin] = argn(0)
40     Fs_pref = 22050;
41     nbits_pref = 8;
42     method_pref = "mu";
43
44     if nargin==1 then
45         error(msprintf(gettext("%s: Wrong number of input arguments: %d to %d expected.\n"),"auwrite",2,5));
46     elseif nargin>5 then
47         error(msprintf(gettext("%s: Wrong number of input arguments: %d to %d expected.\n"),"auwrite",2,5));
48     elseif nargin==4 then
49         aufile = method;
50         method = method_pref;
51     elseif nargin==3 then
52         aufile = nbits;
53         method = method_pref;
54         nbits = nbits_pref;
55     elseif nargin==2 then
56         aufile = Fs;
57         method = method_pref;
58         nbits = nbits_pref;
59         Fs = Fs_pref;
60     end
61
62     // Check aufile
63     // ------------
64     if type(aufile) <> 10 then
65         error(msprintf(gettext("%s: Wrong values for input argument: Filename must be a string.\n"),"auwrite"));
66     end
67     // Append .au extension if it is missing
68     tmp = convstr(fileparts(aufile,"extension"))
69     if tmp=="" | (~isfile(aufile) & tmp<>".au")
70         aufile = aufile + ".au";
71     end
72     [fid,junk] = mopen(aufile,"wb",0) // Big-endian
73     if junk<0 then
74         error(msprintf(gettext("%s: Cannot open file %s.\n"),"auwrite",aufile));
75     end
76
77     // Check y data
78     // ------------
79     if length(size(y)) > 2 then
80         mclose(fid)
81         error(msprintf(gettext("%s: An error occurred: %s\n"),"auwrite",gettext("Data array must have 1- or 2-dimensions only.")));
82     end
83     if size(y,2)==1 then
84         y = y';
85     end
86     // Clip data to normalized range [-1,+1]:
87     i = matrix(find(abs(y)>1),1,-1);
88     if ~(i==[]) then
89         y(i) = sign(y(i));
90         warning(gettext("Data clipped during write to file."));
91     end
92
93     // Writing data
94     // ------------
95     snd = write_sndhdr(fid,Fs,nbits,method,size(y));
96
97     status = write_sndata(fid,snd,y)
98     mclose(fid)
99     if status
100         error(msprintf(gettext("%s: An error occurred: %s\n"),"auwrite",gettext("Error while writing sound file.")));
101     end
102 endfunction
103
104 function status = write_sndata(fid,snd,data)
105     status = 0;
106     if snd("format")==1 then
107         dtype = "uc";
108         data = lin2mu(data);
109     elseif snd("format")==2 then
110         dtype = "c";// 'int8';
111         data = round(data*(2^7-1));
112     elseif snd("format")==3 then
113         dtype = "sb";// 'int16"
114         data = round(data*(2^15-1));
115     elseif snd("format")==5 then
116         dtype = "ib";// 'int32"
117         data = round(data*(2^31-1));
118     elseif snd("format")==6 then
119         dtype = "fb";
120         //
121     elseif snd("format")==7 then
122         dtype = "db";// double precision
123         //
124     else
125         status = -1;
126         return
127     end
128     total_samples = snd("samples")*snd("chans");
129     mput(data,dtype,fid);
130 endfunction
131
132 function snd = write_sndhdr(fid,Fs,nbits,method,sz)
133     // write header part
134     if method=="mu" then
135         if nbits~=8 then
136             mclose(fid)
137             error(msprintf(gettext("%s: An error occurred: %s\n"),"auwrite/write_sndhdr", gettext("Mu-law can only be used with 8 bit data. Use method=''linear'' instead.")));
138         end
139         snd.format = 1;
140         snd.bits = 8;
141     elseif method=="linear" then
142         if nbits==8 then
143             snd.format=2  // 8-bit linear
144             snd.bits=8
145         elseif nbits==16 then
146             snd.format=3  // 16-bit linear
147             snd.bits=16
148         elseif nbits==32 then
149             snd.format=5 //  32-bit linear
150             snd.bits=32;
151         elseif nbits==64 then
152             snd.format=7;  // Double-precision
153             snd.bits=64;
154         else
155             mclose(fid)
156             error(msprintf(gettext("%s: An error occurred: %s\n"),"auwrite/write_sndhdr", gettext("Unrecognized data format.")));
157             return
158         end
159     else
160         mclose(fid)
161         error(msprintf(gettext("%s: An error occurred: %s\n"),"auwrite/write_sndhdr", gettext("Unrecognized data format.")));
162     end
163
164     // Define sound header structure:
165     snd("samples")=sz(2)
166     snd("chans")=sz(1)
167     total_samples = snd("samples")*snd("chans");
168     bytes_per_sample = ceil(snd("bits")/8);
169     snd("rate")=Fs
170     snd("databytes")=bytes_per_sample*total_samples
171     snd("offset")=28
172     snd("info")="SCI0";
173
174     mput(ascii(".snd"),"c",fid); // magic number
175     mput(snd("offset"),"uib",fid); // data location
176     mput(snd("databytes"),"uib",fid); // size in bytes
177     mput(snd("format"),"uib",fid); // data format
178     //
179     mput(snd("rate")/snd("chans"),"uib",fid); // sample rate
180     mput(snd("chans"),"uib",fid); // channels
181     mput(ascii(snd("info")),"c",fid);  // info
182 endfunction