51 #include <QVarLengthArray>
55 bool enabled {
false };
56 float printIntervalSec { 1.0f };
57 int sendChannel { 0 };
59 bool impulsePending {
false };
60 int64_t lastPrintTimeUS { 0 };
61 int64_t impulseTimeUS { 0 };
62 int64_t impulseTimeSamples { 0 };
63 uint64_t sampleCountSinceImpulse { 1 };
64 double roundTripMean { 0.0 };
65 double roundTripMeanSquare { 0.0 };
66 double roundTripCount { 0.0 };
67 const int bufferSkipStart { 100 };
68 int bufferSkip { bufferSkipStart };
69 const float impulseAmplitude { 0.1f };
70 const int numAmpCells { 10 };
71 const float ampCellHeight { impulseAmplitude/numAmpCells };
73 const double latencyHistogramCellWidth { 5.0 };
74 const double latencyHistogramCellMin { 0.0 };
75 const double latencyHistogramCellMax { 19.0 };
76 const int latencyHistogramPrintCountMax { 72 };
78 int pendingCell { 0 };
79 float sampleRate { 48000.0f };
86 unsigned int n_frames);
88 void writeImpulse(QVarLengthArray<sample_t*>& mInBufCopy,
89 unsigned int n_frames);
100 void printHelp(
char* command,
char helpCase);
104 float getImpulseAmp() {
106 if (pendingCell >= numAmpCells) {
109 float imp = float(pendingCell) * (impulseAmplitude/float(numAmpCells));
113 int getImpulseCellNum(
float amp) {
114 float ch = ampCellHeight;
115 float cell = amp / ch;
116 int iCell = int(std::floor(0.5f + cell));
117 if (iCell > numAmpCells - 1) {
118 std::cerr <<
"*** AudioTester.h: getImpulseCellNum("<<amp<<
"): Return pulse amplitude is beyond maximum expected\n";
119 iCell = numAmpCells-1;
120 }
else if (iCell < 0) {
121 std::cerr <<
"*** AudioTester.h: getImpulseCellNum("<<amp<<
"): Return pulse amplitude is below minimum expected\n";
127 uint64_t timeMicroSec() {
129 using namespace std::chrono;
131 return duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
133 clock_t tics_since_launch = std::clock();
134 double timeUS = double(tics_since_launch)/double(CLOCKS_PER_SEC);
135 return (uint64_t)timeUS;
139 std::map<int, int> latencyHistogram;
141 std::map<int, int> getLatencyHistogram() {
142 return latencyHistogram;
145 void extendLatencyHistogram(
double latencyMS) {
146 int latencyCell =
static_cast<int>(floor(std::max(latencyHistogramCellMin,
147 std::min(latencyHistogramCellMax,
148 std::floor(latencyMS / latencyHistogramCellWidth)))));
149 latencyHistogram[latencyCell] += 1;
152 int latencyHistogramCountMax() {
154 int histStart = latencyHistogramFirstNonzeroCellIndex();
155 int histLast = latencyHistogramLastNonzeroCellIndex();
156 for (
int i = histStart; i <= histLast; ++i) {
157 int lhi = latencyHistogram[i];
165 int latencyHistogramFirstNonzeroCellIndex() {
166 for (
int i=latencyHistogramCellMin; i <= latencyHistogramCellMax; i++) {
167 if (latencyHistogram[i]>0) {
171 std::cerr <<
"*** AudioTester: LATENCY HISTOGRAM IS EMPTY!\n";
175 int latencyHistogramLastNonzeroCellIndex() {
176 for (
int i=latencyHistogramCellMax; i>=latencyHistogramCellMin; i--) {
177 if (latencyHistogram[i]>0) {
181 std::cerr <<
"*** AudioTester: LATENCY HISTOGRAM IS EMPTY!\n";
185 std::string getLatencyHistogramString() {
186 int histStart = latencyHistogramFirstNonzeroCellIndex();
187 int histLast = latencyHistogramLastNonzeroCellIndex();
188 std::string marker =
"*";
189 double histScale = 1.0;
190 int lhcm = latencyHistogramCountMax();
191 int lhpcm = latencyHistogramPrintCountMax;
192 bool normalizing = lhpcm < lhcm;
195 histScale = double(lhpcm) / double(lhcm);
197 std::string rows =
"";
198 for (
int i = histStart; i <= histLast; ++i) {
199 int hi = latencyHistogram[i];
200 int hin = int(std::round(histScale *
double(hi)));
201 std::string istrm1 = std::to_string(
int(latencyHistogramCellWidth *
double(i)));
202 std::string istr = std::to_string(
int(latencyHistogramCellWidth *
double(i+1)));
204 std::string histr = std::to_string(hi);
205 while (histr.length()<3) {
208 std::string row =
"["+istrm1+
"-"+istr+
"ms]="+histr+
":";
209 for (
int j=0; j<hin; j++) {
214 if (histLast == latencyHistogramCellMax) {
215 rows +=
" and above\n";