--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef OPENSL_ES_ANDROIDCONFIGURATION_H_
+#define OPENSL_ES_ANDROIDCONFIGURATION_H_
+
+#ifdef __cplusplus
+extern "C" {
+
+/*---------------------------------------------------------------------------*/
+/* Android AudioRecorder configuration */
+/*---------------------------------------------------------------------------*/
+
+/** Audio recording preset */
+/** Audio recording preset key */
+#define SL_ANDROID_KEY_RECORDING_PRESET ((const SLchar*) "androidRecordingPreset")
+/** Audio recording preset values */
+/** preset "none" cannot be set, it is used to indicate the current settings
+ * do not match any of the presets. */
+#define SL_ANDROID_RECORDING_PRESET_NONE ((SLuint32) 0x00000000)
+/** default recording configuration on the platform */
+#define SL_ANDROID_RECORDING_PRESET_DEFAULT ((SLuint32) 0x00000001)
+/** uses the microphone audio source with the same orientation as the camera
+ * if available, the main device microphone otherwise */
+#define SL_ANDROID_RECORDING_PRESET_CAMCORDER ((SLuint32) 0x00000002)
+/** uses the main microphone tuned for voice recognition */
+#define SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION ((SLuint32) 0x00000003)
+
+/*---------------------------------------------------------------------------*/
+/* Android AudioPlayer configuration */
+/*---------------------------------------------------------------------------*/
+
+/** Audio playback stream type */
+/** Audio playback stream type key */
+#define SL_ANDROID_KEY_STREAM_TYPE ((const SLchar*) "androidPlaybackStreamType")
+
+/** Audio playback stream type values */
+// FIXME remove comments in front of #define below once the SLAndroidStreamTypeItf interface is gone
+/* same as android.media.AudioManager.STREAM_VOICE_CALL */
+//#define SL_ANDROID_STREAM_VOICE ((SLint32) 0x00000000)
+/* same as android.media.AudioManager.STREAM_SYSTEM */
+//#define SL_ANDROID_STREAM_SYSTEM ((SLint32) 0x00000001)
+/* same as android.media.AudioManager.STREAM_RING */
+//#define SL_ANDROID_STREAM_RING ((SLint32) 0x00000002)
+/* same as android.media.AudioManager.STREAM_MUSIC */
+//#define SL_ANDROID_STREAM_MEDIA ((SLint32) 0x00000003)
+/* same as android.media.AudioManager.STREAM_ALARM */
+//#define SL_ANDROID_STREAM_ALARM ((SLint32) 0x00000004)
+/* same as android.media.AudioManager.STREAM_NOTIFICATION */
+//#define SL_ANDROID_STREAM_NOTIFICATION ((SLint32) 0x00000005)
+
+
+
+}
+#endif /* __cplusplus */
+
+#endif /* OPENSL_ES_ANDROIDCONFIGURATION_H_ */
SL_ENTER_INTERFACE
IAndroidConfiguration *this = (IAndroidConfiguration *) self;
+
interface_lock_exclusive(this);
- // route key configuration to the appropriate object
- // FIXME implement
-#if 0
- // is SLAndroidConfigurationItf on an AudioPlayer?
- CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
- (CAudioPlayer *) this->mThis : NULL;
-#endif
+#ifndef ANDROID
result = SL_RESULT_SUCCESS;
+#else
+ // route configuration to the appropriate object
+ if (SL_OBJECTID_AUDIORECORDER == IObjectToObjectID((this)->mThis)) {
+ SL_LOGV("SetConfiguration issued for AudioRecorder");
+ result = android_audioRecorder_setConfig((CAudioRecorder *) this->mThis, configKey,
+ pConfigValue, valueSize);
+ } else if (SL_OBJECTID_AUDIOPLAYER == IObjectToObjectID((this)->mThis)) {
+ SL_LOGV("SetConfiguration issued for AudioPlayer");
+ result = SL_RESULT_PARAMETER_INVALID;
+ } else if (SL_OBJECTID_OUTPUTMIX == IObjectToObjectID((this)->mThis)) {
+ SL_LOGV("SetConfiguration issued for OutputMix");
+ result = SL_RESULT_PARAMETER_INVALID;
+ }
+#endif
interface_unlock_exclusive(this);
{
SL_ENTER_INTERFACE
- if (NULL == configKey) {
+#ifndef ANDROID
+ result = SL_RESULT_SUCCESS;
+#else
+ if ((NULL == pValueSize) || (NULL == pConfigValue)) {
result = SL_RESULT_PARAMETER_INVALID;
} else {
IAndroidConfiguration *this = (IAndroidConfiguration *) self;
- interface_lock_shared(this);
- // route key configuration to the appropriate object
- // FIXME implement
- result = SL_RESULT_SUCCESS;
- interface_unlock_shared(this);
+ interface_lock_exclusive(this);
+
+ // route configuration request to the appropriate object
+ if (SL_OBJECTID_AUDIORECORDER == IObjectToObjectID((this)->mThis)) {
+ result = android_audioRecorder_getConfig((CAudioRecorder *) this->mThis, configKey,
+ pValueSize, pConfigValue);
+ } else if (SL_OBJECTID_AUDIOPLAYER == IObjectToObjectID((this)->mThis)) {
+ result = SL_RESULT_PARAMETER_INVALID;
+ } else if (SL_OBJECTID_OUTPUTMIX == IObjectToObjectID((this)->mThis)) {
+ result = SL_RESULT_PARAMETER_INVALID;
+ }
+
+ interface_unlock_exclusive(this);
}
+#endif
SL_LEAVE_INTERFACE
}
} else {
unsigned mask = 1 << index;
object_lock_exclusive(this);
- // Can't get interface on a suspended/suspending/resuming object
if (SL_OBJECT_STATE_REALIZED != this->mState) {
+ // Can't get interface on a suspended/suspending/resuming object
result = SL_RESULT_PRECONDITIONS_VIOLATED;
+
+ // unless this is an explicit + configuration interface,
+ // which will be checked here:
+
+ // FIXME: temporary hack to allow an interface to be called before it's
+ // object is realized
+ if (this->mInterfaceStates[index] == INTERFACE_EXPOSED) {
+ interface = (char *) this + class__->mInterfaces[index].mOffset;
+ if (!(this->mGottenMask & mask)) {
+ this->mGottenMask |= mask;
+ ((size_t *) interface)[0] ^= ~0;
+ }
+ result = SL_RESULT_SUCCESS;
+ }
+
} else {
switch (this->mInterfaceStates[index]) {
case INTERFACE_EXPOSED:
"Cannot create AudioRecorder: data source device type must be SL_IODEVICE_AUDIOINPUT"
#define ERROR_INPUT_ID_MUST_BE_DEFAULT \
"Cannot create AudioRecorder: data source device ID must be SL_DEFAULTDEVICEID_AUDIOINPUT"
+#define ERROR_UNKNOWN_KEY \
+ "Cannot set recording configuration: unknown key"
+#define ERROR_SET_UNKNOWN_PRESET \
+ "Cannot set recording preset: unknown preset"
+#define ERROR_VALUESIZE_TOO_LOW \
+ "Configuration error: value size too low to store valid value"
+#define ERROR_INVALID_SOURCE_FOR_VOICE_RECO \
+ "Cannot set recording preset to voice recognition: incompatible recording source"
+#define ERROR_AEC_UNSUPPORTED \
+ "Cannot change AEC setting: unsupported feature on this platform"
+#define ERROR_AGC_UNSUPPORTED \
+ "Cannot change AGC setting: unsupported feature on this platform"
+#define ERROR_NULL_PARAM \
+ "Configuration error: invalid NULL parameter"
+
+#define KEY_RECORDING_SOURCE_PARAMSIZE sizeof(SLuint32)
+#define KEY_RECORDING_PRESET_PARAMSIZE sizeof(SLuint32)
+
+//-----------------------------------------------------------------------------
+// Internal utility functions
+//----------------------------
+
+SLresult audioRecorder_setPreset(CAudioRecorder* ar, SLuint32 recordPreset) {
+ SLresult result = SL_RESULT_SUCCESS;
+
+ switch (recordPreset) {
+ case SL_ANDROID_RECORDING_PRESET_DEFAULT:
+ ar->mRecordSource = android::AUDIO_SOURCE_DEFAULT;
+ break;
+ case SL_ANDROID_RECORDING_PRESET_CAMCORDER:
+ ar->mRecordSource = android::AUDIO_SOURCE_CAMCORDER;
+ break;
+ case SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION:
+ ar->mRecordSource = android::AUDIO_SOURCE_VOICE_RECOGNITION;
+ break;
+ case SL_ANDROID_RECORDING_PRESET_NONE:
+ // it is an error to set preset "none"
+ default:
+ SL_LOGE(ERROR_SET_UNKNOWN_PRESET);
+ result = SL_RESULT_PARAMETER_INVALID;
+ }
+
+ return result;
+}
+
+
+SLresult audioRecorder_getPreset(CAudioRecorder* ar, SLuint32* pPreset) {
+ SLresult result = SL_RESULT_SUCCESS;
+
+ switch (ar->mRecordSource) {
+ case android::AUDIO_SOURCE_DEFAULT:
+ case android::AUDIO_SOURCE_MIC:
+ *pPreset = SL_ANDROID_RECORDING_PRESET_DEFAULT;
+ break;
+ case android::AUDIO_SOURCE_VOICE_UPLINK:
+ case android::AUDIO_SOURCE_VOICE_DOWNLINK:
+ case android::AUDIO_SOURCE_VOICE_CALL:
+ *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
+ break;
+ case android::AUDIO_SOURCE_VOICE_RECOGNITION:
+ *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
+ break;
+ case android::AUDIO_SOURCE_CAMCORDER:
+ *pPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
+ break;
+ default:
+ *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
+ result = SL_RESULT_INTERNAL_ERROR;
+ break;
+ }
+
+ return result;
+}
+
//-----------------------------------------------------------------------------
SLresult android_audioRecorder_checkSourceSinkSupport(CAudioRecorder* ar) {
SLresult result = SL_RESULT_SUCCESS;
ar->mAudioRecord = NULL;
+ ar->mRecordSource = android::AUDIO_SOURCE_DEFAULT;
+
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
+SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
+ const void *pConfigValue, SLuint32 valueSize) {
+
+ SLresult result = SL_RESULT_SUCCESS;
+
+ if (NULL == ar) {
+ result = SL_RESULT_INTERNAL_ERROR;
+ } else if (NULL == pConfigValue) {
+ SL_LOGE(ERROR_NULL_PARAM);
+ result = SL_RESULT_PARAMETER_INVALID;
+
+ } else if(strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
+
+ // recording preset
+ if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) {
+ SL_LOGE(ERROR_VALUESIZE_TOO_LOW);
+ result = SL_RESULT_PARAMETER_INVALID;
+ } else {
+ result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue);
+ }
+
+ } else {
+ SL_LOGE(ERROR_UNKNOWN_KEY);
+ result = SL_RESULT_PARAMETER_INVALID;
+ }
+
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
+SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
+ SLuint32* pValueSize, void *pConfigValue) {
+
+ SLresult result = SL_RESULT_SUCCESS;
+
+ if (NULL == ar) {
+ return SL_RESULT_INTERNAL_ERROR;
+ } else if ((NULL == pValueSize) || (NULL == pConfigValue)) {
+ SL_LOGE(ERROR_NULL_PARAM);
+ result = SL_RESULT_PARAMETER_INVALID;
+
+ } else if(strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
+
+ // recording preset
+ if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) {
+ SL_LOGE(ERROR_VALUESIZE_TOO_LOW);
+ result = SL_RESULT_PARAMETER_INVALID;
+ } else {
+ *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE;
+ result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue);
+ }
+
+ } else {
+ SL_LOGE(ERROR_UNKNOWN_KEY);
+ result = SL_RESULT_PARAMETER_INVALID;
+ }
return result;
}
// initialize platform-specific CAudioRecorder fields
ar->mAudioRecord = new android::AudioRecord();
- ar->mAudioRecord->set(android::AUDIO_SOURCE_DEFAULT, // source
+ ar->mAudioRecord->set(ar->mRecordSource, // source
sles_to_android_sampleRate(ar->mSampleRateMilliHz), // sample rate in Hertz
android::AudioSystem::PCM_16_BIT, //FIXME use format from buffer queue sink
sles_to_android_channelMask(ar->mNumChannels, 0 /*no channel mask*/), // channel config
extern SLresult android_audioRecorder_create(CAudioRecorder* ar);
+extern SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
+ const void *pConfigValue, SLuint32 valueSize);
+
+extern SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
+ SLuint32* pValueSize, void *pConfigValue);
+
extern SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async);
extern void android_audioRecorder_destroy(CAudioRecorder* ar);
#include <utils/Log.h>
#include <utils/KeyedVector.h>
#include "SLES/OpenSLES_Android.h"
+#include "SLES/OpenSLES_AndroidConfiguration.h"
#include "media/AudioSystem.h"
#include "media/mediarecorder.h"
#include "media/AudioRecord.h"
#define INTERFACE_ADDING_1A 11 ///< /part 1 of asynchronous AddInterface, aborted
#define INTERFACE_RESUMING_1A 12 ///< /part 1 of asynchronous ResumeInterface, aborted
+
// Maps an interface ID to its offset within the class that exposes it
struct iid_vtable {
// implementation-specific data for this instance
#ifdef ANDROID
android::AudioRecord *mAudioRecord;
+ int mRecordSource;
#endif
} /*CAudioRecorder*/;
LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES:= \
- system/media/opensles/include
+ system/media/opensles/include/SLES/
LOCAL_SRC_FILES:= \
slesTestRecBuffQueue.cpp
#include "OpenSLES.h"
#include "OpenSLES_Android.h"
+#include "OpenSLES_AndroidConfiguration.h"
-/* Explicitly requesting SL_IID_BUFFERQUEUE on the AudioRecorder object */
-#define NUM_EXPLICIT_INTERFACES_FOR_RECORDER 1
+/* Explicitly requesting SL_IID_BUFFERQUEUE and SL_IID_ANDROIDCONFIGURATION
+ * on the AudioRecorder object */
+#define NUM_EXPLICIT_INTERFACES_FOR_RECORDER 2
/* Size of the recording buffer queue */
#define NB_BUFFERS_IN_QUEUE 1
SLObjectItf recorder;
/* Interfaces for the audio recorder */
- SLBufferQueueItf recBuffQueueItf;
- SLRecordItf recordItf;
+ SLBufferQueueItf recBuffQueueItf;
+ SLRecordItf recordItf;
+ SLAndroidConfigurationItf configItf;
/* Source of audio data for the recording */
SLDataSource recSource;
/* ------------------------------------------------------ */
/* Configuration of the recorder */
- /* Request the BufferQueue interface */
+ /* Request the BufferQueue and AndroidConfiguration interfaces */
required[0] = SL_BOOLEAN_TRUE;
iidArray[0] = SL_IID_BUFFERQUEUE;
+ required[1] = SL_BOOLEAN_TRUE;
+ iidArray[1] = SL_IID_ANDROIDCONFIGURATION;
/* Setup the data source */
ioDevice.locatorType = SL_DATALOCATOR_IODEVICE;
recDest.pFormat = (void * ) &pcm;
/* Create the audio recorder */
- result = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recDest, 1,
- iidArray, required);
+ result = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recDest,
+ NUM_EXPLICIT_INTERFACES_FOR_RECORDER, iidArray, required);
ExitOnError(result);
fprintf(stdout, "Recorder created\n");
+ /* Get the Android configuration interface which is explicit */
+ result = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
+ ExitOnError(result);
+
+ /* Use the configuration interface to configure the recorder before it's realized */
+ SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
+ result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
+ &presetValue, sizeof(SLuint32));
+ ExitOnError(result);
+ fprintf(stdout, "Recorder parametrized\n");
+
+ presetValue = SL_ANDROID_RECORDING_PRESET_NONE;
+ SLuint32 presetSize = 2*sizeof(SLuint32); // intentionally too big
+ result = (*configItf)->GetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
+ &presetSize, (void*)&presetValue);
+ ExitOnError(result);
+ if (presetValue != SL_ANDROID_RECORDING_PRESET_CAMCORDER) {
+ fprintf(stderr, "Error retrieved recording preset\n");
+ ExitOnError(SL_RESULT_INTERNAL_ERROR);
+ }
+
/* Realize the recorder in synchronous mode. */
result = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE);
ExitOnError(result);