1b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org/* 2b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * 4b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * Use of this source code is governed by a BSD-style license 5b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * that can be found in the LICENSE file in the root of the source 6b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * tree. An additional intellectual property rights grant can be found 7b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * in the file PATENTS. All contributing project authors may 8b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org */ 10b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 116568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org#include <math.h> 12b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org#include <stdio.h> 1383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin#include "webrtc/base/checks.h" 149c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h" 1583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin#include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" 1683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin#include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h" 1783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin#include "webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h" 1883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin#include "webrtc/test/testsupport/fileutils.h" 1983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 2083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinusing std::string; 21b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 22b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgnamespace webrtc { 23b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgnamespace test { 24b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 25b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgconst uint8_t kPayloadType = 95; 26b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgconst int kOutputSizeMs = 10; 276568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgconst int kInitSeed = 0x12345678; 286568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgconst int kPacketLossTimeUnitMs = 10; 296568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 3083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin// Common validator for file names. 3183b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic bool ValidateFilename(const string& value, bool write) { 3283b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin FILE* fid = write ? fopen(value.c_str(), "wb") : fopen(value.c_str(), "rb"); 3383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin if (fid == nullptr) 3483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return false; 3583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin fclose(fid); 3683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return true; 3783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin} 3883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 3983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin// Define switch for input file name. 4083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic bool ValidateInFilename(const char* flagname, const string& value) { 4183b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin if (!ValidateFilename(value, false)) { 4283b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin printf("Invalid input filename."); 4383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return false; 4483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin } 4583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return true; 4683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin} 4783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 4883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik LundinDEFINE_string( 4983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin in_filename, 5083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin ResourcePath("audio_coding/speech_mono_16kHz", "pcm"), 51f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li "Filename for input audio (specify sample rate with --input_sample_rate ," 52f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li "and channels with --channels)."); 5383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 5483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic const bool in_filename_dummy = 5583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename); 5683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 5783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin// Define switch for sample rate. 5883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic bool ValidateSampleRate(const char* flagname, int32_t value) { 5983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin if (value == 8000 || value == 16000 || value == 32000 || value == 48000) 6083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return true; 6183b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin printf("Invalid sample rate should be 8000, 16000, 32000 or 48000 Hz."); 6283b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return false; 6383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin} 6483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 6583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik LundinDEFINE_int32(input_sample_rate, 16000, "Sample rate of input file in Hz."); 6683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 6783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic const bool sample_rate_dummy = 6883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin RegisterFlagValidator(&FLAGS_input_sample_rate, &ValidateSampleRate); 6983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 70f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li// Define switch for channels. 71f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Listatic bool ValidateChannels(const char* flagname, int32_t value) { 72f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li if (value == 1) 73f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li return true; 74f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li printf("Invalid number of channels, current support only 1."); 75f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li return false; 76f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li} 77f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li 78f761d10393ae47283c6170387fcb8cce4aadbd59Minyue LiDEFINE_int32(channels, 1, "Number of channels in input audio."); 79f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li 80f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Listatic const bool channels_dummy = 81f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li RegisterFlagValidator(&FLAGS_channels, &ValidateChannels); 82f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li 8383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin// Define switch for output file name. 8483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic bool ValidateOutFilename(const char* flagname, const string& value) { 8583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin if (!ValidateFilename(value, true)) { 8683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin printf("Invalid output filename."); 8783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return false; 8883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin } 8983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin return true; 9083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin} 9183b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 9283b5c053b9687813c5fc9c08b3beee4d464f7950Henrik LundinDEFINE_string(out_filename, 9383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin OutputPath() + "neteq_quality_test_out.pcm", 9483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin "Name of output audio file."); 9583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 9683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundinstatic const bool out_filename_dummy = 9783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin RegisterFlagValidator(&FLAGS_out_filename, &ValidateOutFilename); 9883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 996568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// Define switch for packet loss rate. 1006568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic bool ValidatePacketLossRate(const char* /* flag_name */, int32_t value) { 1016568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (value >= 0 && value <= 100) 1026568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return true; 1036568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org printf("Invalid packet loss percentile, should be between 0 and 100."); 1046568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return false; 1056568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 1066568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 107e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin// Define switch for runtime. 108e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundinstatic bool ValidateRuntime(const char* flagname, int32_t value) { 109e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin if (value > 0) 110e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin return true; 111e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin printf("Invalid runtime, should be greater than 0."); 112e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin return false; 113e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin} 114e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin 115e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik LundinDEFINE_int32(runtime_ms, 10000, "Simulated runtime (milliseconds)."); 116e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin 117e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundinstatic const bool runtime_dummy = 118e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin RegisterFlagValidator(&FLAGS_runtime_ms, &ValidateRuntime); 119e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin 1206568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgDEFINE_int32(packet_loss_rate, 10, "Percentile of packet loss."); 1216568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1226568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic const bool packet_loss_rate_dummy = 1236568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org RegisterFlagValidator(&FLAGS_packet_loss_rate, &ValidatePacketLossRate); 1246568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1256568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// Define switch for random loss mode. 1266568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic bool ValidateRandomLossMode(const char* /* flag_name */, int32_t value) { 1276568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (value >= 0 && value <= 2) 1286568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return true; 1296568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org printf("Invalid random packet loss mode, should be between 0 and 2."); 1306568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return false; 1316568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 1326568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1336568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgDEFINE_int32(random_loss_mode, 1, 1346568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org "Random loss mode: 0--no loss, 1--uniform loss, 2--Gilbert Elliot loss."); 1356568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic const bool random_loss_mode_dummy = 1366568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org RegisterFlagValidator(&FLAGS_random_loss_mode, &ValidateRandomLossMode); 1376568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1386568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// Define switch for burst length. 1396568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic bool ValidateBurstLength(const char* /* flag_name */, int32_t value) { 1406568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (value >= kPacketLossTimeUnitMs) 1416568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return true; 1426568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org printf("Invalid burst length, should be greater than %d ms.", 1436568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org kPacketLossTimeUnitMs); 1446568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return false; 1456568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 1466568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1476568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgDEFINE_int32(burst_length, 30, 1486568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org "Burst length in milliseconds, only valid for Gilbert Elliot loss."); 1496568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1506568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic const bool burst_length_dummy = 1516568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org RegisterFlagValidator(&FLAGS_burst_length, &ValidateBurstLength); 1526568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1536568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// Define switch for drift factor. 1546568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic bool ValidateDriftFactor(const char* /* flag_name */, double value) { 1556568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (value > -0.1) 1566568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return true; 1576568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org printf("Invalid drift factor, should be greater than -0.1."); 1586568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return false; 1596568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 1606568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1616568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgDEFINE_double(drift_factor, 0.0, "Time drift factor."); 1626568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1636568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic const bool drift_factor_dummy = 1646568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org RegisterFlagValidator(&FLAGS_drift_factor, &ValidateDriftFactor); 1656568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1666568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// ProbTrans00Solver() is to calculate the transition probability from no-loss 1676568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// state to itself in a modified Gilbert Elliot packet loss model. The result is 1686568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// to achieve the target packet loss rate |loss_rate|, when a packet is not 1696568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// lost only if all |units| drawings within the duration of the packet result in 1706568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// no-loss. 1716568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgstatic double ProbTrans00Solver(int units, double loss_rate, 1726568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double prob_trans_10) { 1736568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (units == 1) 1746568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return prob_trans_10 / (1.0f - loss_rate) - prob_trans_10; 1756568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// 0 == prob_trans_00 ^ (units - 1) + (1 - loss_rate) / prob_trans_10 * 1766568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// prob_trans_00 - (1 - loss_rate) * (1 + 1 / prob_trans_10). 1776568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// There is a unique solution between 0.0 and 1.0, due to the monotonicity and 1786568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// an opposite sign at 0.0 and 1.0. 1796568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// For simplicity, we reformulate the equation as 1806568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// f(x) = x ^ (units - 1) + a x + b. 1816568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// Its derivative is 1826568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// f'(x) = (units - 1) x ^ (units - 2) + a. 1836568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// The derivative is strictly greater than 0 when x is between 0 and 1. 1846568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// We use Newton's method to solve the equation, iteration is 1856568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org// x(k+1) = x(k) - f(x) / f'(x); 1866568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org const double kPrecision = 0.001f; 1876568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org const int kIterations = 100; 1886568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org const double a = (1.0f - loss_rate) / prob_trans_10; 1896568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org const double b = (loss_rate - 1.0f) * (1.0f + 1.0f / prob_trans_10); 1906568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double x = 0.0f; // Starting point; 1916568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double f = b; 1926568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double f_p; 1936568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org int iter = 0; 1946568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org while ((f >= kPrecision || f <= -kPrecision) && iter < kIterations) { 1956568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org f_p = (units - 1.0f) * pow(x, units - 2) + a; 1966568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org x -= f / f_p; 1976568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (x > 1.0f) { 1986568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org x = 1.0f; 1996568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } else if (x < 0.0f) { 2006568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org x = 0.0f; 2016568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 2026568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org f = pow(x, units - 1) + a * x + b; 2036568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org iter ++; 2046568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 2056568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return x; 2066568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 207b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 208b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgNetEqQualityTest::NetEqQualityTest(int block_duration_ms, 209b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org int in_sampling_khz, 210b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org int out_sampling_khz, 211ee1879ca40ffe4af9bb9613e03eacc5c2c4881fckwiberg NetEqDecoder decoder_type) 212f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li : decoder_type_(decoder_type), 2136955870806624479723addfae6dcf5d13968796cPeter Kasting channels_(static_cast<size_t>(FLAGS_channels)), 214f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li decoded_time_ms_(0), 215b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org decodable_time_ms_(0), 2166568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org drift_factor_(FLAGS_drift_factor), 2176568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org packet_loss_rate_(FLAGS_packet_loss_rate), 218b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org block_duration_ms_(block_duration_ms), 219b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org in_sampling_khz_(in_sampling_khz), 220b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org out_sampling_khz_(out_sampling_khz), 221dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting in_size_samples_( 222dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting static_cast<size_t>(in_sampling_khz_ * block_duration_ms_)), 223dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting out_size_samples_(static_cast<size_t>(out_sampling_khz_ * kOutputSizeMs)), 224b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org payload_size_bytes_(0), 225b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org max_payload_bytes_(0), 22683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin in_file_(new ResampleInputAudioFile(FLAGS_in_filename, 22783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin FLAGS_input_sample_rate, 22883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin in_sampling_khz * 1000)), 22983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin rtp_generator_( 23083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin new RtpGenerator(in_sampling_khz_, 0, 0, decodable_time_ms_)), 2316568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org total_payload_size_bytes_(0) { 23283b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin const std::string out_filename = FLAGS_out_filename; 23383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin const std::string log_filename = out_filename + ".log"; 234f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li log_file_.open(log_filename.c_str(), std::ofstream::out); 23591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_CHECK(log_file_.is_open()); 23683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 23783b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin if (out_filename.size() >= 4 && 23883b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin out_filename.substr(out_filename.size() - 4) == ".wav") { 23983b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin // Open a wav file. 24083b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin output_.reset( 24183b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin new webrtc::test::OutputWavFile(out_filename, 1000 * out_sampling_khz)); 24283b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin } else { 24383b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin // Open a pcm file. 24483b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin output_.reset(new webrtc::test::OutputAudioFile(out_filename)); 24583b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin } 24683b5c053b9687813c5fc9c08b3beee4d464f7950Henrik Lundin 24735ead381f8dff68ba2f6b7ff163ede6cf4bccc24henrik.lundin@webrtc.org NetEq::Config config; 24835ead381f8dff68ba2f6b7ff163ede6cf4bccc24henrik.lundin@webrtc.org config.sample_rate_hz = out_sampling_khz_ * 1000; 24935ead381f8dff68ba2f6b7ff163ede6cf4bccc24henrik.lundin@webrtc.org neteq_.reset(NetEq::Create(config)); 250b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org max_payload_bytes_ = in_size_samples_ * channels_ * sizeof(int16_t); 251b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org in_data_.reset(new int16_t[in_size_samples_ * channels_]); 252b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org payload_.reset(new uint8_t[max_payload_bytes_]); 253b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org out_data_.reset(new int16_t[out_size_samples_ * channels_]); 254b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} 255b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 256f761d10393ae47283c6170387fcb8cce4aadbd59Minyue LiNetEqQualityTest::~NetEqQualityTest() { 257f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li log_file_.close(); 258f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li} 259f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li 2606568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgbool NoLoss::Lost() { 2616568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return false; 2626568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 2636568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 264194fea7640f6aa8598f1bc454f7350a4b6f22808minyue@webrtc.orgUniformLoss::UniformLoss(double loss_rate) 2656568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org : loss_rate_(loss_rate) { 2666568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 2676568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 2686568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgbool UniformLoss::Lost() { 2696568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org int drop_this = rand(); 2706568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return (drop_this < loss_rate_ * RAND_MAX); 2716568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 2726568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 2736568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgGilbertElliotLoss::GilbertElliotLoss(double prob_trans_11, double prob_trans_01) 2746568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org : prob_trans_11_(prob_trans_11), 2756568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org prob_trans_01_(prob_trans_01), 2766568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org lost_last_(false), 2776568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org uniform_loss_model_(new UniformLoss(0)) { 2786568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 2796568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 2806568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgbool GilbertElliotLoss::Lost() { 2816568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // Simulate bursty channel (Gilbert model). 2826568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // (1st order) Markov chain model with memory of the previous/last 2836568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // packet state (lost or received). 2846568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (lost_last_) { 2856568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // Previous packet was not received. 2866568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org uniform_loss_model_->set_loss_rate(prob_trans_11_); 2876568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return lost_last_ = uniform_loss_model_->Lost(); 2886568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } else { 2896568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org uniform_loss_model_->set_loss_rate(prob_trans_01_); 2906568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return lost_last_ = uniform_loss_model_->Lost(); 2916568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 2926568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 2936568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 294b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgvoid NetEqQualityTest::SetUp() { 2954cf61dd116288e9f119209c59e07f1d9439d8d05henrik.lundin ASSERT_EQ(0, 2964cf61dd116288e9f119209c59e07f1d9439d8d05henrik.lundin neteq_->RegisterPayloadType(decoder_type_, "noname", kPayloadType)); 297b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org rtp_generator_->set_drift_factor(drift_factor_); 2986568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 2996568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org int units = block_duration_ms_ / kPacketLossTimeUnitMs; 3006568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org switch (FLAGS_random_loss_mode) { 3016568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org case 1: { 3026568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // |unit_loss_rate| is the packet loss rate for each unit time interval 3036568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // (kPacketLossTimeUnitMs). Since a packet loss event is generated if any 3046568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // of |block_duration_ms_ / kPacketLossTimeUnitMs| unit time intervals of 3056568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // a full packet duration is drawn with a loss, |unit_loss_rate| fulfills 3066568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // (1 - unit_loss_rate) ^ (block_duration_ms_ / kPacketLossTimeUnitMs) == 3076568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // 1 - packet_loss_rate. 3086568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double unit_loss_rate = (1.0f - pow(1.0f - 0.01f * packet_loss_rate_, 3096568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1.0f / units)); 3106568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org loss_model_.reset(new UniformLoss(unit_loss_rate)); 3116568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org break; 3126568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 3136568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org case 2: { 3146568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // |FLAGS_burst_length| should be integer times of kPacketLossTimeUnitMs. 3156568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org ASSERT_EQ(0, FLAGS_burst_length % kPacketLossTimeUnitMs); 3166568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 3176568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // We do not allow 100 percent packet loss in Gilbert Elliot model, which 3186568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // makes no sense. 3196568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org ASSERT_GT(100, packet_loss_rate_); 3206568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 3216568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // To guarantee the overall packet loss rate, transition probabilities 3226568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // need to satisfy: 3236568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // pi_0 * (1 - prob_trans_01_) ^ units + 3246568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // pi_1 * prob_trans_10_ ^ (units - 1) == 1 - loss_rate 3256568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // pi_0 = prob_trans_10 / (prob_trans_10 + prob_trans_01_) 3266568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // is the stationary state probability of no-loss 3276568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // pi_1 = prob_trans_01_ / (prob_trans_10 + prob_trans_01_) 3286568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // is the stationary state probability of loss 3296568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // After a derivation prob_trans_00 should satisfy: 3306568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // prob_trans_00 ^ (units - 1) = (loss_rate - 1) / prob_trans_10 * 3316568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // prob_trans_00 + (1 - loss_rate) * (1 + 1 / prob_trans_10). 3326568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double loss_rate = 0.01f * packet_loss_rate_; 3336568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double prob_trans_10 = 1.0f * kPacketLossTimeUnitMs / FLAGS_burst_length; 3346568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org double prob_trans_00 = ProbTrans00Solver(units, loss_rate, prob_trans_10); 3356568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org loss_model_.reset(new GilbertElliotLoss(1.0f - prob_trans_10, 3366568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 1.0f - prob_trans_00)); 3376568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org break; 3386568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 3396568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org default: { 3406568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org loss_model_.reset(new NoLoss); 3416568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org break; 3426568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 3436568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 3446568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 3456568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // Make sure that the packet loss profile is same for all derived tests. 3466568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org srand(kInitSeed); 347b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} 348b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 349f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Listd::ofstream& NetEqQualityTest::Log() { 350f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li return log_file_; 351f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li} 352f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li 3536568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.orgbool NetEqQualityTest::PacketLost() { 3546568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org int cycles = block_duration_ms_ / kPacketLossTimeUnitMs; 3556568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 3566568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // The loop is to make sure that codecs with different block lengths share the 3576568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // same packet loss profile. 3586568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org bool lost = false; 3596568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org for (int idx = 0; idx < cycles; idx ++) { 3606568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (loss_model_->Lost()) { 3616568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // The packet will be lost if any of the drawings indicates a loss, but 3626568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // the loop has to go on to make sure that codecs with different block 3636568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // lengths keep the same pace. 3646568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org lost = true; 3656568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 3666568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 3676568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return lost; 3686568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org} 3696568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org 370b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgint NetEqQualityTest::Transmit() { 371b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org int packet_input_time_ms = 372b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org rtp_generator_->GetRtpHeader(kPayloadType, in_size_samples_, 373b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org &rtp_header_); 374f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li Log() << "Packet of size " 375f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << payload_size_bytes_ 376f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << " bytes, for frame at " 377f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << packet_input_time_ms 378f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << " ms "; 3796568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (payload_size_bytes_ > 0) { 3806568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (!PacketLost()) { 381ee2bac26dd3eb4463126098f87701ff66098b288kwiberg int ret = neteq_->InsertPacket( 382ee2bac26dd3eb4463126098f87701ff66098b288kwiberg rtp_header_, 383ee2bac26dd3eb4463126098f87701ff66098b288kwiberg rtc::ArrayView<const uint8_t>(payload_.get(), payload_size_bytes_), 384ee2bac26dd3eb4463126098f87701ff66098b288kwiberg packet_input_time_ms * in_sampling_khz_); 3856568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org if (ret != NetEq::kOK) 3866568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org return -1; 387f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li Log() << "was sent."; 3886568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } else { 389f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li Log() << "was lost."; 3906568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org } 391b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org } 392f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li Log() << std::endl; 393b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org return packet_input_time_ms; 394b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} 395b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 396b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.orgint NetEqQualityTest::DecodeBlock() { 3976955870806624479723addfae6dcf5d13968796cPeter Kasting size_t channels; 398dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting size_t samples; 399b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org int ret = neteq_->GetAudio(out_size_samples_ * channels_, &out_data_[0], 400b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org &samples, &channels, NULL); 401b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 402b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org if (ret != NetEq::kOK) { 403b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org return -1; 404b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org } else { 405b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org assert(channels == channels_); 406dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting assert(samples == static_cast<size_t>(kOutputSizeMs * out_sampling_khz_)); 40791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_CHECK(output_->WriteArray(out_data_.get(), samples * channels)); 408dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting return static_cast<int>(samples); 409b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org } 410b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} 411b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 412e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundinvoid NetEqQualityTest::Simulate() { 413b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org int audio_size_samples; 414b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 415e5ff00a1c65750e7d30a25c4f1da91f0c035d07fHenrik Lundin while (decoded_time_ms_ < FLAGS_runtime_ms) { 4166568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org // Assume 10 packets in packets buffer. 4176568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org while (decodable_time_ms_ - 10 * block_duration_ms_ < decoded_time_ms_) { 418b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org ASSERT_TRUE(in_file_->Read(in_size_samples_ * channels_, &in_data_[0])); 419b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org payload_size_bytes_ = EncodeBlock(&in_data_[0], 420b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org in_size_samples_, &payload_[0], 421b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org max_payload_bytes_); 4226568e97d108dffbf10af04a764287f3d1589691fminyue@webrtc.org total_payload_size_bytes_ += payload_size_bytes_; 423b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org decodable_time_ms_ = Transmit() + block_duration_ms_; 424b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org } 425b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org audio_size_samples = DecodeBlock(); 426b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org if (audio_size_samples > 0) { 427b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org decoded_time_ms_ += audio_size_samples / out_sampling_khz_; 428b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org } 429b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org } 430f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li Log() << "Average bit rate was " 431f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << 8.0f * total_payload_size_bytes_ / FLAGS_runtime_ms 432f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << " kbps" 433f761d10393ae47283c6170387fcb8cce4aadbd59Minyue Li << std::endl; 434b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} 435b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org 436b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} // namespace test 437b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org} // namespace webrtc 438