Example 1 – AwxAudioObjExt.cpp

/*!
*   file      AwxAudioObjExt.cpp
*   brief     Simple example Audio object for building outside from the xAF repo- Source file
*   details   Implements a simple example fucntionality
*   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<xFloat32*>(m_MemRecPtrs[PARAM]);
    m_Coeffs = static_cast<xFloat32*>(m_MemRecPtrs[COEFF]);
	
	if (ENABLE_BLOCK == m_EnMemory)
	{
		m_MemBlock = static_cast<xFloat32*>(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<xInt8*>(m_AdditionalSFDConfig);
	//Assigning additional configuration variable "Abstracted Tuning Memory".
	if (static_cast<void*>(NULL) != m_AdditionalSFDConfig)
	{
		m_EnMemory = addVars8Ptr[m_NumAudioIn * sizeof(xFloat32)];
	}
}

xFloat32 CAwxAudioObjExt::getMaxGain(xSInt32 index)
{
	xFloat32*  addVars32Ptr = reinterpret_cast<xFloat32*>(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<xInt8*>(m_Params);
        break;

        case 1:
        ptr = reinterpret_cast<xInt8*>(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<xUInt32*>(&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);
}