2025-06-04 03:22:50 +02:00

442 lines
12 KiB
C++

//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar snd_sos_show_operator_init;
extern ConVar snd_sos_show_operator_shutdown;
BEGIN_DEFINE_LOGGING_CHANNEL( LOG_SND_OPERATORS, "SndOperators", LCF_CONSOLE_ONLY, LS_MESSAGE );
ADD_LOGGING_CHANNEL_TAG( "SndOperators" );
ADD_LOGGING_CHANNEL_TAG( "SND" );
END_DEFINE_LOGGING_CHANNEL();
Color OpNameColor( 185, 215, 255, 255 );
Color OpColor( 185, 185, 255, 255 );
Color ConnectColor( 255, 185, 255, 255 );
Color NotExecuteColor( 255, 0, 0, 255 );
Color ResultColor( 255, 185, 185, 255 );
int foo;
void S_GetFloatFromString( float *pFlVector, const char *pString, int nSize = 3 )
{
char tempString[128];
Q_strncpy( tempString, pString, sizeof(tempString) );
int i = 0;
char *token = strtok( tempString, "," );
while( token )
{
*pFlVector = atof( token );
token = strtok( NULL, "," );
i++;
if ( i >= nSize )
{
break;
}
pFlVector++;
}
}
//-----------------------------------------------------------------------------
// CSosOperator
// Operator base class
//-----------------------------------------------------------------------------
CSosOperator::CSosOperator( )
{
SOS_REGISTER_INPUT_FLOAT( CSosOperator, m_flExecute, SO_SINGLE, "input_execute" )
}
void CSosOperator::SetBaseDefaults( void *pVoidMem ) const
{
CSosOperator_t *pStructMem = (CSosOperator_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flExecute, SO_SINGLE, 1.0 )
pStructMem->m_bExecuteOnce = false;
pStructMem->m_bHasExecuted = false;
}
void CSosOperator::PrintIO( CSosOperator_t *pStructMem, CSosOperatorStack *pStack, int nLevel ) const
{
int nNumberOfInputs = m_vInputs.Count();
for(int i = 0; i < nNumberOfInputs; i++ )
{
const InputData_t & inputData = m_vInputs[i];
const char *pInputName = m_vInputMap.GetElementName( i );
Log_Msg( LOG_SND_OPERATORS, OpColor , "%*s%s: ", nLevel, " ", pInputName );
int nConnections[8];
int nNumConnections = 0;
char *pInputValue = (char *)pStructMem + inputData.m_nValueOffset;
char *pOffsetOffset = (char *)pStructMem + inputData.m_nOffsetOffset;
bool bAnyConnected = false;
for( int j = 0; j < inputData.m_nCount; j++ )
{
int nOffsetValue = *((int *)pOffsetOffset + j );
bool bIsConnected = nOffsetValue < 0 ? false : true ;
bAnyConnected |= bIsConnected;
if( bIsConnected )
{
nConnections[ nNumConnections ] = nOffsetValue;
nNumConnections++;
}
else
{
nConnections[ nNumConnections ] = -1;
nNumConnections++;
}
Color connectedColor = bIsConnected ? ConnectColor : OpColor;
switch( inputData.m_Type )
{
case SO_FLOAT:
Log_Msg( LOG_SND_OPERATORS, connectedColor, "%f ", *((float *)pInputValue+j) );
break;
default:
Log_Msg( LOG_SND_OPERATORS, connectedColor, " UNKNOWN DATA TYPE %i ", inputData.m_Type );
break;
}
}
if( bAnyConnected )
{
int nOpIndex = pStack->FindOperatorViaOffset( nConnections[0] );
Log_Msg( LOG_SND_OPERATORS, ConnectColor, "%%(connected: %s", pStack->GetOperatorName( nOpIndex ) );
if( nNumConnections > 0 )
{
for( int k = 0; k < nNumConnections; k++ )
{
Log_Msg( LOG_SND_OPERATORS, ConnectColor, " %i", nConnections[k] );
}
}
Log_Msg( LOG_SND_OPERATORS, ConnectColor, ")");
}
Log_Msg( LOG_SND_OPERATORS, ConnectColor, "\n");
}
int nNumberOfOutputs = m_vOutputs.Count();
for(int i = 0; i < nNumberOfOutputs; i++ )
{
const OutputData_t & outputData = m_vOutputs[i];
const char *pOutputName = m_vOutputMap.GetElementName( i );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*s%s: ", nLevel, " ", pOutputName );
char *pOutput = (char *)pStructMem + outputData.m_nValueOffset;
for( int j = 0; j < outputData.m_nCount; j++ )
{
switch( outputData.m_Type )
{
case SO_FLOAT:
Log_Msg( LOG_SND_OPERATORS, OpColor, "%f ", *((float *)pOutput+j) );
break;
default:
Log_Msg( LOG_SND_OPERATORS, OpColor, " UNKNOWN DATA TYPE %i ", outputData.m_Type );
break;
}
}
Log_Msg( LOG_SND_OPERATORS, OpColor, "\n" );
}
}
void CSosOperator::PrintBaseParams( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperator_t *pStructMem = (CSosOperator_t *)pVoidMem;
const char *pName = pStack->GetOperatorName( nOpIndex );
Color executeColor = ( ( pStructMem->m_flExecute[0] > 0.0 ) && !( pStructMem->m_bExecuteOnce && pStructMem->m_bHasExecuted ) ) ? OpNameColor : NotExecuteColor;
Log_Msg( LOG_SND_OPERATORS, executeColor, "\n%*sName: %s\n", nLevel, " ", pName );
Log_Msg( LOG_SND_OPERATORS, OpColor, "\n%*sExecute Once: %s\n", nLevel, " ", pStructMem->m_bExecuteOnce ? "true" : "false" );
PrintIO( pStructMem, pStack, nLevel );
}
int CSosOperator::ParseValueRef( CSosOperatorStack *pStack, const char *pParamString, const char *pValueString ) const
{
if ( pValueString[0] == VALUE_REF_CHAR )
{
pValueString++;
char tempString[64];
Q_strncpy( tempString, pValueString, sizeof(tempString) );
char *pOpname = strtok( tempString, "." );
char *pOutputName = strtok( NULL, "");
int nOutOffset = pStack->GetOperatorOutputOffset( pOpname, pOutputName );
if ( nOutOffset < 0 )
{
return -1;
}
int nOutIndex = BaseParseHasArrayIndice( pOutputName );
if ( nOutIndex > -1 )
{
nOutOffset += nOutIndex;
}
return nOutOffset;
}
return -1;
}
int CSosOperator::BaseParseHasArrayIndice( const char *pParamString ) const
{
int nInputIndex = -1;
char tempString[64];
Q_strncpy( tempString, pParamString, sizeof(tempString) );
// char *pInputParamString = strtok( tempString, "[" );
char *pIndexString = strtok( NULL, "]");
if ( pIndexString && *pIndexString )
{
nInputIndex = Q_atoi( pIndexString );
}
return nInputIndex;
}
bool CSosOperator::BaseParseKV( CSosOperatorStack *pStack, CSosOperator_t *pStructMem, const char *pParamString, const char *pValueString ) const
{
// if we succeed in finding the specified parameter we return true otw false
if ( pParamString && *pParamString && pValueString && *pValueString )
{
// check for simple global params
if ( !V_strcasecmp( pParamString, "operator" ) )
{
return true;
}
else if ( !V_strcasecmp( pParamString, "execute_once" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bExecuteOnce = true;
}
else
{
pStructMem->m_bExecuteOnce = false;
}
return true;
}
// is this accessing into the array?
// "parse" it, UGLY, CLEAN IT... move it to "HasIndice"
// int nInputIndex = BaseParseHasArrayIndice( pParamString );
int nInputIndex = -1;
char tempString[64];
Q_strncpy( tempString, pParamString, sizeof(tempString) );
char *pInputParamString = strtok( tempString, "[" );
char *pIndexString = strtok( NULL, "]");
bool bFillInputArray = false;
if ( pIndexString && *pIndexString )
{
if ( pIndexString[0] == '*' )
{
bFillInputArray = true;
}
else
{
nInputIndex = Q_atoi( pIndexString );
}
}
// find the input
int nInputParamIndex = m_vInputMap.Find( pInputParamString );
if ( ! m_vInputs.IsValidIndex( nInputParamIndex ) )
{
// Log_Warning( LOG_SND_OPERATORS, "Error: Unable to find input parameter %s", pParamString );
return false;
}
const InputData_t & inputData = m_vInputs[ nInputParamIndex ];
short nCount = inputData.m_nCount;
// gotta put some kind of type matching test in here!
// SODataType_t nType = m_vInputType[ nInputParamIndex ];
int nOffsetOffset = inputData.m_nOffsetOffset;
int nOutputOffset = ParseValueRef( pStack, pParamString, pValueString );
if ( nOutputOffset > -1 )
{
if ( nInputIndex > -1 )
{
if ( nInputIndex < nCount )
{
*((int *)((char *)pStructMem + nOffsetOffset) + nInputIndex) = nOutputOffset;
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, illegal array access: %s", pStack->m_pCurrentOperatorName, pParamString );
}
return true;
}
else
{
for ( int i = 0; i < nCount; i++ )
{
if ( bFillInputArray )
{
*((int *)((char *)pStructMem + nOffsetOffset) + i) = nOutputOffset;
}
else
{
*((int *)((char *)pStructMem + nOffsetOffset) + i) = ( nOutputOffset + (sizeof(float)*i) );
}
}
}
return true;
}
else
{
// if an input is explicit, fill array with single value
int nInputOffset = inputData.m_nValueOffset;
float flValue = RandomInterval( ReadInterval( pValueString ) );
//S_GetFloatFromString( &flValue, pValueString );
if ( nInputIndex > -1 )
{
if ( nInputIndex < nCount )
{
*((float *)( (char *)pStructMem + nInputOffset ) + nInputIndex ) = flValue;
// clear potential previous connections
*((int *)((char *)pStructMem + nOffsetOffset) + nInputIndex) = -1;
}
else
{
//error
return true;
}
}
else
{
for ( int i = 0; i < nCount; i++ )
{
*((float *)( (char *)pStructMem + nInputOffset ) + i )= flValue;
// clear potential previous connections
*((int *)((char *)pStructMem + nOffsetOffset) + i) = nOutputOffset;
}
}
return true;
}
}
return false;
}
int CSosOperator::GetOutputOffset( const char *pOutputName ) const
{
int nIndex = m_vOutputMap.Find( pOutputName );
if ( !m_vOutputs.IsValidIndex( nIndex ) )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Unable to find referenced sound operator output: %s", pOutputName );
return -1;
}
return m_vOutputs[ nIndex ].m_nValueOffset;
}
void CSosOperator::ResolveInputValue( void *pInputDefault, int *pOffsetArray, short nDataCount, SODataType_t nDataType, void *pStackMem ) const
{
size_t nDataSize = 0;
switch( nDataType )
{
case SO_FLOAT:
nDataSize = sizeof( float );
break;
default:
break;
}
for ( int i = 0; i < nDataCount; i++ )
{
int nOffset = *( pOffsetArray + i );
void *pSrc = NULL;
if ( nOffset > -1 )
{
// pSrc = (float *)( (char *)pStackMem + nOffset );
pSrc = ( void *)( (char *)pStackMem + nOffset );
Q_memcpy( ( void *) ( (char *) pInputDefault + ( i * nDataSize ) ) , pSrc, nDataSize );
}
// else
// {
// // copying from itself to itself?
// pSrc = ( void *) ( (char *) pInputDefault + ( i * nDataSize ) );
// }
//
//
// Q_memcpy( pInputDefault[i] , pSrc, nDataSize );
// pInputDefault[i] = *pSrc;
}
}
void CSosOperator::ResolveInputValues( void *pStructMem, void *pStackMem ) const
{
for ( unsigned int i = 0; i < m_vInputMap.Count(); i++ )
{
int nInputIndex = m_vInputMap[ i ];
const InputData_t & inputData = m_vInputs[ nInputIndex ];
SODataType_t nDataType = inputData.m_Type;
short nDataCount = inputData.m_nCount;
size_t nOffset = inputData.m_nValueOffset;
int nOffsetOffset = inputData.m_nOffsetOffset;
void *pInput = (void *)( (char *)pStructMem + nOffset );
int *pOffset = (int *)( (char *)pStructMem + nOffsetOffset );
ResolveInputValue( pInput, pOffset, nDataCount, nDataType, pStackMem );
}
}
void CSosOperator::OffsetConnections( void *pVoidMem, size_t nOffset ) const
{
// point offsets to a different memory segment
for ( unsigned int i = 0; i < m_vInputMap.Count(); i++ )
{
int nInputIndex = m_vInputMap[ i ];
const InputData_t & inputData = m_vInputs[ nInputIndex ];
// SODataType_t nDataType = inputData.m_Type;
short nDataCount = inputData.m_nCount;
int nOffsetOffset = m_vInputs[ nInputIndex ].m_nOffsetOffset;
int *pOffset = (int *)( (char *)pVoidMem + nOffsetOffset );
for( int j = 0; j < nDataCount; j++ )
{
if ( *(pOffset + j) > -1 )
{
*(pOffset + j) += nOffset;
}
}
}
}
void CSosOperator::StackInit( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex )
{
}
void CSosOperator::StackShutdown( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex )
{
if ( snd_sos_show_operator_shutdown.GetInt() )
{
Log_Msg( LOG_SND_OPERATORS, OpColor, "Stack Shutdown: Stack: %s : Operator: %s\n", pStack->GetName(), pStack->GetOperatorName( nOpIndex ) );
}
}