Browse Source

Updates to support the latest Oboe (c5c3cc17f7).

tags/2021-05-28
Lukasz Kozakiewicz jules 6 years ago
parent
commit
2718ce96f0
2 changed files with 152 additions and 135 deletions
  1. +1
    -1
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
  2. +151
    -134
      modules/juce_audio_devices/native/juce_android_Oboe.cpp

+ 1
- 1
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h View File

@@ -881,7 +881,7 @@ private:
{
props.add (new TextPropertyComponent (androidOboeRepositoryPath, "Oboe Repository Path", 2048, false),
"Path to the root of Oboe repository. Make sure to point Oboe repository to "
"commit with SHA 44c6b6ea9c8fa9b5b74cbd60f355068b57b50b37 before building.");
"commit with SHA c5c3cc17f78974bf005bf33a2de1a093ac55cc07 before building.");
props.add (new ChoicePropertyComponent (androidInternetNeeded, "Internet Access"),
"If enabled, this will set the android.permission.INTERNET flag in the manifest.");


+ 151
- 134
modules/juce_audio_devices/native/juce_android_Oboe.cpp View File

@@ -124,6 +124,12 @@ struct OboeAudioIODeviceBufferHelpers<float>
}
}
};

template <typename Type>
static String getOboeString (const Type& value)
{
return String (oboe::convertToText (value));
}
//==============================================================================
class OboeAudioIODevice : public AudioIODevice
@@ -438,8 +444,8 @@ private:
~OboeStream()
{
// AudioStreamCallback can only be deleted when stream has been closed
close();
delete stream;
}
bool openedOk() const noexcept
@@ -458,40 +464,47 @@ private:
int64 timeoutNanos = 1000 * oboe::kNanosPerMillisecond;
auto startResult = stream->requestStart();
JUCE_OBOE_LOG ("Requested Oboe stream start with result: " + String (oboe::convertToText (startResult)));
startResult = stream->waitForStateChange (expectedState, &nextState, timeoutNanos);
JUCE_OBOE_LOG ("Starting Oboe stream with result: " + String (oboe::convertToText (startResult));
+ "\nUses AAudio = " + (stream != nullptr ? String ((int) stream->usesAAudio()) : String ("?"))
+ "\nDirection = " + (stream != nullptr ? String (oboe::convertToText (stream->getDirection())) : String ("?"))
+ "\nSharingMode = " + (stream != nullptr ? String (oboe::convertToText (stream->getSharingMode())) : String ("?"))
+ "\nChannelCount = " + (stream != nullptr ? String (stream->getChannelCount()) : String ("?"))
+ "\nFormat = " + (stream != nullptr ? String (oboe::convertToText (stream->getFormat())) : String ("?"))
+ "\nSampleRate = " + (stream != nullptr ? String (stream->getSampleRate()) : String ("?"))
+ "\nBufferSizeInFrames = " + (stream != nullptr ? String (stream->getBufferSizeInFrames()) : String ("?"))
+ "\nBufferCapacityInFrames = " + (stream != nullptr ? String (stream->getBufferCapacityInFrames()) : String ("?"))
+ "\nFramesPerBurst = " + (stream != nullptr ? String (stream->getFramesPerBurst()) : String ("?"))
+ "\nFramesPerCallback = " + (stream != nullptr ? String (stream->getFramesPerCallback()) : String ("?"))
+ "\nBytesPerFrame = " + (stream != nullptr ? String (stream->getBytesPerFrame()) : String ("?"))
+ "\nBytesPerSample = " + (stream != nullptr ? String (stream->getBytesPerSample()) : String ("?"))
+ "\nPerformanceMode = " + String (oboe::convertToText (oboe::PerformanceMode::LowLatency))
+ "\ngetDeviceId = " + (stream != nullptr ? String (stream->getDeviceId()) : String ("?")));
JUCE_OBOE_LOG ("Requested Oboe stream start with result: " + getOboeString (startResult));
startResult = stream->waitForStateChange (expectedState, &nextState, timeoutNanos);
JUCE_OBOE_LOG ("Starting Oboe stream with result: " + getOboeString (startResult);
+ "\nUses AAudio = " + String ((int) stream->usesAAudio())
+ "\nDirection = " + getOboeString (stream->getDirection())
+ "\nSharingMode = " + getOboeString (stream->getSharingMode())
+ "\nChannelCount = " + String (stream->getChannelCount())
+ "\nFormat = " + getOboeString (stream->getFormat())
+ "\nSampleRate = " + String (stream->getSampleRate())
+ "\nBufferSizeInFrames = " + String (stream->getBufferSizeInFrames())
+ "\nBufferCapacityInFrames = " + String (stream->getBufferCapacityInFrames())
+ "\nFramesPerBurst = " + String (stream->getFramesPerBurst())
+ "\nFramesPerCallback = " + String (stream->getFramesPerCallback())
+ "\nBytesPerFrame = " + String (stream->getBytesPerFrame())
+ "\nBytesPerSample = " + String (stream->getBytesPerSample())
+ "\nPerformanceMode = " + getOboeString (oboe::PerformanceMode::LowLatency)
+ "\ngetDeviceId = " + String (stream->getDeviceId()));
}
}
oboe::AudioStream* getNativeStream()
oboe::AudioStream* getNativeStream() const
{
jassert (openedOk());
return stream;
}
int getXRunCount() const
{
if (auto xruns = stream->getXRunCount())
return xruns.value();
return 0;
if (stream != nullptr)
{
auto count = stream->getXRunCount();

if (count)
return count.value();

JUCE_OBOE_LOG ("Failed to get Xrun count: " + getOboeString (count.error()));
}
return 0;
}
private:
@@ -501,39 +514,38 @@ private:
int32 sampleRate, int32 bufferSize,
oboe::AudioStreamCallback* callback = nullptr)
{
oboe::DefaultStreamValues::FramesPerBurst = getDefaultFramesPerBurst();
oboe::AudioStreamBuilder builder;
if (deviceId != -1)
builder.setDeviceId (deviceId);
static int defaultFramesPerBurst = getDefaultFramesPerBurst();
// Note: Letting OS to choose the buffer capacity & frames per callback.
// Note: letting OS to choose the buffer capacity & frames per callback.
builder.setDirection (direction);
builder.setSharingMode (sharingMode);
builder.setChannelCount (channelCount);
builder.setFormat (format);
builder.setSampleRate (sampleRate);
builder.setFramesPerCallback ((int32) defaultFramesPerBurst);
builder.setPerformanceMode (oboe::PerformanceMode::LowLatency);
builder.setCallback (callback);
JUCE_OBOE_LOG (String ("Preparing Oboe stream with params:")
+ "\nAAudio supported = " + String (int (builder.isAAudioSupported()))
+ "\nAPI = " + String (oboe::convertToText (builder.getAudioApi()))
+ "\nAPI = " + getOboeString (builder.getAudioApi())
+ "\nDeviceId = " + String (deviceId)
+ "\nDirection = " + String (oboe::convertToText (direction))
+ "\nSharingMode = " + String (oboe::convertToText (sharingMode))
+ "\nDirection = " + getOboeString (direction)
+ "\nSharingMode = " + getOboeString (sharingMode)
+ "\nChannelCount = " + String (channelCount)
+ "\nFormat = " + String (oboe::convertToText (format))
+ "\nFormat = " + getOboeString (format)
+ "\nSampleRate = " + String (sampleRate)
+ "\nBufferSizeInFrames = " + String (bufferSize)
+ "\nFramesPerBurst = " + String (defaultFramesPerBurst)
+ "\nPerformanceMode = " + String (oboe::convertToText (oboe::PerformanceMode::LowLatency)));
+ "\nFramesPerBurst = " + String (oboe::DefaultStreamValues::FramesPerBurst)
+ "\nPerformanceMode = " + getOboeString (oboe::PerformanceMode::LowLatency));
openResult = builder.openStream (&stream);
JUCE_OBOE_LOG ("Building Oboe stream with result: " + String (oboe::convertToText (openResult))
+ "\nStream state = " + (stream != nullptr ? String (oboe::convertToText (stream->getState())) : String ("?")));
JUCE_OBOE_LOG ("Building Oboe stream with result: " + getOboeString (openResult)
+ "\nStream state = " + (stream != nullptr ? getOboeString (stream->getState()) : String ("?")));
if (stream != nullptr)
stream->setBufferSizeInFrames (bufferSize);
@@ -541,10 +553,10 @@ private:
JUCE_OBOE_LOG (String ("Stream details:")
+ "\nUses AAudio = " + (stream != nullptr ? String ((int) stream->usesAAudio()) : String ("?"))
+ "\nDeviceId = " + (stream != nullptr ? String (stream->getDeviceId()) : String ("?"))
+ "\nDirection = " + (stream != nullptr ? String (oboe::convertToText (stream->getDirection())) : String ("?"))
+ "\nSharingMode = " + (stream != nullptr ? String (oboe::convertToText (stream->getSharingMode())) : String ("?"))
+ "\nDirection = " + (stream != nullptr ? getOboeString (stream->getDirection()) : String ("?"))
+ "\nSharingMode = " + (stream != nullptr ? getOboeString (stream->getSharingMode()) : String ("?"))
+ "\nChannelCount = " + (stream != nullptr ? String (stream->getChannelCount()) : String ("?"))
+ "\nFormat = " + (stream != nullptr ? String (oboe::convertToText (stream->getFormat())) : String ("?"))
+ "\nFormat = " + (stream != nullptr ? getOboeString (stream->getFormat()) : String ("?"))
+ "\nSampleRate = " + (stream != nullptr ? String (stream->getSampleRate()) : String ("?"))
+ "\nBufferSizeInFrames = " + (stream != nullptr ? String (stream->getBufferSizeInFrames()) : String ("?"))
+ "\nBufferCapacityInFrames = " + (stream != nullptr ? String (stream->getBufferCapacityInFrames()) : String ("?"))
@@ -552,7 +564,7 @@ private:
+ "\nFramesPerCallback = " + (stream != nullptr ? String (stream->getFramesPerCallback()) : String ("?"))
+ "\nBytesPerFrame = " + (stream != nullptr ? String (stream->getBytesPerFrame()) : String ("?"))
+ "\nBytesPerSample = " + (stream != nullptr ? String (stream->getBytesPerSample()) : String ("?"))
+ "\nPerformanceMode = " + String (oboe::convertToText (oboe::PerformanceMode::LowLatency)));
+ "\nPerformanceMode = " + getOboeString (oboe::PerformanceMode::LowLatency));
}
void close()
@@ -560,27 +572,10 @@ private:
if (stream != nullptr)
{
oboe::Result result = stream->close();
JUCE_OBOE_LOG ("Requested Oboe stream close with result: " + String (oboe::convertToText (result)));
JUCE_OBOE_LOG ("Requested Oboe stream close with result: " + getOboeString (result));
}
}
int getDefaultFramesPerBurst() const
{
// NB: this function only works for inbuilt speakers and headphones
auto* env = getEnv();
auto audioManager = LocalRef<jobject> (env->CallObjectMethod (android.activity,
JuceAppActivity.getSystemService,
javaString ("audio").get()));
auto propertyJavaString = javaString ("android.media.property.OUTPUT_FRAMES_PER_BUFFER");
auto framesPerBurstString = LocalRef<jstring> ((jstring) android.activity.callObjectMethod (JuceAppActivity.audioManagerGetProperty,
propertyJavaString.get()));
return framesPerBurstString != 0 ? env->CallStaticIntMethod (JavaInteger, JavaInteger.parseInt, framesPerBurstString.get(), 10) : 192;
}
oboe::AudioStream* stream = nullptr;
oboe::Result openResult;
};
@@ -672,9 +667,7 @@ private:
void checkStreamSetup (OboeStream* stream, int deviceId, int numChannels, int sampleRate,
int bufferSize, oboe::AudioFormat format)
{
auto* nativeStream = stream != nullptr ? stream->getNativeStream() : nullptr;
if (nativeStream != nullptr)
if (auto* nativeStream = stream != nullptr ? stream->getNativeStream() : nullptr)
{
ignoreUnused (deviceId, numChannels, sampleRate, bufferSize);
ignoreUnused (streamFormat, bitDepth);
@@ -739,7 +732,8 @@ private:
outputStream->start();
checkIsOutputLatencyDetectionSupported();
isInputLatencyDetectionSupported = isLatencyDetectionSupported (inputStream.get());
isOutputLatencyDetectionSupported = isLatencyDetectionSupported (outputStream.get());
}
void stop() override
@@ -754,19 +748,16 @@ private:
}
int getOutputLatencyInSamples() override { return outputLatency; }
int getInputLatencyInSamples() override { return -1; }
int getInputLatencyInSamples() override { return inputLatency; }
private:
void checkIsOutputLatencyDetectionSupported()
bool isLatencyDetectionSupported (OboeStream* stream)
{
if (! openedOk())
{
isOutputLatencyDetectionSupported = false;
return;
}
if (stream == nullptr || ! openedOk())
return false;
auto result = outputStream->getNativeStream()->getTimestamp (CLOCK_MONOTONIC, 0, 0);
isOutputLatencyDetectionSupported = result != oboe::Result::ErrorUnimplemented;
auto result = stream->getNativeStream()->getTimestamp (CLOCK_MONOTONIC, 0, 0);
return result != oboe::Result::ErrorUnimplemented;
}
oboe::DataCallbackResult onAudioReady (oboe::AudioStream* stream, void* audioData, int32_t numFrames) override
@@ -792,7 +783,7 @@ private:
if (nativeInputStream->getFormat() != oboe::AudioFormat::I16 && nativeInputStream->getFormat() != oboe::AudioFormat::Float)
{
JUCE_OBOE_LOG ("Unsupported input stream audio format: " + String (oboe::convertToText (nativeInputStream->getFormat())));
JUCE_OBOE_LOG ("Unsupported input stream audio format: " + getOboeString (nativeInputStream->getFormat()));
jassertfalse;
return oboe::DataCallbackResult::Continue;
}
@@ -809,9 +800,11 @@ private:
}
else
{
// Failed to read from input stream.
jassertfalse;
JUCE_OBOE_LOG ("Failed to read from input stream: " + getOboeString (result.error()));
}
if (isInputLatencyDetectionSupported)
inputLatency = getLatencyFor (*inputStream);
}
//-----------------
@@ -834,7 +827,7 @@ private:
OboeAudioIODeviceBufferHelpers<SampleType>::convertToOboe (outputStreamSampleBuffer, static_cast<SampleType*> (audioData), numFrames);
if (isOutputLatencyDetectionSupported)
calculateOutputLatency();
outputLatency = getLatencyFor (*outputStream);
audioCallbackGuard.set (0);
}
@@ -847,10 +840,10 @@ private:
ignoreUnused (stream);
JUCE_OBOE_LOG ("\nUses AAudio = " + (stream != nullptr ? String ((int) stream->usesAAudio()) : String ("?"))
+ "\nDirection = " + (stream != nullptr ? String (oboe::convertToText (stream->getDirection())) : String ("?"))
+ "\nSharingMode = " + (stream != nullptr ? String (oboe::convertToText (stream->getSharingMode())) : String ("?"))
+ "\nDirection = " + (stream != nullptr ? getOboeString (stream->getDirection()) : String ("?"))
+ "\nSharingMode = " + (stream != nullptr ? getOboeString (stream->getSharingMode()) : String ("?"))
+ "\nChannelCount = " + (stream != nullptr ? String (stream->getChannelCount()) : String ("?"))
+ "\nFormat = " + (stream != nullptr ? String (oboe::convertToText (stream->getFormat())) : String ("?"))
+ "\nFormat = " + (stream != nullptr ? getOboeString (stream->getFormat()) : String ("?"))
+ "\nSampleRate = " + (stream != nullptr ? String (stream->getSampleRate()) : String ("?"))
+ "\nBufferSizeInFrames = " + (stream != nullptr ? String (stream->getBufferSizeInFrames()) : String ("?"))
+ "\nBufferCapacityInFrames = " + (stream != nullptr ? String (stream->getBufferCapacityInFrames()) : String ("?"))
@@ -858,34 +851,48 @@ private:
+ "\nFramesPerCallback = " + (stream != nullptr ? String (stream->getFramesPerCallback()) : String ("?"))
+ "\nBytesPerFrame = " + (stream != nullptr ? String (stream->getBytesPerFrame()) : String ("?"))
+ "\nBytesPerSample = " + (stream != nullptr ? String (stream->getBytesPerSample()) : String ("?"))
+ "\nPerformanceMode = " + String (oboe::convertToText (oboe::PerformanceMode::LowLatency))
+ "\nPerformanceMode = " + getOboeString (oboe::PerformanceMode::LowLatency)
+ "\ngetDeviceId = " + (stream != nullptr ? String (stream->getDeviceId()) : String ("?")));
}
void calculateOutputLatency()
int getLatencyFor (OboeStream& stream)
{
// Sadly, Oboe uses non-portable int64_t (a.k.a. long on LP64 and long long on LLP64)
int64_t lastWrittenAndPresentedFrameIndex = 0;
int64_t lastFramePresentationTimeNanos = 0;
auto& nativeStream = *stream.getNativeStream();
if (auto latency = nativeStream.calculateLatencyMillis())
return static_cast<int> ((latency.value() * sampleRate) / 1000);
// Get the time that a known audio frame was presented.
int64_t hardwareFrameIndex = 0;
int64_t hardwareFrameHardwareTime = 0;
auto result = outputStream->getNativeStream()->getTimestamp (CLOCK_MONOTONIC,
&lastWrittenAndPresentedFrameIndex,
&lastFramePresentationTimeNanos);
auto result = nativeStream.getTimestamp (CLOCK_MONOTONIC,
&hardwareFrameIndex,
&hardwareFrameHardwareTime);
if (result != oboe::Result::OK)
return;
return 0;
// Get counter closest to the app.
const bool isOutput = nativeStream.getDirection() == oboe::Direction::Output;
const int64_t appFrameIndex = isOutput ? nativeStream.getFramesWritten() : nativeStream.getFramesRead();
int64_t currentNumFramesWritten = outputStream->getNativeStream()->getFramesWritten();
int64_t framesDelta = currentNumFramesWritten - lastWrittenAndPresentedFrameIndex;
int64_t timeDeltaNanos = framesDelta * oboe::kNanosPerSecond / sampleRate;
// Assume that the next frame will be processed at the current time
using namespace std::chrono;
int64_t appFrameAppTime = getCurrentTimeNanos();//duration_cast<nanoseconds> (steady_clock::now().time_since_epoch()).count();
int64_t appFrameAppTime2 = duration_cast<nanoseconds> (steady_clock::now().time_since_epoch()).count();
int64_t nextPresentationTimeNanos = lastFramePresentationTimeNanos + timeDeltaNanos;
int64_t nextFrameWriteTimeNanos = getCurrentTimeNanos();
// Calculate the number of frames between app and hardware
int64_t frameIndexDelta = appFrameIndex - hardwareFrameIndex;
if (nextFrameWriteTimeNanos < 0)
return;
// Calculate the time which the next frame will be or was presented
int64_t frameTimeDelta = (frameIndexDelta * oboe::kNanosPerSecond) / sampleRate;
int64_t appFrameHardwareTime = hardwareFrameHardwareTime + frameTimeDelta;
outputLatency = (int) ((nextPresentationTimeNanos - nextFrameWriteTimeNanos) * sampleRate / oboe::kNanosPerSecond);
// Calculate latency as a difference in time between when the current frame is at the app
// and when it is at the hardware.
auto latencyNanos = isOutput ? (appFrameHardwareTime - appFrameAppTime) : (appFrameAppTime - appFrameHardwareTime);
return static_cast<int> ((latencyNanos * sampleRate) / oboe::kNanosPerSecond);
}
int64_t getCurrentTimeNanos()
@@ -900,19 +907,23 @@ private:
void onErrorBeforeClose (oboe::AudioStream* stream, oboe::Result error) override
{
attachAndroidJNI();
// only output stream should be the master stream receiving callbacks
jassert (stream->getDirection() == oboe::Direction::Output);
JUCE_OBOE_LOG ("Oboe stream onErrorBeforeClose(): " + String (oboe::convertToText (error)));
JUCE_OBOE_LOG ("Oboe stream onErrorBeforeClose(): " + getOboeString (error));
printStreamDebugInfo (stream);
}
void onErrorAfterClose (oboe::AudioStream* stream, oboe::Result error) override
{
attachAndroidJNI();
// only output stream should be the master stream receiving callbacks
jassert (stream->getDirection() == oboe::Direction::Output);
JUCE_OBOE_LOG ("Oboe stream onErrorAfterClose(): " + String (oboe::convertToText (error)));
JUCE_OBOE_LOG ("Oboe stream onErrorAfterClose(): " + getOboeString (error));
if (error == oboe::Result::ErrorDisconnected)
{
@@ -948,7 +959,10 @@ private:
Atomic<int> audioCallbackGuard { 0 },
streamRestartGuard { 0 };
bool isOutputLatencyDetectionSupported = true;
bool isInputLatencyDetectionSupported = false;
int inputLatency = -1;
bool isOutputLatencyDetectionSupported = false;
int outputLatency = -1;
};
@@ -1016,6 +1030,23 @@ private:
return androidHasSystemFeature ("android.hardware.audio.pro");
}
static int getDefaultFramesPerBurst()
{
// NB: this function only works for inbuilt speakers and headphones
auto* env = getEnv();
auto audioManager = LocalRef<jobject> (env->CallObjectMethod (android.activity,
JuceAppActivity.getSystemService,
javaString ("audio").get()));
auto propertyJavaString = javaString ("android.media.property.OUTPUT_FRAMES_PER_BUFFER");
auto framesPerBurstString = LocalRef<jstring> ((jstring) android.activity.callObjectMethod (JuceAppActivity.audioManagerGetProperty,
propertyJavaString.get()));
return framesPerBurstString != 0 ? env->CallStaticIntMethod (JavaInteger, JavaInteger.parseInt, framesPerBurstString.get(), 10) : 192;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OboeAudioIODevice)
};
@@ -1098,7 +1129,7 @@ public:
forInput ? oboe::Direction::Input : oboe::Direction::Output,
oboe::SharingMode::Shared,
forInput ? 1 : 2,
getSdkVersion() >= 21 ? oboe::AudioFormat::Float : oboe::AudioFormat::I16,
getSDKVersion() >= 21 ? oboe::AudioFormat::Float : oboe::AudioFormat::I16,
(int) OboeAudioIODevice::getNativeSampleRate(),
OboeAudioIODevice::getNativeBufferSize(),
nullptr);
@@ -1117,18 +1148,17 @@ public:
int getIndexOfDevice (AudioIODevice* device, bool asInput) const override
{
if (device == nullptr)
return -1;
auto* oboeDevice = static_cast<OboeAudioIODevice*> (device);
auto oboeDeviceId = asInput ? oboeDevice->inputDeviceId
: oboeDevice->outputDeviceId;
if (auto oboeDevice = static_cast<OboeAudioIODevice*> (device))
{
auto oboeDeviceId = asInput ? oboeDevice->inputDeviceId
: oboeDevice->outputDeviceId;
auto& devices = asInput ? inputDevices : outputDevices;
auto& devices = asInput ? inputDevices : outputDevices;
for (int i = 0; i < devices.size(); ++i)
if (devices.getReference (i).id == oboeDeviceId)
return i;
for (int i = 0; i < devices.size(); ++i)
if (devices.getReference (i).id == oboeDeviceId)
return i;
}
return -1;
}
@@ -1233,11 +1263,11 @@ public:
bool supportsDevicesInfo() const
{
static auto result = getSdkVersion() >= 23;
static auto result = getSDKVersion() >= 23;
return result;
}
int getSdkVersion() const
int getSDKVersion() const
{
static auto sdkVersion = getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT);
return sdkVersion;
@@ -1399,7 +1429,7 @@ public:
return testStream != nullptr && testStream->openedOk();
}
pthread_t startThread (void* (*entry) (void*), void* userPtr)
pthread_t startThread (void*(*entry)(void*), void* userPtr)
{
pthread_mutex_lock (&threadReadyMutex);
@@ -1439,26 +1469,16 @@ public:
void onErrorBeforeClose (oboe::AudioStream*, oboe::Result error) override
{
JUCE_OBOE_LOG ("OboeRealtimeThread: Oboe stream onErrorBeforeClose(): " + String (oboe::convertToText (error)));
JUCE_OBOE_LOG ("OboeRealtimeThread: Oboe stream onErrorBeforeClose(): " + getOboeString (error));
ignoreUnused (error);
jassertfalse; // Should never get here!
}
void onErrorAfterClose (oboe::AudioStream* stream, oboe::Result error) override
void onErrorAfterClose (oboe::AudioStream*, oboe::Result error) override
{
JUCE_OBOE_LOG ("OboeRealtimeThread: Oboe stream onErrorAfterClose(): " + String (oboe::convertToText (error)));
if (error == oboe::Result::ErrorDisconnected)
{
testStream.reset();
testStream.reset (new OboeStream (-1,
oboe::Direction::Output,
oboe::SharingMode::Exclusive,
1,
formatUsed,
(int) OboeAudioIODevice::getNativeSampleRate(),
OboeAudioIODevice::getNativeBufferSize(),
this));
testStream->start();
}
JUCE_OBOE_LOG ("OboeRealtimeThread: Oboe stream onErrorAfterClose(): " + getOboeString (error));
ignoreUnused (error);
jassertfalse; // Should never get here!
}
private:
@@ -1482,10 +1502,7 @@ pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr)
return {};
auto threadID = thread->startThread (entry, userPtr);
// the thread will de-allocate itself
thread.release();
thread.release(); // the thread will de-allocate itself
return threadID;
}


Loading…
Cancel
Save