Change-Id: I2087417f9257dce66aa7f6317f1e629b96bb53bc
This commit is contained in:
2022-10-24 21:33:27 +08:00
parent 126cee10bd
commit 3e67015ab9
36 changed files with 19525 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
#
# Copyright 2014 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.
#
# This contains the module build definitions for the hardware-specific
# components for this device.
#
# As much as possible, those components should be built unconditionally,
# with device-specific names to avoid collisions, to avoid device-specific
# bitrot and build breakages. Building a component unconditionally does
# *not* include it on all devices, so it is safe even with hardware-specific
# components.
LOCAL_PATH := $(call my-dir)
# include $(call all-makefiles-under,$(LOCAL_PATH))
include $(CLEAR_VARS)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
#
# Copyright 2014 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.
#
# This contains the module build definitions for the hardware-specific
# components for this device.
#
# As much as possible, those components should be built unconditionally,
# with device-specific names to avoid collisions, to avoid device-specific
# bitrot and build breakages. Building a component unconditionally does
# *not* include it on all devices, so it is safe even with hardware-specific
# components.
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,28 @@
#
# Copyright 2014 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.
#
# This contains the module build definitions for the hardware-specific
# components for this device.
#
# As much as possible, those components should be built unconditionally,
# with device-specific names to avoid collisions, to avoid device-specific
# bitrot and build breakages. Building a component unconditionally does
# *not* include it on all devices, so it is safe even with hardware-specific
# components.
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,53 @@
ifeq ($(BOARD_USE_OFFLOAD_EFFECT),true)
LOCAL_PATH:= $(call my-dir)
# music nxp offload bundle wrapper
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
Bundle/exynos_effectbundle.cpp
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
$(LOCAL_PATH)/Bundle \
$(call include-path-for, audio-effects)
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_MODULE:= libhwnxpbundlewrapper
LOCAL_MODULE_RELATIVE_PATH := soundfx
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
libtinyalsa
include $(BUILD_SHARED_LIBRARY)
# music nxp offload reverb wrapper
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
Reverb/exynos_effectReverb.cpp
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_MODULE:= libhwnxpreverbwrapper
LOCAL_MODULE_RELATIVE_PATH := soundfx
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
libtinyalsa
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
$(LOCAL_PATH)/Reverb \
$(LOCAL_PATH)/Bundle \
$(call include-path-for, audio-effects)
include $(BUILD_SHARED_LIBRARY)
endif

View File

@@ -0,0 +1,628 @@
/*
* Copyright (C) 2004-2010 NXP Software
* 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.
*/
/****************************************************************************************/
/* */
/* Header file for the application layer interface of Concert Sound, Bass Enhancement, */
/* Equalizer, Power Spectrum Analyzer, Trebble Enhancement and volume management */
/* bundle. */
/* */
/* This files includes all definitions, types, structures and function */
/* prototypes required by the calling layer. All other types, structures and */
/* functions are private. */
/* */
/****************************************************************************************/
/* */
/* Note: 1 */
/* ======= */
/* The algorithm can execute either with separate input and output buffers or with */
/* a common buffer, i.e. the data is processed in-place. */
/* */
/****************************************************************************************/
/* */
/* Note: 2 */
/* ======= */
/* Three data formats are support Stereo,Mono-In-Stereo and Mono. The data is */
/* interleaved as follows: */
/* */
/* Byte Offset Stereo Input Mono-In-Stereo Input Mono Input */
/* =========== ============ ==================== ============== */
/* 0 Left Sample #1 Mono Sample #1 Mono Sample #1 */
/* 2 Right Sample #1 Mono Sample #1 Mono Sample #2 */
/* 4 Left Sample #2 Mono Sample #2 Mono Sample #3 */
/* 6 Right Sample #2 Mono Sample #2 Mono Sample #4 */
/* . . . . */
/* . . . . */
/* */
/****************************************************************************************/
#ifndef __LVM_H__
#define __LVM_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/****************************************************************************************/
/* */
/* Includes */
/* */
/****************************************************************************************/
#include "LVM_Types.h"
/****************************************************************************************/
/* */
/* Definitions */
/* */
/****************************************************************************************/
/* Memory table*/
#define LVM_NR_MEMORY_REGIONS 4 /* Number of memory regions */
/* Concert Sound effect level presets */
#define LVM_CS_EFFECT_NONE 0 /* 0% effect, minimum value */
#define LVM_CS_EFFECT_LOW 16384 /* 50% effect */
#define LVM_CS_EFFECT_MED 24576 /* 75% effect */
#define LVM_CS_EFFECT_HIGH 32767 /* 100% effect, maximum value */
/* Treble enhancement */
#define LVM_TE_LOW_MIPS 32767
/* Bass enhancement effect level presets */
#define LVM_BE_0DB 0 /* 0dB boost, no effect */
#define LVM_BE_3DB 3 /* +3dB boost */
#define LVM_BE_6DB 6 /* +6dB boost */
#define LVM_BE_9DB 9 /* +9dB boost */
#define LVM_BE_12DB 12 /* +12dB boost */
#define LVM_BE_15DB 15 /* +15dB boost */
/* N-Band Equalizer */
#define LVM_EQ_NBANDS 5 /* Number of bands for equalizer */
/* Headroom management */
#define LVM_HEADROOM_MAX_NBANDS 5
/****************************************************************************************/
/* */
/* Types */
/* */
/****************************************************************************************/
/* Instance handle */
typedef void *LVM_Handle_t;
/* Status return values */
typedef enum
{
LVM_SUCCESS = 0, /* Successful return from a routine */
LVM_ALIGNMENTERROR = 1, /* Memory alignment error */
LVM_NULLADDRESS = 2, /* NULL allocation address */
LVM_OUTOFRANGE = 3, /* Out of range control parameter */
LVM_INVALIDNUMSAMPLES = 4, /* Invalid number of samples */
LVM_WRONGAUDIOTIME = 5, /* Wrong time value for audio time*/
LVM_ALGORITHMDISABLED = 6, /* Algorithm is disabled*/
LVM_ALGORITHMPSA = 7, /* Algorithm PSA returns an error */
LVM_RETURNSTATUS_DUMMY = LVM_MAXENUM
} LVM_ReturnStatus_en;
/* Buffer Management mode */
typedef enum
{
LVM_MANAGED_BUFFERS = 0,
LVM_UNMANAGED_BUFFERS = 1,
LVM_BUFFERS_DUMMY = LVM_MAXENUM
} LVM_BufferMode_en;
/* Output device type */
typedef enum
{
LVM_HEADPHONES = 0,
LVM_EX_HEADPHONES = 1,
LVM_SPEAKERTYPE_MAX = LVM_MAXENUM
} LVM_OutputDeviceType_en;
/* Virtualizer mode selection*/
typedef enum
{
LVM_CONCERTSOUND = 0,
LVM_VIRTUALIZERTYPE_DUMMY = LVM_MAXENUM
} LVM_VirtualizerType_en;
/* N-Band Equaliser operating mode */
typedef enum
{
LVM_EQNB_OFF = 0,
LVM_EQNB_ON = 1,
LVM_EQNB_DUMMY = LVM_MAXENUM
} LVM_EQNB_Mode_en;
/* Bass Enhancement operating mode */
typedef enum
{
LVM_BE_OFF = 0,
LVM_BE_ON = 1,
LVM_BE_DUMMY = LVM_MAXENUM
} LVM_BE_Mode_en;
/* Bass Enhancement centre frequency selection control */
typedef enum
{
LVM_BE_CENTRE_55Hz = 0,
LVM_BE_CENTRE_66Hz = 1,
LVM_BE_CENTRE_78Hz = 2,
LVM_BE_CENTRE_90Hz = 3,
LVM_BE_CENTRE_DUMMY = LVM_MAXENUM
} LVM_BE_CentreFreq_en;
/* Bass Enhancement HPF selection control */
typedef enum
{
LVM_BE_HPF_OFF = 0,
LVM_BE_HPF_ON = 1,
LVM_BE_HPF_DUMMY = LVM_MAXENUM
} LVM_BE_FilterSelect_en;
/* Volume Control operating mode */
typedef enum
{
LVM_VC_OFF = 0,
LVM_VC_ON = 1,
LVM_VC_DUMMY = LVM_MAXENUM
} LVM_VC_Mode_en;
/* Treble Enhancement operating mode */
typedef enum
{
LVM_TE_OFF = 0,
LVM_TE_ON = 1,
LVM_TE_DUMMY = LVM_MAXENUM
} LVM_TE_Mode_en;
/* Headroom management operating mode */
typedef enum
{
LVM_HEADROOM_OFF = 0,
LVM_HEADROOM_ON = 1,
LVM_Headroom_DUMMY = LVM_MAXENUM
} LVM_Headroom_Mode_en;
typedef enum
{
LVM_PSA_SPEED_SLOW, /* Peak decaying at slow speed */
LVM_PSA_SPEED_MEDIUM, /* Peak decaying at medium speed */
LVM_PSA_SPEED_FAST, /* Peak decaying at fast speed */
LVM_PSA_SPEED_DUMMY = LVM_MAXENUM
} LVM_PSA_DecaySpeed_en;
typedef enum
{
LVM_PSA_OFF = 0,
LVM_PSA_ON = 1,
LVM_PSA_DUMMY = LVM_MAXENUM
} LVM_PSA_Mode_en;
/* Version information */
typedef struct
{
LVM_CHAR *pVersionNumber; /* Pointer to the version number in the format X.YY.ZZ */
LVM_CHAR *pPlatform; /* Pointer to the library platform type */
} LVM_VersionInfo_st;
/****************************************************************************************/
/* */
/* Structures */
/* */
/****************************************************************************************/
/* Memory table containing the region definitions */
typedef struct
{
LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */
} LVM_MemTab_t;
/* N-Band equaliser band definition */
typedef struct
{
LVM_INT16 Gain; /* Band gain in dB */
LVM_UINT16 Frequency; /* Band centre frequency in Hz */
LVM_UINT16 QFactor; /* Band quality factor (x100) */
} LVM_EQNB_BandDef_t;
/* Headroom band definition */
typedef struct
{
LVM_UINT16 Limit_Low; /* Low frequency limit of the band in Hertz */
LVM_UINT16 Limit_High; /* High frequency limit of the band in Hertz */
LVM_INT16 Headroom_Offset; /* Headroom = biggest band gain - Headroom_Offset */
} LVM_HeadroomBandDef_t;
/* Control Parameter structure */
typedef struct
{
/* General parameters */
LVM_Mode_en OperatingMode; /* Bundle operating mode On/Bypass */
LVM_Fs_en SampleRate; /* Sample rate */
LVM_Format_en SourceFormat; /* Input data format */
LVM_OutputDeviceType_en SpeakerType; /* Output device type */
/* Concert Sound Virtualizer parameters*/
LVM_Mode_en VirtualizerOperatingMode; /* Virtualizer operating mode On/Off */
LVM_VirtualizerType_en VirtualizerType; /* Virtualizer type: ConcertSound */
LVM_UINT16 VirtualizerReverbLevel; /* Virtualizer reverb level in % */
LVM_INT16 CS_EffectLevel; /* Concert Sound effect level */
/* N-Band Equaliser parameters */
LVM_EQNB_Mode_en EQNB_OperatingMode; /* N-Band Equaliser operating mode */
LVM_UINT16 EQNB_NBands; /* Number of bands */
LVM_EQNB_BandDef_t *pEQNB_BandDefinition; /* Pointer to equaliser definitions */
/* Bass Enhancement parameters */
LVM_BE_Mode_en BE_OperatingMode; /* Bass Enhancement operating mode */
LVM_INT16 BE_EffectLevel; /* Bass Enhancement effect level */
LVM_BE_CentreFreq_en BE_CentreFreq; /* Bass Enhancement centre frequency */
LVM_BE_FilterSelect_en BE_HPF; /* Bass Enhancement high pass filter selector */
/* Volume Control parameters */
LVM_INT16 VC_EffectLevel; /* Volume Control setting in dBs */
LVM_INT16 VC_Balance; /* Left Right Balance control in dB (-96 to 96 dB), -ve values reduce
Right channel while +ve value reduces Left channel*/
/* Treble Enhancement parameters */
LVM_TE_Mode_en TE_OperatingMode; /* Treble Enhancement On/Off */
LVM_INT16 TE_EffectLevel; /* Treble Enhancement gain dBs */
/* Spectrum Analyzer parameters Control */
LVM_PSA_Mode_en PSA_Enable;
LVM_PSA_DecaySpeed_en PSA_PeakDecayRate; /* Peak value decay rate*/
} LVM_ControlParams_t;
/* Instance Parameter structure */
typedef struct
{
/* General */
LVM_BufferMode_en BufferMode; /* Buffer management mode */
LVM_UINT16 MaxBlockSize; /* Maximum processing block size */
/* N-Band Equaliser */
LVM_UINT16 EQNB_NumBands; /* Maximum number of equaliser bands */
/* PSA */
LVM_PSA_Mode_en PSA_Included; /* Controls the instance memory allocation for PSA: ON/OFF */
} LVM_InstParams_t;
/* Headroom management parameter structure */
typedef struct
{
LVM_Headroom_Mode_en Headroom_OperatingMode; /* Headroom Control On/Off */
LVM_HeadroomBandDef_t *pHeadroomDefinition; /* Pointer to headroom bands definition */
LVM_UINT16 NHeadroomBands; /* Number of headroom bands */
} LVM_HeadroomParams_t;
/****************************************************************************************/
/* */
/* Function Prototypes */
/* */
/****************************************************************************************/
/****************************************************************************************/
/* */
/* FUNCTION: LVM_GetVersionInfo */
/* */
/* DESCRIPTION: */
/* This function is used to retrieve information about the library's version. */
/* */
/* PARAMETERS: */
/* pVersion Pointer to an empty version info structure */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS when pVersion is NULL */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st *pVersion);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_GetMemoryTable */
/* */
/* DESCRIPTION: */
/* This function is used for memory allocation and free. It can be called in */
/* two ways: */
/* */
/* hInstance = NULL Returns the memory requirements */
/* hInstance = Instance handle Returns the memory requirements and */
/* allocated base addresses for the instance */
/* */
/* When this function is called for memory allocation (hInstance=NULL) the memory */
/* base address pointers are NULL on return. */
/* */
/* When the function is called for free (hInstance = Instance Handle) the memory */
/* table returns the allocated memory and base addresses used during initialisation. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pMemoryTable Pointer to an empty memory definition table */
/* pInstParams Pointer to the instance parameters */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS When one of pMemoryTable or pInstParams is NULL */
/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t hInstance,
LVM_MemTab_t *pMemoryTable,
LVM_InstParams_t *pInstParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_GetInstanceHandle */
/* */
/* DESCRIPTION: */
/* This function is used to create a bundle instance. It returns the created instance */
/* handle through phInstance. All parameters are set to their default, inactive state. */
/* */
/* PARAMETERS: */
/* phInstance pointer to the instance handle */
/* pMemoryTable Pointer to the memory definition table */
/* pInstParams Pointer to the instance parameters */
/* */
/* RETURNS: */
/* LVM_SUCCESS Initialisation succeeded */
/* LVM_NULLADDRESS One or more memory has a NULL pointer */
/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */
/* */
/* NOTES: */
/* 1. This function must not be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t *phInstance,
LVM_MemTab_t *pMemoryTable,
LVM_InstParams_t *pInstParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_ClearAudioBuffers */
/* */
/* DESCRIPTION: */
/* This function is used to clear the internal audio buffers of the bundle. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* */
/* RETURNS: */
/* LVM_SUCCESS Initialisation succeeded */
/* LVM_NULLADDRESS Instance memory has a NULL pointer */
/* */
/* NOTES: */
/* 1. This function must not be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t hInstance);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_GetControlParameters */
/* */
/* DESCRIPTION: */
/* Request the LifeVibes module parameters. The current parameter set is returned */
/* via the parameter pointer. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* pParams Pointer to an empty parameter structure */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS when any of hInstance or pParams is NULL */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t hInstance,
LVM_ControlParams_t *pParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_SetControlParameters */
/* */
/* DESCRIPTION: */
/* Sets or changes the LifeVibes module parameters. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* pParams Pointer to a parameter structure */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS When hInstance, pParams or any control pointers are NULL */
/* LVM_OUTOFRANGE When any of the control parameters are out of range */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance,
LVM_ControlParams_t *pParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_Process */
/* */
/* DESCRIPTION: */
/* Process function for the LifeVibes module. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* pInData Pointer to the input data */
/* pOutData Pointer to the output data */
/* NumSamples Number of samples in the input buffer */
/* AudioTime Audio Time of the current input data in milli-seconds */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_INVALIDNUMSAMPLES When the NumSamples is not a valied multiple in unmanaged */
/* buffer mode */
/* LVM_ALIGNMENTERROR When either the input our output buffers are not 32-bit */
/* aligned in unmanaged mode */
/* LVM_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
/* */
/* NOTES: */
/* 1. The input and output buffers must be 32-bit aligned */
/* 2. Number of samples is defined as follows: */
/* MONO the number of samples in the block */
/* MONOINSTEREO the number of sample pairs in the block */
/* STEREO the number of sample pairs in the block */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance,
const LVM_INT16 *pInData,
LVM_INT16 *pOutData,
LVM_UINT16 NumSamples,
LVM_UINT32 AudioTime);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_SetHeadroomParams */
/* */
/* DESCRIPTION: */
/* This function is used to set the automatic headroom management parameters. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pHeadroomParams Pointer to headroom parameter structure */
/* */
/* RETURNS: */
/* LVM_NULLADDRESS When hInstance or pHeadroomParams is NULL */
/* LVM_SUCCESS Succeeded */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_SetHeadroomParams( LVM_Handle_t hInstance,
LVM_HeadroomParams_t *pHeadroomParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_GetHeadroomParams */
/* */
/* DESCRIPTION: */
/* This function is used to get the automatic headroom management parameters. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pHeadroomParams Pointer to headroom parameter structure (output) */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS When hInstance or pHeadroomParams are NULL */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_GetHeadroomParams( LVM_Handle_t hInstance,
LVM_HeadroomParams_t *pHeadroomParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_GetSpectrum */
/* */
/* DESCRIPTION: */
/* This function is used to retrieve Spectral information at a given Audio time */
/* for display usage */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pCurrentPeaks Pointer to location where currents peaks are to be saved */
/* pPastPeaks Pointer to location where past peaks are to be saved */
/* pCentreFreqs Pointer to location where centre frequency of each band is */
/* to be saved */
/* AudioTime Audio time at which the spectral information is needed */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS If any of input addresses are NULL */
/* LVM_WRONGAUDIOTIME Failure due to audio time error */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_GetSpectrum( LVM_Handle_t hInstance,
LVM_UINT8 *pCurrentPeaks,
LVM_UINT8 *pPastPeaks,
LVM_INT32 AudioTime);
/****************************************************************************************/
/* */
/* FUNCTION: LVM_SetVolumeNoSmoothing */
/* */
/* DESCRIPTION: */
/* This function is used to set output volume without any smoothing */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pParams Control Parameters, only volume value is used here */
/* */
/* RETURNS: */
/* LVM_SUCCESS Succeeded */
/* LVM_NULLADDRESS If any of input addresses are NULL */
/* LVM_OUTOFRANGE When any of the control parameters are out of range */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVM_Process function */
/* */
/****************************************************************************************/
LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t hInstance,
LVM_ControlParams_t *pParams);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __LVM_H__ */

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2004-2010 NXP Software
* 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.
*/
/****************************************************************************************/
/* */
/* Header file defining the standard LifeVibes types for use in the application layer */
/* interface of all LifeVibes modules */
/* */
/****************************************************************************************/
#ifndef LVM_TYPES_H
#define LVM_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdint.h>
/****************************************************************************************/
/* */
/* definitions */
/* */
/****************************************************************************************/
#define LVM_NULL 0 /* NULL pointer */
#define LVM_TRUE 1 /* Booleans */
#define LVM_FALSE 0
#define LVM_MAXINT_8 127 /* Maximum positive integer size */
#define LVM_MAXINT_16 32767
#define LVM_MAXINT_32 2147483647
#define LVM_MAXENUM 2147483647
#define LVM_MODULEID_MASK 0xFF00 /* Mask to extract the calling module ID from callbackId */
#define LVM_EVENTID_MASK 0x00FF /* Mask to extract the callback event from callbackId */
/* Memory table*/
#define LVM_MEMREGION_PERSISTENT_SLOW_DATA 0 /* Offset to the instance memory region */
#define LVM_MEMREGION_PERSISTENT_FAST_DATA 1 /* Offset to the persistent data memory region */
#define LVM_MEMREGION_PERSISTENT_FAST_COEF 2 /* Offset to the persistent coefficient memory region */
#define LVM_MEMREGION_TEMPORARY_FAST 3 /* Offset to temporary memory region */
#define LVM_NR_MEMORY_REGIONS 4 /* Number of memory regions */
/* Memory partition type */
#define LVM_MEM_PARTITION0 0 /* 1st memory partition */
#define LVM_MEM_PARTITION1 1 /* 2nd memory partition */
#define LVM_MEM_PARTITION2 2 /* 3rd memory partition */
#define LVM_MEM_PARTITION3 3 /* 4th memory partition */
/* Use type */
#define LVM_MEM_PERSISTENT 0 /* Persistent memory type */
#define LVM_MEM_SCRATCH 4 /* Scratch memory type */
/* Access type */
#define LVM_MEM_INTERNAL 0 /* Internal (fast) access memory */
#define LVM_MEM_EXTERNAL 8 /* External (slow) access memory */
/* Platform specific */
#define LVM_PERSISTENT LVM_MEM_PARTITION0+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
#define LVM_PERSISTENT_DATA LVM_MEM_PARTITION1+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
#define LVM_PERSISTENT_COEF LVM_MEM_PARTITION2+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
#define LVM_SCRATCH LVM_MEM_PARTITION3+LVM_MEM_SCRATCH+LVM_MEM_INTERNAL
/****************************************************************************************/
/* */
/* Basic types */
/* */
/****************************************************************************************/
typedef char LVM_CHAR; /* ASCII character */
typedef int8_t LVM_INT8; /* Signed 8-bit word */
typedef uint8_t LVM_UINT8; /* Unsigned 8-bit word */
typedef int16_t LVM_INT16; /* Signed 16-bit word */
typedef uint16_t LVM_UINT16; /* Unsigned 16-bit word */
typedef int32_t LVM_INT32; /* Signed 32-bit word */
typedef uint32_t LVM_UINT32; /* Unsigned 32-bit word */
/****************************************************************************************/
/* */
/* Standard Enumerated types */
/* */
/****************************************************************************************/
/* Operating mode */
typedef enum
{
LVM_MODE_OFF = 0,
LVM_MODE_ON = 1,
LVM_MODE_DUMMY = LVM_MAXENUM
} LVM_Mode_en;
/* Format */
typedef enum
{
LVM_STEREO = 0,
LVM_MONOINSTEREO = 1,
LVM_MONO = 2,
LVM_SOURCE_DUMMY = LVM_MAXENUM
} LVM_Format_en;
/* LVM sampling rates */
typedef enum
{
LVM_FS_8000 = 0,
LVM_FS_11025 = 1,
LVM_FS_12000 = 2,
LVM_FS_16000 = 3,
LVM_FS_22050 = 4,
LVM_FS_24000 = 5,
LVM_FS_32000 = 6,
LVM_FS_44100 = 7,
LVM_FS_48000 = 8,
LVM_FS_INVALID = LVM_MAXENUM-1,
LVM_FS_DUMMY = LVM_MAXENUM
} LVM_Fs_en;
/* Memory Types */
typedef enum
{
LVM_PERSISTENT_SLOW_DATA = LVM_MEMREGION_PERSISTENT_SLOW_DATA,
LVM_PERSISTENT_FAST_DATA = LVM_MEMREGION_PERSISTENT_FAST_DATA,
LVM_PERSISTENT_FAST_COEF = LVM_MEMREGION_PERSISTENT_FAST_COEF,
LVM_TEMPORARY_FAST = LVM_MEMREGION_TEMPORARY_FAST,
LVM_MEMORYTYPE_DUMMY = LVM_MAXENUM
} LVM_MemoryTypes_en;
/* Memory region definition */
typedef struct
{
LVM_UINT32 Size; /* Region size in bytes */
LVM_MemoryTypes_en Type; /* Region type */
void *pBaseAddress; /* Pointer to the region base address */
} LVM_MemoryRegion_st;
/* Memory table containing the region definitions */
typedef struct
{
LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */
} LVM_MemoryTable_st;
/****************************************************************************************/
/* */
/* Standard Function Prototypes */
/* */
/****************************************************************************************/
typedef LVM_INT32 (*LVM_Callback)(void *pCallbackData, /* Pointer to the callback data structure */
void *pGeneralPurpose, /* General purpose pointer (e.g. to a data structure needed in the callback) */
LVM_INT16 GeneralPurpose ); /* General purpose variable (e.g. to be used as callback ID) */
/****************************************************************************************/
/* */
/* End of file */
/* */
/****************************************************************************************/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LVM_TYPES_H */

View File

@@ -0,0 +1,227 @@
/*
* 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 ANDROID_EFFECTBUNDLE_H_
#define ANDROID_EFFECTBUNDLE_H_
#include <audio_effects/effect_bassboost.h>
#include <audio_effects/effect_equalizer.h>
#include <audio_effects/effect_virtualizer.h>
#include <LVM.h>
#include <limits.h>
#include <tinyalsa/asoundlib.h>
#if __cplusplus
extern "C" {
#endif
#define FIVEBAND_NUMBANDS 5
#define MAX_NUM_BANDS 5
#define MAX_CALL_SIZE 256
#define LVM_MAX_SESSIONS 32
#define LVM_UNUSED_SESSION INT_MAX
#define BASS_BOOST_CUP_LOAD_ARM9E 150 // Expressed in 0.1 MIPS
#define VIRTUALIZER_CUP_LOAD_ARM9E 120 // Expressed in 0.1 MIPS
#define EQUALIZER_CUP_LOAD_ARM9E 220 // Expressed in 0.1 MIPS
#define VOLUME_CUP_LOAD_ARM9E 0 // Expressed in 0.1 MIPS
#define BUNDLE_MEM_USAGE 25 // Expressed in kB
//#define LVM_PCM
#ifndef OPENSL_ES_H_
static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
{ 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
#endif //OPENSL_ES_H_
typedef enum
{
LVM_BASS_BOOST,
LVM_VIRTUALIZER,
LVM_EQUALIZER,
LVM_VOLUME
} lvm_effect_en;
// Preset configuration.
struct PresetConfig {
// Human-readable name.
const char * name;
// An array of size nBands where each element is a configuration for the
// corresponding band.
//const BandConfig * bandConfigs;
};
/* BundledEffectContext : One per session */
struct BundledEffectContext{
LVM_Handle_t hInstance; /* Instance handle */
int SessionNo; /* Current session number */
int SessionId; /* Current session id */
bool bVolumeEnabled; /* Flag for Volume */
bool bEqualizerEnabled; /* Flag for EQ */
bool bBassEnabled; /* Flag for Bass */
bool bBassTempDisabled; /* Flag for Bass to be re-enabled */
bool bVirtualizerEnabled; /* Flag for Virtualizer */
bool bVirtualizerTempDisabled; /* Flag for effect to be re-enabled */
audio_devices_t nOutputDevice; /* Output device for the effect */
audio_devices_t nVirtualizerForcedDevice; /* Forced device virtualization mode*/
int NumberEffectsEnabled; /* Effects in this session */
int NumberEffectsCalled; /* Effects called so far */
bool firstVolume; /* No smoothing on first Vol change */
// Saved parameters for each effect */
// Bass Boost
int BassStrengthSaved; /* Conversion between Get/Set */
// Equalizer
int CurPreset; /* Current preset being used */
// Virtualzer
int VirtStrengthSaved; /* Conversion between Get/Set */
// Volume
int levelSaved; /* for when mute is set, level must be saved */
int positionSaved;
bool bMuteEnabled; /* Must store as mute = -96dB level */
bool bStereoPositionEnabled;
LVM_Fs_en SampleRate;
int SamplesPerSecond;
int SamplesToExitCountEq;
int SamplesToExitCountBb;
int SamplesToExitCountVirt;
LVM_INT16 *workBuffer;
int frameCount;
int32_t bandGaindB[FIVEBAND_NUMBANDS];
int volume;
#ifdef LVM_PCM
FILE *PcmInPtr;
FILE *PcmOutPtr;
#endif
LVM_ControlParams_t ActiveParams;
struct mixer *mixerHandle;
struct mixer_ctl *mixerCtl;
/* output io-handle to which the effect is attached to */
audio_io_handle_t OutHandle;
bool OffloadEnabled;
};
/* SessionContext : One session */
struct SessionContext{
bool bBundledEffectsEnabled;
bool bVolumeInstantiated;
bool bEqualizerInstantiated;
bool bBassInstantiated;
bool bVirtualizerInstantiated;
BundledEffectContext *pBundledContext;
};
struct EffectContext{
const struct effect_interface_s *itfe;
effect_config_t config;
lvm_effect_en EffectType;
BundledEffectContext *pBundledContext;
};
/* enumerated parameter settings for Volume effect */
typedef enum
{
VOLUME_PARAM_LEVEL, // type SLmillibel = typedef SLuint16 (set & get)
VOLUME_PARAM_MAXLEVEL, // type SLmillibel = typedef SLuint16 (get)
VOLUME_PARAM_MUTE, // type SLboolean = typedef SLuint32 (set & get)
VOLUME_PARAM_ENABLESTEREOPOSITION, // type SLboolean = typedef SLuint32 (set & get)
VOLUME_PARAM_STEREOPOSITION, // type SLpermille = typedef SLuint16 (set & get)
} t_volume_params;
static const int PRESET_CUSTOM = -1;
static const uint32_t bandFreqRange[FIVEBAND_NUMBANDS][2] = {
{30000, 120000},
{120001, 460000},
{460001, 1800000},
{1800001, 7000000},
{7000001, 1}};
//Note: If these frequencies change, please update LimitLevel values accordingly.
static const LVM_UINT16 EQNB_5BandPresetsFrequencies[] = {
60, /* Frequencies in Hz */
230,
910,
3600,
14000};
static const LVM_UINT16 EQNB_5BandPresetsQFactors[] = {
96, /* Q factor multiplied by 100 */
96,
96,
96,
96};
static const LVM_INT16 EQNB_5BandNormalPresets[] = {
3, 0, 0, 0, 3, /* Normal Preset */
8, 5, -3, 5, 6, /* Classical Preset */
15, -6, 7, 13, 10, /* Dance Preset */
0, 0, 0, 0, 0, /* Flat Preset */
6, -2, -2, 6, -3, /* Folk Preset */
8, -8, 13, -1, -4, /* Heavy Metal Preset */
10, 6, -4, 5, 8, /* Hip Hop Preset */
8, 5, -4, 5, 9, /* Jazz Preset */
-6, 4, 9, 4, -5, /* Pop Preset */
10, 6, -1, 8, 10}; /* Rock Preset */
static const LVM_INT16 EQNB_5BandSoftPresets[] = {
3, 0, 0, 0, 3, /* Normal Preset */
5, 3, -2, 4, 4, /* Classical Preset */
6, 0, 2, 4, 1, /* Dance Preset */
0, 0, 0, 0, 0, /* Flat Preset */
3, 0, 0, 2, -1, /* Folk Preset */
4, 1, 9, 3, 0, /* Heavy Metal Preset */
5, 3, 0, 1, 3, /* Hip Hop Preset */
4, 2, -2, 2, 5, /* Jazz Preset */
-1, 2, 5, 1, -2, /* Pop Preset */
5, 3, -1, 3, 5}; /* Rock Preset */
static const PresetConfig gEqualizerPresets[] = {
{"Normal"},
{"Classical"},
{"Dance"},
{"Flat"},
{"Folk"},
{"Heavy Metal"},
{"Hip Hop"},
{"Jazz"},
{"Pop"},
{"Rock"}};
/* The following tables have been computed using the actual levels measured by the output of
* white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
* the actual energy that 'could' be present in the given band.
* If the frequency values in EQNB_5BandPresetsFrequencies change, these values might need to be
* updated.
*/
static const float LimitLevel_bandEnergyCoefficient[FIVEBAND_NUMBANDS] = {
7.56, 9.69, 9.59, 7.37, 2.88};
static const float LimitLevel_bandEnergyCrossCoefficient[FIVEBAND_NUMBANDS-1] = {
126.0, 115.0, 125.0, 104.0 };
static const float LimitLevel_bassBoostEnergyCrossCoefficient[FIVEBAND_NUMBANDS] = {
221.21, 208.10, 28.16, 0.0, 0.0 };
static const float LimitLevel_bassBoostEnergyCoefficient = 7.12;
static const float LimitLevel_virtualizerContribution = 1.9;
#if __cplusplus
} // extern "C"
#endif
#endif /*ANDROID_EFFECTBUNDLE_H_*/

View File

@@ -0,0 +1,190 @@
Copyright (c) 2005-2008, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@@ -0,0 +1,312 @@
/*
* Copyright (C) 2004-2010 NXP Software
* 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.
*/
/****************************************************************************************/
/* */
/* Header file for the application layer interface of the LVREV module */
/* */
/* This files includes all definitions, types, structures and function prototypes */
/* required by the calling layer. All other types, structures and functions are */
/* private. */
/* */
/****************************************************************************************/
#ifndef __LVREV_H__
#define __LVREV_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/****************************************************************************************/
/* */
/* Includes */
/* */
/****************************************************************************************/
#include "LVM_Types.h"
/****************************************************************************************/
/* */
/* Definitions */
/* */
/****************************************************************************************/
/* General */
#define LVREV_BLOCKSIZE_MULTIPLE 1 /* Processing block size multiple */
#define LVREV_MAX_T60 7000 /* Maximum decay time is 7000ms */
/* Memory table*/
#define LVREV_NR_MEMORY_REGIONS 4 /* Number of memory regions */
/****************************************************************************************/
/* */
/* Types */
/* */
/****************************************************************************************/
/* Instance handle */
typedef void *LVREV_Handle_t;
/* Status return values */
typedef enum
{
LVREV_SUCCESS = 0, /* Successful return from a routine */
LVREV_NULLADDRESS = 1, /* NULL allocation address */
LVREV_OUTOFRANGE = 2, /* Out of range control parameter */
LVREV_INVALIDNUMSAMPLES = 3, /* Invalid number of samples */
LVREV_RETURNSTATUS_DUMMY = LVM_MAXENUM
} LVREV_ReturnStatus_en;
/* Reverb delay lines */
typedef enum
{
LVREV_DELAYLINES_1 = 1, /* One delay line */
LVREV_DELAYLINES_2 = 2, /* Two delay lines */
LVREV_DELAYLINES_4 = 4, /* Four delay lines */
LVREV_DELAYLINES_DUMMY = LVM_MAXENUM
} LVREV_NumDelayLines_en;
/****************************************************************************************/
/* */
/* Structures */
/* */
/****************************************************************************************/
/* Memory table containing the region definitions */
typedef struct
{
LVM_MemoryRegion_st Region[LVREV_NR_MEMORY_REGIONS]; /* One definition for each region */
} LVREV_MemoryTable_st;
/* Control Parameter structure */
typedef struct
{
/* General parameters */
LVM_Mode_en OperatingMode; /* Operating mode */
LVM_Fs_en SampleRate; /* Sample rate */
LVM_Format_en SourceFormat; /* Source data format */
/* Parameters for REV */
LVM_UINT16 Level; /* Level, 0 to 100 representing percentage of reverb */
LVM_UINT16 LPF; /* Low pass filter, in Hz */
LVM_UINT16 HPF; /* High pass filter, in Hz */
LVM_UINT16 T60; /* Decay time constant, in ms */
LVM_UINT16 Density; /* Echo density, 0 to 100 for minimum to maximum density */
LVM_UINT16 Damping; /* Damping */
LVM_UINT16 RoomSize; /* Simulated room size, 1 to 100 for minimum to maximum size */
} LVREV_ControlParams_st;
/* Instance Parameter structure */
typedef struct
{
/* General */
LVM_UINT16 MaxBlockSize; /* Maximum processing block size */
/* Reverb */
LVM_Format_en SourceFormat; /* Source data formats to support */
LVREV_NumDelayLines_en NumDelays; /* The number of delay lines, 1, 2 or 4 */
} LVREV_InstanceParams_st;
/****************************************************************************************/
/* */
/* Function Prototypes */
/* */
/****************************************************************************************/
/****************************************************************************************/
/* */
/* FUNCTION: LVREV_GetMemoryTable */
/* */
/* DESCRIPTION: */
/* This function is used to obtain the LVREV module memory requirements to support */
/* memory allocation. It can also be used to return the memory base address provided */
/* during memory allocation to support freeing of memory when the LVREV module is no */
/* longer required. It is called in two ways: */
/* */
/* hInstance = NULL Returns the memory requirements */
/* hInstance = Instance handle Returns the memory requirements and allocated */
/* base addresses. */
/* */
/* When this function is called with hInstance = NULL the memory base address pointers */
/* will be NULL on return. */
/* */
/* When the function is called for freeing memory, hInstance = Instance Handle the */
/* memory table returns the allocated memory and base addresses used during */
/* initialisation. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pMemoryTable Pointer to an empty memory table */
/* pInstanceParams Pointer to the instance parameters */
/* */
/* RETURNS: */
/* LVREV_SUCCESS Succeeded */
/* LVREV_NULLADDRESS When pMemoryTable is NULL */
/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
/* is NULL */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVREV_Process function */
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
LVREV_MemoryTable_st *pMemoryTable,
LVREV_InstanceParams_st *pInstanceParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVREV_GetInstanceHandle */
/* */
/* DESCRIPTION: */
/* This function is used to create a LVREV module instance. It returns the created */
/* instance handle through phInstance. All parameters are set to invalid values, the */
/* LVREV_SetControlParameters function must be called with a set of valid control */
/* parameters before the LVREV_Process function can be called. */
/* */
/* The memory allocation must be provided by the application by filling in the memory */
/* region base addresses in the memory table before calling this function. */
/* */
/* PARAMETERS: */
/* phInstance Pointer to the instance handle */
/* pMemoryTable Pointer to the memory definition table */
/* pInstanceParams Pointer to the instance parameters */
/* */
/* RETURNS: */
/* LVREV_SUCCESS Succeeded */
/* LVREV_NULLADDRESS When phInstance or pMemoryTable or pInstanceParams is NULL */
/* LVREV_NULLADDRESS When one of the memory regions has a NULL pointer */
/* */
/* NOTES: */
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t *phInstance,
LVREV_MemoryTable_st *pMemoryTable,
LVREV_InstanceParams_st *pInstanceParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVXX_GetControlParameters */
/* */
/* DESCRIPTION: */
/* Request the LVREV module control parameters. The current parameter set is returned */
/* via the parameter pointer. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* pControlParams Pointer to an empty parameter structure */
/* */
/* RETURNS: */
/* LVREV_SUCCESS Succeeded */
/* LVREV_NULLADDRESS When hInstance or pControlParams is NULL */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVREV_Process function */
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t hInstance,
LVREV_ControlParams_st *pControlParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVREV_SetControlParameters */
/* */
/* DESCRIPTION: */
/* Sets or changes the LVREV module parameters. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* pNewParams Pointer to a parameter structure */
/* */
/* RETURNS: */
/* LVREV_SUCCESS Succeeded */
/* LVREV_NULLADDRESS When hInstance or pNewParams is NULL */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVREV_Process function */
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t hInstance,
LVREV_ControlParams_st *pNewParams);
/****************************************************************************************/
/* */
/* FUNCTION: LVREV_ClearAudioBuffers */
/* */
/* DESCRIPTION: */
/* This function is used to clear the internal audio buffers of the module. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* */
/* RETURNS: */
/* LVREV_SUCCESS Initialisation succeeded */
/* LVREV_NULLADDRESS Instance is NULL */
/* */
/* NOTES: */
/* 1. This function must not be interrupted by the LVREV_Process function */
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t hInstance);
/****************************************************************************************/
/* */
/* FUNCTION: LVREV_Process */
/* */
/* DESCRIPTION: */
/* Process function for the LVREV module. */
/* */
/* PARAMETERS: */
/* hInstance Instance handle */
/* pInData Pointer to the input data */
/* pOutData Pointer to the output data */
/* NumSamples Number of samples in the input buffer */
/* */
/* RETURNS: */
/* LVREV_SUCCESS Succeeded */
/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
/* */
/* NOTES: */
/* 1. The input and output buffers must be 32-bit aligned */
/* */
/****************************************************************************************/
LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance,
const LVM_INT32 *pInData,
LVM_INT32 *pOutData,
const LVM_UINT16 NumSamples);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __LVREV_H__ */
/* End of file */

View File

@@ -0,0 +1,47 @@
/*
* 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 ANDROID_EXYNOS_EFFECTREVERB_H_
#define ANDROID_EXYNOS_EFFECTREVERB_H_
#include <audio_effects/effect_environmentalreverb.h>
#include <audio_effects/effect_presetreverb.h>
#include <tinyalsa/asoundlib.h>
#if __cplusplus
extern "C" {
#endif
#define MAX_NUM_BANDS 5
#define MAX_CALL_SIZE 256
#define LVREV_MAX_T60 7000
#define LVREV_MAX_REVERB_LEVEL 2000
#define LVREV_MAX_FRAME_SIZE 2560
#define LVREV_CUP_LOAD_ARM9E 470 // Expressed in 0.1 MIPS
#define LVREV_MEM_USAGE 71+(LVREV_MAX_FRAME_SIZE>>7) // Expressed in kB
//#define LVM_PCM
typedef struct _LPFPair_t
{
int16_t Room_HF;
int16_t LPF;
} LPFPair_t;
#if __cplusplus
} // extern "C"
#endif
#endif /*ANDROID_EXYNOS_EFFECTREVERB_H_*/

View File

@@ -0,0 +1,27 @@
ifeq ($(BOARD_USE_OFFLOAD_EFFECT),true)
LOCAL_PATH:= $(call my-dir)
# Exynos Offload Visualizer library
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
exynos_visualizer.c
LOCAL_C_INCLUDES := \
external/tinyalsa/include \
$(call include-path-for, audio-effects)
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
libtinyalsa
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
LOCAL_MODULE:= libexynosvisualizer
LOCAL_MODULE_RELATIVE_PATH := soundfx
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
endif

View File

@@ -0,0 +1,190 @@
Copyright (c) 2005-2008, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2014 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.
*/
#include <cutils/list.h>
#include <cutils/log.h>
#include <system/thread_defs.h>
#include <hardware/audio_effect.h>
#include <tinyalsa/asoundlib.h>
#include <audio_effects/effect_visualizer.h>
enum {
EFFECT_STATE_UNINITIALIZED,
EFFECT_STATE_INITIALIZED,
EFFECT_STATE_ACTIVE,
};
typedef struct effect_context_s effect_context_t;
typedef struct output_context_s output_context_t;
/* effect specific operations. Only the init() and process() operations must be defined.
* Others are optional.
*/
typedef struct effect_ops_s {
int (*init)(effect_context_t *context);
int (*release)(effect_context_t *context);
int (*reset)(effect_context_t *context);
int (*enable)(effect_context_t *context);
int (*disable)(effect_context_t *context);
int (*start)(effect_context_t *context, output_context_t *output);
int (*stop)(effect_context_t *context, output_context_t *output);
int (*process)(effect_context_t *context, audio_buffer_t *in, audio_buffer_t *out);
int (*set_parameter)(effect_context_t *context, effect_param_t *param, uint32_t size);
int (*get_parameter)(effect_context_t *context, effect_param_t *param, uint32_t *size);
int (*command)(effect_context_t *context, uint32_t cmd_code, uint32_t cmd_size, void *cmd_data, uint32_t *reply_size, void *reply_data);
} effect_ops_t;
struct effect_context_s {
const struct effect_interface_s *itfe;
struct listnode effects_list_node; /* node in created_effects_list */
struct listnode output_node; /* node in output_context_t.effects_list */
effect_config_t config;
const effect_descriptor_t *desc;
audio_io_handle_t out_handle; /* io handle of the output the effect is attached to */
uint32_t state;
bool offload_enabled; /* when offload is enabled we process VISUALIZER_CMD_CAPTURE command.
Otherwise non offloaded visualizer has already processed the command
and we must not overwrite the reply. */
effect_ops_t ops;
};
typedef struct output_context_s {
struct listnode outputs_list_node; /* node in active_outputs_list */
audio_io_handle_t handle; /* io handle */
struct listnode effects_list; /* list of effects attached to this output */
} output_context_t;
/* maximum time since last capture buffer update before resetting capture buffer. This means
that the framework has stopped playing audio and we must start returning silence */
#define MAX_STALL_TIME_MS 1000
#define CAPTURE_BUF_SIZE 65536 /* "64k should be enough for everyone" */
#define DISCARD_MEASUREMENTS_TIME_MS 2000 /* discard measurements older than this number of ms */
/* maximum number of buffers for which we keep track of the measurements */
#define MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS 25 /* note: buffer index is stored in uint8_t */
typedef struct buffer_stats_s {
bool is_valid;
uint16_t peak_u16; /* the positive peak of the absolute value of the samples in a buffer */
float rms_squared; /* the average square of the samples in a buffer */
} buffer_stats_t;
typedef struct visualizer_context_s {
effect_context_t common;
uint32_t capture_idx;
uint32_t capture_size;
uint32_t scaling_mode;
uint32_t last_capture_idx;
uint32_t latency;
struct timespec buffer_update_time;
uint8_t capture_buf[CAPTURE_BUF_SIZE];
/* for measurements */
uint8_t channel_count; /* to avoid recomputing it every time a buffer is processed */
uint32_t meas_mode;
uint8_t meas_wndw_size_in_buffers;
uint8_t meas_buffer_idx;
buffer_stats_t past_meas[MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS];
} visualizer_context_t;
#define DSP_OUTPUT_LATENCY_MS 0 /* Fudge factor for latency after capture point in audio DSP */
#define SOUND_CARD 0
#define CAPTURE_DEVICE 8
/* Proxy port supports only MMAP read and those fixed parameters*/
#define AUDIO_CAPTURE_CHANNEL_COUNT 2
#define AUDIO_CAPTURE_SMP_RATE 48000
#define AUDIO_CAPTURE_PERIOD_SIZE 1024
#define AUDIO_CAPTURE_PERIOD_COUNT 4
struct pcm_config pcm_config_capture = {
.channels = AUDIO_CAPTURE_CHANNEL_COUNT,
.rate = AUDIO_CAPTURE_SMP_RATE,
.period_size = AUDIO_CAPTURE_PERIOD_SIZE,
.period_count = AUDIO_CAPTURE_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.start_threshold = AUDIO_CAPTURE_PERIOD_SIZE / 4,
.stop_threshold = INT_MAX,
.avail_min = AUDIO_CAPTURE_PERIOD_SIZE / 4,
};

View File

@@ -0,0 +1,56 @@
# Copyright (C) 2014 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.
#
# Primary Audio HAL
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
audio_hw.c
LOCAL_SRC_FILES += \
ww/voice_manager.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
external/tinycompress/include \
external/kernel-headers/original/uapi/sound \
$(call include-path-for, audio-route) \
$(call include-path-for, audio-utils) \
external/expat/lib
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/ww
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
libtinyalsa \
libtinycompress \
libaudioroute \
libaudioutils \
libdl \
libexpat
LOCAL_MODULE := audio.primary.m86
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))

190
exynos/libaudio/hal/NOTICE Normal file
View File

@@ -0,0 +1,190 @@
Copyright (c) 2014, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,427 @@
/*
* Copyright (C) 2014 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 __EXYNOS_AUDIOHAL_H__
#define __EXYNOS_AUDIOHAL_H__
#include <cutils/list.h>
#include <audio_route/audio_route.h>
#include <audio_utils/resampler.h>
/* Definition of AudioHAL */
#include <hardware/hardware.h>
#include <hardware/audio.h>
#include <hardware/audio_alsaops.h>
#include <system/audio.h>
/* PCM Interface of ALSA & Compress Offload Interface */
#include <tinyalsa/asoundlib.h>
#include <tinycompress/tinycompress.h>
#include <compress_params.h>
/* SoC specific header */
#include <audio_conf.h>
/* Voice call - RIL interface */
#include "voice_manager.h"
/* Mixer Path configuration file for working AudioHAL */
#define VENDOR_MIXER_XML_PATH "/vendor/etc/mixer_paths.xml"
/* Effect HAL and Visualizer library path for offload scenario */
#define OFFLOAD_VISUALIZERHAL_PATH "/system/lib/soundfx/libexynosvisualizer.so"
/**
** Audio Usages For AudioHAL
**/
typedef enum {
AUSAGE_PLAYBACK,
AUSAGE_CAPTURE,
} audio_usage_type_t;
/* Audio Usages */
typedef enum {
AUSAGE_DEFAULT = -1,
AUSAGE_MIN = 0,
AUSAGE_PLAYBACK_PRIMARY = 0, // For Primary Output Profile
AUSAGE_PLAYBACK_LOW_LATENCY, // For Fast Output Profile
AUSAGE_PLAYBACK_DEEP_BUFFER, // For Deep Buffer Profile
AUSAGE_PLAYBACK_COMPR_OFFLOAD, // For Compress Offload Profile
AUSAGE_PLAYBACK_AUX_DIGITAL, // For HDMI Profile
AUSAGE_CAPTURE_LOW_LATENCY, // For Primary Input Profile
AUSAGE_MAX,
AUSAGE_CNT = AUSAGE_MAX
} audio_usage_id_t;
/* usage mode definitions */
typedef enum {
AUSAGE_MODE_NORMAL = 0,
AUSAGE_MODE_VOICE_CALL,
AUSAGE_MODE_VOIP_CALL,
AUSAGE_MODE_LTE_CALL,
AUSAGE_MODE_WIFI_CALL,
AUSAGE_MODE_NONE,
AUSAGE_MODE_MAX,
AUSAGE_MODE_CNT = AUSAGE_MODE_MAX
} audio_usage_mode_t;
/**
** Stream Status
**/
typedef enum {
STATE_STANDBY = 0, // Stream is opened, but Device(PCM or Compress) is not opened yet.
STATE_IDLE, // Stream is opened & Device(PCM or Compress) is opened.
STATE_PLAYING, // Stream is opened & Device(PCM or Compress) is opened & Device is working.
STATE_PAUSED, // Stream is opened & Device(Compress) is opened & Device is pausing.(only available for Compress Offload Stream)
} stream_state_type_t;
/**
** Exynos Offload Message List
**/
typedef enum {
OFFLOAD_MSG_INVALID = 0,
OFFLOAD_MSG_WAIT_WRITE,
OFFLOAD_MSG_WAIT_DRAIN,
OFFLOAD_MSG_WAIT_PARTIAL_DRAIN,
OFFLOAD_MSG_EXIT,
OFFLOAD_MSG_MAX,
} offload_msg_type_t;
/**
** Call State
**/
typedef enum {
CALL_OFF = 0,
CP_CALL,
LTE_CALL,
WIFI_CALL,
} call_state_type_t;
struct exynos_offload_msg {
struct listnode node;
offload_msg_type_t msg;
};
/**
** Real Audio In/Output Device based on Target Device
**/
typedef enum {
DEVICE_EARPIECE = 0, // handset or receiver
DEVICE_SPEAKER,
DEVICE_HEADSET, // headphone + mic
DEVICE_HEADPHONE, // headphone or earphone
DEVICE_SPEAKER_AND_HEADSET,
DEVICE_SPEAKER_AND_HEADPHONE,
DEVICE_BT_HEADSET,
DEVICE_MAIN_MIC,
DEVICE_HEADSET_MIC,
DEVICE_BT_HEADSET_MIC,
DEVICE_NONE,
DEVICE_MAX,
DEVICE_CNT = DEVICE_MAX
} device_type_t;
/**
** Mapping Audio In/Output Device in Audio.h into Real In/Output Device of Set/Board
**/
static device_type_t get_device_id(audio_devices_t devices)
{
if (devices > AUDIO_DEVICE_BIT_IN) {
/* Input Devices */
if (popcount(devices) == 2) {
switch (devices) {
case AUDIO_DEVICE_IN_BUILTIN_MIC: return DEVICE_MAIN_MIC;
case AUDIO_DEVICE_IN_WIRED_HEADSET: return DEVICE_HEADSET_MIC;
case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET: return DEVICE_BT_HEADSET_MIC;
default: return DEVICE_NONE;
}
}
} else {
/* Output Devices */
if (popcount(devices) == 1) {
/* Single Device */
switch (devices) {
case AUDIO_DEVICE_OUT_EARPIECE: return DEVICE_EARPIECE;
case AUDIO_DEVICE_OUT_SPEAKER: return DEVICE_SPEAKER;
case AUDIO_DEVICE_OUT_WIRED_HEADSET: return DEVICE_HEADSET;
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: return DEVICE_HEADPHONE;
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
return DEVICE_BT_HEADSET;
case AUDIO_DEVICE_NONE:
default: return DEVICE_NONE;
}
} else if (popcount(devices) == 2) {
/* Dual Device */
if (devices == (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_WIRED_HEADSET))
return DEVICE_SPEAKER_AND_HEADSET;
if (devices == (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_WIRED_HEADPHONE))
return DEVICE_SPEAKER_AND_HEADPHONE;
}
}
return DEVICE_NONE;
}
static device_type_t get_indevice_id_from_outdevice(device_type_t devices)
{
switch (devices) {
case DEVICE_EARPIECE:
case DEVICE_SPEAKER:
case DEVICE_HEADPHONE:
case DEVICE_SPEAKER_AND_HEADPHONE:
return DEVICE_MAIN_MIC;
case DEVICE_HEADSET:
case DEVICE_SPEAKER_AND_HEADSET:
return DEVICE_HEADSET_MIC;
case DEVICE_BT_HEADSET:
return DEVICE_BT_HEADSET_MIC;
case DEVICE_MAIN_MIC:
case DEVICE_HEADSET_MIC:
return devices;
case DEVICE_NONE:
default:
return DEVICE_NONE;
}
return DEVICE_NONE;
}
/**
** Structure for Audio Output Stream
** Implement audio_stream_out structure
**/
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock;
/* These variables are needed to save Android Request becuase pcm_config
and audio_config are different */
audio_io_handle_t handle;
audio_devices_t devices;
audio_output_flags_t flags;
unsigned int sample_rate;
audio_channel_mask_t channel_mask;
audio_format_t format;
audio_usage_id_t ausage;
stream_state_type_t sstate;
bool mixer_path_setup;
/* PCM specific */
struct pcm *pcminfo;
struct pcm_config pcmconfig;
uint64_t written; /* total frames written, not cleared when entering standby */
/* Offload specific */
struct compress *comprinfo;
struct compr_config comprconfig;
int nonblock_flag;
float vol_left, vol_right;
stream_callback_t offload_callback;
void *offload_cookie;
pthread_t offload_callback_thread;
pthread_cond_t offload_msg_cond;
struct listnode offload_msg_list;
pthread_cond_t offload_sync_cond;
bool callback_thread_blocked;
struct compr_gapless_mdata offload_metadata;
int ready_new_metadata;
unsigned long err_count;
struct audio_device *adev;
};
/**
** Structure for Audio Input Stream
** Implement audio_stream_in structure
**/
struct stream_in {
struct audio_stream_in stream;
pthread_mutex_t lock;
/* These variables are needed to save Android Request becuase pcm_config
and audio_config are different */
audio_io_handle_t handle;
audio_devices_t devices;
audio_source_t source;
audio_input_flags_t flags;
unsigned int sample_rate;
audio_channel_mask_t channel_mask;
audio_format_t format;
audio_usage_id_t ausage;
stream_state_type_t sstate;
bool mixer_path_setup;
/* PCM specific */
struct pcm *pcminfo;
struct pcm_config pcmconfig;
unsigned long err_count;
struct audio_device *adev;
};
/**
** Exynos AudioHAL Usage List
**/
union stream_ptr {
struct stream_in *in;
struct stream_out *out;
};
struct exynos_audio_usage {
struct listnode node;
audio_usage_type_t usage_type; /* Audio Usage Type */
audio_usage_id_t usage_id; /* Audio Usage ID */
device_type_t out_device_id; /* related out_device */
device_type_t in_device_id; /* related in_device */
audio_usage_mode_t out_device_amode; /*related out device usage mode */
audio_usage_mode_t in_device_amode; /*related in device usage mode */
union stream_ptr stream; /* related stream_in/stream_out structure */
};
/**
** Routing Information
**/
struct route_info {
unsigned int card_num;
struct audio_route *aroute;
};
/**
** Structure for Audio Primary HW Module
** Implement audio_hw_device structure
**/
struct audio_device { // size : 0x140u -> 320
struct audio_hw_device hw_device;
pthread_mutex_t lock;// *+ 41 // adev + 164 /* see note below on mutex acquisition order */
audio_mode_t amode; // *+ 42 // adev + 168
struct stream_out *out_device; // out_device; // *+ 43 // adev + 172
struct stream_in *in_device; // *+ 44 // adev + 176
bool mic_mute_state; // adev + 180
bool screen_state; // adev + 181
bool bt_headset_nrec; // adev + 182
bool voice_call_wb; // adev + 183
bool mic_nr_off; // adev + 184
bool b_185; // adev + 185
bool b_186; // adev + 186
bool b_187; // adev + 187
struct audio_route* audio_route;// *+ 47 // adev + 188
struct mixer *mixer;// * +48 // adev + 192
struct mixer *hifi_mixer;// * + 49 // adev + 196
void *v_50;// * + 50 // adev + 200
void *v_51;// * + 51 // adev + 204
void *v_52;// * + 52 // adev + 208
void *v_53;// * + 53 // adev + 212
void *v_54;// * + 54 // adev + 216
struct pcm *pcm_voice_out;// * + 55 // adev + 220 // VOICE_OUT
struct pcm *pcm_voice_in;// * + 56 // adev + 224 // VOICE_IN
struct pcm *pcm_be_out;// * + 57 // adev + 228 // VOICE_BE_OUT
struct pcm *pcm_be_in;// * + 58 // adev + 232 // VOICE_BE_IN
/* BT-SCO */
struct pcm *pcm_btsco_out;// * + 59 // adev + 236 // SCO_OUT
struct pcm *pcm_btsco_in;// * + 60 // adev + 240 // SCO_IN
struct pcm *pcm_pa_out;// * + 61 // adev + 244 // PA_OUT
struct pcm *pcm_pa_in;// * + 62 // adev + 248 // PA_IN
void *v_63; // * + 63 // adev + 252
void *v_64; // * + 64 // adev + 256
bool tfa_power_state; // adev + 260
bool mute_state; // adev + 261
bool b_262; // adev + 262
bool b_263; // adev + 263
int sample_rate; // * + 66 // adev + 264
bool b_268; // * + 67 // adev + 268
bool output_stream_state; // adev + 269
bool b_270; // adev + 270
bool b_271; // adev + 271
int headset_volume; // * + 68 // adev + 272
int headphone_volume; // * + 69 // adev + 276
void *v_70; // * + 70 // adev + 280
void *v_71; // * + 71 // adev + 284
bool hifi_state; // * + 72 // adev + 288
bool b_289; // adev + 289
bool b_290; // adev + 290
bool b_291; // adev + 291
int hifi_gain_state; // * + 73 // adev + 292
int hifi_gain; // * + 74 // adev + 296
int hifi_volume; // * + 75 // adev + 300
bool is_oversea; // * + 76 // adev + 304
bool b_305; // adev + 305
bool b_306; // adev + 306
bool b_307; // adev + 307
int hifi_impedance; // * + 77 // adev + 308
bool messagerecord_state; // * + 78 // adev + 312
bool asr_ready; // adev + 313
bool b_314; // adev + 314
bool b_315; // adev + 315
void *v_79; // * + 79 // adev + 316
};
#define MAX_PATH_NAME_LEN 50
#define MAX_ERR_COUNT 10
#endif // __EXYNOS_AUDIOHAL_H__

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2014 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 __EXYNOS_AUDIOHAL_DEF_H__
#define __EXYNOS_AUDIOHAL_DEF_H__
#include <system/audio.h>
char * offload_msg_table[OFFLOAD_MSG_MAX] = {
[OFFLOAD_MSG_INVALID] = "Offload Message_Invalid",
[OFFLOAD_MSG_WAIT_WRITE] = "Offload Message_Wait to write",
[OFFLOAD_MSG_WAIT_DRAIN] = "Offload Message_Wait to drain",
[OFFLOAD_MSG_WAIT_PARTIAL_DRAIN] = "Offload Message_Wait to drain partially",
[OFFLOAD_MSG_EXIT] = "Offload Message_Wait to exit",
};
/**
** Default PCM Configuration
**
** start_threshold: PCM Device start automatically
** when PCM data in ALSA Buffer it equal or greater than this value.
** stop_threshold: PCM Device stop automatically
** when available room in ALSA Buffer it equal or greater than this value.
**/
struct pcm_config pcm_config_primary = {
.channels = DEFAULT_OUTPUT_CHANNELS,
.rate = DEFAULT_OUTPUT_SAMPLING_RATE,
.period_size = PRIMARY_OUTPUT_PERIOD_SIZE,
.period_count = PRIMARY_OUTPUT_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.start_threshold = PRIMARY_OUTPUT_PERIOD_SIZE,
.stop_threshold = PRIMARY_OUTPUT_STOP_THREASHOLD,
// .silence_threshold = 0,
// .avail_min = PRIMARY_OUTPUT_PERIOD_SIZE,
};
struct pcm_config pcm_config_low_latency = {
.channels = DEFAULT_OUTPUT_CHANNELS,
.rate = DEFAULT_OUTPUT_SAMPLING_RATE,
.period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
.period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
.stop_threshold = LOW_LATENCY_OUTPUT_STOP_THREASHOLD,
// .silence_threshold = 0,
// .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
};
struct pcm_config pcm_config_deep_buffer = {
.channels = DEFAULT_OUTPUT_CHANNELS,
.rate = DEFAULT_OUTPUT_SAMPLING_RATE,
.period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
.period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
.stop_threshold = DEEP_BUFFER_OUTPUT_STOP_THREASHOLD,
// .silence_threshold = 0,
// .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
};
struct pcm_config pcm_config_audio_capture = {
.channels = DEFAULT_INPUT_CHANNELS,
.rate = DEFAULT_INPUT_SAMPLING_RATE,
.period_size = AUDIO_CAPTURE_PERIOD_SIZE,
.period_count = AUDIO_CAPTURE_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
struct pcm_config pcm_config_vc_nb = {
.channels = DEFAULT_VOICE_CHANNELS,
.rate = NB_VOICE_SAMPLING_RATE,
.period_size = WB_VOICE_PERIOD_SIZE,
.period_count = WB_VOICE_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
struct pcm_config pcm_config_vc_wb = {
.channels = DEFAULT_VOICE_CHANNELS,
.rate = WB_VOICE_SAMPLING_RATE,
.period_size = WB_VOICE_PERIOD_SIZE,
.period_count = WB_VOICE_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
struct pcm_config pcm_config_bt_sco = {
.channels = DEFAULT_BT_SCO_CHANNELS,
.rate = WB_VOICE_SAMPLING_RATE,
.period_size = BT_SCO_PERIOD_SIZE,
.period_count = BT_SCO_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
/**
** Sound Card and Sound Device for specific Audio usage
**/
int sound_device_table[AUSAGE_MAX][2] = {
[AUSAGE_PLAYBACK_PRIMARY] = {PRIMARY_SOUND_CARD, PRIMARY_PLAYBACK_DEVICE},
[AUSAGE_PLAYBACK_LOW_LATENCY] = {LOW_LATENCY_SOUND_CARD, LOW_LATENCY_PLAYBACK_DEVICE},
[AUSAGE_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_SOUND_CARD, DEEP_BUFFER_PLAYBACK_DEVICE},
[AUSAGE_PLAYBACK_COMPR_OFFLOAD] = {COMPR_OFFLOAD_SOUND_CARD, COMPR_OFFLOAD_PLAYBACK_DEVICE},
[AUSAGE_PLAYBACK_AUX_DIGITAL] = {AUX_DIGITAL_SOUND_CARD, AUX_DIGITAL_PLAYBACK_DEVICE},
[AUSAGE_CAPTURE_LOW_LATENCY] = {LOW_LATENCY_SOUND_CARD, LOW_LATENCY_CAPTURE_DEVICE},
};
/**
** Audio Usage & Mode Table for readable log messages
**/
char * usage_table[AUSAGE_CNT] = {
[AUSAGE_PLAYBACK_PRIMARY] = "primary_out",
[AUSAGE_PLAYBACK_LOW_LATENCY] = "fast_out",
[AUSAGE_PLAYBACK_DEEP_BUFFER] = "deep_out",
[AUSAGE_PLAYBACK_COMPR_OFFLOAD] = "offload_out",
[AUSAGE_PLAYBACK_AUX_DIGITAL] = "aux_out",
[AUSAGE_CAPTURE_LOW_LATENCY] = "primary_in",
};
char * mode_table[AUSAGE_CNT] = {
[AUSAGE_MODE_NORMAL] = "normal",
[AUSAGE_MODE_VOICE_CALL] = "voice_call",
[AUSAGE_MODE_VOIP_CALL] = "voip_call",
[AUSAGE_MODE_LTE_CALL] = "LTE_call",
[AUSAGE_MODE_WIFI_CALL] = "WiFi_call",
[AUSAGE_MODE_NONE] = "none",
};
/**
** Device Path(Codec to Device) Configuration based on Audio Input/Output Device
**/
char * device_path_table[DEVICE_CNT] = {
[DEVICE_EARPIECE] = "handset",
[DEVICE_SPEAKER] = "speaker",
[DEVICE_HEADSET] = "headset",
[DEVICE_HEADPHONE] = "headset",
[DEVICE_SPEAKER_AND_HEADSET] = "speaker-headset",
[DEVICE_SPEAKER_AND_HEADPHONE] = "speaker-headset",
[DEVICE_BT_HEADSET] = "bt-sco-headset",
[DEVICE_MAIN_MIC] = "mic",
[DEVICE_HEADSET_MIC] = "headset-mic",
[DEVICE_BT_HEADSET_MIC] = "bt-sco-mic",
[DEVICE_NONE] = "none",
};
/* Audio Routing Path = Ausage_Mode or Service Name + -(Hyphen) + Device Name */
/**
** Service Path(AP/CP to Codec) Configuration based on Audio Usage
**/
char * mode_path_table[AUSAGE_CNT] = {
[AUSAGE_MODE_NORMAL] = "media",
[AUSAGE_MODE_VOICE_CALL] = "incall",
[AUSAGE_MODE_VOIP_CALL] = "communication",
[AUSAGE_MODE_LTE_CALL] = "incall",
[AUSAGE_MODE_WIFI_CALL] = "media",
[AUSAGE_MODE_NONE] = "none",
};
#endif // __EXYNOS_AUDIOHAL_DEF_H__

View File

@@ -0,0 +1,337 @@
/*
* Copyright (C) 2014 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.
*/
#define LOG_TAG "voice_manager"
//#define LOG_NDEBUG 0
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <cutils/log.h>
#include "voice_manager.h"
#include <cutils/properties.h>
#define VOLUME_STEPS_DEFAULT "5"
#define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps"
bool voice_is_in_call(struct voice_manager *voice)
{
return voice->state_call;
}
int voice_set_call_mode(struct voice_manager *voice, enum voice_call_mode cmode)
{
int ret = 0;
if (voice) {
voice->mode = cmode;
ALOGD("%s: Set Call Mode = %d!", __func__, voice->mode);
}
return ret;
}
int voice_callback(void * handle, int event, const void *data, unsigned int datalen)
{
struct voice_manager *voice = (struct voice_manager *)handle;
int (*funcp)(int, const void *, unsigned int) = NULL;
ALOGD("%s: Called Callback Function from RIL Audio Client!", __func__);
if (voice) {
switch (event) {
case VOICE_AUDIO_EVENT_RINGBACK_STATE_CHANGED:
ALOGD("%s: Received RINGBACK_STATE_CHANGED event!", __func__);
break;
case VOICE_AUDIO_EVENT_IMS_SRVCC_HANDOVER:
ALOGD("%s: Received IMS_SRVCC_HANDOVER event!", __func__);
break;
default:
ALOGD("%s: Received Unsupported event (%d)!", __func__, event);
return 0;
}
funcp = voice->callback;
funcp(event, data, datalen);
}
return 0;
}
int voice_set_mic_mute(struct voice_manager *voice, bool state)
{
int ret = 0;
voice->state_mic_mute = state;
if (voice->state_call) {
if (voice->rilc.ril_set_mute) {
if (state)
voice->rilc.ril_set_mute(VOICE_AUDIO_MUTE_ENABLED);
else
voice->rilc.ril_set_mute(VOICE_AUDIO_MUTE_DISABLED);
}
ALOGD("%s: MIC Mute = %d!", __func__, state);
}
return ret;
}
bool voice_get_mic_mute(struct voice_manager *voice)
{
ALOGD("%s: MIC Mute = %d!", __func__, voice->state_mic_mute);
return voice->state_mic_mute;
}
int voice_set_volume(struct voice_manager *voice, float volume)
{
int vol, ret = 0;
if (voice->state_call) {
if (voice->rilc.ril_set_audio_volume)
voice->rilc.ril_set_audio_volume((int)(volume * voice->volume_steps_max));
ALOGD("%s: Volume = %d(%f)!", __func__, (int)(volume * voice->volume_steps_max), volume);
}
return ret;
}
int voice_set_audio_clock(struct voice_manager *voice, enum ril_audio_clockmode clockmode)
{
int ret = 0;
if (voice->state_call) {
if (voice->rilc.ril_set_audio_clock)
voice->rilc.ril_set_audio_clock((int)clockmode);
ALOGD("%s: AudioClock Mode = %s!", __func__, (clockmode? "ON" : "OFF"));
}
return ret;
}
static enum ril_audio_path map_incall_device(struct voice_manager *voice, audio_devices_t devices)
{
enum ril_audio_path device_type = VOICE_AUDIO_PATH_HANDSET;
switch(devices) {
case AUDIO_DEVICE_OUT_EARPIECE:
if (voice->mode == VOICE_CALL_CS)
device_type = VOICE_AUDIO_PATH_HANDSET;
else
device_type = VOICE_AUIDO_PATH_VOLTE_HANDSET;
break;
case AUDIO_DEVICE_OUT_SPEAKER:
if (voice->mode == VOICE_CALL_CS)
device_type = VOICE_AUIDO_PATH_SPEAKRERPHONE;
else
device_type = VOICE_AUIDO_PATH_VOLTE_SPEAKRERPHONE;
break;
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
if (voice->mode == VOICE_CALL_CS)
device_type = VOICE_AUIDO_PATH_HEADSET;
else
device_type = VOICE_AUIDO_PATH_VOLTE_HEADSET;
break;
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
if (voice->mode == VOICE_CALL_CS)
device_type = VOICE_AUIDO_PATH_STEREO_BLUETOOTH;
else
device_type = VOICE_AUIDO_PATH_VOLTE_STEREO_BLUETOOTH;
break;
default:
if (voice->mode == VOICE_CALL_CS)
device_type = VOICE_AUDIO_PATH_HANDSET;
else
device_type = VOICE_AUIDO_PATH_VOLTE_HANDSET;
break;
}
return device_type;
}
int voice_set_path(struct voice_manager *voice, audio_devices_t devices)
{
int ret = 0;
enum ril_audio_path path;
if (voice->state_call) {
/* Mapping */
path = map_incall_device(voice, devices);
if (voice->rilc.ril_set_audio_path) {
ret = voice->rilc.ril_set_audio_path(path);
if (ret == 0) {
ALOGD("%s: Set Audio Path to %d!", __func__, path);
} else {
ALOGE("%s: Failed to set path in RIL Client!", __func__);
return ret;
}
} else {
ALOGE("%s: ril_set_audio_path is not available.", __func__);
ret = -1;
}
} else {
ALOGE("%s: Voice is not IN_CALL", __func__);
ret = -1;
}
return ret;
}
int voice_open(struct voice_manager *voice)
{
int ret = 0;
if (!voice->state_call) {
if (voice->rilc.ril_open_client) {
ret = voice->rilc.ril_open_client();
if (ret == 0) {
voice->state_call = true;
ALOGD("%s: Opened RIL Client, Transit to IN_CALL!", __func__);
} else {
ALOGE("%s: Failed to open RIL Client!", __func__);
}
} else {
ALOGE("%s: ril_open_client is not available.", __func__);
ret = -1;
}
}
return ret;
}
int voice_close(struct voice_manager *voice)
{
int ret = 0;
if (voice->state_call) {
if (voice->rilc.ril_close_client) {
ret = voice->rilc.ril_close_client();
if (ret == 0) {
voice->state_call = false;
ALOGD("%s: Closed RIL Client, Transit to NOT_IN_CALL!", __func__);
} else {
ALOGE("%s: Failed to close RIL Client!", __func__);
}
} else {
ALOGE("%s: ril_close_client is not available.", __func__);
ret = -1;
}
}
return ret;
}
int voice_set_callback(struct voice_manager * voice, void * callback_func)
{
int ret = 0;
if (voice->rilc.ril_register_callback) {
ret = voice->rilc.ril_register_callback((void *)voice, (int *)voice_callback);
if (ret == 0) {
ALOGD("%s: Succeded to register Callback Function!", __func__);
voice->callback = callback_func;
}
else
ALOGE("%s: Failed to register Callback Function!", __func__);
}
else {
ALOGE("%s: ril_register_callback is not available.", __func__);
ret = -1;
}
return ret;
}
void voice_deinit(struct voice_manager *voice)
{
if (voice) {
if (voice->rilc.handle)
dlclose(voice->rilc.handle);
free(voice);
}
return ;
}
struct voice_manager* voice_init(void)
{
struct voice_manager *voice = NULL;
char property[PROPERTY_VALUE_MAX];
voice = calloc(1, sizeof(struct voice_manager));
if (voice) {
if (access(RIL_CLIENT_LIBPATH, R_OK) == 0) {
voice->rilc.handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW);
if (voice->rilc.handle) {
voice->rilc.ril_open_client = (int (*)(void))dlsym(voice->rilc.handle, "Open");
voice->rilc.ril_close_client = (int (*)(void))dlsym(voice->rilc.handle, "Close");
voice->rilc.ril_register_callback = (int (*)(void *, int *))dlsym(voice->rilc.handle, "RegisterEventCallback");
voice->rilc.ril_set_audio_volume = (int (*)(int))dlsym(voice->rilc.handle, "SetAudioVolume");
voice->rilc.ril_set_audio_path = (int (*)(int))dlsym(voice->rilc.handle, "SetAudioPath");
voice->rilc.ril_set_multi_mic = (int (*)(int))dlsym(voice->rilc.handle, "SetMultiMic");
voice->rilc.ril_set_mute = (int (*)(int))dlsym(voice->rilc.handle, "SetMute");
voice->rilc.ril_set_audio_clock = (int (*)(int))dlsym(voice->rilc.handle, "SetAudioClock");
voice->rilc.ril_set_audio_loopback = (int (*)(int, int))dlsym(voice->rilc.handle, "SetAudioLoopback");
ALOGD("%s: Successed to open SMI RIL Client Interface!", __func__);
} else {
ALOGE("%s: Failed to open SMI RIL Client Interface(%s)!", __func__, RIL_CLIENT_LIBPATH);
goto open_err;
}
} else {
ALOGE("%s: Failed to access SMI RIL Client Interface(%s)!", __func__, RIL_CLIENT_LIBPATH);
goto open_err;
}
voice->state_call = false;
voice->mode = VOICE_CALL_NONE;
voice->state_mic_mute = false;
property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT);
voice->volume_steps_max = atoi(property);
/* this catches the case where VOLUME_STEPS_PROPERTY does not contain an integer */
if (voice->volume_steps_max == 0)
voice->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT);
voice->callback = NULL;
}
return voice;
open_err:
if (voice) {
free(voice);
voice = NULL;
}
return voice;
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright (C) 2014 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 __EXYNOS_VOICE_SERVICE_H__
#define __EXYNOS_VOICE_SERVICE_H__
#include <system/audio.h>
#define RIL_CLIENT_LIBPATH "/system/lib/libsmiril-audio.so"
/* Syncup with RIL Audio Client */
/* Voice Audio Path */
enum ril_audio_path {
VOICE_AUIDO_PATH_NONE = 0,
VOICE_AUDIO_PATH_HANDSET = 1,
VOICE_AUIDO_PATH_HEADSET = 2,
VOICE_AUIDO_PATH_HANDSFREE = 3,
VOICE_AUIDO_PATH_BLUETOOTH = 4,
VOICE_AUIDO_PATH_STEREO_BLUETOOTH = 5,
VOICE_AUIDO_PATH_SPEAKRERPHONE = 6,
VOICE_AUIDO_PATH_35PI_HEADSET = 7,
VOICE_AUIDO_PATH_BT_NS_EC_OFF = 8,
VOICE_AUIDO_PATH_WB_BLUETOOTH = 9,
VOICE_AUIDO_PATH_WB_BT_NS_EC_OFF = 10,
VOICE_AUIDO_PATH_HANDSET_HAC = 11,
VOICE_AUIDO_PATH_VOLTE_HANDSET = 65,
VOICE_AUIDO_PATH_VOLTE_HEADSET = 66,
VOICE_AUIDO_PATH_VOLTE_HFK = 67,
VOICE_AUIDO_PATH_VOLTE_BLUETOOTH = 68,
VOICE_AUIDO_PATH_VOLTE_STEREO_BLUETOOTH = 69,
VOICE_AUIDO_PATH_VOLTE_SPEAKRERPHONE = 70,
VOICE_AUIDO_PATH_VOLTE_35PI_HEADSET = 71,
VOICE_AUIDO_PATH_VOLTE_BT_NS_EC_OFF = 72,
VOICE_AUIDO_PATH_VOLTE_WB_BLUETOOTH = 73,
VOICE_AUIDO_PATH_VOLTE_WB_BT_NS_EC_OFF = 74,
VOICE_AUIDO_PATH_MAX
};
/* Voice Audio Multi-MIC */
enum ril_audio_multimic {
VOICE_MULTI_MIC_OFF,
VOICE_MULTI_MIC_ON,
};
/* Voice Audio Volume */
enum ril_audio_volume {
VOICE_AUDIO_VOLUME_INVALID = -1,
VOICE_AUDIO_VOLUME_LEVEL0 = 0,
VOICE_AUDIO_VOLUME_LEVEL1,
VOICE_AUDIO_VOLUME_LEVEL2,
VOICE_AUDIO_VOLUME_LEVEL3,
VOICE_AUDIO_VOLUME_LEVEL4,
VOICE_AUDIO_VOLUME_LEVEL5,
VOICE_AUDIO_VOLUME_LEVEL_MAX = VOICE_AUDIO_VOLUME_LEVEL5,
};
/* Voice Audio Mute */
enum ril_audio_mute {
VOICE_AUDIO_MUTE_DISABLED,
VOICE_AUDIO_MUTE_ENABLED,
};
/* Voice Audio Clock */
enum ril_audio_clockmode {
VOICE_AUDIO_TURN_OFF_I2S,
VOICE_AUDIO_TURN_ON_I2S,
};
/* Voice Loopback */
enum ril_audio_loopback {
VOICE_AUDIO_LOOPBACK_STOP,
VOICE_AUDIO_LOOPBACK_START,
};
enum ril_audio_loopback_path {
VOICE_AUDIO_LOOPBACK_PATH_NA = 0, //0: N/A
VOICE_AUDIO_LOOPBACK_PATH_HANDSET = 1, //1: handset
VOICE_AUDIO_LOOPBACK_PATH_HEADSET = 2, //2: headset
VOICE_AUDIO_LOOPBACK_PATH_HANDSFREE = 3, //3: handsfree
VOICE_AUDIO_LOOPBACK_PATH_BT = 4, //4: Bluetooth
VOICE_AUDIO_LOOPBACK_PATH_STEREO_BT = 5, //5: stereo Bluetooth
VOICE_AUDIO_LOOPBACK_PATH_SPK = 6, //6: speaker phone
VOICE_AUDIO_LOOPBACK_PATH_35PI_HEADSET = 7, //7: 3.5pi headset
VOICE_AUDIO_LOOPBACK_PATH_BT_NS_EC_OFF = 8, //8: BT NS/EC off
VOICE_AUDIO_LOOPBACK_PATH_WB_BT = 9, //9: WB Bluetooth
VOICE_AUDIO_LOOPBACK_PATH_WB_BT_NS_EC_OFF = 10, //10: WB BT NS/EC
VOICE_AUDIO_LOOPBACK_PATH_HANDSET_HAC = 11, //11: handset HAC
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_HANDSET = 65, //65: VOLTE handset
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_HEADSET = 66, //66: VOLTE headset
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_HANDSFREE = 67, //67: VOLTE hands
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_BT = 68, //68: VOLTE Bluetooth
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_STEREO_BT = 69, //69: VOLTE stere
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_SPK = 70, //70: VOLTE speaker phone
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_35PI_HEADSET = 71, //71: VOLTE 3.5pi
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_BT_NS_EC_OFF = 72, //72: VOLTE BT NS
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_WB_BT = 73, //73: VOLTE WB Blueto
VOICE_AUDIO_LOOPBACK_PATH_VOLTE_WB_BT_NS_EC_OFF = 74, //74: VOLTE W
VOICE_AUDIO_LOOPBACK_PATH_HEADSET_MIC1 = 129, //129: Headset ? MIC1
VOICE_AUDIO_LOOPBACK_PATH_HEADSET_MIC2 = 130, //130: Headset ? MIC2
VOICE_AUDIO_LOOPBACK_PATH_HEADSET_MIC3 = 131, //131: Headset ? MIC3
};
/* Voice Call Mode */
enum voice_call_mode {
VOICE_CALL_NONE = 0,
VOICE_CALL_CS, // CS(Circit Switched) Call
VOICE_CALL_PS, // PS(Packet Switched) Call
VOICE_CALL_MAX,
};
/* Event from RIL Audio Client */
#define VOICE_AUDIO_EVENT_BASE 10000
#define VOICE_AUDIO_EVENT_RINGBACK_STATE_CHANGED (VOICE_AUDIO_EVENT_BASE + 1)
#define VOICE_AUDIO_EVENT_IMS_SRVCC_HANDOVER (VOICE_AUDIO_EVENT_BASE + 2)
/* RIL Audio Client Interface Structure */
struct rilclient_intf {
/* The pointer of interface library for RIL Client*/
void *handle;
/* Function pointers */
int (*ril_open_client)(void);
int (*ril_close_client)(void);
int (*ril_register_callback)(void *, int *);
int (*ril_set_audio_volume)(int);
int (*ril_set_audio_path)(int);
int (*ril_set_multi_mic)(int);
int (*ril_set_mute)(int);
int (*ril_set_audio_clock)(int);
int (*ril_set_audio_loopback)(int, int);
};
struct voice_manager {
struct rilclient_intf rilc;
bool state_call; // Current Call Status
enum voice_call_mode mode; // Current Call Mode
bool state_mic_mute; // Current Main MIC Mute Status
int volume_steps_max; // Voice Volume maximum steps
int (*callback)(int, const void *, unsigned int); // Callback Function Pointer
};
/* General Functiuons */
bool voice_is_in_call(struct voice_manager *voice);
int voice_set_call_mode(struct voice_manager *voice, enum voice_call_mode cmode);
/* RIL Audio Client related Functions */
int voice_open(struct voice_manager * voice);
int voice_close(struct voice_manager * voice);
int voice_set_callback(struct voice_manager * voice, void * callback_func);
int voice_set_volume(struct voice_manager *voice, float volume);
int voice_set_path(struct voice_manager * voice, audio_devices_t devices);
int voice_set_multimic(struct voice_manager *voice, enum ril_audio_multimic mmic);
int voice_set_mic_mute(struct voice_manager *voice, bool state);
bool voice_get_mic_mute(struct voice_manager *voice);
int voice_set_audio_clock(struct voice_manager *voice, enum ril_audio_clockmode clockmode);
/* Voice Manager related Functiuons */
void voice_deinit(struct voice_manager *voice);
struct voice_manager * voice_init(void);
#endif // __EXYNOS_VOICE_SERVICE_H__

3
m86/Android.mk Normal file
View File

@@ -0,0 +1,3 @@
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))

3
m86/hw/Android.mk Normal file
View File

@@ -0,0 +1,3 @@
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,115 @@
#
# Copyright 2014 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.
#
# This contains the module build definitions for the hardware-specific
# components for this device.
#
# As much as possible, those components should be built unconditionally,
# with device-specific names to avoid collisions, to avoid device-specific
# bitrot and build breakages. Building a component unconditionally does
# *not* include it on all devices, so it is safe even with hardware-specific
# components.
LOCAL_PATH := $(call my-dir)
# include $(call all-makefiles-under,$(LOCAL_PATH))
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
audio_hw.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
external/tinycompress/include \
external/kernel-headers/original/uapi/sound \
$(call include-path-for, audio-route) \
$(call include-path-for, audio-utils) \
external/expat/lib
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
libtinyalsa \
libtinycompress \
libaudioroute \
libaudioutils \
libdl \
libexpat \
libtfa9890 \
LOCAL_MODULE := audio.primary.m86
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
audio_print_config.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
external/tinycompress/include \
external/kernel-headers/original/uapi/sound \
$(call include-path-for, audio-route) \
$(call include-path-for, audio-utils) \
external/expat/lib
LOCAL_SHARED_LIBRARIES := \
libdl \
LOCAL_32_BIT_ONLY = true
#LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE := audio_print_config
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
tinyplay.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
external/tinycompress/include \
external/kernel-headers/original/uapi/sound \
$(call include-path-for, audio-route) \
$(call include-path-for, audio-utils) \
external/expat/lib
LOCAL_STATIC_LIBRARIES:= libutils libcutils
LOCAL_SHARED_LIBRARIES := libtinyalsa libaudioroute libaudioutils \
liblog \
libtfa9890 \
LOCAL_MODULE := m86_tinyplay
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,120 @@
#ifndef __EXYNOS_AUDIOCONF_H__
#define __EXYNOS_AUDIOCONF_H__
#define SOUND_CARD0 0
/* You have to select this number based on your AudioHAL's service */
#define PRIMARY_SOUND_CARD SOUND_CARD0
#define LOW_LATENCY_SOUND_CARD SOUND_CARD0
#define DEEP_BUFFER_SOUND_CARD SOUND_CARD0
#define COMPR_OFFLOAD_SOUND_CARD SOUND_CARD0
#define VOICE_CALL_SOUND_CARD SOUND_CARD0
#define AUX_DIGITAL_SOUND_CARD SOUND_CARD0 // Not Defined
#define BT_SCO_SOUND_CARD SOUND_CARD0
/* You have to match this number with real kernel information */
#define PRIMARY_SOUND_DEVICE 0 // Primary Device
#define SECONDARY_SOUND_DEVICE 1 // Secondary Device
#define VOICE_CALL_SOUND_DEVICE 2 // CP Voice Call Device
#define EAX0_SOUND_DEVICE 3 // EAX0 for system sound
#define EAX1_SOUND_DEVICE 4 // EAX1 for SoundCamp
#define EAX2_SOUND_DEVICE 5 // EXA2 for deep buffer playback
#define EAX3_SOUND_DEVICE 6 // EAX3 for reserved
#define COMPR_OFFLOAD_SOUND_DEVICE 7 // Compress Offload Playback
#define AUX_DIGITAL_SOUND_DEVICE 0 // Not defined
#define BT_SCO_SOUND_DEVICE 3 // Not defined
/* You have to select this number based on your AudioHAL's service */
// Playback Devices
#define PRIMARY_PLAYBACK_DEVICE PRIMARY_SOUND_DEVICE
#define LOW_LATENCY_PLAYBACK_DEVICE PRIMARY_SOUND_DEVICE
#define DEEP_BUFFER_PLAYBACK_DEVICE SECONDARY_SOUND_DEVICE
#define COMPR_OFFLOAD_PLAYBACK_DEVICE COMPR_OFFLOAD_SOUND_DEVICE
#define VOICE_CALL_PLAYBACK_DEVICE VOICE_CALL_SOUND_DEVICE
#define AUX_DIGITAL_PLAYBACK_DEVICE AUX_DIGITAL_SOUND_DEVICE
#define BT_SCO_PLAYBACK_DEVICE BT_SCO_SOUND_DEVICE
// Capture Devices
#define LOW_LATENCY_CAPTURE_DEVICE PRIMARY_SOUND_DEVICE
#define VOICE_CALL_CAPTURE_DEVICE VOICE_CALL_SOUND_DEVICE
/**
** PCM Configuration for Stop_Threshold
**/
// EAX Mixer has 480 Frames(10ms) Buffer. SO limitation is under 480 Frames
#define EAX_MIXER_PERIOD_SIZE 480
#define EAX_STOP_PERIOD_SIZE EAX_MIXER_PERIOD_SIZE / 4
#define NORMAL_STOP_PERIOD_SIZE EAX_MIXER_PERIOD_SIZE
/**
** Default PCM Device Configurations
**/
#define DEFAULT_OUTPUT_CHANNELS 2 // Stereo
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000 // 48KHz
#define PRIMARY_OUTPUT_PERIOD_SIZE 480 // 480 frames, 10ms in case of 48KHz Stream
#define PRIMARY_OUTPUT_PERIOD_COUNT 4 // Total 7,680 Bytes(40ms) = 480 * 2(Stereo) * 2(16bit PCM) * 4(Buffers)
#define PRIMARY_OUTPUT_MAX_PERIOD_SIZE PRIMARY_OUTPUT_PERIOD_SIZE * PRIMARY_OUTPUT_PERIOD_COUNT
// Primary Stream use EAX Mixer
#define PRIMARY_OUTPUT_STOP_THREASHOLD PRIMARY_OUTPUT_MAX_PERIOD_SIZE - EAX_STOP_PERIOD_SIZE
#define LOW_LATENCY_OUTPUT_PERIOD_SIZE 480 // 480 frames, 10ms in case of 48KHz Stream
#define LOW_LATENCY_OUTPUT_PERIOD_COUNT 2 // Total 3,840 Bytes(20ms) = 480 * 2(Stereo) * 2(16bit PCM) * 2(Buffers)
#define LOW_LATENCY_OUTPUT_MAX_PERIOD_SIZE LOW_LATENCY_OUTPUT_PERIOD_SIZE * LOW_LATENCY_OUTPUT_PERIOD_COUNT
// LOW LATENCY(Fast) Stream doesn't use EAX Mixer
#define LOW_LATENCY_OUTPUT_STOP_THREASHOLD INT_MAX
#define DEEP_BUFFER_OUTPUT_PERIOD_SIZE 960 // 960 frames, 20ms in case of 48KHz Stream
#define DEEP_BUFFER_OUTPUT_PERIOD_COUNT 5 // Total 16,200 Bytes(100ms) = 960 * 2(Stereo) * 2(16bit PCM) * 5(Buffers)
#define DEEP_BUFFER_OUTPUT_MAX_PERIOD_SIZE DEEP_BUFFER_OUTPUT_PERIOD_SIZE * DEEP_BUFFER_OUTPUT_PERIOD_COUNT
// DEEP BUFFER Stream use EAX Mixer
#define DEEP_BUFFER_OUTPUT_STOP_THREASHOLD DEEP_BUFFER_OUTPUT_MAX_PERIOD_SIZE - EAX_STOP_PERIOD_SIZE
#define DEFAULT_INPUT_CHANNELS 2 // Stereo
#define DEFAULT_INPUT_SAMPLING_RATE 48000 // 48KHz
#define AUDIO_CAPTURE_PERIOD_SIZE 960 // 960 frames, 20ms in case of 48KHz Stream
#define AUDIO_CAPTURE_PERIOD_COUNT 2 // Total 7,680 Bytes = 960 * 2(Stereo) * 2(16bit PCM) * 2(Buffers)
#define DEFAULT_VOICE_CHANNELS 2 // Stereo
#define NB_VOICE_SAMPLING_RATE 8000 // 8KHz
#define WB_VOICE_SAMPLING_RATE 16000 // 16KHz
#define WB_VOICE_PERIOD_SIZE 160 //
#define WB_VOICE_PERIOD_COUNT 2 //
#define DEFAULT_BT_SCO_CHANNELS 1
#define BT_SCO_PERIOD_SIZE 128
#define BT_SCO_PERIOD_COUNT 2
/**
** These values are based on HW Decoder: Max Buffer Size = FRAGMENT_SIZE * NUM_FRAGMENTS
** 0 means that we will use the predefined value by device driver
**/
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE 0
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 0
#define COMPRESS_PLAYBACK_BUFFER_SIZE (1024 * 4) // min.fragment_size is fixed 4KBytes = 4 * 1024
#define COMPRESS_PLAYBACK_BUFFER_COUNT 5 // max.fragment is fixed 5
#define COMPRESS_PLAYBACK_VOLUME_MAX 8192
// Need to change to Exynos name, not Kiwi name
#define OFFLOAD_VOLUME_CONTROL_NAME "Compress Playback 3 Volume"
#define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20//Capture audio data during 20ms periods = 960 Samples for 48KHz
#endif

View File

@@ -0,0 +1,960 @@
/*
* Copyright (C) 2011 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.
*/
#define LOG_TAG "audio_hw_m86"
//#define LOG_NDEBUG 0
#include <cutils/properties.h>
#include "audio_hw.h"
#include "audio_hw_def.h"
#include <cutils/str_parms.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/**
* @brief get_output_device_id
*
* @param device
*
* @returns
*/
int get_output_device_id(audio_devices_t device)
{
if (device == AUDIO_DEVICE_NONE)
return OUT_DEVICE_NONE;
if (popcount(device) == 2) {
if ((device == (AUDIO_DEVICE_OUT_SPEAKER |
AUDIO_DEVICE_OUT_WIRED_HEADSET)) ||
(device == (AUDIO_DEVICE_OUT_SPEAKER |
AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
return OUT_DEVICE_SPEAKER_AND_HEADSET;
else
return OUT_DEVICE_NONE;
}
if (popcount(device) != 1)
return OUT_DEVICE_NONE;
switch (device) {
case AUDIO_DEVICE_OUT_SPEAKER:
return OUT_DEVICE_SPEAKER;
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
return OUT_DEVICE_HEADSET;
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
return OUT_DEVICE_HEADPHONES;
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
return OUT_DEVICE_BT_SCO;
default:
return OUT_DEVICE_NONE;
}
}
/**
* @brief get_input_source_id
*
* @param source
*
* @returns
*/
int get_input_source_id(audio_source_t source)
{
switch (source) {
case AUDIO_SOURCE_DEFAULT:
return IN_SOURCE_NONE;
case AUDIO_SOURCE_MIC:
return IN_SOURCE_MIC;
case AUDIO_SOURCE_CAMCORDER:
return IN_SOURCE_CAMCORDER;
case AUDIO_SOURCE_VOICE_RECOGNITION:
return IN_SOURCE_VOICE_RECOGNITION;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
return IN_SOURCE_VOICE_COMMUNICATION;
default:
return IN_SOURCE_NONE;
}
}
bool is_headphone_on()
{
FILE *file = fopen("/sys/class/switch/h2w/state", "r");
char buf[2] = {0};
if (file != NULL)
{
fread(buf, 1, 1, file);
fclose(file);
}
return atoi(buf) != 0;
}
bool amplifier_initialize(struct audio_device *adev){
bool started = false;
pthread_mutex_lock(adev->lock);
struct pcm *pcm = pcm_open(0, 2, 0, &pcm_config_amplifier);
if ( pcm == NULL || !pcm_is_ready(pcm) )
{
ALOGE("%s(): pcm_open(BACKEND) failed: %s", __func__,pcm_get_error(pcm));
started = false;
}
else
{
pcm_prepare(pcm);
struct pcm *pcm2 = pcm_open(0, 6, 0x10000000, &pcm_config_amplifier);
if ( pcm2 == NULL || !pcm_is_ready(pcm2) )
{
ALOGE("%s(): pcm_open(AMPLIFIER) failed: %s", __func__,pcm_get_error(pcm2));
started = false;
}
else
{
pcm_prepare(pcm2);
audio_route_reset(adev->audio_route);
audio_route_apply_path(adev->audio_route, "speaker");
audio_route_update_mixer(adev->audio_route);
pthread_mutex_unlock(adev->lock);
usleep(1000);
started = NxpTfa98xx_StartUp(pcm_config_amplifier.rate);
if ( started != 0)
ALOGE("%s(): failed to bring up tfa98xx", __func__);
usleep(1000);
}
pcm_close(pcm2);
}
pcm_close(pcm);
pthread_mutex_unlock(adev->lock);
return started;
}
int thread_refresh_audio_route(struct audio_device *adev)
{
ALOGE("%s(): enter", __func__);
int count = 0;
while ( true )
{
struct mixer *mixer = mixer_open(0);
if ( mixer == NULL )
{
ALOGE("%s(): Unable to open mixer", __func__);
return 0;
}
struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, "Internal Route");
mixer_close(mixer);
if ( ctl == NULL )
break;
usleep(50000);
if ( ++count >= 500 )
{
ALOGE("%s(): Waiting for escore being ready timeout", __func__);
return 0;
}
}
pthread_mutex_lock(adev->lock);
audio_route_free(adev->audio_route);
struct audio_route* audio_route = audio_route_init(0, "/system/etc/mixer_paths.xml");
adev->audio_route = audio_route;
if ( audio_route == NULL )
ALOGE( "%s(): failed to open audio route", __func__);
pthread_mutex_unlock(adev->lock);
if ( !amplifier_initialize(adev) )
ALOGE("%s(): failed to bring up amplifier, speaker will be silent", __func__);
else
property_set("primary.pa.ready", "1");
ALOGE("%s(): leave", __func__);
return 0;
}
// -----------
static uint32_t out_get_sample_rate(const struct audio_stream *stream)
{
return 44100;
}
static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
{
ALOGE("out_set_sample_rate: %d", 0);
return -ENOSYS;
}
static size_t out_get_buffer_size(const struct audio_stream *stream)
{
ALOGE("out_get_buffer_size: %d", 4096);
return 4096;
}
static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
{
ALOGE("out_get_channels");
return AUDIO_CHANNEL_OUT_STEREO;
}
static audio_format_t out_get_format(const struct audio_stream *stream)
{
ALOGE("out_get_format");
return AUDIO_FORMAT_PCM_16_BIT;
}
static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
ALOGE("out_set_format: %d",format);
return -ENOSYS;
}
static int out_standby(struct audio_stream *stream)
{
ALOGE("out_standby");
return 0;
}
static int out_dump(const struct audio_stream *stream, int fd)
{
ALOGE("out_dump");
return 0;
}
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
ALOGE("out_set_parameters");
return 0;
}
static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
{
ALOGV("%s: keys = %s", __func__, keys);
struct stream_out *out = (struct stream_out *)stream;
struct str_parms *query = str_parms_create_str(keys);
char *str;
char value[256];
struct str_parms *reply = str_parms_create();
size_t i, j;
int ret;
bool first = true;
ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
if (ret >= 0) {
value[0] = '\0';
i = 0;
/* the last entry in supported_channel_masks[] is always 0 */
while (out->supported_channel_masks[i] != 0) {
for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
if (!first) {
strcat(value, "|");
}
strcat(value, out_channels_name_to_enum_table[j].name);
first = false;
break;
}
}
i++;
}
str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
str = str_parms_to_str(reply);
} else {
ALOGV("str_parms_get_str failed !");
str = strdup("");
}
str_parms_destroy(query);
str_parms_destroy(reply);
return str;
}
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
ALOGE("out_get_latency");
return 0;
}
static int out_set_volume(struct audio_stream_out *stream, float left,
float right)
{
ALOGE("out_set_volume: Left:%f Right:%f", left, right);
return 0;
}
static int start_output_stream(){
return 0;
}
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
size_t bytes)
{
ALOGE("out_write: bytes: %d", bytes);
struct stream_out *out = (struct stream_out *)stream;
struct audio_device *adev = (struct audio_device *)out->adev;
size_t frame_size = audio_stream_out_frame_size(&out->stream.common);
size_t in_frames = bytes / frame_size;
size_t out_frames = 4 * out->pcmconfig.period_size * out->pcmconfig.period_count / frame_size;
pthread_mutex_lock(adev->lock);
pthread_mutex_lock(out->lock);
if ( out->disabled ){
int ret = start_output_stream();
if(ret != 0){
goto err_open;
}
}
pthread_mutex_unlock(adev->lock);
audio_format_t in_format = out->in_format;
if ( in_format != AUDIO_FORMAT_PCM_16_BIT && out->pcmconfig.format == PCM_FORMAT_S16_LE )
{
size_t frames = bytes >> 2;
for (i = 0; i < frames; i++) {
if ( in_format == AUDIO_FORMAT_PCM_8_24_BIT )
buffer[2*i] = (int16_t)((buffer[4*i]) >> 8);
else
buffer[2*i] = (int16_t)((buffer[4*i]) >> 16);
}
frame_size >>= 1;
in_frames = (bytes >> 1) / frame_size;
out_frames = 4 * pcmconfig_period_count * pcmconfig_period_size / frame_size;
}
return bytes;
err_open:
frame_size = audio_stream_out_frame_size(&out->stream.common);
usleep(1000000 * bytes / (out->in_sample_rate * frame_size));
return bytes;
}
static int out_get_render_position(const struct audio_stream_out *stream,
uint32_t *dsp_frames)
{
*dsp_frames = 0;
ALOGE("out_get_render_position: dsp_frames: %p", dsp_frames);
return -EINVAL;
}
static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
ALOGE("out_add_audio_effect: %p", effect);
return 0;
}
static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
ALOGE("out_remove_audio_effect: %p", effect);
return 0;
}
static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
int64_t *timestamp)
{
*timestamp = 0;
ALOGE("out_get_next_write_timestamp: %ld", (long int)(*timestamp));
return -EINVAL;
}
/** audio_stream_in implementation **/
static uint32_t in_get_sample_rate(const struct audio_stream *stream)
{
ALOGE("in_get_sample_rate");
return 8000;
}
static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
{
ALOGE("in_set_sample_rate: %d", rate);
return -ENOSYS;
}
static size_t in_get_buffer_size(const struct audio_stream *stream)
{
ALOGE("in_get_buffer_size: %d", 320);
return 320;
}
static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
{
ALOGE("in_get_channels: %d", AUDIO_CHANNEL_IN_MONO);
return AUDIO_CHANNEL_IN_MONO;
}
static audio_format_t in_get_format(const struct audio_stream *stream)
{
return AUDIO_FORMAT_PCM_16_BIT;
}
static int in_set_format(struct audio_stream *stream, audio_format_t format)
{
return -ENOSYS;
}
static int in_standby(struct audio_stream *stream)
{
struct stream_in *in = (struct stream_in *)stream;
return 0;
}
static int in_dump(const struct audio_stream *stream, int fd)
{
return 0;
}
static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
return 0;
}
static char * in_get_parameters(const struct audio_stream *stream,
const char *keys)
{
return strdup("");
}
static int in_set_gain(struct audio_stream_in *stream, float gain)
{
return 0;
}
static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
size_t bytes)
{
ALOGE("in_read: bytes %d", bytes);
struct stream_in *in = (struct stream_in *)stream;
return bytes;
}
static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
{
return 0;
}
static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
return 0;
}
static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
return 0;
}
static int get_output_buffer_size(struct stream_out *out){
return 4096;
}
static int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
struct audio_stream_out **stream_out,
const char *address __unused)
{
ALOGE("adev_open_output_stream...");
struct audio_device *ladev = (struct audio_device *)dev;
if ( ladev->output_stream_state )
{
ALOGE("%s(): output stream has been opened, abort...", __func__);
*stream_out = NULL;
return -22;
}
struct stream_out *out;
int ret;
out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
if (!out)
return -ENOMEM;
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
memset(out->supported_channel_masks, 0, sizeof(out->supported_channel_masks));
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
out->pcmconfig = pcmconfig;
out->stream.common.get_sample_rate = out_get_sample_rate;
out->stream.common.set_sample_rate = out_set_sample_rate;
out->stream.common.get_buffer_size = out_get_buffer_size;
out->stream.common.get_channels = out_get_channels;
out->stream.common.get_format = out_get_format;
out->stream.common.set_format = out_set_format;
out->stream.common.standby = out_standby;
out->stream.common.dump = out_dump;
out->stream.common.set_parameters = out_set_parameters;
out->stream.common.get_parameters = out_get_parameters;
out->stream.common.add_audio_effect = out_add_audio_effect;
out->stream.common.remove_audio_effect = out_remove_audio_effect;
out->stream.get_latency = out_get_latency;
out->stream.set_volume = out_set_volume;
out->stream.write = out_write;
out->stream.get_render_position = out_get_render_position;
out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
*stream_out = &out->stream;
out->in_sample_rate = 48000;
out->in_format = AUDIO_FORMAT_PCM_16_BIT;
out->output_buffer_size = get_output_buffer_size(out);
out->pcmconfig.period_size = out->output_buffer_size / audio_stream_out_frame_size(&out->stream.common);
config->format = out->in_format;
config->channel_mask = out->channel_mask;
config->sample_rate = out->in_sample_rate;
out->disabled = 1;
pthread_mutex_lock(ladev->lock);
if ( ladev->stream_out != NULL)
{
pthread_mutex_unlock(ladev->lock);
ALOGE("%s(): output device busy, abort...", "adev_open_output_stream");
ret = -EBUSY;
goto err_open;
}
ladev->stream_out = &out->stream;
ladev->output_stream_state = 1;
pthread_mutex_unlock(ladev->lock);
*stream_out = &out->stream;
return 0;
err_open:
free(out);
*stream_out = NULL;
return ret;
}
static void adev_close_output_stream(struct audio_hw_device *dev,
struct audio_stream_out *stream)
{
struct audio_device *ladev = (struct audio_device *)dev;
ALOGE("adev_close_output_stream...");
out_standby(&stream->common);
pthread_mutex_lock(ladev->lock);
if ( ladev->stream_out == stream )
ladev->stream_out = NULL;
ladev->output_stream_state = 0;
pthread_mutex_unlock(ladev->lock);
free(stream);
}
static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
{
ALOGE("adev_set_parameters");
return -ENOSYS;
}
static char * adev_get_parameters(const struct audio_hw_device *dev,
const char *keys)
{
ALOGE("adev_get_parameters");
return strdup("");
}
static int adev_init_check(const struct audio_hw_device *dev)
{
ALOGE("adev_init_check");
return 0;
}
static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
{
ALOGE("adev_set_voice_volume: %f", volume);
return -ENOSYS;
}
static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
{
ALOGE("adev_set_master_volume: %f", volume);
return -ENOSYS;
}
static int adev_set_headset_volume(struct audio_hw_device *dev, float volume)
{
ALOGE("adev_set_headset_volume: %f", volume);
return -ENOSYS;
}
static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
{
ALOGE("adev_get_master_volume: %f", *volume);
return -ENOSYS;
}
static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
{
ALOGE("adev_set_master_mute: %d", muted);
return -ENOSYS;
}
static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
{
ALOGE("adev_get_master_mute: %d", *muted);
return -ENOSYS;
}
static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
{
ALOGE("adev_set_mode: %d", mode);
return 0;
}
static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
{
ALOGE("adev_set_mic_mute: %d",state);
struct audio_device *ladev = (struct audio_device *)dev;
ladev->mic_mute_state = state;
return 0;
}
static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
{
struct audio_device *ladev = (struct audio_device *)dev;
ALOGE("adev_get_mic_mute");
*state = ladev->mic_mute_state;
return 0;
}
/**
* @brief get_next_buffer
*
* @param buffer_provider
* @param buffer
*
* @returns
*/
static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
struct resampler_buffer* buffer)
{
struct stream_in *in;
size_t i,size;
if (buffer_provider == NULL || buffer == NULL)
return -EINVAL;
in = (struct stream_in *)((char *)buffer_provider -
offsetof(struct stream_in, buf_provider));
if (in->pcm == NULL) {
buffer->raw = NULL;
buffer->frame_count = 0;
in->read_status = -ENODEV;
return -ENODEV;
}
if (in->frames_in == 0) {
size = pcm_frames_to_bytes(in->pcm,pcm_get_buffer_size(in->pcm));
in->read_status = pcm_read(in->pcm,
(void*)in->buffer,pcm_frames_to_bytes(in->pcm, in->config->period_size));
if (in->read_status != 0) {
ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
buffer->raw = NULL;
buffer->frame_count = 0;
return in->read_status;
}
//fwrite(in->buffer,pcm_frames_to_bytes(in->pcm,pcm_get_buffer_size(in->pcm)),1,in_debug);
in->frames_in = in->config->period_size;
/* Do stereo to mono conversion in place by discarding right channel */
if (in->frames_in >= 2) {
//ALOGE("channel_mask = AUDIO_CHANNEL_IN_MONO");
for (i = 0; i < in->frames_in; i++)
in->buffer[i] = in->buffer[i * 2];
}
}
//ALOGV("pcm_frames_to_bytes(in->pcm,pcm_get_buffer_size(in->pcm)):%d",size);
buffer->frame_count = (buffer->frame_count > in->frames_in) ?
in->frames_in : buffer->frame_count;
buffer->i16 = in->buffer +
(in->config->period_size - in->frames_in) *2;
return in->read_status;
}
/**
* @brief release_buffer
*
* @param buffer_provider
* @param buffer
*/
static void release_buffer(struct resampler_buffer_provider *buffer_provider,
struct resampler_buffer* buffer)
{
struct stream_in *in;
if (buffer_provider == NULL || buffer == NULL)
return;
in = (struct stream_in *)((char *)buffer_provider -
offsetof(struct stream_in, buf_provider));
in->frames_in -= buffer->frame_count;
}
static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
const struct audio_config *config)
{
unsigned int v5;
int v6;
v5 = popcount(config->channel_mask)
* ((pcm_config_in.period_size * config->sample_rate / pcm_config_in.rate + 15) & 0xFFFFFFF0);
switch ( config->format )
{
case AUDIO_FORMAT_PCM_16_BIT:
case AUDIO_FORMAT_IEC61937:
v6 = 2;
break;
case AUDIO_FORMAT_PCM_8_BIT:
v6 = 1;
break;
case AUDIO_FORMAT_PCM_32_BIT:
case AUDIO_FORMAT_PCM_8_24_BIT:
case AUDIO_FORMAT_PCM_FLOAT:
v6 = 4;
break;
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
v6 = 3;
break;
default:
v6 = 0;
break;
}
ALOGE("adev_get_input_buffer_size: %d", v5 * v6);
return v5 * v6;
}
static int adev_open_input_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
audio_input_flags_t flags __unused,
const char *address __unused,
audio_source_t source __unused)
{
ALOGE("adev_open_input_stream...");
struct audio_device *ladev = (struct audio_device *)dev;
struct stream_in *in;
int ret;
in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
if (!in)
return -ENOMEM;
in->stream.common.get_sample_rate = in_get_sample_rate;
in->stream.common.set_sample_rate = in_set_sample_rate;
in->stream.common.get_buffer_size = in_get_buffer_size;
in->stream.common.get_channels = in_get_channels;
in->stream.common.get_format = in_get_format;
in->stream.common.set_format = in_set_format;
in->stream.common.standby = in_standby;
in->stream.common.dump = in_dump;
in->stream.common.set_parameters = in_set_parameters;
in->stream.common.get_parameters = in_get_parameters;
in->stream.common.add_audio_effect = in_add_audio_effect;
in->stream.common.remove_audio_effect = in_remove_audio_effect;
in->stream.set_gain = in_set_gain;
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
*stream_in = &in->stream;
return 0;
err_open:
free(in);
*stream_in = NULL;
return ret;
}
static void adev_close_input_stream(struct audio_hw_device *dev,
struct audio_stream_in *in)
{
ALOGE("adev_close_input_stream...");
struct audio_device *adev = (struct audio_device *)dev;
struct stream_in *stream_in = (struct stream_in *)in;
struct stream_out *stream_out = (struct stream_out *)adev->stream_out;
in_standby(&in->common);
ALOGE("%s(): is_cvq=%d", "adev_close_input_stream", stream_in->is_cvq);
if ( stream_out
&& !adev->hifi_pcm_opened
&& (stream_out->in_sample_rate != pcm_config_in.rate || stream_out->in_format != AUDIO_FORMAT_PCM_16_BIT)
&& (!adev->asr_ready || stream_in->is_cvq)
&& adev->amode != AUDIO_MODE_IN_CALL ) {
out_standby(stream_out);
}
free(stream_in);
return;
}
static int adev_dump(const audio_hw_device_t *device, int fd)
{
ALOGE("adev_dump");
return 0;
}
static int adev_close(hw_device_t *device)
{
ALOGE("adev_close");
struct audio_device *adev = (struct audio_device *)device;
NxpTfa98xx_Stop();
mixer_close(adev->mixer);
mixer_close(adev->hifi_mixer);
audio_route_free(adev->audio_route);
free(device);
return 0;
}
static int adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
ALOGE("adev_open: %s", name);
struct audio_device *adev;
int ret;
if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
return -EINVAL;
adev = calloc(1, sizeof(struct audio_device));
if (!adev)
return -ENOMEM;
adev->device.common.tag = HARDWARE_DEVICE_TAG;
adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
adev->device.common.module = (struct hw_module_t *) module;
adev->device.common.close = adev_close;
adev->device.init_check = adev_init_check;
adev->device.set_voice_volume = adev_set_voice_volume;
adev->device.set_master_volume = adev_set_master_volume;
adev->device.get_master_volume = adev_get_master_volume;
adev->device.set_master_mute = adev_set_master_mute;
adev->device.get_master_mute = adev_get_master_mute;
adev->device.set_mode = adev_set_mode;
adev->device.set_mic_mute = adev_set_mic_mute;
adev->device.get_mic_mute = adev_get_mic_mute;
adev->device.set_parameters = adev_set_parameters;
adev->device.get_parameters = adev_get_parameters;
adev->device.get_input_buffer_size = adev_get_input_buffer_size;
adev->device.open_output_stream = adev_open_output_stream;
adev->device.close_output_stream = adev_close_output_stream;
adev->device.open_input_stream = adev_open_input_stream;
adev->device.close_input_stream = adev_close_input_stream;
adev->device.dump = adev_dump;
adev->device.set_headphone_volume = adev_set_headset_volume;
struct audio_route *audio_route = audio_route_init(0, "/system/etc/mixer_paths.xml");
adev->audio_route = audio_route;
if ( audio_route == NULL )
{
ALOGE("%s(): failed to open audio route, abort...", __func__);
free(adev);
return -12;
}
struct mixer *mixer = mixer_open(0);
if ( mixer == NULL )
{
ALOGE("%s(): failed to open mixer, abort...", __func__);
audio_route_free(adev->audio_route);
free(adev);
return -12;
}
adev->mixer = mixer;
struct mixer *hifi_mixer = mixer_open(1);
if ( hifi_mixer == NULL )
{
ALOGE("%s(): failed to open HiFi mixer, abort...", __func__);
mixer_close(adev->mixer);
audio_route_free(adev->audio_route);
free(adev);
return -12;
}
adev->hifi_mixer = hifi_mixer;
adev->in_source = AUDIO_SOURCE_DEFAULT;
adev->amode = AUDIO_MODE_NORMAL;
adev->adv_int_52 = 0;
adev->adv_int_53 = 0;
adev->tfa_power_state = 0;
adev->b_268 = 0;
adev->sample_rate = 48000;
adev->stream_in = 0;
adev->hifi_state = 0;
adev->dirac_state = 0;
adev->output_stream_state = 0;
adev->hifi_gain_state = 0;
adev->headset_volume = 28;
adev->headphone_volume = 56;
adev->adv_int_70 = 7;
adev->adv_int_71 = 7;
*device = &adev->device.common;
//Open();
thread_refresh_audio_route(adev);
char region[128];
char language[128];
property_get("ro.product.locale.region", region, "0");
property_get("ro.product.locale.language", language, "0");
ALOGE("%s:region=%s,language=%s", __func__, region, language);
bool is_oversea = strcmp(region, "CN") || strcmp(language, "zh");
adev->is_oversea = is_oversea;
ALOGE("%s:is_oversea=%d", __func__, adev->is_oversea);
return 0;
}
static struct hw_module_methods_t hal_module_methods = {
.open = adev_open,
};
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = AUDIO_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "m86 audio HW HAL",
.author = "The Android Open Source Project",
.methods = &hal_module_methods,
},
};

View File

@@ -0,0 +1,290 @@
/*
* Copyright (C) 2011 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 __EXYNOS_AUDIOHAL_H__
#define __EXYNOS_AUDIOHAL_H__
#include <errno.h>
#include <malloc.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
#include <cutils/log.h>
#include <hardware/hardware.h>
#include <system/audio.h>
#include <hardware/audio.h>
#include <audio_route/audio_route.h>
#include <audio_utils/resampler.h>
/* PCM Interface of ALSA & Compress Offload Interface */
#include <tinyalsa/asoundlib.h>
#include <tinycompress/tinycompress.h>
#include <compress_params.h>
#include <audio_utils/primitives.h>
enum {
OUT_DEVICE_SPEAKER,
OUT_DEVICE_HEADSET,
OUT_DEVICE_HEADPHONES,
OUT_DEVICE_BT_SCO,
OUT_DEVICE_SPEAKER_AND_HEADSET,
OUT_DEVICE_OFF,
OUT_DEVICE_TAB_SIZE, /* number of rows in route_configs[][] */
OUT_DEVICE_NONE,
OUT_DEVICE_CNT
};
enum {
IN_SOURCE_MIC,
IN_SOURCE_CAMCORDER,
IN_SOURCE_VOICE_RECOGNITION,
IN_SOURCE_VOICE_COMMUNICATION,
IN_SOURCE_OFF,
IN_SOURCE_TAB_SIZE, /* number of lines in route_configs[][] */
IN_SOURCE_NONE,
IN_SOURCE_CNT
};
enum {
PCM_CARD_PRIMARY,
PCM_CARD_HIFI,
PCM_CARD_SPDIF
};
struct stream_out;
struct stream_in;
// size : 0x140 -> 320
struct audio_device {
struct audio_hw_device device;
pthread_mutex_t *lock;// *+ 41 // adev + 164 /* see note below on mutex acquisition order */
audio_mode_t amode; // *+ 42 // adev + 168
audio_devices_t out_device; // out_device; // *+ 43 // adev + 172
// audio_devices_t :/system/media/audio/include/system/audio.h 844: typedef uint32_t audio_devices_t;
audio_devices_t in_device; // *+ 44 // adev + 176
bool mic_mute_state; // adev + 180
bool screen_state; // adev + 181
bool bt_headset_nrec; // adev + 182
bool voice_call_wb; // adev + 183
bool mic_nr_off; // adev + 184
bool b_185; // adev + 185
bool b_186; // adev + 186
bool b_187; // adev + 187
struct audio_route* audio_route;// *+ 47 // adev + 188
struct mixer *mixer;// * +48 // adev + 192
struct mixer *hifi_mixer;// * + 49 // adev + 196
audio_source_t in_source;// * + 50 // adev + 200
void *v_51;// * + 51 // adev + 204
int adv_int_52;// * + 52 // adev + 208
int adv_int_53;// * + 53 // adev + 212
void *v_54;// * + 54 // adev + 216
struct pcm *pcm_voice_out;// * + 55 // adev + 220 // VOICE_OUT
struct pcm *pcm_voice_in;// * + 56 // adev + 224 // VOICE_IN
struct pcm *pcm_be_out;// * + 57 // adev + 228 // VOICE_BE_OUT
struct pcm *pcm_be_in;// * + 58 // adev + 232 // VOICE_BE_IN
/* BT-SCO */
struct pcm *pcm_btsco_out;// * + 59 // adev + 236 // SCO_OUT
struct pcm *pcm_btsco_in;// * + 60 // adev + 240 // SCO_IN
struct pcm *pcm_pa_out;// * + 61 // adev + 244 // PA_OUT
struct pcm *pcm_pa_in;// * + 62 // adev + 248 // PA_IN
struct audio_stream_in *stream_in; // * + 63 // adev + 252
struct audio_stream_out *stream_out; // * + 64 // adev + 256
bool tfa_power_state; // adev + 260
bool mute_state; // adev + 261
bool b_262; // adev + 262
bool b_263; // adev + 263
uint32_t sample_rate; // * + 66 // adev + 264
bool b_268; // * + 67 // adev + 268
bool output_stream_state; // adev + 269
bool b_270; // adev + 270
bool b_271; // adev + 271
int headset_volume; // * + 68 // adev + 272
int headphone_volume; // * + 69 // adev + 276
int adv_int_70; // * + 70 // adev + 280
int adv_int_71; // * + 71 // adev + 284
bool hifi_state; // * + 72 // adev + 288
bool hifi_pcm_opened; // adev + 289
bool dirac_state; // adev + 290
bool b_291; // adev + 291
int hifi_gain_state; // * + 73 // adev + 292
int hifi_gain; // * + 74 // adev + 296
int hifi_volume; // * + 75 // adev + 300
bool is_oversea; // * + 76 // adev + 304
bool b_305; // adev + 305
bool b_306; // adev + 306
bool b_307; // adev + 307
int hifi_impedance; // * + 77 // adev + 308
bool messagerecord_state; // * + 78 // adev + 312
bool asr_ready; // adev + 313
bool b_314; // adev + 314
bool b_315; // adev + 315
void *adev_pcm_out_buffer; // * + 79 // adev + 316
};
// size : 0xD8 -> 216
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t *lock; // *out + 25 // out + 100
struct pcm *pcm; // *out + 26 // out + 104
struct pcm *hifi_pcm; // *out + 27 // out + 108
struct pcm *spdif_pcm; // *out + 28 // out + 112
struct pcm_config pcmconfig; // *out + 29 // out + 116 // size: 40
audio_devices_t devices; // *out + 39 // out + 156
bool disabled; // *out + 40 // out + 160
bool out_b_161;
bool out_b_162;
bool out_b_163;
audio_devices_t out_device; // *out + 41 // out + 164
audio_channel_mask_t channel_mask; // *out + 42 // out + 168
audio_channel_mask_t supported_channel_masks[3]; // *out + 43 // out + 172
int in_sample_rate; // *out + 46 // out + 184
audio_format_t in_format; // *out + 47 // out + 188
size_t output_buffer_size; // *out + 48 // out + 192
struct resampler_itfe *resampler; // *out + 49 // out + 196
void *out_resampler_pcm_out_buffer; // *out + 50 // out + 200
struct audio_device *adev; // *out + 51 // out + 204
uint64_t written;//out_v_208; // *out + 52 // out + 208
//void *out_v_212; // *out + 53 // out + 212
};
// size : 0x4E264 -> 1161144
struct CVQStream {
unsigned int *L_0;
void *cvq_v_4;// + 4
int cvq_int_8;// + 8
void *cvq_v_12;// + 12
void *cvq_v_16;// + 16
pthread_t *read_on_raw_data_thread; // +20
void *cvq_v_24; // +24
void *cvq_v_28; // +28
pthread_t *read_on_thread; //+ 32
void *cvq_v_36_320036[80001];// + 20 - 320036
void *cvq_v_320040;// + 320040
void *cvq_v_320044;// + 320044
void *cvq_v_320048;// + 320048
void *cvq_v_320052;// + 320052
FILE *uart_char_dev;// + 320056
void *cvq_v_320060;// + 320060
void *cvq_v_320064;// + 320064
void *cvq_v_320068;// + 320068
int exit;// + 320072
int (*cvq_open)();// + 320076
int (*cvq_close)();// + 320080
int (*cvq_start)();// + 320084
int (*readdirect)();// + 320088
int (*cvq_read)();// + 320092
int (*pcm_read_uart_char_dev)();// + 320096
void *cvq_v_320100_1161140[210260];// + 320100 - 1161140
};
// size : 0xB0 -> 176
struct stream_in {
struct audio_stream_in stream;
struct CVQStream * cvqStream;// *in + 17 // in + 68
int is_cvq;/// *in + 18 // in + 72
int in_int_76;/// *in + 19 // in + 76
pthread_t *pcm_read_thread;/// *in + 20 // in + 80
int in_int_84;/// *in + 21 // in + 84
int read_size;/// *in + 22 // in + 88
void *in_v_92;/// *in + 23 // in + 92
int max_bytes;/// *in + 24 // in + 96
int read_offset;/// *in + 25 // in + 100
int write_offset;/// *in + 26 // in + 104
int write_size;/// *in + 27 // in + 108
void *in_v_112;/// *in + 28 // in + 112
pthread_mutex_t *lock;// *in + 29 // in + 116
struct pcm *pcm; // *in + 30 // in + 120
bool in_b_124; // *in + 31 // in + 124
bool in_b_125; // in + 125
bool in_b_126; // in + 126
bool in_b_127; // in + 127
struct pcm_config *config; // *in + 32 // in + 128
struct resampler_itfe *resampler;/// *in + 33 // in + 132
struct resampler_buffer_provider buf_provider;/// *in + 34 // in + 136
//int in_int_140;/// *in + 35 // in + 140
int16_t *buffer;/// *in + 36 // in + 144
size_t frames_in;/// *in + 37 // in + 148
int read_status;/// *in + 38 // in + 152
audio_source_t in_source;/// *in + 39 // in + 156
audio_devices_t devices; // *in + 40 // in + 160
void *in_v_164;/// *in + 41 // in + 164
void *in_v_168;/// *in + 42 // in + 168
struct audio_device *adev; // *in + 43 // in + 172
};
struct mixer_route_settings {
char *ctl_name;
int i_value;
char *s_value;
};
// Tfa98xx fun
extern int NxpTfa98xx_Stop();
extern bool NxpTfa98xx_StartUp(int in_sample_rate);
#endif // __EXYNOS_AUDIOHAL_H__

View File

@@ -0,0 +1,206 @@
#ifndef __EXYNOS_AUDIOHAL_DEF_H__
#define __EXYNOS_AUDIOHAL_DEF_H__
#include <system/audio.h>
struct pcm_config pcmconfig = {
.channels = 2,
.rate = 48000,
.period_size = 4096,
.period_count = 2,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = 0,
.silence_threshold = 0,
.silence_size = 0,
.avail_min = 0
};
struct pcm_config pcm_config_in = {
.channels = 2,
.rate = 48000,
.period_size = 1024,
.period_count = 4,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = 0,
.silence_threshold = 0,
.silence_size = 0,
.avail_min = 0
};
struct pcm_config pcm_config_voice_call = {
.channels = 1,
.rate = 16000,
.period_size = 512,
.period_count = 2,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = 0,
.silence_threshold = 0,
.silence_size = 0,
.avail_min = 0
};
struct pcm_config pcm_config_backend = {
.channels = 2,
.rate = 48000,
.period_size = 4096,
.period_count = 2,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = 0,
.silence_threshold = 0,
.silence_size = 0,
.avail_min = 0
};
struct pcm_config pcm_config_sco = {
.channels = 2,
.rate = 8000,
.period_size = 1024,
.period_count = 2,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = 0,
.silence_threshold = 0,
.silence_size = 0,
.avail_min = 0
};
struct pcm_config pcm_config_amplifier = {
.channels = 2,
.rate = 48000,
.period_size = 1024,
.period_count = 4,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = 0,
.silence_threshold = 0,
.silence_size = 0,
.avail_min = 0
};
struct mixer_route_settings default_settings[9] = {
{"ES705 RX1 Enable",0,NULL},
{"Internal Route",1,NULL},
{"EPOUT Digital Switch",0,NULL},
{"Headphone Switch",0,NULL},
{"IN2 Volume",18,NULL},
{"Earpiece Switch",1,NULL},
{"Headphone Switch",1,NULL},
{"HPOUTL Input 1",0,"IN2L"},
{"Headset Mic Switch",1,NULL}
};
struct mixer_route_settings test_earphones[9] = {
{"IN2MUX Input",0,"IN2B"},
{"IN2 Volume",18,NULL},
{"EPOUT Input 1",0,"IN2L"},
{"Earpiece Switch",1,NULL},
{"HPOUT Digital Volume",128,NULL},
{"Internal Route",1,NULL},
{"HPOUT Digital Volume",112,NULL},
{"ISRC2INT1 Input",0,"IN2L"},
{"HPOUTL Input 1",0,"AIF1RX1"}
};
struct mixer_route_settings test_headphone[9] = {
{"ES705 RX1 Enable",0,NULL},
{"Internal Route",1,NULL},
{"IN2 Volume",18,NULL},
{"HPOUTR Input 1",0,"IN2L"},
{NULL,0,NULL},
{"ISRC2INT2 Input",0,"IN2L"},
{"Internal Route",91,NULL},
{"Internal Route",91,NULL},
{"Internal Route",90,NULL}
};
struct mixer_route_settings test_speaker[9] = {
{"IN2MUX Input",0,"IN2B"},
{"IN2 Volume",26,NULL},
{"ISRC2INT1 Input",0,"IN2L"},
{"AIF3TX2 Input 1",0,"ISRC2INT2"},
{"Internal Route",91,NULL},
{NULL,0,NULL},
{"HPOUT Digital Switch",1,NULL},
{"HPOUT Digital Volume",128,NULL},
{"ES705 RX1 Enable",1,NULL}
};
struct mixer_route_settings test_pri_mic[9] = {
{"ES705 RX1 Enable",1,NULL},
{"Internal Route",91,NULL},
{"HPOUTR Input 1",0,"AIF1RX1"},
{"Headphone Switch",1,NULL},
{"HPOUTL Input 1",0,"AIF1RX1"},
{"AIF1TX1 Input 1",0,"IN2L"},
{"Internal Route",92,NULL},
{"Earpiece Switch",1,NULL},
{"IN1MUXL Input",0,"IN1A"}
};
struct mixer_route_settings test_sec_mic[9] = {
{"ES705 RX1 Enable",1,NULL},
{"Internal Route",90,NULL},
{"HPOUTR Input 1",0,"AIF1RX1"},
{"Headphone Switch",1,NULL},
{"Sec Mic Switch",1,NULL},
{"IN2 Volume",18,NULL},
{"HPOUTL Input 1",0,"AIF1RX1"},
{"IN1MUXL Input",0,"IN1A"},
{"Earpiece Switch",1,NULL}
};
struct mixer_route_settings test_ter_mic[9] = {
{"ES705 RX1 Enable",1,NULL},
{"Internal Route",92,NULL},
{"IN2 Volume",18,NULL},
{"EPOUT Digital Volume",144,NULL},
{"HPOUTR Input 1",0,"AIF1RX1"},
{"AIF1TX2 Input 1",0,"IN1L"},
{"EPOUT Input 1",0,"AIF1RX1"},
{"Sec Mic Switch",1,NULL},
{"AIF1TX2 Input 1",0,"IN2L"}
};
struct mixer_route_settings test_modem_loopback_earphone[9] = {
{"ES705 RX1 Enable",1,NULL},
{"Internal Route",93,NULL},
{"EPOUT Digital Volume",128,NULL},
{"AIF1TX1 Input 1",0,"IN2L"},
{NULL,0,NULL},
{"Headset Mic Switch",1,NULL},
{"HPOUT Digital Switch",1,NULL},
{NULL,0,NULL},
{NULL,0,NULL}
};
struct mixer_route_settings test_modem_loopback_headphone[9] = {
{"ES705 RX1 Enable",1,NULL},
{"Internal Route",94,NULL},
{"IN2 Volume",18,NULL},
{"AIF1TX2 Input 1",0,"IN2L"},
{"HPOUT Digital Switch",1,NULL},
{NULL,0,NULL},
{NULL,0,NULL},
{NULL,0,NULL},
{NULL,0,NULL}
};
#define STRING_TO_ENUM(string) { #string, string }
struct string_to_enum {
const char *name;
uint32_t value;
};
static const struct string_to_enum out_channels_name_to_enum_table[] = {
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
};
#endif // __EXYNOS_AUDIOHAL_DEF_H__

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2011 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.
*/
#define LOG_TAG "audio_hw_m86"
//#define LOG_NDEBUG 0
#include "audio_hw.h"
#include <system/audio.h>
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
typedef struct mixer_route_settings {
char *ctl_name;
int i_value;
char *s_value;
} settings_t;
void print_pcm_config(void* so_handle, char *name){
struct pcm_config *settings = (struct pcm_config *)dlsym(so_handle, name);
if (settings == NULL) {
printf("ERROR:%s:dlsym\n", dlerror());
return;
}
printf("------%s-----\n", name);
printf("{\n");
printf("channels -> %u\n",settings-> channels);
printf("rate -> %u\n",settings-> rate);
printf("period_size -> %u\n",settings-> period_size);
printf("period_count -> %u\n",settings-> period_count);
printf("format -> %d\n",settings-> format);
printf("start_threshold -> %u\n",settings-> start_threshold);
printf("stop_threshold -> %u\n",settings-> stop_threshold);
printf("silence_threshold -> %u\n",settings-> silence_threshold);
printf("silence_size -> %u\n",settings-> silence_size);
printf("avail_min -> %d\n",settings-> avail_min);
printf("}\n");
printf("------%s-----\n", name);
}
void print_mixer_route_settings(void* so_handle, char *name){
settings_t *settings = (settings_t *)dlsym(so_handle, name);
if (settings == NULL) {
printf("ERROR:%s:dlsym\n", dlerror());
return;
}
printf("------%s-----\n", name);
for(int i = 0;i < 9; i++){
settings = settings + i;
printf("{\"%s\"", settings-> ctl_name);
printf(",%d", settings-> i_value);
if(settings-> s_value == NULL){
printf(",NULL}\n");
}else{
printf(",\"%s\"}\n", settings-> s_value);
}
}
printf("------%s-----\n", name);
}
int main(int argc, char **argv) {
void* so_handle = dlopen("/system/lib/hw/audio.primary.m86.so",RTLD_NOW);
if (so_handle == NULL) {
printf("ERROR:%s:dlopen\n", dlerror());
return -1;
}
print_mixer_route_settings(so_handle,"default_settings");
print_mixer_route_settings(so_handle,"test_earphones");
print_mixer_route_settings(so_handle,"test_headphone");
print_mixer_route_settings(so_handle,"test_speaker");
print_mixer_route_settings(so_handle,"test_pri_mic");
print_mixer_route_settings(so_handle,"test_sec_mic");
print_mixer_route_settings(so_handle,"test_ter_mic");
print_mixer_route_settings(so_handle,"test_modem_loopback_earphone");
print_mixer_route_settings(so_handle,"test_modem_loopback_headphone");
print_pcm_config(so_handle,"pcm_config");
print_pcm_config(so_handle,"pcm_config_in");
print_pcm_config(so_handle,"pcm_config_voice_call");
print_pcm_config(so_handle,"pcm_config_backend");
print_pcm_config(so_handle,"pcm_config_sco");
print_pcm_config(so_handle,"pcm_config_amplifier");
dlclose(so_handle);
return 0;
}

View File

@@ -0,0 +1,373 @@
/system/lib/hw/audio.primary.m86.so
m86:/cache # ./audio_print_config
------default_settings-----
{"ES705 RX1 Enable",0,NULL}
{"Internal Route",1,NULL}
{"EPOUT Digital Switch",0,NULL}
{"Headphone Switch",0,NULL}
{"IN2 Volume",18,NULL}
{"Earpiece Switch",1,NULL}
{"Headphone Switch",1,NULL}
{"HPOUTL Input 1",0,"IN2L"}
{"Headset Mic Switch",1,NULL}
------default_settings-----
------test_earphones-----
{"IN2MUX Input",0,"IN2B"}
{"IN2 Volume",18,NULL}
{"EPOUT Input 1",0,"IN2L"}
{"Earpiece Switch",1,NULL}
{"HPOUT Digital Volume",128,NULL}
{"Internal Route",1,NULL}
{"HPOUT Digital Volume",112,NULL}
{"ISRC2INT1 Input",0,"IN2L"}
{"HPOUTL Input 1",0,"AIF1RX1"}
------test_earphones-----
------test_headphone-----
{"ES705 RX1 Enable",0,NULL}
{"Internal Route",1,NULL}
{"IN2 Volume",18,NULL}
{"HPOUTR Input 1",0,"IN2L"}
{"(null)",0,NULL}
{"ISRC2INT2 Input",0,"IN2L"}
{"Internal Route",91,NULL}
{"Internal Route",91,NULL}
{"Internal Route",90,NULL}
------test_headphone-----
------test_speaker-----
{"IN2MUX Input",0,"IN2B"}
{"IN2 Volume",26,NULL}
{"ISRC2INT1 Input",0,"IN2L"}
{"AIF3TX2 Input 1",0,"ISRC2INT2"}
{"Internal Route",91,NULL}
{"(null)",0,NULL}
{"HPOUT Digital Switch",1,NULL}
{"HPOUT Digital Volume",128,NULL}
{"ES705 RX1 Enable",1,NULL}
------test_speaker-----
------test_pri_mic-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",91,NULL}
{"HPOUTR Input 1",0,"AIF1RX1"}
{"Headphone Switch",1,NULL}
{"HPOUTL Input 1",0,"AIF1RX1"}
{"AIF1TX1 Input 1",0,"IN2L"}
{"Internal Route",92,NULL}
{"Earpiece Switch",1,NULL}
{"IN1MUXL Input",0,"IN1A"}
------test_pri_mic-----
------test_sec_mic-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",90,NULL}
{"HPOUTR Input 1",0,"AIF1RX1"}
{"Headphone Switch",1,NULL}
{"Sec Mic Switch",1,NULL}
{"IN2 Volume",18,NULL}
{"HPOUTL Input 1",0,"AIF1RX1"}
{"IN1MUXL Input",0,"IN1A"}
{"Earpiece Switch",1,NULL}
------test_sec_mic-----
------test_ter_mic-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",92,NULL}
{"IN2 Volume",18,NULL}
{"EPOUT Digital Volume",144,NULL}
{"HPOUTR Input 1",0,"AIF1RX1"}
{"AIF1TX2 Input 1",0,"IN1L"}
{"EPOUT Input 1",0,"AIF1RX1"}
{"Sec Mic Switch",1,NULL}
{"AIF1TX2 Input 1",0,"IN2L"}
------test_ter_mic-----
------test_modem_loopback_earphone-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",93,NULL}
{"EPOUT Digital Volume",128,NULL}
{"AIF1TX1 Input 1",0,"IN2L"}
{"(null)",0,NULL}
{"Headset Mic Switch",1,NULL}
{"HPOUT Digital Switch",1,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
------test_modem_loopback_earphone-----
------test_modem_loopback_headphone-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",94,NULL}
{"IN2 Volume",18,NULL}
{"AIF1TX2 Input 1",0,"IN2L"}
{"HPOUT Digital Switch",1,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
------test_modem_loopback_headphone-----
------pcm_config-----
{
channels -> 2
rate -> 48000
period_size -> 4096
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config-----
------pcm_config_in-----
{
channels -> 2
rate -> 48000
period_size -> 1024
period_count -> 4
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_in-----
------pcm_config_voice_call-----
{
channels -> 1
rate -> 16000
period_size -> 512
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_voice_call-----
------pcm_config_backend-----
{
channels -> 2
rate -> 48000
period_size -> 4096
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_backend-----
------pcm_config_sco-----
{
channels -> 2
rate -> 8000
period_size -> 1024
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_sco-----
------pcm_config_amplifier-----
{
channels -> 2
rate -> 48000
period_size -> 1024
period_count -> 4
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_amplifier-----
/system/lib64/hw/audio.primary.m86.so
~ # /cache/audio_print_config
------default_settings-----
{"ES705 RX1 Enable",0,NULL}
{"Internal Route",1,NULL}
{"EPOUT Digital Switch",0,NULL}
{"Headphone Switch",0,NULL}
{"IN2 Volume",18,NULL}
{"Earpiece Switch",1,NULL}
{"Headphone Switch",1,NULL}
{"HPOUTL Input 1",0,"IN2L"}
{"Headset Mic Switch",1,NULL}
------default_settings-----
------test_earphones-----
{"IN2MUX Input",0,"IN2B"}
{"IN2 Volume",18,NULL}
{"EPOUT Input 1",0,"IN2L"}
{"Earpiece Switch",1,NULL}
{"HPOUT Digital Volume",128,NULL}
{"Internal Route",1,NULL}
{"HPOUT Digital Volume",112,NULL}
{"ISRC2INT1 Input",0,"IN2L"}
{"HPOUTL Input 1",0,"AIF1RX1"}
------test_earphones-----
------test_headphone-----
{"ES705 RX1 Enable",0,NULL}
{"Internal Route",1,NULL}
{"IN2 Volume",18,NULL}
{"HPOUTR Input 1",0,"IN2L"}
{"(null)",0,NULL}
{"ISRC2INT2 Input",0,"IN2L"}
{"Internal Route",91,NULL}
{"Internal Route",91,NULL}
{"Internal Route",90,NULL}
------test_headphone-----
------test_speaker-----
{"IN2MUX Input",0,"IN2B"}
{"IN2 Volume",26,NULL}
{"ISRC2INT1 Input",0,"IN2L"}
{"AIF3TX2 Input 1",0,"ISRC2INT2"}
{"Internal Route",91,NULL}
{"(null)",0,NULL}
{"HPOUT Digital Switch",1,NULL}
{"HPOUT Digital Volume",128,NULL}
{"ES705 RX1 Enable",1,NULL}
------test_speaker-----
------test_pri_mic-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",91,NULL}
{"HPOUTR Input 1",0,"AIF1RX1"}
{"Headphone Switch",1,NULL}
{"HPOUTL Input 1",0,"AIF1RX1"}
{"AIF1TX1 Input 1",0,"IN2L"}
{"Internal Route",92,NULL}
{"Earpiece Switch",1,NULL}
{"IN1MUXL Input",0,"IN1A"}
------test_pri_mic-----
------test_sec_mic-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",90,NULL}
{"HPOUTR Input 1",0,"AIF1RX1"}
{"Headphone Switch",1,NULL}
{"Sec Mic Switch",1,NULL}
{"IN2 Volume",18,NULL}
{"HPOUTL Input 1",0,"AIF1RX1"}
{"IN1MUXL Input",0,"IN1A"}
{"Earpiece Switch",1,NULL}
------test_sec_mic-----
------test_ter_mic-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",92,NULL}
{"IN2 Volume",18,NULL}
{"EPOUT Digital Volume",144,NULL}
{"HPOUTR Input 1",0,"AIF1RX1"}
{"AIF1TX2 Input 1",0,"IN1L"}
{"EPOUT Input 1",0,"AIF1RX1"}
{"Sec Mic Switch",1,NULL}
{"AIF1TX2 Input 1",0,"IN2L"}
------test_ter_mic-----
------test_modem_loopback_earphone-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",93,NULL}
{"EPOUT Digital Volume",128,NULL}
{"AIF1TX1 Input 1",0,"IN2L"}
{"(null)",0,NULL}
{"Headset Mic Switch",1,NULL}
{"HPOUT Digital Switch",1,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
------test_modem_loopback_earphone-----
------test_modem_loopback_headphone-----
{"ES705 RX1 Enable",1,NULL}
{"Internal Route",94,NULL}
{"IN2 Volume",18,NULL}
{"AIF1TX2 Input 1",0,"IN2L"}
{"HPOUT Digital Switch",1,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
{"(null)",0,NULL}
------test_modem_loopback_headphone-----
------pcm_config-----
{
channels -> 2
rate -> 48000
period_size -> 4096
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config-----
------pcm_config_in-----
{
channels -> 2
rate -> 48000
period_size -> 1024
period_count -> 4
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_in-----
------pcm_config_voice_call-----
{
channels -> 1
rate -> 16000
period_size -> 512
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_voice_call-----
------pcm_config_backend-----
{
channels -> 2
rate -> 48000
period_size -> 4096
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_backend-----
------pcm_config_sco-----
{
channels -> 2
rate -> 8000
period_size -> 1024
period_count -> 2
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_sco-----
------pcm_config_amplifier-----
{
channels -> 2
rate -> 48000
period_size -> 1024
period_count -> 4
format -> 0
start_threshold -> 0
stop_threshold -> 0
silence_threshold -> 0
silence_size -> 0
avail_min -> 0
}
------pcm_config_amplifier-----

View File

@@ -0,0 +1,315 @@
/* tinyplay.c
**
** Copyright 2011, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of The Android Open Source Project nor the names of
** its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
** DAMAGE.
*/
#include <tinyalsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <audio_route/audio_route.h>
#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
#define ID_FMT 0x20746d66
#define ID_DATA 0x61746164
struct riff_wave_header {
uint32_t riff_id;
uint32_t riff_sz;
uint32_t wave_id;
};
struct chunk_header {
uint32_t id;
uint32_t sz;
};
struct chunk_fmt {
uint16_t audio_format;
uint16_t num_channels;
uint32_t sample_rate;
uint32_t byte_rate;
uint16_t block_align;
uint16_t bits_per_sample;
};
static int close = 0;
void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
unsigned int rate, unsigned int bits, unsigned int period_size,
unsigned int period_count);
void stream_close(int sig)
{
/* allow the stream to be closed gracefully */
signal(sig, SIG_IGN);
close = 1;
}
int main(int argc, char **argv)
{
FILE *file;
struct riff_wave_header riff_wave_header;
struct chunk_header chunk_header;
struct chunk_fmt chunk_fmt;
unsigned int device = 0;
unsigned int card = 0;
unsigned int period_size = 1024;
unsigned int period_count = 4;
char *filename;
int more_chunks = 1;
if (argc < 2) {
fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]"
" [-n n_periods] \n", argv[0]);
return 1;
}
filename = argv[1];
file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
return 1;
}
fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
if ((riff_wave_header.riff_id != ID_RIFF) ||
(riff_wave_header.wave_id != ID_WAVE)) {
fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
fclose(file);
return 1;
}
do {
fread(&chunk_header, sizeof(chunk_header), 1, file);
switch (chunk_header.id) {
case ID_FMT:
fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
/* If the format header is larger, skip the rest */
if (chunk_header.sz > sizeof(chunk_fmt))
fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
break;
case ID_DATA:
/* Stop looking for chunks */
more_chunks = 0;
break;
default:
/* Unknown chunk, skip bytes */
fseek(file, chunk_header.sz, SEEK_CUR);
}
} while (more_chunks);
/* parse command line arguments */
argv += 2;
while (*argv) {
if (strcmp(*argv, "-d") == 0) {
argv++;
if (*argv)
device = atoi(*argv);
}
if (strcmp(*argv, "-p") == 0) {
argv++;
if (*argv)
period_size = atoi(*argv);
}
if (strcmp(*argv, "-n") == 0) {
argv++;
if (*argv)
period_count = atoi(*argv);
}
if (strcmp(*argv, "-D") == 0) {
argv++;
if (*argv)
card = atoi(*argv);
}
if (*argv)
argv++;
}
play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
chunk_fmt.bits_per_sample, period_size, period_count);
fclose(file);
return 0;
}
int check_param(struct pcm_params *params, unsigned int param, unsigned int value,
char *param_name, char *param_unit)
{
unsigned int min;
unsigned int max;
int is_within_bounds = 1;
min = pcm_params_get_min(params, param);
if (value < min) {
fprintf(stderr, "%s is %u%s, device only supports >= %u%s\n", param_name, value,
param_unit, min, param_unit);
is_within_bounds = 0;
}
max = pcm_params_get_max(params, param);
if (value > max) {
fprintf(stderr, "%s is %u%s, device only supports <= %u%s\n", param_name, value,
param_unit, max, param_unit);
is_within_bounds = 0;
}
return is_within_bounds;
}
int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels,
unsigned int rate, unsigned int bits, unsigned int period_size,
unsigned int period_count)
{
struct pcm_params *params;
int can_play;
params = pcm_params_get(card, device, PCM_OUT);
if (params == NULL) {
fprintf(stderr, "Unable to open PCM device %u.\n", device);
return 0;
}
can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz");
can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels");
can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits");
can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", "Hz");
can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", "Hz");
pcm_params_free(params);
return can_play;
}
extern void NxpTfa98xx_StartUp(int in_sample_rate);
void set_mixer_value_by_name(struct mixer *mixer, char* a2, int a3);
void set_mixer(unsigned int rate){
struct audio_route * audio_route = audio_route_init(0, "/system/etc/mixer_paths.xml");
audio_route_reset(audio_route);
audio_route_apply_path(audio_route, "speaker");
audio_route_update_mixer(audio_route);
struct mixer *mixer = mixer_open(1);
printf("play_sample(): set hifi gain: 2, 12\n");
set_mixer_value_by_name(mixer, "Gain selection", 2);
set_mixer_value_by_name(mixer, "Master Playback Volume", 12);
set_mixer_value_by_name(mixer, "Filter Shape", 1);
set_mixer_value_by_name(mixer, "bypass IIR", 1);
set_mixer_value_by_name(mixer, "THD Compensation", 1);
set_mixer_value_by_name(mixer, "2nd Harmonic Compensation", 0);
set_mixer_value_by_name(mixer, "3nd Harmonic Compensation", 254);
mixer_close(mixer);
NxpTfa98xx_StartUp(rate);
}
void set_mixer_value_by_name(struct mixer *mixer, char* a2, int a3)
{
struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, a2);
unsigned int result = mixer_ctl_get_num_values(ctl);
unsigned int i = 0;
for ( i = 0; i < result; ++i )
{
mixer_ctl_set_value(ctl, i, a3);
}
}
void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
unsigned int rate, unsigned int bits, unsigned int period_size,
unsigned int period_count)
{
struct pcm_config config = {0};
struct pcm *pcm;
char *buffer;
int size;
int num_read;
memset(&config, 0, sizeof(config));
config.channels = channels;
config.rate = rate;
config.period_size = period_size;
config.period_count = period_count;
if (bits == 32)
config.format = PCM_FORMAT_S32_LE;
else if (bits == 16)
config.format = PCM_FORMAT_S16_LE;
config.start_threshold = 0;
config.stop_threshold = 0;
config.silence_threshold = 0;
if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) {
return;
}
pcm = pcm_open(card, device, PCM_OUT, &config);
if (!pcm || !pcm_is_ready(pcm)) {
fprintf(stderr, "Unable to open PCM device %u (%s)\n",
device, pcm_get_error(pcm));
return;
}
set_mixer(rate);
size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
buffer = malloc(size);
if (!buffer) {
fprintf(stderr, "Unable to allocate %d bytes\n", size);
free(buffer);
pcm_close(pcm);
return;
}
printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits);
/* catch ctrl-c to shutdown cleanly */
signal(SIGINT, stream_close);
do {
num_read = fread(buffer, 1, size, file);
if (num_read > 0) {
if (pcm_write(pcm, buffer, num_read)) {
fprintf(stderr, "Error playing sample\n");
break;
}
}
} while (!close && num_read > 0);
free(buffer);
pcm_close(pcm);
}