blob: 4057d7553d8734353e77911711fbcb955e8a19a1 [file] [log] [blame]
Amy Lin8c768a72016-08-01 15:44:16 +08001// Copyright 2016 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <stdlib.h>
6
7#include <iostream>
8
9#include "include/connector.h"
10#include "include/evaluator.h"
11#include "include/param_config.h"
12#include "include/frame_generator.h"
13
14using autotest_client::audio::Connector;
15using autotest_client::audio::Evaluator;
16using autotest_client::audio::FrameGenerator;
17using autotest_client::audio::ParamConfig;
18using autotest_client::audio::PlayClient;
19using autotest_client::audio::RecordClient;
20
21// Randomly picks an integer from the given range [min, max],
22// including both end points.
23inline int RandomPick(int min, int max) {
24 if (min > max) {
25 std::cerr << "Range error: min > max" << std::endl;
26 assert(false);
27 }
28
29 static unsigned int seed = time(NULL) + getpid();
30 return (rand_r(&seed) % (max - min + 1)) + min;
31}
32
33// Controls the main process of audiofuntest.
34void ControlLoop(const ParamConfig &config,
35 Evaluator *evaluator,
36 RecordClient *recorder,
37 FrameGenerator *generator,
38 const int min_frequency = 4000,
39 const int max_frequency = 10000) {
40 const double frequency_resolution =
41 static_cast<double>(config.sample_rate) / config.fft_size;
42 const int min_bin = min_frequency / frequency_resolution;
43 const int max_bin = max_frequency / frequency_resolution;
44
45 vector<int> passes(config.num_mic_channels);
46 vector<bool> single_round_pass(config.num_mic_channels);
47
48 for (int round = 1; round <= config.test_rounds; ++round) {
49 std::fill(single_round_pass.begin(), single_round_pass.end(), false);
50 int bin = RandomPick(min_bin, max_bin);
51 double frequency = bin * frequency_resolution;
52
53 // Sets the frequency to be generated.
54 generator->SetFrequency(frequency);
55
Earl Ou733306b2016-11-14 14:26:04 +080056 evaluator->Evaluate(recorder, bin, &single_round_pass);
Amy Lin8c768a72016-08-01 15:44:16 +080057 for (int chn = 0; chn < config.num_mic_channels; ++chn) {
58 if (single_round_pass[chn]) {
59 ++passes[chn];
60 }
61 }
62 generator->SetStopPlayTone();
63
Earl Ou733306b2016-11-14 14:26:04 +080064 std::cout << "carrier = " << bin << endl;
Amy Lin8c768a72016-08-01 15:44:16 +080065 for (auto c : config.active_mic_channels) {
Earl Ou733306b2016-11-14 14:26:04 +080066 const char *res = single_round_pass[c] ? "O" : "X";
Amy Lin8c768a72016-08-01 15:44:16 +080067 std::cout << (res)
Earl Ou733306b2016-11-14 14:26:04 +080068 << ": channel = " << c
Amy Lin8c768a72016-08-01 15:44:16 +080069 << ", success = " << passes[c]
70 << ", fail = " << round - passes[c]
71 << std::setprecision(4)
72 << ", rate = "
Earl Ou733306b2016-11-14 14:26:04 +080073 << 100.0 * passes[c] / round << endl;
Amy Lin8c768a72016-08-01 15:44:16 +080074 }
Amy Lin8c768a72016-08-01 15:44:16 +080075 }
76}
77
78int main(int argc, char *argv[]) {
79 // Parses configuration.
80 ParamConfig config;
81 if (!config.ParseOptions(argc, argv)) {
82 config.PrintUsage(&std::cout, argv[0]);
83 return 0;
84 }
85 config.Print(&std::cout);
86
87 // Main role initialization.
88 FrameGenerator generator(config);
89
90 PlayClient player(config);
91 player.InitProcess(config.is_logging);
92
93 RecordClient recorder(config);
94 recorder.InitProcess(config.is_logging);
95
96 Evaluator evaluator(config);
97
98 generator.PlayTo(&player);
99
100 // Starts evaluation.
101 ControlLoop(config, &evaluator, &recorder, &generator);
102
103 // Terminates and cleans up.
104 recorder.Terminate();
105
106 // Stops generator before player to
107 // avoid sending tones to closed pipe.
108 generator.Stop();
109 player.Terminate();
110
111 return 0;
112}