The test program modules/audio_processing/test/audioproc_float.cc defined the flag 'agc_compression_gain' and had checks if the parameter was valid (audioproc_float). The flag was also copied to webrtc::test::SimulationSettings of audio_processing_simulator.h. The setting was however never applied to APM. This change applies the setting on the GainControl submodule in the same way as the agc_target_level is applied. This is needed for e.g. testing the AGC fixed digital limiter with the same configuration as it is (currently) used with in AudioMixerImpl. Also added new flag '-experimental_agc'. This flag allows disabling the experimental AGC, which is how the AGC is used in AudioMixerImpl. ExperimentalAgc is enabled by default, exactly as it was prior to this change. The change has been tested locally by listening tests and diff comparisons. BUG=None NOTRY=True # win_dbg bot not cooperating Review-Url: https://codereview.webrtc.org/2684983004 Cr-Commit-Position: refs/heads/master@{#16603}
468 lines
20 KiB
C++
468 lines
20 KiB
C++
/*
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <memory>
|
|
|
|
#include <string.h>
|
|
|
|
#include "gflags/gflags.h"
|
|
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
|
#include "webrtc/modules/audio_processing/test/aec_dump_based_simulator.h"
|
|
#include "webrtc/modules/audio_processing/test/audio_processing_simulator.h"
|
|
#include "webrtc/modules/audio_processing/test/wav_based_simulator.h"
|
|
|
|
namespace webrtc {
|
|
namespace test {
|
|
namespace {
|
|
|
|
const int kParameterNotSpecifiedValue = -10000;
|
|
|
|
const char kUsageDescription[] =
|
|
"Usage: audioproc_f [options] -i <input.wav>\n"
|
|
" or\n"
|
|
" audioproc_f [options] -dump_input <aec_dump>\n"
|
|
"\n\n"
|
|
"Command-line tool to simulate a call using the audio "
|
|
"processing module, either based on wav files or "
|
|
"protobuf debug dump recordings.";
|
|
|
|
DEFINE_string(dump_input, "", "Aec dump input filename");
|
|
DEFINE_string(dump_output, "", "Aec dump output filename");
|
|
DEFINE_string(i, "", "Forward stream input wav filename");
|
|
DEFINE_string(o, "", "Forward stream output wav filename");
|
|
DEFINE_string(ri, "", "Reverse stream input wav filename");
|
|
DEFINE_string(ro, "", "Reverse stream output wav filename");
|
|
DEFINE_string(artificial_nearend, "", "Artificial nearend wav filename");
|
|
DEFINE_int32(output_num_channels,
|
|
kParameterNotSpecifiedValue,
|
|
"Number of forward stream output channels");
|
|
DEFINE_int32(reverse_output_num_channels,
|
|
kParameterNotSpecifiedValue,
|
|
"Number of Reverse stream output channels");
|
|
DEFINE_int32(output_sample_rate_hz,
|
|
kParameterNotSpecifiedValue,
|
|
"Forward stream output sample rate in Hz");
|
|
DEFINE_int32(reverse_output_sample_rate_hz,
|
|
kParameterNotSpecifiedValue,
|
|
"Reverse stream output sample rate in Hz");
|
|
DEFINE_string(mic_positions,
|
|
"",
|
|
"Space delimited cartesian coordinates of microphones in "
|
|
"meters. The coordinates of each point are contiguous. For a "
|
|
"two element array: \"x1 y1 z1 x2 y2 z2\"");
|
|
DEFINE_int32(target_angle_degrees,
|
|
90,
|
|
"The azimuth of the target in degrees (0-359). Only applies to "
|
|
"beamforming.");
|
|
DEFINE_bool(fixed_interface,
|
|
false,
|
|
"Use the fixed interface when operating on wav files");
|
|
DEFINE_int32(aec,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the echo canceller");
|
|
DEFINE_int32(aecm,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the mobile echo controller");
|
|
DEFINE_int32(ed,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate (0) the residual echo detector");
|
|
DEFINE_string(ed_graph, "", "Output filename for graph of echo likelihood");
|
|
DEFINE_int32(agc,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the AGC");
|
|
DEFINE_int32(hpf,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the high-pass filter");
|
|
DEFINE_int32(ns,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the noise suppressor");
|
|
DEFINE_int32(ts,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the transient suppressor");
|
|
DEFINE_int32(bf,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the beamformer");
|
|
DEFINE_int32(ie,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the intelligibility enhancer");
|
|
DEFINE_int32(vad,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the voice activity detector");
|
|
DEFINE_int32(le,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the level estimator");
|
|
DEFINE_bool(all_default,
|
|
false,
|
|
"Activate all of the default components (will be overridden by any "
|
|
"other settings)");
|
|
DEFINE_int32(aec_suppression_level,
|
|
kParameterNotSpecifiedValue,
|
|
"Set the aec suppression level (0-2)");
|
|
DEFINE_int32(delay_agnostic,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the AEC delay agnostic mode");
|
|
DEFINE_int32(extended_filter,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the AEC extended filter mode");
|
|
DEFINE_int32(drift_compensation,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the drift compensation");
|
|
DEFINE_int32(aec3,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the experimental AEC mode AEC3");
|
|
DEFINE_int32(lc,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the level control");
|
|
DEFINE_int32(experimental_agc,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the experimental AGC");
|
|
DEFINE_int32(
|
|
refined_adaptive_filter,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the refined adaptive filter functionality");
|
|
DEFINE_int32(aecm_routing_mode,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the AECM routing mode (0-4)");
|
|
DEFINE_int32(aecm_comfort_noise,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the AECM comfort noise");
|
|
DEFINE_int32(agc_mode,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the AGC mode (0-2)");
|
|
DEFINE_int32(agc_target_level,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the AGC target level (0-31)");
|
|
DEFINE_int32(agc_limiter,
|
|
kParameterNotSpecifiedValue,
|
|
"Activate (1) or deactivate(0) the level estimator");
|
|
DEFINE_int32(agc_compression_gain,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the AGC compression gain (0-90)");
|
|
DEFINE_int32(vad_likelihood,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the VAD likelihood (0-3)");
|
|
DEFINE_int32(ns_level,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the NS level (0-3)");
|
|
DEFINE_int32(stream_delay,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the stream delay in ms to use");
|
|
DEFINE_int32(stream_drift_samples,
|
|
kParameterNotSpecifiedValue,
|
|
"Specify the number of stream drift samples to use");
|
|
DEFINE_bool(performance_report, false, "Report the APM performance ");
|
|
DEFINE_bool(verbose, false, "Produce verbose output");
|
|
DEFINE_bool(bitexactness_report,
|
|
false,
|
|
"Report bitexactness for aec dump result reproduction");
|
|
DEFINE_bool(discard_settings_in_aecdump,
|
|
false,
|
|
"Discard any config settings specified in the aec dump");
|
|
DEFINE_bool(store_intermediate_output,
|
|
false,
|
|
"Creates new output files after each init");
|
|
DEFINE_string(custom_call_order_file, "", "Custom process API call order file");
|
|
|
|
void SetSettingIfSpecified(const std::string value,
|
|
rtc::Optional<std::string>* parameter) {
|
|
if (value.compare("") != 0) {
|
|
*parameter = rtc::Optional<std::string>(value);
|
|
}
|
|
}
|
|
|
|
void SetSettingIfSpecified(int value, rtc::Optional<int>* parameter) {
|
|
if (value != kParameterNotSpecifiedValue) {
|
|
*parameter = rtc::Optional<int>(value);
|
|
}
|
|
}
|
|
|
|
void SetSettingIfFlagSet(int32_t flag, rtc::Optional<bool>* parameter) {
|
|
if (flag == 0) {
|
|
*parameter = rtc::Optional<bool>(false);
|
|
} else if (flag == 1) {
|
|
*parameter = rtc::Optional<bool>(true);
|
|
}
|
|
}
|
|
|
|
SimulationSettings CreateSettings() {
|
|
SimulationSettings settings;
|
|
if (FLAGS_all_default) {
|
|
settings.use_le = rtc::Optional<bool>(true);
|
|
settings.use_vad = rtc::Optional<bool>(true);
|
|
settings.use_ie = rtc::Optional<bool>(false);
|
|
settings.use_bf = rtc::Optional<bool>(false);
|
|
settings.use_ts = rtc::Optional<bool>(true);
|
|
settings.use_ns = rtc::Optional<bool>(true);
|
|
settings.use_hpf = rtc::Optional<bool>(true);
|
|
settings.use_agc = rtc::Optional<bool>(true);
|
|
settings.use_aec = rtc::Optional<bool>(true);
|
|
settings.use_aecm = rtc::Optional<bool>(false);
|
|
settings.use_ed = rtc::Optional<bool>(false);
|
|
}
|
|
SetSettingIfSpecified(FLAGS_dump_input, &settings.aec_dump_input_filename);
|
|
SetSettingIfSpecified(FLAGS_dump_output, &settings.aec_dump_output_filename);
|
|
SetSettingIfSpecified(FLAGS_i, &settings.input_filename);
|
|
SetSettingIfSpecified(FLAGS_o, &settings.output_filename);
|
|
SetSettingIfSpecified(FLAGS_ri, &settings.reverse_input_filename);
|
|
SetSettingIfSpecified(FLAGS_ro, &settings.reverse_output_filename);
|
|
SetSettingIfSpecified(FLAGS_artificial_nearend,
|
|
&settings.artificial_nearend_filename);
|
|
SetSettingIfSpecified(FLAGS_output_num_channels,
|
|
&settings.output_num_channels);
|
|
SetSettingIfSpecified(FLAGS_reverse_output_num_channels,
|
|
&settings.reverse_output_num_channels);
|
|
SetSettingIfSpecified(FLAGS_output_sample_rate_hz,
|
|
&settings.output_sample_rate_hz);
|
|
SetSettingIfSpecified(FLAGS_reverse_output_sample_rate_hz,
|
|
&settings.reverse_output_sample_rate_hz);
|
|
SetSettingIfSpecified(FLAGS_mic_positions, &settings.microphone_positions);
|
|
settings.target_angle_degrees = FLAGS_target_angle_degrees;
|
|
SetSettingIfFlagSet(FLAGS_aec, &settings.use_aec);
|
|
SetSettingIfFlagSet(FLAGS_aecm, &settings.use_aecm);
|
|
SetSettingIfFlagSet(FLAGS_ed, &settings.use_ed);
|
|
SetSettingIfSpecified(FLAGS_ed_graph, &settings.ed_graph_output_filename);
|
|
SetSettingIfFlagSet(FLAGS_agc, &settings.use_agc);
|
|
SetSettingIfFlagSet(FLAGS_hpf, &settings.use_hpf);
|
|
SetSettingIfFlagSet(FLAGS_ns, &settings.use_ns);
|
|
SetSettingIfFlagSet(FLAGS_ts, &settings.use_ts);
|
|
SetSettingIfFlagSet(FLAGS_bf, &settings.use_bf);
|
|
SetSettingIfFlagSet(FLAGS_ie, &settings.use_ie);
|
|
SetSettingIfFlagSet(FLAGS_vad, &settings.use_vad);
|
|
SetSettingIfFlagSet(FLAGS_le, &settings.use_le);
|
|
SetSettingIfSpecified(FLAGS_aec_suppression_level,
|
|
&settings.aec_suppression_level);
|
|
SetSettingIfFlagSet(FLAGS_delay_agnostic, &settings.use_delay_agnostic);
|
|
SetSettingIfFlagSet(FLAGS_extended_filter, &settings.use_extended_filter);
|
|
SetSettingIfFlagSet(FLAGS_drift_compensation,
|
|
&settings.use_drift_compensation);
|
|
SetSettingIfFlagSet(FLAGS_refined_adaptive_filter,
|
|
&settings.use_refined_adaptive_filter);
|
|
|
|
SetSettingIfFlagSet(FLAGS_aec3, &settings.use_aec3);
|
|
SetSettingIfFlagSet(FLAGS_lc, &settings.use_lc);
|
|
SetSettingIfFlagSet(FLAGS_experimental_agc, &settings.use_experimental_agc);
|
|
SetSettingIfSpecified(FLAGS_aecm_routing_mode, &settings.aecm_routing_mode);
|
|
SetSettingIfFlagSet(FLAGS_aecm_comfort_noise,
|
|
&settings.use_aecm_comfort_noise);
|
|
SetSettingIfSpecified(FLAGS_agc_mode, &settings.agc_mode);
|
|
SetSettingIfSpecified(FLAGS_agc_target_level, &settings.agc_target_level);
|
|
SetSettingIfFlagSet(FLAGS_agc_limiter, &settings.use_agc_limiter);
|
|
SetSettingIfSpecified(FLAGS_agc_compression_gain,
|
|
&settings.agc_compression_gain);
|
|
SetSettingIfSpecified(FLAGS_vad_likelihood, &settings.vad_likelihood);
|
|
SetSettingIfSpecified(FLAGS_ns_level, &settings.ns_level);
|
|
SetSettingIfSpecified(FLAGS_stream_delay, &settings.stream_delay);
|
|
SetSettingIfSpecified(FLAGS_stream_drift_samples,
|
|
&settings.stream_drift_samples);
|
|
SetSettingIfSpecified(FLAGS_custom_call_order_file,
|
|
&settings.custom_call_order_filename);
|
|
settings.report_performance = FLAGS_performance_report;
|
|
settings.use_verbose_logging = FLAGS_verbose;
|
|
settings.report_bitexactness = FLAGS_bitexactness_report;
|
|
settings.discard_all_settings_in_aecdump = FLAGS_discard_settings_in_aecdump;
|
|
settings.fixed_interface = FLAGS_fixed_interface;
|
|
settings.store_intermediate_output = FLAGS_store_intermediate_output;
|
|
|
|
return settings;
|
|
}
|
|
|
|
void ReportConditionalErrorAndExit(bool condition, std::string message) {
|
|
if (condition) {
|
|
std::cerr << message << std::endl;
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void PerformBasicParameterSanityChecks(const SimulationSettings& settings) {
|
|
if (settings.input_filename || settings.reverse_input_filename) {
|
|
ReportConditionalErrorAndExit(!!settings.aec_dump_input_filename,
|
|
"Error: The aec dump cannot be specified "
|
|
"together with input wav files!\n");
|
|
|
|
ReportConditionalErrorAndExit(!!settings.artificial_nearend_filename,
|
|
"Error: The artificial nearend cannot be "
|
|
"specified together with input wav files!\n");
|
|
|
|
ReportConditionalErrorAndExit(!settings.input_filename,
|
|
"Error: When operating at wav files, the "
|
|
"input wav filename must be "
|
|
"specified!\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.reverse_output_filename && !settings.reverse_input_filename,
|
|
"Error: When operating at wav files, the reverse input wav filename "
|
|
"must be specified if the reverse output wav filename is specified!\n");
|
|
} else {
|
|
ReportConditionalErrorAndExit(!settings.aec_dump_input_filename,
|
|
"Error: Either the aec dump or the wav "
|
|
"input files must be specified!\n");
|
|
}
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.use_aec && *settings.use_aec && settings.use_aecm &&
|
|
*settings.use_aecm,
|
|
"Error: The AEC and the AECM cannot be activated at the same time!\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.output_sample_rate_hz && *settings.output_sample_rate_hz <= 0,
|
|
"Error: --output_sample_rate_hz must be positive!\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.reverse_output_sample_rate_hz &&
|
|
settings.output_sample_rate_hz &&
|
|
*settings.output_sample_rate_hz <= 0,
|
|
"Error: --reverse_output_sample_rate_hz must be positive!\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.output_num_channels && *settings.output_num_channels <= 0,
|
|
"Error: --output_num_channels must be positive!\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.reverse_output_num_channels &&
|
|
*settings.reverse_output_num_channels <= 0,
|
|
"Error: --reverse_output_num_channels must be positive!\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.use_bf && *settings.use_bf && !settings.microphone_positions,
|
|
"Error: --mic_positions must be specified when the beamformer is "
|
|
"activated.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.target_angle_degrees < 0 || settings.target_angle_degrees > 359,
|
|
"Error: -target_angle_degrees must be specified between 0 and 359.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.aec_suppression_level &&
|
|
((*settings.aec_suppression_level) < 0 ||
|
|
(*settings.aec_suppression_level) > 2),
|
|
"Error: --aec_suppression_level must be specified between 0 and 2.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.aecm_routing_mode && ((*settings.aecm_routing_mode) < 0 ||
|
|
(*settings.aecm_routing_mode) > 4),
|
|
"Error: --aecm_routing_mode must be specified between 0 and 4.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.agc_target_level && ((*settings.agc_target_level) < 0 ||
|
|
(*settings.agc_target_level) > 31),
|
|
"Error: --agc_target_level must be specified between 0 and 31.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.agc_compression_gain && ((*settings.agc_compression_gain) < 0 ||
|
|
(*settings.agc_compression_gain) > 90),
|
|
"Error: --agc_compression_gain must be specified between 0 and 90.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.vad_likelihood &&
|
|
((*settings.vad_likelihood) < 0 || (*settings.vad_likelihood) > 3),
|
|
"Error: --vad_likelihood must be specified between 0 and 3.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.ns_level &&
|
|
((*settings.ns_level) < 0 || (*settings.ns_level) > 3),
|
|
"Error: --ns_level must be specified between 0 and 3.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.report_bitexactness && !settings.aec_dump_input_filename,
|
|
"Error: --bitexactness_report can only be used when operating on an "
|
|
"aecdump\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.custom_call_order_filename && settings.aec_dump_input_filename,
|
|
"Error: --custom_call_order_file cannot be used when operating on an "
|
|
"aecdump\n");
|
|
|
|
auto valid_wav_name = [](const std::string& wav_file_name) {
|
|
if (wav_file_name.size() < 5) {
|
|
return false;
|
|
}
|
|
if ((wav_file_name.compare(wav_file_name.size() - 4, 4, ".wav") == 0) ||
|
|
(wav_file_name.compare(wav_file_name.size() - 4, 4, ".WAV") == 0)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.input_filename && (!valid_wav_name(*settings.input_filename)),
|
|
"Error: --i must be a valid .wav file name.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.output_filename && (!valid_wav_name(*settings.output_filename)),
|
|
"Error: --o must be a valid .wav file name.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.reverse_input_filename &&
|
|
(!valid_wav_name(*settings.reverse_input_filename)),
|
|
"Error: --ri must be a valid .wav file name.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.reverse_output_filename &&
|
|
(!valid_wav_name(*settings.reverse_output_filename)),
|
|
"Error: --ro must be a valid .wav file name.\n");
|
|
|
|
ReportConditionalErrorAndExit(
|
|
settings.artificial_nearend_filename &&
|
|
!valid_wav_name(*settings.artificial_nearend_filename),
|
|
"Error: --artifical_nearend must be a valid .wav file name.\n");
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char* argv[]) {
|
|
google::SetUsageMessage(kUsageDescription);
|
|
google::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
SimulationSettings settings = CreateSettings();
|
|
PerformBasicParameterSanityChecks(settings);
|
|
std::unique_ptr<AudioProcessingSimulator> processor;
|
|
|
|
if (settings.aec_dump_input_filename) {
|
|
processor.reset(new AecDumpBasedSimulator(settings));
|
|
} else {
|
|
processor.reset(new WavBasedSimulator(settings));
|
|
}
|
|
|
|
processor->Process();
|
|
|
|
if (settings.report_performance) {
|
|
const auto& proc_time = processor->proc_time();
|
|
int64_t exec_time_us = proc_time.sum / rtc::kNumNanosecsPerMicrosec;
|
|
std::cout << std::endl
|
|
<< "Execution time: " << exec_time_us * 1e-6 << " s, File time: "
|
|
<< processor->get_num_process_stream_calls() * 1.f /
|
|
AudioProcessingSimulator::kChunksPerSecond
|
|
<< std::endl
|
|
<< "Time per fwd stream chunk (mean, max, min): " << std::endl
|
|
<< exec_time_us * 1.f / processor->get_num_process_stream_calls()
|
|
<< " us, " << 1.f * proc_time.max / rtc::kNumNanosecsPerMicrosec
|
|
<< " us, " << 1.f * proc_time.min / rtc::kNumNanosecsPerMicrosec
|
|
<< " us" << std::endl;
|
|
}
|
|
|
|
if (settings.report_bitexactness && settings.aec_dump_input_filename) {
|
|
if (processor->OutputWasBitexact()) {
|
|
std::cout << "The processing was bitexact.";
|
|
} else {
|
|
std::cout << "The processing was not bitexact.";
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace webrtc
|
|
|
|
int main(int argc, char* argv[]) {
|
|
return webrtc::test::main(argc, argv);
|
|
}
|