Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OboeTester: add sine wave oscillator as a reference for input #2069

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions apps/OboeTester/app/src/main/cpp/FullDuplexAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ class FullDuplexAnalyzer : public FullDuplexStreamWithConversion {
public:
FullDuplexAnalyzer(LoopbackProcessor *processor)
: mLoopbackProcessor(processor) {
// If we are measuring glitches then we should set this >1 to avoid input underruns.
// Underruns are more common when doing sample rate conversion because of the variable
// callback sizes.
setNumInputBurstsCushion(3);
}

/**
Expand Down
27 changes: 21 additions & 6 deletions apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ class BaseSineAnalyzer : public LoopbackProcessor {
mTolerance = tolerance;
}

// advance and wrap phase
void incrementInputPhase() {
mInputPhase += mPhaseIncrement;
if (mInputPhase > M_PI) {
mInputPhase -= (2.0 * M_PI);
}
}

// advance and wrap phase
void incrementOutputPhase() {
mOutputPhase += mPhaseIncrement;
Expand All @@ -82,6 +90,7 @@ class BaseSineAnalyzer : public LoopbackProcessor {
}
}


/**
* @param frameData upon return, contains the reference sine wave
* @param channelCount
Expand Down Expand Up @@ -142,11 +151,12 @@ class BaseSineAnalyzer : public LoopbackProcessor {
* @param referencePhase
* @return true if magnitude and phase updated
*/
bool transformSample(float sample, float referencePhase) {
// Track incoming signal and slowly adjust magnitude to account
// for drift in the DRC or AGC.
mSinAccumulator += static_cast<double>(sample) * sinf(referencePhase);
mCosAccumulator += static_cast<double>(sample) * cosf(referencePhase);
bool transformSample(float sample) {
// Compare incoming signal with the reference input sine wave.
mSinAccumulator += static_cast<double>(sample) * sinf(mInputPhase);
mCosAccumulator += static_cast<double>(sample) * cosf(mInputPhase);
incrementInputPhase();

mFramesAccumulated++;
// Must be a multiple of the period or the calculation will not be accurate.
if (mFramesAccumulated == mSinePeriod) {
Expand Down Expand Up @@ -181,6 +191,7 @@ class BaseSineAnalyzer : public LoopbackProcessor {
void prepareToTest() override {
LoopbackProcessor::prepareToTest();
mSinePeriod = getSampleRate() / kTargetGlitchFrequency;
mInputPhase = 0.0f;
mOutputPhase = 0.0f;
mInverseSinePeriod = 1.0 / mSinePeriod;
mPhaseIncrement = 2.0 * M_PI * mInverseSinePeriod;
Expand All @@ -193,9 +204,13 @@ class BaseSineAnalyzer : public LoopbackProcessor {
int32_t mSinePeriod = 1; // this will be set before use
double mInverseSinePeriod = 1.0;
double mPhaseIncrement = 0.0;
// Use two sine wave phases, input and output.
// This is because the number of input and output samples may differ
// in a callback and the output frame count may advance ahead of the input, or visa versa.
double mInputPhase = 0.0;
double mOutputPhase = 0.0;
double mOutputAmplitude = 0.75;
// This is the phase offset between the output sine wave and the recorded
// This is the phase offset between the mInputPhase sine wave and the recorded
// signal at the tuned frequency.
// If this jumps around then we are probably just hearing noise.
// Noise can cause the magnitude to be high but mPhaseOffset will be pretty random.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class DataPathAnalyzer : public BaseSineAnalyzer {
float sample = frameData[getInputChannel()];
mInfiniteRecording.write(sample);

if (transformSample(sample, mOutputPhase)) {
if (transformSample(sample)) {
// Analyze magnitude and phase on every period.
if (mPhaseOffset != kPhaseInvalid) {
double diff = fabs(calculatePhaseError(mPhaseOffset, mPreviousPhaseOffset));
Expand Down
12 changes: 1 addition & 11 deletions apps/OboeTester/app/src/main/cpp/analyzer/GlitchAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class GlitchAnalyzer : public BaseSineAnalyzer {
// Track incoming signal and slowly adjust magnitude to account
// for drift in the DRC or AGC.
// Must be a multiple of the period or the calculation will not be accurate.
if (transformSample(sample, mInputPhase)) {
if (transformSample(sample)) {
// Adjust phase to account for sample rate drift.
mInputPhase += mPhaseOffset;

Expand All @@ -249,7 +249,6 @@ class GlitchAnalyzer : public BaseSineAnalyzer {
}
}
}
incrementInputPhase();
} break;

case STATE_GLITCHING: {
Expand Down Expand Up @@ -288,14 +287,6 @@ class GlitchAnalyzer : public BaseSineAnalyzer {

int maxMeasurableGlitchLength() const { return 2 * mSinePeriod; }

// advance and wrap phase
void incrementInputPhase() {
mInputPhase += mPhaseIncrement;
if (mInputPhase > M_PI) {
mInputPhase -= (2.0 * M_PI);
}
}

bool isOutputEnabled() override { return mState != STATE_IDLE; }

void onGlitchStart() {
Expand Down Expand Up @@ -399,7 +390,6 @@ class GlitchAnalyzer : public BaseSineAnalyzer {
sine_state_t mState = STATE_IDLE;
int64_t mLastGlitchPosition;

double mInputPhase = 0.0;
double mMaxGlitchDelta = 0.0;
int32_t mGlitchCount = 0;
int32_t mConsecutiveBadFrames = 0;
Expand Down