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