/* * Copyright (C) 2017 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. */ #include #include #include "lb2/logging.h" #include "lb2/loopback2.h" #include "lb2/loopback_test.h" #include "lb2/sound_system_aaudio.h" #include "lb2/sound_system_echo.h" // The Java layer always uses "mono" mode for native tests. static constexpr int CHANNEL_COUNT = 1; struct LbData { std::unique_ptr testContext; std::unique_ptr soundSys; std::unique_ptr currentTest; }; int lb2ComputeDefaultSettings(int performanceMode, int *samplingRate, int *playerBufferFrameCount, int *recorderBufferFrameCount) { SoundSystemAAudio ss; return ss.probeDefaultSettings(static_cast(performanceMode), samplingRate, playerBufferFrameCount, recorderBufferFrameCount) ? STATUS_SUCCESS : STATUS_FAIL; } int lb2Init(void **ppLbData, int samplingRate, int frameCount, int /*micSource*/, int performanceMode, int testType, double frequency1, char* byteBufferPtr, int byteBufferLength, short* loopbackTone, int /*maxRecordedLateCallbacks*/, int ignoreFirstFrames) { *ppLbData = nullptr; std::unique_ptr lbData(new LbData()); // will auto-release in case if init fails. switch (testType) { case TEST_TYPE_LATENCY: lbData->testContext.reset(new LatencyTestContext( static_cast(performanceMode), frameCount, CHANNEL_COUNT, samplingRate, ignoreFirstFrames, loopbackTone)); break; case TEST_TYPE_BUFFER_PERIOD: { // TODO: Get rid of ByteBuffer. static_assert( sizeof(sample_t) == sizeof(short), "byteBuffer only supports short samples"); AudioBufferView byteBuffer( reinterpret_cast(byteBufferPtr), byteBufferLength, CHANNEL_COUNT); lbData->testContext.reset(new GlitchTestContext( static_cast(performanceMode),frameCount, CHANNEL_COUNT, samplingRate, frequency1, std::move(byteBuffer))); break; } default: ALOGE("Invalid test type: %d", testType); return STATUS_FAIL; } // TODO: Implement switching from the Java side. lbData->soundSys.reset(new SoundSystemAAudio(lbData->testContext.get())); // lbData->soundSys.reset(new SoundSystemEcho(lbData->testContext.get())); switch (testType) { case TEST_TYPE_LATENCY: lbData->currentTest.reset(new LatencyTest( lbData->soundSys.get(), static_cast(lbData->testContext.get()))); break; case TEST_TYPE_BUFFER_PERIOD: lbData->currentTest.reset(new GlitchTest( lbData->soundSys.get(), static_cast(lbData->testContext.get()))); break; } if (!lbData->currentTest->init()) return STATUS_FAIL; *ppLbData = lbData.release(); return STATUS_SUCCESS; } int lb2ProcessNext(void *pLbData, double *pSamples, long maxSamples) { if (pLbData == nullptr) return 0; LbData *lbData = static_cast(pLbData); return lbData->currentTest->collectRecording( AudioBufferView(pSamples, maxSamples / CHANNEL_COUNT, CHANNEL_COUNT)); } int lb2Destroy(void **ppCtx) { LbData** ppLbData = reinterpret_cast(ppCtx); if (ppLbData != nullptr) { delete *ppLbData; *ppLbData = nullptr; return STATUS_SUCCESS; } else { return STATUS_FAIL; } } int* lb2GetRecorderBufferPeriod(void*) { static int *bufferPeriod = new int[1002](); return bufferPeriod; } int lb2GetRecorderMaxBufferPeriod(void*) { return 0; } int64_t lb2GetRecorderVarianceBufferPeriod(void*) { return 0; } int* lb2GetPlayerBufferPeriod(void*) { static int *bufferPeriod = new int[1002](); return bufferPeriod; } int lb2GetPlayerMaxBufferPeriod(void*) { return 0; } int64_t lb2GetPlayerVarianceBufferPeriod(void*) { return 0; } int lb2GetCaptureRank(void*) { return 0; } int lb2GetPlayerTimeStampsAndExpectedBufferPeriod(void*, callbackTimeStamps **ppTSs) { static callbackTimeStamps tss = { new int[10], //int* timeStampsMs new short[10], //short* callbackDurations 0, //short index {0,0}, //struct timespec startTime; 0, //int capacity false //bool exceededCapacity }; *ppTSs = &tss; return 0; } int lb2GetRecorderTimeStampsAndExpectedBufferPeriod(void*, callbackTimeStamps **ppTSs) { static callbackTimeStamps tss = { new int[10], //int* timeStampsMs new short[10], //short* callbackDurations 0, //short index {0,0}, //struct timespec startTime; 0, //int capacity false //bool exceededCapacity }; *ppTSs = &tss; return 0; }