blob: 31369b4d9d7d25112d3cc8999a28ec849f676bd1 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANALYZER_DATA_PATH_ANALYZER_H
#define ANALYZER_DATA_PATH_ANALYZER_H
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <math.h>
#include "BaseSineAnalyzer.h"
#include "InfiniteRecording.h"
#include "LatencyAnalyzer.h"
/**
* Output a steady sine wave and analyze the return signal.
*
* Use a cosine transform to measure the predicted magnitude and relative phase of the
* looped back sine wave.
*/
class DataPathAnalyzer : public BaseSineAnalyzer {
public:
DataPathAnalyzer() : BaseSineAnalyzer() {
// Add a little bit of noise to reduce blockage by speaker protection and DRC.
setNoiseAmplitude(0.05);
}
/**
* @param frameData contains microphone data with sine signal feedback
* @param channelCount
*/
result_code processInputFrame(float *frameData, int /* channelCount */) override {
result_code result = RESULT_OK;
float sample = frameData[getInputChannel()];
mInfiniteRecording.write(sample);
if (transformSample(sample, mOutputPhase)) {
resetAccumulator();
}
// Update MaxMagnitude if we are locked.
double diff = abs(mPhaseOffset - mPreviousPhaseOffset);
if (diff < mPhaseTolerance) {
mMaxMagnitude = std::max(mMagnitude, mMaxMagnitude);
}
mPreviousPhaseOffset = mPhaseOffset;
return result;
}
std::string analyze() override {
std::stringstream report;
report << "DataPathAnalyzer ------------------\n";
report << LOOPBACK_RESULT_TAG "sine.magnitude = " << std::setw(8)
<< mMagnitude << "\n";
report << LOOPBACK_RESULT_TAG "frames.accumulated = " << std::setw(8)
<< mFramesAccumulated << "\n";
report << LOOPBACK_RESULT_TAG "sine.period = " << std::setw(8)
<< mSinePeriod << "\n";
return report.str();
}
void reset() override {
BaseSineAnalyzer::reset();
mPreviousPhaseOffset = 999.0; // Arbitrary high offset to prevent early lock.
mMaxMagnitude = 0.0;
}
double getMaxMagnitude() {
return mMaxMagnitude;
}
private:
double mPreviousPhaseOffset = 0.0;
double mPhaseTolerance = 2 * M_PI / 48;
double mMaxMagnitude = 0.0;
};
#endif // ANALYZER_DATA_PATH_ANALYZER_H