//============================================================
// (C) 2017 Harman International Industries, Incorporated.
// Confidential & Proprietary. All Rights Reserved.
// ============================================================
/*!
* file AwxAudioObjExt.cpp
* brief Simple example Audio object for building outside from the xAF repo- Source file
* details Implements a simple example functionality
* details Project Extendable Audio Framework
* copyright Harman/Becker Automotive Systems GmbH
*
2022
*
All rights reserved
* author xAF Team
*/
/*!
* xaf mandataory includes
*/
#include "AwxAudioObjExt.h"
#include "XafMacros.h"
#include "vector.h"
VERSION_STRING_AO(AwxAudioObjExt, AWXAUDIOOBJEXT);
AO_VERSION(AwxAudioObjExt, AWXAUDIOOBJEXT);
/** here you can add all required include files required for
the core functionality of your objects
**/
#define MAX_CONFIG_MIN_GAIN_dB (0.0f)
#define MAX_CONFIG_MAX_GAIN_dB (30.0f)
#define MAX_GAIN_DEFAULT_GAIN_dB (10.0f)
#define CONTROL_GAIN_MIN (-128.0f)
#define GAINDB_CONVERSION_FACTOR (0.05f)
CAwxAudioObjExt::CAwxAudioObjExt()
: m_Coeffs(NULL)
, m_Params(NULL), m_MemBlock(NULL), m_EnMemory(DISABLE_BLOCK)
{
}
CAwxAudioObjExt::~CAwxAudioObjExt()
{
}
void CAwxAudioObjExt::init()
{
m_Params = static_cast(m_MemRecPtrs[PARAM]);
m_Coeffs = static_cast(m_MemRecPtrs[COEFF]);
if (ENABLE_BLOCK == m_EnMemory)
{
m_MemBlock = static_cast(m_MemRecPtrs[FLOATARRAY]);
}
if (static_cast(GAIN_WITH_CONTROL) == m_Mode)
{
m_NumControlIn = 1;
m_NumControlOut = 0;
}
else
{
m_NumControlIn = 0;
m_NumControlOut = 0;
}
}
void CAwxAudioObjExt::assignAdditionalConfig()
{
xInt8* addVars8Ptr = reinterpret_cast(m_AdditionalSFDConfig);
//Assigning additional configuration variable "Abstracted Tuning Memory".
if (static_cast(NULL) != m_AdditionalSFDConfig)
{
m_EnMemory = addVars8Ptr[m_NumAudioIn * sizeof(xFloat32)];
}
}
xFloat32 CAwxAudioObjExt::getMaxGain(xSInt32 index)
{
xFloat32* addVars32Ptr = reinterpret_cast(m_AdditionalSFDConfig);
xFloat32 value = addVars32Ptr[index];
return value;
}
xInt8* CAwxAudioObjExt::getSubBlockPtr(xUInt16 subBlock)
{
xInt8* ptr = NULL;
// this is just an example of how memory could be split by an AO developer. There is no strict rule
// how memory has to be split for each subblock
switch(subBlock)
{
case 0:
ptr = reinterpret_cast(m_Params);
break;
case 1:
ptr = reinterpret_cast(m_MemBlock);
break;
default:
// by default we will return a null ptr, hence wrong subBlock was provided
break;
}
return ptr;
}
xSInt32 CAwxAudioObjExt::getSubBlockSize(xUInt16 subBlock)
{
xSInt32 subBlockSize = 0;
// this is just an example of how memory could be split by an AO developer. There is no strict rule
// how memory has to be split for each subblock
switch(subBlock)
{
case 0:
subBlockSize = static_cast(sizeof(xFloat32)) * static_cast(m_NumAudioIn) * NUM_PARAMS_PER_CHANNEL;
break;
case 1:
subBlockSize = (nullptr != m_MemBlock) ? (static_cast(sizeof(xFloat32)) * FLOAT_ARRAY_SIZE) : 0;
break;
default:
// by default we will return a null ptr, hence wrong subBlock was provided
break;
}
return subBlockSize;
}
void CAwxAudioObjExt::calc(xAFAudio** inputs, xAFAudio** outputs)
{
if (static_cast(ENABLE_BLOCK) == m_EnMemory)
{
xSInt32 numAudioIn = static_cast(m_NumAudioIn);
for (xSInt32 i = 0; i < numAudioIn; i++)
{
// for example if m_MemBlock[0] is to mute all channels
xFloat32 factor = m_Coeffs[i] * m_MemBlock[0];
scalMpy(factor, inputs[i], outputs[i], static_cast(m_BlockLength));
}
}
else
{
xSInt32 numAudioIn = static_cast(m_NumAudioIn);
for (xSInt32 i = 0; i < numAudioIn; i++)
{
scalMpy(m_Coeffs[i], inputs[i], outputs[i], static_cast(m_BlockLength));
}
}
}
void CAwxAudioObjExt::calcGain(xSInt32 channelIndex, xFloat32 gainIndB)
{
xFloat32 maxGainIndB = getMaxGain(channelIndex);
LIMIT(gainIndB, CONTROL_GAIN_MIN, maxGainIndB);
m_Params[channelIndex * NUM_PARAMS_PER_CHANNEL] = gainIndB;
xUInt32* mutePtr = reinterpret_cast(&m_Params[(channelIndex * NUM_PARAMS_PER_CHANNEL) + 1u]);
m_Coeffs[channelIndex] = (0 == *mutePtr) ? powf(MAX_GAIN_DEFAULT_GAIN_dB, gainIndB * GAINDB_CONVERSION_FACTOR) : 0.f;
}
void CAwxAudioObjExt::tuneXTP(xSInt32 subBlock, xSInt32 offsetBytes, xSInt32 sizeBytes, xBool shouldAttemptRamp)
{
if(0 == subBlock)
{
xUInt32 channelu = static_cast(offsetBytes) >> 2u;
xSInt32 channel = static_cast(channelu) / NUM_PARAMS_PER_CHANNEL;
while (sizeBytes > 0)
{
calcGain(channel, m_Params[channel * NUM_PARAMS_PER_CHANNEL]);
sizeBytes -= static_cast(NUM_PARAMS_PER_CHANNEL * sizeof(xFloat32));
channel++;
}
}
else if(1 == subBlock)
{ // handle float array related here
// values are available in m_MemBlock
}
else
{
}
}
xSInt32 CAwxAudioObjExt::controlSet(xSInt32 index, xFloat32 value)
{
if ((0 == index) && (static_cast(GAIN_WITH_CONTROL) == m_Mode))
{
xSInt32 numAudioIn = static_cast(m_NumAudioIn);
for (xSInt32 i = 0; i < numAudioIn; i++)
{
calcGain(i, value);
}
}
return 0;
}
xUInt32 CAwxAudioObjExt::getSize() const
{
return sizeof(*this);
}