/*!
* file AwxAudioObjExtToolbox.cpp
* brief AwxAudioObjExt Toolbox Source file
* details Implements the AwxAudioObjExt signal design API
* details Project Extendable Audio Framework
* copyright Harman/Becker Automotive Systems GmbH
*
2020
*
All rights reserved
* author xAF Team
*/
/*!
* xaf mandataory includes to handle the toolbox related data
*/
#include "AwxAudioObjExtToolbox.h"
#include "XafXmlHelper.h"
#include "AudioObjectProperties.h"
#include "AwxAudioObjExt.h"
#include "XafMacros.h"
#include "AudioObject.h"
// the revision number may be different for specific targets
#define MIN_REQUIRED_XAF_VERSION (RELEASE_U)
// mode specific defines
#define AUDIO_IN_OUT_MIN (1)
#define AUDIO_IN_OUT_MAX (255)
#define EST_MEMORY_CONSUMPTION_NA (0) // memory consuption not available/measured
#define EST_CPU_LOAD_CONSUMPTION_NA (0.f) // cpu load not available/measured
#define CONTROL_GAIN_MAX (30.0f)
#define CONTROL_GAIN_MIN (-128.0f)
#define CONTROL_GAIN_IN_LABEL "Gain"
#define MAX_CONFIG_MIN_GAIN_dB (-12.0f)
#define MAX_CONFIG_MAX_GAIN_dB (30.0f)
#define MAX_GAIN_DEFAULT_GAIN_dB (10.0f)
CAwxAudioObjExtToolbox::CAwxAudioObjExtToolbox()
{
}
CAwxAudioObjExtToolbox::~CAwxAudioObjExtToolbox()
{
}
static CAudioObjectToolbox::additionalSfdVarDescription theVar;
const CAwxAudioObjExtToolbox::additionalSfdVarDescription* CAwxAudioObjExtToolbox::getAdditionalSfdVarsDescription(xUInt32 index)
{
CAudioObjectToolbox::additionalSfdVarDescription* ptr = &theVar;
static CAudioObjectToolbox::MinMaxDefault addVar1 = { MAX_CONFIG_MIN_GAIN_dB ,MAX_CONFIG_MAX_GAIN_dB ,MAX_GAIN_DEFAULT_GAIN_dB }; //Min,max,default values for additional config variable
static CAudioObjectToolbox::MinMaxDefault addVar2 = { 0, 1, 0 }; //Min,max,default values
static CAudioObjectToolbox::addVarsSize m_AddtionalVarSize1[NUM_DIMENSION_VAR] =
{
// size, label, start index, increment
{1, "Max Gain per channel(dB)", 0, 1}
};
static CAudioObjectToolbox::addVarsSize m_AddtionalVarSize2[NUM_DIMENSION_VAR] =
{
// size, label, start index, increment
{1, "Disable: 0nEnable : 1", 0, 1}
};
if (index == 0)
{
theVar.mP_Label = "Max Gain per channel";
theVar.m_DataType = xAF_FLOAT_32;
theVar.mP_RangeSet = &addVar1;
theVar.m_Dimension = 1;
theVar.m_DataOrder = xAF_NONE;
//size varies according to the number of channels
m_AddtionalVarSize1[0].m_Size = static_cast(m_NumAudioIn);
theVar.mP_MaddVarsSize = m_AddtionalVarSize1;
}
else if (index == 1)
{
theVar.mP_Label = "Abstracted Tuning Memory";
theVar.m_DataType = xAF_UCHAR;
theVar.mP_RangeSet = &addVar2;
theVar.m_Dimension = 1;
theVar.m_DataOrder = xAF_NONE;
theVar.mP_MaddVarsSize = m_AddtionalVarSize2;
}
else
{
/* Invalid index. Return NULL */
ptr = NULL;
}
return ptr;
}
const CAudioObjectToolbox::tObjectDescription* CAwxAudioObjExtToolbox::getObjectDescription()
{
static const CAudioObjectToolbox::tObjectDescription descriptions =
{
1, 1, 0, 0, "AwxAudioObjExt", "Simple Object to start with for 3rd party/external objects integration", "External", AWX_EXT_NUM_ADD_VARS, AWX_EXT_NUM_MODES
};
return &descriptions;
}
const CAudioObjectToolbox::tModeDescription* CAwxAudioObjExtToolbox::getModeDescription(xUInt32 mode)
{
static const CAudioObjectToolbox::tModeDescription modeDescription[AWX_EXT_NUM_MODES] =
{
{"Gain", "No control input", 0, 0, "", CFG_NCHANNEL},
{"GainWithControl", "One gain control input pin gets added", 0, 0, "", CFG_NCHANNEL},
};
return (mode < (sizeof(modeDescription) / sizeof(tModeDescription))) ? &modeDescription[mode] : static_cast(NULL);
}
xAF_Error CAwxAudioObjExtToolbox::getObjectIo(ioObjectConfigOutput* configOut)
{
if (static_cast(GAIN_WITH_CONTROL) == m_Mode)
{
configOut->numControlIn = 1;
configOut->numControlOut = 0;
}
else
{
configOut->numControlIn = 0;
configOut->numControlOut = 0;
}
return xAF_SUCCESS;
}
xUInt32 CAwxAudioObjExtToolbox::getXmlObjectTemplate(tTuningInfo* info, xInt8* buffer, xUInt32 maxLen)
{
initiateNewBufferWrite(buffer, maxLen);
// add your tuning parameters here in order to show up in the tuning tool
// the number of params specified here, depends on the number to be tuned in GTT
// in this example we are exposing the tuning parameters as arrays split into 2 subblocks
//template 1
xSInt32 numAudioIn = static_cast(m_NumAudioIn);
xSInt32 blockID = info->Global_Object_Count; // uniq to this instance
xUInt32 id = 0;
for (xSInt32 i = 0; i < numAudioIn; i++)
{
//Max value for each channel to show up shall be specified by this function
xFloat32 gainval = getMaxGain(i);
xAFOpenLongXMLTag("Object");
string templateName = string("").append("AwxAudioObjExtTuneTemplate").append(xAFIntToString(i + 1)).append(xAFIntToString(blockID));
xAFAddFieldToXMLTag("Key", templateName.c_str());
xAFEndLongXMLTag();
xAFWriteQuickXmlTag("ExplorerIcon", "Object");
xAFWriteXmlTag("StateVariables", XML_OPEN);
xAFWriteStateVariable("Gain", // name
id, // id
NULL, // control law
"dB", // unit type
DataTypes[xAF_FLOAT], // data type
-128.0, // min
gainval, // max
0.0, // default
0u, // offset
NULL, // encode value
NULL, // decode value
DataTypeConverters[xAF_FLOAT], // bit converter
false // disable streaming
);
id++;
xAFWriteStateVariable("Mute", // name
id, // id
NULL, // control law
NULL, // unit type
DataTypes[xAF_UINT], // data type
0.0, // min
1.0, // max
0.0, // default
4u, // offset
NULL, // encode value
NULL, // decode value
DataTypeConverters[xAF_UINT], // bit converter
false // disable streaming
);
id++;
xAFWriteXmlTag("StateVariables", XML_CLOSE);
xAFWriteXmlTag("Object", XML_CLOSE);
}
//template 2
//It shall be shown up in the State Variable Explorer if through additional configuration "Abstracted Tuning Memory" is set to 1 or enabled.
if (static_cast(ENABLE_BLOCK) == m_EnMemory)
{
xAFOpenLongXMLTag("Object");
xAFAddFieldToXMLTag("Key", "AwxAudioObjExtArrayTemplate");
xAFEndLongXMLTag();
xAFWriteQuickXmlTag("ExplorerIcon", "Object");
xAFWriteXmlTag("StateVariables", XML_OPEN);
xAFWriteStateVariableBuffer(/* name = */ "FloatArray",
/* id = */ id,
/* type = */ FLOATARRAY_SV,
/* size = */ FLOAT_ARRAY_SIZE,
/* streamIdx = */ id,
/* minVal = */ -1000.0,
/* maxVal = */ 1000.0,
/* defaultVal = */ 0.0,
/* offset = */ 0,
/* isStreamable = */ false);
xAFWriteXmlTag("StateVariables", XML_CLOSE);
xAFWriteXmlTag("Object", XML_CLOSE);
}
return finishWritingToBuffer();
}
xUInt32 CAwxAudioObjExtToolbox::getXmlFileInfo(tTuningInfo* info, xInt8* buffer, xUInt32 maxLen)
{
initiateNewBufferWrite(buffer, maxLen);
xUInt32 hiqnetInc = 0u;
xUInt8 subBlock = 0u;
xSInt32 blockID = info->Global_Object_Count; // uniq to this instance
xAFWriteObject(info->Name, static_cast(info->Global_Object_Count), hiqnetInc, static_cast(info->HiQNetVal), 0);
xAFWriteXmlTag("Objects", XML_OPEN);
xSInt32 numAudioIn = static_cast(m_NumAudioIn); // m_NumAudioIn == m_NumAudioOut
xAFWriteXmlObjectContainer("Gains", hiqnetInc, subBlock, PARAM_CATEGORY);
xAFWriteXmlTag("Objects", XML_OPEN);
for(xSInt32 i = 0; i < numAudioIn; i++)
{
string templateName = string("").append("AwxAudioObjExtTuneTemplate").append(xAFIntToString(i+1)).append(xAFIntToString(blockID));
xAFWriteXmlObjectTemplateInstance(templateName.c_str(), string("Ch").append(xAFIntToString(i+1)).c_str(), i * 8, 1 + i);
// 8 is related here to the internal memory layout where a "state/tuning" is related to a block of N-bytes and withing this needs to be offset
hiqnetInc++;
}
xAFWriteXmlTag("Objects", XML_CLOSE);
xAFWriteXmlTag("Object", XML_CLOSE); //gains
if (static_cast(ENABLE_BLOCK) == m_EnMemory)
{
xAFWriteXmlObjectBlockOffset("AwxAudioObjExtArrayTemplate", "FloatArrayMemory", subBlock, static_cast(info->HiQNetVal), hiqnetInc, PARAM_CATEGORY);
hiqnetInc++;
}
xAFWriteXmlTag("Objects", XML_CLOSE);
xAFWriteXmlTag("Object", XML_CLOSE);
return finishWritingToBuffer();
}
void CAwxAudioObjExtToolbox::createStaticMetadata()
{
m_StaticMetadata.minReqXafVersion = static_cast(MIN_REQUIRED_XAF_VERSION);
setAudioObjectVersion(AWXAUDIOOBJEXT_VERSION_MAJOR, AWXAUDIOOBJEXT_VERSION_MINOR, AWXAUDIOOBJEXT_VERSION_REVISION);
setTuningVersion (AWXAUDIOOBJEXT_TUNING_VERSION_MAJOR, AWXAUDIOOBJEXT_TUNING_VERSION_MINOR);
m_StaticMetadata.supDataFormats.push_back(xAF_DATATYPE_FLOAT);
//creation/release date
setCreationDate(2022, 8, 4);
//Simple AO supports in-place computation
m_StaticMetadata.inPlaceComputationEnabled = true;
//This flag allows to set whether the object dynamically updates its additional vars based on input params
m_StaticMetadata.isAddVarUpdateRequired = true;
}
void CAwxAudioObjExtToolbox::createDynamicMetadata(ioObjectConfigInput& configIn, ioObjectConfigOutput& configOut)
{
metaDataControlDescription ctrlDesc;
// define audio in metadata
m_DynamicMetadata.audioIn.Min = AUDIO_IN_OUT_MIN;
m_DynamicMetadata.audioIn.Max = AUDIO_IN_OUT_MAX;
// define audio out metadata
m_DynamicMetadata.audioOut.Min = AUDIO_IN_OUT_MIN;
m_DynamicMetadata.audioOut.Max = AUDIO_IN_OUT_MAX;
switch (configIn.mode)
{
case static_cast(GAIN_WITH_CONTROL) :
// define control in min, max and label values for the control pin
ctrlDesc.Min = CONTROL_GAIN_MIN;
ctrlDesc.Max = CONTROL_GAIN_MAX;
ctrlDesc.Label = CONTROL_GAIN_IN_LABEL;
m_DynamicMetadata.controlIn.push_back(ctrlDesc);
break;
default:
break;
}
m_DynamicMetadata.estMemory = EST_MEMORY_CONSUMPTION_NA;
m_DynamicMetadata.estMIPS = EST_CPU_LOAD_CONSUMPTION_NA;
}