commit bbcdf238a93a85f0826ca66a2284f0ad6a411d2f Author: Martmists Date: Tue Jul 27 09:47:15 2021 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a98bb5f --- /dev/null +++ b/.gitignore @@ -0,0 +1,139 @@ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/ + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### C template +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +### C++ template +# Prerequisites + +# Compiled Object files +*.slo + +# Precompiled Headers + +# Compiled Dynamic libraries + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai + +# Executables + +### CMake template +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +*.cbp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cee13dd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.19) + +project("ViPER4Android Reworked") + +set(CMAKE_CXX_COMPILER_VERSION 20) + +include_directories("include/") + +set(FILES + # Main + src/Effect.cpp + src/ProcessUnit_FX.cpp + src/viper.cpp + + # Effects + src/effects/Cure.cpp + src/effects/TubeSimulator.cpp + + # Utils + src/utils/CAllpassFilter.cpp + src/utils/Crossfeed.cpp + src/utils/FixedBiquad.cpp + src/utils/IIR_1st.cpp + src/utils/IIR_NOrder_BW_BP.cpp + src/utils/IIR_NOrder_BW_LH.cpp + src/utils/MultiBiquad.cpp + src/utils/PassFilter.cpp + src/utils/TimeConstDelay.cpp +) + +add_library( + # Sets the name of the library. + v4afx_r + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + ${FILES}) + diff --git a/include/hardware/audio_effect.h b/include/hardware/audio_effect.h new file mode 100644 index 0000000..2955a23 --- /dev/null +++ b/include/hardware/audio_effect.h @@ -0,0 +1,1026 @@ +/* + * 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 ANDROID_AUDIO_EFFECT_H +#define ANDROID_AUDIO_EFFECT_H + +#include +#include +#include +#include +#include + +#include "system/cutils/bitops.h" + +#include "system/audio.h" + + +__BEGIN_DECLS + + +///////////////////////////////////////////////// +// Common Definitions +///////////////////////////////////////////////// + +// +//--- Effect descriptor structure effect_descriptor_t +// + +// Unique effect ID (can be generated from the following site: +// http://www.itu.int/ITU-T/asn1/uuid.html) +// This format is used for both "type" and "uuid" fields of the effect descriptor structure. +// - When used for effect type and the engine is implementing and effect corresponding to a standard +// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface. +// - When used as uuid, it should be a unique UUID for this particular implementation. +typedef struct effect_uuid_s +{ + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} effect_uuid_t; + +// Maximum length of character strings in structures defines by this API. +#define EFFECT_STRING_LEN_MAX 64 + +// NULL UUID definition (matches SL_IID_NULL_) +#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \ + { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } } +static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER; +static const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_; +static const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210"; + + +// The effect descriptor contains necessary information to facilitate the enumeration of the effect +// engines present in a library. +typedef struct effect_descriptor_s +{ + effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect + effect_uuid_t uuid; // UUID for this particular implementation + uint32_t apiVersion; // Version of the effect control API implemented + uint32_t flags; // effect engine capabilities/requirements flags (see below) + uint16_t cpuLoad; // CPU load indication (see below) + uint16_t memoryUsage; // Data Memory usage (see below) + char name[EFFECT_STRING_LEN_MAX]; // human readable effect name + char implementor[EFFECT_STRING_LEN_MAX]; // human readable effect implementor name +} effect_descriptor_t; + +// CPU load and memory usage indication: each effect implementation must provide an indication of +// its CPU and memory usage for the audio effect framework to limit the number of effects +// instantiated at a given time on a given platform. +// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS. +// The memory usage is expressed in KB and includes only dynamically allocated memory + +// Definitions for flags field of effect descriptor. +// +---------------------------+-----------+----------------------------------- +// | description | bits | values +// +---------------------------+-----------+----------------------------------- +// | connection mode | 0..2 | 0 insert: after track process +// | | | 1 auxiliary: connect to track auxiliary +// | | | output and use send level +// | | | 2 replace: replaces track process function; +// | | | must implement SRC, volume and mono to stereo. +// | | | 3 pre processing: applied below audio HAL on input +// | | | 4 post processing: applied below audio HAL on output +// | | | 5 - 7 reserved +// +---------------------------+-----------+----------------------------------- +// | insertion preference | 3..5 | 0 none +// | | | 1 first of the chain +// | | | 2 last of the chain +// | | | 3 exclusive (only effect in the insert chain) +// | | | 4..7 reserved +// +---------------------------+-----------+----------------------------------- +// | Volume management | 6..8 | 0 none +// | | | 1 implements volume control +// | | | 2 requires volume indication +// | | | 4 reserved +// +---------------------------+-----------+----------------------------------- +// | Device indication | 9..11 | 0 none +// | | | 1 requires device updates +// | | | 2, 4 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample input mode | 12..13 | 1 direct: process() function or EFFECT_CMD_SET_CONFIG +// | | | command must specify a buffer descriptor +// | | | 2 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_SET_CONFIG command to request input. +// | | | buffers. +// | | | 3 both: both input modes are supported +// +---------------------------+-----------+----------------------------------- +// | Sample output mode | 14..15 | 1 direct: process() function or EFFECT_CMD_SET_CONFIG +// | | | command must specify a buffer descriptor +// | | | 2 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_SET_CONFIG command to request output +// | | | buffers. +// | | | 3 both: both output modes are supported +// +---------------------------+-----------+----------------------------------- +// | Hardware acceleration | 16..17 | 0 No hardware acceleration +// | | | 1 non tunneled hw acceleration: the process() function +// | | | reads the samples, send them to HW accelerated +// | | | effect processor, reads back the processed samples +// | | | and returns them to the output buffer. +// | | | 2 tunneled hw acceleration: the process() function is +// | | | transparent. The effect interface is only used to +// | | | control the effect engine. This mode is relevant for +// | | | global effects actually applied by the audio +// | | | hardware on the output stream. +// +---------------------------+-----------+----------------------------------- +// | Audio Mode indication | 18..19 | 0 none +// | | | 1 requires audio mode updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Audio source indication | 20..21 | 0 none +// | | | 1 requires audio source updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Effect offload supported | 22 | 0 The effect cannot be offloaded to an audio DSP +// | | | 1 The effect can be offloaded to an audio DSP +// +---------------------------+-----------+----------------------------------- + +// Insert mode +#define EFFECT_FLAG_TYPE_SHIFT 0 +#define EFFECT_FLAG_TYPE_SIZE 3 +#define EFFECT_FLAG_TYPE_MASK (((1 << EFFECT_FLAG_TYPE_SIZE) -1) \ + << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_INSERT (0 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_AUXILIARY (1 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_REPLACE (2 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_PRE_PROC (3 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_POST_PROC (4 << EFFECT_FLAG_TYPE_SHIFT) + +// Insert preference +#define EFFECT_FLAG_INSERT_SHIFT (EFFECT_FLAG_TYPE_SHIFT + EFFECT_FLAG_TYPE_SIZE) +#define EFFECT_FLAG_INSERT_SIZE 3 +#define EFFECT_FLAG_INSERT_MASK (((1 << EFFECT_FLAG_INSERT_SIZE) -1) \ + << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_ANY (0 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_FIRST (1 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_LAST (2 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_EXCLUSIVE (3 << EFFECT_FLAG_INSERT_SHIFT) + + +// Volume control +#define EFFECT_FLAG_VOLUME_SHIFT (EFFECT_FLAG_INSERT_SHIFT + EFFECT_FLAG_INSERT_SIZE) +#define EFFECT_FLAG_VOLUME_SIZE 3 +#define EFFECT_FLAG_VOLUME_MASK (((1 << EFFECT_FLAG_VOLUME_SIZE) -1) \ + << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_CTRL (1 << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_IND (2 << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_NONE (0 << EFFECT_FLAG_VOLUME_SHIFT) + +// Device indication +#define EFFECT_FLAG_DEVICE_SHIFT (EFFECT_FLAG_VOLUME_SHIFT + EFFECT_FLAG_VOLUME_SIZE) +#define EFFECT_FLAG_DEVICE_SIZE 3 +#define EFFECT_FLAG_DEVICE_MASK (((1 << EFFECT_FLAG_DEVICE_SIZE) -1) \ + << EFFECT_FLAG_DEVICE_SHIFT) +#define EFFECT_FLAG_DEVICE_IND (1 << EFFECT_FLAG_DEVICE_SHIFT) +#define EFFECT_FLAG_DEVICE_NONE (0 << EFFECT_FLAG_DEVICE_SHIFT) + +// Sample input modes +#define EFFECT_FLAG_INPUT_SHIFT (EFFECT_FLAG_DEVICE_SHIFT + EFFECT_FLAG_DEVICE_SIZE) +#define EFFECT_FLAG_INPUT_SIZE 2 +#define EFFECT_FLAG_INPUT_MASK (((1 << EFFECT_FLAG_INPUT_SIZE) -1) \ + << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_DIRECT (1 << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_PROVIDER (2 << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_BOTH (3 << EFFECT_FLAG_INPUT_SHIFT) + +// Sample output modes +#define EFFECT_FLAG_OUTPUT_SHIFT (EFFECT_FLAG_INPUT_SHIFT + EFFECT_FLAG_INPUT_SIZE) +#define EFFECT_FLAG_OUTPUT_SIZE 2 +#define EFFECT_FLAG_OUTPUT_MASK (((1 << EFFECT_FLAG_OUTPUT_SIZE) -1) \ + << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_DIRECT (1 << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_PROVIDER (2 << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_BOTH (3 << EFFECT_FLAG_OUTPUT_SHIFT) + +// Hardware acceleration mode +#define EFFECT_FLAG_HW_ACC_SHIFT (EFFECT_FLAG_OUTPUT_SHIFT + EFFECT_FLAG_OUTPUT_SIZE) +#define EFFECT_FLAG_HW_ACC_SIZE 2 +#define EFFECT_FLAG_HW_ACC_MASK (((1 << EFFECT_FLAG_HW_ACC_SIZE) -1) \ + << EFFECT_FLAG_HW_ACC_SHIFT) +#define EFFECT_FLAG_HW_ACC_SIMPLE (1 << EFFECT_FLAG_HW_ACC_SHIFT) +#define EFFECT_FLAG_HW_ACC_TUNNEL (2 << EFFECT_FLAG_HW_ACC_SHIFT) + +// Audio mode indication +#define EFFECT_FLAG_AUDIO_MODE_SHIFT (EFFECT_FLAG_HW_ACC_SHIFT + EFFECT_FLAG_HW_ACC_SIZE) +#define EFFECT_FLAG_AUDIO_MODE_SIZE 2 +#define EFFECT_FLAG_AUDIO_MODE_MASK (((1 << EFFECT_FLAG_AUDIO_MODE_SIZE) -1) \ + << EFFECT_FLAG_AUDIO_MODE_SHIFT) +#define EFFECT_FLAG_AUDIO_MODE_IND (1 << EFFECT_FLAG_AUDIO_MODE_SHIFT) +#define EFFECT_FLAG_AUDIO_MODE_NONE (0 << EFFECT_FLAG_AUDIO_MODE_SHIFT) + +// Audio source indication +#define EFFECT_FLAG_AUDIO_SOURCE_SHIFT (EFFECT_FLAG_AUDIO_MODE_SHIFT + EFFECT_FLAG_AUDIO_MODE_SIZE) +#define EFFECT_FLAG_AUDIO_SOURCE_SIZE 2 +#define EFFECT_FLAG_AUDIO_SOURCE_MASK (((1 << EFFECT_FLAG_AUDIO_SOURCE_SIZE) -1) \ + << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) +#define EFFECT_FLAG_AUDIO_SOURCE_IND (1 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) +#define EFFECT_FLAG_AUDIO_SOURCE_NONE (0 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) + +// Effect offload indication +#define EFFECT_FLAG_OFFLOAD_SHIFT (EFFECT_FLAG_AUDIO_SOURCE_SHIFT + \ + EFFECT_FLAG_AUDIO_SOURCE_SIZE) +#define EFFECT_FLAG_OFFLOAD_SIZE 1 +#define EFFECT_FLAG_OFFLOAD_MASK (((1 << EFFECT_FLAG_OFFLOAD_SIZE) -1) \ + << EFFECT_FLAG_OFFLOAD_SHIFT) +#define EFFECT_FLAG_OFFLOAD_SUPPORTED (1 << EFFECT_FLAG_OFFLOAD_SHIFT) + +#define EFFECT_MAKE_API_VERSION(M, m) (((M)<<16) | ((m) & 0xFFFF)) +#define EFFECT_API_VERSION_MAJOR(v) ((v)>>16) +#define EFFECT_API_VERSION_MINOR(v) ((m) & 0xFFFF) + + + +///////////////////////////////////////////////// +// Effect control interface +///////////////////////////////////////////////// + +// Effect control interface version 2.0 +#define EFFECT_CONTROL_API_VERSION EFFECT_MAKE_API_VERSION(2,0) + +// Effect control interface structure: effect_interface_s +// The effect control interface is exposed by each effect engine implementation. It consists of +// a set of functions controlling the configuration, activation and process of the engine. +// The functions are grouped in a structure of type effect_interface_s. +// +// Effect control interface handle: effect_handle_t +// The effect_handle_t serves two purposes regarding the implementation of the effect engine: +// - 1 it is the address of a pointer to an effect_interface_s structure where the functions +// of the effect control API for a particular effect are located. +// - 2 it is the address of the context of a particular effect instance. +// A typical implementation in the effect library would define a structure as follows: +// struct effect_module_s { +// const struct effect_interface_s *itfe; +// effect_config_t config; +// effect_context_t context; +// } +// The implementation of EffectCreate() function would then allocate a structure of this +// type and return its address as effect_handle_t +typedef struct effect_interface_s **effect_handle_t; + + +// Forward definition of type audio_buffer_t +typedef struct audio_buffer_s audio_buffer_t; + + + + + + +// Effect control interface definition +struct effect_interface_s +{ + //////////////////////////////////////////////////////////////////////////////// + // + // Function: process + // + // Description: Effect process function. Takes input samples as specified + // (count and location) in input buffer descriptor and output processed + // samples as specified in output buffer descriptor. If the buffer descriptor + // is not specified the function must use either the buffer or the + // buffer provider function installed by the EFFECT_CMD_SET_CONFIG command. + // The effect framework will call the process() function after the EFFECT_CMD_ENABLE + // command is received and until the EFFECT_CMD_DISABLE is received. When the engine + // receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully + // and when done indicate that it is OK to stop calling the process() function by + // returning the -ENODATA status. + // + // NOTE: the process() function implementation should be "real-time safe" that is + // it should not perform blocking calls: malloc/free, sleep, read/write/open/close, + // pthread_cond_wait/pthread_mutex_lock... + // + // Input: + // self: handle to the effect interface this function + // is called on. + // inBuffer: buffer descriptor indicating where to read samples to process. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG command. + // + // outBuffer: buffer descriptor indicating where to write processed samples. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG command. + // + // Output: + // returned value: 0 successful operation + // -ENODATA the engine has finished the disable phase and the framework + // can stop calling process() + // -EINVAL invalid interface handle or + // invalid input/output buffer description + //////////////////////////////////////////////////////////////////////////////// + int32_t (*process)(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: command + // + // Description: Send a command and receive a response to/from effect engine. + // + // Input: + // self: handle to the effect interface this function + // is called on. + // cmdCode: command code: the command can be a standardized command defined in + // effect_command_e (see below) or a proprietary command. + // cmdSize: size of command in bytes + // pCmdData: pointer to command data + // pReplyData: pointer to reply data + // + // Input/Output: + // replySize: maximum size of reply data as input + // actual size of reply data as output + // + // Output: + // returned value: 0 successful operation + // -EINVAL invalid interface handle or + // invalid command/reply size or format according to command code + // The return code should be restricted to indicate problems related to the this + // API specification. Status related to the execution of a particular command should be + // indicated as part of the reply field. + // + // *pReplyData updated with command response + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*command)(effect_handle_t self, + uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: get_descriptor + // + // Description: Returns the effect descriptor + // + // Input: + // self: handle to the effect interface this function + // is called on. + // + // Input/Output: + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -EINVAL invalid interface handle or invalid pDescriptor + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*get_descriptor)(effect_handle_t self, + effect_descriptor_t *pDescriptor); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: process_reverse + // + // Description: Process reverse stream function. This function is used to pass + // a reference stream to the effect engine. If the engine does not need a reference + // stream, this function pointer can be set to NULL. + // This function would typically implemented by an Echo Canceler. + // + // Input: + // self: handle to the effect interface this function + // is called on. + // inBuffer: buffer descriptor indicating where to read samples to process. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG_REVERSE command. + // + // outBuffer: buffer descriptor indicating where to write processed samples. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG_REVERSE command. + // If the buffer and buffer provider in the configuration received by + // EFFECT_CMD_SET_CONFIG_REVERSE are also NULL, do not return modified reverse + // stream data + // + // Output: + // returned value: 0 successful operation + // -ENODATA the engine has finished the disable phase and the framework + // can stop calling process_reverse() + // -EINVAL invalid interface handle or + // invalid input/output buffer description + //////////////////////////////////////////////////////////////////////////////// + int32_t (*process_reverse)(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); +}; + + +// +//--- Standardized command codes for command() function +// +enum effect_command_e +{ + EFFECT_CMD_INIT, // initialize effect engine + EFFECT_CMD_SET_CONFIG, // configure effect engine (see effect_config_t) + EFFECT_CMD_RESET, // reset effect engine + EFFECT_CMD_ENABLE, // enable effect process + EFFECT_CMD_DISABLE, // disable effect process + EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t) + EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred + EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred + EFFECT_CMD_GET_PARAM, // get parameter + EFFECT_CMD_SET_DEVICE, // set audio device (see audio.h, audio_devices_t) + EFFECT_CMD_SET_VOLUME, // set volume + EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...) + EFFECT_CMD_SET_CONFIG_REVERSE, // configure effect engine reverse stream(see effect_config_t) + EFFECT_CMD_SET_INPUT_DEVICE, // set capture device (see audio.h, audio_devices_t) + EFFECT_CMD_GET_CONFIG, // read effect engine configuration + EFFECT_CMD_GET_CONFIG_REVERSE, // read configure effect engine reverse stream configuration + EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature. + EFFECT_CMD_GET_FEATURE_CONFIG, // get current feature configuration + EFFECT_CMD_SET_FEATURE_CONFIG, // set current feature configuration + EFFECT_CMD_SET_AUDIO_SOURCE, // set the audio source (see audio.h, audio_source_t) + EFFECT_CMD_OFFLOAD, // set if effect thread is an offload one, + // send the ioHandle of the effect thread + EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code +}; + +//================================================================================================== +// command: EFFECT_CMD_INIT +//-------------------------------------------------------------------------------------------------- +// description: +// Initialize effect engine: All configurations return to default +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_RESET +//-------------------------------------------------------------------------------------------------- +// description: +// Reset the effect engine. Keep configuration but resets state and buffer content +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_ENABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Enable the process. Called by the framework before the first call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_DISABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Disable the process. Called by the framework after the last call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter and apply it immediately +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_DEFERRED +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_COMMIT +//-------------------------------------------------------------------------------------------------- +// description: +// Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_GET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Get a parameter value +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param +// data: effect_param_t + param +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//================================================================================================== +// command: EFFECT_CMD_SET_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the rendering device the audio output path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_VOLUME +//-------------------------------------------------------------------------------------------------- +// description: +// Set and get volume. Used by audio framework to delegate volume control to effect engine. +// The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in +// its descriptor to receive this command before every call to process() function +// If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return +// the volume that should be applied before the effect is processed. The overall volume (the volume +// actually applied by the effect engine multiplied by the returned value) should match the value +// indicated in the command. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: n * sizeof(uint32_t) +// data: volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: n * sizeof(uint32_t) / 0 +// data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor: +// volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +// - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor: +// N/A +// It is legal to receive a null pointer as pReplyData in which case the effect framework has +// delegated volume control to another effect +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_MODE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its +// descriptor to receive this command when the audio mode changes. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: audio_mode_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers of reverse stream. +// An example of reverse stream is the echo reference supplied to an Acoustic Echo Canceler. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_INPUT_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the capture device the audio input path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_GET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: EFFECT_CMD_GET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers of reverse stream +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS +//-------------------------------------------------------------------------------------------------- +// description: +// Queries for supported configurations for a particular feature (e.g. get the supported +// combinations of main and auxiliary channels for a noise suppressor). +// The command parameter is the feature identifier (See effect_feature_e for a list of defined +// features) followed by the maximum number of configuration descriptor to return. +// The reply is composed of: +// - status (uint32_t): +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -ENOMEM if the feature is supported but the total number of supported configurations +// exceeds the maximum number indicated by the caller. +// - total number of supported configurations (uint32_t) +// - an array of configuration descriptors. +// The actual number of descriptors returned must not exceed the maximum number indicated by +// the caller. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 2 x sizeof(uint32_t) +// data: effect_feature_e + maximum number of configurations to return +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 2 x sizeof(uint32_t) + n x sizeof () +// data: status + total number of configurations supported + array of n config descriptors +//================================================================================================== +// command: EFFECT_CMD_GET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Retrieves current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: effect_feature_e +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) + sizeof () +// data: status + config descriptor +//================================================================================================== +// command: EFFECT_CMD_SET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Sets current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -EINVAL if the configuration is invalid +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) + sizeof () +// data: effect_feature_e + config descriptor +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_SOURCE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio source the capture path is configured for (Camcorder, voice recognition...). +// See audio.h, audio_source_t for values. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_OFFLOAD +//-------------------------------------------------------------------------------------------------- +// description: +// 1.indicate if the playback thread the effect is attached to is offloaded or not +// 2.update the io handle of the playback thread the effect is attached to +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_offload_param_t) +// data: effect_offload_param_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// command: EFFECT_CMD_FIRST_PROPRIETARY +//-------------------------------------------------------------------------------------------------- +// description: +// All proprietary effect commands must use command codes above this value. The size and format of +// command and response fields is free in this case +//================================================================================================== + + +// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t +// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with +// regard to the channel mask definition in audio.h, audio_channel_mask_t e.g : +// Stereo: left, right +// 5 point 1: front left, front right, front center, low frequency, back left, back right +// The buffer size is expressed in frame count, a frame being composed of samples for all +// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by +// definition +typedef struct audio_buffer_s { + size_t frameCount; // number of frames in buffer + union { + void* raw; // raw pointer to start of buffer + float* f32; // pointer to float 32 bit data at start of buffer + int32_t* s32; // pointer to signed 32 bit data at start of buffer + int16_t* s16; // pointer to signed 16 bit data at start of buffer + uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer + }; +} audio_buffer_t; + +// The buffer_provider_s structure contains functions that can be used +// by the effect engine process() function to query and release input +// or output audio buffer. +// The getBuffer() function is called to retrieve a buffer where data +// should read from or written to by process() function. +// The releaseBuffer() function MUST be called when the buffer retrieved +// with getBuffer() is not needed anymore. +// The process function should use the buffer provider mechanism to retrieve +// input or output buffer if the inBuffer or outBuffer passed as argument is NULL +// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_SET_CONFIG +// command did not specify an audio buffer. + +typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer); + +typedef struct buffer_provider_s +{ + buffer_function_t getBuffer; // retrieve next buffer + buffer_function_t releaseBuffer; // release used buffer + void *cookie; // for use by client of buffer provider functions +} buffer_provider_t; + + +// The buffer_config_s structure specifies the input or output audio format +// to be used by the effect engine. It is part of the effect_config_t +// structure that defines both input and output buffer configurations and is +// passed by the EFFECT_CMD_SET_CONFIG or EFFECT_CMD_SET_CONFIG_REVERSE command. +typedef struct buffer_config_s +{ + audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly + uint32_t samplingRate; // sampling rate + uint32_t channels; // channel mask (see audio_channel_mask_t in audio.h) + buffer_provider_t bufferProvider; // buffer provider + uint8_t format; // Audio format (see audio_format_t in audio.h) + uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e) + uint16_t mask; // indicates which of the above fields is valid +} buffer_config_t; + +// Values for "accessMode" field of buffer_config_t: +// overwrite, read only, accumulate (read/modify/write) +enum effect_buffer_access_e +{ + EFFECT_BUFFER_ACCESS_WRITE, + EFFECT_BUFFER_ACCESS_READ, + EFFECT_BUFFER_ACCESS_ACCUMULATE + +}; + +// feature identifiers for EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS command +enum effect_feature_e +{ + EFFECT_FEATURE_AUX_CHANNELS, // supports auxiliary channels (e.g. dual mic noise suppressor) + EFFECT_FEATURE_CNT +}; + +// EFFECT_FEATURE_AUX_CHANNELS feature configuration descriptor. Describe a combination +// of main and auxiliary channels supported +typedef struct channel_config_s +{ + audio_channel_mask_t main_channels; // channel mask for main channels + audio_channel_mask_t aux_channels; // channel mask for auxiliary channels +} channel_config_t; + + +// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field +// in buffer_config_t must be taken into account when executing the EFFECT_CMD_SET_CONFIG command +#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account +#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account +#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account +#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account +#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account +#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account +#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \ + EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \ + EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER) + + +// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_CONFIG +// command to configure audio parameters and buffers for effect engine input and output. +typedef struct effect_config_s +{ + buffer_config_t inputCfg; + buffer_config_t outputCfg; +} effect_config_t; + + +// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM +// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command. +// psize and vsize represent the actual size of parameter and value. +// +// NOTE: the start of value field inside the data field is always on a 32 bit boundary: +// +// +-----------+ +// | status | sizeof(int) +// +-----------+ +// | psize | sizeof(int) +// +-----------+ +// | vsize | sizeof(int) +// +-----------+ +// | | | | +// ~ parameter ~ > psize | +// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int) +// +-----------+ | +// | padding | | +// +-----------+ +// | | | +// ~ value ~ > vsize +// | | | +// +-----------+ + +typedef struct effect_param_s +{ + int32_t status; // Transaction status (unused for command, used for reply) + uint32_t psize; // Parameter size + uint32_t vsize; // Value size + char data[]; // Start of Parameter + Value data +} effect_param_t; + +// structure used by EFFECT_CMD_OFFLOAD command +typedef struct effect_offload_param_s +{ + bool isOffload; // true if the playback thread the effect is attached to is offloaded + int ioHandle; // io handle of the playback thread the effect is attached to +} effect_offload_param_t; + + +///////////////////////////////////////////////// +// Effect library interface +///////////////////////////////////////////////// + +// Effect library interface version 3.0 +// Note that EffectsFactory.c only checks the major version component, so changes to the minor +// number can only be used for fully backwards compatible changes +#define EFFECT_LIBRARY_API_VERSION EFFECT_MAKE_API_VERSION(3,0) + +#define AUDIO_EFFECT_LIBRARY_TAG ((('A') << 24) | (('E') << 16) | (('L') << 8) | ('T')) + +// Every effect library must have a data structure named AUDIO_EFFECT_LIBRARY_INFO_SYM +// and the fields of this data structure must begin with audio_effect_library_t + +typedef struct audio_effect_library_s +{ + // tag must be initialized to AUDIO_EFFECT_LIBRARY_TAG + uint32_t tag; + // Version of the effect library API : 0xMMMMmmmm MMMM: Major, mmmm: minor + uint32_t version; + // Name of this library + const char *name; + // Author/owner/implementor of the library + const char *implementor; + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: create_effect + // + // Description: Creates an effect engine of the specified implementation uuid and + // returns an effect control interface on this engine. The function will allocate the + // resources for an instance of the requested effect engine and return + // a handle on the effect control interface. + // + // Input: + // uuid: pointer to the effect uuid. + // sessionId: audio session to which this effect instance will be attached. All effects + // created with the same session ID are connected in series and process the same signal + // stream. Knowing that two effects are part of the same effect chain can help the + // library implement some kind of optimizations. + // ioId: identifies the output or input stream this effect is directed to at audio HAL. + // For future use especially with tunneled HW accelerated effects + // + // Input/Output: + // pHandle: address where to return the effect interface handle. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pEffectUuid or pHandle + // -ENOENT no effect with this uuid found + // *pHandle: updated with the effect interface handle. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*create_effect)(const effect_uuid_t *uuid, + int32_t sessionId, + int32_t ioId, + effect_handle_t *pHandle); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: release_effect + // + // Description: Releases the effect engine whose handle is given as argument. + // All resources allocated to this particular instance of the effect are + // released. + // + // Input: + // handle: handle on the effect interface to be released. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid interface handle + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*release_effect)(effect_handle_t handle); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: get_descriptor + // + // Description: Returns the descriptor of the effect engine which implementation UUID is + // given as argument. + // + // Input/Output: + // uuid: pointer to the effect uuid. + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pDescriptor or uuid + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*get_descriptor)(const effect_uuid_t *uuid, + effect_descriptor_t *pDescriptor); +} audio_effect_library_t; + +// Name of the hal_module_info +#define AUDIO_EFFECT_LIBRARY_INFO_SYM AELI + +// Name of the hal_module_info as a string +#define AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR "AELI" + +__END_DECLS + +#endif // ANDROID_AUDIO_EFFECT_H diff --git a/include/hardware/audio_policy.h b/include/hardware/audio_policy.h new file mode 100644 index 0000000..3c0cd4c --- /dev/null +++ b/include/hardware/audio_policy.h @@ -0,0 +1,461 @@ +/* + * 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 ANDROID_AUDIO_POLICY_INTERFACE_H +#define ANDROID_AUDIO_POLICY_INTERFACE_H + +#include +#include +#include + +#include + +#include "system/audio.h" +#include "system/audio_policy.h" + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy" + +/** + * Name of the audio devices to open + */ +#define AUDIO_POLICY_INTERFACE "policy" + +/* ---------------------------------------------------------------------------- */ + +/* + * The audio_policy and audio_policy_service_ops structs define the + * communication interfaces between the platform specific audio policy manager + * and Android generic audio policy manager. + * The platform specific audio policy manager must implement methods of the + * audio_policy struct. + * This implementation makes use of the audio_policy_service_ops to control + * the activity and configuration of audio input and output streams. + * + * The platform specific audio policy manager is in charge of the audio + * routing and volume control policies for a given platform. + * The main roles of this module are: + * - keep track of current system state (removable device connections, phone + * state, user requests...). + * System state changes and user actions are notified to audio policy + * manager with methods of the audio_policy. + * + * - process get_output() queries received when AudioTrack objects are + * created: Those queries return a handler on an output that has been + * selected, configured and opened by the audio policy manager and that + * must be used by the AudioTrack when registering to the AudioFlinger + * with the createTrack() method. + * When the AudioTrack object is released, a release_output() query + * is received and the audio policy manager can decide to close or + * reconfigure the output depending on other streams using this output and + * current system state. + * + * - similarly process get_input() and release_input() queries received from + * AudioRecord objects and configure audio inputs. + * - process volume control requests: the stream volume is converted from + * an index value (received from UI) to a float value applicable to each + * output as a function of platform specific settings and current output + * route (destination device). It also make sure that streams are not + * muted if not allowed (e.g. camera shutter sound in some countries). + */ + +/* XXX: this should be defined OUTSIDE of frameworks/base */ +struct effect_descriptor_s; + +struct audio_policy +{ + /* + * configuration functions + */ + + /* indicate a change in device connection status */ + int (*set_device_connection_state)(struct audio_policy *pol, + audio_devices_t device, + audio_policy_dev_state_t state, + const char *device_address); + + /* retrieve a device connection status */ + audio_policy_dev_state_t (*get_device_connection_state)( + const struct audio_policy *pol, + audio_devices_t device, + const char *device_address); + + /* indicate a change in phone state. Valid phones states are defined + * by audio_mode_t */ + void (*set_phone_state)(struct audio_policy *pol, audio_mode_t state); + + /* deprecated, never called (was "indicate a change in ringer mode") */ + void (*set_ringer_mode)(struct audio_policy *pol, uint32_t mode, + uint32_t mask); + + /* force using a specific device category for the specified usage */ + void (*set_force_use)(struct audio_policy *pol, + audio_policy_force_use_t usage, + audio_policy_forced_cfg_t config); + + /* retrieve current device category forced for a given usage */ + audio_policy_forced_cfg_t (*get_force_use)(const struct audio_policy *pol, + audio_policy_force_use_t usage); + + /* if can_mute is true, then audio streams that are marked ENFORCED_AUDIBLE + * can still be muted. */ + void (*set_can_mute_enforced_audible)(struct audio_policy *pol, + bool can_mute); + + /* check proper initialization */ + int (*init_check)(const struct audio_policy *pol); + + /* + * Audio routing query functions + */ + + /* request an output appropriate for playback of the supplied stream type and + * parameters */ + audio_io_handle_t (*get_output)(struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo); + + /* indicates to the audio policy manager that the output starts being used + * by corresponding stream. */ + int (*start_output)(struct audio_policy *pol, + audio_io_handle_t output, + audio_stream_type_t stream, + int session); + + /* indicates to the audio policy manager that the output stops being used + * by corresponding stream. */ + int (*stop_output)(struct audio_policy *pol, + audio_io_handle_t output, + audio_stream_type_t stream, + int session); + + /* releases the output. */ + void (*release_output)(struct audio_policy *pol, audio_io_handle_t output); + + /* request an input appropriate for record from the supplied device with + * supplied parameters. */ + audio_io_handle_t (*get_input)(struct audio_policy *pol, audio_source_t inputSource, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_in_acoustics_t acoustics); + + /* indicates to the audio policy manager that the input starts being used */ + int (*start_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* indicates to the audio policy manager that the input stops being used. */ + int (*stop_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* releases the input. */ + void (*release_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* + * volume control functions + */ + + /* initialises stream volume conversion parameters by specifying volume + * index range. The index range for each stream is defined by AudioService. */ + void (*init_stream_volume)(struct audio_policy *pol, + audio_stream_type_t stream, + int index_min, + int index_max); + + /* sets the new stream volume at a level corresponding to the supplied + * index. The index is within the range specified by init_stream_volume() */ + int (*set_stream_volume_index)(struct audio_policy *pol, + audio_stream_type_t stream, + int index); + + /* retrieve current volume index for the specified stream */ + int (*get_stream_volume_index)(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index); + + /* sets the new stream volume at a level corresponding to the supplied + * index for the specified device. + * The index is within the range specified by init_stream_volume() */ + int (*set_stream_volume_index_for_device)(struct audio_policy *pol, + audio_stream_type_t stream, + int index, + audio_devices_t device); + + /* retrieve current volume index for the specified stream for the specified device */ + int (*get_stream_volume_index_for_device)(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index, + audio_devices_t device); + + /* return the strategy corresponding to a given stream type */ + uint32_t (*get_strategy_for_stream)(const struct audio_policy *pol, + audio_stream_type_t stream); + + /* return the enabled output devices for the given stream type */ + audio_devices_t (*get_devices_for_stream)(const struct audio_policy *pol, + audio_stream_type_t stream); + + /* Audio effect management */ + audio_io_handle_t (*get_output_for_effect)(struct audio_policy *pol, + const struct effect_descriptor_s *desc); + + int (*register_effect)(struct audio_policy *pol, + const struct effect_descriptor_s *desc, + audio_io_handle_t output, + uint32_t strategy, + int session, + int id); + + int (*unregister_effect)(struct audio_policy *pol, int id); + + int (*set_effect_enabled)(struct audio_policy *pol, int id, bool enabled); + + bool (*is_stream_active)(const struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t in_past_ms); + + bool (*is_stream_active_remotely)(const struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t in_past_ms); + + bool (*is_source_active)(const struct audio_policy *pol, + audio_source_t source); + + /* dump state */ + int (*dump)(const struct audio_policy *pol, int fd); + + /* check if offload is possible for given sample rate, bitrate, duration, ... */ + bool (*is_offload_supported)(const struct audio_policy *pol, + const audio_offload_info_t *info); +}; + + +struct audio_policy_service_ops +{ + /* + * Audio output Control functions + */ + + /* Opens an audio output with the requested parameters. + * + * The parameter values can indicate to use the default values in case the + * audio policy manager has no specific requirements for the output being + * opened. + * + * When the function returns, the parameter values reflect the actual + * values used by the audio hardware output stream. + * + * The audio policy manager can check if the proposed parameters are + * suitable or not and act accordingly. + */ + audio_io_handle_t (*open_output)(void *service, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_output_flags_t flags); + + /* creates a special output that is duplicated to the two outputs passed as + * arguments. The duplication is performed by + * a special mixer thread in the AudioFlinger. + */ + audio_io_handle_t (*open_duplicate_output)(void *service, + audio_io_handle_t output1, + audio_io_handle_t output2); + + /* closes the output stream */ + int (*close_output)(void *service, audio_io_handle_t output); + + /* suspends the output. + * + * When an output is suspended, the corresponding audio hardware output + * stream is placed in standby and the AudioTracks attached to the mixer + * thread are still processed but the output mix is discarded. + */ + int (*suspend_output)(void *service, audio_io_handle_t output); + + /* restores a suspended output. */ + int (*restore_output)(void *service, audio_io_handle_t output); + + /* */ + /* Audio input Control functions */ + /* */ + + /* opens an audio input + * deprecated - new implementations should use open_input_on_module, + * and the acoustics parameter is ignored + */ + audio_io_handle_t (*open_input)(void *service, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + audio_in_acoustics_t acoustics); + + /* closes an audio input */ + int (*close_input)(void *service, audio_io_handle_t input); + + /* */ + /* misc control functions */ + /* */ + + /* set a stream volume for a particular output. + * + * For the same user setting, a given stream type can have different + * volumes for each output (destination device) it is attached to. + */ + int (*set_stream_volume)(void *service, + audio_stream_type_t stream, + float volume, + audio_io_handle_t output, + int delay_ms); + + /* invalidate a stream type, causing a reroute to an unspecified new output */ + int (*invalidate_stream)(void *service, + audio_stream_type_t stream); + + /* function enabling to send proprietary informations directly from audio + * policy manager to audio hardware interface. */ + void (*set_parameters)(void *service, + audio_io_handle_t io_handle, + const char *kv_pairs, + int delay_ms); + + /* function enabling to receive proprietary informations directly from + * audio hardware interface to audio policy manager. + * + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + + char * (*get_parameters)(void *service, audio_io_handle_t io_handle, + const char *keys); + + /* request the playback of a tone on the specified stream. + * used for instance to replace notification sounds when playing over a + * telephony device during a phone call. + */ + int (*start_tone)(void *service, + audio_policy_tone_t tone, + audio_stream_type_t stream); + + int (*stop_tone)(void *service); + + /* set down link audio volume. */ + int (*set_voice_volume)(void *service, + float volume, + int delay_ms); + + /* move effect to the specified output */ + int (*move_effects)(void *service, + int session, + audio_io_handle_t src_output, + audio_io_handle_t dst_output); + + /* loads an audio hw module. + * + * The module name passed is the base name of the HW module library, e.g "primary" or "a2dp". + * The function returns a handle on the module that will be used to specify a particular + * module when calling open_output_on_module() or open_input_on_module() + */ + audio_module_handle_t (*load_hw_module)(void *service, + const char *name); + + /* Opens an audio output on a particular HW module. + * + * Same as open_output() but specifying a specific HW module on which the output must be opened. + */ + audio_io_handle_t (*open_output_on_module)(void *service, + audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo); + + /* Opens an audio input on a particular HW module. + * + * Same as open_input() but specifying a specific HW module on which the input must be opened. + * Also removed deprecated acoustics parameter + */ + audio_io_handle_t (*open_input_on_module)(void *service, + audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask); + +}; + +/**********************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct audio_policy_module +{ + struct hw_module_t common; +} audio_policy_module_t; + +struct audio_policy_device +{ + /** + * Common methods of the audio policy device. This *must* be the first member of + * audio_policy_device as users of this structure will cast a hw_device_t to + * audio_policy_device pointer in contexts where it's known the hw_device_t references an + * audio_policy_device. + */ + struct hw_device_t common; + + int (*create_audio_policy)(const struct audio_policy_device *device, + struct audio_policy_service_ops *aps_ops, + void *service, + struct audio_policy **ap); + + int (*destroy_audio_policy)(const struct audio_policy_device *device, + struct audio_policy *ap); +}; + +/** convenience API for opening and closing a supported device */ + +static inline int audio_policy_dev_open(const hw_module_t* module, + struct audio_policy_device** device) +{ + return module->methods->open(module, AUDIO_POLICY_INTERFACE, + (hw_device_t**)device); +} + +static inline int audio_policy_dev_close(struct audio_policy_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_AUDIO_POLICY_INTERFACE_H diff --git a/include/hardware/hardware.h b/include/hardware/hardware.h new file mode 100644 index 0000000..d6ac1d6 --- /dev/null +++ b/include/hardware/hardware.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 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. + * 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_INCLUDE_HARDWARE_HARDWARE_H +#define ANDROID_INCLUDE_HARDWARE_HARDWARE_H + +#include +#include + +#include "system/cutils/native_handle.h" +//#include "system/graphics.h" + +__BEGIN_DECLS + +/* + * Value for the hw_module_t.tag field + */ + +#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D)) + +#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T') +#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T') + +#define HARDWARE_MAKE_API_VERSION(maj,min) \ + ((((maj) & 0xff) << 8) | ((min) & 0xff)) + +#define HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) \ + ((((maj) & 0xff) << 24) | (((min) & 0xff) << 16) | ((hdr) & 0xffff)) +#define HARDWARE_API_VERSION_2_MAJ_MIN_MASK 0xffff0000 +#define HARDWARE_API_VERSION_2_HEADER_MASK 0x0000ffff + + +/* + * The current HAL API version. + * + * All module implementations must set the hw_module_t.hal_api_version field + * to this value when declaring the module with HAL_MODULE_INFO_SYM. + * + * Note that previous implementations have always set this field to 0. + * Therefore, libhardware HAL API will always consider versions 0.0 and 1.0 + * to be 100% binary compatible. + * + */ +#define HARDWARE_HAL_API_VERSION HARDWARE_MAKE_API_VERSION(1, 0) + +/* + * Helper macros for module implementors. + * + * The derived modules should provide convenience macros for supported + * versions so that implementations can explicitly specify module/device + * versions at definition time. + * + * Use this macro to set the hw_module_t.module_api_version field. + */ +#define HARDWARE_MODULE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min) +#define HARDWARE_MODULE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) + +/* + * Use this macro to set the hw_device_t.version field + */ +#define HARDWARE_DEVICE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min) +#define HARDWARE_DEVICE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) + +struct hw_module_t; +struct hw_module_methods_t; +struct hw_device_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct hw_module_t +{ + /** tag must be initialized to HARDWARE_MODULE_TAG */ + uint32_t tag; + + /** + * The API version of the implemented module. The module owner is + * responsible for updating the version when a module interface has + * changed. + * + * The derived modules such as gralloc and audio own and manage this field. + * The module user must interpret the version field to decide whether or + * not to inter-operate with the supplied module implementation. + * For example, SurfaceFlinger is responsible for making sure that + * it knows how to manage different versions of the gralloc-module API, + * and AudioFlinger must know how to do the same for audio-module API. + * + * The module API version should include a major and a minor component. + * For example, version 1.0 could be represented as 0x0100. This format + * implies that versions 0x0100-0x01ff are all API-compatible. + * + * In the future, libhardware will expose a hw_get_module_version() + * (or equivalent) function that will take minimum/maximum supported + * versions as arguments and would be able to reject modules with + * versions outside of the supplied range. + */ + uint16_t module_api_version; +#define version_major module_api_version + /** + * version_major/version_minor defines are supplied here for temporary + * source code compatibility. They will be removed in the next version. + * ALL clients must convert to the new version format. + */ + + /** + * The API version of the HAL module interface. This is meant to + * version the hw_module_t, hw_module_methods_t, and hw_device_t + * structures and definitions. + * + * The HAL interface owns this field. Module users/implementations + * must NOT rely on this value for version information. + * + * Presently, 0 is the only valid value. + */ + uint16_t hal_api_version; +#define version_minor hal_api_version + + /** Identifier of module */ + const char *id; + + /** Name of this module */ + const char *name; + + /** Author/owner/implementor of the module */ + const char *author; + + /** Modules methods */ + struct hw_module_methods_t* methods; + + /** module's dso */ + void* dso; + +#ifdef __LP64__ + uint64_t reserved[32-7]; +#else + /** padding to 128 bytes, reserved for future use */ + uint32_t reserved[32-7]; +#endif + +} hw_module_t; + +typedef struct hw_module_methods_t +{ + /** Open a specific device */ + int (*open)(const struct hw_module_t* module, const char* id, + struct hw_device_t** device); + +} hw_module_methods_t; + +/** + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ +typedef struct hw_device_t +{ + /** tag must be initialized to HARDWARE_DEVICE_TAG */ + uint32_t tag; + + /** + * Version of the module-specific device API. This value is used by + * the derived-module user to manage different device implementations. + * + * The module user is responsible for checking the module_api_version + * and device version fields to ensure that the user is capable of + * communicating with the specific module implementation. + * + * One module can support multiple devices with different versions. This + * can be useful when a device interface changes in an incompatible way + * but it is still necessary to support older implementations at the same + * time. One such example is the Camera 2.0 API. + * + * This field is interpreted by the module user and is ignored by the + * HAL interface itself. + */ + uint32_t version; + + /** reference to the module this device belongs to */ + struct hw_module_t* module; + + /** padding reserved for future use */ +#ifdef __LP64__ + uint64_t reserved[12]; +#else + uint32_t reserved[12]; +#endif + + /** Close this device */ + int (*close)(struct hw_device_t* device); + +} hw_device_t; + +/** + * Name of the hal_module_info + */ +#define HAL_MODULE_INFO_SYM HMI + +/** + * Name of the hal_module_info as a string + */ +#define HAL_MODULE_INFO_SYM_AS_STR "HMI" + +/** + * Get the module info associated with a module by id. + * + * @return: 0 == success, <0 == error and *module == NULL + */ +int hw_get_module(const char *id, const struct hw_module_t **module); + +/** + * Get the module info associated with a module instance by class 'class_id' + * and instance 'inst'. + * + * Some modules types necessitate multiple instances. For example audio supports + * multiple concurrent interfaces and thus 'audio' is the module class + * and 'primary' or 'a2dp' are module interfaces. This implies that the files + * providing these modules would be named audio.primary..so and + * audio.a2dp..so + * + * @return: 0 == success, <0 == error and *module == NULL + */ +int hw_get_module_by_class(const char *class_id, const char *inst, + const struct hw_module_t **module); + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */ diff --git a/include/hardware/system/audio-base-utils.h b/include/hardware/system/audio-base-utils.h new file mode 100644 index 0000000..016a085 --- /dev/null +++ b/include/hardware/system/audio-base-utils.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2018 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_AUDIO_BASE_UTILS_H +#define ANDROID_AUDIO_BASE_UTILS_H + +#include "audio-base.h" + +/** Define helper values to iterate over enum, extend them or checking value validity. + * Those values are compatible with the O corresponding enum values. + * They are not macro like similar values in audio.h to avoid conflicting + * with the libhardware_legacy audio.h. + */ +enum { + /** Number of audio stream available to vendors. */ + AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_ACCESSIBILITY + 1, + +#ifndef AUDIO_NO_SYSTEM_DECLARATIONS + /** Total number of stream handled by the policy*/ + AUDIO_STREAM_FOR_POLICY_CNT= AUDIO_STREAM_REROUTING + 1, +#endif + + /** Total number of stream. */ + AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1, + + AUDIO_SOURCE_MAX = AUDIO_SOURCE_UNPROCESSED, + AUDIO_SOURCE_CNT = AUDIO_SOURCE_MAX + 1, + + AUDIO_MODE_MAX = AUDIO_MODE_IN_COMMUNICATION, + AUDIO_MODE_CNT = AUDIO_MODE_MAX + 1, + + /** For retrocompatibility AUDIO_MODE_* and AUDIO_STREAM_* must be signed. */ + AUDIO_DETAIL_NEGATIVE_VALUE = -1, +}; + +enum { + AUDIO_CHANNEL_OUT_ALL = AUDIO_CHANNEL_OUT_FRONT_LEFT | + AUDIO_CHANNEL_OUT_FRONT_RIGHT | + AUDIO_CHANNEL_OUT_FRONT_CENTER | + AUDIO_CHANNEL_OUT_LOW_FREQUENCY | + AUDIO_CHANNEL_OUT_BACK_LEFT | + AUDIO_CHANNEL_OUT_BACK_RIGHT | + AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER | + AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | + AUDIO_CHANNEL_OUT_BACK_CENTER | + AUDIO_CHANNEL_OUT_SIDE_LEFT | + AUDIO_CHANNEL_OUT_SIDE_RIGHT | + AUDIO_CHANNEL_OUT_TOP_CENTER | + AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT | + AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER | + AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT | + AUDIO_CHANNEL_OUT_TOP_BACK_LEFT | + AUDIO_CHANNEL_OUT_TOP_BACK_CENTER | + AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT | + AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT | + AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT, + + AUDIO_CHANNEL_IN_ALL = AUDIO_CHANNEL_IN_LEFT | + AUDIO_CHANNEL_IN_RIGHT | + AUDIO_CHANNEL_IN_FRONT | + AUDIO_CHANNEL_IN_BACK| + AUDIO_CHANNEL_IN_LEFT_PROCESSED | + AUDIO_CHANNEL_IN_RIGHT_PROCESSED | + AUDIO_CHANNEL_IN_FRONT_PROCESSED | + AUDIO_CHANNEL_IN_BACK_PROCESSED| + AUDIO_CHANNEL_IN_PRESSURE | + AUDIO_CHANNEL_IN_X_AXIS | + AUDIO_CHANNEL_IN_Y_AXIS | + AUDIO_CHANNEL_IN_Z_AXIS | + AUDIO_CHANNEL_IN_VOICE_UPLINK | + AUDIO_CHANNEL_IN_VOICE_DNLINK | + AUDIO_CHANNEL_IN_BACK_LEFT | + AUDIO_CHANNEL_IN_BACK_RIGHT | + AUDIO_CHANNEL_IN_CENTER | + AUDIO_CHANNEL_IN_LOW_FREQUENCY | + AUDIO_CHANNEL_IN_TOP_LEFT | + AUDIO_CHANNEL_IN_TOP_RIGHT, + + AUDIO_DEVICE_OUT_ALL = AUDIO_DEVICE_OUT_EARPIECE | + AUDIO_DEVICE_OUT_SPEAKER | + AUDIO_DEVICE_OUT_WIRED_HEADSET | + AUDIO_DEVICE_OUT_WIRED_HEADPHONE | + AUDIO_DEVICE_OUT_BLUETOOTH_SCO | + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET | + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | + AUDIO_DEVICE_OUT_HDMI | + AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET | + AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET | + AUDIO_DEVICE_OUT_USB_ACCESSORY | + AUDIO_DEVICE_OUT_USB_DEVICE | + AUDIO_DEVICE_OUT_REMOTE_SUBMIX | + AUDIO_DEVICE_OUT_TELEPHONY_TX | + AUDIO_DEVICE_OUT_LINE | + AUDIO_DEVICE_OUT_HDMI_ARC | + AUDIO_DEVICE_OUT_SPDIF | + AUDIO_DEVICE_OUT_FM | + AUDIO_DEVICE_OUT_AUX_LINE | + AUDIO_DEVICE_OUT_SPEAKER_SAFE | + AUDIO_DEVICE_OUT_IP | + AUDIO_DEVICE_OUT_BUS | + AUDIO_DEVICE_OUT_PROXY | + AUDIO_DEVICE_OUT_USB_HEADSET | + AUDIO_DEVICE_OUT_HEARING_AID | + AUDIO_DEVICE_OUT_ECHO_CANCELLER | + AUDIO_DEVICE_OUT_DEFAULT, + + AUDIO_DEVICE_OUT_ALL_A2DP = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, + + AUDIO_DEVICE_OUT_ALL_SCO = AUDIO_DEVICE_OUT_BLUETOOTH_SCO | + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET | + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, + + AUDIO_DEVICE_OUT_ALL_USB = AUDIO_DEVICE_OUT_USB_ACCESSORY | + AUDIO_DEVICE_OUT_USB_DEVICE | + AUDIO_DEVICE_OUT_USB_HEADSET, + + AUDIO_DEVICE_IN_ALL = AUDIO_DEVICE_IN_COMMUNICATION | + AUDIO_DEVICE_IN_AMBIENT | + AUDIO_DEVICE_IN_BUILTIN_MIC | + AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET | + AUDIO_DEVICE_IN_WIRED_HEADSET | + AUDIO_DEVICE_IN_HDMI | + AUDIO_DEVICE_IN_TELEPHONY_RX | + AUDIO_DEVICE_IN_BACK_MIC | + AUDIO_DEVICE_IN_REMOTE_SUBMIX | + AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET | + AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET | + AUDIO_DEVICE_IN_USB_ACCESSORY | + AUDIO_DEVICE_IN_USB_DEVICE | + AUDIO_DEVICE_IN_FM_TUNER | + AUDIO_DEVICE_IN_TV_TUNER | + AUDIO_DEVICE_IN_LINE | + AUDIO_DEVICE_IN_SPDIF | + AUDIO_DEVICE_IN_BLUETOOTH_A2DP | + AUDIO_DEVICE_IN_LOOPBACK | + AUDIO_DEVICE_IN_IP | + AUDIO_DEVICE_IN_BUS | + AUDIO_DEVICE_IN_PROXY | + AUDIO_DEVICE_IN_USB_HEADSET | + AUDIO_DEVICE_IN_BLUETOOTH_BLE | + AUDIO_DEVICE_IN_DEFAULT, + + AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, + + AUDIO_DEVICE_IN_ALL_USB = AUDIO_DEVICE_IN_USB_ACCESSORY | + AUDIO_DEVICE_IN_USB_DEVICE | + AUDIO_DEVICE_IN_USB_HEADSET, + + AUDIO_USAGE_MAX = AUDIO_USAGE_ASSISTANT, + AUDIO_USAGE_CNT = AUDIO_USAGE_ASSISTANT + 1, + + AUDIO_PORT_CONFIG_ALL = AUDIO_PORT_CONFIG_SAMPLE_RATE | + AUDIO_PORT_CONFIG_CHANNEL_MASK | + AUDIO_PORT_CONFIG_FORMAT | + AUDIO_PORT_CONFIG_GAIN, +}; // enum + + +#endif // ANDROID_AUDIO_BASE_UTILS_H diff --git a/include/hardware/system/audio-base.h b/include/hardware/system/audio-base.h new file mode 100644 index 0000000..3d0638d --- /dev/null +++ b/include/hardware/system/audio-base.h @@ -0,0 +1,450 @@ +// This file is autogenerated by hidl-gen +// then manualy edited for retrocompatiblity +// Source: android.hardware.audio.common@4.0 +// Root: android.hardware:hardware/interfaces + +#ifndef HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V4_0_EXPORTED_CONSTANTS_H_ +#define HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V4_0_EXPORTED_CONSTANTS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + AUDIO_IO_HANDLE_NONE = 0, + AUDIO_MODULE_HANDLE_NONE = 0, + AUDIO_PORT_HANDLE_NONE = 0, + AUDIO_PATCH_HANDLE_NONE = 0, +}; + +typedef enum { + AUDIO_STREAM_DEFAULT = -1, // (-1) + AUDIO_STREAM_MIN = 0, + AUDIO_STREAM_VOICE_CALL = 0, + AUDIO_STREAM_SYSTEM = 1, + AUDIO_STREAM_RING = 2, + AUDIO_STREAM_MUSIC = 3, + AUDIO_STREAM_ALARM = 4, + AUDIO_STREAM_NOTIFICATION = 5, + AUDIO_STREAM_BLUETOOTH_SCO = 6, + AUDIO_STREAM_ENFORCED_AUDIBLE = 7, + AUDIO_STREAM_DTMF = 8, + AUDIO_STREAM_TTS = 9, + AUDIO_STREAM_ACCESSIBILITY = 10, +#ifndef AUDIO_NO_SYSTEM_DECLARATIONS + /** For dynamic policy output mixes. Only used by the audio policy */ + AUDIO_STREAM_REROUTING = 11, + /** For audio flinger tracks volume. Only used by the audioflinger */ + AUDIO_STREAM_PATCH = 12, +#endif // AUDIO_NO_SYSTEM_DECLARATIONS +} audio_stream_type_t; + +typedef enum { + AUDIO_SOURCE_DEFAULT = 0, + AUDIO_SOURCE_MIC = 1, + AUDIO_SOURCE_VOICE_UPLINK = 2, + AUDIO_SOURCE_VOICE_DOWNLINK = 3, + AUDIO_SOURCE_VOICE_CALL = 4, + AUDIO_SOURCE_CAMCORDER = 5, + AUDIO_SOURCE_VOICE_RECOGNITION = 6, + AUDIO_SOURCE_VOICE_COMMUNICATION = 7, + AUDIO_SOURCE_REMOTE_SUBMIX = 8, + AUDIO_SOURCE_UNPROCESSED = 9, + AUDIO_SOURCE_FM_TUNER = 1998, +#ifndef AUDIO_NO_SYSTEM_DECLARATIONS + /** + * A low-priority, preemptible audio source for for background software + * hotword detection. Same tuning as VOICE_RECOGNITION. + * Used only internally by the framework. + */ + AUDIO_SOURCE_HOTWORD = 1999, +#endif // AUDIO_NO_SYSTEM_DECLARATIONS +} audio_source_t; + +typedef enum { + AUDIO_SESSION_OUTPUT_STAGE = -1, // (-1) + AUDIO_SESSION_OUTPUT_MIX = 0, + AUDIO_SESSION_ALLOCATE = 0, + AUDIO_SESSION_NONE = 0, +} audio_session_t; + +typedef enum { + AUDIO_FORMAT_INVALID = 0xFFFFFFFFu, + AUDIO_FORMAT_DEFAULT = 0, + AUDIO_FORMAT_PCM = 0x00000000u, + AUDIO_FORMAT_MP3 = 0x01000000u, + AUDIO_FORMAT_AMR_NB = 0x02000000u, + AUDIO_FORMAT_AMR_WB = 0x03000000u, + AUDIO_FORMAT_AAC = 0x04000000u, + AUDIO_FORMAT_HE_AAC_V1 = 0x05000000u, + AUDIO_FORMAT_HE_AAC_V2 = 0x06000000u, + AUDIO_FORMAT_VORBIS = 0x07000000u, + AUDIO_FORMAT_OPUS = 0x08000000u, + AUDIO_FORMAT_AC3 = 0x09000000u, + AUDIO_FORMAT_E_AC3 = 0x0A000000u, + AUDIO_FORMAT_DTS = 0x0B000000u, + AUDIO_FORMAT_DTS_HD = 0x0C000000u, + AUDIO_FORMAT_IEC61937 = 0x0D000000u, + AUDIO_FORMAT_DOLBY_TRUEHD = 0x0E000000u, + AUDIO_FORMAT_EVRC = 0x10000000u, + AUDIO_FORMAT_EVRCB = 0x11000000u, + AUDIO_FORMAT_EVRCWB = 0x12000000u, + AUDIO_FORMAT_EVRCNW = 0x13000000u, + AUDIO_FORMAT_AAC_ADIF = 0x14000000u, + AUDIO_FORMAT_WMA = 0x15000000u, + AUDIO_FORMAT_WMA_PRO = 0x16000000u, + AUDIO_FORMAT_AMR_WB_PLUS = 0x17000000u, + AUDIO_FORMAT_MP2 = 0x18000000u, + AUDIO_FORMAT_QCELP = 0x19000000u, + AUDIO_FORMAT_DSD = 0x1A000000u, + AUDIO_FORMAT_FLAC = 0x1B000000u, + AUDIO_FORMAT_ALAC = 0x1C000000u, + AUDIO_FORMAT_APE = 0x1D000000u, + AUDIO_FORMAT_AAC_ADTS = 0x1E000000u, + AUDIO_FORMAT_SBC = 0x1F000000u, + AUDIO_FORMAT_APTX = 0x20000000u, + AUDIO_FORMAT_APTX_HD = 0x21000000u, + AUDIO_FORMAT_AC4 = 0x22000000u, + AUDIO_FORMAT_LDAC = 0x23000000u, + AUDIO_FORMAT_MAT = 0x24000000u, + AUDIO_FORMAT_MAIN_MASK = 0xFF000000u, + AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFu, + + /* Subformats */ + AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1u, + AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2u, + AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3u, + AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4u, + AUDIO_FORMAT_PCM_SUB_FLOAT = 0x5u, + AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED = 0x6u, + + AUDIO_FORMAT_MP3_SUB_NONE = 0x0u, + + AUDIO_FORMAT_AMR_SUB_NONE = 0x0u, + + AUDIO_FORMAT_AAC_SUB_MAIN = 0x1u, + AUDIO_FORMAT_AAC_SUB_LC = 0x2u, + AUDIO_FORMAT_AAC_SUB_SSR = 0x4u, + AUDIO_FORMAT_AAC_SUB_LTP = 0x8u, + AUDIO_FORMAT_AAC_SUB_HE_V1 = 0x10u, + AUDIO_FORMAT_AAC_SUB_SCALABLE = 0x20u, + AUDIO_FORMAT_AAC_SUB_ERLC = 0x40u, + AUDIO_FORMAT_AAC_SUB_LD = 0x80u, + AUDIO_FORMAT_AAC_SUB_HE_V2 = 0x100u, + AUDIO_FORMAT_AAC_SUB_ELD = 0x200u, + AUDIO_FORMAT_AAC_SUB_XHE = 0x300u, + + AUDIO_FORMAT_VORBIS_SUB_NONE = 0x0u, + + AUDIO_FORMAT_E_AC3_SUB_JOC = 0x1u, + + AUDIO_FORMAT_MAT_SUB_1_0 = 0x1u, + AUDIO_FORMAT_MAT_SUB_2_0 = 0x2u, + AUDIO_FORMAT_MAT_SUB_2_1 = 0x3u, + + /* Aliases */ + AUDIO_FORMAT_PCM_16_BIT = 0x1u, // (PCM | PCM_SUB_16_BIT) + AUDIO_FORMAT_PCM_8_BIT = 0x2u, // (PCM | PCM_SUB_8_BIT) + AUDIO_FORMAT_PCM_32_BIT = 0x3u, // (PCM | PCM_SUB_32_BIT) + AUDIO_FORMAT_PCM_8_24_BIT = 0x4u, // (PCM | PCM_SUB_8_24_BIT) + AUDIO_FORMAT_PCM_FLOAT = 0x5u, // (PCM | PCM_SUB_FLOAT) + AUDIO_FORMAT_PCM_24_BIT_PACKED = 0x6u, // (PCM | PCM_SUB_24_BIT_PACKED) + AUDIO_FORMAT_AAC_MAIN = 0x4000001u, // (AAC | AAC_SUB_MAIN) + AUDIO_FORMAT_AAC_LC = 0x4000002u, // (AAC | AAC_SUB_LC) + AUDIO_FORMAT_AAC_SSR = 0x4000004u, // (AAC | AAC_SUB_SSR) + AUDIO_FORMAT_AAC_LTP = 0x4000008u, // (AAC | AAC_SUB_LTP) + AUDIO_FORMAT_AAC_HE_V1 = 0x4000010u, // (AAC | AAC_SUB_HE_V1) + AUDIO_FORMAT_AAC_SCALABLE = 0x4000020u, // (AAC | AAC_SUB_SCALABLE) + AUDIO_FORMAT_AAC_ERLC = 0x4000040u, // (AAC | AAC_SUB_ERLC) + AUDIO_FORMAT_AAC_LD = 0x4000080u, // (AAC | AAC_SUB_LD) + AUDIO_FORMAT_AAC_HE_V2 = 0x4000100u, // (AAC | AAC_SUB_HE_V2) + AUDIO_FORMAT_AAC_ELD = 0x4000200u, // (AAC | AAC_SUB_ELD) + AUDIO_FORMAT_AAC_XHE = 0x4000300u, // (AAC | AAC_SUB_XHE) + AUDIO_FORMAT_AAC_ADTS_MAIN = 0x1e000001u, // (AAC_ADTS | AAC_SUB_MAIN) + AUDIO_FORMAT_AAC_ADTS_LC = 0x1e000002u, // (AAC_ADTS | AAC_SUB_LC) + AUDIO_FORMAT_AAC_ADTS_SSR = 0x1e000004u, // (AAC_ADTS | AAC_SUB_SSR) + AUDIO_FORMAT_AAC_ADTS_LTP = 0x1e000008u, // (AAC_ADTS | AAC_SUB_LTP) + AUDIO_FORMAT_AAC_ADTS_HE_V1 = 0x1e000010u, // (AAC_ADTS | AAC_SUB_HE_V1) + AUDIO_FORMAT_AAC_ADTS_SCALABLE = 0x1e000020u, // (AAC_ADTS | AAC_SUB_SCALABLE) + AUDIO_FORMAT_AAC_ADTS_ERLC = 0x1e000040u, // (AAC_ADTS | AAC_SUB_ERLC) + AUDIO_FORMAT_AAC_ADTS_LD = 0x1e000080u, // (AAC_ADTS | AAC_SUB_LD) + AUDIO_FORMAT_AAC_ADTS_HE_V2 = 0x1e000100u, // (AAC_ADTS | AAC_SUB_HE_V2) + AUDIO_FORMAT_AAC_ADTS_ELD = 0x1e000200u, // (AAC_ADTS | AAC_SUB_ELD) + AUDIO_FORMAT_AAC_ADTS_XHE = 0x1e000300u, // (AAC_ADTS | AAC_SUB_XHE) + AUDIO_FORMAT_E_AC3_JOC = 0xA000001u, // (E_AC3 | E_AC3_SUB_JOC) + AUDIO_FORMAT_MAT_1_0 = 0x24000001u, // (MAT | MAT_SUB_1_0) + AUDIO_FORMAT_MAT_2_0 = 0x24000002u, // (MAT | MAT_SUB_2_0) + AUDIO_FORMAT_MAT_2_1 = 0x24000003u, // (MAT | MAT_SUB_2_1) +} audio_format_t; + +enum { + FCC_2 = 2, + FCC_8 = 8, +}; + +enum { + AUDIO_CHANNEL_REPRESENTATION_POSITION = 0x0u, + AUDIO_CHANNEL_REPRESENTATION_INDEX = 0x2u, + AUDIO_CHANNEL_NONE = 0x0u, + AUDIO_CHANNEL_INVALID = 0xC0000000u, + + AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1u, + AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2u, + AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4u, + AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8u, + AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10u, + AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20u, + AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40u, + AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u, + AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100u, + AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200u, + AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400u, + AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800u, + AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000u, + AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000u, + AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000u, + AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000u, + AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000u, + AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000u, + AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT = 0x40000u, + AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT = 0x80000u, + AUDIO_CHANNEL_OUT_MONO = 0x1u, // OUT_FRONT_LEFT + AUDIO_CHANNEL_OUT_STEREO = 0x3u, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT + AUDIO_CHANNEL_OUT_2POINT1 = 0xBu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_LOW_FREQUENCY + AUDIO_CHANNEL_OUT_2POINT0POINT2 = 0xC0003u, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT + AUDIO_CHANNEL_OUT_2POINT1POINT2 = 0xC000Bu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY + AUDIO_CHANNEL_OUT_3POINT0POINT2 = 0xC0007u, // OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT + AUDIO_CHANNEL_OUT_3POINT1POINT2 = 0xC000Fu, // OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY + AUDIO_CHANNEL_OUT_QUAD = 0x33u, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_BACK_LEFT | OUT_BACK_RIGHT + AUDIO_CHANNEL_OUT_QUAD_BACK = 0x33u, // OUT_QUAD + AUDIO_CHANNEL_OUT_QUAD_SIDE = 0x603u, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_SIDE_LEFT | OUT_SIDE_RIGHT + AUDIO_CHANNEL_OUT_SURROUND = 0x107u, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_BACK_CENTER + AUDIO_CHANNEL_OUT_PENTA = 0x37u, // OUT_QUAD | OUT_FRONT_CENTER + AUDIO_CHANNEL_OUT_5POINT1 = 0x3Fu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT + AUDIO_CHANNEL_OUT_5POINT1_BACK = 0x3Fu, // OUT_5POINT1 + AUDIO_CHANNEL_OUT_5POINT1_SIDE = 0x60Fu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_SIDE_LEFT | OUT_SIDE_RIGHT + AUDIO_CHANNEL_OUT_5POINT1POINT2 = 0xC003Fu, // OUT_5POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT + AUDIO_CHANNEL_OUT_5POINT1POINT4 = 0x2D03Fu, // OUT_5POINT1 | OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT | OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT + AUDIO_CHANNEL_OUT_6POINT1 = 0x13Fu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT | OUT_BACK_CENTER + AUDIO_CHANNEL_OUT_7POINT1 = 0x63Fu, // OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT | OUT_SIDE_LEFT | OUT_SIDE_RIGHT + AUDIO_CHANNEL_OUT_7POINT1POINT2 = 0xC063Fu, // OUT_7POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT + AUDIO_CHANNEL_OUT_7POINT1POINT4 = 0x2D63Fu, // OUT_7POINT1 | OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT | OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT + + AUDIO_CHANNEL_IN_LEFT = 0x4u, + AUDIO_CHANNEL_IN_RIGHT = 0x8u, + AUDIO_CHANNEL_IN_FRONT = 0x10u, + AUDIO_CHANNEL_IN_BACK = 0x20u, + AUDIO_CHANNEL_IN_LEFT_PROCESSED = 0x40u, + AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80u, + AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100u, + AUDIO_CHANNEL_IN_BACK_PROCESSED = 0x200u, + AUDIO_CHANNEL_IN_PRESSURE = 0x400u, + AUDIO_CHANNEL_IN_X_AXIS = 0x800u, + AUDIO_CHANNEL_IN_Y_AXIS = 0x1000u, + AUDIO_CHANNEL_IN_Z_AXIS = 0x2000u, + AUDIO_CHANNEL_IN_BACK_LEFT = 0x10000u, + AUDIO_CHANNEL_IN_BACK_RIGHT = 0x20000u, + AUDIO_CHANNEL_IN_CENTER = 0x40000u, + AUDIO_CHANNEL_IN_LOW_FREQUENCY = 0x100000u, + AUDIO_CHANNEL_IN_TOP_LEFT = 0x200000u, + AUDIO_CHANNEL_IN_TOP_RIGHT = 0x400000u, + AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000u, + AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000u, + AUDIO_CHANNEL_IN_MONO = 0x10u, // IN_FRONT + AUDIO_CHANNEL_IN_STEREO = 0xCu, // IN_LEFT | IN_RIGHT + AUDIO_CHANNEL_IN_FRONT_BACK = 0x30u, // IN_FRONT | IN_BACK + AUDIO_CHANNEL_IN_6 = 0xFCu, // IN_LEFT | IN_RIGHT | IN_FRONT | IN_BACK | IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED + AUDIO_CHANNEL_IN_2POINT0POINT2 = 0x60000Cu, // IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT + AUDIO_CHANNEL_IN_2POINT1POINT2 = 0x70000Cu, // IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY + AUDIO_CHANNEL_IN_3POINT0POINT2 = 0x64000Cu, // IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT + AUDIO_CHANNEL_IN_3POINT1POINT2 = 0x74000Cu, // IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY + AUDIO_CHANNEL_IN_5POINT1 = 0x17000Cu, // IN_LEFT | IN_CENTER | IN_RIGHT | IN_BACK_LEFT | IN_BACK_RIGHT | IN_LOW_FREQUENCY + AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO = 0x4010u, // IN_VOICE_UPLINK | IN_MONO + AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO = 0x8010u, // IN_VOICE_DNLINK | IN_MONO + AUDIO_CHANNEL_IN_VOICE_CALL_MONO = 0xC010u, // IN_VOICE_UPLINK_MONO | IN_VOICE_DNLINK_MONO + + AUDIO_CHANNEL_COUNT_MAX = 30u, + AUDIO_CHANNEL_INDEX_HDR = 0x80000000u, // REPRESENTATION_INDEX << COUNT_MAX + AUDIO_CHANNEL_INDEX_MASK_1 = 0x80000001u, // INDEX_HDR | (1 << 1) - 1 + AUDIO_CHANNEL_INDEX_MASK_2 = 0x80000003u, // INDEX_HDR | (1 << 2) - 1 + AUDIO_CHANNEL_INDEX_MASK_3 = 0x80000007u, // INDEX_HDR | (1 << 3) - 1 + AUDIO_CHANNEL_INDEX_MASK_4 = 0x8000000Fu, // INDEX_HDR | (1 << 4) - 1 + AUDIO_CHANNEL_INDEX_MASK_5 = 0x8000001Fu, // INDEX_HDR | (1 << 5) - 1 + AUDIO_CHANNEL_INDEX_MASK_6 = 0x8000003Fu, // INDEX_HDR | (1 << 6) - 1 + AUDIO_CHANNEL_INDEX_MASK_7 = 0x8000007Fu, // INDEX_HDR | (1 << 7) - 1 + AUDIO_CHANNEL_INDEX_MASK_8 = 0x800000FFu, // INDEX_HDR | (1 << 8) - 1 +}; + +typedef enum { +#ifndef AUDIO_NO_SYSTEM_DECLARATIONS + AUDIO_MODE_INVALID = -2, // (-2) + AUDIO_MODE_CURRENT = -1, // (-1) +#endif // AUDIO_NO_SYSTEM_DECLARATIONS + AUDIO_MODE_NORMAL = 0, + AUDIO_MODE_RINGTONE = 1, + AUDIO_MODE_IN_CALL = 2, + AUDIO_MODE_IN_COMMUNICATION = 3, +} audio_mode_t; + +enum { + AUDIO_DEVICE_NONE = 0x0u, + AUDIO_DEVICE_BIT_IN = 0x80000000u, + AUDIO_DEVICE_BIT_DEFAULT = 0x40000000u, + + AUDIO_DEVICE_OUT_EARPIECE = 0x1u, + AUDIO_DEVICE_OUT_SPEAKER = 0x2u, + AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4u, + AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8u, + AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10u, + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20u, + AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40u, + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80u, + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100u, + AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200u, + AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400u, + AUDIO_DEVICE_OUT_HDMI = 0x400u, // OUT_AUX_DIGITAL + AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800u, + AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000u, + AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000u, + AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000u, + AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000u, + AUDIO_DEVICE_OUT_TELEPHONY_TX = 0x10000u, + AUDIO_DEVICE_OUT_LINE = 0x20000u, + AUDIO_DEVICE_OUT_HDMI_ARC = 0x40000u, + AUDIO_DEVICE_OUT_SPDIF = 0x80000u, + AUDIO_DEVICE_OUT_FM = 0x100000u, + AUDIO_DEVICE_OUT_AUX_LINE = 0x200000u, + AUDIO_DEVICE_OUT_SPEAKER_SAFE = 0x400000u, + AUDIO_DEVICE_OUT_IP = 0x800000u, + AUDIO_DEVICE_OUT_BUS = 0x1000000u, + AUDIO_DEVICE_OUT_PROXY = 0x2000000u, + AUDIO_DEVICE_OUT_USB_HEADSET = 0x4000000u, + AUDIO_DEVICE_OUT_HEARING_AID = 0x8000000u, + AUDIO_DEVICE_OUT_ECHO_CANCELLER = 0x10000000u, + AUDIO_DEVICE_OUT_DEFAULT = 0x40000000u, // BIT_DEFAULT + + AUDIO_DEVICE_IN_COMMUNICATION = 0x80000001u, // BIT_IN | 0x1 + AUDIO_DEVICE_IN_AMBIENT = 0x80000002u, // BIT_IN | 0x2 + AUDIO_DEVICE_IN_BUILTIN_MIC = 0x80000004u, // BIT_IN | 0x4 + AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000008u, // BIT_IN | 0x8 + AUDIO_DEVICE_IN_WIRED_HEADSET = 0x80000010u, // BIT_IN | 0x10 + AUDIO_DEVICE_IN_AUX_DIGITAL = 0x80000020u, // BIT_IN | 0x20 + AUDIO_DEVICE_IN_HDMI = 0x80000020u, // IN_AUX_DIGITAL + AUDIO_DEVICE_IN_VOICE_CALL = 0x80000040u, // BIT_IN | 0x40 + AUDIO_DEVICE_IN_TELEPHONY_RX = 0x80000040u, // IN_VOICE_CALL + AUDIO_DEVICE_IN_BACK_MIC = 0x80000080u, // BIT_IN | 0x80 + AUDIO_DEVICE_IN_REMOTE_SUBMIX = 0x80000100u, // BIT_IN | 0x100 + AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = 0x80000200u, // BIT_IN | 0x200 + AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = 0x80000400u, // BIT_IN | 0x400 + AUDIO_DEVICE_IN_USB_ACCESSORY = 0x80000800u, // BIT_IN | 0x800 + AUDIO_DEVICE_IN_USB_DEVICE = 0x80001000u, // BIT_IN | 0x1000 + AUDIO_DEVICE_IN_FM_TUNER = 0x80002000u, // BIT_IN | 0x2000 + AUDIO_DEVICE_IN_TV_TUNER = 0x80004000u, // BIT_IN | 0x4000 + AUDIO_DEVICE_IN_LINE = 0x80008000u, // BIT_IN | 0x8000 + AUDIO_DEVICE_IN_SPDIF = 0x80010000u, // BIT_IN | 0x10000 + AUDIO_DEVICE_IN_BLUETOOTH_A2DP = 0x80020000u, // BIT_IN | 0x20000 + AUDIO_DEVICE_IN_LOOPBACK = 0x80040000u, // BIT_IN | 0x40000 + AUDIO_DEVICE_IN_IP = 0x80080000u, // BIT_IN | 0x80000 + AUDIO_DEVICE_IN_BUS = 0x80100000u, // BIT_IN | 0x100000 + AUDIO_DEVICE_IN_PROXY = 0x81000000u, // BIT_IN | 0x1000000 + AUDIO_DEVICE_IN_USB_HEADSET = 0x82000000u, // BIT_IN | 0x2000000 + AUDIO_DEVICE_IN_BLUETOOTH_BLE = 0x84000000u, // BIT_IN | 0x4000000 + AUDIO_DEVICE_IN_DEFAULT = 0xC0000000u, // BIT_IN | BIT_DEFAULT +}; + +typedef enum { + AUDIO_OUTPUT_FLAG_NONE = 0x0, + AUDIO_OUTPUT_FLAG_DIRECT = 0x1, + AUDIO_OUTPUT_FLAG_PRIMARY = 0x2, + AUDIO_OUTPUT_FLAG_FAST = 0x4, + AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, + AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10, + AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20, + AUDIO_OUTPUT_FLAG_HW_AV_SYNC = 0x40, + AUDIO_OUTPUT_FLAG_TTS = 0x80, + AUDIO_OUTPUT_FLAG_RAW = 0x100, + AUDIO_OUTPUT_FLAG_SYNC = 0x200, + AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO = 0x400, + AUDIO_OUTPUT_FLAG_DIRECT_PCM = 0x2000, + AUDIO_OUTPUT_FLAG_MMAP_NOIRQ = 0x4000, + AUDIO_OUTPUT_FLAG_VOIP_RX = 0x8000, + AUDIO_OUTPUT_FLAG_INCALL_MUSIC = 0x10000, +} audio_output_flags_t; + +typedef enum { + AUDIO_INPUT_FLAG_NONE = 0x0, + AUDIO_INPUT_FLAG_FAST = 0x1, + AUDIO_INPUT_FLAG_HW_HOTWORD = 0x2, + AUDIO_INPUT_FLAG_RAW = 0x4, + AUDIO_INPUT_FLAG_SYNC = 0x8, + AUDIO_INPUT_FLAG_MMAP_NOIRQ = 0x10, + AUDIO_INPUT_FLAG_VOIP_TX = 0x20, + AUDIO_INPUT_FLAG_HW_AV_SYNC = 0x40, +} audio_input_flags_t; + +typedef enum { + AUDIO_USAGE_UNKNOWN = 0, + AUDIO_USAGE_MEDIA = 1, + AUDIO_USAGE_VOICE_COMMUNICATION = 2, + AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING = 3, + AUDIO_USAGE_ALARM = 4, + AUDIO_USAGE_NOTIFICATION = 5, + AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6, +#ifndef AUDIO_NO_SYSTEM_DECLARATIONS + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9, + AUDIO_USAGE_NOTIFICATION_EVENT = 10, +#endif // AUDIO_NO_SYSTEM_DECLARATIONS + AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY = 11, + AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12, + AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13, + AUDIO_USAGE_GAME = 14, + AUDIO_USAGE_VIRTUAL_SOURCE = 15, + AUDIO_USAGE_ASSISTANT = 16, +} audio_usage_t; + +typedef enum { + AUDIO_CONTENT_TYPE_UNKNOWN = 0u, + AUDIO_CONTENT_TYPE_SPEECH = 1u, + AUDIO_CONTENT_TYPE_MUSIC = 2u, + AUDIO_CONTENT_TYPE_MOVIE = 3u, + AUDIO_CONTENT_TYPE_SONIFICATION = 4u, +} audio_content_type_t; + +enum { + AUDIO_GAIN_MODE_JOINT = 0x1u, + AUDIO_GAIN_MODE_CHANNELS = 0x2u, + AUDIO_GAIN_MODE_RAMP = 0x4u, +}; + +typedef enum { + AUDIO_PORT_ROLE_NONE = 0, + AUDIO_PORT_ROLE_SOURCE = 1, // (::android::hardware::audio::common::V4_0::AudioPortRole.NONE implicitly + 1) + AUDIO_PORT_ROLE_SINK = 2, // (::android::hardware::audio::common::V4_0::AudioPortRole.SOURCE implicitly + 1) +} audio_port_role_t; + +typedef enum { + AUDIO_PORT_TYPE_NONE = 0, + AUDIO_PORT_TYPE_DEVICE = 1, // (::android::hardware::audio::common::V4_0::AudioPortType.NONE implicitly + 1) + AUDIO_PORT_TYPE_MIX = 2, // (::android::hardware::audio::common::V4_0::AudioPortType.DEVICE implicitly + 1) + AUDIO_PORT_TYPE_SESSION = 3, // (::android::hardware::audio::common::V4_0::AudioPortType.MIX implicitly + 1) +} audio_port_type_t; + +enum { + AUDIO_PORT_CONFIG_SAMPLE_RATE = 0x1u, + AUDIO_PORT_CONFIG_CHANNEL_MASK = 0x2u, + AUDIO_PORT_CONFIG_FORMAT = 0x4u, + AUDIO_PORT_CONFIG_GAIN = 0x8u, +}; + +typedef enum { + AUDIO_LATENCY_LOW = 0, + AUDIO_LATENCY_NORMAL = 1, // (::android::hardware::audio::common::V4_0::AudioMixLatencyClass.LOW implicitly + 1) +} audio_mix_latency_class_t; + +#ifdef __cplusplus +} +#endif + +#endif // HIDL_GENERATED_ANDROID_HARDWARE_AUDIO_COMMON_V4_0_EXPORTED_CONSTANTS_H_ diff --git a/include/hardware/system/audio.h b/include/hardware/system/audio.h new file mode 100644 index 0000000..42f17dc --- /dev/null +++ b/include/hardware/system/audio.h @@ -0,0 +1,1230 @@ +/* + * 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 ANDROID_AUDIO_CORE_H +#define ANDROID_AUDIO_CORE_H + +#include +#include +#include +#include +#include + +#include "cutils/bitops.h" + +#include "audio-base.h" +#include "audio-base-utils.h" + +__BEGIN_DECLS + +/* The enums were moved here mostly from + * frameworks/base/include/media/AudioSystem.h + */ + +/* represents an invalid uid for tracks; the calling or client uid is often substituted. */ +#define AUDIO_UID_INVALID ((uid_t)-1) + +/* device address used to refer to the standard remote submix */ +#define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0" + +/* AudioFlinger and AudioPolicy services use I/O handles to identify audio sources and sinks */ +typedef int audio_io_handle_t; + +typedef uint32_t audio_flags_mask_t; + +/* Do not change these values without updating their counterparts + * in frameworks/base/media/java/android/media/AudioAttributes.java + */ +enum { + AUDIO_FLAG_NONE = 0x0, + AUDIO_FLAG_AUDIBILITY_ENFORCED = 0x1, + AUDIO_FLAG_SECURE = 0x2, + AUDIO_FLAG_SCO = 0x4, + AUDIO_FLAG_BEACON = 0x8, + AUDIO_FLAG_HW_AV_SYNC = 0x10, + AUDIO_FLAG_HW_HOTWORD = 0x20, + AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY = 0x40, + AUDIO_FLAG_BYPASS_MUTE = 0x80, + AUDIO_FLAG_LOW_LATENCY = 0x100, + AUDIO_FLAG_DEEP_BUFFER = 0x200, +}; + +/* Audio attributes */ +#define AUDIO_ATTRIBUTES_TAGS_MAX_SIZE 256 +typedef struct { + audio_content_type_t content_type; + audio_usage_t usage; + audio_source_t source; + audio_flags_mask_t flags; + char tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */ +} __attribute__((packed)) audio_attributes_t; // sent through Binder; + +/* a unique ID allocated by AudioFlinger for use as an audio_io_handle_t, audio_session_t, + * effect ID (int), audio_module_handle_t, and audio_patch_handle_t. + * Audio port IDs (audio_port_handle_t) are allocated by AudioPolicy + * in a different namespace than AudioFlinger unique IDs. + */ +typedef int audio_unique_id_t; + +/* Possible uses for an audio_unique_id_t */ +typedef enum { + AUDIO_UNIQUE_ID_USE_UNSPECIFIED = 0, + AUDIO_UNIQUE_ID_USE_SESSION = 1, // for allocated sessions, not special AUDIO_SESSION_* + AUDIO_UNIQUE_ID_USE_MODULE = 2, + AUDIO_UNIQUE_ID_USE_EFFECT = 3, + AUDIO_UNIQUE_ID_USE_PATCH = 4, + AUDIO_UNIQUE_ID_USE_OUTPUT = 5, + AUDIO_UNIQUE_ID_USE_INPUT = 6, + AUDIO_UNIQUE_ID_USE_PLAYER = 7, + AUDIO_UNIQUE_ID_USE_MAX = 8, // must be a power-of-two + AUDIO_UNIQUE_ID_USE_MASK = AUDIO_UNIQUE_ID_USE_MAX - 1 +} audio_unique_id_use_t; + +/* Return the use of an audio_unique_id_t */ +static inline audio_unique_id_use_t audio_unique_id_get_use(audio_unique_id_t id) +{ + return (audio_unique_id_use_t) (id & AUDIO_UNIQUE_ID_USE_MASK); +} + +/* Reserved audio_unique_id_t values. FIXME: not a complete list. */ +#define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE + +/* A channel mask per se only defines the presence or absence of a channel, not the order. + * But see AUDIO_INTERLEAVE_* below for the platform convention of order. + * + * audio_channel_mask_t is an opaque type and its internal layout should not + * be assumed as it may change in the future. + * Instead, always use the functions declared in this header to examine. + * + * These are the current representations: + * + * AUDIO_CHANNEL_REPRESENTATION_POSITION + * is a channel mask representation for position assignment. + * Each low-order bit corresponds to the spatial position of a transducer (output), + * or interpretation of channel (input). + * The user of a channel mask needs to know the context of whether it is for output or input. + * The constants AUDIO_CHANNEL_OUT_* or AUDIO_CHANNEL_IN_* apply to the bits portion. + * It is not permitted for no bits to be set. + * + * AUDIO_CHANNEL_REPRESENTATION_INDEX + * is a channel mask representation for index assignment. + * Each low-order bit corresponds to a selected channel. + * There is no platform interpretation of the various bits. + * There is no concept of output or input. + * It is not permitted for no bits to be set. + * + * All other representations are reserved for future use. + * + * Warning: current representation distinguishes between input and output, but this will not the be + * case in future revisions of the platform. Wherever there is an ambiguity between input and output + * that is currently resolved by checking the channel mask, the implementer should look for ways to + * fix it with additional information outside of the mask. + */ +typedef uint32_t audio_channel_mask_t; + +/* log(2) of maximum number of representations, not part of public API */ +#define AUDIO_CHANNEL_REPRESENTATION_LOG2 2 + +/* The return value is undefined if the channel mask is invalid. */ +static inline uint32_t audio_channel_mask_get_bits(audio_channel_mask_t channel) +{ + return channel & ((1 << AUDIO_CHANNEL_COUNT_MAX) - 1); +} + +typedef uint32_t audio_channel_representation_t; + +/* The return value is undefined if the channel mask is invalid. */ +static inline audio_channel_representation_t audio_channel_mask_get_representation( + audio_channel_mask_t channel) +{ + // The right shift should be sufficient, but also "and" for safety in case mask is not 32 bits + return (audio_channel_representation_t) + ((channel >> AUDIO_CHANNEL_COUNT_MAX) & ((1 << AUDIO_CHANNEL_REPRESENTATION_LOG2) - 1)); +} + +/* Returns true if the channel mask is valid, + * or returns false for AUDIO_CHANNEL_NONE, AUDIO_CHANNEL_INVALID, and other invalid values. + * This function is unable to determine whether a channel mask for position assignment + * is invalid because an output mask has an invalid output bit set, + * or because an input mask has an invalid input bit set. + * All other APIs that take a channel mask assume that it is valid. + */ +static inline bool audio_channel_mask_is_valid(audio_channel_mask_t channel) +{ + uint32_t bits = audio_channel_mask_get_bits(channel); + audio_channel_representation_t representation = audio_channel_mask_get_representation(channel); + switch (representation) { + case AUDIO_CHANNEL_REPRESENTATION_POSITION: + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + break; + default: + bits = 0; + break; + } + return bits != 0; +} + +/* Not part of public API */ +static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bits( + audio_channel_representation_t representation, uint32_t bits) +{ + return (audio_channel_mask_t) ((representation << AUDIO_CHANNEL_COUNT_MAX) | bits); +} + +/** + * Expresses the convention when stereo audio samples are stored interleaved + * in an array. This should improve readability by allowing code to use + * symbolic indices instead of hard-coded [0] and [1]. + * + * For multi-channel beyond stereo, the platform convention is that channels + * are interleaved in order from least significant channel mask bit to most + * significant channel mask bit, with unused bits skipped. Any exceptions + * to this convention will be noted at the appropriate API. + */ +enum { + AUDIO_INTERLEAVE_LEFT = 0, + AUDIO_INTERLEAVE_RIGHT = 1, +}; + +/* This enum is deprecated */ +typedef enum { + AUDIO_IN_ACOUSTICS_NONE = 0, + AUDIO_IN_ACOUSTICS_AGC_ENABLE = 0x0001, + AUDIO_IN_ACOUSTICS_AGC_DISABLE = 0, + AUDIO_IN_ACOUSTICS_NS_ENABLE = 0x0002, + AUDIO_IN_ACOUSTICS_NS_DISABLE = 0, + AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE = 0x0004, + AUDIO_IN_ACOUSTICS_TX_DISABLE = 0, +} audio_in_acoustics_t; + +typedef uint32_t audio_devices_t; +/** + * Stub audio output device. Used in policy configuration file on platforms without audio outputs. + * This alias value to AUDIO_DEVICE_OUT_DEFAULT is only used in the audio policy context. + */ +#define AUDIO_DEVICE_OUT_STUB AUDIO_DEVICE_OUT_DEFAULT +/** + * Stub audio input device. Used in policy configuration file on platforms without audio inputs. + * This alias value to AUDIO_DEVICE_IN_DEFAULT is only used in the audio policy context. + */ +#define AUDIO_DEVICE_IN_STUB AUDIO_DEVICE_IN_DEFAULT + +/* Additional information about compressed streams offloaded to + * hardware playback + * The version and size fields must be initialized by the caller by using + * one of the constants defined here. + * Must be aligned to transmit as raw memory through Binder. + */ +typedef struct { + uint16_t version; // version of the info structure + uint16_t size; // total size of the structure including version and size + uint32_t sample_rate; // sample rate in Hz + audio_channel_mask_t channel_mask; // channel mask + audio_format_t format; // audio format + audio_stream_type_t stream_type; // stream type + uint32_t bit_rate; // bit rate in bits per second + int64_t duration_us; // duration in microseconds, -1 if unknown + bool has_video; // true if stream is tied to a video stream + bool is_streaming; // true if streaming, false if local playback + uint32_t bit_width; + uint32_t offload_buffer_size; // offload fragment size + audio_usage_t usage; +} __attribute__((aligned(8))) audio_offload_info_t; + +#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \ + ((((maj) & 0xff) << 8) | ((min) & 0xff)) + +#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1) +#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1 + +static const audio_offload_info_t AUDIO_INFO_INITIALIZER = { + /* .version = */ AUDIO_OFFLOAD_INFO_VERSION_CURRENT, + /* .size = */ sizeof(audio_offload_info_t), + /* .sample_rate = */ 0, + /* .channel_mask = */ 0, + /* .format = */ AUDIO_FORMAT_DEFAULT, + /* .stream_type = */ AUDIO_STREAM_VOICE_CALL, + /* .bit_rate = */ 0, + /* .duration_us = */ 0, + /* .has_video = */ false, + /* .is_streaming = */ false, + /* .bit_width = */ 16, + /* .offload_buffer_size = */ 0, + /* .usage = */ AUDIO_USAGE_UNKNOWN +}; + +/* common audio stream configuration parameters + * You should memset() the entire structure to zero before use to + * ensure forward compatibility + * Must be aligned to transmit as raw memory through Binder. + */ +struct __attribute__((aligned(8))) audio_config { + uint32_t sample_rate; + audio_channel_mask_t channel_mask; + audio_format_t format; + audio_offload_info_t offload_info; + uint32_t frame_count; +}; +typedef struct audio_config audio_config_t; + +static const audio_config_t AUDIO_CONFIG_INITIALIZER = { + /* .sample_rate = */ 0, + /* .channel_mask = */ AUDIO_CHANNEL_NONE, + /* .format = */ AUDIO_FORMAT_DEFAULT, + /* .offload_info = */ { + /* .version = */ AUDIO_OFFLOAD_INFO_VERSION_CURRENT, + /* .size = */ sizeof(audio_offload_info_t), + /* .sample_rate = */ 0, + /* .channel_mask = */ 0, + /* .format = */ AUDIO_FORMAT_DEFAULT, + /* .stream_type = */ AUDIO_STREAM_VOICE_CALL, + /* .bit_rate = */ 0, + /* .duration_us = */ 0, + /* .has_video = */ false, + /* .is_streaming = */ false, + /* .bit_width = */ 16, + /* .offload_buffer_size = */ 0, + /* .usage = */ AUDIO_USAGE_UNKNOWN + }, + /* .frame_count = */ 0, +}; + +struct audio_config_base { + uint32_t sample_rate; + audio_channel_mask_t channel_mask; + audio_format_t format; +}; + +typedef struct audio_config_base audio_config_base_t; + +static const audio_config_base_t AUDIO_CONFIG_BASE_INITIALIZER = { + /* .sample_rate = */ 0, + /* .channel_mask = */ AUDIO_CHANNEL_NONE, + /* .format = */ AUDIO_FORMAT_DEFAULT +}; + +/* audio hw module handle functions or structures referencing a module */ +typedef int audio_module_handle_t; + +/****************************** + * Volume control + *****************************/ + +/** 3 dB headroom are allowed on float samples (3db = 10^(3/20) = 1.412538). +* See: https://developer.android.com/reference/android/media/AudioTrack.html#write(float[], int, int, int) +*/ +#define FLOAT_NOMINAL_RANGE_HEADROOM 1.412538 + +/* If the audio hardware supports gain control on some audio paths, + * the platform can expose them in the audio_policy.conf file. The audio HAL + * will then implement gain control functions that will use the following data + * structures. */ + +typedef uint32_t audio_gain_mode_t; + + +/* An audio_gain struct is a representation of a gain stage. + * A gain stage is always attached to an audio port. */ +struct audio_gain { + audio_gain_mode_t mode; /* e.g. AUDIO_GAIN_MODE_JOINT */ + audio_channel_mask_t channel_mask; /* channels which gain an be controlled. + N/A if AUDIO_GAIN_MODE_CHANNELS is not supported */ + int min_value; /* minimum gain value in millibels */ + int max_value; /* maximum gain value in millibels */ + int default_value; /* default gain value in millibels */ + unsigned int step_value; /* gain step in millibels */ + unsigned int min_ramp_ms; /* minimum ramp duration in ms */ + unsigned int max_ramp_ms; /* maximum ramp duration in ms */ +}; + +/* The gain configuration structure is used to get or set the gain values of a + * given port */ +struct audio_gain_config { + int index; /* index of the corresponding audio_gain in the + audio_port gains[] table */ + audio_gain_mode_t mode; /* mode requested for this command */ + audio_channel_mask_t channel_mask; /* channels which gain value follows. + N/A in joint mode */ + + // note this "8" is not FCC_8, so it won't need to be changed for > 8 channels + int values[sizeof(audio_channel_mask_t) * 8]; /* gain values in millibels + for each channel ordered from LSb to MSb in + channel mask. The number of values is 1 in joint + mode or popcount(channel_mask) */ + unsigned int ramp_duration_ms; /* ramp duration in ms */ +}; + +/****************************** + * Routing control + *****************************/ + +/* Types defined here are used to describe an audio source or sink at internal + * framework interfaces (audio policy, patch panel) or at the audio HAL. + * Sink and sources are grouped in a concept of “audio port” representing an + * audio end point at the edge of the system managed by the module exposing + * the interface. */ + +/* Each port has a unique ID or handle allocated by policy manager */ +typedef int audio_port_handle_t; + +/* the maximum length for the human-readable device name */ +#define AUDIO_PORT_MAX_NAME_LEN 128 + +/* maximum audio device address length */ +#define AUDIO_DEVICE_MAX_ADDRESS_LEN 32 + +/* extension for audio port configuration structure when the audio port is a + * hardware device */ +struct audio_port_config_device_ext { + audio_module_handle_t hw_module; /* module the device is attached to */ + audio_devices_t type; /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */ + char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; /* device address. "" if N/A */ +}; + +/* extension for audio port configuration structure when the audio port is a + * sub mix */ +struct audio_port_config_mix_ext { + audio_module_handle_t hw_module; /* module the stream is attached to */ + audio_io_handle_t handle; /* I/O handle of the input/output stream */ + union { + //TODO: change use case for output streams: use strategy and mixer attributes + audio_stream_type_t stream; + audio_source_t source; + } usecase; +}; + +/* extension for audio port configuration structure when the audio port is an + * audio session */ +struct audio_port_config_session_ext { + audio_session_t session; /* audio session */ +}; + +/* audio port configuration structure used to specify a particular configuration of + * an audio port */ +struct audio_port_config { + audio_port_handle_t id; /* port unique ID */ + audio_port_role_t role; /* sink or source */ + audio_port_type_t type; /* device, mix ... */ + unsigned int config_mask; /* e.g AUDIO_PORT_CONFIG_ALL */ + unsigned int sample_rate; /* sampling rate in Hz */ + audio_channel_mask_t channel_mask; /* channel mask if applicable */ + audio_format_t format; /* format if applicable */ + struct audio_gain_config gain; /* gain to apply if applicable */ + union { + struct audio_port_config_device_ext device; /* device specific info */ + struct audio_port_config_mix_ext mix; /* mix specific info */ + struct audio_port_config_session_ext session; /* session specific info */ + } ext; +}; + + +/* max number of sampling rates in audio port */ +#define AUDIO_PORT_MAX_SAMPLING_RATES 32 +/* max number of channel masks in audio port */ +#define AUDIO_PORT_MAX_CHANNEL_MASKS 32 +/* max number of audio formats in audio port */ +#define AUDIO_PORT_MAX_FORMATS 32 +/* max number of gain controls in audio port */ +#define AUDIO_PORT_MAX_GAINS 16 + +/* extension for audio port structure when the audio port is a hardware device */ +struct audio_port_device_ext { + audio_module_handle_t hw_module; /* module the device is attached to */ + audio_devices_t type; /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */ + char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; +}; + +/* extension for audio port structure when the audio port is a sub mix */ +struct audio_port_mix_ext { + audio_module_handle_t hw_module; /* module the stream is attached to */ + audio_io_handle_t handle; /* I/O handle of the input.output stream */ + audio_mix_latency_class_t latency_class; /* latency class */ + // other attributes: routing strategies +}; + +/* extension for audio port structure when the audio port is an audio session */ +struct audio_port_session_ext { + audio_session_t session; /* audio session */ +}; + +struct audio_port { + audio_port_handle_t id; /* port unique ID */ + audio_port_role_t role; /* sink or source */ + audio_port_type_t type; /* device, mix ... */ + char name[AUDIO_PORT_MAX_NAME_LEN]; + unsigned int num_sample_rates; /* number of sampling rates in following array */ + unsigned int sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES]; + unsigned int num_channel_masks; /* number of channel masks in following array */ + audio_channel_mask_t channel_masks[AUDIO_PORT_MAX_CHANNEL_MASKS]; + unsigned int num_formats; /* number of formats in following array */ + audio_format_t formats[AUDIO_PORT_MAX_FORMATS]; + unsigned int num_gains; /* number of gains in following array */ + struct audio_gain gains[AUDIO_PORT_MAX_GAINS]; + struct audio_port_config active_config; /* current audio port configuration */ + union { + struct audio_port_device_ext device; + struct audio_port_mix_ext mix; + struct audio_port_session_ext session; + } ext; +}; + +/* An audio patch represents a connection between one or more source ports and + * one or more sink ports. Patches are connected and disconnected by audio policy manager or by + * applications via framework APIs. + * Each patch is identified by a handle at the interface used to create that patch. For instance, + * when a patch is created by the audio HAL, the HAL allocates and returns a handle. + * This handle is unique to a given audio HAL hardware module. + * But the same patch receives another system wide unique handle allocated by the framework. + * This unique handle is used for all transactions inside the framework. + */ +typedef int audio_patch_handle_t; + +#define AUDIO_PATCH_PORTS_MAX 16 + +struct audio_patch { + audio_patch_handle_t id; /* patch unique ID */ + unsigned int num_sources; /* number of sources in following array */ + struct audio_port_config sources[AUDIO_PATCH_PORTS_MAX]; + unsigned int num_sinks; /* number of sinks in following array */ + struct audio_port_config sinks[AUDIO_PATCH_PORTS_MAX]; +}; + + + +/* a HW synchronization source returned by the audio HAL */ +typedef uint32_t audio_hw_sync_t; + +/* an invalid HW synchronization source indicating an error */ +#define AUDIO_HW_SYNC_INVALID 0 + +/** + * Mmap buffer descriptor returned by audio_stream->create_mmap_buffer(). + * note\ Used by streams opened in mmap mode. + */ +struct audio_mmap_buffer_info { + void* shared_memory_address; /**< base address of mmap memory buffer. + For use by local process only */ + int32_t shared_memory_fd; /**< FD for mmap memory buffer */ + int32_t buffer_size_frames; /**< total buffer size in frames */ + int32_t burst_size_frames; /**< transfer size granularity in frames */ +}; + +/** + * Mmap buffer read/write position returned by audio_stream->get_mmap_position(). + * note\ Used by streams opened in mmap mode. + */ +struct audio_mmap_position { + int64_t time_nanoseconds; /**< timestamp in ns, CLOCK_MONOTONIC */ + int32_t position_frames; /**< increasing 32 bit frame count reset when stream->stop() + is called */ +}; + +/** Metadata of a record track for an in stream. */ +typedef struct playback_track_metadata { + audio_usage_t usage; + audio_content_type_t content_type; + float gain; // Normalized linear volume. 0=silence, 1=0dbfs... +} playback_track_metadata_t; + +/** Metadata of a playback track for an out stream. */ +typedef struct record_track_metadata { + audio_source_t source; + float gain; // Normalized linear volume. 0=silence, 1=0dbfs... +} record_track_metadata_t; + + +/****************************** + * Helper functions + *****************************/ + +static inline bool audio_is_output_device(audio_devices_t device) +{ + if (((device & AUDIO_DEVICE_BIT_IN) == 0) && + (popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0)) + return true; + else + return false; +} + +static inline bool audio_is_input_device(audio_devices_t device) +{ + if ((device & AUDIO_DEVICE_BIT_IN) != 0) { + device &= ~AUDIO_DEVICE_BIT_IN; + if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0)) + return true; + } + return false; +} + +static inline bool audio_is_output_devices(audio_devices_t device) +{ + return (device & AUDIO_DEVICE_BIT_IN) == 0; +} + +static inline bool audio_is_a2dp_in_device(audio_devices_t device) +{ + if ((device & AUDIO_DEVICE_BIT_IN) != 0) { + device &= ~AUDIO_DEVICE_BIT_IN; + if ((popcount(device) == 1) && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP)) + return true; + } + return false; +} + +static inline bool audio_is_a2dp_out_device(audio_devices_t device) +{ + if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_A2DP)) + return true; + else + return false; +} + +// Deprecated - use audio_is_a2dp_out_device() instead +static inline bool audio_is_a2dp_device(audio_devices_t device) +{ + return audio_is_a2dp_out_device(device); +} + +static inline bool audio_is_bluetooth_sco_device(audio_devices_t device) +{ + if ((device & AUDIO_DEVICE_BIT_IN) == 0) { + if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL_SCO) == 0)) + return true; + } else { + device &= ~AUDIO_DEVICE_BIT_IN; + if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) == 0)) + return true; + } + + return false; +} + +static inline bool audio_is_hearing_aid_out_device(audio_devices_t device) +{ + return device == AUDIO_DEVICE_OUT_HEARING_AID; +} + +static inline bool audio_is_usb_out_device(audio_devices_t device) +{ + return ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB)); +} + +static inline bool audio_is_usb_in_device(audio_devices_t device) +{ + if ((device & AUDIO_DEVICE_BIT_IN) != 0) { + device &= ~AUDIO_DEVICE_BIT_IN; + if (popcount(device) == 1 && (device & AUDIO_DEVICE_IN_ALL_USB) != 0) + return true; + } + return false; +} + +/* OBSOLETE - use audio_is_usb_out_device() instead. */ +static inline bool audio_is_usb_device(audio_devices_t device) +{ + return audio_is_usb_out_device(device); +} + +static inline bool audio_is_remote_submix_device(audio_devices_t device) +{ + if ((audio_is_output_devices(device) && + (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) + || (!audio_is_output_devices(device) && + (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX)) + return true; + else + return false; +} + +/* Returns true if: + * representation is valid, and + * there is at least one channel bit set which _could_ correspond to an input channel, and + * there are no channel bits set which could _not_ correspond to an input channel. + * Otherwise returns false. + */ +static inline bool audio_is_input_channel(audio_channel_mask_t channel) +{ + uint32_t bits = audio_channel_mask_get_bits(channel); + switch (audio_channel_mask_get_representation(channel)) { + case AUDIO_CHANNEL_REPRESENTATION_POSITION: + if (bits & ~AUDIO_CHANNEL_IN_ALL) { + bits = 0; + } + // fall through + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + return bits != 0; + default: + return false; + } +} + +/* Returns true if: + * representation is valid, and + * there is at least one channel bit set which _could_ correspond to an output channel, and + * there are no channel bits set which could _not_ correspond to an output channel. + * Otherwise returns false. + */ +static inline bool audio_is_output_channel(audio_channel_mask_t channel) +{ + uint32_t bits = audio_channel_mask_get_bits(channel); + switch (audio_channel_mask_get_representation(channel)) { + case AUDIO_CHANNEL_REPRESENTATION_POSITION: + if (bits & ~AUDIO_CHANNEL_OUT_ALL) { + bits = 0; + } + // fall through + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + return bits != 0; + default: + return false; + } +} + +/* Returns the number of channels from an input channel mask, + * used in the context of audio input or recording. + * If a channel bit is set which could _not_ correspond to an input channel, + * it is excluded from the count. + * Returns zero if the representation is invalid. + */ +static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel) +{ + uint32_t bits = audio_channel_mask_get_bits(channel); + switch (audio_channel_mask_get_representation(channel)) { + case AUDIO_CHANNEL_REPRESENTATION_POSITION: + // TODO: We can now merge with from_out_mask and remove anding + bits &= AUDIO_CHANNEL_IN_ALL; + // fall through + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + return popcount(bits); + default: + return 0; + } +} + +/* Returns the number of channels from an output channel mask, + * used in the context of audio output or playback. + * If a channel bit is set which could _not_ correspond to an output channel, + * it is excluded from the count. + * Returns zero if the representation is invalid. + */ +static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel) +{ + uint32_t bits = audio_channel_mask_get_bits(channel); + switch (audio_channel_mask_get_representation(channel)) { + case AUDIO_CHANNEL_REPRESENTATION_POSITION: + // TODO: We can now merge with from_in_mask and remove anding + bits &= AUDIO_CHANNEL_OUT_ALL; + // fall through + case AUDIO_CHANNEL_REPRESENTATION_INDEX: + return popcount(bits); + default: + return 0; + } +} + +/* Derive a channel mask for index assignment from a channel count. + * Returns the matching channel mask, + * or AUDIO_CHANNEL_NONE if the channel count is zero, + * or AUDIO_CHANNEL_INVALID if the channel count exceeds AUDIO_CHANNEL_COUNT_MAX. + */ +static inline audio_channel_mask_t audio_channel_mask_for_index_assignment_from_count( + uint32_t channel_count) +{ + if (channel_count == 0) { + return AUDIO_CHANNEL_NONE; + } + if (channel_count > AUDIO_CHANNEL_COUNT_MAX) { + return AUDIO_CHANNEL_INVALID; + } + uint32_t bits = (1 << channel_count) - 1; + return audio_channel_mask_from_representation_and_bits( + AUDIO_CHANNEL_REPRESENTATION_INDEX, bits); +} + +/* Derive an output channel mask for position assignment from a channel count. + * This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel + * cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad, + * and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC + * for continuity with stereo. + * Returns the matching channel mask, + * or AUDIO_CHANNEL_NONE if the channel count is zero, + * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the + * configurations for which a default output channel mask is defined. + */ +static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count) +{ + uint32_t bits; + switch (channel_count) { + case 0: + return AUDIO_CHANNEL_NONE; + case 1: + bits = AUDIO_CHANNEL_OUT_MONO; + break; + case 2: + bits = AUDIO_CHANNEL_OUT_STEREO; + break; + case 3: + bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER; + break; + case 4: // 4.0 + bits = AUDIO_CHANNEL_OUT_QUAD; + break; + case 5: // 5.0 + bits = AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER; + break; + case 6: // 5.1 + bits = AUDIO_CHANNEL_OUT_5POINT1; + break; + case 7: // 6.1 + bits = AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER; + break; + case 8: + bits = AUDIO_CHANNEL_OUT_7POINT1; + break; + // FIXME FCC_8 + default: + return AUDIO_CHANNEL_INVALID; + } + return audio_channel_mask_from_representation_and_bits( + AUDIO_CHANNEL_REPRESENTATION_POSITION, bits); +} + +/* Derive a default input channel mask from a channel count. + * Assumes a position mask for mono and stereo, or an index mask for channel counts > 2. + * Returns the matching channel mask, + * or AUDIO_CHANNEL_NONE if the channel count is zero, + * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the + * configurations for which a default input channel mask is defined. + */ +static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count) +{ + uint32_t bits; + switch (channel_count) { + case 0: + return AUDIO_CHANNEL_NONE; + case 1: + bits = AUDIO_CHANNEL_IN_MONO; + break; + case 2: + bits = AUDIO_CHANNEL_IN_STEREO; + break; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + // FIXME FCC_8 + return audio_channel_mask_for_index_assignment_from_count(channel_count); + default: + return AUDIO_CHANNEL_INVALID; + } + return audio_channel_mask_from_representation_and_bits( + AUDIO_CHANNEL_REPRESENTATION_POSITION, bits); +} + +static inline audio_channel_mask_t audio_channel_mask_in_to_out(audio_channel_mask_t in) +{ + switch (in) { + case AUDIO_CHANNEL_IN_MONO: + return AUDIO_CHANNEL_OUT_MONO; + case AUDIO_CHANNEL_IN_STEREO: + return AUDIO_CHANNEL_OUT_STEREO; + case AUDIO_CHANNEL_IN_5POINT1: + return AUDIO_CHANNEL_OUT_5POINT1; + case AUDIO_CHANNEL_IN_3POINT1POINT2: + return AUDIO_CHANNEL_OUT_3POINT1POINT2; + case AUDIO_CHANNEL_IN_3POINT0POINT2: + return AUDIO_CHANNEL_OUT_3POINT0POINT2; + case AUDIO_CHANNEL_IN_2POINT1POINT2: + return AUDIO_CHANNEL_OUT_2POINT1POINT2; + case AUDIO_CHANNEL_IN_2POINT0POINT2: + return AUDIO_CHANNEL_OUT_2POINT0POINT2; + default: + return AUDIO_CHANNEL_INVALID; + } +} + +static inline bool audio_is_valid_format(audio_format_t format) +{ + switch (format & AUDIO_FORMAT_MAIN_MASK) { + case AUDIO_FORMAT_PCM: + switch (format) { + case AUDIO_FORMAT_PCM_16_BIT: + case AUDIO_FORMAT_PCM_8_BIT: + case AUDIO_FORMAT_PCM_32_BIT: + case AUDIO_FORMAT_PCM_8_24_BIT: + case AUDIO_FORMAT_PCM_FLOAT: + case AUDIO_FORMAT_PCM_24_BIT_PACKED: + return true; + default: + return false; + } + /* not reached */ + case AUDIO_FORMAT_MP3: + case AUDIO_FORMAT_AMR_NB: + case AUDIO_FORMAT_AMR_WB: + case AUDIO_FORMAT_AAC: + case AUDIO_FORMAT_AAC_ADTS: + case AUDIO_FORMAT_HE_AAC_V1: + case AUDIO_FORMAT_HE_AAC_V2: + case AUDIO_FORMAT_AAC_ELD: + case AUDIO_FORMAT_AAC_XHE: + case AUDIO_FORMAT_VORBIS: + case AUDIO_FORMAT_OPUS: + case AUDIO_FORMAT_AC3: + case AUDIO_FORMAT_E_AC3: + case AUDIO_FORMAT_DTS: + case AUDIO_FORMAT_DTS_HD: + case AUDIO_FORMAT_IEC61937: + case AUDIO_FORMAT_DOLBY_TRUEHD: + case AUDIO_FORMAT_QCELP: + case AUDIO_FORMAT_EVRC: + case AUDIO_FORMAT_EVRCB: + case AUDIO_FORMAT_EVRCWB: + case AUDIO_FORMAT_AAC_ADIF: + case AUDIO_FORMAT_AMR_WB_PLUS: + case AUDIO_FORMAT_MP2: + case AUDIO_FORMAT_EVRCNW: + case AUDIO_FORMAT_FLAC: + case AUDIO_FORMAT_ALAC: + case AUDIO_FORMAT_APE: + case AUDIO_FORMAT_WMA: + case AUDIO_FORMAT_WMA_PRO: + case AUDIO_FORMAT_DSD: + case AUDIO_FORMAT_AC4: + case AUDIO_FORMAT_LDAC: + case AUDIO_FORMAT_E_AC3_JOC: + case AUDIO_FORMAT_MAT_1_0: + case AUDIO_FORMAT_MAT_2_0: + case AUDIO_FORMAT_MAT_2_1: + return true; + default: + return false; + } +} + +/** + * Extract the primary format, eg. PCM, AC3, etc. + */ +static inline audio_format_t audio_get_main_format(audio_format_t format) +{ + return (audio_format_t)(format & AUDIO_FORMAT_MAIN_MASK); +} + +/** + * Is the data plain PCM samples that can be scaled and mixed? + */ +static inline bool audio_is_linear_pcm(audio_format_t format) +{ + return (audio_get_main_format(format) == AUDIO_FORMAT_PCM); +} + +/** + * For this format, is the number of PCM audio frames directly proportional + * to the number of data bytes? + * + * In other words, is the format transported as PCM audio samples, + * but not necessarily scalable or mixable. + * This returns true for real PCM, but also for AUDIO_FORMAT_IEC61937, + * which is transported as 16 bit PCM audio, but where the encoded data + * cannot be mixed or scaled. + */ +static inline bool audio_has_proportional_frames(audio_format_t format) +{ + audio_format_t mainFormat = audio_get_main_format(format); + return (mainFormat == AUDIO_FORMAT_PCM + || mainFormat == AUDIO_FORMAT_IEC61937); +} + +static inline size_t audio_bytes_per_sample(audio_format_t format) +{ + size_t size = 0; + + switch (format) { + case AUDIO_FORMAT_PCM_32_BIT: + case AUDIO_FORMAT_PCM_8_24_BIT: + size = sizeof(int32_t); + break; + case AUDIO_FORMAT_PCM_24_BIT_PACKED: + size = sizeof(uint8_t) * 3; + break; + case AUDIO_FORMAT_PCM_16_BIT: + case AUDIO_FORMAT_IEC61937: + size = sizeof(int16_t); + break; + case AUDIO_FORMAT_PCM_8_BIT: + size = sizeof(uint8_t); + break; + case AUDIO_FORMAT_PCM_FLOAT: + size = sizeof(float); + break; + default: + break; + } + return size; +} + +static inline size_t audio_bytes_per_frame(uint32_t channel_count, audio_format_t format) +{ + // cannot overflow for reasonable channel_count + return channel_count * audio_bytes_per_sample(format); +} + +/* converts device address to string sent to audio HAL via set_parameters */ +static inline char *audio_device_address_to_parameter(audio_devices_t device, const char *address) +{ + const size_t kSize = AUDIO_DEVICE_MAX_ADDRESS_LEN + sizeof("a2dp_sink_address="); + char param[kSize]; + + if (device & AUDIO_DEVICE_OUT_ALL_A2DP) + snprintf(param, kSize, "%s=%s", "a2dp_sink_address", address); + else if (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) + snprintf(param, kSize, "%s=%s", "mix", address); + else + snprintf(param, kSize, "%s", address); + + return strdup(param); +} + +static inline bool audio_device_is_digital(audio_devices_t device) { + if ((device & AUDIO_DEVICE_BIT_IN) != 0) { + // input + return (~AUDIO_DEVICE_BIT_IN & device & (AUDIO_DEVICE_IN_ALL_USB | + AUDIO_DEVICE_IN_HDMI | + AUDIO_DEVICE_IN_SPDIF | + AUDIO_DEVICE_IN_IP | + AUDIO_DEVICE_IN_BUS)) != 0; + } else { + // output + return (device & (AUDIO_DEVICE_OUT_ALL_USB | + AUDIO_DEVICE_OUT_HDMI | + AUDIO_DEVICE_OUT_HDMI_ARC | + AUDIO_DEVICE_OUT_SPDIF | + AUDIO_DEVICE_OUT_IP | + AUDIO_DEVICE_OUT_BUS)) != 0; + } +} + +// Unique effect ID (can be generated from the following site: +// http://www.itu.int/ITU-T/asn1/uuid.html) +// This struct is used for effects identification and in soundtrigger. +typedef struct audio_uuid_s { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} audio_uuid_t; + +//TODO: audio_microphone_location_t need to move to HAL v4.0 +typedef enum { + AUDIO_MICROPHONE_LOCATION_UNKNOWN = 0, + AUDIO_MICROPHONE_LOCATION_MAINBODY = 1, + AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE = 2, + AUDIO_MICROPHONE_LOCATION_PERIPHERAL = 3, + AUDIO_MICROPHONE_LOCATION_CNT = 4, +} audio_microphone_location_t; + +//TODO: audio_microphone_directionality_t need to move to HAL v4.0 +typedef enum { + AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN = 0, + AUDIO_MICROPHONE_DIRECTIONALITY_OMNI = 1, + AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL = 2, + AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID = 3, + AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID = 4, + AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID = 5, + AUDIO_MICROPHONE_DIRECTIONALITY_CNT = 6, +} audio_microphone_directionality_t; + +/* A 3D point which could be used to represent geometric location + * or orientation of a microphone. + */ +struct audio_microphone_coordinate { + float x; + float y; + float z; +}; + +/* An number to indicate which group the microphone locate. Main body is + * usually group 0. Developer could use this value to group the microphones + * that locate on the same peripheral or attachments. + */ +typedef int audio_microphone_group_t; + +typedef enum { + AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED = 0, + AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT = 1, + AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED = 2, + AUDIO_MICROPHONE_CHANNEL_MAPPING_CNT = 3, +} audio_microphone_channel_mapping_t; + +/* the maximum length for the microphone id */ +#define AUDIO_MICROPHONE_ID_MAX_LEN 32 +/* max number of frequency responses in a frequency response table */ +#define AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES 256 +/* max number of microphone */ +#define AUDIO_MICROPHONE_MAX_COUNT 32 +/* the value of unknown spl */ +#define AUDIO_MICROPHONE_SPL_UNKNOWN -FLT_MAX +/* the value of unknown sensitivity */ +#define AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN -FLT_MAX +/* the value of unknown coordinate */ +#define AUDIO_MICROPHONE_COORDINATE_UNKNOWN -FLT_MAX +/* the value used as address when the address of bottom microphone is empty */ +#define AUDIO_BOTTOM_MICROPHONE_ADDRESS "bottom" +/* the value used as address when the address of back microphone is empty */ +#define AUDIO_BACK_MICROPHONE_ADDRESS "back" + +struct audio_microphone_characteristic_t { + char device_id[AUDIO_MICROPHONE_ID_MAX_LEN]; + audio_port_handle_t id; + audio_devices_t device; + char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; + audio_microphone_channel_mapping_t channel_mapping[AUDIO_CHANNEL_COUNT_MAX]; + audio_microphone_location_t location; + audio_microphone_group_t group; + unsigned int index_in_the_group; + float sensitivity; + float max_spl; + float min_spl; + audio_microphone_directionality_t directionality; + unsigned int num_frequency_responses; + float frequency_responses[2][AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES]; + struct audio_microphone_coordinate geometric_location; + struct audio_microphone_coordinate orientation; +}; + +__END_DECLS + +/** + * List of known audio HAL modules. This is the base name of the audio HAL + * library composed of the "audio." prefix, one of the base names below and + * a suffix specific to the device. + * e.g: audio.primary.goldfish.so or audio.a2dp.default.so + * + * The same module names are used in audio policy configuration files. + */ + +#define AUDIO_HARDWARE_MODULE_ID_PRIMARY "primary" +#define AUDIO_HARDWARE_MODULE_ID_A2DP "a2dp" +#define AUDIO_HARDWARE_MODULE_ID_USB "usb" +#define AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX "r_submix" +#define AUDIO_HARDWARE_MODULE_ID_CODEC_OFFLOAD "codec_offload" +#define AUDIO_HARDWARE_MODULE_ID_STUB "stub" +#define AUDIO_HARDWARE_MODULE_ID_HEARING_AID "hearing_aid" + +/** + * Multi-Stream Decoder (MSD) HAL service name. MSD HAL is used to mix + * encoded streams together with PCM streams, producing re-encoded + * streams or PCM streams. + * + * The service must register itself using this name, and audioserver + * tries to instantiate a device factory using this name as well. + * Note that the HIDL implementation library file name *must* have the + * suffix "msd" in order to be picked up by HIDL that is: + * + * android.hardware.audio@x.x-implmsd.so + */ +#define AUDIO_HAL_SERVICE_NAME_MSD "msd" + +/** + * Parameter definitions. + * Note that in the framework code it's recommended to use AudioParameter.h + * instead of these preprocessor defines, and for sure avoid just copying + * the constant values. + */ + +#define AUDIO_PARAMETER_VALUE_ON "on" +#define AUDIO_PARAMETER_VALUE_OFF "off" + +/** + * audio device parameters + */ + +/* BT SCO Noise Reduction + Echo Cancellation parameters */ +#define AUDIO_PARAMETER_KEY_BT_NREC "bt_headset_nrec" + +/* Get a new HW synchronization source identifier. + * Return a valid source (positive integer) or AUDIO_HW_SYNC_INVALID if an error occurs + * or no HW sync is available. */ +#define AUDIO_PARAMETER_HW_AV_SYNC "hw_av_sync" + +/* Screen state */ +#define AUDIO_PARAMETER_KEY_SCREEN_STATE "screen_state" + +/** + * audio stream parameters + */ + +#define AUDIO_PARAMETER_STREAM_ROUTING "routing" /* audio_devices_t */ +#define AUDIO_PARAMETER_STREAM_FORMAT "format" /* audio_format_t */ +#define AUDIO_PARAMETER_STREAM_CHANNELS "channels" /* audio_channel_mask_t */ +#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count" /* size_t */ +#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" /* audio_source_t */ +#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */ + +/* Request the presentation id to be decoded by a next gen audio decoder */ +#define AUDIO_PARAMETER_STREAM_PRESENTATION_ID "presentation_id" /* int32_t */ + +/* Request the program id to be decoded by a next gen audio decoder */ +#define AUDIO_PARAMETER_STREAM_PROGRAM_ID "program_id" /* int32_t */ + +#define AUDIO_PARAMETER_DEVICE_CONNECT "connect" /* audio_devices_t */ +#define AUDIO_PARAMETER_DEVICE_DISCONNECT "disconnect" /* audio_devices_t */ + +/* Enable mono audio playback if 1, else should be 0. */ +#define AUDIO_PARAMETER_MONO_OUTPUT "mono_output" + +/* Set the HW synchronization source for an output stream. */ +#define AUDIO_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync" + +/* Query supported formats. The response is a '|' separated list of strings from + * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */ +#define AUDIO_PARAMETER_STREAM_SUP_FORMATS "sup_formats" +/* Query supported channel masks. The response is a '|' separated list of strings from + * audio_channel_mask_t enum e.g: "sup_channels=AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_MONO" */ +#define AUDIO_PARAMETER_STREAM_SUP_CHANNELS "sup_channels" +/* Query supported sampling rates. The response is a '|' separated list of integer values e.g: + * "sup_sampling_rates=44100|48000" */ +#define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates" + +#define AUDIO_PARAMETER_VALUE_LIST_SEPARATOR "|" + +/* Reconfigure offloaded A2DP codec */ +#define AUDIO_PARAMETER_RECONFIG_A2DP "reconfigA2dp" +/* Query if HwModule supports reconfiguration of offloaded A2DP codec */ +#define AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED "isReconfigA2dpSupported" + +/** + * audio codec parameters + */ + +#define AUDIO_OFFLOAD_CODEC_PARAMS "music_offload_codec_param" +#define AUDIO_OFFLOAD_CODEC_BIT_PER_SAMPLE "music_offload_bit_per_sample" +#define AUDIO_OFFLOAD_CODEC_BIT_RATE "music_offload_bit_rate" +#define AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE "music_offload_avg_bit_rate" +#define AUDIO_OFFLOAD_CODEC_ID "music_offload_codec_id" +#define AUDIO_OFFLOAD_CODEC_BLOCK_ALIGN "music_offload_block_align" +#define AUDIO_OFFLOAD_CODEC_SAMPLE_RATE "music_offload_sample_rate" +#define AUDIO_OFFLOAD_CODEC_ENCODE_OPTION "music_offload_encode_option" +#define AUDIO_OFFLOAD_CODEC_NUM_CHANNEL "music_offload_num_channels" +#define AUDIO_OFFLOAD_CODEC_DOWN_SAMPLING "music_offload_down_sampling" +#define AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES "delay_samples" +#define AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES "padding_samples" + +#endif // ANDROID_AUDIO_CORE_H diff --git a/include/hardware/system/audio_policy.h b/include/hardware/system/audio_policy.h new file mode 100644 index 0000000..2d69507 --- /dev/null +++ b/include/hardware/system/audio_policy.h @@ -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. + */ + + +#ifndef ANDROID_AUDIO_POLICY_CORE_H +#define ANDROID_AUDIO_POLICY_CORE_H + +#include +#include +#include + +#include "cutils/bitops.h" + +__BEGIN_DECLS + +/* The enums were moved here mostly from + * frameworks/base/include/media/AudioSystem.h + */ + +/* device categories used for audio_policy->set_force_use() */ +typedef enum +{ + AUDIO_POLICY_FORCE_NONE, + AUDIO_POLICY_FORCE_SPEAKER, + AUDIO_POLICY_FORCE_HEADPHONES, + AUDIO_POLICY_FORCE_BT_SCO, + AUDIO_POLICY_FORCE_BT_A2DP, + AUDIO_POLICY_FORCE_WIRED_ACCESSORY, + AUDIO_POLICY_FORCE_BT_CAR_DOCK, + AUDIO_POLICY_FORCE_BT_DESK_DOCK, + AUDIO_POLICY_FORCE_ANALOG_DOCK, + AUDIO_POLICY_FORCE_DIGITAL_DOCK, + AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */ + AUDIO_POLICY_FORCE_SYSTEM_ENFORCED, + AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED, + + AUDIO_POLICY_FORCE_CFG_CNT, + AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1, + + AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE, +} audio_policy_forced_cfg_t; + +/* usages used for audio_policy->set_force_use() */ +typedef enum +{ + AUDIO_POLICY_FORCE_FOR_COMMUNICATION, + AUDIO_POLICY_FORCE_FOR_MEDIA, + AUDIO_POLICY_FORCE_FOR_RECORD, + AUDIO_POLICY_FORCE_FOR_DOCK, + AUDIO_POLICY_FORCE_FOR_SYSTEM, + AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO, + + AUDIO_POLICY_FORCE_USE_CNT, + AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1, +} audio_policy_force_use_t; + +/* device connection states used for audio_policy->set_device_connection_state() + */ +typedef enum +{ + AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, + AUDIO_POLICY_DEVICE_STATE_AVAILABLE, + + AUDIO_POLICY_DEVICE_STATE_CNT, + AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1, +} audio_policy_dev_state_t; + +typedef enum +{ + /* Used to generate a tone to notify the user of a + * notification/alarm/ringtone while they are in a call. */ + AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION = 0, + + AUDIO_POLICY_TONE_CNT, + AUDIO_POLICY_TONE_MAX = AUDIO_POLICY_TONE_CNT - 1, +} audio_policy_tone_t; + + +static inline bool audio_is_low_visibility(audio_stream_type_t stream) +{ + switch (stream) + { + case AUDIO_STREAM_SYSTEM: + case AUDIO_STREAM_NOTIFICATION: + case AUDIO_STREAM_RING: + return true; + default: + return false; + } +} + + +__END_DECLS + +#endif // ANDROID_AUDIO_POLICY_CORE_H diff --git a/include/hardware/system/cutils/atomic.h b/include/hardware/system/cutils/atomic.h new file mode 100644 index 0000000..4587835 --- /dev/null +++ b/include/hardware/system/cutils/atomic.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2007 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_CUTILS_ATOMIC_H +#define ANDROID_CUTILS_ATOMIC_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A handful of basic atomic operations. + * THESE ARE HERE FOR LEGACY REASONS ONLY. AVOID. + * + * PREFERRED ALTERNATIVES: + * - Use C++/C/pthread locks/mutexes whenever there is not a + * convincing reason to do otherwise. Note that very clever and + * complicated, but correct, lock-free code is often slower than + * using locks, especially where nontrivial data structures + * are involved. + * - C11 stdatomic.h. + * - Where supported, C++11 std::atomic . + * + * PLEASE STOP READING HERE UNLESS YOU ARE TRYING TO UNDERSTAND + * OR UPDATE OLD CODE. + * + * The "acquire" and "release" terms can be defined intuitively in terms + * of the placement of memory barriers in a simple lock implementation: + * - wait until compare-and-swap(lock-is-free --> lock-is-held) succeeds + * - barrier + * - [do work] + * - barrier + * - store(lock-is-free) + * In very crude terms, the initial (acquire) barrier prevents any of the + * "work" from happening before the lock is held, and the later (release) + * barrier ensures that all of the work happens before the lock is released. + * (Think of cached writes, cache read-ahead, and instruction reordering + * around the CAS and store instructions.) + * + * The barriers must apply to both the compiler and the CPU. Note it is + * legal for instructions that occur before an "acquire" barrier to be + * moved down below it, and for instructions that occur after a "release" + * barrier to be moved up above it. + * + * The ARM-driven implementation we use here is short on subtlety, + * and actually requests a full barrier from the compiler and the CPU. + * The only difference between acquire and release is in whether they + * are issued before or after the atomic operation with which they + * are associated. To ease the transition to C/C++ atomic intrinsics, + * you should not rely on this, and instead assume that only the minimal + * acquire/release protection is provided. + * + * NOTE: all int32_t* values are expected to be aligned on 32-bit boundaries. + * If they are not, atomicity is not guaranteed. + */ + +/* + * Basic arithmetic and bitwise operations. These all provide a + * barrier with "release" ordering, and return the previous value. + * + * These have the same characteristics (e.g. what happens on overflow) + * as the equivalent non-atomic C operations. + */ +int32_t android_atomic_inc(volatile int32_t* addr); +int32_t android_atomic_dec(volatile int32_t* addr); +int32_t android_atomic_add(int32_t value, volatile int32_t* addr); +int32_t android_atomic_and(int32_t value, volatile int32_t* addr); +int32_t android_atomic_or(int32_t value, volatile int32_t* addr); + +/* + * Perform an atomic load with "acquire" or "release" ordering. + * + * Note that the notion of a "release" ordering for a load does not + * really fit into the C11 or C++11 memory model. The extra ordering + * is normally observable only by code using memory_order_relaxed + * atomics, or data races. In the rare cases in which such ordering + * is called for, use memory_order_relaxed atomics and a leading + * atomic_thread_fence (typically with memory_order_acquire, + * not memory_order_release!) instead. If you do not understand + * this comment, you are in the vast majority, and should not be + * using release loads or replacing them with anything other than + * locks or default sequentially consistent atomics. + * + * This is only necessary if you need the memory barrier. A 32-bit read + * from a 32-bit aligned address is atomic on all supported platforms. + */ +int32_t android_atomic_acquire_load(volatile const int32_t* addr); +int32_t android_atomic_release_load(volatile const int32_t* addr); + +/* + * Perform an atomic store with "acquire" or "release" ordering. + * + * Note that the notion of a "acquire" ordering for a store does not + * really fit into the C11 or C++11 memory model. The extra ordering + * is normally observable only by code using memory_order_relaxed + * atomics, or data races. In the rare cases in which such ordering + * is called for, use memory_order_relaxed atomics and a trailing + * atomic_thread_fence (typically with memory_order_release, + * not memory_order_acquire!) instead. + * + * This is only necessary if you need the memory barrier. A 32-bit write + * to a 32-bit aligned address is atomic on all supported platforms. + */ +void android_atomic_acquire_store(int32_t value, volatile int32_t* addr); +void android_atomic_release_store(int32_t value, volatile int32_t* addr); + +/* + * Compare-and-set operation with "acquire" or "release" ordering. + * + * This returns zero if the new value was successfully stored, which will + * only happen when *addr == oldvalue. + * + * (The return value is inverted from implementations on other platforms, + * but matches the ARM ldrex/strex result.) + * + * Implementations that use the release CAS in a loop may be less efficient + * than possible, because we re-issue the memory barrier on each iteration. + */ +int android_atomic_acquire_cas(int32_t oldvalue, int32_t newvalue, + volatile int32_t* addr); +int android_atomic_release_cas(int32_t oldvalue, int32_t newvalue, + volatile int32_t* addr); + +/* + * Aliases for code using an older version of this header. These are now + * deprecated and should not be used. The definitions will be removed + * in a future release. + */ +#define android_atomic_write android_atomic_release_store +#define android_atomic_cmpxchg android_atomic_release_cas + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // ANDROID_CUTILS_ATOMIC_H diff --git a/include/hardware/system/cutils/bitops.h b/include/hardware/system/cutils/bitops.h new file mode 100644 index 0000000..bdd989f --- /dev/null +++ b/include/hardware/system/cutils/bitops.h @@ -0,0 +1,120 @@ +/* + * 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 __CUTILS_BITOPS_H +#define __CUTILS_BITOPS_H + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * Bitmask Operations + * + * Note this doesn't provide any locking/exclusion, and isn't atomic. + * Additionally no bounds checking is done on the bitmask array. + * + * Example: + * + * int num_resources; + * unsigned int resource_bits[BITS_TO_WORDS(num_resources)]; + * bitmask_init(resource_bits, num_resources); + * ... + * int bit = bitmask_ffz(resource_bits, num_resources); + * bitmask_set(resource_bits, bit); + * ... + * if (bitmask_test(resource_bits, bit)) { ... } + * ... + * bitmask_clear(resource_bits, bit); + * + */ + +#define BITS_PER_WORD (sizeof(unsigned int) * 8) +#define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD) +#define BIT_IN_WORD(x) ((x) % BITS_PER_WORD) +#define BIT_WORD(x) ((x) / BITS_PER_WORD) +#define BIT_MASK(x) (1 << BIT_IN_WORD(x)) + +static inline void bitmask_init(unsigned int *bitmask, int num_bits) +{ + memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int)); +} + +static inline int bitmask_ffz(unsigned int *bitmask, int num_bits) +{ + int bit, result; + size_t i; + for (i = 0; i < BITS_TO_WORDS(num_bits); i++) + { + bit = ffs(~bitmask[i]); + if (bit) + { + // ffs is 1-indexed, return 0-indexed result + bit--; + result = BITS_PER_WORD * i + bit; + if (result >= num_bits) + return -1; + return result; + } + } + return -1; +} + +static inline int bitmask_weight(unsigned int *bitmask, int num_bits) +{ + size_t i; + int weight = 0; + for (i = 0; i < BITS_TO_WORDS(num_bits); i++) + weight += __builtin_popcount(bitmask[i]); + return weight; +} + +static inline void bitmask_set(unsigned int *bitmask, int bit) +{ + bitmask[BIT_WORD(bit)] |= BIT_MASK(bit); +} + +static inline void bitmask_clear(unsigned int *bitmask, int bit) +{ + bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit); +} + +static inline bool bitmask_test(unsigned int *bitmask, int bit) +{ + return bitmask[BIT_WORD(bit)] & BIT_MASK(bit); +} + +static inline int popcount(unsigned int x) +{ + return __builtin_popcount(x); +} + +static inline int popcountl(unsigned long x) +{ + return __builtin_popcountl(x); +} + +static inline int popcountll(unsigned long long x) +{ + return __builtin_popcountll(x); +} + +__END_DECLS + +#endif /* __CUTILS_BITOPS_H */ diff --git a/include/hardware/system/cutils/native_handle.h b/include/hardware/system/cutils/native_handle.h new file mode 100644 index 0000000..9c424c5 --- /dev/null +++ b/include/hardware/system/cutils/native_handle.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 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 NATIVE_HANDLE_H_ +#define NATIVE_HANDLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct native_handle +{ + int version; /* sizeof(native_handle_t) */ + int numFds; /* number of file-descriptors at &data[0] */ + int numInts; /* number of ints at &data[numFds] */ + int data[0]; /* numFds + numInts ints */ +} native_handle_t; + +/* + * native_handle_close + * + * closes the file descriptors contained in this native_handle_t + * + * return 0 on success, or a negative error code on failure + * + */ +int native_handle_close(const native_handle_t* h); + + +/* + * native_handle_create + * + * creates a native_handle_t and initializes it. must be destroyed with + * native_handle_delete(). + * + */ +native_handle_t* native_handle_create(int numFds, int numInts); + +/* + * native_handle_delete + * + * frees a native_handle_t allocated with native_handle_create(). + * This ONLY frees the memory allocated for the native_handle_t, but doesn't + * close the file descriptors; which can be achieved with native_handle_close(). + * + * return 0 on success, or a negative error code on failure + * + */ +int native_handle_delete(native_handle_t* h); + + +#ifdef __cplusplus +} +#endif + +#endif /* NATIVE_HANDLE_H_ */ diff --git a/src/Effect.cpp b/src/Effect.cpp new file mode 100644 index 0000000..13d69f9 --- /dev/null +++ b/src/Effect.cpp @@ -0,0 +1,116 @@ +// +// Created by mart on 7/25/21. +// + +#include +#include "Effect.h" +#include "constants.h" + +Effect::Effect() { + this->enabled = false; + this->configureOk = false; + this->sampleRate = DEFAULT_SAMPLERATE; + + memset(&this->config, 0, sizeof(effect_config_t)); + + this->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; + this->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; // TODO: Try to use PCM_FLOAT instead + this->config.inputCfg.samplingRate = DEFAULT_SAMPLERATE; + this->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; + this->config.inputCfg.mask = AUDIO_PORT_CONFIG_ALL; + + this->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE; + this->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; // TODO: Try to use PCM_FLOAT instead + this->config.outputCfg.samplingRate = DEFAULT_SAMPLERATE; + this->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; + this->config.outputCfg.mask = AUDIO_PORT_CONFIG_ALL; + + this->buffer = nullptr; + this->bufferSize = 0; + this->instance = nullptr; +} + +Effect::~Effect() { + if (this->buffer != nullptr) { + free(this->buffer); + } +} + +int32_t Effect::process(audio_buffer_s *in, audio_buffer_s *out) { + // TODO + return -1; +} + +int32_t Effect::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) { + switch(cmdCode) { + case EFFECT_CMD_INIT: + case EFFECT_CMD_SET_CONFIG: + case EFFECT_CMD_SET_PARAM: + case EFFECT_CMD_SET_PARAM_COMMIT: + *((int*)pReplyData) = 0; + case EFFECT_CMD_RESET: + case EFFECT_CMD_SET_PARAM_DEFERRED: + case EFFECT_CMD_SET_DEVICE: + case EFFECT_CMD_SET_VOLUME: + case EFFECT_CMD_SET_AUDIO_MODE: + case EFFECT_CMD_SET_INPUT_DEVICE: + case EFFECT_CMD_SET_AUDIO_SOURCE: + break; + case EFFECT_CMD_SET_CONFIG_REVERSE: + *((int*)pReplyData) = -EINVAL; + default: + return -EINVAL; + case EFFECT_CMD_GET_CONFIG: + memcpy(pReplyData, &this->config, sizeof(effect_config_t)); + break; + case EFFECT_CMD_OFFLOAD: + // TODO: Figure this out + return -1; + } + return 0; +} + +#define ERROR this->configureOk = false;\ +return -EINVAL; + +int32_t Effect::configure(effect_config_t *newConfig) { + if (newConfig->inputCfg.samplingRate != newConfig->outputCfg.samplingRate) { + // __android_log_print(4,"ViPER4Android_v2","ViPER4Android disabled, reason [in.SR = %d, out.SR = %d]",inSamplingRate,outSamplingRate); + ERROR + } + + if (newConfig->inputCfg.samplingRate > 48000) { + // __android_log_print(4,"ViPER4Android_v2","ViPER4Android disabled, reason [SR out of range]"); + ERROR + } + + if (newConfig->inputCfg.channels != newConfig->outputCfg.channels) { + // __android_log_print(4,"ViPER4Android_v2","ViPER4Android disabled, reason [in.CH = %d, out.CH = %d]",inChannels,outChannels); + ERROR + } + + if (newConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) { + // __android_log_print(4,"ViPER4Android_v2","ViPER4Android disabled, reason [CH != 2]"); + ERROR + } + +// if (((inFormat & 0x80000) != 0) && ((outFormat & 0x80000) != 0)) { +// if ((inFormat & 0xfd) != 1) { +// __android_log_print(4,"ViPER4Android_v2","ViPER4Android disabled, reason [in.FMT = %d]"); +// __android_log_print(4,"ViPER4Android_v2","We only accept s16 and fixed.31 format"); +// this->configureOk = false; +// return 0xffffffea; +// } +// if ((outFormat & 0xfd) != 1) { +// __android_log_print(4,"ViPER4Android_v2","ViPER4Android disabled, reason [out.FMT = %d]"); +// __android_log_print(4,"ViPER4Android_v2","We only accept s16 and fixed.31 format"); +// this->configureOk = false; +// return 0xffffffea; +// } +// } + + memcpy(&this->config, newConfig, sizeof(effect_config_t)); + this->configureOk = true; + return 0; +} + diff --git a/src/Effect.h b/src/Effect.h new file mode 100644 index 0000000..6ba0491 --- /dev/null +++ b/src/Effect.h @@ -0,0 +1,29 @@ +// +// Created by mart on 7/25/21. +// + +#pragma once + +#include +#include + +class Effect { +public: + Effect(); + ~Effect(); + + virtual int32_t command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize, void* pReplyData); + int32_t process(audio_buffer_s *in, audio_buffer_s *out); + int32_t configure(effect_config_t* config); + + bool enabled; + bool configureOk; + uint32_t sampleRate; + effect_config_t config{}; + // Misc data here? + + // TODO: Figure out what buffer is used for + float* buffer; + uint32_t bufferSize; + void* instance; // type: ProcessUnit_FX +}; diff --git a/src/ProcessUnit_FX.cpp b/src/ProcessUnit_FX.cpp new file mode 100644 index 0000000..9c172df --- /dev/null +++ b/src/ProcessUnit_FX.cpp @@ -0,0 +1,32 @@ +// +// Created by mart on 7/25/21. +// + +#include "ProcessUnit_FX.h" +#include "Effect.h" + +ProcessUnit_FX::ProcessUnit_FX() { + +} + +ProcessUnit_FX::~ProcessUnit_FX() { + +} + +int32_t ProcessUnit_FX::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) { + // TODO + return -1; +} + +void ProcessUnit_FX::processBuffer(float *buffer, int frameSize) { + // TODO +} + +void ProcessUnit_FX::DispatchCommand(int param_1, int param_2, int param_3, int param_4, int param_5, int param_6, + int param_7) { + // TODO +} + +void ProcessUnit_FX::ResetAllEffects() { + // TODO +} diff --git a/src/ProcessUnit_FX.h b/src/ProcessUnit_FX.h new file mode 100644 index 0000000..bab806b --- /dev/null +++ b/src/ProcessUnit_FX.h @@ -0,0 +1,20 @@ +// +// Created by mart on 7/25/21. +// +#pragma once + +#include "Effect.h" + +class ProcessUnit_FX : public Effect { +public: + ProcessUnit_FX(); + ~ProcessUnit_FX(); + + int32_t command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize, void* pReplyData) override; + + void processBuffer(float* buffer, int frameSize); + + // TODO: Parameter types/names + void DispatchCommand(int param_1, int param_2,int param_3, int param_4,int param_5, int param_6,int param_7); + void ResetAllEffects(); +}; diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 0000000..7a6aec6 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,7 @@ +// +// Created by mart on 7/25/21. +// + +#pragma once + +#define DEFAULT_SAMPLERATE 44100 diff --git a/src/effects/Cure.cpp b/src/effects/Cure.cpp new file mode 100644 index 0000000..8a3953a --- /dev/null +++ b/src/effects/Cure.cpp @@ -0,0 +1,27 @@ +// +// Created by mart on 7/26/21. +// + +#include "Cure.h" + +Cure::Cure() { + this->enabled = false; + Reset(); +} + +void Cure::Process(float *buffer, uint32_t size) { + if (this->enabled) { + Crossfeed::ProcessFrames(buffer, size); + this->pass.ProcessFrames(buffer, size); + } +} + +void Cure::Reset() { + Crossfeed::Reset(); + this->pass.Reset(); +} + +void Cure::SetSamplingRate(uint32_t samplerate) { + Crossfeed::SetSamplingRate(samplerate); + this->pass.SetSamplingRate(samplerate); +} diff --git a/src/effects/Cure.h b/src/effects/Cure.h new file mode 100644 index 0000000..65f8936 --- /dev/null +++ b/src/effects/Cure.h @@ -0,0 +1,21 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + + +#include "../utils/Crossfeed.h" +#include "../utils/PassFilter.h" + +class Cure : public Crossfeed { +public: + Cure(); + + void Process(float* buffer, uint32_t size); + void Reset(); + void SetSamplingRate(uint32_t samplerate); + + PassFilter pass; + bool enabled; +}; diff --git a/src/effects/TubeSimulator.cpp b/src/effects/TubeSimulator.cpp new file mode 100644 index 0000000..85dd1ea --- /dev/null +++ b/src/effects/TubeSimulator.cpp @@ -0,0 +1,28 @@ +// +// Created by mart on 7/26/21. +// + +#include "TubeSimulator.h" + +TubeSimulator::TubeSimulator() { + this->acc[0] = 0.f; + this->acc[1] = 0.f; + this->enabled = false; +} + +void TubeSimulator::Reset() { + this->acc[0] = 0.f; + this->acc[1] = 0.f; + this->enabled = false; +} + +void TubeSimulator::TubeProcess(float *buffer, uint32_t size) { + if (this->enabled && size > 0) { + for (int x = 0; x < size; x++) { + this->acc[0] = (this->acc[0] + buffer[2*x]) / 2.f; + this->acc[1] = (this->acc[1] + buffer[2*x+1]) / 2.f; + buffer[2*x] = this->acc[0]; + buffer[2*x+1] = this->acc[1]; + } + } +} \ No newline at end of file diff --git a/src/effects/TubeSimulator.h b/src/effects/TubeSimulator.h new file mode 100644 index 0000000..92d444f --- /dev/null +++ b/src/effects/TubeSimulator.h @@ -0,0 +1,19 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + +#include + +class TubeSimulator { +public: + TubeSimulator(); + + void Reset(); + void TubeProcess(float* buffer, uint32_t size); + + float acc[2]; + bool enabled; +}; + diff --git a/src/utils/CAllpassFilter.cpp b/src/utils/CAllpassFilter.cpp new file mode 100644 index 0000000..f33ed7f --- /dev/null +++ b/src/utils/CAllpassFilter.cpp @@ -0,0 +1,40 @@ +// +// Created by mart on 7/26/21. +// + +#include +#include "CAllpassFilter.h" + +CAllpassFilter::CAllpassFilter() { + this->buffer = nullptr; + this->bufidx = 0; + this->bufsize = 0; + this->feedback = 0; +} + +void CAllpassFilter::Mute() { + memset(this->buffer, 0, this->bufsize * sizeof(float)) +} + +float CAllpassFilter::Process(float sample) { + float outSample = this->buffer[this->bufidx]; + this->buffer[this->bufidx] = sample + (outSample * this->feedback); + this->bufidx++; + if (this->bufidx >= this->bufsize) { + this->bufidx = 0; + } + return outSample - sample; +} + +float CAllpassFilter::GetFeedback() { + return this->feedback; +} + +void CAllpassFilter::SetBuffer(float *buffer, uint32_t size) { + this->buffer = buffer; + this->bufsize = size; +} + +void CAllpassFilter::SetFeedback(float feedback) { + this->feedback = feedback; +} diff --git a/src/utils/CAllpassFilter.h b/src/utils/CAllpassFilter.h new file mode 100644 index 0000000..d5488b1 --- /dev/null +++ b/src/utils/CAllpassFilter.h @@ -0,0 +1,24 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + +#include + +class CAllpassFilter { +public: + CAllpassFilter(); + + void Mute(); + float Process(float sample); + + float GetFeedback(); + void SetBuffer(float* buffer, uint32_t size); + void SetFeedback(float feedback); + + float* buffer; + uint32_t bufidx; + uint32_t bufsize; + float feedback; +}; diff --git a/src/utils/Crossfeed.cpp b/src/utils/Crossfeed.cpp new file mode 100644 index 0000000..cb46477 --- /dev/null +++ b/src/utils/Crossfeed.cpp @@ -0,0 +1,110 @@ +// +// Created by mart on 7/26/21. +// + +#include +#include +#include "Crossfeed.h" +#include "../constants.h" + +// Basically Bauer-to-Stereophonic Binaural filter +// See: http://bs2b.sourceforge.net/ +Crossfeed::Crossfeed() { + this->a0_lo = 0.f; + this->b1_lo = 0.f; + this->a0_hi = 0.f; + this->a1_hi = 0.f; + this->b1_hi = 0.f; + this->gain = 0.f; + memset(&this->lfs, 0, 6*sizeof(float)); + this->samplerate = DEFAULT_SAMPLERATE; + this->preset.cutoff = 700; + this->preset.feedback = 45; +} + +void Crossfeed::Reset() { + uint16_t cutoff = this->preset.cutoff; + uint16_t level = this->preset.feedback; + + level /= 10.0; + + double GB_lo = level * -5.0 / 6.0 - 3.0; + double GB_hi = level / 6.0 - 3.0; + + double G_lo = pow( 10, GB_lo / 20.0 ); + double G_hi = 1.0 - pow( 10, GB_hi / 20.0 ); + double Fc_hi = cutoff * pow( 2.0, ( GB_lo - 20.0 * log10( G_hi ) ) / 12.0 ); + + double x = exp( -2.0 * M_PI * cutoff / this->samplerate ); + this->b1_lo = (float)x; + this->a0_lo = (float)(G_lo * ( 1.0 - x )); + + x = exp( -2.0 * M_PI * Fc_hi / this->samplerate ); + this->b1_hi = (float)x; + this->a0_hi = (float)(1.0 - G_hi * ( 1.0 - x )); + this->a1_hi = (float)-x; + + this->gain = (float)(1.0 / ( 1.0 - G_hi + G_lo )); + memset(&this->lfs, 0, 6*sizeof(float)); +} + +void Crossfeed::ProcessFrames(float* buffer, uint32_t size) { + for (int x = 0; x < size; x+=2) { + FilterSample(&buffer[x]) + } +} + +#define lo_filter(in, out_1) (this->a0_lo * (in) + this->b1_lo * (out_1)) +#define hi_filter(in, in_1, out_1) (this->a0_hi * (in) + this->a1_hi * (in_1) + this->b1_hi * (out_1)) +void Crossfeed::FilterSample(float *sample) { + this->lfs.lo[0] = lo_filter(sample[0], this->lfs.lo[0]); + this->lfs.lo[1] = lo_filter(sample[1], this->lfs.lo[1]); + + this->lfs.hi[0] = hi_filter(sample[0], this->lfs.asis[0], this->lfs.hi[0]); + this->lfs.hi[1] = hi_filter(sample[1], this->lfs.asis[1], this->lfs.hi[1]); + this->lfs.asis[0] = sample[0]; + this->lfs.asis[1] = sample[1]; + + sample[0] = (this->lfs.hi[0] + this->lfs.lo[1]) * this->gain; + sample[1] = (this->lfs.hi[1] + this->lfs.lo[0]) * this->gain; +} + +uint16_t Crossfeed::GetCutoff() { + return this->preset.cutoff; +} + +float Crossfeed::GetFeedback() { + return (float)this->preset.feedback / 10.f; +} + +float Crossfeed::GetLevelDelay() { + if (this->preset.cutoff <= 1800) { + return (18700.f / (float)this->preset.cutoff) * 10.f; + } else { + return 0.f; + } +} + +preset_t Crossfeed::GetPreset() { + return this->preset; +} + +void Crossfeed::SetCutoff(uint16_t cutoff) { + this->preset.cutoff = cutoff; + Reset(); +} + +void Crossfeed::SetFeedback(float feedback) { + this->preset.feedback = (uint16_t)(feedback * 10); + Reset(); +} + +void Crossfeed::SetPreset(preset_t preset) { + this->preset = preset; + Reset(); +} + +void Crossfeed::SetSamplingRate(uint32_t samplerate) { + this->samplerate = samplerate; + Reset(); +} diff --git a/src/utils/Crossfeed.h b/src/utils/Crossfeed.h new file mode 100644 index 0000000..665b27b --- /dev/null +++ b/src/utils/Crossfeed.h @@ -0,0 +1,40 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + + +#include + +typedef struct { + uint16_t cutoff; + uint16_t feedback; +} preset_t; + +class Crossfeed { +public: + Crossfeed(); + + void Reset(); + void ProcessFrames(float* buffer, uint32_t size); + void FilterSample(float* sample); + + uint16_t GetCutoff(); + float GetFeedback(); + float GetLevelDelay(); + preset_t GetPreset(); + void SetCutoff(uint16_t cutoff); + void SetFeedback(float feedback); + void SetPreset(preset_t preset); + void SetSamplingRate(uint32_t samplerate); + + uint32_t samplerate; + float a0_lo, b1_lo; + float a0_hi, b1_hi, a1_hi; + float gain; + struct { + float asis[2], lo[2], hi[2]; + } lfs; + preset_t preset; +}; diff --git a/src/utils/FixedBiquad.cpp b/src/utils/FixedBiquad.cpp new file mode 100644 index 0000000..7ce6351 --- /dev/null +++ b/src/utils/FixedBiquad.cpp @@ -0,0 +1,83 @@ +// +// Created by mart on 7/26/21. +// + +#include +#include "FixedBiquad.h" + +FixedBiquad::FixedBiquad() { + Reset(); + SetCoeffs(1.f, 0.f, 0.f, 1.f, 0.f, 0.f); +} + +float FixedBiquad::ProcessSample(float sample) { + float out = sample * this->b0 + this->x_1 * this->b1 + this->x_2 * this->b2 + this->y_1 * this->a1 + this->y_2 * this->a2; + this->y_2 = this->y_1; + this->y_1 = out; + this->x_2 = this->x_1; + this->x_1 = sample; + return out; +} + +void FixedBiquad::Reset() { + this->y_2 = 0; + this->y_1 = 0; + this->x_2 = 0; + this->x_1 = 0; + this->b0 = 0; + this->b1 = 0; + this->b2 = 0; + this->a1 = 0; + this->a2 = 0; +} + +void FixedBiquad::SetCoeffs(float a0, float a1, float a2, float b0, float b1, float b2) { + this->y_2 = 0; + this->y_1 = 0; + this->x_2 = 0; + this->x_1 = 0; + this->b0 = b0 / a0; + this->b1 = b1 / a0; + this->b2 = b2 / a0; + this->a1 = -a1 / a0; + this->a2 = -a2 / a0; +} + +void FixedBiquad::SetBandPassParameter(float frequency, uint32_t samplerate, float qFactor) { + float x = (2.f * frequency * (float)M_PI / (float)samplerate); + float sinX = sinf(x); + float cosX = cosf(x); + float y = x / (2.f * qFactor); + SetCoeffs(y + 1.f, -2.f * cosX, 1.f - y, sinX / 2.f, 0.f, -sinX / 2.f); +} + +void FixedBiquad::SetHighPassParameter(float frequency, uint32_t samplerate, float param_4, float qFactor, float param_6) { + // TODO: Cleanup and named params + float fVar12 = (frequency * 2.f * (float)M_PI) / (float)samplerate; + float x = powf(10.f, param_4 / 40.f); + float fVar5 = (1.f / x + x) * (1.f / qFactor - 1.f) + 2.f; + float fVar7 = sqrtf(x); + float fVar8 = x - 1.f; + float fVar10 = x + 1.f; + float fVar6 = sinf(fVar12) * 0.f * sqrtf(fVar5); + fVar5 = cosf(fVar12); + fVar12 = fVar10 + fVar8 * fVar5; + float fVar11 = fVar10 - fVar8 * fVar5; + float fVar2 = powf(10.f,param_6 / 20.f); + float fVar9 = fVar8 - fVar10 * fVar5; + SetCoeffs(fVar11 + (fVar7 + fVar7) * fVar6, + fVar9 + fVar9, + fVar11 - (fVar7 + fVar7) * fVar6, + (fVar12 + (fVar7 + fVar7) * fVar6) * x * fVar2, + x * -2.0 * (fVar8 + fVar10 * fVar5) * fVar2, + (fVar12 - (fVar7 + fVar7) * fVar6) * x * fVar2); +} + +void FixedBiquad::SetLowPassParameter(float frequency, uint32_t samplerate, float qFactor) { + float x = (frequency * 2.f * (float)M_PI) / (float)samplerate; + float sinX = sinf(x); + float y = sinX / (qFactor * 2.f); + float cosX = cosf(x); + float z = (1.f - cosX) / 2.f; + SetCoeffs(y + 1.f, cosX * -2.f, 1.f - y, z, 1.f - cosX, z); +} diff --git a/src/utils/FixedBiquad.h b/src/utils/FixedBiquad.h new file mode 100644 index 0000000..4adf121 --- /dev/null +++ b/src/utils/FixedBiquad.h @@ -0,0 +1,24 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + + +#include + +class FixedBiquad { +public: + FixedBiquad(); + + float ProcessSample(float sample); + void Reset(); + void SetCoeffs(float a0, float a1, float a2, float b0, float b1, float b2); + void SetBandPassParameter(float frequency, uint32_t samplerate, float qFactor); + void SetHighPassParameter(float frequency, uint32_t samplerate, float param_4, float qFactor, float param_6); + void SetLowPassParameter(float frequency, uint32_t samplerate, float qFactor); + + + float y_2, y_1, x_2, x_1; + float b0, b1, b2, a1, a2; +}; diff --git a/src/utils/IIR_1st.cpp b/src/utils/IIR_1st.cpp new file mode 100644 index 0000000..d1efdfa --- /dev/null +++ b/src/utils/IIR_1st.cpp @@ -0,0 +1,154 @@ +// +// Created by mart on 7/26/21. +// + +#include +#include "IIR_1st.h" + +// Seems to be taken from https://github.com/michaelwillis/dragonfly-reverb/blob/master/common/freeverb/efilter.cpp +// Or similar sources + +IIR_1st::IIR_1st() { + this->b0 = 0.f; + this->b1 = 0.f; + this->a1 = 0.f; + Mute() +} + + +void IIR_1st::Mute() { + this->prevSample = 0.f; +} + +void IIR_1st::SetCoefficients(float b0, float b1, float a1) { + this->b0 = b0; + this->b1 = b1; + this->a1 = a1; +} + +#define angle(freq, samplerate) (expf(-1*(float)M_PI*(freq)/((float)(samplerate)/2.f))) +#define omega() (2.f * (float)M_PI * frequency / (float)samplerate) +#define omega_2() ((float)M_PI * frequency / (float)samplerate) + +void IIR_1st::setHPF_A(float frequency, uint32_t samplerate) { + this->a1 = angle(frequency, samplerate); + float norm = (1+a1)/2.f; + this->b0 = norm; + this->b1 = -norm; +} + +void IIR_1st::setHPF_BW(float frequency, uint32_t samplerate) { + float omega_2 = omega_2(); + float tan_omega_2 = tanf(omega_2); + this->b0 = 1/(1+tan_omega_2); + this->b1 = -this->b0; + this->a1 = (1-tan_omega_2)/(1+tan_omega_2); +} + +void IIR_1st::setHPF_C(float frequency, uint32_t samplerate) { + this->b0 = (float)samplerate/((float)samplerate+frequency); + this->b1 = -1 * this->b0; + this->a1 = ((float)samplerate-frequency)/((float)samplerate+frequency); +} + +void IIR_1st::setHPFwLPS_A(float frequency, uint32_t samplerate) { + this->a1 = -0.12f; + this->b0 = -1.f; + this->b1 = angle(frequency, samplerate); + float norm = (1-this->a1) / fabsf(this->b0 + this->b1); + this->b0 *= norm; + this->b1 *= norm;; +} + +void IIR_1st::setHSF_A(float f1, float f2, uint32_t samplerate) { + this->a1 = angle(f1, samplerate); + this->b0 = -1.f; + this->b1 = angle(f2, samplerate); + float norm = (1-this->a1)/(this->b0 + this->b1); + this->b0 *= norm; + this->b1 *= norm; +} + +void IIR_1st::setLPF_A(float frequency, uint32_t samplerate) { + this->a1 = angle(frequency, samplerate); + this->b0 = 1.f; + this->b1 = 0.12f; + float norm = (1+this->a1)/(this->b0 + this->b1); + this->b0 *= norm; + this->b1 *= norm; +} + +void IIR_1st::setLPF_BW(float frequency, uint32_t samplerate) { + float omega_2 = omega_2(); + float tan_omega_2 = tanf(omega_2); + this->a1 = (1-tan_omega_2)/(1+tan_omega_2); + this->b0 = tan_omega_2/(1+tan_omega_2); + this->b1 = this->b0; +} + +void IIR_1st::setLPF_C(float frequency, uint32_t samplerate) { + this->b0 = frequency/((float)samplerate+frequency); + this->b1 = this->b0; + this->a1 = ((float)samplerate-frequency)/((float)samplerate+frequency); +} + +void IIR_1st::setLSF_A(float f1, float f2, uint32_t samplerate) { + this->a1 = angle(f1, samplerate); + this->b0 = -1.f; + this->b1 = angle(f2, samplerate); +} + +void IIR_1st::setPole(float a1) { + this->a1 = a1; + this->b0 = 1.f-fabsf(a1); + this->b1 = 0.f; +} + +void IIR_1st::setPoleHPF(float frequency, uint32_t samplerate) { + float omega = omega(); + float cos_omega = cosf(omega); + float tmp = (2.f + cos_omega); + float coeff = tmp-sqrtf(tmp*tmp-1.f); + this->a1 = -coeff; + this->b0 = 1.f - coeff; + this->b1 = 0; +} + +void IIR_1st::setPoleLPF(float frequency, uint32_t samplerate) { + float omega = omega(); + float cos_omega = cosf(omega); + float tmp = (2.f - cos_omega); + float coeff = tmp-sqrtf(tmp*tmp-1.f); + this->a1 = coeff; + this->b0 = 1.f - coeff; + this->b1 = 0.f; +} + +void IIR_1st::setZero(float b1) { + this->a1 = 0; + this->b0 = -1; + this->b1 = b1; + float norm = fabsf(this->b0) + fabsf(this->b1); + this->b0 *= norm; + this->b1 *= norm; +} + +void IIR_1st::setZeroHPF(float frequency, uint32_t samplerate) { + float omega = omega(); + float cos_omega = cosf(omega); + float tmp = (1.f - 2.f * cos_omega); + float coeff = tmp-sqrtf(tmp*tmp-1.f); + this->a1 = 0.f; + this->b0 = 1.f/(1.f+coeff); + this->b1 = -coeff/(1.f+coeff); +} + +void IIR_1st::setZeroLPF(float frequency, uint32_t samplerate) { + float omega = omega(); + float cos_omega = cosf(omega); + float tmp = (1.f + 2.f * cos_omega); + float coeff = tmp-sqrtf(tmp*tmp-1.f); + this->a1 = 0.f; + this->b0 = 1.f/(1.f+coeff); + this->b1 = coeff/(1.f+coeff); +} \ No newline at end of file diff --git a/src/utils/IIR_1st.h b/src/utils/IIR_1st.h new file mode 100644 index 0000000..6b29f9b --- /dev/null +++ b/src/utils/IIR_1st.h @@ -0,0 +1,32 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once +#include + +class IIR_1st { +public: + IIR_1st(); + + void Mute(); + void SetCoefficients(float b0, float b1, float a1); + void setHPF_A(float frequency, uint32_t samplerate); + void setHPF_BW(float frequency, uint32_t samplerate); + void setHPF_C(float frequency, uint32_t samplerate); + void setHPFwLPS_A(float frequency, uint32_t samplerate); + void setHSF_A(float f1, float f2, uint32_t samplerate); + void setLPF_A(float frequency, uint32_t samplerate); + void setLPF_BW(float frequency, uint32_t samplerate); + void setLPF_C(float frequency, uint32_t samplerate); + void setLSF_A(float f1, float f2, uint32_t samplerate); + void setPole(float a1); + void setPoleHPF(float frequency, uint32_t samplerate); + void setPoleLPF(float frequency, uint32_t samplerate); + void setZero(float b1); + void setZeroHPF(float frequency, uint32_t samplerate); + void setZeroLPF(float frequency, uint32_t samplerate); + + float b0, b1, a1; + float prevSample; +}; diff --git a/src/utils/IIR_NOrder_BW_BP.cpp b/src/utils/IIR_NOrder_BW_BP.cpp new file mode 100644 index 0000000..0a096ca --- /dev/null +++ b/src/utils/IIR_NOrder_BW_BP.cpp @@ -0,0 +1,35 @@ +// +// Created by mart on 7/26/21. +// + +#include "IIR_NOrder_BW_BP.h" + +IIR_NOrder_BW_BP::IIR_NOrder_BW_BP(uint32_t order) { + this->lowpass = new IIR_1st[order]; + this->highpass = new IIR_1st[order]; + this->order = order; + + for (int x = 0; x < order; x++) { + this->lowpass[x].Mute(); + this->highpass[x].Mute(); + } +} + +IIR_NOrder_BW_BP::~IIR_NOrder_BW_BP() { + delete[] this->lowpass; + delete[] this->highpass; +} + +void IIR_NOrder_BW_BP::Mute() { + for (int x = 0; x < this->order; x++) { + this->lowpass[x].Mute(); + this->highpass[x].Mute(); + } +} + +void IIR_NOrder_BW_BP::setBPF(float highCut, float lowCut, uint32_t samplerate) { + for (int x = 0; x < this->order; x++) { + this->lowpass[x].setLPF_BW(lowCut, samplerate); + this->highpass[x].setHPF_BW(highCut, samplerate); + } +} diff --git a/src/utils/IIR_NOrder_BW_BP.h b/src/utils/IIR_NOrder_BW_BP.h new file mode 100644 index 0000000..602641a --- /dev/null +++ b/src/utils/IIR_NOrder_BW_BP.h @@ -0,0 +1,21 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + +#include "IIR_1st.h" + +class IIR_NOrder_BW_BP { +public: + explicit IIR_NOrder_BW_BP(uint32_t order); + ~IIR_NOrder_BW_BP(); + + void Mute(); + void setBPF(float highCut, float lowCut, uint32_t samplerate); + + IIR_1st* lowpass; + IIR_1st* highpass; + uint32_t order; +}; + diff --git a/src/utils/IIR_NOrder_BW_LH.cpp b/src/utils/IIR_NOrder_BW_LH.cpp new file mode 100644 index 0000000..ccfba01 --- /dev/null +++ b/src/utils/IIR_NOrder_BW_LH.cpp @@ -0,0 +1,36 @@ +// +// Created by mart on 7/26/21. +// + +#include "IIR_NOrder_BW_LH.h" + +IIR_NOrder_BW_LH::IIR_NOrder_BW_LH(uint32_t order) { + this->filters = new IIR_1st[order]; + this->order = order; + + for (int x = 0; x < order; x++) { + this->filters[x].Mute(); + } +} + +IIR_NOrder_BW_LH::~IIR_NOrder_BW_LH() { + delete[] this->filters; +} + +void IIR_NOrder_BW_LH::Mute() { + for (int x = 0; x < this->order; x++) { + this->filters[x].Mute(); + } +} + +void IIR_NOrder_BW_LH::setLPF(float frequency, uint32_t samplerate) { + for (int x = 0; x < this->order; x++) { + this->filters[x].setLPF_BW(frequency, samplerate); + } +} + +void IIR_NOrder_BW_LH::setHPF(float frequency, uint32_t samplerate) { + for (int x = 0; x < this->order; x++) { + this->filters[x].setHPF_BW(frequency, samplerate); + } +} diff --git a/src/utils/IIR_NOrder_BW_LH.h b/src/utils/IIR_NOrder_BW_LH.h new file mode 100644 index 0000000..5bf9590 --- /dev/null +++ b/src/utils/IIR_NOrder_BW_LH.h @@ -0,0 +1,20 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + +#include "IIR_1st.h" + +class IIR_NOrder_BW_LH { +public: + explicit IIR_NOrder_BW_LH(uint32_t order); + ~IIR_NOrder_BW_LH(); + + void Mute(); + void setLPF(float frequency, uint32_t samplerate); + void setHPF(float frequency, uint32_t samplerate); + + IIR_1st* filters; + uint32_t order; +}; diff --git a/src/utils/MultiBiquad.cpp b/src/utils/MultiBiquad.cpp new file mode 100644 index 0000000..6262cc1 --- /dev/null +++ b/src/utils/MultiBiquad.cpp @@ -0,0 +1,35 @@ +// +// Created by mart on 7/27/21. +// + +#include "MultiBiquad.h" + +MultiBiquad::MultiBiquad() { + this->y_2 = 0; + this->y_1 = 0; + this->x_2 = 0; + this->x_1 = 0; + this->b0 = 0; + this->b1 = 0; + this->b2 = 0; + this->a1 = 0; + this->a2 = 0; +} + +float MultiBiquad::ProcessSample(float sample) { + float out = sample * this->b0 + this->x_1 * this->b1 + this->x_2 * this->b2 + this->y_1 * this->a1 + this->y_2 * this->a2; + this->y_2 = this->y_1; + this->y_1 = out; + this->x_2 = this->x_1; + this->x_1 = sample; + return out; +} + +void MultiBiquad::RefreshFilter(FilterType type, float gainAmp, float freq, float samplerate, float qFactor, bool param_7) { + // TODO + + this->y_2 = 0.f; + this->y_1 = 0.f; + this->x_2 = 0.f; + this->x_1 = 0.f; +} diff --git a/src/utils/MultiBiquad.h b/src/utils/MultiBiquad.h new file mode 100644 index 0000000..bb07dcb --- /dev/null +++ b/src/utils/MultiBiquad.h @@ -0,0 +1,25 @@ +// +// Created by mart on 7/27/21. +// + +#pragma once + + +enum FilterType { + +}; + + +class MultiBiquad { +public: + MultiBiquad(); + + float ProcessSample(float sample); + void RefreshFilter(FilterType type, float gainAmp, float freq, float samplerate, float qFactor, bool param_7); + + float y_2, y_1, x_2, x_1; + float b0, b1, b2, a1, a2; +}; + + + diff --git a/src/utils/PassFilter.cpp b/src/utils/PassFilter.cpp new file mode 100644 index 0000000..20691a9 --- /dev/null +++ b/src/utils/PassFilter.cpp @@ -0,0 +1,69 @@ +// +// Created by mart on 7/26/21. +// + +#include "PassFilter.h" +#include "../constants.h" + +PassFilter::PassFilter() { + this->filters[0] = new IIR_NOrder_BW_LH(3); + this->filters[1] = new IIR_NOrder_BW_LH(3); + this->filters[2] = new IIR_NOrder_BW_LH(1); + this->filters[3] = new IIR_NOrder_BW_LH(1); + this->samplerate = DEFAULT_SAMPLERATE; + Reset(); +} + +PassFilter::~PassFilter() { + delete this->filters[0]; + delete this->filters[1]; + delete this->filters[2]; + delete this->filters[3]; +} + +void PassFilter::Reset() { + uint32_t cutoff; + if (this->samplerate < 44100) { + cutoff = this->samplerate - 100; + } else { + cutoff = 18000; + } + + this->filters[0]->setLPF((float)cutoff, this->samplerate); + this->filters[1]->setLPF((float)cutoff, this->samplerate); + this->filters[2]->setLPF(10.f, cutoff); + this->filters[3]->setLPF(10.f, cutoff); + + this->filters[0]->Mute(); + this->filters[1]->Mute(); + this->filters[2]->Mute(); + this->filters[3]->Mute(); +} + +#define do_filter(filt, sample) \ +for (int idx = 0; idx < (filt)->order; idx++) {\ + IIR_1st filter = this->filters[2]->filters[idx];\ + float hist = (sample) * filter.b1;\ + left = filter.prevSample + (sample) * filter.b0;\ + filter.prevSample = (sample) * filter.a1 + hist;\ +} + +void PassFilter::ProcessFrames(float *buffer, uint32_t size) { + for (int x = 0; x < size; x++) { + float left = buffer[2*x]; + float right = buffer[2*x+1]; + + do_filter(this->filters[2], left) + do_filter(this->filters[0], left) + do_filter(this->filters[3], right) + do_filter(this->filters[1], right) + + buffer[2*x] = left; + buffer[2*x+1] = right; + } +} + +void PassFilter::SetSamplingRate(uint32_t samplerate) { + this->samplerate = samplerate; + Reset(); +} diff --git a/src/utils/PassFilter.h b/src/utils/PassFilter.h new file mode 100644 index 0000000..28a652e --- /dev/null +++ b/src/utils/PassFilter.h @@ -0,0 +1,21 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + +#include +#include "IIR_NOrder_BW_LH.h" + +class PassFilter { +public: + PassFilter(); + ~PassFilter(); + + void Reset(); + void ProcessFrames(float* buffer, uint32_t size); + void SetSamplingRate(uint32_t samplerate); + + IIR_NOrder_BW_LH* filters[4]; + uint32_t samplerate; +}; diff --git a/src/utils/TimeConstDelay.cpp b/src/utils/TimeConstDelay.cpp new file mode 100644 index 0000000..38ad9d2 --- /dev/null +++ b/src/utils/TimeConstDelay.cpp @@ -0,0 +1,40 @@ +// +// Created by mart on 7/26/21. +// + +#include +#include +#include "TimeConstDelay.h" + +TimeConstDelay::TimeConstDelay() { + this->samples = nullptr; + this->offset = 0; + this->sampleCount = 0; +} + +TimeConstDelay::~TimeConstDelay() { + if (this->samples != nullptr) { + free(this->samples); + this->samples = nullptr; + } +} + +float TimeConstDelay::ProcessSample(float sample) { + if (this->samples != nullptr) { + float val = this->samples[this->offset]; + this->samples[this->offset] = sample; + this->offset = (int)modf((float)this->offset + 1, (float*)&this->sampleCount); + return val; + } + return 0.f; +} + +void TimeConstDelay::SetParameters(uint32_t samplerate, float delay) { + this->sampleCount = (int)((float)samplerate * delay * 0.5f); + if (this->samples != nullptr) { + free(this->samples); + } + this->samples = new float[this->sampleCount * sizeof(float)]; + this->offset = 0; + memset(this->samples, 0, this->sampleCount * sizeof(float)); +} diff --git a/src/utils/TimeConstDelay.h b/src/utils/TimeConstDelay.h new file mode 100644 index 0000000..cd0a75a --- /dev/null +++ b/src/utils/TimeConstDelay.h @@ -0,0 +1,19 @@ +// +// Created by mart on 7/26/21. +// +#pragma once + +#include + +class TimeConstDelay { +public: + TimeConstDelay(); + ~TimeConstDelay(); + + float ProcessSample(float sample); + void SetParameters(uint32_t samplerate, float delay); + + float* samples; + uint32_t offset; + uint32_t sampleCount; +}; diff --git a/src/viper.cpp b/src/viper.cpp new file mode 100644 index 0000000..439203a --- /dev/null +++ b/src/viper.cpp @@ -0,0 +1,94 @@ +#include +#include +#include + +#include "Effect.h" +#include "ProcessUnit_FX.h" + +static effect_descriptor_t viper_descriptor = { + // Identical type/uuid to original ViPER4Android + .type = {0x00000000, 0x0000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + .uuid = {0x41d3c987, 0xe6cf, 0x11e3, 0xa88a, { 0x11, 0xab, 0xa5, 0xd5, 0xc5, 0x1b } }, + .apiVersion = 0x20000, + .flags = 0xf010, + .cpuLoad = 0x08, + .memoryUsage = 0x01, +}; + +extern "C" { + typedef struct { + const struct effect_interface_s* interface; + Effect* effect; + effect_descriptor_t* descriptor; + } handle; + + static int32_t generic_process(effect_handle_t self, audio_buffer_t *in, audio_buffer_t *out) { + auto e = (handle *) self; + return e->effect->process(in, out); + } + static int32_t generic_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) { + auto e = (handle *) self; + return e->effect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData); + } + static int32_t generic_getDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor) { + auto e = (handle *) self; + strcpy(viper_descriptor.name, "ViPER4Android Reworked [1.0.0.0]"); + strcpy(viper_descriptor.implementor, "ViPER.WYF, Martmists, Iscle"); + + memcpy(pDescriptor, e->descriptor, sizeof(effect_descriptor_t)); + return 0; + } + + const effect_interface_s viper_interface = { + .process = generic_process, + .command = generic_command, + .get_descriptor = generic_getDescriptor, + .process_reverse = nullptr + }; + + int32_t EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_handle_t *pEffect) { + if (memcmp(uuid, &viper_descriptor.uuid, sizeof(effect_uuid_t)) == 0) { + // UUID matches + strcpy(viper_descriptor.name, "ViPER4Android Reworked [1.0.0.0]"); + strcpy(viper_descriptor.implementor, "ViPER.WYF, Martmists, Iscle"); + + auto ptr = (handle*)calloc(1, sizeof(handle)); + ptr->interface = &viper_interface; + ptr->effect = new ProcessUnit_FX(); + ptr->descriptor = &viper_descriptor; + *pEffect = (effect_handle_t)ptr; + } else { + return -ENOENT; + } + return 0; + } + + int32_t EffectRelease(effect_handle_t ei) { + auto ptr = (handle*)ei; + delete ptr->effect; + free(ptr); + return 0; + } + + int32_t EffectGetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) { + if (memcmp(uuid, &viper_descriptor.uuid, sizeof(effect_uuid_t)) == 0) { + strcpy(viper_descriptor.name, "ViPER4Android Reworked [1.0.0.0]"); + strcpy(viper_descriptor.implementor, "ViPER.WYF, Martmists, Iscle"); + + memcpy(pDescriptor, &viper_descriptor, sizeof(effect_descriptor_t)); + } else { + return -EINVAL; + } + return 0; + } + + audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { + .tag = ((('A') << 24) | (('E') << 16) | (('L') << 8) | ('I')), + .version = 0x30000, + .name = "ViPER4Android FX Reworked", + .implementor = "ViPER.WYF, Martmists, Iscle", + .create_effect = EffectCreate, + .release_effect = EffectRelease, + .get_descriptor = EffectGetDescriptor, + }; +} diff --git a/src/viper.h b/src/viper.h new file mode 100644 index 0000000..af1f2da --- /dev/null +++ b/src/viper.h @@ -0,0 +1,165 @@ +// +// Created by mart on 7/26/21. +// + +#pragma once + +// Source: https://github.com/vipersaudio/viperfx_core_binary/blob/master/viperfx_intf.h + +extern "C" { + enum + { + COMMAND_CODE_GET = 0x01, + COMMAND_CODE_SET, + }; + + enum + { + PARAM_GET_STATUS_BEGIN = 0x08000, + PARAM_GET_DRIVER_VERSION, + PARAM_GET_NEONENABLED, + PARAM_GET_ENABLED, + PARAM_GET_DRVCANWORK, + PARAM_GET_EFFECT_TYPE, + PARAM_GET_SAMPLINGRATE, + PARAM_GET_CONVKNLID, + PARAM_GET_STATUS_END + }; + + enum + { + PARAM_SET_STATUS_BEGIN = 0x09000, + PARAM_SET_RESET_STATUS, + PARAM_SET_SAMPLINGRATE, + PARAM_SET_DOPROCESS_STATUS, + PARAM_SET_STATUS_END + }; + + enum + { + PARAM_PROCESSUNIT_FX_BEGIN = 0x10000, + + PARAM_FX_TYPE_SWITCH, + PARAM_HPFX_CONV_PROCESS_ENABLED, + PARAM_HPFX_CONV_UPDATEKERNEL, + /*****************************************/ + // Please use PARAM_HPFX_CONV_UPDATEKERNEL instead + PARAM_HPFX_CONV_PREPAREBUFFER, + PARAM_HPFX_CONV_SETBUFFER, + PARAM_HPFX_CONV_COMMITBUFFER, + /*****************************************/ + PARAM_HPFX_CONV_CROSSCHANNEL, + PARAM_HPFX_VHE_PROCESS_ENABLED, + PARAM_HPFX_VHE_EFFECT_LEVEL, + PARAM_HPFX_VDDC_PROCESS_ENABLED, + PARAM_HPFX_VDDC_COEFFS, + PARAM_HPFX_VSE_PROCESS_ENABLED, + PARAM_HPFX_VSE_REFERENCE_BARK, + PARAM_HPFX_VSE_BARK_RECONSTRUCT, + PARAM_HPFX_FIREQ_PROCESS_ENABLED, + PARAM_HPFX_FIREQ_BANDLEVEL, + PARAM_HPFX_COLM_PROCESS_ENABLED, + PARAM_HPFX_COLM_WIDENING, + PARAM_HPFX_COLM_MIDIMAGE, + PARAM_HPFX_COLM_DEPTH, + PARAM_HPFX_DIFFSURR_PROCESS_ENABLED, + PARAM_HPFX_DIFFSURR_DELAYTIME, + PARAM_HPFX_REVB_PROCESS_ENABLED, + PARAM_HPFX_REVB_ROOMSIZE, + PARAM_HPFX_REVB_WIDTH, + PARAM_HPFX_REVB_DAMP, + PARAM_HPFX_REVB_WET, + PARAM_HPFX_REVB_DRY, + PARAM_HPFX_AGC_PROCESS_ENABLED, + PARAM_HPFX_AGC_RATIO, + PARAM_HPFX_AGC_VOLUME, + PARAM_HPFX_AGC_MAXSCALER, + PARAM_HPFX_DYNSYS_PROCESS_ENABLED, + PARAM_HPFX_DYNSYS_XCOEFFS, + PARAM_HPFX_DYNSYS_YCOEFFS, + PARAM_HPFX_DYNSYS_SIDEGAIN, + PARAM_HPFX_DYNSYS_BASSGAIN, + PARAM_HPFX_VIPERBASS_PROCESS_ENABLED, + PARAM_HPFX_VIPERBASS_MODE, + PARAM_HPFX_VIPERBASS_SPEAKER, + PARAM_HPFX_VIPERBASS_BASSGAIN, + PARAM_HPFX_VIPERCLARITY_PROCESS_ENABLED, + PARAM_HPFX_VIPERCLARITY_MODE, + PARAM_HPFX_VIPERCLARITY_CLARITY, + PARAM_HPFX_CURE_PROCESS_ENABLED, + PARAM_HPFX_CURE_CROSSFEED, + PARAM_HPFX_TUBE_PROCESS_ENABLED, + PARAM_HPFX_ANALOGX_PROCESS_ENABLED, + PARAM_HPFX_ANALOGX_MODE, + PARAM_HPFX_OUTPUT_VOLUME, + PARAM_HPFX_OUTPUT_PAN, + PARAM_HPFX_LIMITER_THRESHOLD, + PARAM_SPKFX_CONV_PROCESS_ENABLED, + PARAM_SPKFX_CONV_UPDATEKERNEL, + PARAM_SPKFX_CONV_PREPAREBUFFER, + PARAM_SPKFX_CONV_SETBUFFER, + PARAM_SPKFX_CONV_COMMITBUFFER, + PARAM_SPKFX_CONV_CROSSCHANNEL, + PARAM_SPKFX_FIREQ_PROCESS_ENABLED, + PARAM_SPKFX_FIREQ_BANDLEVEL, + PARAM_SPKFX_REVB_PROCESS_ENABLED, + PARAM_SPKFX_REVB_ROOMSIZE, + PARAM_SPKFX_REVB_WIDTH, + PARAM_SPKFX_REVB_DAMP, + PARAM_SPKFX_REVB_WET, + PARAM_SPKFX_REVB_DRY, + PARAM_SPKFX_AGC_PROCESS_ENABLED, + PARAM_SPKFX_AGC_RATIO, + PARAM_SPKFX_AGC_VOLUME, + PARAM_SPKFX_AGC_MAXSCALER, + PARAM_SPKFX_OUTPUT_VOLUME, + PARAM_SPKFX_LIMITER_THRESHOLD, + PARAM_HPFX_FETCOMP_PROCESS_ENABLED, + PARAM_HPFX_FETCOMP_THRESHOLD, + PARAM_HPFX_FETCOMP_RATIO, + PARAM_HPFX_FETCOMP_KNEEWIDTH, + PARAM_HPFX_FETCOMP_AUTOKNEE_ENABLED, + PARAM_HPFX_FETCOMP_GAIN, + PARAM_HPFX_FETCOMP_AUTOGAIN_ENABLED, + PARAM_HPFX_FETCOMP_ATTACK, + PARAM_HPFX_FETCOMP_AUTOATTACK_ENABLED, + PARAM_HPFX_FETCOMP_RELEASE, + PARAM_HPFX_FETCOMP_AUTORELEASE_ENABLED, + PARAM_HPFX_FETCOMP_META_KNEEMULTI, + PARAM_HPFX_FETCOMP_META_MAXATTACK, + PARAM_HPFX_FETCOMP_META_MAXRELEASE, + PARAM_HPFX_FETCOMP_META_CREST, + PARAM_HPFX_FETCOMP_META_ADAPT, + PARAM_HPFX_FETCOMP_META_NOCLIP_ENABLED, + PARAM_SPKFX_FETCOMP_PROCESS_ENABLED, + PARAM_SPKFX_FETCOMP_THRESHOLD, + PARAM_SPKFX_FETCOMP_RATIO, + PARAM_SPKFX_FETCOMP_KNEEWIDTH, + PARAM_SPKFX_FETCOMP_AUTOKNEE_ENABLED, + PARAM_SPKFX_FETCOMP_GAIN, + PARAM_SPKFX_FETCOMP_AUTOGAIN_ENABLED, + PARAM_SPKFX_FETCOMP_ATTACK, + PARAM_SPKFX_FETCOMP_AUTOATTACK_ENABLED, + PARAM_SPKFX_FETCOMP_RELEASE, + PARAM_SPKFX_FETCOMP_AUTORELEASE_ENABLED, + PARAM_SPKFX_FETCOMP_META_KNEEMULTI, + PARAM_SPKFX_FETCOMP_META_MAXATTACK, + PARAM_SPKFX_FETCOMP_META_MAXRELEASE, + PARAM_SPKFX_FETCOMP_META_CREST, + PARAM_SPKFX_FETCOMP_META_ADAPT, + PARAM_SPKFX_FETCOMP_META_NOCLIP_ENABLED, + + PARAM_PROCESSUNIT_FX_END + }; + + enum + { + ViPER_FX_TYPE_NONE = 0, + + ViPER_FX_TYPE_HEADPHONE = 1, + ViPER_FX_TYPE_SPEAKER = 2, + + ViPER_FX_TYPE_COUNT + }; + +}