1function apmtest(task, testname, filepath, casenumber, legacy)
2%APMTEST is a tool to process APM file sets and easily display the output.
3%   APMTEST(TASK, TESTNAME, CASENUMBER) performs one of several TASKs:
4%     'test'  Processes the files to produce test output.
5%     'list'  Prints a list of cases in the test set, preceded by their
6%             CASENUMBERs.
7%     'show'  Uses spclab to show the test case specified by the
8%             CASENUMBER parameter.
9%
10%   using a set of test files determined by TESTNAME:
11%     'all'   All tests.
12%     'apm'   The standard APM test set (default).
13%     'apmm'  The mobile APM test set.
14%     'aec'   The AEC test set.
15%     'aecm'  The AECM test set.
16%     'agc'   The AGC test set.
17%     'ns'    The NS test set.
18%     'vad'   The VAD test set.
19%
20%   FILEPATH specifies the path to the test data files.
21%
22%   CASENUMBER can be used to select a single test case. Omit CASENUMBER,
23%   or set to zero, to use all test cases.
24%
25
26if nargin < 5 || isempty(legacy)
27  % Set to true to run old VQE recordings.
28  legacy = false;
29end
30
31if nargin < 4 || isempty(casenumber)
32  casenumber = 0;
33end
34
35if nargin < 3 || isempty(filepath)
36  filepath = 'data/';
37end
38
39if nargin < 2 || isempty(testname)
40  testname = 'all';
41end
42
43if nargin < 1 || isempty(task)
44  task = 'test';
45end
46
47if ~strcmp(task, 'test') && ~strcmp(task, 'list') && ~strcmp(task, 'show')
48  error(['TASK ' task ' is not recognized']);
49end
50
51if casenumber == 0 && strcmp(task, 'show')
52  error(['CASENUMBER must be specified for TASK ' task]);
53end
54
55inpath = [filepath 'input/'];
56outpath = [filepath 'output/'];
57refpath = [filepath 'reference/'];
58
59if strcmp(testname, 'all')
60  tests = {'apm','apmm','aec','aecm','agc','ns','vad'};
61else
62  tests = {testname};
63end
64
65if legacy
66  progname = './test';
67else
68  progname = './process_test';
69end
70
71global farFile;
72global nearFile;
73global eventFile;
74global delayFile;
75global driftFile;
76
77if legacy
78  farFile = 'vqeFar.pcm';
79  nearFile = 'vqeNear.pcm';
80  eventFile = 'vqeEvent.dat';
81  delayFile = 'vqeBuf.dat';
82  driftFile = 'vqeDrift.dat';
83else
84  farFile = 'apm_far.pcm';
85  nearFile = 'apm_near.pcm';
86  eventFile = 'apm_event.dat';
87  delayFile = 'apm_delay.dat';
88  driftFile = 'apm_drift.dat';
89end
90
91simulateMode = false;
92nErr = 0;
93nCases = 0;
94for i=1:length(tests)
95  simulateMode = false;
96
97  if strcmp(tests{i}, 'apm')
98    testdir = ['apm/'];
99    outfile = ['out'];
100    if legacy
101      opt = ['-ec 1 -agc 2 -nc 2 -vad 3'];
102    else
103      opt = ['--no_progress -hpf' ...
104          ' -aec --drift_compensation -agc --fixed_digital' ...
105          ' -ns --ns_moderate -vad'];
106    end
107
108  elseif strcmp(tests{i}, 'apm-swb')
109    simulateMode = true;
110    testdir = ['apm-swb/'];
111    outfile = ['out'];
112    if legacy
113      opt = ['-fs 32000 -ec 1 -agc 2 -nc 2'];
114    else
115      opt = ['--no_progress -fs 32000 -hpf' ...
116          ' -aec --drift_compensation -agc --adaptive_digital' ...
117          ' -ns --ns_moderate -vad'];
118    end
119  elseif strcmp(tests{i}, 'apmm')
120    testdir = ['apmm/'];
121    outfile = ['out'];
122    opt = ['-aec --drift_compensation -agc --fixed_digital -hpf -ns ' ...
123        '--ns_moderate'];
124
125  else
126    error(['TESTNAME ' tests{i} ' is not recognized']);
127  end
128
129  inpathtest = [inpath testdir];
130  outpathtest = [outpath testdir];
131  refpathtest = [refpath testdir];
132
133  if ~exist(inpathtest,'dir')
134    error(['Input directory ' inpathtest ' does not exist']);
135  end
136
137  if ~exist(refpathtest,'dir')
138    warning(['Reference directory ' refpathtest ' does not exist']);
139  end
140
141  [status, errMsg] = mkdir(outpathtest);
142  if (status == 0)
143    error(errMsg);
144  end
145
146  [nErr, nCases] = recurseDir(inpathtest, outpathtest, refpathtest, outfile, ...
147      progname, opt, simulateMode, nErr, nCases, task, casenumber, legacy);
148
149  if strcmp(task, 'test') || strcmp(task, 'show')
150    system(['rm ' farFile]);
151    system(['rm ' nearFile]);
152    if simulateMode == false
153      system(['rm ' eventFile]);
154      system(['rm ' delayFile]);
155      system(['rm ' driftFile]);
156    end
157  end
158end
159
160if ~strcmp(task, 'list')
161  if nErr == 0
162    fprintf(1, '\nAll files are bit-exact to reference\n', nErr);
163  else
164    fprintf(1, '\n%d files are NOT bit-exact to reference\n', nErr);
165  end
166end
167
168
169function [nErrOut, nCases] = recurseDir(inpath, outpath, refpath, ...
170    outfile, progname, opt, simulateMode, nErr, nCases, task, casenumber, ...
171    legacy)
172
173global farFile;
174global nearFile;
175global eventFile;
176global delayFile;
177global driftFile;
178
179dirs = dir(inpath);
180nDirs = 0;
181nErrOut = nErr;
182for i=3:length(dirs) % skip . and ..
183  nDirs = nDirs + dirs(i).isdir;
184end
185
186
187if nDirs == 0
188  nCases = nCases + 1;
189
190  if casenumber == nCases || casenumber == 0
191
192    if strcmp(task, 'list')
193      fprintf([num2str(nCases) '. ' outfile '\n'])
194    else
195      vadoutfile = ['vad_' outfile '.dat'];
196      outfile = [outfile '.pcm'];
197
198      % Check for VAD test
199      vadTest = 0;
200      if ~isempty(findstr(opt, '-vad'))
201        vadTest = 1;
202        if legacy
203          opt = [opt ' ' outpath vadoutfile];
204        else
205          opt = [opt ' --vad_out_file ' outpath vadoutfile];
206        end
207      end
208
209      if exist([inpath 'vqeFar.pcm'])
210        system(['ln -s -f ' inpath 'vqeFar.pcm ' farFile]);
211      elseif exist([inpath 'apm_far.pcm'])
212        system(['ln -s -f ' inpath 'apm_far.pcm ' farFile]);
213      end
214
215      if exist([inpath 'vqeNear.pcm'])
216        system(['ln -s -f ' inpath 'vqeNear.pcm ' nearFile]);
217      elseif exist([inpath 'apm_near.pcm'])
218        system(['ln -s -f ' inpath 'apm_near.pcm ' nearFile]);
219      end
220
221      if exist([inpath 'vqeEvent.dat'])
222        system(['ln -s -f ' inpath 'vqeEvent.dat ' eventFile]);
223      elseif exist([inpath 'apm_event.dat'])
224        system(['ln -s -f ' inpath 'apm_event.dat ' eventFile]);
225      end
226
227      if exist([inpath 'vqeBuf.dat'])
228        system(['ln -s -f ' inpath 'vqeBuf.dat ' delayFile]);
229      elseif exist([inpath 'apm_delay.dat'])
230        system(['ln -s -f ' inpath 'apm_delay.dat ' delayFile]);
231      end
232
233      if exist([inpath 'vqeSkew.dat'])
234        system(['ln -s -f ' inpath 'vqeSkew.dat ' driftFile]);
235      elseif exist([inpath 'vqeDrift.dat'])
236        system(['ln -s -f ' inpath 'vqeDrift.dat ' driftFile]);
237      elseif exist([inpath 'apm_drift.dat'])
238        system(['ln -s -f ' inpath 'apm_drift.dat ' driftFile]);
239      end
240
241      if simulateMode == false
242        command = [progname ' -o ' outpath outfile ' ' opt];
243      else
244        if legacy
245          inputCmd = [' -in ' nearFile];
246        else
247          inputCmd = [' -i ' nearFile];
248        end
249
250        if exist([farFile])
251          if legacy
252            inputCmd = [' -if ' farFile inputCmd];
253          else
254            inputCmd = [' -ir ' farFile inputCmd];
255          end
256        end
257        command = [progname inputCmd ' -o ' outpath outfile ' ' opt];
258      end
259      % This prevents MATLAB from using its own C libraries.
260      shellcmd = ['bash -c "unset LD_LIBRARY_PATH;'];
261      fprintf([command '\n']);
262      [status, result] = system([shellcmd command '"']);
263      fprintf(result);
264
265      fprintf(['Reference file: ' refpath outfile '\n']);
266
267      if vadTest == 1
268        equal_to_ref = are_files_equal([outpath vadoutfile], ...
269                                       [refpath vadoutfile], ...
270                                       'int8');
271        if ~equal_to_ref
272          nErr = nErr + 1;
273        end
274      end
275
276      [equal_to_ref, diffvector] = are_files_equal([outpath outfile], ...
277                                                   [refpath outfile], ...
278                                                   'int16');
279      if ~equal_to_ref
280        nErr = nErr + 1;
281      end
282
283      if strcmp(task, 'show')
284        % Assume the last init gives the sample rate of interest.
285        str_idx = strfind(result, 'Sample rate:');
286        fs = str2num(result(str_idx(end) + 13:str_idx(end) + 17));
287        fprintf('Using %d Hz\n', fs);
288
289        if exist([farFile])
290          spclab(fs, farFile, nearFile, [refpath outfile], ...
291              [outpath outfile], diffvector);
292          %spclab(fs, diffvector);
293        else
294          spclab(fs, nearFile, [refpath outfile], [outpath outfile], ...
295              diffvector);
296          %spclab(fs, diffvector);
297        end
298      end
299    end
300  end
301else
302
303  for i=3:length(dirs)
304    if dirs(i).isdir
305      [nErr, nCases] = recurseDir([inpath dirs(i).name '/'], outpath, ...
306          refpath,[outfile '_' dirs(i).name], progname, opt, ...
307          simulateMode, nErr, nCases, task, casenumber, legacy);
308    end
309  end
310end
311nErrOut = nErr;
312
313function [are_equal, diffvector] = ...
314    are_files_equal(newfile, reffile, precision, diffvector)
315
316are_equal = false;
317diffvector = 0;
318if ~exist(newfile,'file')
319  warning(['Output file ' newfile ' does not exist']);  
320  return
321end
322
323if ~exist(reffile,'file')
324  warning(['Reference file ' reffile ' does not exist']);  
325  return
326end
327
328fid = fopen(newfile,'rb');
329new = fread(fid,inf,precision);
330fclose(fid);
331
332fid = fopen(reffile,'rb');
333ref = fread(fid,inf,precision);
334fclose(fid);
335
336if length(new) ~= length(ref)
337  warning('Reference is not the same length as output');
338  minlength = min(length(new), length(ref));
339  new = new(1:minlength);
340  ref = ref(1:minlength);
341end
342diffvector = new - ref;
343
344if isequal(new, ref)
345  fprintf([newfile ' is bit-exact to reference\n']);
346  are_equal = true;
347else
348  if isempty(new)
349    warning([newfile ' is empty']);
350    return
351  end
352  snr = snrseg(new,ref,80);
353  fprintf('\n');
354  are_equal = false;
355end
356