| @@ -33,7 +33,6 @@ namespace juce | |||
| METHOD (release, "release", "()V") \ | |||
| METHOD (flush, "flush", "()V") \ | |||
| METHOD (write, "write", "([SII)I") \ | |||
| METHOD (getUnderrunCount, "getUnderrunCount", "()I") \ | |||
| DECLARE_JNI_CLASS (AudioTrack, "android/media/AudioTrack"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| @@ -51,6 +50,13 @@ DECLARE_JNI_CLASS (AudioTrack, "android/media/AudioTrack"); | |||
| DECLARE_JNI_CLASS (AudioRecord, "android/media/AudioRecord"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICFIELD (SDK_INT, "SDK_INT", "I") \ | |||
| DECLARE_JNI_CLASS (AndroidBuildVersion, "android/os/Build$VERSION"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| enum | |||
| { | |||
| @@ -196,6 +202,9 @@ public: | |||
| STREAM_MUSIC, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT, | |||
| (jint) (minBufferSizeOut * numDeviceOutputChannels * static_cast<int> (sizeof (int16))), MODE_STREAM)); | |||
| const bool supportsUnderrunCount = (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 24); | |||
| getUnderrunCount = supportsUnderrunCount ? env->GetMethodID (AudioTrack, "getUnderrunCount", "()I") : 0; | |||
| int outputDeviceState = env->CallIntMethod (outputDevice, AudioTrack.getState); | |||
| if (outputDeviceState > 0) | |||
| { | |||
| @@ -284,8 +293,8 @@ public: | |||
| int getXRunCount() const noexcept override | |||
| { | |||
| if (outputDevice != nullptr) | |||
| return getEnv()->CallIntMethod (outputDevice, AudioTrack.getUnderrunCount); | |||
| if (outputDevice != nullptr && getUnderrunCount != 0) | |||
| return getEnv()->CallIntMethod (outputDevice, getUnderrunCount); | |||
| return -1; | |||
| } | |||
| @@ -415,6 +424,7 @@ private: | |||
| BigInteger activeOutputChans, activeInputChans; | |||
| GlobalRef outputDevice, inputDevice; | |||
| AudioSampleBuffer inputChannelBuffer, outputChannelBuffer; | |||
| jmethodID getUnderrunCount = 0; | |||
| void closeDevices() | |||
| { | |||
| @@ -23,12 +23,6 @@ | |||
| namespace juce | |||
| { | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICFIELD (SDK_INT, "SDK_INT", "I") \ | |||
| DECLARE_JNI_CLASS (AndroidBuildVersion, "android/os/Build$VERSION"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #ifndef SL_ANDROID_DATAFORMAT_PCM_EX | |||
| #define SL_ANDROID_DATAFORMAT_PCM_EX ((SLuint32) 0x00000004) | |||
| @@ -306,15 +300,22 @@ public: | |||
| if (runner == nullptr) | |||
| return false; | |||
| // may return nullptr on some platforms - that's ok | |||
| config = SlRef<SLAndroidConfigurationItf_>::cast (runner); | |||
| if (config != nullptr) | |||
| const bool supportsJavaProxy = (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 24); | |||
| if (supportsJavaProxy) | |||
| { | |||
| jobject audioRoutingJni; | |||
| auto status = (*config)->AcquireJavaProxy (config, SL_ANDROID_JAVA_PROXY_ROUTING, &audioRoutingJni); | |||
| // may return nullptr on some platforms - that's ok | |||
| config = SlRef<SLAndroidConfigurationItf_>::cast (runner); | |||
| if (status == SL_RESULT_SUCCESS && audioRoutingJni != 0) | |||
| javaProxy = GlobalRef (audioRoutingJni); | |||
| if (config != nullptr) | |||
| { | |||
| jobject audioRoutingJni; | |||
| auto status = (*config)->AcquireJavaProxy (config, SL_ANDROID_JAVA_PROXY_ROUTING, | |||
| &audioRoutingJni); | |||
| if (status == SL_RESULT_SUCCESS && audioRoutingJni != 0) | |||
| javaProxy = GlobalRef (audioRoutingJni); | |||
| } | |||
| } | |||
| queue = SlRef<SLAndroidSimpleBufferQueueItf_>::cast (runner); | |||
| @@ -634,6 +635,9 @@ public: | |||
| player = nullptr; | |||
| return; | |||
| } | |||
| const bool supportsUnderrunCount = (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 24); | |||
| getUnderrunCount = supportsUnderrunCount ? getEnv()->GetMethodID (AudioTrack, "getUnderrunCount", "()I") : 0; | |||
| } | |||
| } | |||
| } | |||
| @@ -698,8 +702,8 @@ public: | |||
| int getXRunCount() const noexcept override | |||
| { | |||
| if (player != nullptr && player->javaProxy != nullptr) | |||
| return getEnv()->CallIntMethod (player->javaProxy, AudioTrack.getUnderrunCount); | |||
| if (player != nullptr && player->javaProxy != nullptr && getUnderrunCount != 0) | |||
| return getEnv()->CallIntMethod (player->javaProxy, getUnderrunCount); | |||
| return -1; | |||
| } | |||
| @@ -754,6 +758,7 @@ public: | |||
| ScopedPointer<OpenSLQueueRunnerPlayer<T> > player; | |||
| ScopedPointer<OpenSLQueueRunnerRecorder<T> > recorder; | |||
| Atomic<int> guard; | |||
| jmethodID getUnderrunCount = 0; | |||
| }; | |||
| //============================================================================== | |||