Browse Source

A bugfix and some fine-tuning for the android openSL audio device.

tags/2021-05-28
jules 13 years ago
parent
commit
dbe71f8c67
1 changed files with 32 additions and 22 deletions
  1. +32
    -22
      modules/juce_audio_devices/native/juce_android_OpenSL.cpp

+ 32
- 22
modules/juce_audio_devices/native/juce_android_OpenSL.cpp View File

@@ -31,8 +31,8 @@ bool isOpenSLAvailable()
return library.open ("libOpenSLES.so"); return library.open ("libOpenSLES.so");
} }
const unsigned short openSLRates[] = { 8000, 16000, 32000, 44100, 48000 };
const unsigned short openSLBufferSizes[] = { 256, 512, 768, 1024, 1280, 1600, 2048, 3072 };
const unsigned short openSLRates[] = { 8000, 16000, 32000, 44100, 48000 };
const unsigned short openSLBufferSizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
//============================================================================== //==============================================================================
class OpenSLAudioIODevice : public AudioIODevice, class OpenSLAudioIODevice : public AudioIODevice,
@@ -49,10 +49,15 @@ public:
// get a number for this is by asking the AudioTrack/AudioRecord classes.. // get a number for this is by asking the AudioTrack/AudioRecord classes..
AndroidAudioIODevice javaDevice (String::empty); AndroidAudioIODevice javaDevice (String::empty);
// this is a total guess about how to calculate this: assuming that internally the
// hardware probably uses 3 buffers, so the latency is about 2/3 of it.. YMMV
inputLatency = (javaDevice.minBufferSizeIn * 2) / 3;
outputLatency = (javaDevice.minBufferSizeOut * 2) / 3;
// this is a total guess about how to calculate the latency, but seems to vaguely agree
// with the devices I've tested.. YMMV
inputLatency = ((javaDevice.minBufferSizeIn * 2) / 3);
outputLatency = ((javaDevice.minBufferSizeOut * 2) / 3);
const int longestLatency = jmax (inputLatency, outputLatency);
const int totalLatency = inputLatency + outputLatency;
inputLatency = ((longestLatency * inputLatency) / totalLatency) & ~15;
outputLatency = ((longestLatency * outputLatency) / totalLatency) & ~15;
} }
~OpenSLAudioIODevice() ~OpenSLAudioIODevice()
@@ -85,7 +90,7 @@ public:
return (int) openSLRates [index]; return (int) openSLRates [index];
} }
int getDefaultBufferSize() { return 2048; }
int getDefaultBufferSize() { return 1024; }
int getNumBufferSizesAvailable() { return numElementsInArray (openSLBufferSizes); } int getNumBufferSizesAvailable() { return numElementsInArray (openSLBufferSizes); }
int getBufferSizeSamples (int index) int getBufferSizeSamples (int index)
@@ -124,18 +129,14 @@ public:
startThread (8); startThread (8);
if (recorder != nullptr) recorder->start();
if (player != nullptr) player->start();
deviceOpen = true; deviceOpen = true;
return lastError; return lastError;
} }
void close() void close()
{ {
stop(); stop();
stopThread (2000);
stopThread (6000);
deviceOpen = false; deviceOpen = false;
recorder = nullptr; recorder = nullptr;
player = nullptr; player = nullptr;
@@ -175,15 +176,18 @@ public:
void run() void run()
{ {
if (recorder != nullptr) recorder->start();
if (player != nullptr) player->start();
while (! threadShouldExit()) while (! threadShouldExit())
{ {
if (player != nullptr && ! threadShouldExit())
player->writeBuffer (outputBuffer, *this);
if (recorder != nullptr) if (recorder != nullptr)
recorder->readNextBlock (inputBuffer, *this); recorder->readNextBlock (inputBuffer, *this);
invokeCallback(); invokeCallback();
if (player != nullptr && ! threadShouldExit())
player->writeBuffer (outputBuffer, *this);
} }
} }
@@ -297,9 +301,8 @@ private:
//================================================================================================== //==================================================================================================
struct BufferList struct BufferList
{ {
BufferList (const int numChannels_, const int numSamples_ = 256, const int numBuffers_ = 16)
: numChannels (numChannels_), numSamples (numSamples_), numBuffers (numBuffers_),
bufferSpace (numChannels_ * numSamples_ * numBuffers_), nextBlock (0)
BufferList (const int numChannels_)
: numChannels (numChannels_), bufferSpace (numChannels_ * numSamples * numBuffers), nextBlock (0)
{ {
} }
@@ -307,7 +310,7 @@ private:
{ {
while (numBlocksOut.get() == numBuffers) while (numBlocksOut.get() == numBuffers)
{ {
Thread::sleep (1);
dataArrived.wait (1);
if (threadToCheck.threadShouldExit()) if (threadToCheck.threadShouldExit())
return nullptr; return nullptr;
@@ -324,17 +327,19 @@ private:
return bufferSpace + nextBlock * numChannels * numSamples; return bufferSpace + nextBlock * numChannels * numSamples;
} }
void bufferReturned() { --numBlocksOut; }
void bufferSent() { ++numBlocksOut; }
void bufferReturned() { --numBlocksOut; dataArrived.signal(); }
void bufferSent() { ++numBlocksOut; dataArrived.signal(); }
int getBufferSizeBytes() const { return numChannels * numSamples * sizeof (int16); } int getBufferSizeBytes() const { return numChannels * numSamples * sizeof (int16); }
const int numChannels, numSamples, numBuffers;
const int numChannels;
enum { numSamples = 256, numBuffers = 16 };
private: private:
HeapBlock<int16> bufferSpace; HeapBlock<int16> bufferSpace;
int nextBlock; int nextBlock;
Atomic<int> numBlocksOut; Atomic<int> numBlocksOut;
WaitableEvent dataArrived;
}; };
//================================================================================================== //==================================================================================================
@@ -482,6 +487,7 @@ private:
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_RECORD, &recorderRecord)); check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_RECORD, &recorderRecord));
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue)); check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue));
check ((*recorderBufferQueue)->RegisterCallback (recorderBufferQueue, staticCallback, this)); check ((*recorderBufferQueue)->RegisterCallback (recorderBufferQueue, staticCallback, this));
check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED));
for (int i = bufferList.numBuffers; --i >= 0;) for (int i = bufferList.numBuffers; --i >= 0;)
{ {
@@ -517,6 +523,7 @@ private:
{ {
jassert (buffer.getNumChannels() == bufferList.numChannels); jassert (buffer.getNumChannels() == bufferList.numChannels);
jassert (buffer.getNumSamples() < bufferList.numSamples * bufferList.numBuffers); jassert (buffer.getNumSamples() < bufferList.numSamples * bufferList.numBuffers);
jassert ((buffer.getNumSamples() % bufferList.numSamples) == 0);
int offset = 0; int offset = 0;
int numSamples = buffer.getNumSamples(); int numSamples = buffer.getNumSamples();
@@ -525,6 +532,9 @@ private:
{ {
int16* const srcBuffer = bufferList.waitForFreeBuffer (thread); int16* const srcBuffer = bufferList.waitForFreeBuffer (thread);
if (srcBuffer == nullptr)
break;
for (int i = 0; i < bufferList.numChannels; ++i) for (int i = 0; i < bufferList.numChannels; ++i)
{ {
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DstSampleType; typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DstSampleType;


Loading…
Cancel
Save