Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19ae3119 authored by Phil Burk's avatar Phil Burk Committed by Android (Google) Code Review
Browse files

Merge "aaudio_loopback: improve tolerance to noise"

parents 3ca58193 5bce4c9f
Loading
Loading
Loading
Loading
+142 −66
Original line number Diff line number Diff line
@@ -163,8 +163,7 @@ static int measureLatencyFromEchos(const float *haystack, int haystackSize,
                            const float *needle, int needleSize,
                            LatencyReport *report) {
    const double threshold = 0.1;
    printf("measureLatencyFromEchos: haystackSize = %d, needleSize = %d\n",
           haystackSize, needleSize);
    // printf("%s: haystackSize = %d, needleSize = %d\n", __func__, haystackSize, needleSize);

    // Find first peak
    int first = (int) (findFirstMatch(haystack,
@@ -181,8 +180,6 @@ static int measureLatencyFromEchos(const float *haystack, int haystackSize,
                                      needle,
                                      needleSize,
                                      threshold) + 0.5);

    printf("measureLatencyFromEchos: first = %d, again at %d\n", first, again);
    first = again;

    // Allocate results array
@@ -199,7 +196,7 @@ static int measureLatencyFromEchos(const float *haystack, int haystackSize,

    // Add higher harmonics mapped onto lower harmonics.
    // This reinforces the "fundamental" echo.
    const int numEchoes = 10;
    const int numEchoes = 8;
    for (int partial = 1; partial < numEchoes; partial++) {
        for (int i = 0; i < numCorrelations; i++) {
            harmonicSums[i / partial] += correlations[i] / partial;
@@ -216,7 +213,7 @@ static int measureLatencyFromEchos(const float *haystack, int haystackSize,
            maxCorrelation = harmonicSums[i];
            sumOfPeaks += maxCorrelation;
            peakIndex = i;
            printf("maxCorrelation = %f at %d\n", maxCorrelation, peakIndex);
            // printf("maxCorrelation = %f at %d\n", maxCorrelation, peakIndex);
        }
    }

@@ -476,9 +473,13 @@ public:
    void report() override {

        printf("EchoAnalyzer ---------------\n");
        printf(LOOPBACK_RESULT_TAG "measured.gain          = %f\n", mMeasuredLoopGain);
        printf(LOOPBACK_RESULT_TAG "echo.gain              = %f\n", mEchoGain);
        printf(LOOPBACK_RESULT_TAG "test.state             = %d\n", mState);
        printf(LOOPBACK_RESULT_TAG "measured.gain          = %8f\n", mMeasuredLoopGain);
        printf(LOOPBACK_RESULT_TAG "echo.gain              = %8f\n", mEchoGain);
        printf(LOOPBACK_RESULT_TAG "test.state             = %8d\n", mState);
        printf(LOOPBACK_RESULT_TAG "test.state.name        = %8s\n", convertStateToText(mState));
        if (mState == STATE_WAITING_FOR_SILENCE) {
            printf("WARNING - Stuck waiting for silence. Input may be too noisy!\n");
        }
        if (mMeasuredLoopGain >= 0.9999) {
            printf("   ERROR - clipping, turn down volume slightly\n");
        } else {
@@ -491,9 +492,12 @@ public:
                printf("   ERROR - confidence too low = %f\n", mLatencyReport.confidence);
            } else {
                double latencyMillis = 1000.0 * mLatencyReport.latencyInFrames / getSampleRate();
                printf(LOOPBACK_RESULT_TAG "latency.frames        = %8.2f\n", mLatencyReport.latencyInFrames);
                printf(LOOPBACK_RESULT_TAG "latency.msec          = %8.2f\n", latencyMillis);
                printf(LOOPBACK_RESULT_TAG "latency.confidence    = %8.6f\n", mLatencyReport.confidence);
                printf(LOOPBACK_RESULT_TAG "latency.frames         = %8.2f\n",
                       mLatencyReport.latencyInFrames);
                printf(LOOPBACK_RESULT_TAG "latency.msec           = %8.2f\n",
                       latencyMillis);
                printf(LOOPBACK_RESULT_TAG "latency.confidence     = %8.6f\n",
                       mLatencyReport.confidence);
            }
        }
    }
@@ -527,7 +531,7 @@ public:
        int numWritten;
        int numSamples;

        echo_state_t nextState = mState;
        echo_state nextState = mState;

        switch (mState) {
            case STATE_INITIAL_SILENCE:
@@ -553,6 +557,7 @@ public:
                        //       mLoopCounter, peak);
                        mDownCounter = 8;
                        mMeasuredLoopGain = peak;  // assumes original pulse amplitude is one
                        mSilenceThreshold = peak * 0.1; // scale silence to measured pulse
                        // Calculate gain that will give us a nice decaying echo.
                        mEchoGain = mDesiredEchoGain / mMeasuredLoopGain;
                        if (mEchoGain > MAX_ECHO_GAIN) {
@@ -638,7 +643,7 @@ public:

private:

    enum echo_state_t {
    enum echo_state {
        STATE_INITIAL_SILENCE,
        STATE_MEASURING_GAIN,
        STATE_WAITING_FOR_SILENCE,
@@ -648,6 +653,35 @@ private:
        STATE_FAILED
    };

    const char *convertStateToText(echo_state state) {
        const char *result = "Unknown";
        switch(state) {
            case STATE_INITIAL_SILENCE:
                result = "INIT";
                break;
            case STATE_MEASURING_GAIN:
                result = "GAIN";
                break;
            case STATE_WAITING_FOR_SILENCE:
                result = "SILENCE";
                break;
            case STATE_SENDING_PULSE:
                result = "PULSE";
                break;
            case STATE_GATHERING_ECHOS:
                result = "ECHOS";
                break;
            case STATE_DONE:
                result = "DONE";
                break;
            case STATE_FAILED:
                result = "FAILED";
                break;
        }
        return result;
    }


    int32_t         mDownCounter = 500;
    int32_t         mLoopCounter = 0;
    int32_t         mSampleIndex = 0;
@@ -656,7 +690,7 @@ private:
    float           mMeasuredLoopGain = 0.0f;
    float           mDesiredEchoGain = 0.95f;
    float           mEchoGain = 1.0f;
    echo_state_t    mState = STATE_INITIAL_SILENCE;
    echo_state      mState = STATE_INITIAL_SILENCE;

    AudioRecording  mAudioRecording; // contains only the input after the gain detection burst
    LatencyReport   mLatencyReport;
@@ -680,21 +714,32 @@ public:

    void report() override {
        printf("SineAnalyzer ------------------\n");
        printf(LOOPBACK_RESULT_TAG "peak.amplitude     = %7.5f\n", mPeakAmplitude);
        printf(LOOPBACK_RESULT_TAG "sine.magnitude     = %7.5f\n", mMagnitude);
        printf(LOOPBACK_RESULT_TAG "phase.offset       = %7.5f\n", mPhaseOffset);
        printf(LOOPBACK_RESULT_TAG "ref.phase          = %7.5f\n", mPhase);
        printf(LOOPBACK_RESULT_TAG "frames.accumulated = %6d\n", mFramesAccumulated);
        printf(LOOPBACK_RESULT_TAG "sine.period        = %6d\n", mSinePeriod);
        printf(LOOPBACK_RESULT_TAG "test.state         = %6d\n", mState);
        printf(LOOPBACK_RESULT_TAG "frame.count        = %6d\n", mFrameCounter);
        printf(LOOPBACK_RESULT_TAG "peak.amplitude     = %8f\n", mPeakAmplitude);
        printf(LOOPBACK_RESULT_TAG "sine.magnitude     = %8f\n", mMagnitude);
        printf(LOOPBACK_RESULT_TAG "peak.noise         = %8f\n", mPeakNoise);
        printf(LOOPBACK_RESULT_TAG "rms.noise          = %8f\n", mRootMeanSquareNoise);
        float amplitudeRatio = mMagnitude / mPeakNoise;
        float signalToNoise = amplitudeRatio * amplitudeRatio;
        printf(LOOPBACK_RESULT_TAG "signal.to.noise    = %8.2f\n", signalToNoise);
        float signalToNoiseDB = 10.0 * log(signalToNoise);
        printf(LOOPBACK_RESULT_TAG "signal.to.noise.db = %8.2f\n", signalToNoiseDB);
        if (signalToNoiseDB < MIN_SNRATIO_DB) {
            printf("WARNING - signal to noise ratio is too low! < %d dB\n", MIN_SNRATIO_DB);
        }
        printf(LOOPBACK_RESULT_TAG "phase.offset       = %8.5f\n", mPhaseOffset);
        printf(LOOPBACK_RESULT_TAG "ref.phase          = %8.5f\n", mPhase);
        printf(LOOPBACK_RESULT_TAG "frames.accumulated = %8d\n", mFramesAccumulated);
        printf(LOOPBACK_RESULT_TAG "sine.period        = %8d\n", mSinePeriod);
        printf(LOOPBACK_RESULT_TAG "test.state         = %8d\n", mState);
        printf(LOOPBACK_RESULT_TAG "frame.count        = %8d\n", mFrameCounter);
        // Did we ever get a lock?
        bool gotLock = (mState == STATE_LOCKED) || (mGlitchCount > 0);
        if (!gotLock) {
            printf("ERROR - failed to lock on reference sine tone\n");
        } else {
            // Only print if meaningful.
            printf(LOOPBACK_RESULT_TAG "glitch.count       = %6d\n", mGlitchCount);
            printf(LOOPBACK_RESULT_TAG "glitch.count       = %8d\n", mGlitchCount);
            printf(LOOPBACK_RESULT_TAG "max.glitch         = %8f\n", mMaxGlitchDelta);
        }
    }

@@ -732,15 +777,48 @@ public:
        }

        for (int i = 0; i < numFrames; i++) {
            bool sineEnabled = true;
            float sample = inputData[i * inputChannelCount];

            float sinOut = sinf(mPhase);

            switch (mState) {
                case STATE_IDLE:
                    sineEnabled = false;
                    mDownCounter--;
                    if (mDownCounter <= 0) {
                        mState = STATE_MEASURE_NOISE;
                        mDownCounter = NOISE_FRAME_COUNT;
                    }
                    break;
                case STATE_MEASURE_NOISE:
                    sineEnabled = false;
                    mPeakNoise = std::max(abs(sample), mPeakNoise);
                    mNoiseSumSquared += sample * sample;
                    mDownCounter--;
                    if (mDownCounter <= 0) {
                        mState = STATE_WAITING_FOR_SIGNAL;
                        mRootMeanSquareNoise = sqrt(mNoiseSumSquared / NOISE_FRAME_COUNT);
                        mTolerance = std::max(MIN_TOLERANCE, mPeakNoise * 2.0f);
                        mPhase = 0.0; // prevent spike at start
                    }
                    break;

                case STATE_IMMUNE:
                    mDownCounter--;
                    if (mDownCounter <= 0) {
                        mState = STATE_WAITING_FOR_SIGNAL;
                    }
                    break;

                case STATE_WAITING_FOR_SIGNAL:
                    if (peak > mThreshold) {
                        mState = STATE_WAITING_FOR_LOCK;
                        //printf("%5d: switch to STATE_WAITING_FOR_LOCK\n", mFrameCounter);
                        resetAccumulator();
                    }
                    break;

                case STATE_WAITING_FOR_LOCK:
                    mSinAccumulator += sample * sinOut;
                    mCosAccumulator += sample * cosf(mPhase);
@@ -766,13 +844,14 @@ public:
                    // printf("    predicted = %f, actual = %f\n", predicted, sample);

                    float diff = predicted - sample;
                    if (fabs(diff) > mTolerance) {
                    float absDiff = fabs(diff);
                    mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
                    if (absDiff > mTolerance) {
                        mGlitchCount++;
                        //printf("%5d: Got a glitch # %d, predicted = %f, actual = %f\n",
                        //       mFrameCounter, mGlitchCount, predicted, sample);
                        mState = STATE_IMMUNE;
                        //printf("%5d: switch to STATE_IMMUNE\n", mFrameCounter);
                        mDownCounter = mSinePeriod;  // Set duration of IMMUNE state.
                        mDownCounter = mSinePeriod * PERIODS_IMMUNE;
                    }

                    // Track incoming signal and slowly adjust magnitude to account
@@ -792,44 +871,23 @@ public:
                } break;
            }

            float output = 0.0f;
            // Output sine wave so we can measure it.
            outputData[i * outputChannelCount] = (sinOut * mOutputAmplitude)
            if (sineEnabled) {
                output = (sinOut * mOutputAmplitude)
                         + (mWhiteNoise.nextRandomDouble() * mNoiseAmplitude);
                // printf("%5d: sin(%f) = %f, %f\n", i, mPhase, sinOut,  mPhaseIncrement);

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

            mFrameCounter++;
            }
            outputData[i * outputChannelCount] = output;

        // Do these once per buffer.
        switch (mState) {
            case STATE_IDLE:
                mState = STATE_IMMUNE; // so we can tell when
                break;
            case STATE_IMMUNE:
                mDownCounter -= numFrames;
                if (mDownCounter <= 0) {
                    mState = STATE_WAITING_FOR_SIGNAL;
                    //printf("%5d: switch to STATE_WAITING_FOR_SIGNAL\n", mFrameCounter);
                }
                break;
            case STATE_WAITING_FOR_SIGNAL:
                if (peak > mThreshold) {
                    mState = STATE_WAITING_FOR_LOCK;
                    //printf("%5d: switch to STATE_WAITING_FOR_LOCK\n", mFrameCounter);
                    resetAccumulator();
                }
                break;
            case STATE_WAITING_FOR_LOCK:
            case STATE_LOCKED:
                break;
        }

            mFrameCounter++;
        }
    }

    void resetAccumulator() {
@@ -840,18 +898,24 @@ public:

    void reset() override {
        mGlitchCount = 0;
        mState = STATE_IMMUNE;
        mDownCounter = IMMUNE_FRAME_COUNT;
        mState = STATE_IDLE;
        mDownCounter = IDLE_FRAME_COUNT;
        mPhaseIncrement = 2.0 * M_PI / mSinePeriod;
        printf("phaseInc = %f for period %d\n", mPhaseIncrement, mSinePeriod);
        resetAccumulator();
        mProcessCount = 0;
        mPeakNoise = 0.0f;
        mNoiseSumSquared = 0.0;
        mRootMeanSquareNoise = 0.0;
        mPhase = 0.0f;
        mMaxGlitchDelta = 0.0;
    }

private:

    enum sine_state_t {
        STATE_IDLE,
        STATE_MEASURE_NOISE,
        STATE_IMMUNE,
        STATE_WAITING_FOR_SIGNAL,
        STATE_WAITING_FOR_LOCK,
@@ -859,10 +923,16 @@ private:
    };

    enum constants {
        IMMUNE_FRAME_COUNT = 48 * 500,
        PERIODS_NEEDED_FOR_LOCK = 8
        // Arbitrary durations, assuming 48000 Hz
        IDLE_FRAME_COUNT = 48 * 100,
        NOISE_FRAME_COUNT = 48 * 600,
        PERIODS_NEEDED_FOR_LOCK = 8,
        PERIODS_IMMUNE = 2,
        MIN_SNRATIO_DB = 65
    };

    static constexpr float MIN_TOLERANCE = 0.01;

    int     mSinePeriod = 79;
    double  mPhaseIncrement = 0.0;
    double  mPhase = 0.0;
@@ -870,17 +940,23 @@ private:
    double  mPreviousPhaseOffset = 0.0;
    double  mMagnitude = 0.0;
    double  mThreshold = 0.005;
    double  mTolerance = 0.01;
    double  mTolerance = MIN_TOLERANCE;
    int32_t mFramesAccumulated = 0;
    int32_t mProcessCount = 0;
    double  mSinAccumulator = 0.0;
    double  mCosAccumulator = 0.0;
    float   mMaxGlitchDelta = 0.0f;
    int32_t mGlitchCount = 0;
    double  mPeakAmplitude = 0.0;
    int     mDownCounter = IMMUNE_FRAME_COUNT;
    int     mDownCounter = IDLE_FRAME_COUNT;
    int32_t mFrameCounter = 0;
    float   mOutputAmplitude = 0.75;

    // measure background noise
    float   mPeakNoise = 0.0f;
    double  mNoiseSumSquared = 0.0;
    double  mRootMeanSquareNoise = 0.0;

    PseudoRandom  mWhiteNoise;
    float   mNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC.

+16 −20
Original line number Diff line number Diff line
@@ -37,13 +37,12 @@

// Tag for machine readable results as property = value pairs
#define RESULT_TAG              "RESULT: "
#define NUM_SECONDS             5
#define PERIOD_MILLIS           1000
#define NUM_INPUT_CHANNELS      1
#define FILENAME_ALL            "/data/loopback_all.wav"
#define FILENAME_ECHOS          "/data/loopback_echos.wav"
#define APP_VERSION             "0.2.04"
#define APP_VERSION             "0.3.00"

constexpr int kLogPeriodMillis       = 1000;
constexpr int kNumInputChannels      = 1;
constexpr int kNumCallbacksToDrain   = 20;
constexpr int kNumCallbacksToDiscard = 20;

@@ -336,7 +335,7 @@ int main(int argc, const char **argv)

    aaudio_result_t       result = AAUDIO_OK;
    aaudio_sharing_mode_t requestedInputSharingMode  = AAUDIO_SHARING_MODE_SHARED;
    int                   requestedInputChannelCount = NUM_INPUT_CHANNELS;
    int                   requestedInputChannelCount = kNumInputChannels;
    aaudio_format_t       requestedInputFormat       = AAUDIO_FORMAT_UNSPECIFIED;
    int32_t               requestedInputCapacity     = AAUDIO_UNSPECIFIED;
    aaudio_performance_mode_t inputPerformanceLevel  = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
@@ -459,7 +458,9 @@ int main(int argc, const char **argv)
    argParser.setPerformanceMode(inputPerformanceLevel);
    argParser.setChannelCount(requestedInputChannelCount);
    argParser.setSharingMode(requestedInputSharingMode);
    // Warning! If you change input capacity then you may not get a FAST track on Legacy path.
    if (requestedInputCapacity != AAUDIO_UNSPECIFIED) {
        printf("Warning! If you set input capacity then maybe no FAST track on Legacy path!\n");
    }
    argParser.setBufferCapacity(requestedInputCapacity);

    result = recorder.open(argParser);
@@ -510,15 +511,11 @@ int main(int argc, const char **argv)
    // Start OUTPUT first so INPUT does not overflow.
    result = player.start();
    if (result != AAUDIO_OK) {
        printf("ERROR - AAudioStream_requestStart(output) returned %d = %s\n",
               result, AAudio_convertResultToText(result));
        goto finish;
    }

    result = recorder.start();
    if (result != AAUDIO_OK) {
        printf("ERROR - AAudioStream_requestStart(input) returned %d = %s\n",
               result, AAudio_convertResultToText(result));
        goto finish;
    }

@@ -561,7 +558,7 @@ int main(int argc, const char **argv)
                   AAudioStream_getXRunCount(outputStream)
            );
        }
        int32_t periodMillis = (timeMillis < 2000) ? PERIOD_MILLIS / 4 : PERIOD_MILLIS;
        int32_t periodMillis = (timeMillis < 2000) ? kLogPeriodMillis / 4 : kLogPeriodMillis;
        usleep(periodMillis * 1000);
        timeMillis += periodMillis;
    }
@@ -586,12 +583,12 @@ int main(int argc, const char **argv)
    if (loopbackData.inputError == AAUDIO_OK) {
        if (testMode == TEST_SINE_MAGNITUDE) {
            printAudioGraph(loopbackData.audioRecording, 200);
        }
            // Print again so we don't have to scroll past waveform.
            printf("OUTPUT Stream ----------------------------------------\n");
            argParser.compareWithStream(outputStream);
            printf("INPUT  Stream ----------------------------------------\n");
            argParser.compareWithStream(inputStream);
        }

        loopbackData.loopbackProcessor->report();
    }
@@ -600,21 +597,21 @@ int main(int argc, const char **argv)
        int32_t framesRead = AAudioStream_getFramesRead(inputStream);
        int32_t framesWritten = AAudioStream_getFramesWritten(inputStream);
        printf("Callback Results ---------------------------------------- INPUT\n");
        printf("  input overruns   = %d\n", AAudioStream_getXRunCount(inputStream));
        printf("  input overruns   = %8d\n", AAudioStream_getXRunCount(inputStream));
        printf("  framesWritten    = %8d\n", framesWritten);
        printf("  framesRead       = %8d\n", framesRead);
        printf("  myFramesRead     = %8d\n", (int) loopbackData.framesReadTotal);
        printf("  written - read   = %8d\n", (int) (framesWritten - framesRead));
        printf("  insufficient #   = %8d\n", (int) loopbackData.insufficientReadCount);
        if (loopbackData.insufficientReadCount > 0) {
            printf("  insufficient frames = %8d\n", (int) loopbackData.insufficientReadFrames);
            printf("  insuffic. frames = %8d\n", (int) loopbackData.insufficientReadFrames);
        }
    }
    {
        int32_t framesRead = AAudioStream_getFramesRead(outputStream);
        int32_t framesWritten = AAudioStream_getFramesWritten(outputStream);
        printf("Callback Results ---------------------------------------- OUTPUT\n");
        printf("  output underruns = %d\n", AAudioStream_getXRunCount(outputStream));
        printf("  output underruns = %8d\n", AAudioStream_getXRunCount(outputStream));
        printf("  myFramesWritten  = %8d\n", (int) loopbackData.framesWrittenTotal);
        printf("  framesWritten    = %8d\n", framesWritten);
        printf("  framesRead       = %8d\n", framesRead);
@@ -659,4 +656,3 @@ finish:
        return EXIT_SUCCESS;
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -193,7 +193,7 @@ public:
     aaudio_result_t start() {
        aaudio_result_t result = AAudioStream_requestStart(mStream);
        if (result != AAUDIO_OK) {
            printf("ERROR - AAudioStream_requestStart() returned %d %s\n",
            printf("ERROR - AAudioStream_requestStart(output) returned %d %s\n",
                    result, AAudio_convertResultToText(result));
        }
        return result;
@@ -203,7 +203,7 @@ public:
    aaudio_result_t stop() {
        aaudio_result_t result = AAudioStream_requestStop(mStream);
        if (result != AAUDIO_OK) {
            printf("ERROR - AAudioStream_requestStop() returned %d %s\n",
            printf("ERROR - AAudioStream_requestStop(output) returned %d %s\n",
                   result, AAudio_convertResultToText(result));
        }
        int32_t xRunCount = AAudioStream_getXRunCount(mStream);
@@ -215,7 +215,7 @@ public:
    aaudio_result_t pause() {
        aaudio_result_t result = AAudioStream_requestPause(mStream);
        if (result != AAUDIO_OK) {
            printf("ERROR - AAudioStream_requestPause() returned %d %s\n",
            printf("ERROR - AAudioStream_requestPause(output) returned %d %s\n",
                   result, AAudio_convertResultToText(result));
        }
        int32_t xRunCount = AAudioStream_getXRunCount(mStream);
@@ -227,7 +227,7 @@ public:
    aaudio_result_t flush() {
        aaudio_result_t result = AAudioStream_requestFlush(mStream);
        if (result != AAUDIO_OK) {
            printf("ERROR - AAudioStream_requestFlush() returned %d %s\n",
            printf("ERROR - AAudioStream_requestFlush(output) returned %d %s\n",
                   result, AAudio_convertResultToText(result));
        }
        return result;
+6 −3
Original line number Diff line number Diff line
@@ -201,8 +201,10 @@ public:
     aaudio_result_t start() {
        aaudio_result_t result = AAudioStream_requestStart(mStream);
        if (result != AAUDIO_OK) {
            fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n",
            fprintf(stderr, "ERROR - AAudioStream_requestStart(input) returned %d %s\n",
                    result, AAudio_convertResultToText(result));
            fprintf(stderr, "        Did you remember to enter:   adb root    ????\n");

        }
        return result;
    }
@@ -211,8 +213,9 @@ public:
    aaudio_result_t stop() {
        aaudio_result_t result = AAudioStream_requestStop(mStream);
        if (result != AAUDIO_OK) {
            fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
            fprintf(stderr, "ERROR - AAudioStream_requestStop(input) returned %d %s\n",
                    result, AAudio_convertResultToText(result));

        }
        return result;
    }
@@ -221,7 +224,7 @@ public:
    aaudio_result_t pause() {
        aaudio_result_t result = AAudioStream_requestPause(mStream);
        if (result != AAUDIO_OK) {
            fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
            fprintf(stderr, "ERROR - AAudioStream_requestPause(input) returned %d %s\n",
                    result, AAudio_convertResultToText(result));
        }
        return result;