You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
665 lines
27 KiB
665 lines
27 KiB
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
// Demonstrate environmental reverb and preset reverb on an output mix and audio player
|
|
|
|
#include <SLES/OpenSLES.h>
|
|
#include <assert.h>
|
|
#include <pthread.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#define bool int
|
|
#define false 0
|
|
#define true 1
|
|
|
|
// Table of I3DL2 named environmental reverb settings
|
|
|
|
typedef struct {
|
|
const char *mName;
|
|
SLEnvironmentalReverbSettings mSettings;
|
|
} Pair;
|
|
|
|
#define _(name) {#name, SL_I3DL2_ENVIRONMENT_PRESET_##name},
|
|
|
|
Pair pairs[] = {
|
|
_(DEFAULT)
|
|
_(GENERIC)
|
|
_(PADDEDCELL)
|
|
_(ROOM)
|
|
_(BATHROOM)
|
|
_(LIVINGROOM)
|
|
_(STONEROOM)
|
|
_(AUDITORIUM)
|
|
_(CONCERTHALL)
|
|
_(CAVE)
|
|
_(ARENA)
|
|
_(HANGAR)
|
|
_(CARPETEDHALLWAY)
|
|
_(HALLWAY)
|
|
_(STONECORRIDOR)
|
|
_(ALLEY)
|
|
_(FOREST)
|
|
_(CITY)
|
|
_(MOUNTAINS)
|
|
_(QUARRY)
|
|
_(PLAIN)
|
|
_(PARKINGLOT)
|
|
_(SEWERPIPE)
|
|
_(UNDERWATER)
|
|
_(SMALLROOM)
|
|
_(MEDIUMROOM)
|
|
_(LARGEROOM)
|
|
_(MEDIUMHALL)
|
|
_(LARGEHALL)
|
|
_(PLATE)
|
|
};
|
|
|
|
// Parameters for preset reverb on output mix
|
|
bool outputMixPresetItfRequested = false;
|
|
SLuint16 outputMixPresetNumber = ~0;
|
|
|
|
// Parameters for environmental reverb on output mix
|
|
bool outputMixEnvironmentalItfRequested = false;
|
|
char *outputMixEnvironmentalName = NULL;
|
|
SLEnvironmentalReverbSettings outputMixEnvironmentalSettings;
|
|
|
|
// Parameters for preset reverb on audio player (not supported)
|
|
bool playerPresetItfRequested = false;
|
|
SLuint16 playerPresetNumber = ~0;
|
|
|
|
// Parameters for environmental reverb on audio player (not supported)
|
|
bool playerEnvironmentalItfRequested = false;
|
|
char *playerEnvironmentalName = NULL;
|
|
SLEnvironmentalReverbSettings playerEnvironmentalSettings;
|
|
|
|
// Compare two environmental reverb settings structures.
|
|
// Returns true if the settings are identical, or false if they are different.
|
|
|
|
bool slesutCompareEnvironmentalReverbSettings(
|
|
const SLEnvironmentalReverbSettings *settings1,
|
|
const SLEnvironmentalReverbSettings *settings2)
|
|
{
|
|
return
|
|
(settings1->roomLevel == settings2->roomLevel) &&
|
|
(settings1->roomHFLevel == settings2->roomHFLevel) &&
|
|
(settings1->decayTime == settings2->decayTime) &&
|
|
(settings1->decayHFRatio == settings2->decayHFRatio) &&
|
|
(settings1->reflectionsLevel == settings2->reflectionsLevel) &&
|
|
(settings1->reflectionsDelay == settings2->reflectionsDelay) &&
|
|
(settings1->reverbLevel == settings2->reverbLevel) &&
|
|
(settings1->reverbDelay == settings2->reverbDelay) &&
|
|
(settings1->diffusion == settings2->diffusion) &&
|
|
(settings1->density == settings2->density);
|
|
}
|
|
|
|
// Print an environmental reverb settings structure.
|
|
|
|
void slesutPrintEnvironmentalReverbSettings(const SLEnvironmentalReverbSettings *settings)
|
|
{
|
|
printf("roomLevel: %d\n", settings->roomLevel);
|
|
printf("roomHFLevel: %d\n", settings->roomHFLevel);
|
|
printf("decayTime: %d\n", settings->decayTime);
|
|
printf("decayHFRatio: %d\n", settings->decayHFRatio);
|
|
printf("reflectionsLevel: %d\n", settings->reflectionsLevel);
|
|
printf("reflectionsDelay: %d\n", settings->reflectionsDelay);
|
|
printf("reverbLevel: %d\n", settings->reverbLevel);
|
|
printf("reverbDelay: %d\n", settings->reverbDelay);
|
|
printf("diffusion: %d\n", settings->diffusion);
|
|
printf("density: %d\n", settings->density);
|
|
}
|
|
|
|
// Lookup environmental reverb settings by name
|
|
|
|
const SLEnvironmentalReverbSettings *lookupEnvName(const char *name)
|
|
{
|
|
unsigned j;
|
|
for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) {
|
|
if (!strcasecmp(name, pairs[j].mName)) {
|
|
return &pairs[j].mSettings;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Print all available environmental reverb names
|
|
|
|
void printEnvNames(void)
|
|
{
|
|
unsigned j;
|
|
bool needSpace = false;
|
|
bool needNewline = false;
|
|
unsigned lineLen = 0;
|
|
for (j = 0; j < sizeof(pairs) / sizeof(pairs[0]); ++j) {
|
|
const char *name = pairs[j].mName;
|
|
unsigned nameLen = strlen(name);
|
|
if (lineLen + (needSpace ? 1 : 0) + nameLen > 72) {
|
|
putchar('\n');
|
|
needSpace = false;
|
|
needNewline = false;
|
|
lineLen = 0;
|
|
}
|
|
if (needSpace) {
|
|
putchar(' ');
|
|
++lineLen;
|
|
}
|
|
fputs(name, stdout);
|
|
lineLen += nameLen;
|
|
needSpace = true;
|
|
needNewline = true;
|
|
}
|
|
if (needNewline) {
|
|
putchar('\n');
|
|
}
|
|
}
|
|
|
|
// These are extensions to OpenSL ES 1.0.1 values
|
|
|
|
#define SL_PREFETCHSTATUS_UNKNOWN ((SLuint32) 0)
|
|
#define SL_PREFETCHSTATUS_ERROR ((SLuint32) -1)
|
|
|
|
// Mutex and condition shared with main program to protect prefetch_status
|
|
|
|
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
|
SLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
|
|
|
|
/* used to detect errors likely to have occured when the OpenSL ES framework fails to open
|
|
* a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
|
|
*/
|
|
#define PREFETCHEVENT_ERROR_CANDIDATE \
|
|
(SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
|
|
|
|
// Prefetch status callback
|
|
|
|
void prefetch_callback(SLPrefetchStatusItf caller, void *context, SLuint32 event)
|
|
{
|
|
SLresult result;
|
|
assert(context == NULL);
|
|
SLpermille level;
|
|
result = (*caller)->GetFillLevel(caller, &level);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLuint32 status;
|
|
result = (*caller)->GetPrefetchStatus(caller, &status);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLuint32 new_prefetch_status;
|
|
if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
|
|
&& level == 0 && status == SL_PREFETCHSTATUS_UNDERFLOW) {
|
|
new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
|
|
} else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
|
|
status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
|
|
new_prefetch_status = status;
|
|
} else {
|
|
return;
|
|
}
|
|
int ok;
|
|
ok = pthread_mutex_lock(&mutex);
|
|
assert(ok == 0);
|
|
prefetch_status = new_prefetch_status;
|
|
ok = pthread_cond_signal(&cond);
|
|
assert(ok == 0);
|
|
ok = pthread_mutex_unlock(&mutex);
|
|
assert(ok == 0);
|
|
}
|
|
|
|
// Main program
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
SLresult result;
|
|
bool loop = false;
|
|
|
|
// process command line parameters
|
|
char *prog = argv[0];
|
|
int i;
|
|
for (i = 1; i < argc; ++i) {
|
|
char *arg = argv[i];
|
|
if (arg[0] != '-')
|
|
break;
|
|
bool bad = false; // whether the option string is invalid
|
|
if (!strncmp(arg, "--mix-preset", 12)) {
|
|
if ('\0' == arg[12]) {
|
|
outputMixPresetItfRequested = true;
|
|
} else if ('=' == arg[12]) {
|
|
outputMixPresetNumber = atoi(&arg[13]);
|
|
outputMixPresetItfRequested = true;
|
|
} else {
|
|
bad = true;
|
|
}
|
|
} else if (!strncmp(arg, "--mix-name", 10)) {
|
|
if ('\0' == arg[10]) {
|
|
outputMixEnvironmentalItfRequested = true;
|
|
} else if ('=' == arg[10]) {
|
|
outputMixEnvironmentalName = &arg[11];
|
|
outputMixEnvironmentalItfRequested = true;
|
|
} else {
|
|
bad = true;
|
|
}
|
|
} else if (!strncmp(arg, "--player-preset", 15)) {
|
|
if ('\0' == arg[15]) {
|
|
playerPresetItfRequested = true;
|
|
} else if ('=' == arg[15]) {
|
|
playerPresetNumber = atoi(&arg[16]);
|
|
playerPresetItfRequested = true;
|
|
} else {
|
|
bad = true;
|
|
}
|
|
} else if (!strncmp(arg, "--player-name", 13)) {
|
|
if ('\0' == arg[13]) {
|
|
playerEnvironmentalItfRequested = true;
|
|
} else if ('=' == arg[13]) {
|
|
playerEnvironmentalName = &arg[14];
|
|
playerEnvironmentalItfRequested = true;
|
|
} else {
|
|
bad = true;
|
|
}
|
|
} else if (!strcmp(arg, "--loop")) {
|
|
loop = true;
|
|
} else {
|
|
bad = true;
|
|
}
|
|
if (bad) {
|
|
fprintf(stderr, "%s: unknown option %s ignored\n", prog, arg);
|
|
}
|
|
}
|
|
if (argc - i != 1) {
|
|
fprintf(stderr, "usage: %s --mix-preset=# --mix-name=I3DL2 --player-preset=# "
|
|
"--player-name=I3DL2 --loop filename\n", prog);
|
|
return EXIT_FAILURE;
|
|
}
|
|
char *pathname = argv[i];
|
|
|
|
const SLEnvironmentalReverbSettings *envSettings;
|
|
if (NULL != outputMixEnvironmentalName) {
|
|
envSettings = lookupEnvName(outputMixEnvironmentalName);
|
|
if (NULL == envSettings) {
|
|
fprintf(stderr, "%s: output mix environmental reverb name %s not found, "
|
|
"available names are:\n", prog, outputMixEnvironmentalName);
|
|
printEnvNames();
|
|
return EXIT_FAILURE;
|
|
}
|
|
outputMixEnvironmentalSettings = *envSettings;
|
|
}
|
|
if (NULL != playerEnvironmentalName) {
|
|
envSettings = lookupEnvName(playerEnvironmentalName);
|
|
if (NULL == envSettings) {
|
|
fprintf(stderr, "%s: player environmental reverb name %s not found, "
|
|
"available names are:\n", prog, playerEnvironmentalName);
|
|
printEnvNames();
|
|
return EXIT_FAILURE;
|
|
}
|
|
playerEnvironmentalSettings = *envSettings;
|
|
}
|
|
|
|
// create engine
|
|
SLObjectItf engineObject;
|
|
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLEngineItf engineEngine;
|
|
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// create output mix
|
|
SLInterfaceID mix_ids[2];
|
|
SLboolean mix_req[2];
|
|
SLuint32 count = 0;
|
|
if (outputMixPresetItfRequested) {
|
|
mix_req[count] = SL_BOOLEAN_TRUE;
|
|
mix_ids[count++] = SL_IID_PRESETREVERB;
|
|
}
|
|
if (outputMixEnvironmentalItfRequested) {
|
|
mix_req[count] = SL_BOOLEAN_TRUE;
|
|
mix_ids[count++] = SL_IID_ENVIRONMENTALREVERB;
|
|
}
|
|
SLObjectItf mixObject;
|
|
result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, count, mix_ids, mix_req);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// configure preset reverb on output mix
|
|
SLPresetReverbItf outputMixPresetReverb;
|
|
if (outputMixPresetItfRequested) {
|
|
result = (*mixObject)->GetInterface(mixObject, SL_IID_PRESETREVERB, &outputMixPresetReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLuint16 getPresetReverb = 12345;
|
|
result = (*outputMixPresetReverb)->GetPreset(outputMixPresetReverb, &getPresetReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix default preset reverb number = %u\n", getPresetReverb);
|
|
if (outputMixPresetNumber != ((SLuint16) ~0)) {
|
|
result = (*outputMixPresetReverb)->SetPreset(outputMixPresetReverb,
|
|
outputMixPresetNumber);
|
|
if (SL_RESULT_SUCCESS == result) {
|
|
result = (*outputMixPresetReverb)->GetPreset(outputMixPresetReverb,
|
|
&getPresetReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
assert(getPresetReverb == outputMixPresetNumber);
|
|
printf("Output mix preset reverb successfully changed to %u\n",
|
|
outputMixPresetNumber);
|
|
} else {
|
|
printf("Unable to set output mix preset reverb to %u, result=%u\n",
|
|
outputMixPresetNumber, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
// configure environmental reverb on output mix
|
|
SLEnvironmentalReverbItf outputMixEnvironmentalReverb;
|
|
if (outputMixEnvironmentalItfRequested) {
|
|
result = (*mixObject)->GetInterface(mixObject, SL_IID_ENVIRONMENTALREVERB,
|
|
&outputMixEnvironmentalReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLEnvironmentalReverbSettings getSettings;
|
|
result = (*outputMixEnvironmentalReverb)->GetEnvironmentalReverbProperties(
|
|
outputMixEnvironmentalReverb, &getSettings);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix default environmental reverb settings\n");
|
|
printf("------------------------------------------------\n");
|
|
slesutPrintEnvironmentalReverbSettings(&getSettings);
|
|
printf("\n");
|
|
if (outputMixEnvironmentalName != NULL) {
|
|
result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
|
|
outputMixEnvironmentalReverb, &outputMixEnvironmentalSettings);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix new environmental reverb settings\n");
|
|
printf("--------------------------------------------\n");
|
|
slesutPrintEnvironmentalReverbSettings(&outputMixEnvironmentalSettings);
|
|
printf("\n");
|
|
result = (*outputMixEnvironmentalReverb)->GetEnvironmentalReverbProperties(
|
|
outputMixEnvironmentalReverb, &getSettings);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix read environmental reverb settings\n");
|
|
printf("--------------------------------------------\n");
|
|
slesutPrintEnvironmentalReverbSettings(&getSettings);
|
|
printf("\n");
|
|
if (!slesutCompareEnvironmentalReverbSettings(&getSettings,
|
|
&outputMixEnvironmentalSettings)) {
|
|
printf("Warning: new and read are different; check details above\n");
|
|
} else {
|
|
printf("New and read match, life is good\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
// create audio player
|
|
SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, (SLchar *) pathname};
|
|
SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
|
|
SLDataSource audioSrc = {&locURI, &dfMIME};
|
|
SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject};
|
|
SLDataSink audioSnk = {&locOutputMix, NULL};
|
|
SLInterfaceID player_ids[5];
|
|
SLboolean player_req[5];
|
|
count = 0;
|
|
if (playerPresetItfRequested) {
|
|
player_req[count] = SL_BOOLEAN_TRUE;
|
|
player_ids[count++] = SL_IID_PRESETREVERB;
|
|
}
|
|
if (playerEnvironmentalItfRequested) {
|
|
player_req[count] = SL_BOOLEAN_TRUE;
|
|
player_ids[count++] = SL_IID_ENVIRONMENTALREVERB;
|
|
}
|
|
if (outputMixPresetItfRequested || outputMixEnvironmentalItfRequested) {
|
|
player_req[count] = SL_BOOLEAN_TRUE;
|
|
player_ids[count++] = SL_IID_EFFECTSEND;
|
|
}
|
|
if (loop) {
|
|
player_req[count] = SL_BOOLEAN_TRUE;
|
|
player_ids[count++] = SL_IID_SEEK;
|
|
}
|
|
player_req[count] = SL_BOOLEAN_TRUE;
|
|
player_ids[count++] = SL_IID_PREFETCHSTATUS;
|
|
SLObjectItf playerObject;
|
|
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
|
|
&audioSnk, count, player_ids, player_req);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// realize audio player
|
|
result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// if reverb is on output mix (aux effect), then enable it for this player
|
|
if (outputMixPresetItfRequested || outputMixEnvironmentalItfRequested) {
|
|
SLEffectSendItf playerEffectSend;
|
|
result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLboolean enabled;
|
|
SLmillibel directLevel;
|
|
SLmillibel sendLevel;
|
|
if (outputMixPresetItfRequested) {
|
|
result = (*playerEffectSend)->IsEnabled(playerEffectSend, outputMixPresetReverb,
|
|
&enabled);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix preset reverb: player effect send default enabled = %s\n",
|
|
enabled ? "true" : "false");
|
|
directLevel = 12345;
|
|
result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix preset reverb: player effect send default direct level = %d\n",
|
|
directLevel);
|
|
sendLevel = 12345;
|
|
result = (*playerEffectSend)->GetSendLevel(playerEffectSend, outputMixPresetReverb,
|
|
&sendLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix preset reverb: player effect send default send level = %d\n",
|
|
sendLevel);
|
|
if (outputMixPresetNumber != ((SLuint16) ~0)) {
|
|
result = (*playerEffectSend)->EnableEffectSend(playerEffectSend,
|
|
outputMixPresetReverb, SL_BOOLEAN_TRUE, (SLmillibel) 0);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*playerEffectSend)->IsEnabled(playerEffectSend, outputMixPresetReverb,
|
|
&enabled);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
directLevel = 12345;
|
|
result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
sendLevel = 12345;
|
|
result = (*playerEffectSend)->GetSendLevel(playerEffectSend, outputMixPresetReverb,
|
|
&sendLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix preset reverb: player effect send new enabled = %s, direct level"
|
|
" = %d, send level = %d\n", enabled ? "true" : "false", directLevel, sendLevel);
|
|
}
|
|
}
|
|
if (outputMixEnvironmentalItfRequested) {
|
|
if (outputMixEnvironmentalName != NULL) {
|
|
result = (*playerEffectSend)->IsEnabled(playerEffectSend,
|
|
outputMixEnvironmentalReverb, &enabled);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix environmental reverb: player effect send default enabled = %s\n",
|
|
enabled ? "true" : "false");
|
|
directLevel = 12345;
|
|
result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix environmental reverb: player effect send default direct level"
|
|
" = %d\n", directLevel);
|
|
sendLevel = 12345;
|
|
result = (*playerEffectSend)->GetSendLevel(playerEffectSend,
|
|
outputMixEnvironmentalReverb, &sendLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix environmental reverb: player effect send default send level"
|
|
" = %d\n", sendLevel);
|
|
result = (*playerEffectSend)->EnableEffectSend(playerEffectSend,
|
|
outputMixEnvironmentalReverb, SL_BOOLEAN_TRUE, (SLmillibel) 0);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*playerEffectSend)->IsEnabled(playerEffectSend,
|
|
outputMixEnvironmentalReverb, &enabled);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
directLevel = 12345;
|
|
result = (*playerEffectSend)->GetDirectLevel(playerEffectSend, &directLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
sendLevel = 12345;
|
|
result = (*playerEffectSend)->GetSendLevel(playerEffectSend,
|
|
outputMixEnvironmentalReverb, &sendLevel);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Output mix environmental reverb: player effect send new enabled = %s, "
|
|
"direct level = %d, send level = %d\n", enabled ? "true" : "false",
|
|
directLevel, sendLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
// configure preset reverb on player
|
|
SLPresetReverbItf playerPresetReverb;
|
|
if (playerPresetItfRequested) {
|
|
result = (*playerObject)->GetInterface(playerObject, SL_IID_PRESETREVERB,
|
|
&playerPresetReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLuint16 getPresetReverb = 12345;
|
|
result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb);
|
|
if (SL_RESULT_SUCCESS == result) {
|
|
printf("Player default preset reverb %u\n", getPresetReverb);
|
|
if (playerPresetNumber != ((SLuint16) ~0)) {
|
|
result = (*playerPresetReverb)->SetPreset(playerPresetReverb, playerPresetNumber);
|
|
if (SL_RESULT_SUCCESS == result) {
|
|
result = (*playerPresetReverb)->GetPreset(playerPresetReverb, &getPresetReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
assert(getPresetReverb == playerPresetNumber);
|
|
printf("Player preset reverb successfully changed to %u\n", playerPresetNumber);
|
|
} else {
|
|
printf("Unable to set player preset reverb to %u, result=%u\n",
|
|
playerPresetNumber, result);
|
|
}
|
|
}
|
|
} else {
|
|
printf("Unable to get player default preset reverb, result=%u\n", result);
|
|
}
|
|
}
|
|
|
|
// configure environmental reverb on player
|
|
SLEnvironmentalReverbItf playerEnvironmentalReverb;
|
|
if (playerEnvironmentalItfRequested) {
|
|
result = (*playerObject)->GetInterface(playerObject, SL_IID_ENVIRONMENTALREVERB,
|
|
&playerEnvironmentalReverb);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
SLEnvironmentalReverbSettings getSettings;
|
|
memset(&getSettings, 0, sizeof(getSettings));
|
|
result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties(
|
|
playerEnvironmentalReverb, &getSettings);
|
|
if (SL_RESULT_SUCCESS == result) {
|
|
printf("Player default environmental reverb settings\n");
|
|
printf("--------------------------------------------\n");
|
|
slesutPrintEnvironmentalReverbSettings(&getSettings);
|
|
printf("\n");
|
|
if (playerEnvironmentalName != NULL) {
|
|
result = (*playerEnvironmentalReverb)->SetEnvironmentalReverbProperties(
|
|
playerEnvironmentalReverb, &playerEnvironmentalSettings);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Player new environmental reverb settings\n");
|
|
printf("----------------------------------------\n");
|
|
slesutPrintEnvironmentalReverbSettings(&playerEnvironmentalSettings);
|
|
printf("\n");
|
|
result = (*playerEnvironmentalReverb)->GetEnvironmentalReverbProperties(
|
|
playerEnvironmentalReverb, &getSettings);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
printf("Player read environmental reverb settings\n");
|
|
printf("-----------------------------------------\n");
|
|
slesutPrintEnvironmentalReverbSettings(&getSettings);
|
|
printf("\n");
|
|
if (!slesutCompareEnvironmentalReverbSettings(&getSettings,
|
|
&playerEnvironmentalSettings)) {
|
|
printf("Warning: new and read are different; check details above\n");
|
|
} else {
|
|
printf("New and read match, life is good\n");
|
|
}
|
|
}
|
|
} else {
|
|
printf("Unable to get player default environmental reverb properties, result=%u\n",
|
|
result);
|
|
}
|
|
}
|
|
|
|
// get the play interface
|
|
SLPlayItf playerPlay;
|
|
result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// get the prefetch status interface
|
|
SLPrefetchStatusItf playerPrefetchStatus;
|
|
result = (*playerObject)->GetInterface(playerObject, SL_IID_PREFETCHSTATUS,
|
|
&playerPrefetchStatus);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// enable prefetch status callbacks
|
|
result = (*playerPrefetchStatus)->RegisterCallback(playerPrefetchStatus, prefetch_callback,
|
|
NULL);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*playerPrefetchStatus)->SetCallbackEventsMask(playerPrefetchStatus,
|
|
SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// set play state to paused to enable pre-fetch so we can get a more reliable duration
|
|
result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// wait for prefetch status callback to indicate either sufficient data or error
|
|
pthread_mutex_lock(&mutex);
|
|
while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
|
|
pthread_cond_wait(&cond, &mutex);
|
|
}
|
|
pthread_mutex_unlock(&mutex);
|
|
if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
|
|
fprintf(stderr, "Error during prefetch, exiting\n");
|
|
goto destroyRes;
|
|
}
|
|
|
|
// get the duration
|
|
SLmillisecond duration;
|
|
result = (*playerPlay)->GetDuration(playerPlay, &duration);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
if (SL_TIME_UNKNOWN == duration) {
|
|
printf("duration: unknown\n");
|
|
} else {
|
|
printf("duration: %.1f seconds\n", duration / 1000.0);
|
|
}
|
|
|
|
// enable looping
|
|
if (loop) {
|
|
SLSeekItf playerSeek;
|
|
result = (*playerObject)->GetInterface(playerObject, SL_IID_SEEK, &playerSeek);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*playerSeek)->SetLoop(playerSeek, SL_BOOLEAN_TRUE, (SLmillisecond) 0,
|
|
SL_TIME_UNKNOWN);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
}
|
|
|
|
// start audio playing
|
|
result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// wait for audio to finish playing
|
|
SLuint32 state;
|
|
for (;;) {
|
|
result = (*playerPlay)->GetPlayState(playerPlay, &state);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
if (SL_PLAYSTATE_PLAYING != state)
|
|
break;
|
|
usleep(1000000);
|
|
}
|
|
assert(SL_PLAYSTATE_PAUSED == state);
|
|
|
|
destroyRes:
|
|
// cleanup objects
|
|
(*playerObject)->Destroy(playerObject);
|
|
(*mixObject)->Destroy(mixObject);
|
|
(*engineObject)->Destroy(engineObject);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|