1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
|