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