6 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
7 #include <QAndroidJniEnvironment>
9 #include <QJniEnvironment>
11 #define QAndroidJniEnvironment QJniEnvironment
12 #define QAndroidJniObject QJniObject
19 #define LOC QString("AOSLES: ")
21 #define OPENSLES_BUFFERS 10
25 #define POSITIONUPDATEPERIOD 40
28 #define CHECK_OPENSL_ERROR(msg) \
29 if (result != SL_RESULT_SUCCESS) \
31 VBERROR(QString("Open Error: (%1)").arg(result)); \
36 #define CHECK_OPENSL_START_ERROR(msg) \
37 if (result != SL_RESULT_SUCCESS) \
39 VBERROR(QString("Start Error: (%1)").arg(result)); \
45 #define Destroy(a) (*(a))->Destroy(a);
46 #define SetPlayState(a, b) (*(a))->SetPlayState(a, b)
47 #define RegisterCallback(a, b, c) (*(a))->RegisterCallback(a, b, c)
48 #define GetInterface(a, b, c) (*(a))->GetInterface(a, b, c)
49 #define Realize(a, b) (*(a))->Realize(a, b)
50 #define CreateOutputMix(a, b, c, d, e) (*(a))->CreateOutputMix(a, b, c, d, e)
51 #define CreateAudioPlayer(a, b, c, d, e, f, g) \
52 (*(a))->CreateAudioPlayer(a, b, c, d, e, f, g)
53 #define Enqueue(a, b, c) (*(a))->Enqueue(a, b, c)
54 #define Clear(a) (*(a))->Clear(a)
55 #define GetState(a, b) (*(a))->GetState(a, b)
56 #define SetPositionUpdatePeriod(a, b) (*(a))->SetPositionUpdatePeriod(a, b)
57 #define SetVolumeLevel(a, b) (*(a))->SetVolumeLevel(a, b)
58 #define GetVolumeLevel(a, b) (*(a))->GetVolumeLevel(a, b)
59 #define SetMute(a, b) (*(a))->SetMute(a, b)
67 jclass cls = jniEnv->FindClass(
"android/media/AudioTrack");
68 jmethodID method = jniEnv->GetStaticMethodID (cls,
"getNativeOutputSampleRate",
"(I)I");
69 int sample_rate = jniEnv->CallStaticIntMethod (cls, method, 3);
73 return QAndroidJniObject::callStaticMethodInt(
"android/media/AudioTrack",
"getNativeOutputSampleRate",
"(I)I", 3);
78 int GetNativeOutputFramesPerBuffer(
void)
80 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
83 QJniObject activity = QNativeInterface::QAndroidApplication::context();
86 QAndroidJniObject audioManager = activity.callObjectMethod(
"getSystemService",
"", );
87 jstring sValue = audioManager.callMethod<jstring>(
"getProperty", PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
89 return QAndroidJniObject::callStaticMethodInt(
"android/media/AudioManager",
"getProperty",
"(I)I", 3);
100 VBERROR(
"Error: Failed to load libOpenSLES");
108 VBERROR(
"Error: Failed to load symbol slCreateEngine");
113 #define OPENSL_DLSYM(dest, name) \
115 const SLInterfaceID *sym = (const SLInterfaceID *)dlsym(m_so_handle, "SL_IID_" name); \
116 if (sym == nullptr) \
118 LOG(VB_GENERAL, LOG_ERR, "AOOSLES Error: Failed to load symbol SL_IID_" name); \
145 const SLboolean req1[] = { SL_BOOLEAN_FALSE };
161 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
162 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
166 SLDataFormat_PCM format_pcm;
167 format_pcm.formatType = SL_DATAFORMAT_PCM;
168 format_pcm.numChannels = 2;
169 format_pcm.samplesPerSec = ((SLuint32)
m_sampleRate * 1000) ;
170 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
173 case FORMAT_U8: format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_8;
break;
174 case FORMAT_S16: format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
break;
176 case FORMAT_S24LSB: format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_24;
break;
178 format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
179 format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_24;
181 case FORMAT_S32: format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_32;
break;
188 format_pcm.containerSize = format_pcm.bitsPerSample;
189 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
191 SLDataSource audioSrc = {&loc_bufq, &format_pcm};
194 SLDataLocator_OutputMix loc_outmix = {
195 SL_DATALOCATOR_OUTPUTMIX,
198 SLDataSink audioSnk = {&loc_outmix,
nullptr};
202 static const SLboolean req2[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
206 &audioSnk,
sizeof(ids2) /
sizeof(*ids2),
215 result = SL_RESULT_UNKNOWN_ERROR;
217 if (result != SL_RESULT_SUCCESS) {
220 format_pcm.samplesPerSec = ((SLuint32) 48000 * 1000) ;
222 &audioSnk,
sizeof(ids2) /
sizeof(*ids2),
351 VBGENERAL(QString(
"Native Rate %1").arg(nativeRate));
360 #if 0 // 32-bit floating point (AC3) is not supported on all platforms.
387 VBAUDIO(QString(
"Buffering %1 fragments of %2 bytes each, total: %3 bytes")
417 SLAndroidSimpleBufferQueueState st;
419 if (res != SL_RESULT_SUCCESS) {
420 VBERROR(QString(
"Could not query buffer queue state in %1 (%2)").arg(__func__).arg(res));
423 VBAUDIO(QString(
"Num Queued %1").arg(st.count));
429 VBAUDIO(QString(
"WriteAudio %1").arg(size));
434 if (numBufferesQueued < 0)
460 if (r != SL_RESULT_SUCCESS)
463 VBERROR(QString(
"error %1 when writing %2 bytes %3")
466 .arg((r == SL_RESULT_BUFFER_INSUFFICIENT) ?
" (buffer insufficient)" :
""));
481 if (numBufferesQueued < 0)
493 if (r == SL_RESULT_SUCCESS)
495 if (mb <= SL_MILLIBEL_MIN)
501 volume = lroundf(expf(mb / (3*2000.0F)) * 100);
503 VBAUDIO(QString(
"GetVolume(%1) %2 (%3)")
504 .arg(channel).arg(volume).arg(mb));
508 VBERROR(QString(
"GetVolume(%1) %2 (%3) : %4")
509 .arg(channel).arg(volume).arg(mb).arg(r));
518 VBERROR(
"Android volume only supports stereo!");
523 float vol = volume / 100.f;
528 mb = SL_MILLIBEL_MIN;
533 mb = lroundf(3 * 2000.F * log10f(vol));
534 if (mb < SL_MILLIBEL_MIN)
535 mb = SL_MILLIBEL_MIN;
541 if (r == SL_RESULT_SUCCESS)
543 VBAUDIO(QString(
"SetVolume(%1) %2(%3)")
544 .arg(channel).arg(volume).arg(mb));
548 VBERROR(QString(
"SetVolume(%1) %2(%3) : %4")
549 .arg(channel).arg(volume).arg(mb).arg(r));