- clang format + naming improved
This commit is contained in:
+372
-378
@@ -14,586 +14,580 @@ using namespace Audio;
|
||||
|
||||
// -------------------- AndroidEnumerator -----------------------------
|
||||
|
||||
AndroidEnumerator::AndroidEnumerator()
|
||||
{}
|
||||
AndroidEnumerator::AndroidEnumerator() {}
|
||||
|
||||
AndroidEnumerator::~AndroidEnumerator()
|
||||
{}
|
||||
AndroidEnumerator::~AndroidEnumerator() {}
|
||||
|
||||
int AndroidEnumerator::indexOfDefaultDevice()
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AndroidEnumerator::count()
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AndroidEnumerator::idAt(int index)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string AndroidEnumerator::nameAt(int index)
|
||||
{
|
||||
return "Audio";
|
||||
return "Audio";
|
||||
}
|
||||
|
||||
void AndroidEnumerator::open(int direction)
|
||||
{}
|
||||
void AndroidEnumerator::open(int direction) {}
|
||||
|
||||
void AndroidEnumerator::close()
|
||||
{}
|
||||
void AndroidEnumerator::close() {}
|
||||
|
||||
// -----------------------
|
||||
|
||||
OpenSLEngine::OpenSLEngine()
|
||||
{}
|
||||
OpenSLEngine::OpenSLEngine() {}
|
||||
|
||||
OpenSLEngine::~OpenSLEngine()
|
||||
{}
|
||||
OpenSLEngine::~OpenSLEngine() {}
|
||||
|
||||
void OpenSLEngine::open()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
if (++mUsageCounter == 1)
|
||||
internalOpen();
|
||||
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
if (++mUsageCounter == 1)
|
||||
internalOpen();
|
||||
}
|
||||
|
||||
void OpenSLEngine::close()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
if (mUsageCounter == 0)
|
||||
return;
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
if (mUsageCounter == 0)
|
||||
return;
|
||||
|
||||
if (--mUsageCounter == 0)
|
||||
internalClose();
|
||||
if (--mUsageCounter == 0)
|
||||
internalClose();
|
||||
}
|
||||
|
||||
#define CHECK_OPENSLES_ERROR if (resultCode != SL_RESULT_SUCCESS) throw Exception(ERR_OPENSLES, (int)resultCode)
|
||||
#define CHECK_OPENSLES_ERROR \
|
||||
if (resultCode != SL_RESULT_SUCCESS) \
|
||||
throw Exception(ERR_OPENSLES, (int)resultCode)
|
||||
|
||||
void OpenSLEngine::internalOpen()
|
||||
{
|
||||
SLresult resultCode;
|
||||
SLresult resultCode;
|
||||
|
||||
// Instantiate OpenSL ES engine object
|
||||
resultCode = slCreateEngine(&mEngineObject, 0, nullptr, 0, nullptr, nullptr);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Instantiate OpenSL ES engine object
|
||||
resultCode = slCreateEngine(&mEngineObject, 0, nullptr, 0, nullptr, nullptr);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Bring it online (realize)
|
||||
resultCode = (*mEngineObject)->Realize(mEngineObject, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Bring it online (realize)
|
||||
resultCode = (*mEngineObject)->Realize(mEngineObject, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Get interface finally
|
||||
resultCode = (*mEngineObject)->GetInterface(mEngineObject, SL_IID_ENGINE, &mEngineInterface);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Get interface finally
|
||||
resultCode = (*mEngineObject)->GetInterface(mEngineObject, SL_IID_ENGINE, &mEngineInterface);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
ICELogInfo(<< "OpenSL engine object created.");
|
||||
ICELogInfo(<< "OpenSL engine object created.");
|
||||
}
|
||||
|
||||
void OpenSLEngine::internalClose()
|
||||
{
|
||||
if (mEngineObject != nullptr)
|
||||
{
|
||||
ICELogInfo(<< "Destroy OpenSL engine object.");
|
||||
if (mEngineObject != nullptr)
|
||||
{
|
||||
ICELogInfo(<< "Destroy OpenSL engine object.");
|
||||
|
||||
(*mEngineObject)->Destroy(mEngineObject);
|
||||
mEngineObject = nullptr;
|
||||
mEngineInterface = nullptr;
|
||||
}
|
||||
(*mEngineObject)->Destroy(mEngineObject);
|
||||
mEngineObject = nullptr;
|
||||
mEngineInterface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SLEngineItf OpenSLEngine::getNativeEngine() const
|
||||
{
|
||||
return mEngineInterface;
|
||||
return mEngineInterface;
|
||||
}
|
||||
|
||||
static OpenSLEngine OpenSLEngineInstance;
|
||||
|
||||
OpenSLEngine& OpenSLEngine::instance()
|
||||
OpenSLEngine& OpenSLEngine::instance()
|
||||
{
|
||||
return OpenSLEngineInstance;
|
||||
return OpenSLEngineInstance;
|
||||
}
|
||||
|
||||
// --------------- Input implementation ----------------
|
||||
AndroidInputDevice::AndroidInputDevice(int devId)
|
||||
{}
|
||||
AndroidInputDevice::AndroidInputDevice(int devId) {}
|
||||
|
||||
AndroidInputDevice::~AndroidInputDevice()
|
||||
{}
|
||||
AndroidInputDevice::~AndroidInputDevice() {}
|
||||
|
||||
static int RateToProbe[12][2] = {
|
||||
{ SL_SAMPLINGRATE_16, 16000 },
|
||||
{ SL_SAMPLINGRATE_8, 8000 },
|
||||
{ SL_SAMPLINGRATE_32, 32000 },
|
||||
{ SL_SAMPLINGRATE_44_1, 44100 },
|
||||
{ SL_SAMPLINGRATE_11_025, 10025 },
|
||||
{ SL_SAMPLINGRATE_22_05, 22050 },
|
||||
{ SL_SAMPLINGRATE_24, 24000 },
|
||||
{ SL_SAMPLINGRATE_48, 48000 },
|
||||
{ SL_SAMPLINGRATE_64, 64000 },
|
||||
{ SL_SAMPLINGRATE_88_2, 88200 },
|
||||
{ SL_SAMPLINGRATE_96, 96000 },
|
||||
{ SL_SAMPLINGRATE_192, 192000} };
|
||||
{SL_SAMPLINGRATE_16, 16000}, {SL_SAMPLINGRATE_8, 8000}, {SL_SAMPLINGRATE_32, 32000},
|
||||
{SL_SAMPLINGRATE_44_1, 44100}, {SL_SAMPLINGRATE_11_025, 10025}, {SL_SAMPLINGRATE_22_05, 22050},
|
||||
{SL_SAMPLINGRATE_24, 24000}, {SL_SAMPLINGRATE_48, 48000}, {SL_SAMPLINGRATE_64, 64000},
|
||||
{SL_SAMPLINGRATE_88_2, 88200}, {SL_SAMPLINGRATE_96, 96000}, {SL_SAMPLINGRATE_192, 192000}};
|
||||
|
||||
bool AndroidInputDevice::open()
|
||||
{
|
||||
if (active())
|
||||
return true;
|
||||
if (active())
|
||||
return true;
|
||||
|
||||
OpenSLEngine::instance().open();
|
||||
OpenSLEngine::instance().open();
|
||||
|
||||
// Probe few sampling rates
|
||||
bool opened = false;
|
||||
for (int rateIndex = 0; rateIndex < 12 && !opened; rateIndex++)
|
||||
{
|
||||
try
|
||||
// Probe few sampling rates
|
||||
bool opened = false;
|
||||
for (int rateIndex = 0; rateIndex < 12 && !opened; rateIndex++)
|
||||
{
|
||||
internalOpen(RateToProbe[rateIndex][0], RateToProbe[rateIndex][1]);
|
||||
mDeviceRate = RateToProbe[rateIndex][1];
|
||||
ICELogInfo(<< "Input Opened with rate " << mDeviceRate << " and rate index " << rateIndex);
|
||||
opened = mDeviceRate != 0;
|
||||
if (!opened)
|
||||
internalClose();
|
||||
try
|
||||
{
|
||||
internalOpen(RateToProbe[rateIndex][0], RateToProbe[rateIndex][1]);
|
||||
mDeviceRate = RateToProbe[rateIndex][1];
|
||||
ICELogInfo(<< "Input Opened with rate " << mDeviceRate << " and rate index " << rateIndex);
|
||||
opened = mDeviceRate != 0;
|
||||
if (!opened)
|
||||
internalClose();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
opened = false;
|
||||
internalClose();
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
opened = false;
|
||||
internalClose();
|
||||
}
|
||||
}
|
||||
mActive = opened;
|
||||
mActive = opened;
|
||||
|
||||
return opened;
|
||||
return opened;
|
||||
}
|
||||
|
||||
void AndroidInputDevice::close()
|
||||
{
|
||||
// There is no check for active() value because close() can be called to cleanup after bad open() call.
|
||||
internalClose();
|
||||
OpenSLEngine::instance().close();
|
||||
mActive = false;
|
||||
// There is no check for active() value because close() can be called to cleanup after bad open() call.
|
||||
internalClose();
|
||||
OpenSLEngine::instance().close();
|
||||
mActive = false;
|
||||
}
|
||||
|
||||
Format AndroidInputDevice::getFormat()
|
||||
{
|
||||
return Format(mDeviceRate, 1);
|
||||
return Format(mDeviceRate, 1);
|
||||
}
|
||||
|
||||
bool AndroidInputDevice::active() const
|
||||
{
|
||||
return mActive;
|
||||
return mActive;
|
||||
}
|
||||
|
||||
bool AndroidInputDevice::fakeMode()
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void AndroidInputDevice::setFakeMode(bool fakemode)
|
||||
{}
|
||||
void AndroidInputDevice::setFakeMode(bool fakemode) {}
|
||||
|
||||
int AndroidInputDevice::readBuffer(void* buffer)
|
||||
int AndroidInputDevice::readBuffer(void* buffer)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
while (mSdkRateCache.filled() < AUDIO_MIC_BUFFER_SIZE)
|
||||
{
|
||||
mDataCondVar.wait(l);
|
||||
}
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
while (mSdkRateCache.filled() < AUDIO_MIC_BUFFER_SIZE)
|
||||
{
|
||||
mDataCondVar.wait(l);
|
||||
}
|
||||
|
||||
return mSdkRateCache.read(buffer, AUDIO_MIC_BUFFER_SIZE);
|
||||
return mSdkRateCache.read(buffer, AUDIO_MIC_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
#define CHECK_SL_INTERFACE(INTF, ERR) {if (!INTF) throw Exception(ERR_OPENSLES, ERR); if (!(*INTF)) throw Exception(ERR_OPENSLES, ERR);}
|
||||
#define CHECK_SL_INTERFACE(INTF, ERR) \
|
||||
{ \
|
||||
if (!INTF) \
|
||||
throw Exception(ERR_OPENSLES, ERR); \
|
||||
if (!(*INTF)) \
|
||||
throw Exception(ERR_OPENSLES, ERR); \
|
||||
}
|
||||
|
||||
void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
||||
{
|
||||
SLresult resultCode = 0;
|
||||
SLuint32 nrOfChannels = 1;
|
||||
SLresult resultCode = 0;
|
||||
SLuint32 nrOfChannels = 1;
|
||||
|
||||
// Prepare audio source
|
||||
SLDataLocator_IODevice devDescription = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
||||
SLDataSource audioSource = { &devDescription, NULL };
|
||||
// Prepare audio source
|
||||
SLDataLocator_IODevice devDescription = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
|
||||
SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
||||
SLDataSource audioSource = {&devDescription, NULL};
|
||||
|
||||
// Source flags
|
||||
SLuint32 speakersFlags = nrOfChannels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
||||
// Source flags
|
||||
SLuint32 speakersFlags =
|
||||
nrOfChannels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
||||
|
||||
// Buffer queue
|
||||
SLDataLocator_AndroidSimpleBufferQueue queueDescription = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
|
||||
// Buffer queue
|
||||
SLDataLocator_AndroidSimpleBufferQueue queueDescription = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||
|
||||
// Audio format
|
||||
SLDataFormat_PCM formatDescription = { SL_DATAFORMAT_PCM, nrOfChannels, (SLuint32)rateCode, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, (SLuint32)speakersFlags, SL_BYTEORDER_LITTLEENDIAN };
|
||||
// Audio format
|
||||
SLDataFormat_PCM formatDescription = {SL_DATAFORMAT_PCM, nrOfChannels,
|
||||
(SLuint32)rateCode, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, (SLuint32)speakersFlags,
|
||||
SL_BYTEORDER_LITTLEENDIAN};
|
||||
|
||||
SLDataSink audioSink = { &queueDescription, &formatDescription };
|
||||
SLDataSink audioSink = {&queueDescription, &formatDescription};
|
||||
|
||||
// Create recorder
|
||||
// Do not forget about RECORD_AUDIO permission
|
||||
const SLInterfaceID interfacesList[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
|
||||
const SLboolean interfacesRequirements[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
|
||||
// Create recorder
|
||||
// Do not forget about RECORD_AUDIO permission
|
||||
const SLInterfaceID interfacesList[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
|
||||
const SLboolean interfacesRequirements[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
|
||||
// Get access to OpenSL engine
|
||||
SLEngineItf engine_interface = OpenSLEngine::instance().getNativeEngine();
|
||||
CHECK_SL_INTERFACE(engine_interface, -1);
|
||||
// Get access to OpenSL engine
|
||||
SLEngineItf engine_interface = OpenSLEngine::instance().getNativeEngine();
|
||||
CHECK_SL_INTERFACE(engine_interface, -1);
|
||||
|
||||
resultCode = (*engine_interface)->CreateAudioRecorder(
|
||||
OpenSLEngine::instance().getNativeEngine(),
|
||||
&mRecorderObject, &audioSource, &audioSink, 2, interfacesList, interfacesRequirements);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
CHECK_SL_INTERFACE(mRecorderObject, -2);
|
||||
resultCode = (*engine_interface)
|
||||
->CreateAudioRecorder(OpenSLEngine::instance().getNativeEngine(), &mRecorderObject, &audioSource,
|
||||
&audioSink, 2, interfacesList, interfacesRequirements);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
CHECK_SL_INTERFACE(mRecorderObject, -2);
|
||||
|
||||
// Obtain stream type
|
||||
resultCode = (*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_ANDROIDCONFIGURATION, &mAndroidCfg);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Obtain stream type
|
||||
resultCode = (*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_ANDROIDCONFIGURATION, &mAndroidCfg);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Now audio recorder goes to real world
|
||||
resultCode = (*mRecorderObject)->Realize(mRecorderObject, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Now audio recorder goes to real world
|
||||
resultCode = (*mRecorderObject)->Realize(mRecorderObject, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Get recorder interface
|
||||
resultCode = (*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_RECORD, &mRecorderInterface);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
CHECK_SL_INTERFACE(mRecorderInterface, -3);
|
||||
// Get recorder interface
|
||||
resultCode = (*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_RECORD, &mRecorderInterface);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
CHECK_SL_INTERFACE(mRecorderInterface, -3);
|
||||
|
||||
// Now buffer queue interface...
|
||||
resultCode = (*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mRecorderBufferInterface);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
CHECK_SL_INTERFACE(mRecorderBufferInterface, -4);
|
||||
// Now buffer queue interface...
|
||||
resultCode =
|
||||
(*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mRecorderBufferInterface);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
CHECK_SL_INTERFACE(mRecorderBufferInterface, -4);
|
||||
|
||||
// Resampler is needed to provide SDK's rate
|
||||
mResampler = std::make_shared<Resampler>();
|
||||
mResampler->start(nrOfChannels, rate, AUDIO_SAMPLERATE);
|
||||
// Resampler is needed to provide SDK's rate
|
||||
mResampler = std::make_shared<Resampler>();
|
||||
mResampler->start(nrOfChannels, rate, AUDIO_SAMPLERATE);
|
||||
|
||||
// Allocate recorder buffer size
|
||||
mBufferSize = (AUDIO_MIC_BUFFER_LENGTH / 10) * (rate / 100) * 2;
|
||||
mRecorderBuffer.setCapacity(mBufferSize * AUDIO_MIC_BUFFER_COUNT);
|
||||
mRecorderBufferIndex = 0;
|
||||
// Allocate recorder buffer size
|
||||
mBufferSize = (AUDIO_MIC_BUFFER_LENGTH / 10) * (rate / 100) * 2;
|
||||
mRecorderBuffer.setCapacity(mBufferSize * AUDIO_MIC_BUFFER_COUNT);
|
||||
mRecorderBufferIndex = 0;
|
||||
|
||||
// Setup data consuming callback
|
||||
resultCode = (*mRecorderBufferInterface)->RegisterCallback(mRecorderBufferInterface, DeviceCallback, (void*)this);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Setup data consuming callback
|
||||
resultCode = (*mRecorderBufferInterface)->RegisterCallback(mRecorderBufferInterface, DeviceCallback, (void*)this);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Setup buffers
|
||||
for (int i=0; i<AUDIO_MIC_BUFFER_COUNT; i++)
|
||||
(*mRecorderBufferInterface)->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + i * mBufferSize, mBufferSize);
|
||||
// Setup buffers
|
||||
for (int i = 0; i < AUDIO_MIC_BUFFER_COUNT; i++)
|
||||
(*mRecorderBufferInterface)
|
||||
->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + i * mBufferSize, mBufferSize);
|
||||
|
||||
// Start finally
|
||||
resultCode = (*mRecorderInterface)->SetRecordState(mRecorderInterface, SL_RECORDSTATE_RECORDING);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Start finally
|
||||
resultCode = (*mRecorderInterface)->SetRecordState(mRecorderInterface, SL_RECORDSTATE_RECORDING);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
}
|
||||
|
||||
void AndroidInputDevice::internalClose()
|
||||
{
|
||||
if (!mRecorderObject)
|
||||
return;
|
||||
if (!mRecorderObject)
|
||||
return;
|
||||
|
||||
if (*mRecorderObject)
|
||||
{
|
||||
if (active())
|
||||
if (*mRecorderObject)
|
||||
{
|
||||
// Stop recording
|
||||
(*mRecorderInterface)->SetRecordState(mRecorderInterface, SL_RECORDSTATE_STOPPED);
|
||||
if (active())
|
||||
{
|
||||
// Stop recording
|
||||
(*mRecorderInterface)->SetRecordState(mRecorderInterface, SL_RECORDSTATE_STOPPED);
|
||||
|
||||
// Wait until recording will not stop really
|
||||
SLuint32 state = SL_RECORDSTATE_STOPPED;
|
||||
do
|
||||
{
|
||||
(*mRecorderInterface)->GetRecordState(mRecorderInterface, &state);
|
||||
SyncHelper::delay(1);
|
||||
}
|
||||
while (state == SL_RECORDSTATE_RECORDING);
|
||||
// Wait until recording will not stop really
|
||||
SLuint32 state = SL_RECORDSTATE_STOPPED;
|
||||
do
|
||||
{
|
||||
(*mRecorderInterface)->GetRecordState(mRecorderInterface, &state);
|
||||
SyncHelper::delay(1);
|
||||
} while (state == SL_RECORDSTATE_RECORDING);
|
||||
}
|
||||
(*mRecorderObject)->Destroy(mRecorderObject);
|
||||
}
|
||||
(*mRecorderObject)->Destroy(mRecorderObject);
|
||||
}
|
||||
|
||||
mRecorderObject = nullptr;
|
||||
mRecorderInterface = nullptr;
|
||||
mRecorderBufferInterface = nullptr;
|
||||
mAndroidCfg = nullptr;
|
||||
mRecorderObject = nullptr;
|
||||
mRecorderInterface = nullptr;
|
||||
mRecorderBufferInterface = nullptr;
|
||||
mAndroidCfg = nullptr;
|
||||
}
|
||||
|
||||
void AndroidInputDevice::handleCallback(SLAndroidSimpleBufferQueueItf bq)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
|
||||
// Send data to AudioPair
|
||||
if (mConnection)
|
||||
mConnection->onMicData(getFormat(), mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||
/*
|
||||
// Send audio to cache with native sample rate
|
||||
mDeviceRateCache.add(mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||
|
||||
// Check if there is enough data (10 ms) to send
|
||||
int tenMsSize = (int)Format(mDeviceRate, 1).sizeFromTime(10);
|
||||
while (mDeviceRateCache.filled() >= tenMsSize)
|
||||
{
|
||||
char* resampled = (char*)alloca(Format().sizeFromTime(10));
|
||||
int processed = 0;
|
||||
int outlen = mResampler->processBuffer(mDeviceRateCache.data(), tenMsSize, processed, resampled, Format().sizeFromTime(10));
|
||||
if (outlen > 0)
|
||||
mSdkRateCache.add(resampled, (int)Format().sizeFromTime(10));
|
||||
mDeviceRateCache.erase(tenMsSize);
|
||||
}
|
||||
|
||||
// Tell about data
|
||||
while (mSdkRateCache.filled() >= AUDIO_MIC_BUFFER_SIZE)
|
||||
{
|
||||
// Send data to AudioPair
|
||||
if (mConnection)
|
||||
mConnection->onMicData(Format(), mSdkRateCache.data(), AUDIO_MIC_BUFFER_SIZE);
|
||||
mSdkRateCache.erase(AUDIO_MIC_BUFFER_SIZE);
|
||||
}
|
||||
*/
|
||||
// Re-enqueue used buffer
|
||||
(*mRecorderBufferInterface)->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||
mRecorderBufferIndex++;
|
||||
mRecorderBufferIndex %= AUDIO_MIC_BUFFER_COUNT;
|
||||
mConnection->onMicData(getFormat(), mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||
/*
|
||||
// Send audio to cache with native sample rate
|
||||
mDeviceRateCache.add(mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||
|
||||
// Check if there is enough data (10 ms) to send
|
||||
int tenMsSize = (int)Format(mDeviceRate, 1).sizeFromTime(10);
|
||||
while (mDeviceRateCache.filled() >= tenMsSize)
|
||||
{
|
||||
char* resampled = (char*)alloca(Format().sizeFromTime(10));
|
||||
int processed = 0;
|
||||
int outlen = mResampler->processBuffer(mDeviceRateCache.data(), tenMsSize, processed, resampled,
|
||||
Format().sizeFromTime(10)); if (outlen > 0) mSdkRateCache.add(resampled, (int)Format().sizeFromTime(10));
|
||||
mDeviceRateCache.erase(tenMsSize);
|
||||
}
|
||||
|
||||
// Tell about data
|
||||
while (mSdkRateCache.filled() >= AUDIO_MIC_BUFFER_SIZE)
|
||||
{
|
||||
if (mConnection)
|
||||
mConnection->onMicData(Format(), mSdkRateCache.data(), AUDIO_MIC_BUFFER_SIZE);
|
||||
mSdkRateCache.erase(AUDIO_MIC_BUFFER_SIZE);
|
||||
}
|
||||
*/
|
||||
// Re-enqueue used buffer
|
||||
(*mRecorderBufferInterface)
|
||||
->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||
mRecorderBufferIndex++;
|
||||
mRecorderBufferIndex %= AUDIO_MIC_BUFFER_COUNT;
|
||||
}
|
||||
|
||||
void AndroidInputDevice::DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
void AndroidInputDevice::DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context)
|
||||
reinterpret_cast<AndroidInputDevice*>(context)->handleCallback(bq);
|
||||
}
|
||||
catch(...)
|
||||
{}
|
||||
try
|
||||
{
|
||||
if (context)
|
||||
reinterpret_cast<AndroidInputDevice*>(context)->handleCallback(bq);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// ------------ AndroidOutputDevice -----------------
|
||||
AndroidOutputDevice::AndroidOutputDevice(int devId)
|
||||
{
|
||||
ICELogDebug(<< "Creating AndroidOutputDevice. This is: " << strx::toHex(this));
|
||||
ICELogDebug(<< "Creating AndroidOutputDevice. This is: " << strx::toHex(this));
|
||||
}
|
||||
|
||||
AndroidOutputDevice::~AndroidOutputDevice()
|
||||
{
|
||||
ICELogDebug(<< "Deleting AndroidOutputDevice.");
|
||||
close();
|
||||
ICELogDebug(<< "Deleting AndroidOutputDevice.");
|
||||
close();
|
||||
}
|
||||
|
||||
bool AndroidOutputDevice::open()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
bool opened = false;
|
||||
for (int rateIndex = 0; rateIndex < 12 && !opened; rateIndex++)
|
||||
{
|
||||
try
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
bool opened = false;
|
||||
for (int rateIndex = 0; rateIndex < 12 && !opened; rateIndex++)
|
||||
{
|
||||
internalOpen(RateToProbe[rateIndex][0], RateToProbe[rateIndex][1], true);
|
||||
opened = true;
|
||||
mDeviceRate = RateToProbe[rateIndex][1];
|
||||
ICELogCritical(<< "Output opened with rate " << mDeviceRate << " and index " << rateIndex);
|
||||
try
|
||||
{
|
||||
internalOpen(RateToProbe[rateIndex][0], RateToProbe[rateIndex][1], true);
|
||||
opened = true;
|
||||
mDeviceRate = RateToProbe[rateIndex][1];
|
||||
ICELogCritical(<< "Output opened with rate " << mDeviceRate << " and index " << rateIndex);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
opened = false;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
opened = false;
|
||||
}
|
||||
}
|
||||
if (opened)
|
||||
ICELogInfo(<< "Speaker opened on rate " << mDeviceRate);
|
||||
if (opened)
|
||||
ICELogInfo(<< "Speaker opened on rate " << mDeviceRate);
|
||||
|
||||
return opened;
|
||||
return opened;
|
||||
}
|
||||
|
||||
void AndroidOutputDevice::close()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
internalClose();
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
internalClose();
|
||||
}
|
||||
|
||||
Format AndroidOutputDevice::getFormat()
|
||||
{
|
||||
return Format(mDeviceRate, 1);
|
||||
return Format(mDeviceRate, 1);
|
||||
}
|
||||
|
||||
bool AndroidOutputDevice::fakeMode()
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void AndroidOutputDevice::setFakeMode(bool fakemode)
|
||||
{
|
||||
}
|
||||
void AndroidOutputDevice::setFakeMode(bool fakemode) {}
|
||||
|
||||
void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
||||
{
|
||||
mInShutdown = false;
|
||||
mInShutdown = false;
|
||||
|
||||
SLresult resultCode;
|
||||
SLuint32 channels = 1;
|
||||
SLresult resultCode;
|
||||
SLuint32 channels = 1;
|
||||
|
||||
// Configure audio source
|
||||
SLDataLocator_AndroidSimpleBufferQueue queue_desc = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
|
||||
// Configure audio source
|
||||
SLDataLocator_AndroidSimpleBufferQueue queue_desc = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||
|
||||
const SLInterfaceID interfacesList[] = { SL_IID_VOLUME };
|
||||
const SLboolean interfaceRequirements[] = { SL_BOOLEAN_FALSE };
|
||||
resultCode = (*OpenSLEngine::instance().getNativeEngine())->CreateOutputMix(
|
||||
OpenSLEngine::instance().getNativeEngine(), &mMixer, 1, interfacesList,
|
||||
interfaceRequirements);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
const SLInterfaceID interfacesList[] = {SL_IID_VOLUME};
|
||||
const SLboolean interfaceRequirements[] = {SL_BOOLEAN_FALSE};
|
||||
resultCode = (*OpenSLEngine::instance().getNativeEngine())
|
||||
->CreateOutputMix(OpenSLEngine::instance().getNativeEngine(), &mMixer, 1, interfacesList,
|
||||
interfaceRequirements);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Bring mixer online
|
||||
resultCode = (*mMixer)->Realize(mMixer, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Bring mixer online
|
||||
resultCode = (*mMixer)->Realize(mMixer, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Prepare mixer configuration
|
||||
SLuint32 speakers =
|
||||
channels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
||||
// Prepare mixer configuration
|
||||
SLuint32 speakers = channels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
||||
|
||||
// Describe audio format
|
||||
SLDataFormat_PCM pcm_format = {SL_DATAFORMAT_PCM, channels, (SLuint32) rateId,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
speakers, SL_BYTEORDER_LITTLEENDIAN};
|
||||
// Describe audio format
|
||||
SLDataFormat_PCM pcm_format = {
|
||||
SL_DATAFORMAT_PCM, channels, (SLuint32)rateId, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, speakers, SL_BYTEORDER_LITTLEENDIAN};
|
||||
|
||||
// Describe audio source - buffers + audio format
|
||||
SLDataSource audio_source = { &queue_desc, &pcm_format };
|
||||
// Describe audio source - buffers + audio format
|
||||
SLDataSource audio_source = {&queue_desc, &pcm_format};
|
||||
|
||||
// Describe audio sink
|
||||
SLDataLocator_OutputMix mixer_desc = { SL_DATALOCATOR_OUTPUTMIX, mMixer };
|
||||
SLDataSink audio_sink = { &mixer_desc, NULL };
|
||||
// Describe audio sink
|
||||
SLDataLocator_OutputMix mixer_desc = {SL_DATALOCATOR_OUTPUTMIX, mMixer};
|
||||
SLDataSink audio_sink = {&mixer_desc, NULL};
|
||||
|
||||
// Create player instance
|
||||
const SLInterfaceID playerInterfaces[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
SL_IID_VOLUME,
|
||||
SL_IID_ANDROIDCONFIGURATION };
|
||||
const SLboolean playerInterfacesReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
|
||||
// Create player instance
|
||||
const SLInterfaceID playerInterfaces[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME,
|
||||
SL_IID_ANDROIDCONFIGURATION};
|
||||
const SLboolean playerInterfacesReqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
|
||||
resultCode = (*OpenSLEngine::instance().getNativeEngine())->CreateAudioPlayer(
|
||||
OpenSLEngine::instance().getNativeEngine(), &mPlayer,
|
||||
&audio_source, &audio_sink, 3, playerInterfaces, playerInterfacesReqs);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
resultCode = (*OpenSLEngine::instance().getNativeEngine())
|
||||
->CreateAudioPlayer(OpenSLEngine::instance().getNativeEngine(), &mPlayer, &audio_source,
|
||||
&audio_sink, 3, playerInterfaces, playerInterfacesReqs);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Get android config interface
|
||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_ANDROIDCONFIGURATION, &mAndroidConfig);
|
||||
// Get android config interface
|
||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_ANDROIDCONFIGURATION, &mAndroidConfig);
|
||||
|
||||
if (resultCode == SL_RESULT_SUCCESS)
|
||||
{
|
||||
SLint32 streamType = voice ? SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA;
|
||||
resultCode = (*mAndroidConfig)->SetConfiguration(mAndroidConfig, SL_ANDROID_KEY_STREAM_TYPE,
|
||||
&streamType, sizeof(SLint32));
|
||||
if (resultCode != SL_RESULT_SUCCESS)
|
||||
ICELogCritical(<< "Failed to set audio destination with error " << (unsigned)resultCode);
|
||||
}
|
||||
else
|
||||
ICELogCritical(<< "Failed to obtain android cfg audio interface with error " << (unsigned)resultCode);
|
||||
if (resultCode == SL_RESULT_SUCCESS)
|
||||
{
|
||||
SLint32 streamType = voice ? SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA;
|
||||
resultCode = (*mAndroidConfig)
|
||||
->SetConfiguration(mAndroidConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
|
||||
if (resultCode != SL_RESULT_SUCCESS)
|
||||
ICELogCritical(<< "Failed to set audio destination with error " << (unsigned)resultCode);
|
||||
}
|
||||
else
|
||||
ICELogCritical(<< "Failed to obtain android cfg audio interface with error " << (unsigned)resultCode);
|
||||
|
||||
// Bring player online
|
||||
resultCode = (*mPlayer)->Realize(mPlayer, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Bring player online
|
||||
resultCode = (*mPlayer)->Realize(mPlayer, SL_BOOLEAN_FALSE);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Obtain player control
|
||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_PLAY, &mPlayerControl);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Obtain player control
|
||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_PLAY, &mPlayerControl);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Get the buffer queue interface
|
||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&mBufferQueue);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Get the buffer queue interface
|
||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mBufferQueue);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Setup callback
|
||||
resultCode = (*mBufferQueue)->RegisterCallback(mBufferQueue, DeviceCallback, this);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Setup callback
|
||||
resultCode = (*mBufferQueue)->RegisterCallback(mBufferQueue, DeviceCallback, this);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
// Enqueue buffers
|
||||
mBufferSize = (int)Format(rate, channels).sizeFromTime(AUDIO_SPK_BUFFER_LENGTH);
|
||||
mPlayBuffer.setCapacity(AUDIO_SPK_BUFFER_COUNT * mBufferSize);
|
||||
// Enqueue buffers
|
||||
mBufferSize = (int)Format(rate, channels).sizeFromTime(AUDIO_SPK_BUFFER_LENGTH);
|
||||
mPlayBuffer.setCapacity(AUDIO_SPK_BUFFER_COUNT * mBufferSize);
|
||||
|
||||
mBufferIndex = 0;
|
||||
for (int i = 0; i < AUDIO_SPK_BUFFER_COUNT; i++)
|
||||
(*mBufferQueue)->Enqueue(mBufferQueue, mPlayBuffer.data() + i * mBufferSize,
|
||||
(SLuint32)mBufferSize);
|
||||
mBufferIndex = 0;
|
||||
for (int i = 0; i < AUDIO_SPK_BUFFER_COUNT; i++)
|
||||
(*mBufferQueue)->Enqueue(mBufferQueue, mPlayBuffer.data() + i * mBufferSize, (SLuint32)mBufferSize);
|
||||
|
||||
// Set the player's state to playing
|
||||
resultCode = (*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_PLAYING);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
// Set the player's state to playing
|
||||
resultCode = (*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_PLAYING);
|
||||
CHECK_OPENSLES_ERROR;
|
||||
|
||||
ICELogInfo(<< "Android audio output is opened and playing.");
|
||||
ICELogInfo(<< "Android audio output is opened and playing.");
|
||||
}
|
||||
|
||||
void AndroidOutputDevice::internalClose()
|
||||
{
|
||||
if (mPlayer)
|
||||
{
|
||||
if (*mPlayer)
|
||||
if (mPlayer)
|
||||
{
|
||||
mInShutdown = true;
|
||||
ICELogInfo(<< "Stop player");
|
||||
if (mPlayerControl) {
|
||||
if (*mPlayerControl) {
|
||||
SLuint32 state = SL_PLAYSTATE_PLAYING;
|
||||
(*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_STOPPED);
|
||||
if (*mPlayer)
|
||||
{
|
||||
mInShutdown = true;
|
||||
ICELogInfo(<< "Stop player");
|
||||
if (mPlayerControl)
|
||||
{
|
||||
if (*mPlayerControl)
|
||||
{
|
||||
SLuint32 state = SL_PLAYSTATE_PLAYING;
|
||||
(*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_STOPPED);
|
||||
|
||||
while (state != SL_PLAYSTATE_STOPPED) {
|
||||
(*mPlayerControl)->GetPlayState(mPlayerControl, &state);
|
||||
SyncHelper::delay(1);
|
||||
}
|
||||
while (state != SL_PLAYSTATE_STOPPED)
|
||||
{
|
||||
(*mPlayerControl)->GetPlayState(mPlayerControl, &state);
|
||||
SyncHelper::delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear buffer queue
|
||||
ICELogInfo(<< "Clear player buffer queue");
|
||||
(*mBufferQueue)->Clear(mBufferQueue);
|
||||
|
||||
ICELogInfo(<< "Destroy player object");
|
||||
// Destroy player object
|
||||
(*mPlayer)->Destroy(mPlayer);
|
||||
|
||||
ICELogInfo(<< "Android audio output closed.");
|
||||
|
||||
mPlayer = nullptr;
|
||||
mPlayerControl = nullptr;
|
||||
mBufferQueue = nullptr;
|
||||
mEffect = nullptr;
|
||||
mAndroidConfig = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear buffer queue
|
||||
ICELogInfo(<< "Clear player buffer queue");
|
||||
(*mBufferQueue)->Clear(mBufferQueue);
|
||||
|
||||
ICELogInfo(<< "Destroy player object");
|
||||
// Destroy player object
|
||||
(*mPlayer)->Destroy(mPlayer);
|
||||
|
||||
ICELogInfo(<< "Android audio output closed.");
|
||||
|
||||
mPlayer = nullptr;
|
||||
mPlayerControl = nullptr;
|
||||
mBufferQueue = nullptr;
|
||||
mEffect = nullptr;
|
||||
mAndroidConfig = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMixer)
|
||||
{
|
||||
if (*mMixer)
|
||||
(*mMixer)->Destroy(mMixer);
|
||||
mMixer = nullptr;
|
||||
}
|
||||
if (mMixer)
|
||||
{
|
||||
if (*mMixer)
|
||||
(*mMixer)->Destroy(mMixer);
|
||||
mMixer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidOutputDevice::handleCallback(SLAndroidSimpleBufferQueueItf bq)
|
||||
{
|
||||
if (mInShutdown)
|
||||
return;
|
||||
/*{
|
||||
char silence[mBufferSize]; memset(silence, 0, mBufferSize);
|
||||
(*mBufferQueue)->Enqueue(mBufferQueue, silence, mBufferSize);
|
||||
return;
|
||||
}*/
|
||||
if (mInShutdown)
|
||||
return;
|
||||
/*{
|
||||
char silence[mBufferSize]; memset(silence, 0, mBufferSize);
|
||||
(*mBufferQueue)->Enqueue(mBufferQueue, silence, mBufferSize);
|
||||
return;
|
||||
}*/
|
||||
|
||||
// Ask producer about data
|
||||
char* buffer = mPlayBuffer.mutableData() + mBufferIndex * mBufferSize;
|
||||
if (mConnection)
|
||||
{
|
||||
Format f = getFormat();
|
||||
if (f.mRate != 0)
|
||||
mConnection->onSpkData(f, buffer, mBufferSize);
|
||||
}
|
||||
(*mBufferQueue)->Enqueue(mBufferQueue, buffer, (SLuint32)mBufferSize);
|
||||
// Ask producer about data
|
||||
char* buffer = mPlayBuffer.mutableData() + mBufferIndex * mBufferSize;
|
||||
if (mConnection)
|
||||
{
|
||||
Format f = getFormat();
|
||||
if (f.mRate != 0)
|
||||
mConnection->onSpkData(f, buffer, mBufferSize);
|
||||
}
|
||||
(*mBufferQueue)->Enqueue(mBufferQueue, buffer, (SLuint32)mBufferSize);
|
||||
|
||||
mBufferIndex++;
|
||||
mBufferIndex %= AUDIO_SPK_BUFFER_COUNT;
|
||||
mBufferIndex++;
|
||||
mBufferIndex %= AUDIO_SPK_BUFFER_COUNT;
|
||||
}
|
||||
|
||||
void AndroidOutputDevice::DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
reinterpret_cast<AndroidOutputDevice*>(context)->handleCallback(bq);
|
||||
}
|
||||
catch(...)
|
||||
{}
|
||||
try
|
||||
{
|
||||
reinterpret_cast<AndroidOutputDevice*>(context)->handleCallback(bq);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TARGET_ANDROID
|
||||
|
||||
Reference in New Issue
Block a user