wolffd@0
|
1 function [Y,FS,NBITS,OPTS] = mp3read(FILE,N,MONO,DOWNSAMP,DELAY)
|
wolffd@0
|
2 % MP3READ Read MP3 audio file via use of external binaries.
|
wolffd@0
|
3 % Y = MP3READ(FILE) reads an mp3-encoded audio file into the
|
wolffd@0
|
4 % vector Y just like wavread reads a wav-encoded file (one channel
|
wolffd@0
|
5 % per column). Extension ".mp3" is added if FILE has none.
|
wolffd@0
|
6 % Also accepts other formats of wavread, such as
|
wolffd@0
|
7 % Y = MP3READ(FILE,N) to read just the first N sample frames (N
|
wolffd@0
|
8 % scalar), or the frames from N(1) to N(2) if N is a two-element vector.
|
wolffd@0
|
9 % Y = MP3READ(FILE,FMT) or Y = mp3read(FILE,N,FMT)
|
wolffd@0
|
10 % with FMT as 'native' returns int16 samples instead of doubles;
|
wolffd@0
|
11 % FMT can be 'double' for default behavior (to exactly mirror the
|
wolffd@0
|
12 % syntax of wavread).
|
wolffd@0
|
13 %
|
wolffd@0
|
14 % [Y,FS,NBITS,OPTS] = MP3READ(FILE...) returns extra information:
|
wolffd@0
|
15 % FS is the sampling rate, NBITS is the bit depth (always 16),
|
wolffd@0
|
16 % OPTS.fmt is a format info string; OPTS has multiple other
|
wolffd@0
|
17 % fields, see WAVREAD.
|
wolffd@0
|
18 %
|
wolffd@0
|
19 % SIZ = MP3READ(FILE,'size') returns the size of the audio data contained
|
wolffd@0
|
20 % in the file in place of the actual audio data, returning the
|
wolffd@0
|
21 % 2-element vector SIZ=[samples channels].
|
wolffd@0
|
22 %
|
wolffd@0
|
23 % [Y...] = MP3READ(FILE,N,MONO,DOWNSAMP,DELAY) extends the
|
wolffd@0
|
24 % WAVREAD syntax to allow access to special features of the
|
wolffd@0
|
25 % mpg123 engine: MONO = 1 forces output to be mono (by
|
wolffd@0
|
26 % averaging stereo channels); DOWNSAMP = 2 or 4 downsamples by
|
wolffd@0
|
27 % a factor of 2 or 4 (thus FS returns as 22050 or 11025
|
wolffd@0
|
28 % respectively for a 44 kHz mp3 file);
|
wolffd@0
|
29 % To accommodate a bug in mpg123-0.59, DELAY controls how many
|
wolffd@0
|
30 % "warm up" samples to drop at the start of the file; the
|
wolffd@0
|
31 % default value of 2257 makes an mp3write/mp3read loop for a 44
|
wolffd@0
|
32 % kHz mp3 file be as close as possible to being temporally
|
wolffd@0
|
33 % aligned; specify as 0 to prevent discard of initial samples.
|
wolffd@0
|
34 % For later versions of mpg123 (e.g. 1.9.0) this is not needed;
|
wolffd@0
|
35 % a flag in mp3read.m makes the default DELAY zero in this case.
|
wolffd@0
|
36 %
|
wolffd@0
|
37 % [Y...] = MP3READ(URL...) uses the built-in network
|
wolffd@0
|
38 % functionality of mpg123 to read an MP3 file across the
|
wolffd@0
|
39 % network. URL must be of the form 'http://...' or
|
wolffd@0
|
40 % 'ftp://...'. 'size' and OPTS are not available in this mode.
|
wolffd@0
|
41 %
|
wolffd@0
|
42 % Example:
|
wolffd@0
|
43 % To read an mp3 file as doubles at its original width and sampling rate:
|
wolffd@0
|
44 % [Y,FS] = mp3read('piano.mp3');
|
wolffd@0
|
45 % To read the first 1 second of the same file, downsampled by a
|
wolffd@0
|
46 % factor of 4, cast to mono, using the default filename
|
wolffd@0
|
47 % extension:
|
wolffd@0
|
48 % [Y,FS4] = mp3read('piano', FS/4, 1, 4);
|
wolffd@0
|
49 %
|
wolffd@0
|
50 % Note: Because the mp3 format encodes samples in blocks of 26 ms (at
|
wolffd@0
|
51 % 44 kHz), and because of the "warm up" period of the encoder,
|
wolffd@0
|
52 % the file length may not be exactly what you expect, depending
|
wolffd@0
|
53 % on your version of mpg123 (recent versions fix warmup).
|
wolffd@0
|
54 %
|
wolffd@0
|
55 % Note: requires external binaries mpg123 and mp3info; you
|
wolffd@0
|
56 % can find binaries for several platforms at:
|
wolffd@0
|
57 % http://labrosa.ee.columbia.edu/matlab/mp3read.html
|
wolffd@0
|
58 %
|
wolffd@0
|
59 % See also mp3write, wavread.
|
wolffd@0
|
60
|
wolffd@0
|
61 % $Header: /Users/dpwe/matlab/columbiafns/RCS/mp3read.m,v 1.7 2010/04/09 18:13:00 dpwe Exp dpwe $
|
wolffd@0
|
62
|
wolffd@0
|
63 % 2003-07-20 dpwe@ee.columbia.edu This version calls mpg123.
|
wolffd@0
|
64 % 2004-08-31 Fixed to read whole files correctly
|
wolffd@0
|
65 % 2004-09-08 Uses mp3info to get info about mp3 files too
|
wolffd@0
|
66 % 2004-09-18 Reports all mp3info fields in OPTS.fmt; handles MPG2LSF sizes
|
wolffd@0
|
67 % + added MONO, DOWNSAMP flags, changed default behavior.
|
wolffd@0
|
68 % 2005-09-28 Fixed bug reading full-rate stereo as 1ch (thx bjoerns@vjk.dk)
|
wolffd@0
|
69 % 2006-09-17 Chop off initial 2257 sample delay (for 44.1 kHz mp3)
|
wolffd@0
|
70 % so read-write loop doesn't get progressively delayed.
|
wolffd@0
|
71 % You can suppress this with a 5th argument of 0.
|
wolffd@0
|
72 % 2007-02-04 Added support for FMT argument to match wavread
|
wolffd@0
|
73 % Added automatic selection of binary etc. to allow it
|
wolffd@0
|
74 % to work cross-platform without editing prior to
|
wolffd@0
|
75 % submitting to Matlab File Exchange
|
wolffd@0
|
76 % 2007-07-23 Tweaks to 'size' mode so it exactly agrees with read data.
|
wolffd@0
|
77 % 2009-03-15 Added fixes so 'http://...' file URLs will work.
|
wolffd@0
|
78 % 2009-03-26 Added filename length check to http: test (thx fabricio guzman)
|
wolffd@0
|
79
|
wolffd@0
|
80 % find our baseline directory
|
wolffd@0
|
81 path = fileparts(which('mp3read'));
|
wolffd@0
|
82
|
wolffd@0
|
83 % %%%%% Directory for temporary file (if needed)
|
wolffd@0
|
84 % % Try to read from environment, or use /tmp if it exists, or use CWD
|
wolffd@0
|
85 tmpdir = getenv('TMPDIR');
|
wolffd@0
|
86 if isempty(tmpdir) || exist(tmpdir,'file')==0
|
wolffd@0
|
87 tmpdir = '/tmp';
|
wolffd@0
|
88 end
|
wolffd@0
|
89 if exist(tmpdir,'file')==0
|
wolffd@0
|
90 tmpdir = '';
|
wolffd@0
|
91 end
|
wolffd@0
|
92 % ensure it exists
|
wolffd@0
|
93 %if length(tmpdir) > 0 && exist(tmpdir,'file')==0
|
wolffd@0
|
94 % mkdir(tmpdir);
|
wolffd@0
|
95 %end
|
wolffd@0
|
96
|
wolffd@0
|
97 %%%%%% Command to delete temporary file (if needed)
|
wolffd@0
|
98 rmcmd = 'rm';
|
wolffd@0
|
99
|
wolffd@0
|
100 %%%%%% Location of the binaries - attempt to choose automatically
|
wolffd@0
|
101 %%%%%% (or edit to be hard-coded for your installation)
|
wolffd@0
|
102 ext = lower(computer);
|
wolffd@0
|
103 if ispc
|
wolffd@0
|
104 ext = 'exe';
|
wolffd@0
|
105 rmcmd = 'del';
|
wolffd@0
|
106 end
|
wolffd@0
|
107 % mpg123-0.59 inserts silence at the start of decoded files, which
|
wolffd@0
|
108 % we compensate. However, this is fixed in mpg123-1.9.0, so
|
wolffd@0
|
109 % make this flag 1 only if you have mpg123-0.5.9
|
wolffd@0
|
110 MPG123059 = 0;
|
wolffd@0
|
111 mpg123 = fullfile(path,['mpg123.',ext]);
|
wolffd@0
|
112 mp3info = fullfile(path,['mp3info.',ext]);
|
wolffd@0
|
113
|
wolffd@0
|
114 %%%%% Check for network mode
|
wolffd@0
|
115 if length(FILE) > 6 && (strcmp(lower(FILE(1:7)),'http://') == 1 ...
|
wolffd@0
|
116 || strcmp(lower(FILE(1:6)),'ftp://'))
|
wolffd@0
|
117 % mp3info not available over network
|
wolffd@0
|
118 OVERNET = 1;
|
wolffd@0
|
119 else
|
wolffd@0
|
120 OVERNET = 0;
|
wolffd@0
|
121 end
|
wolffd@0
|
122
|
wolffd@0
|
123
|
wolffd@0
|
124 %%%%% Process input arguments
|
wolffd@0
|
125 if nargin < 2
|
wolffd@0
|
126 N = 0;
|
wolffd@0
|
127 end
|
wolffd@0
|
128
|
wolffd@0
|
129 % Check for FMT spec (per wavread)
|
wolffd@0
|
130 FMT = 'double';
|
wolffd@0
|
131 if ischar(N)
|
wolffd@0
|
132 FMT = lower(N);
|
wolffd@0
|
133 N = 0;
|
wolffd@0
|
134 end
|
wolffd@0
|
135
|
wolffd@0
|
136 if length(N) == 1
|
wolffd@0
|
137 % Specified N was upper limit
|
wolffd@0
|
138 N = [1 N];
|
wolffd@0
|
139 end
|
wolffd@0
|
140 if nargin < 3
|
wolffd@0
|
141 forcemono = 0;
|
wolffd@0
|
142 else
|
wolffd@0
|
143 % Check for 3rd arg as FMT
|
wolffd@0
|
144 if ischar(MONO)
|
wolffd@0
|
145 FMT = lower(MONO);
|
wolffd@0
|
146 MONO = 0;
|
wolffd@0
|
147 end
|
wolffd@0
|
148 forcemono = (MONO ~= 0);
|
wolffd@0
|
149 end
|
wolffd@0
|
150 if nargin < 4
|
wolffd@0
|
151 downsamp = 1;
|
wolffd@0
|
152 else
|
wolffd@0
|
153 downsamp = DOWNSAMP;
|
wolffd@0
|
154 end
|
wolffd@0
|
155 if downsamp ~= 1 && downsamp ~= 2 && downsamp ~= 4
|
wolffd@0
|
156 error('DOWNSAMP can only be 1, 2, or 4');
|
wolffd@0
|
157 end
|
wolffd@0
|
158
|
wolffd@0
|
159 % process DELAY option (nargin 5) after we've read the SR
|
wolffd@0
|
160
|
wolffd@0
|
161 if strcmp(FMT,'native') == 0 && strcmp(FMT,'double') == 0 && ...
|
wolffd@0
|
162 strcmp(FMT,'size') == 0
|
wolffd@0
|
163 error(['FMT must be ''native'' or ''double'' (or ''size''), not ''',FMT,'''']);
|
wolffd@0
|
164 end
|
wolffd@0
|
165
|
wolffd@0
|
166
|
wolffd@0
|
167 %%%%%% Constants
|
wolffd@0
|
168 NBITS=16;
|
wolffd@0
|
169
|
wolffd@0
|
170 %%%%% add extension if none (like wavread)
|
wolffd@0
|
171 [path,file,ext] = fileparts(FILE);
|
wolffd@0
|
172 if isempty(ext)
|
wolffd@0
|
173 FILE = [FILE, '.mp3'];
|
wolffd@0
|
174 end
|
wolffd@0
|
175
|
wolffd@0
|
176 %%%%% maybe expand ~ %%%%%%
|
wolffd@0
|
177 if FILE(1) == '~'
|
wolffd@0
|
178 FILE = [getenv('HOME'),FILE(2:end)];
|
wolffd@0
|
179 end
|
wolffd@0
|
180
|
wolffd@0
|
181
|
wolffd@0
|
182 if ~OVERNET
|
wolffd@0
|
183 %%%%%% Probe file to find format, size, etc. using "mp3info" utility
|
wolffd@0
|
184 cmd = ['"',mp3info, '" -r m -p "%Q %u %b %r %v * %C %e %E %L %O %o %p" "', FILE,'"'];
|
wolffd@0
|
185 % Q = samprate, u = #frames, b = #badframes (needed to get right answer from %u)
|
wolffd@0
|
186 % r = bitrate, v = mpeg version (1/2/2.5)
|
wolffd@0
|
187 % C = Copyright, e = emph, E = CRC, L = layer, O = orig, o = mono, p = pad
|
wolffd@0
|
188 w = mysystem(cmd);
|
wolffd@0
|
189 % Break into numerical and ascii parts by finding the delimiter we put in
|
wolffd@0
|
190 starpos = findstr(w,'*');
|
wolffd@0
|
191 nums = str2num(w(1:(starpos - 2)));
|
wolffd@0
|
192 strs = tokenize(w((starpos+2):end));
|
wolffd@0
|
193
|
wolffd@0
|
194 SR = nums(1);
|
wolffd@0
|
195 nframes = nums(2);
|
wolffd@0
|
196 nchans = 2 - strcmp(strs{6}, 'mono');
|
wolffd@0
|
197 layer = length(strs{4});
|
wolffd@0
|
198 bitrate = nums(4)*1000;
|
wolffd@0
|
199 mpgv = nums(5);
|
wolffd@0
|
200 % Figure samples per frame, after
|
wolffd@0
|
201 % http://board.mp3-tech.org/view.php3?bn=agora_mp3techorg&key=1019510889
|
wolffd@0
|
202 if layer == 1
|
wolffd@0
|
203 smpspfrm = 384;
|
wolffd@0
|
204 elseif SR < 32000 && layer ==3
|
wolffd@0
|
205 smpspfrm = 576;
|
wolffd@0
|
206 if mpgv == 1
|
wolffd@0
|
207 error('SR < 32000 but mpeg version = 1');
|
wolffd@0
|
208 end
|
wolffd@0
|
209 else
|
wolffd@0
|
210 smpspfrm = 1152;
|
wolffd@0
|
211 end
|
wolffd@0
|
212
|
wolffd@0
|
213 OPTS.fmt.mpgBitrate = bitrate;
|
wolffd@0
|
214 OPTS.fmt.mpgVersion = mpgv;
|
wolffd@0
|
215 % fields from wavread's OPTS
|
wolffd@0
|
216 OPTS.fmt.nAvgBytesPerSec = bitrate/8;
|
wolffd@0
|
217 OPTS.fmt.nSamplesPerSec = SR;
|
wolffd@0
|
218 OPTS.fmt.nChannels = nchans;
|
wolffd@0
|
219 OPTS.fmt.nBlockAlign = smpspfrm/SR*bitrate/8;
|
wolffd@0
|
220 OPTS.fmt.nBitsPerSample = NBITS;
|
wolffd@0
|
221 OPTS.fmt.mpgNFrames = nframes;
|
wolffd@0
|
222 OPTS.fmt.mpgCopyright = strs{1};
|
wolffd@0
|
223 OPTS.fmt.mpgEmphasis = strs{2};
|
wolffd@0
|
224 OPTS.fmt.mpgCRC = strs{3};
|
wolffd@0
|
225 OPTS.fmt.mpgLayer = strs{4};
|
wolffd@0
|
226 OPTS.fmt.mpgOriginal = strs{5};
|
wolffd@0
|
227 OPTS.fmt.mpgChanmode = strs{6};
|
wolffd@0
|
228 OPTS.fmt.mpgPad = strs{7};
|
wolffd@0
|
229 OPTS.fmt.mpgSampsPerFrame = smpspfrm;
|
wolffd@0
|
230 else
|
wolffd@0
|
231 % OVERNET mode
|
wolffd@0
|
232 OPTS = [];
|
wolffd@0
|
233 % guesses
|
wolffd@0
|
234 smpspfrm = 1152;
|
wolffd@0
|
235 SR = 44100;
|
wolffd@0
|
236 nframes = 0;
|
wolffd@0
|
237 end
|
wolffd@0
|
238
|
wolffd@0
|
239 if SR == 16000 && downsamp == 4
|
wolffd@0
|
240 error('mpg123 will not downsample 16 kHz files by 4 (only 2)');
|
wolffd@0
|
241 end
|
wolffd@0
|
242
|
wolffd@0
|
243 % from libmpg123/frame.h
|
wolffd@0
|
244 GAPLESS_DELAY = 529;
|
wolffd@0
|
245
|
wolffd@0
|
246 % process or set delay
|
wolffd@0
|
247 if nargin < 5
|
wolffd@0
|
248
|
wolffd@0
|
249 if MPG123059
|
wolffd@0
|
250 mpg123delay44kHz = 2257; % empirical delay of lame/mpg123 loop
|
wolffd@0
|
251 mpg123delay16kHz = 1105; % empirical delay of lame/mpg123 loop
|
wolffd@0
|
252 % for 16 kHz sampling - one 1152
|
wolffd@0
|
253 % sample frame less??
|
wolffd@0
|
254 if SR == 16000
|
wolffd@0
|
255 rawdelay = mpg123delay16kHz;
|
wolffd@0
|
256 else
|
wolffd@0
|
257 rawdelay = mpg123delay44kHz; % until we know better
|
wolffd@0
|
258 end
|
wolffd@0
|
259 delay = round(rawdelay/downsamp);
|
wolffd@0
|
260 else
|
wolffd@0
|
261 % seems like predelay is fixed in mpg123-1.9.0
|
wolffd@0
|
262 delay = 0;
|
wolffd@0
|
263 end
|
wolffd@0
|
264 else
|
wolffd@0
|
265 delay = DELAY;
|
wolffd@0
|
266 end
|
wolffd@0
|
267
|
wolffd@0
|
268 if downsamp == 1
|
wolffd@0
|
269 downsampstr = '';
|
wolffd@0
|
270 else
|
wolffd@0
|
271 downsampstr = [' -',num2str(downsamp)];
|
wolffd@0
|
272 end
|
wolffd@0
|
273 FS = SR/downsamp;
|
wolffd@0
|
274
|
wolffd@0
|
275 if forcemono == 1
|
wolffd@0
|
276 nchans = 1;
|
wolffd@0
|
277 chansstr = ' -m';
|
wolffd@0
|
278 else
|
wolffd@0
|
279 chansstr = '';
|
wolffd@0
|
280 end
|
wolffd@0
|
281
|
wolffd@0
|
282 % Size-reading version
|
wolffd@0
|
283 if strcmp(FMT,'size') == 1
|
wolffd@0
|
284 if MPG123059
|
wolffd@0
|
285 Y = [floor(smpspfrm*nframes/downsamp)-delay, nchans];
|
wolffd@0
|
286 else
|
wolffd@0
|
287 Y = [floor(smpspfrm*nframes/downsamp)-GAPLESS_DELAY, nchans];
|
wolffd@0
|
288 end
|
wolffd@0
|
289 else
|
wolffd@0
|
290
|
wolffd@0
|
291 % Temporary file to use
|
wolffd@0
|
292 tmpfile = fullfile(tmpdir, ['tmp',num2str(round(1000*rand(1))),'.wav']);
|
wolffd@0
|
293
|
wolffd@0
|
294 skipx = 0;
|
wolffd@0
|
295 skipblks = 0;
|
wolffd@0
|
296 skipstr = '';
|
wolffd@0
|
297 sttfrm = N(1)-1;
|
wolffd@0
|
298
|
wolffd@0
|
299 % chop off transcoding delay?
|
wolffd@0
|
300 %sttfrm = sttfrm + delay; % empirically measured
|
wolffd@0
|
301 % no, we want to *decode* those samples, then drop them
|
wolffd@0
|
302 % so delay gets added to skipx instead
|
wolffd@0
|
303
|
wolffd@0
|
304 if sttfrm > 0
|
wolffd@0
|
305 skipblks = floor(sttfrm*downsamp/smpspfrm);
|
wolffd@0
|
306 skipx = sttfrm - (skipblks*smpspfrm/downsamp);
|
wolffd@0
|
307 skipstr = [' -k ', num2str(skipblks)];
|
wolffd@0
|
308 end
|
wolffd@0
|
309 skipx = skipx + delay;
|
wolffd@0
|
310
|
wolffd@0
|
311 lenstr = '';
|
wolffd@0
|
312 endfrm = -1;
|
wolffd@0
|
313 decblk = 0;
|
wolffd@0
|
314 if length(N) > 1
|
wolffd@0
|
315 endfrm = N(2);
|
wolffd@0
|
316 if endfrm > sttfrm
|
wolffd@0
|
317 decblk = ceil((endfrm+delay)*downsamp/smpspfrm) - skipblks + 10;
|
wolffd@0
|
318 % we read 10 extra blks (+10) to cover the case where up to 10 bad
|
wolffd@0
|
319 % blocks are included in the part we are trying to read (it happened)
|
wolffd@0
|
320 lenstr = [' -n ', num2str(decblk)];
|
wolffd@0
|
321 % This generates a spurious "Warn: requested..." if reading right
|
wolffd@0
|
322 % to the last sample by index (or bad blks), but no matter.
|
wolffd@0
|
323 end
|
wolffd@0
|
324 end
|
wolffd@0
|
325
|
wolffd@0
|
326 % Run the decode
|
wolffd@0
|
327 cmd=['"',mpg123,'"', downsampstr, chansstr, skipstr, lenstr, ...
|
wolffd@0
|
328 ' -q -w "', tmpfile,'" "',FILE,'"'];
|
wolffd@0
|
329 %w =
|
wolffd@0
|
330 mysystem(cmd);
|
wolffd@0
|
331
|
wolffd@0
|
332 % Load the data (may update FS if it was based on a guess previously)
|
wolffd@0
|
333 [Y,FS] = wavread(tmpfile);
|
wolffd@0
|
334
|
wolffd@0
|
335 % % pad delay on to end, just in case
|
wolffd@0
|
336 % Y = [Y; zeros(delay,size(Y,2))];
|
wolffd@0
|
337 % % no, the saved file is just longer
|
wolffd@0
|
338
|
wolffd@0
|
339 if decblk > 0 && length(Y) < decblk*smpspfrm/downsamp
|
wolffd@0
|
340 % This will happen if the selected block range includes >1 bad block
|
wolffd@0
|
341 disp(['Warn: requested ', num2str(decblk*smpspfrm/downsamp),' frames, returned ',num2str(length(Y))]);
|
wolffd@0
|
342 end
|
wolffd@0
|
343
|
wolffd@0
|
344 % Delete tmp file
|
wolffd@0
|
345 mysystem([rmcmd,' "', tmpfile,'"']);
|
wolffd@0
|
346
|
wolffd@0
|
347 % debug
|
wolffd@0
|
348 % disp(['sttfrm=',num2str(sttfrm),' endfrm=',num2str(endfrm),' skipx=',num2str(skipx),' delay=',num2str(delay),' len=',num2str(length(Y))]);
|
wolffd@0
|
349
|
wolffd@0
|
350 % Select the desired part
|
wolffd@0
|
351 if skipx+endfrm-sttfrm > length(Y)
|
wolffd@0
|
352 endfrm = length(Y)+sttfrm-skipx;
|
wolffd@0
|
353 end
|
wolffd@0
|
354
|
wolffd@0
|
355 if endfrm > sttfrm
|
wolffd@0
|
356 Y = Y(skipx+(1:(endfrm-sttfrm)),:);
|
wolffd@0
|
357 elseif skipx > 0
|
wolffd@0
|
358 Y = Y((skipx+1):end,:);
|
wolffd@0
|
359 end
|
wolffd@0
|
360
|
wolffd@0
|
361 % Convert to int if format = 'native'
|
wolffd@0
|
362 if strcmp(FMT,'native')
|
wolffd@0
|
363 Y = int16((2^15)*Y);
|
wolffd@0
|
364 end
|
wolffd@0
|
365
|
wolffd@0
|
366 end
|
wolffd@0
|
367
|
wolffd@0
|
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
369 function w = mysystem(cmd)
|
wolffd@0
|
370 % Run system command; report error; strip all but last line
|
wolffd@0
|
371 [s,w] = system(cmd);
|
wolffd@0
|
372 if s ~= 0
|
wolffd@0
|
373 error(['unable to execute ',cmd,' (',w,')']);
|
wolffd@0
|
374 end
|
wolffd@0
|
375 % Keep just final line
|
wolffd@0
|
376 w = w((1+max([0,findstr(w,10)])):end);
|
wolffd@0
|
377 % Debug
|
wolffd@0
|
378 %disp([cmd,' -> ','*',w,'*']);
|
wolffd@0
|
379
|
wolffd@0
|
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
381 function a = tokenize(s,t)
|
wolffd@0
|
382 % Break space-separated string into cell array of strings.
|
wolffd@0
|
383 % Optional second arg gives alternate separator (default ' ')
|
wolffd@0
|
384 % 2004-09-18 dpwe@ee.columbia.edu
|
wolffd@0
|
385 if nargin < 2; t = ' '; end
|
wolffd@0
|
386 a = [];
|
wolffd@0
|
387 p = 1;
|
wolffd@0
|
388 n = 1;
|
wolffd@0
|
389 l = length(s);
|
wolffd@0
|
390 nss = findstr([s(p:end),t],t);
|
wolffd@0
|
391 for ns = nss
|
wolffd@0
|
392 % Skip initial spaces (separators)
|
wolffd@0
|
393 if ns == p
|
wolffd@0
|
394 p = p+1;
|
wolffd@0
|
395 else
|
wolffd@0
|
396 if p <= l
|
wolffd@0
|
397 a{n} = s(p:(ns-1));
|
wolffd@0
|
398 n = n+1;
|
wolffd@0
|
399 p = ns+1;
|
wolffd@0
|
400 end
|
wolffd@0
|
401 end
|
wolffd@0
|
402 end
|
wolffd@0
|
403
|