audiofuntest: Add --active-mic-channels

CL:425596 supports testing only a subset of mic channels.
For audiofuntest, we also need this feature to ignore invalid channls,
otherwise audiofuntest will wait all invalid channels until timeout,
impacting the performance of audio_loop test.

BUG=b:35941747
TEST=Run audio_loop test

Change-Id: I1b74935adf78929a2545265921dee14b629ac734
Reviewed-on: https://chromium-review.googlesource.com/451237
Commit-Ready: Ting Shen <phoenixshen@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Reviewed-by: Shun-Hsing Ou <shunhsingou@chromium.org>
diff --git a/include/common.h b/include/common.h
index bb490d9..e9175c8 100644
--- a/include/common.h
+++ b/include/common.h
@@ -56,6 +56,7 @@
         verbose(false) {}
 
   std::set<int> active_speaker_channels;
+  std::set<int> active_mic_channels;
   double allowed_delay_sec;
   int fft_size;
   int match_window_size;
diff --git a/include/evaluator.h b/include/evaluator.h
index 5a76e43..b6b5322 100644
--- a/include/evaluator.h
+++ b/include/evaluator.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <set>
 #include <vector>
 
 #include "include/binary_client.h"
@@ -32,6 +33,7 @@
   std::vector<double> filter_;
   int half_window_size_;
   int num_channels_;
+  std::set<int> active_mic_channels_;
   SampleFormat format_;
   int sample_rate_;
   std::vector<double> bin_;
diff --git a/src/audiofuntest.cc b/src/audiofuntest.cc
index 916b6ae..9945618 100644
--- a/src/audiofuntest.cc
+++ b/src/audiofuntest.cc
@@ -17,10 +17,11 @@
 #include "include/tone_generators.h"
 
 constexpr static const char *short_options =
-    "a:d:n:o:w:P:f:R:F:r:t:c:C:T:l:hv";
+    "a:m:d:n:o:w:P:f:R:F:r:t:c:C:T:l:hv";
 
 constexpr static const struct option long_options[] = {
   {"active-speaker-channels", 1, NULL, 'a'},
+  {"active-mic-channels", 1, NULL, 'm'},
   {"allowed-delay", 1, NULL, 'd'},
   {"fft-size", 1, NULL, 'n'},
   {"confidence-threshold", 1, NULL, 'o'},
@@ -68,6 +69,9 @@
       case 'a':
         ParseActiveChannels(optarg, &(config->active_speaker_channels));
         break;
+      case 'm':
+        ParseActiveChannels(optarg, &(config->active_mic_channels));
+        break;
       case 'd':
         config->allowed_delay_sec = atof(optarg);
         break;
@@ -151,6 +155,12 @@
       config->active_speaker_channels.insert(i);
     }
   }
+
+  if (config->active_mic_channels.empty()) {
+    for (int i = 0; i < config->num_mic_channels; ++i) {
+      config->active_mic_channels.insert(i);
+    }
+  }
   return true;
 }
 
@@ -165,6 +175,10 @@
           "\t\tComma-separated list of speaker channels to play on. "
           "(def all channels)\n");
   fprintf(fd,
+          "\t-m, --active-mic-channels:\n"
+          "\t\tComma-separated list of mic channels to test. "
+          "(def all channels)\n");
+  fprintf(fd,
           "\t-d, --allowed-delay:\n"
           "\t\tAllowed latency between player & recorder "
           "(def %.4f).\n", default_config.allowed_delay_sec);
@@ -228,17 +242,24 @@
           "\t-h, --help: Show this page.\n");
 }
 
-void PrintConfig(const AudioFunTestConfig &config, FILE *fd = stdout) {
-  fprintf(fd, "Config values.\n");
-
-  fprintf(fd, "\tSpeaker active channels: ");
+void PrintSet(const std::set<int> &numbers, FILE *fd = stdout) {
   bool first = true;
-  for (auto it : config.active_speaker_channels) {
+  for (auto it : numbers) {
     if (!first)
       fprintf(fd, ", ");
     fprintf(fd, "%d", it);
     first = false;
   }
+}
+
+void PrintConfig(const AudioFunTestConfig &config, FILE *fd = stdout) {
+  fprintf(fd, "Config values.\n");
+
+  fprintf(fd, "\tSpeaker active channels: ");
+  PrintSet(config.active_speaker_channels, fd);
+  fprintf(fd, "\n");
+  fprintf(fd, "\tMic active channels: ");
+  PrintSet(config.active_mic_channels, fd);
   fprintf(fd, "\n");
   fprintf(fd, "\tAllowed delay: %.4f(s)\n", config.allowed_delay_sec);
   fprintf(fd, "\tFFT size: %d\n", config.fft_size);
@@ -315,7 +336,7 @@
     generatorPlayer.Stop();
 
     printf("carrier = %d\n", bin);
-    for (int c = 0; c < config.num_mic_channels; ++c) {
+    for (auto c : config.active_mic_channels) {
       const char *res = single_round_pass[c] ? "O" : "X";
       printf("%s: channel = %d, success = %d, fail = %d, rate = %.4f\n",
              res, c, passes[c], round - passes[c], 100.0 * passes[c] / round);
diff --git a/src/evaluator.cc b/src/evaluator.cc
index 1f9beba..6c424b6 100644
--- a/src/evaluator.cc
+++ b/src/evaluator.cc
@@ -82,6 +82,7 @@
     : filter_(config.match_window_size),
       half_window_size_(config.match_window_size / 2),
       num_channels_(config.num_mic_channels),
+      active_mic_channels_(config.active_mic_channels),
       format_(config.sample_format),
       sample_rate_(config.sample_rate),
       bin_(config.match_window_size),
@@ -129,7 +130,7 @@
     std::vector<double> complex_data(num_frames * 2);
 
     // Evaluates all channels.
-    for (int channel = 0; channel < num_channels_; ++channel) {
+    for (int channel: active_mic_channels_) {
       if (accum_confidence[channel] >= confidence_threshold_)
         continue;
       ToComplex(data[channel], &complex_data);