This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,10 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "audio_pch.h"

View File

@@ -0,0 +1,409 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "winlite.h"
#include "MPAFile.h"
#include "soundchars.h"
#include "tier1/utlrbtree.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
// exception class
CMPAException::CMPAException(ErrorIDs ErrorID, const char *szFile, const char *szFunction, bool bGetLastError ) :
m_ErrorID( ErrorID ), m_bGetLastError( bGetLastError )
{
m_szFile = strdup(szFile);
m_szFunction = strdup(szFunction);
}
// copy constructor (necessary for exception throwing without pointers)
CMPAException::CMPAException(const CMPAException& Source)
{
m_ErrorID = Source.m_ErrorID;
m_bGetLastError = Source.m_bGetLastError;
m_szFile = strdup(Source.m_szFile);
m_szFunction = strdup(Source.m_szFunction);
}
// destructor
CMPAException::~CMPAException()
{
if( m_szFile )
free( (void*)m_szFile );
if( m_szFunction )
free( (void*)m_szFunction );
}
// should be in resource file for multi language applications
const char *m_szErrors[] =
{
"Can't open the file.",
"Can't set file position.",
"Can't read from file.",
"Reached end of buffer.",
"No VBR Header found.",
"Incomplete VBR Header.",
"No subsequent frame found within tolerance range.",
"No frame found."
};
#define MAX_ERR_LENGTH 256
void CMPAException::ShowError()
{
char szErrorMsg[MAX_ERR_LENGTH] = {0};
char szHelp[MAX_ERR_LENGTH];
// this is not buffer-overflow-proof!
if( m_szFunction )
{
sprintf( szHelp, _T("%s: "), m_szFunction );
strcat( szErrorMsg, szHelp );
}
if( m_szFile )
{
sprintf( szHelp, _T("'%s'\n"), m_szFile );
strcat( szErrorMsg, szHelp );
}
strcat( szErrorMsg, m_szErrors[m_ErrorID] );
#if defined(WIN32) && !defined(_X360)
if( m_bGetLastError )
{
// get error message of last system error id
LPVOID pMsgBuf;
if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &pMsgBuf,
0,
NULL ))
{
strcat( szErrorMsg, "\n" );
strcat( szErrorMsg, (const char *)pMsgBuf );
LocalFree( pMsgBuf );
}
}
#endif
// show error message
Warning( "%s\n", szErrorMsg );
}
// 1KB is inital buffersize, each time the buffer needs to be increased it is doubled
const uint32 CMPAFile::m_dwInitBufferSize = 1024;
CMPAFile::CMPAFile( const char * szFile, uint32 dwFileOffset, FileHandle_t hFile ) :
m_pBuffer(NULL), m_dwBufferSize(0), m_dwBegin( dwFileOffset ), m_dwEnd(0),
m_dwNumTimesRead(0), m_bVBRFile( false ), m_pVBRHeader(NULL), m_bMustReleaseFile( false ),
m_pMPAHeader(NULL), m_hFile( hFile ), m_szFile(NULL), m_dwFrameNo(1)
{
// open file, if not already done
if( m_hFile == FILESYSTEM_INVALID_HANDLE )
{
Open( szFile );
m_bMustReleaseFile = true;
}
// save filename
m_szFile = strdup( szFile );
// set end of MPEG data (assume file end)
if( m_dwEnd <= 0 )
{
// get file size
m_dwEnd = g_pFullFileSystem->Size( m_hFile );
}
// find first valid MPEG frame
m_pMPAHeader = new CMPAHeader( this );
// is VBR header available?
CVBRHeader::VBRHeaderType HeaderType = CVBRHeader::NoHeader;
uint32 dwOffset = m_pMPAHeader->m_dwSyncOffset;
if( CVBRHeader::IsVBRHeaderAvailable( this, HeaderType, dwOffset ) )
{
try
{
// read out VBR header
m_pVBRHeader = new CVBRHeader( this, HeaderType, dwOffset );
m_bVBRFile = true;
m_dwBytesPerSec = m_pVBRHeader->m_dwBytesPerSec;
if( m_pVBRHeader->m_dwBytes > 0 )
m_dwEnd = m_dwBegin + m_pVBRHeader->m_dwBytes;
}
catch(CMPAException& Exc)
{
Exc.ShowError();
}
}
if( !m_pVBRHeader )
{
// always skip empty (32kBit) frames
m_bVBRFile = m_pMPAHeader->SkipEmptyFrames();
m_dwBytesPerSec = m_pMPAHeader->GetBytesPerSecond();
}
}
bool CMPAFile::GetNextFrame()
{
uint32 dwOffset = m_pMPAHeader->m_dwSyncOffset + m_pMPAHeader->m_dwRealFrameSize;
try
{
CMPAHeader* pFrame = new CMPAHeader( this, dwOffset, false );
delete m_pMPAHeader;
m_pMPAHeader = pFrame;
if( m_dwFrameNo > 0 )
m_dwFrameNo++;
}
catch(...)
{
return false;
}
return true;
}
bool CMPAFile::GetPrevFrame()
{
uint32 dwOffset = m_pMPAHeader->m_dwSyncOffset-MPA_HEADER_SIZE;
try
{
// look backward from dwOffset on
CMPAHeader* pFrame = new CMPAHeader( this, dwOffset, false, true );
delete m_pMPAHeader;
m_pMPAHeader = pFrame;
if( m_dwFrameNo > 0 )
m_dwFrameNo --;
}
catch(...)
{
return false;
}
return true;
}
bool CMPAFile::GetFirstFrame()
{
uint32 dwOffset = 0;
try
{
CMPAHeader* pFrame = new CMPAHeader( this, dwOffset, false );
delete m_pMPAHeader;
m_pMPAHeader = pFrame;
m_dwFrameNo = 1;
}
catch(...)
{
return false;
}
return true;
}
bool CMPAFile::GetLastFrame()
{
uint32 dwOffset = m_dwEnd - m_dwBegin - MPA_HEADER_SIZE;
try
{
// look backward from dwOffset on
CMPAHeader* pFrame = new CMPAHeader( this, dwOffset, false, true );
delete m_pMPAHeader;
m_pMPAHeader = pFrame;
m_dwFrameNo = 0;
}
catch(...)
{
return false;
}
return true;
}
// destructor
CMPAFile::~CMPAFile(void)
{
delete m_pMPAHeader;
if( m_pVBRHeader )
delete m_pVBRHeader;
if( m_pBuffer )
delete[] m_pBuffer;
// close file
if( m_bMustReleaseFile )
g_pFullFileSystem->Close( m_hFile );
if( m_szFile )
free( (void*)m_szFile );
}
// open file
void CMPAFile::Open( const char * szFilename )
{
// open with CreateFile (no limitation of 128byte filename length, like in mmioOpen)
m_hFile = g_pFullFileSystem->Open( szFilename, "rb", "GAME" );//::CreateFile( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( m_hFile == FILESYSTEM_INVALID_HANDLE )
{
// throw error
throw CMPAException( CMPAException::ErrOpenFile, szFilename, _T("CreateFile"), true );
}
}
// set file position
void CMPAFile::SetPosition( int offset )
{
/*
LARGE_INTEGER liOff;
liOff.QuadPart = lOffset;
liOff.LowPart = ::SetFilePointer(m_hFile, liOff.LowPart, &liOff.HighPart, dwMoveMethod );
if (liOff.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
{
// throw error
throw CMPAException( CMPAException::ErrSetPosition, m_szFile, _T("SetFilePointer"), true );
}
*/
g_pFullFileSystem->Seek( m_hFile, offset, FILESYSTEM_SEEK_HEAD );
}
// read from file, return number of bytes read
uint32 CMPAFile::Read( void *pData, uint32 dwSize, uint32 dwOffset )
{
uint32 dwBytesRead = 0;
// set position first
SetPosition( m_dwBegin+dwOffset );
//if( !::ReadFile( m_hFile, pData, dwSize, &dwBytesRead, NULL ) )
// throw CMPAException( CMPAException::ErrReadFile, m_szFile, _T("ReadFile"), true );
dwBytesRead = g_pFullFileSystem->Read( pData, dwSize, m_hFile );
return dwBytesRead;
}
// convert from big endian to native format (Intel=little endian) and return as uint32 (32bit)
uint32 CMPAFile::ExtractBytes( uint32& dwOffset, uint32 dwNumBytes, bool bMoveOffset )
{
Assert( dwNumBytes > 0 );
Assert( dwNumBytes <= 4 ); // max 4 byte
// enough bytes in buffer, otherwise read from file
if( !m_pBuffer || ( ((int)(m_dwBufferSize - dwOffset)) < (int)dwNumBytes) )
FillBuffer( dwOffset + dwNumBytes );
uint32 dwResult = 0;
// big endian extract (most significant byte first) (will work on little and big-endian computers)
uint32 dwNumByteShifts = dwNumBytes - 1;
for( uint32 n=dwOffset; n < dwOffset+dwNumBytes; n++ )
{
dwResult |= ( ( unsigned char ) m_pBuffer[n] ) << 8*dwNumByteShifts--; // the bit shift will do the correct byte order for you
}
if( bMoveOffset )
dwOffset += dwNumBytes;
return dwResult;
}
// throws exception if not possible
void CMPAFile::FillBuffer( uint32 dwOffsetToRead )
{
uint32 dwNewBufferSize;
// calc new buffer size
if( m_dwBufferSize == 0 )
dwNewBufferSize = m_dwInitBufferSize;
else
dwNewBufferSize = m_dwBufferSize*2;
// is it big enough?
if( dwNewBufferSize < dwOffsetToRead )
dwNewBufferSize = dwOffsetToRead;
// reserve new buffer
BYTE* pNewBuffer = new BYTE[dwNewBufferSize];
// take over data from old buffer
if( m_pBuffer )
{
memcpy( pNewBuffer, m_pBuffer, m_dwBufferSize );
// release old buffer
delete[] m_pBuffer;
}
m_pBuffer = (char*)pNewBuffer;
// read <dwNewBufferSize-m_dwBufferSize> bytes from offset <m_dwBufferSize>
uint32 dwBytesRead = Read( m_pBuffer+m_dwBufferSize, dwNewBufferSize-m_dwBufferSize, m_dwBufferSize );
// no more bytes in buffer than read out from file
m_dwBufferSize += dwBytesRead;
}
// Uses mp3 code from: http://www.codeproject.com/audio/MPEGAudioInfo.asp
struct MP3Duration_t
{
FileNameHandle_t h;
float duration;
static bool LessFunc( const MP3Duration_t& lhs, const MP3Duration_t& rhs )
{
return lhs.h < rhs.h;
}
};
CUtlRBTree< MP3Duration_t, int > g_MP3Durations( 0, 0, MP3Duration_t::LessFunc );
float GetMP3Duration_Helper( char const *filename )
{
float duration = 60.0f;
// See if it's in the RB tree already...
char fn[ 512 ];
Q_snprintf( fn, sizeof( fn ), "sound/%s", PSkipSoundChars( filename ) );
FileNameHandle_t h = g_pFullFileSystem->FindOrAddFileName( fn );
MP3Duration_t search;
search.h = h;
int idx = g_MP3Durations.Find( search );
if ( idx != g_MP3Durations.InvalidIndex() )
{
return g_MP3Durations[ idx ].duration;
}
try
{
CMPAFile MPAFile( fn, 0 );
if ( MPAFile.m_dwBytesPerSec != 0 )
{
duration = (float)(MPAFile.m_dwEnd - MPAFile.m_dwBegin) / (float)MPAFile.m_dwBytesPerSec;
}
}
catch ( ... )
{
}
search.duration = duration;
g_MP3Durations.Insert( search );
return duration;
}

View File

@@ -0,0 +1,125 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose: Uses mp3 code from: http://www.codeproject.com/audio/MPEGAudioInfo.asp
//
// There don't appear to be any licensing restrictions for using this code:
//
/*
- Readme - MPEG Audio Info Tool V2.0 - 2004-11-01
Description:
This tool can display information about MPEG audio files. It supports
MPEG1, MPEG2, MPEG2.5 in all three layers. You can get all the fields
from the MPEG audio frame in each frame of the file. Additionally you
can check the whole file for inconsistencies.
This tool was written as an example on how to use the classes:
CMPAFile, CMPAHeader, CVBRHeader and CMPAException.
The article MPEG Audio Frame Header on Sourceproject
[http://www.codeproject.com/audio/MPEGAudioInfo.asp]
provides additional information about these classes and the frame header
in general.
This tool was written with MS Visual C++ 7.1. The MFC library is
statically linked.
*/
//=============================================================================
#ifndef MPAFILE_H
#define MPAFILE_H
#ifdef _WIN32
#pragma once
#endif
#pragma once
#include "VBRHeader.h"
#include "MPAHeader.h"
#include "filesystem.h"
// exception class
class CMPAException
{
public:
enum ErrorIDs
{
ErrOpenFile,
ErrSetPosition,
ErrReadFile,
EndOfBuffer,
NoVBRHeader,
IncompleteVBRHeader,
NoFrameInTolerance,
NoFrame
};
CMPAException( ErrorIDs ErrorID, const char *szFile, const char *szFunction = NULL, bool bGetLastError=false );
// copy constructor (necessary because of LPSTR members)
CMPAException(const CMPAException& Source);
~CMPAException(void);
ErrorIDs GetErrorID() { return m_ErrorID; }
void ShowError();
private:
ErrorIDs m_ErrorID;
bool m_bGetLastError;
const char *m_szFunction;
const char *m_szFile;
};
class CMPAFile
{
public:
CMPAFile( const char *szFile, uint32 dwFileOffset, FileHandle_t hFile = FILESYSTEM_INVALID_HANDLE );
~CMPAFile(void);
uint32 ExtractBytes( uint32 &dwOffset, uint32 dwNumBytes, bool bMoveOffset = true );
const char *GetFilename() const { return m_szFile; };
bool GetNextFrame();
bool GetPrevFrame();
bool GetFirstFrame();
bool GetLastFrame();
private:
static const uint32 m_dwInitBufferSize;
// methods for file access
void Open( const char *szFilename );
void SetPosition( int offset );
uint32 Read( void *pData, uint32 dwSize, uint32 dwOffset );
void FillBuffer( uint32 dwOffsetToRead );
static uint32 m_dwBufferSizes[MAXTIMESREAD];
// concerning file itself
FileHandle_t m_hFile;
const char *m_szFile;
bool m_bMustReleaseFile;
public:
uint32 m_dwBegin; // offset of first MPEG Audio frame
uint32 m_dwEnd; // offset of last MPEG Audio frame (estimated)
bool m_bVBRFile;
uint32 m_dwBytesPerSec;
CMPAHeader* m_pMPAHeader;
uint32 m_dwFrameNo;
CVBRHeader* m_pVBRHeader; // XING or VBRI
// concerning read-buffer
uint32 m_dwNumTimesRead;
char *m_pBuffer;
uint32 m_dwBufferSize;
};
#endif // MPAFILE_H

View File

@@ -0,0 +1,336 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#if defined( WIN32) && !defined( _X360 )
#include "winlite.h"
#endif
#include "tier0/platform.h"
#include "MPAFile.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
// static variables
const char *CMPAHeader::m_szLayers[] = { "Layer I", "Layer II", "Layer III" };
const char *CMPAHeader::m_szMPEGVersions[] = {"MPEG 2.5", "", "MPEG 2", "MPEG 1" };
const char *CMPAHeader::m_szChannelModes[] = { "Stereo", "Joint Stereo", "Dual Channel", "Single Channel" };
const char *CMPAHeader::m_szEmphasis[] = { "None", "50/15ms", "", "CCIT J.17" };
// tolerance range, look at expected offset +/- m_dwTolerance for subsequent frames
const uint32 CMPAHeader::m_dwTolerance = 3; // 3 bytes
// max. range where to look for frame sync
const uint32 CMPAHeader::m_dwMaxRange = ( 256 * 1024 );
// sampling rates in hertz: 1. index = MPEG Version ID, 2. index = sampling rate index
const uint32 CMPAHeader::m_dwSamplingRates[4][3] =
{
{11025, 12000, 8000, }, // MPEG 2.5
{0, 0, 0, }, // reserved
{22050, 24000, 16000, }, // MPEG 2
{44100, 48000, 32000 } // MPEG 1
};
// padding sizes in bytes for different layers: 1. index = layer
const uint32 CMPAHeader::m_dwPaddingSizes[3] =
{
4, // Layer1
1, // Layer2
1 // Layer3
};
// bitrates: 1. index = LSF, 2. index = Layer, 3. index = bitrate index
const uint32 CMPAHeader::m_dwBitrates[2][3][15] =
{
{ // MPEG 1
{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, // Layer1
{0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, // Layer2
{0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} // Layer3
},
{ // MPEG 2, 2.5
{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, // Layer1
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, // Layer2
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} // Layer3
}
};
// Samples per Frame: 1. index = LSF, 2. index = Layer
const uint32 CMPAHeader::m_dwSamplesPerFrames[2][3] =
{
{ // MPEG 1
384, // Layer1
1152, // Layer2
1152 // Layer3
},
{ // MPEG 2, 2.5
384, // Layer1
1152, // Layer2
576 // Layer3
}
};
// Samples per Frame / 8
const uint32 CMPAHeader::m_dwCoefficients[2][3] =
{
{ // MPEG 1
48, // Layer1
144, // Layer2
144 // Layer3
},
{ // MPEG 2, 2.5
48, // Layer1
144, // Layer2
72 // Layer3
}
};
// needed later for CRC check
// sideinformation size: 1.index = lsf, 2. index = layer, 3. index = mono
const uint32 CMPAHeader::m_dwSideinfoSizes[2][3][2] =
{
{ // MPEG 1 (not mono, mono
{0,0}, // Layer1
{0,0}, // Layer2
{9,17} // Layer3
},
{ // MPEG 2, 2.5
{0,0}, // Layer1
{0,0}, // Layer2
{17,32} // Layer3
}
};
// constructor (throws exception if no frame found)
CMPAHeader::CMPAHeader( CMPAFile* pMPAFile, uint32 dwExpectedOffset, bool bSubsequentFrame, bool bReverse ) :
m_pMPAFile( pMPAFile ), m_dwSyncOffset( dwExpectedOffset ), m_dwRealFrameSize( 0 )
{
// first check at expected offset (extended for not subsequent frames)
HeaderError error = IsSync( m_dwSyncOffset, !bSubsequentFrame );
int nStep=1;
int nSyncOffset;
while( error != noError )
{
// either look in tolerance range
if( bSubsequentFrame )
{
if( nStep > m_dwTolerance )
{
// out of tolerance range
throw CMPAException( CMPAException::NoFrameInTolerance, pMPAFile->GetFilename() );
}
// look around dwExpectedOffset with increasing steps (+1,-1,+2,-2,...)
if( m_dwSyncOffset <= dwExpectedOffset )
{
nSyncOffset = dwExpectedOffset + nStep;
}
else
{
nSyncOffset = dwExpectedOffset - nStep++;
}
}
// just go forward/backward to find sync
else
{
nSyncOffset = ((int)m_dwSyncOffset) + (bReverse?-1:+1);
}
// is new offset within valid range?
if( nSyncOffset < 0 || nSyncOffset > (int)((pMPAFile->m_dwEnd - pMPAFile->m_dwBegin) - MPA_HEADER_SIZE) || abs( (long)(nSyncOffset-dwExpectedOffset) ) > m_dwMaxRange )
{
// out of tolerance range
throw CMPAException( CMPAException::NoFrame, pMPAFile->GetFilename() );
}
m_dwSyncOffset = nSyncOffset;
// found sync?
error = IsSync( m_dwSyncOffset, !bSubsequentFrame );
}
}
// destructor
CMPAHeader::~CMPAHeader()
{
}
// skips first 32kbit/s or lower bitrate frames to estimate bitrate (returns true if bitrate is variable)
bool CMPAHeader::SkipEmptyFrames()
{
if( m_dwBitrate > 32 )
return false;
uint32 dwHeader;
try
{
while( m_dwBitrate <= 32 )
{
m_dwSyncOffset += m_dwComputedFrameSize + MPA_HEADER_SIZE;
dwHeader = m_pMPAFile->ExtractBytes( m_dwSyncOffset, MPA_HEADER_SIZE, false );
if( IsSync( dwHeader, false ) != noError )
return false;
}
}
catch(CMPAException& /*Exc*/) // just catch the exception and return false
{
return false;
}
return true;
}
// in dwHeader stands 32bit header in big-endian format: frame sync at the end!
// because shifts do only work for integral types!!!
CMPAHeader::HeaderError CMPAHeader::DecodeHeader( uint32 dwHeader, bool bSimpleDecode )
{
// Check SYNC bits (last eleven bits set)
if( (dwHeader >> 24 != 0xff) || ((((dwHeader >> 16))&0xe0) != 0xe0) )
return noSync;
// get MPEG version
m_Version = (MPAVersion)((dwHeader >> 19) & 0x03); // mask only the rightmost 2 bits
if( m_Version == MPEGReserved )
return headerCorrupt;
if( m_Version == MPEG1 )
m_bLSF = false;
else
m_bLSF = true;
// get layer (0 = layer1, 2 = layer2, ...)
m_Layer = (MPALayer)(3 - ((dwHeader >> 17) & 0x03));
if( m_Layer == LayerReserved )
return headerCorrupt;
// protection bit (inverted)
m_bCRC = !((dwHeader >> 16) & 0x01);
// bitrate
BYTE bIndex = (BYTE)((dwHeader >> 12) & 0x0F);
if( bIndex == 0x0F ) // all bits set is reserved
return headerCorrupt;
m_dwBitrate = m_dwBitrates[m_bLSF][m_Layer][bIndex] * 1000; // convert from kbit to bit
if( m_dwBitrate == 0 ) // means free bitrate (is unsupported yet)
return freeBitrate;
// sampling rate
bIndex = (BYTE)((dwHeader >> 10) & 0x03);
if( bIndex == 0x03 ) // all bits set is reserved
return headerCorrupt;
m_dwSamplesPerSec = m_dwSamplingRates[m_Version][bIndex];
// padding bit
m_dwPaddingSize = m_dwPaddingSizes[m_Layer] * ((dwHeader >> 9) & 0x01);
// calculate frame size
m_dwComputedFrameSize = (m_dwCoefficients[m_bLSF][m_Layer] * m_dwBitrate / m_dwSamplesPerSec) + m_dwPaddingSize;
m_dwSamplesPerFrame = m_dwSamplesPerFrames[m_bLSF][m_Layer];
if( !bSimpleDecode )
{
// private bit
m_bPrivate = (dwHeader >> 8) & 0x01;
// channel mode
m_ChannelMode = (ChannelMode)((dwHeader >> 6) & 0x03);
// mode extension (currently not used)
m_ModeExt = (BYTE)((dwHeader >> 4) & 0x03);
// copyright bit
m_bCopyright = (dwHeader >> 3) & 0x01;
// original bit
m_bCopyright = (dwHeader >> 2) & 0x01;
// emphasis
m_Emphasis = (Emphasis)(dwHeader & 0x03);
if( m_Emphasis == EmphReserved )
return headerCorrupt;
}
return noError;
}
CMPAHeader::HeaderError CMPAHeader::IsSync( uint32 dwOffset, bool bExtended )
{
HeaderError error = noSync;
uint32 dwHeader = m_pMPAFile->ExtractBytes( dwOffset, MPA_HEADER_SIZE, false );
// sync bytes found?
if( (dwHeader & 0xFFE00000) == 0xFFE00000 )
{
error = DecodeHeader( dwHeader );
if( error == noError )
{
// enough buffer to do extended check?
if( bExtended )
{
// recursive call (offset for next frame header)
uint32 dwOffset = m_dwSyncOffset+m_dwComputedFrameSize;
try
{
CMPAHeader m_SubsequentFrame( m_pMPAFile, dwOffset, true );
m_dwRealFrameSize = m_SubsequentFrame.m_dwSyncOffset - m_dwSyncOffset;
}
catch( CMPAException& Exc )
{
// could not find any subsequent frame, assume it is the last frame
if( Exc.GetErrorID() == CMPAException::NoFrame )
{
if( dwOffset + m_pMPAFile->m_dwBegin > m_pMPAFile->m_dwEnd )
m_dwRealFrameSize = m_pMPAFile->m_dwEnd - m_pMPAFile->m_dwBegin - m_dwSyncOffset;
else
m_dwRealFrameSize = m_dwComputedFrameSize;
error = noError;
}
else
error = noSync;
}
}
}
}
return error;
}
// CRC-16 lookup table
const uint16 CMPAHeader::wCRC16Table[256] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};

View File

@@ -0,0 +1,116 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef MPAHEADER_H
#define MPAHEADER_H
#ifdef _WIN32
#pragma once
#endif
#pragma once
#define MPA_HEADER_SIZE 4 // MPEG-Audio Header Size 32bit
#define MAXTIMESREAD 5
class CMPAFile;
class CMPAHeader
{
public:
CMPAHeader( CMPAFile* pMPAFile, uint32 dwExpectedOffset = 0, bool bSubsequentFrame = false, bool bReverse = false );
~CMPAHeader();
bool SkipEmptyFrames();
// bitrate is in bit per second, to calculate in bytes => (/ 8)
uint32 GetBytesPerSecond() const { return m_dwBitrate / 8; };
// calc number of seconds from number of frames
uint32 GetLengthSecond(uint32 dwNumFrames) const { return dwNumFrames * m_dwSamplesPerFrame / m_dwSamplesPerSec; };
uint32 GetBytesPerSecond( uint32 dwNumFrames, uint32 dwNumBytes ) const { return dwNumBytes / GetLengthSecond( dwNumFrames ); };
bool IsMono() const { return (m_ChannelMode == SingleChannel)?true:false; };
// true if MPEG2/2.5 otherwise false
bool IsLSF() const { return m_bLSF; };
private:
static const uint32 m_dwMaxRange;
static const uint32 m_dwTolerance;
static const uint32 m_dwSamplingRates[4][3];
static const uint32 m_dwPaddingSizes[3];
static const uint32 m_dwBitrates[2][3][15];
static const uint32 m_dwSamplesPerFrames[2][3];
static const uint32 m_dwCoefficients[2][3];
// necessary for CRC check (not yet implemented)
static const uint32 m_dwSideinfoSizes[2][3][2];
static const uint16 wCRC16Table[256];
bool m_bLSF; // true means lower sampling frequencies (=MPEG2/MPEG2.5)
CMPAFile* m_pMPAFile;
public:
static const char * m_szLayers[];
static const char * m_szMPEGVersions[];
static const char * m_szChannelModes[];
static const char * m_szEmphasis[];
enum MPAVersion
{
MPEG25 = 0,
MPEGReserved,
MPEG2,
MPEG1
}m_Version;
enum MPALayer
{
Layer1,
Layer2,
Layer3,
LayerReserved
}m_Layer;
enum Emphasis
{
EmphNone = 0,
Emph5015,
EmphReserved,
EmphCCITJ17
}m_Emphasis;
enum ChannelMode
{
Stereo,
JointStereo,
DualChannel,
SingleChannel
}m_ChannelMode;
uint32 m_dwSamplesPerSec;
uint32 m_dwSamplesPerFrame;
uint32 m_dwBitrate; // in bit per second (1 kb = 1000 bit, not 1024)
uint32 m_dwSyncOffset;
uint32 m_dwComputedFrameSize, m_dwRealFrameSize;
uint32 m_dwPaddingSize;
// flags
bool m_bCopyright, m_bPrivate, m_bOriginal;
bool m_bCRC;
uint8 m_ModeExt;
private:
enum HeaderError
{
noError,
noSync,
freeBitrate,
headerCorrupt
};
HeaderError DecodeHeader( uint32 dwHeader, bool bSimpleDecode = false );
inline HeaderError IsSync( uint32 dwOffset, bool bExtended );
};
#endif // MPAHEADER_H

View File

@@ -0,0 +1,308 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "audio_pch.h"
#include "tier0/platform.h"
#include "MPAFile.h" // also includes vbrheader.h
#include "tier0/dbg.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint32)(BYTE)(ch0) | ((uint32)(BYTE)(ch1) << 8) | \
((uint32)(BYTE)(ch2) << 16) | ((uint32)(BYTE)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)
// XING Header offset: 1. index = lsf, 2. index = mono
uint32 CVBRHeader::m_dwXINGOffsets[2][2] =
{
// MPEG 1 (not mono, mono)
{ 32 + MPA_HEADER_SIZE, 17 + MPA_HEADER_SIZE },
// MPEG 2/2.5
{ 17 + MPA_HEADER_SIZE, 9 + MPA_HEADER_SIZE }
};
// first test with this static method, if it does exist
bool CVBRHeader::IsVBRHeaderAvailable( CMPAFile* pMPAFile, VBRHeaderType& HeaderType, uint32& dwOffset )
{
Assert(pMPAFile);
// where does VBR header begin (XING)
uint32 dwNewOffset = dwOffset + m_dwXINGOffsets[pMPAFile->m_pMPAHeader->IsLSF()][pMPAFile->m_pMPAHeader->IsMono()];
// check for XING header first
if( CheckXING( pMPAFile, dwNewOffset ) )
{
HeaderType = XINGHeader;
// seek offset back to header begin
dwOffset = dwNewOffset - 4;
return true;
}
// VBRI header always at fixed offset
dwNewOffset = dwOffset + 32 + MPA_HEADER_SIZE;
if( CheckVBRI( pMPAFile, dwNewOffset ) )
{
HeaderType = VBRIHeader;
// seek offset back to header begin
dwOffset = dwNewOffset - 4;
return true;
}
HeaderType = NoHeader;
return false;
}
CVBRHeader::CVBRHeader( CMPAFile* pMPAFile, VBRHeaderType HeaderType, uint32 dwOffset ) :
m_pMPAFile( pMPAFile ), m_pnToc(NULL), m_HeaderType( HeaderType ), m_dwOffset(dwOffset), m_dwFrames(0), m_dwBytes(0)
{
switch( m_HeaderType )
{
case NoHeader:
// no Header found
throw CMPAException( CMPAException::NoVBRHeader, pMPAFile->GetFilename(), NULL, false );
break;
case XINGHeader:
if( !ExtractXINGHeader( m_dwOffset ) )
throw CMPAException( CMPAException::NoVBRHeader, pMPAFile->GetFilename(), NULL, false );
break;
case VBRIHeader:
if( !ExtractVBRIHeader( m_dwOffset ) )
throw CMPAException( CMPAException::NoVBRHeader, pMPAFile->GetFilename(), NULL, false );
break;
}
// calc bitrate
if( m_dwBytes > 0 && m_dwFrames > 0 )
{
// calc number of seconds
m_dwBytesPerSec = m_pMPAFile->m_pMPAHeader->GetBytesPerSecond( m_dwFrames, m_dwBytes );
}
else // incomplete header found
{
throw CMPAException( CMPAException::IncompleteVBRHeader, pMPAFile->GetFilename(), NULL, false );
}
}
bool CVBRHeader::CheckID( CMPAFile* pMPAFile, char ch0, char ch1, char ch2, char ch3, uint32& dwOffset )
{
return ( pMPAFile->ExtractBytes( dwOffset, 4 ) == MAKEFOURCC( ch3, ch2, ch1, ch0 ) );
}
bool CVBRHeader::CheckXING( CMPAFile* pMPAFile, uint32& dwOffset )
{
// XING ID found?
if( !CheckID( pMPAFile, 'X', 'i', 'n', 'g', dwOffset) && !CheckID( pMPAFile, 'I', 'n', 'f', 'o', dwOffset) )
return false;
return true;
}
bool CVBRHeader::CheckVBRI( CMPAFile* pMPAFile, uint32& dwOffset )
{
// VBRI ID found?
if( !CheckID( pMPAFile, 'V', 'B', 'R', 'I', dwOffset ) )
return false;
return true;
}
// currently not used
bool CVBRHeader::ExtractLAMETag( uint32 dwOffset )
{
// LAME ID found?
if( !CheckID( m_pMPAFile, 'L', 'A', 'M', 'E', dwOffset ) && !CheckID( m_pMPAFile, 'G', 'O', 'G', 'O', dwOffset ) )
return false;
return true;
}
bool CVBRHeader::ExtractXINGHeader( uint32 dwOffset )
{
/* XING VBR-Header
size description
4 'Xing' or 'Info'
4 flags (indicates which fields are used)
4 frames (optional)
4 bytes (optional)
100 toc (optional)
4 a VBR quality indicator: 0=best 100=worst (optional)
*/
if( !CheckXING( m_pMPAFile, dwOffset ) )
return false;
uint32 dwFlags;
// get flags (mandatory in XING header)
dwFlags = m_pMPAFile->ExtractBytes( dwOffset, 4 );
// extract total number of frames in file
if(dwFlags & FRAMES_FLAG)
m_dwFrames = m_pMPAFile->ExtractBytes(dwOffset,4);
// extract total number of bytes in file
if(dwFlags & BYTES_FLAG)
m_dwBytes = m_pMPAFile->ExtractBytes(dwOffset,4);
// extract TOC (for more accurate seeking)
if (dwFlags & TOC_FLAG)
{
m_dwTableSize = 100;
m_pnToc = new int[m_dwTableSize];
if( m_pnToc )
{
for(uint32 i=0;i<m_dwTableSize;i++)
m_pnToc[i] = m_pMPAFile->ExtractBytes( dwOffset, 1 );
}
}
m_dwQuality = (uint32)-1;
if(dwFlags & VBR_SCALE_FLAG )
m_dwQuality = m_pMPAFile->ExtractBytes(dwOffset, 4);
return true;
}
bool CVBRHeader::ExtractVBRIHeader( uint32 dwOffset )
{
/* FhG VBRI Header
size description
4 'VBRI' (ID)
2 version
2 delay
2 quality
4 # bytes
4 # frames
2 table size (for TOC)
2 table scale (for TOC)
2 size of table entry (max. size = 4 byte (must be stored in an integer))
2 frames per table entry
?? dynamic table consisting out of frames with size 1-4
whole length in table size! (for TOC)
*/
if( !CheckVBRI( m_pMPAFile, dwOffset ) )
return false;
// extract all fields from header (all mandatory)
m_dwVersion = m_pMPAFile->ExtractBytes(dwOffset, 2 );
m_fDelay = (float)m_pMPAFile->ExtractBytes(dwOffset, 2 );
m_dwQuality = m_pMPAFile->ExtractBytes(dwOffset, 2 );
m_dwBytes = m_pMPAFile->ExtractBytes(dwOffset, 4 );
m_dwFrames = m_pMPAFile->ExtractBytes(dwOffset, 4 );
m_dwTableSize = m_pMPAFile->ExtractBytes(dwOffset, 2 ) + 1; //!!!
m_dwTableScale = m_pMPAFile->ExtractBytes(dwOffset, 2 );
m_dwBytesPerEntry = m_pMPAFile->ExtractBytes(dwOffset, 2 );
m_dwFramesPerEntry = m_pMPAFile->ExtractBytes(dwOffset, 2 );
// extract TOC (for more accurate seeking)
m_pnToc = new int[m_dwTableSize];
if( m_pnToc )
{
for ( unsigned int i = 0 ; i < m_dwTableSize ; i++)
{
m_pnToc[i] = m_pMPAFile->ExtractBytes(dwOffset, m_dwBytesPerEntry );
}
}
return true;
}
CVBRHeader::~CVBRHeader(void)
{
if( m_pnToc )
delete[] m_pnToc;
}
// get byte position for percentage value (fPercent) of file
bool CVBRHeader::SeekPoint(float fPercent, uint32& dwSeekPoint)
{
if( !m_pnToc || m_dwBytes == 0 )
return false;
if( fPercent < 0.0f )
fPercent = 0.0f;
if( fPercent > 100.0f )
fPercent = 100.0f;
switch( m_HeaderType )
{
case XINGHeader:
dwSeekPoint = SeekPointXING( fPercent );
break;
case VBRIHeader:
dwSeekPoint = SeekPointVBRI( fPercent );
break;
}
return true;
}
uint32 CVBRHeader::SeekPointXING(float fPercent) const
{
// interpolate in TOC to get file seek point in bytes
int a;
float fa, fb, fx;
a = (int)fPercent;
if( a > 99 ) a = 99;
fa = (float)m_pnToc[a];
if( a < 99 )
{
fb = (float)m_pnToc[a+1];
}
else
{
fb = 256.0f;
}
fx = fa + (fb-fa)*(fPercent-a);
uint32 dwSeekpoint = (int)((1.0f/256.0f)*fx*m_dwBytes);
return dwSeekpoint;
}
uint32 CVBRHeader::SeekPointVBRI(float fPercent) const
{
return SeekPointByTimeVBRI( (fPercent/100.0f) * m_pMPAFile->m_pMPAHeader->GetLengthSecond( m_dwFrames ) * 1000.0f );
}
uint32 CVBRHeader::SeekPointByTimeVBRI(float fEntryTimeMS) const
{
unsigned int i=0, fraction = 0;
uint32 dwSeekPoint = 0;
float fLengthMS;
float fLengthMSPerTOCEntry;
float fAccumulatedTimeMS = 0.0f ;
fLengthMS = (float)m_pMPAFile->m_pMPAHeader->GetLengthSecond( m_dwFrames ) * 1000.0f ;
fLengthMSPerTOCEntry = fLengthMS / (float)m_dwTableSize;
if ( fEntryTimeMS > fLengthMS )
fEntryTimeMS = fLengthMS;
while ( fAccumulatedTimeMS <= fEntryTimeMS )
{
dwSeekPoint += m_pnToc[i++];
fAccumulatedTimeMS += fLengthMSPerTOCEntry;
}
// Searched too far; correct result
fraction = ( (int)(((( fAccumulatedTimeMS - fEntryTimeMS ) / fLengthMSPerTOCEntry )
+ (1.0f/(2.0f*(float)m_dwFramesPerEntry))) * (float)m_dwFramesPerEntry));
dwSeekPoint -= (uint32)((float)m_pnToc[i-1] * (float)(fraction)
/ (float)m_dwFramesPerEntry);
return dwSeekPoint;
}

View File

@@ -0,0 +1,73 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef VBRHEADER_H
#define VBRHEADER_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
// for XING VBR Header flags
#define FRAMES_FLAG 0x0001
#define BYTES_FLAG 0x0002
#define TOC_FLAG 0x0004
#define VBR_SCALE_FLAG 0x0008
class CMPAFile;
class CVBRHeader
{
public:
enum VBRHeaderType
{
NoHeader,
XINGHeader,
VBRIHeader
};
CVBRHeader( CMPAFile* pMPAFile, VBRHeaderType HeaderType, uint32 dwOffset );
~CVBRHeader(void);
static bool IsVBRHeaderAvailable( CMPAFile* pMPAFile, VBRHeaderType& HeaderType, uint32& dwOffset );
bool SeekPoint(float fPercent, uint32& dwSeekPoint);
uint32 m_dwBytesPerSec;
uint32 m_dwBytes; // total number of bytes
uint32 m_dwFrames; // total number of frames
private:
static uint32 m_dwXINGOffsets[2][2];
static bool CheckID( CMPAFile* pMPAFile, char ch0, char ch1, char ch2, char ch3, uint32& dwOffset );
static bool CheckXING( CMPAFile* pMPAFile, uint32& dwOffset );
static bool CheckVBRI( CMPAFile* pMPAFile, uint32& dwOffset );
bool ExtractLAMETag( uint32 dwOffset );
bool ExtractXINGHeader( uint32 dwOffset );
bool ExtractVBRIHeader( uint32 dwOffset );
uint32 SeekPointXING(float fPercent)const ;
uint32 SeekPointVBRI(float fPercent) const;
uint32 SeekPointByTimeVBRI(float fEntryTimeMS) const;
CMPAFile* m_pMPAFile;
public:
VBRHeaderType m_HeaderType;
uint32 m_dwOffset;
uint32 m_dwQuality; // quality (0..100)
int* m_pnToc; // TOC points for seeking (must be freed)
uint32 m_dwTableSize; // size of table (number of entries)
// only VBRI
float m_fDelay;
uint32 m_dwTableScale; // for seeking
uint32 m_dwBytesPerEntry;
uint32 m_dwFramesPerEntry;
uint32 m_dwVersion;
};
#endif // VBRHEADER_H

View File

@@ -0,0 +1,10 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "audio_pch.h"

View File

@@ -0,0 +1,78 @@
//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#include "platform.h"
#if !defined( _X360 ) && defined( WIN32 )
#define WIN32_LEAN_AND_MEAN
#pragma warning(push, 1)
#pragma warning(disable: 4005)
#include <windows.h>
#include <mmsystem.h>
#pragma warning(pop)
#include <mmreg.h>
#endif
#ifdef _PS3
#include "ps3/ps3_core.h"
#endif
#include "basetypes.h"
#include "commonmacros.h"
#include "mathlib/mathlib.h"
#include "tier0/dbg.h"
#include "tier0/vprof.h"
#include "tier0/icommandline.h"
#include "tier1/strtools.h"
#include "tier2/riff.h"
#include "sound.h"
#include "color.h"
#include "convar.h"
#include "soundservice.h"
#include "voice_sound_engine_interface.h"
#include "soundflags.h"
#include "filesystem.h"
#include "../filesystem_engine.h"
#include "snd_device.h"
#include "sound_private.h"
#include "snd_mix_buf.h"
#include "snd_env_fx.h"
#include "snd_channels.h"
#include "snd_audio_source.h"
#include "snd_convars.h"
#include "snd_dev_common.h"
#include "snd_dev_direct.h"
#ifdef _PS3
#include "snd_dev_ps3audio.h"
#else
#include "snd_dev_xaudio.h"
#endif
#include "snd_sfx.h"
#include "snd_stubs.h"
#include "snd_audio_source.h"
#include "snd_wave_source.h"
#include "snd_wave_temp.h"
#include "snd_wave_data.h"
#include "snd_wave_mixer_private.h"
#include "snd_wave_mixer_adpcm.h"
#include "snd_io.h"
#include "voice_mixer_controls.h"
#if IsX360()
# include "snd_wave_mixer_xma.h"
# include "xbox/xbox_win32stubs.h"
# include <xhv2.h>
#elif IsPS3()
# include "snd_wave_mixer_ps3_mp3.h"
# include "ps3/ps3_win32stubs.h"
#elif defined(POSIX)
# include "audio/private/posix_stubs.h"
#endif

View File

@@ -0,0 +1,307 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Circular Buffer
//
//=============================================================================//
#include "tier0/dbg.h"
#include "tier1/mempool.h"
#include "circularbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CCircularBuffer::CCircularBuffer()
{
SetSize( 0 );
}
CCircularBuffer::CCircularBuffer(int size)
{
SetSize(size);
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Sets the maximum size for a circular buffer. This does not do any
// memory allocation, it simply informs the buffer of its size.
//Author : DSpeyrer
//------------------------------------------------------------------------------
void CCircularBuffer::SetSize(int size)
{
Assert( this );
m_nSize = size;
m_nRead = 0;
m_nWrite = 0;
m_nCount = 0;
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Empties a circular buffer.
//Author : DSpeyrer
//------------------------------------------------------------------------------
void CCircularBuffer::Flush()
{
AssertValid();
m_nRead = 0;
m_nWrite = 0;
m_nCount = 0;
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Returns the available space in a circular buffer.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::GetWriteAvailable()
{
AssertValid();
return(m_nSize - m_nCount);
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Returns the size of a circular buffer.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::GetSize()
{
AssertValid();
return(m_nSize);
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Returns the number of bytes in a circular buffer.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::GetReadAvailable()
{
AssertValid();
return(m_nCount);
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Reads a specified number of bytes from a circular buffer without
// consuming them. They will still be available for future calls to
// Read or Peek.
//Input : pchDest - destination buffer.
// m_nCount - number of bytes to place in destination buffer.
//Output : Returns the number of bytes placed in the destination buffer.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::Peek(char *pchDest, int nCount)
{
// If no data available, just return.
if(m_nCount == 0)
{
return(0);
}
//
// Requested amount should not exceed the available amount.
//
nCount = MIN(m_nCount, nCount);
//
// Copy as many of the requested bytes as possible.
// If buffer wrap occurs split the data into two chunks.
//
if (m_nRead + nCount > m_nSize)
{
int nCount1 = m_nSize - m_nRead;
memcpy(pchDest, &m_chData[m_nRead], nCount1);
pchDest += nCount1;
int nCount2 = nCount - nCount1;
memcpy(pchDest, m_chData, nCount2);
}
// Otherwise copy it in one go.
else
{
memcpy(pchDest, &m_chData[m_nRead], nCount);
}
AssertValid();
return nCount;
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Advances the read index, consuming a specified number of bytes from
// the circular buffer.
//Input : m_nCount - number of bytes to consume.
//Output : Returns the actual number of bytes consumed.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::Advance(int nCount)
{
// If no data available, just return.
if (m_nCount == 0)
{
return(0);
}
//
// Requested amount should not exceed the available amount.
//
nCount = MIN(m_nCount, nCount);
//
// Advance the read pointer, checking for buffer wrap.
//
m_nRead = (m_nRead + nCount) % m_nSize;
m_nCount -= nCount;
//
// If we have emptied the buffer, reset the read and write indices
// to minimize buffer wrap.
//
if (m_nCount == 0)
{
m_nRead = 0;
m_nWrite = 0;
}
AssertValid();
return nCount;
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Reads a specified number of bytes from a circular buffer. The bytes
// will be consumed by the read process.
//Input : pchDest - destination buffer.
// m_nCount - number of bytes to place in destination buffer.
//Output : Returns the number of bytes placed in the destination buffer.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::Read(void *pchDestIn, int m_nCount)
{
int nPeeked;
int m_nRead;
char *pchDest = (char*)pchDestIn;
nPeeked = Peek(pchDest, m_nCount);
if (nPeeked != 0)
{
m_nRead = Advance(nPeeked);
assert(m_nRead == nPeeked);
}
else
{
m_nRead = 0;
}
AssertValid();
return(m_nRead);
}
//------------------ Copyright (c) 1999 Valve, LLC. ----------------------------
//Purpose : Writes a specified number of bytes to the buffer.
//Input : pm_chData - buffer containing bytes to bw written.
// m_nCount - the number of bytes to write.
//Output : Returns the number of bytes written. If there wa insufficient space
// to write all requested bytes, the value returned will be less than
// the requested amount.
//Author : DSpeyrer
//------------------------------------------------------------------------------
int CCircularBuffer::Write(void *pData, int nBytesRequested)
{
// Write all the data.
int nBytesToWrite = nBytesRequested;
char *pDataToWrite = (char*)pData;
while(nBytesToWrite)
{
int from = m_nWrite;
int to = m_nWrite + nBytesToWrite;
if(to >= m_nSize)
{
to = m_nSize;
}
memcpy(&m_chData[from], pDataToWrite, to - from);
pDataToWrite += to - from;
m_nWrite = to % m_nSize;
nBytesToWrite -= to - from;
}
// Did it cross the read pointer? Then slide the read pointer up.
// This way, we will discard the old data.
if(nBytesRequested > (m_nSize - m_nCount))
{
m_nCount = m_nSize;
m_nRead = m_nWrite;
}
else
{
m_nCount += nBytesRequested;
}
AssertValid();
return nBytesRequested;
}
CFixedBudgetMemoryPool<ALIGN_VALUE(sizeof( CCircularBuffer ) + 8820 - 1, TSLIST_NODE_ALIGNMENT ), 24> g_SmallBuffers;
CFixedBudgetMemoryPool<ALIGN_VALUE(sizeof( CCircularBuffer ) + 17640 - 1, TSLIST_NODE_ALIGNMENT ), 44> g_MediumBuffers;
CFixedBudgetMemoryPool<ALIGN_VALUE(sizeof( CCircularBuffer ) + 35280 - 1, TSLIST_NODE_ALIGNMENT ), 16> g_LargeBuffers;
CCircularBuffer *AllocateCircularBuffer( int nSize )
{
CCircularBuffer *pCCircularBuffer;
if ( nSize <= 8820 )
{
pCCircularBuffer = (CCircularBuffer *)g_SmallBuffers.Alloc();
}
else if ( nSize <= 17640 )
{
pCCircularBuffer = (CCircularBuffer *)g_MediumBuffers.Alloc();
}
else if ( nSize <= 35280 )
{
pCCircularBuffer = (CCircularBuffer *)g_LargeBuffers.Alloc();
}
else
{
pCCircularBuffer = (CCircularBuffer *)malloc( sizeof( CCircularBuffer ) + nSize - 1 );
}
pCCircularBuffer->SetSize( nSize );
return pCCircularBuffer;
}
void FreeCircularBuffer( CCircularBuffer *pCircularBuffer )
{
int nSize = pCircularBuffer->GetSize();
if ( nSize <= 8820 )
{
g_SmallBuffers.Free( pCircularBuffer );
}
else if ( nSize <= 17640 )
{
g_MediumBuffers.Free( pCircularBuffer );
}
else if ( nSize <= 35280 )
{
g_LargeBuffers.Free( pCircularBuffer );
}
else
{
free( pCircularBuffer );
}
}

View File

@@ -0,0 +1,99 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines an interface for circular buffers. Data can be written to
// and read from these buffers as though from a file. When it is
// write-overflowed (you write more data in than the buffer can hold),
// the read pointer is advanced to allow the new data to be written.
// This means old data will be discarded if you write too much data
// into the buffer.
//
// MikeD: Moved all the functions into a class.
// Changed it so when the buffer overflows, the old data
// is discarded rather than the new.
//
//=====================================================================================//
#ifndef CIRCULARBUFFER_H
#define CIRCULARBUFFER_H
#pragma once
class CCircularBuffer
{
public:
CCircularBuffer();
CCircularBuffer( int size );
void SetSize( int nSize );
protected:
inline void AssertValid()
{
#ifdef _DEBUG
Assert( this );
Assert( m_nSize > 0 );
Assert( m_nCount >= 0 );
Assert( m_nCount <= m_nSize );
Assert( m_nWrite < m_nSize );
// Verify that m_nCount is correct.
if( m_nRead == m_nWrite )
{
Assert( m_nCount == 0 || m_nCount == m_nSize );
}
else
{
int testCount=0;
if ( m_nRead < m_nWrite )
testCount = m_nWrite - m_nRead;
else
testCount = (m_nSize - m_nRead) + m_nWrite;
Assert( testCount == m_nCount );
}
#endif
}
public:
void Flush();
int GetSize(); // Get the size of the buffer (how much can you write without reading
// before losing data.
int GetWriteAvailable(); // Get the amount available to write without overflowing.
// Note: you can write however much you want, but it may overflow,
// in which case the newest data is kept and the oldest is discarded.
int GetReadAvailable(); // Get the amount available to read.
int GetMaxUsed();
int Peek(char *pchDest, int nCount);
int Advance(int nCount);
int Read(void *pchDest, int nCount);
int Write(void *pchData, int nCount);
public:
int m_nCount; // Space between the read and write pointers (how much data we can read).
int m_nRead; // Read index into circular buffer
int m_nWrite; // Write index into circular buffer
int m_nSize; // Size of circular buffer in bytes (how much data it can hold).
char m_chData[1]; // Circular buffer holding data
};
// Use this to instantiate a CircularBuffer.
template< int size >
class CSizedCircularBuffer : public CCircularBuffer
{
public:
CSizedCircularBuffer() : CCircularBuffer(size) {}
private:
char myData[size-1];
};
CCircularBuffer *AllocateCircularBuffer( int nSize );
void FreeCircularBuffer( CCircularBuffer *pCircularBuffer );
#endif // CIRCULARBUFFER_H

124
engine/audio/private/eax.h Normal file
View File

@@ -0,0 +1,124 @@
// EAX.H -- DirectSound Environmental Audio Extensions
#ifndef EAX_H
#define EAX_H
#pragma once
// EAX (listener) reverb property set {4a4e6fc1-c341-11d1-b73a-444553540000}
DEFINE_GUID(DSPROPSETID_EAX_ReverbProperties,
0x4a4e6fc1,
0xc341,
0x11d1,
0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
typedef enum
{
DSPROPERTY_EAX_ALL, // all reverb properties
DSPROPERTY_EAX_ENVIRONMENT, // standard environment no.
DSPROPERTY_EAX_VOLUME, // loudness of the reverb
DSPROPERTY_EAX_DECAYTIME, // how long the reverb lasts
DSPROPERTY_EAX_DAMPING // the high frequencies decay faster
} DSPROPERTY_EAX_REVERBPROPERTY;
#define EAX_NUM_STANDARD_PROPERTIES (DSPROPERTY_EAX_DAMPING + 1)
// use this structure for get/set all properties...
typedef struct
{
unsigned long environment; // 0 to EAX_ENVIRONMENT_COUNT-1
float fVolume; // 0 to 1
float fDecayTime_sec; // seconds, 0.1 to 100
float fDamping; // 0 to 1
} EAX_REVERBPROPERTIES;
enum
{
EAX_ENVIRONMENT_GENERIC, // factory default
EAX_ENVIRONMENT_PADDEDCELL,
EAX_ENVIRONMENT_ROOM, // standard environments
EAX_ENVIRONMENT_BATHROOM,
EAX_ENVIRONMENT_LIVINGROOM,
EAX_ENVIRONMENT_STONEROOM,
EAX_ENVIRONMENT_AUDITORIUM,
EAX_ENVIRONMENT_CONCERTHALL,
EAX_ENVIRONMENT_CAVE,
EAX_ENVIRONMENT_ARENA,
EAX_ENVIRONMENT_HANGAR,
EAX_ENVIRONMENT_CARPETEDHALLWAY,
EAX_ENVIRONMENT_HALLWAY,
EAX_ENVIRONMENT_STONECORRIDOR,
EAX_ENVIRONMENT_ALLEY,
EAX_ENVIRONMENT_FOREST,
EAX_ENVIRONMENT_CITY,
EAX_ENVIRONMENT_MOUNTAINS,
EAX_ENVIRONMENT_QUARRY,
EAX_ENVIRONMENT_PLAIN,
EAX_ENVIRONMENT_PARKINGLOT,
EAX_ENVIRONMENT_SEWERPIPE,
EAX_ENVIRONMENT_UNDERWATER,
EAX_ENVIRONMENT_DRUGGED,
EAX_ENVIRONMENT_DIZZY,
EAX_ENVIRONMENT_PSYCHOTIC,
EAX_ENVIRONMENT_COUNT // total number of environments
};
#define EAX_MAX_ENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1)
// presets
#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F
#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F
#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F
#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F
#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F
#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F
#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F
#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F
#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F
#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F
#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F
#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F
#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F
#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F
#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F
#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F
#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F
#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F
#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F
#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F
#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F
#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F
#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F
#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F
#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F
#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F
// EAX buffer reverb property set {4a4e6fc0-c341-11d1-b73a-444553540000}
DEFINE_GUID(DSPROPSETID_EAXBUFFER_ReverbProperties,
0x4a4e6fc0,
0xc341,
0x11d1,
0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
typedef enum
{
DSPROPERTY_EAXBUFFER_ALL, // all reverb buffer properties
DSPROPERTY_EAXBUFFER_REVERBMIX // the wet source amount
} DSPROPERTY_EAXBUFFER_REVERBPROPERTY;
// use this structure for get/set all properties...
typedef struct
{
float fMix; // linear factor, 0.0F to 1.0F
} EAXBUFFER_REVERBPROPERTIES;
#define EAX_REVERBMIX_USEDISTANCE -1.0F // out of normal range
// signifies the reverb engine should
// calculate it's own reverb mix value
// based on distance
#endif // EAX_H

View File

@@ -0,0 +1,234 @@
//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============
//
// Purpose: Posix win32 replacements - Mocks trivial windows flow
//
//=============================================================================
#if !defined( POSIX_AUDIO_STUBS_H ) && !defined( _PS3 )
#define POSIX_AUDIO_STUBS_H
#define DSBCAPS_LOCSOFTWARE 0
#define DSERR_BUFFERLOST 0
#define DSBSTATUS_BUFFERLOST 0x02
#define DSSPEAKER_GEOMETRY(x) (((x)>>16) & 0xFFFF)
#define DSSPEAKER_CONFIG(x) ((x) & 0xFFFF)
#define DSSPEAKER_HEADPHONE -1
#define DSSPEAKER_QUAD -2
#define DSSPEAKER_5POINT1 -3
#define DSSPEAKER_7POINT1 -4
#define DISP_CHANGE_SUCCESSFUL 0
#define HKEY_CURRENT_USER NULL
#define HKEY_LOCAL_MACHINE NULL
#define KEY_QUERY_VALUE 0
#define KEY_READ 0
#define KEY_WRITE 1
#define KEY_ALL_ACCESS ((ULONG)-1)
#define SMTO_ABORTIFHUNG 0
#define JOY_RETURNX 0x01
#define JOY_RETURNY 0x02
#define JOY_RETURNZ 0x04
#define JOY_RETURNR 0x08
#define JOY_RETURNU 0x10
#define JOY_RETURNV 0x20
#define JOYCAPS_HASPOV 0x01
#define JOYCAPS_HASU 0x01
#define JOYCAPS_HASV 0x01
#define JOYCAPS_HASR 0x01
#define JOYCAPS_HASZ 0x01
#define MMSYSERR_NODRIVER 1
#define JOYERR_NOERROR 0
#define JOY_RETURNCENTERED 0
#define JOY_RETURNBUTTONS 0
#define JOY_RETURNPOV 0
#define JOY_POVCENTERED 0
#define JOY_POVFORWARD 0
#define JOY_POVRIGHT 0
#define JOY_POVBACKWARD 0
#define JOY_POVLEFT 0
#define CCHDEVICENAME 32
#define CCHFORMNAME 32
typedef wchar_t BCHAR;
typedef uint MMRESULT;
//typedef uint32 *DWORD_PTR;
typedef const char *LPCSTR;
typedef uint POINTL;
#define IDLE_PRIORITY_CLASS 1
#define HIGH_PRIORITY_CLASS 2
typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union u1 {
struct s {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
};
POINTL dmPosition;
DWORD dmDisplayOrientation;
DWORD dmDisplayFixedOutput;
};
short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BYTE dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union u2 {
DWORD dmDisplayFlags;
DWORD dmNup;
};
DWORD dmDisplayFrequency;
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
DWORD dmPanningWidth;
DWORD dmPanningHeight;
} DEVMODE, *LPDEVMODE;
typedef uint32 MCIERROR;
typedef uint MCIDEVICEID;
typedef struct {
DWORD_PTR dwCallback;
} MCI_GENERIC_PARMS;
typedef struct {
DWORD_PTR dwCallback;
DWORD dwReturn;
DWORD dwItem;
DWORD dwTrack;
} MCI_STATUS_PARMS;
typedef struct {
DWORD_PTR dwCallback;
DWORD dwFrom;
DWORD dwTo;
} MCI_PLAY_PARMS;
typedef struct {
DWORD_PTR dwCallback;
MCIDEVICEID wDeviceID;
LPCSTR lpstrDeviceType;
LPCSTR lpstrElementName;
LPCSTR lpstrAlias;
} MCI_OPEN_PARMS;
typedef struct {
DWORD_PTR dwCallback;
DWORD dwTimeFormat;
DWORD dwAudio;
} MCI_SET_PARMS;
#define MCI_MAKE_TMSF(t, m, s, f) ((DWORD)(((BYTE)(t) | ((WORD)(m) << 8)) | ((DWORD)(BYTE)(s) | ((WORD)(f)<<8)) << 16))
#define MCI_MSF_MINUTE(msf) ((BYTE)(msf))
#define MCI_MSF_SECOND(msf) ((BYTE)(((WORD)(msf)) >> 8))
#define MCI_OPEN 0
#define MCI_OPEN_TYPE 0
#define MCI_OPEN_SHAREABLE 0
#define MCI_FORMAT_TMSF 0
#define MCI_SET_TIME_FORMAT 0
#define MCI_CLOSE 0
#define MCI_STOP 0
#define MCI_PAUSE 0
#define MCI_PLAY 0
#define MCI_SET 0
#define MCI_SET_DOOR_OPEN 0
#define MCI_SET_DOOR_CLOSED 0
#define MCI_STATUS_READY 0
#define MCI_STATUS 0
#define MCI_STATUS_ITEM 0
#define MCI_STATUS_WAIT 0
#define MCI_STATUS_NUMBER_OF_TRACKS 0
#define MCI_CDA_STATUS_TYPE_TRACK 0
#define MCI_TRACK 0
#define MCI_WAIT 0
#define MCI_CDA_TRACK_AUDIO 0
#define MCI_STATUS_LENGTH 0
#define MCI_NOTIFY 0
#define MCI_FROM 0
#define MCI_TO 0
#define MCIERR_DRIVER -1
#define DSERR_ALLOCATED 0
#pragma pack(push, 1)
typedef struct tWAVEFORMATEX
{
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX, *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX;
typedef const WAVEFORMATEX *LPCWAVEFORMATEX;
typedef struct waveformat_tag
{
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
} WAVEFORMAT, *PWAVEFORMAT, *NPWAVEFORMAT, *LPWAVEFORMAT;
typedef const WAVEFORMAT *LPCWAVEFORMAT;
typedef struct pcmwaveformat_tag
{
WAVEFORMAT wf;
WORD wBitsPerSample;
} PCMWAVEFORMAT, *PPCMWAVEFORMAT, *NPPCMWAVEFORMAT, *LPPCMWAVEFORMAT;
typedef const PCMWAVEFORMAT *LPCPCMWAVEFORMAT;
typedef struct adpcmcoef_tag {
short iCoef1;
short iCoef2;
} ADPCMCOEFSET;
typedef struct adpcmwaveformat_tag {
WAVEFORMATEX wfx;
WORD wSamplesPerBlock;
WORD wNumCoef;
ADPCMCOEFSET aCoef[1];
} ADPCMWAVEFORMAT;
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,251 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef SND_CHANNELS_H
#define SND_CHANNELS_H
#include "mathlib/vector.h"
#include "phonon/phonon_3d.h"
#if defined( _WIN32 )
#pragma once
#endif
class CSfxTable;
class CAudioMixer;
class CSosOperatorStackList;
typedef int SoundSource;
// DO NOT REORDER: indices to fvolume arrays in channel_t
#define IFRONT_LEFT 0 // NOTE: must correspond to order of fvolume array below!
#define IFRONT_RIGHT 1
#define IREAR_LEFT 2
#define IREAR_RIGHT 3
#define IFRONT_CENTER 4
#define IFRONT_CENTER0 5 // dummy slot - center channel is mono, but mixers reference volume[1] slot
#define IFRONT_LEFTD 6 // start of doppler right array
#define IFRONT_RIGHTD 7
#define IREAR_LEFTD 8
#define IREAR_RIGHTD 9
#define IFRONT_CENTERD 10
#define IFRONT_CENTERD0 11 // dummy slot - center channel is mono, but mixers reference volume[1] slot
#define CCHANVOLUMES 12
struct gain_t
{
float ob_gain; // gain drop if sound source obscured from listener
float ob_gain_target; // target gain while crossfading between ob_gain & ob_gain_target
float ob_gain_inc; // crossfade increment
};
struct hrtf_info_t
{
Vector vec; // Sound source relative to the listener, updated every frame for channels using HRTF.
float lerp; // 1.0 = use phonon fully, 0.0 = don't use phonon at all.
bool follow_entity; // If true, we update the position of the entity every frame, otherwise we use the position of the sound.
bool bilinear_filtering; // If true, we use more expensive bilinear filtering for this sound.
bool debug_lock_position; // If true, the vec will not be modified after the sound starts.
};
//-----------------------------------------------------------------------------
// Purpose: Each currently playing wave is stored in a channel
//-----------------------------------------------------------------------------
// NOTE: 128bytes. These are memset to zero at some points. Do not add virtuals without changing that pattern.
// UNDONE: now 300 bytes...
struct channel_t
{
int guid; // incremented each time a channel is allocated (to match with channel free in tools, etc.)
int userdata; // user specified data for syncing to tools
hrtf_info_t hrtf;
CSfxTable *sfx; // the actual sound
CAudioMixer *pMixer; // The sound's instance data for this channel
CSosOperatorStackList *m_pStackList; // The operator stack for this channel
HSOUNDSCRIPTHASH m_nSoundScriptHash;
// speaker channel volumes, indexed using IFRONT_LEFT to IFRONT_CENTER.
// NOTE: never access these fvolume[] elements directly! Use channel helpers in snd_dma.cpp.
float fvolume[CCHANVOLUMES]; // 0.0-255.0 current output volumes
float fvolume_target[CCHANVOLUMES]; // 0.0-255.0 target output volumes
float fvolume_inc[CCHANVOLUMES]; // volume increment, per frame, moves volume[i] to vol_target[i] (per spatialization)
SoundSource soundsource; // see iclientsound.h for description.
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
int speakerentity; // if a sound is being played through a speaker entity (e.g., on a monitor,), this is the
// entity upon which to show the lips moving, if the sound has sentence data
short master_vol; // 0-255 master volume
short basePitch; // base pitch percent (100% is normal pitch playback)
float pitch; // real-time pitch after any modulation or shift by dynamic data
int mixgroups[8]; // sound belongs to these mixgroups: world, actor, player weapon, explosion etc.
int last_mixgroupid;// last mixgroupid selected
float last_vol; // last volume after spatialization
Vector origin; // origin of sound effect
Vector direction; // direction of the sound
float dist_mult; // distance multiplier (attenuation/clipK)
float m_flSoundLevel; // storing actual spl to avoid switching back and forth from dist_mult
float dspmix; // 0 - 1.0 proportion of dsp to mix with original sound, based on distance
// NOTE: this gets multiplied by g_dsp_volume in snd_mix.cpp, which is a culum of
// other dsp setttings!
float dspface; // -1.0 - 1.0 (1.0 = facing listener)
float distmix; // 0 - 1.0 proportion based on distance from listner (1.0 - 100% wav right - far)
float dsp_mix_min; // for dspmix calculation - set by current preset in SND_GetDspMix
float dsp_mix_max; // for dspmix calculation - set by current preset in SND_GetDspMix
float radius; // Radius of this sound effect (spatialization is different within the radius)
gain_t gain[ MAX_SPLITSCREEN_CLIENTS ];
short activeIndex;
char wavtype; // 0 default, CHAR_DOPPLER, CHAR_DIRECTIONAL, CHAR_DISTVARIANT
char pad;
char sample_prev[8]; // last sample(s) in previous input data buffer - space for 2, 16 bit, stereo samples
int initialStreamPosition;
int skipInitialSamples;
union
{
unsigned int flagsword;
struct
{
bool bUpdatePositions : 1; // if true, assume sound source can move and update according to entity
bool isSentence : 1; // true if playing linked sentence
bool bdry : 1; // if true, bypass all dsp processing for this sound (ie: music)
bool bSpeaker : 1; // true if sound is playing through in-game speaker entity.
bool bstereowav : 1; // if true, a stereo .wav file is the sample data source
bool delayed_start : 1; // If true, sound had a delay and so same sound on same channel won't channel steal from it
bool fromserver : 1; // for snd_show, networked sounds get colored differently than local sounds
bool bfirstpass : 1; // true if this is first time sound is spatialized
bool bTraced : 1; // true if channel was already checked this frame for obscuring
bool bfast_pitch : 1; // true if using low quality pitch (fast, but no interpolation)
bool m_bIsFreeingChannel : 1; // true when inside S_FreeChannel - prevents reentrance
bool m_bCompatibilityAttenuation : 1; // True when we want to use goldsrc compatibility mode for the attenuation
// In that case, dist_mul is set to a relatively meaningful value in StartDynamic/StartStaticSound,
// but we interpret it totally differently in SND_GetGain.
bool m_bShouldPause : 1; // if true, sound should pause when the game is paused
bool m_bIgnorePhonemes : 1; // if true, we don't want to drive animation w/ phoneme data
bool m_bHasMouth : 1; // needs to output mouth records
bool m_bMouthEnvelope : 1; // needs mouth wave envelope follower
bool m_bShouldSaveRestore : 1; // Should be saved and restored
bool m_bUpdateDelayForChoreo : 1; // Should update snd_delay_for_choreo with IO latency.
bool m_bInEyeSound : 1; // This sound is playing from the viewpoint of the camera.
} flags;
};
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define MAX_CHANNELS 128
#define MAX_DYNAMIC_CHANNELS 32
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
extern channel_t channels[MAX_CHANNELS];
// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
// MAX_DYNAMIC_CHANNELS to total_channels = static sounds
extern int total_channels;
class CChannelList
{
public:
int Count();
int GetChannelIndex( int listIndex );
channel_t *GetChannel( int listIndex );
void RemoveChannelFromList( int listIndex );
bool IsQuashed( int listIndex );
int m_count;
short m_list[MAX_CHANNELS];
bool m_quashed[MAX_CHANNELS]; // if true, the channel should be advanced, but not mixed, because it's been heuristically suppressed
bool m_hasSpeakerChannels : 1;
bool m_hasDryChannels : 1;
bool m_has11kChannels : 1;
bool m_has22kChannels : 1;
bool m_has44kChannels : 1;
};
inline int CChannelList::Count()
{
return m_count;
}
inline int CChannelList::GetChannelIndex( int listIndex )
{
return m_list[listIndex];
}
inline channel_t *CChannelList::GetChannel( int listIndex )
{
return &channels[GetChannelIndex(listIndex)];
}
inline bool CChannelList::IsQuashed( int listIndex )
{
return m_quashed[listIndex];
}
inline void CChannelList::RemoveChannelFromList( int listIndex )
{
// decrease the count by one, and swap the deleted channel with
// the last one.
m_count--;
if ( m_count > 0 && listIndex != m_count )
{
m_list[listIndex] = m_list[m_count];
m_quashed[listIndex] = m_quashed[m_count];
}
}
struct activethreadsound_t
{
int m_nGuid;
float m_flElapsedTime;
};
class CActiveChannels
{
public:
void Add( channel_t *pChannel );
void Remove( channel_t *pChannel );
void GetActiveChannels( CChannelList &list ) const;
void CopyActiveSounds( CUtlVector<activethreadsound_t> &list ) const;
channel_t * FindActiveChannelByGuid( int guid ) const;
void DumpChannelInfo( CUtlBuffer &buf );
void Init();
int GetActiveCount() { return m_count; }
private:
int m_count;
short m_list[MAX_CHANNELS];
};
extern CActiveChannels g_ActiveChannels;
//=============================================================================
#endif // SND_CHANNELS_H

View File

@@ -0,0 +1,21 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_CONVARS_H
#define SND_CONVARS_H
#if defined( _WIN32 )
#pragma once
#endif
#include "convar.h"
extern ConVar snd_legacy_surround;
extern ConVar snd_surround;
extern ConVar snd_mix_async;
#endif // SND_CONVARS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Device Common Routines
//
//=====================================================================================//
#ifndef SND_DEV_COMMON_H
#define SND_DEV_COMMON_H
#pragma once
void DEBUG_DrawPanCurves(void);
#if USE_AUDIO_DEVICE_V1
class CAudioDeviceBase : public IAudioDevice
{
public:
virtual bool IsActive( void ) { return false; }
virtual bool Init( void ) { return false; }
virtual void Shutdown( void ) {}
virtual void Pause( void ) {}
virtual void UnPause( void ) {}
virtual int64 PaintBegin( float, int64 soundtime, int64 paintedtime ) { return 0; }
virtual void PaintEnd( void ) {}
virtual int GetOutputPosition( void ) { return 0; }
virtual void ClearBuffer( void ) {}
// virtual void TransferSamples( int64 end ) {}
virtual int DeviceSampleCount( void ) { return 0; }
};
#endif
extern void Device_MixUpsample( int sampleCount, int filtertype );
extern void Device_ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
extern void Device_SpatializeChannel( int nSlot, float volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono, int nWavType );
extern void Device_SpatializeChannel( int nSlot, float volume[CCHANVOLUMES/2], const Vector& sourceDir, float mono, float flRearToStereoScale = 0.75 );
extern void Device_Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
extern void Device_Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
extern void Device_Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
extern void Device_Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
#endif // SND_DEV_COMMON_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_DIRECT_H
#define SND_DEV_DIRECT_H
#pragma once
class IAudioDevice;
IAudioDevice *Audio_CreateDirectSoundDevice( void );
#endif // SND_DEV_DIRECT_H

View File

@@ -0,0 +1,481 @@
//===== Copyright (c) 1996-2010, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "audio_pch.h"
#include <AudioToolbox/AudioQueue.h>
#include <AudioToolbox/AudioFile.h>
#include <AudioToolbox/AudioFormat.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern bool snd_firsttime;
extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, int volume[CCHANVOLUMES], int mixchans );
#define NUM_BUFFERS_SOURCES 128
#define BUFF_MASK (NUM_BUFFERS_SOURCES - 1 )
#define BUFFER_SIZE 0x0400
//-----------------------------------------------------------------------------
//
// NOTE: This only allows 16-bit, stereo wave out
//
//-----------------------------------------------------------------------------
class CAudioDeviceAudioQueue : public CAudioDeviceBase
{
public:
CAudioDeviceAudioQueue()
{
m_pName = "AudioQueue";
m_nChannels = 2;
m_nSampleBits = 16;
m_nSampleRate = 44100;
m_bIsActive = true;
}
bool IsActive( void );
bool Init( void );
void Shutdown( void );
int GetOutputPosition( void );
void Pause( void );
void UnPause( void );
int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
void PaintEnd( void );
void ClearBuffer( void );
void UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up );
void TransferSamples( int end );
int DeviceSampleCount( void ) { return m_deviceSampleCount; }
void BufferCompleted() { m_buffersCompleted++; }
void SetRunning( bool bState ) { m_bRunning = bState; }
private:
void OpenWaveOut( void );
void CloseWaveOut( void );
bool ValidWaveOut( void ) const;
bool BIsPlaying();
AudioStreamBasicDescription m_DataFormat;
AudioQueueRef m_Queue;
AudioQueueBufferRef m_Buffers[NUM_BUFFERS_SOURCES];
int m_SndBufSize;
void *m_sndBuffers;
CInterlockedInt m_deviceSampleCount;
int m_buffersSent;
int m_buffersCompleted;
int m_pauseCount;
bool m_bSoundsShutdown;
bool m_bFailed;
bool m_bRunning;
bool m_bSurround;
bool m_bSurroundCenter;
bool m_bHeadphone;
};
CAudioDeviceAudioQueue *wave = NULL;
static void AudioCallback(void *pContext, AudioQueueRef pQueue, AudioQueueBufferRef pBuffer)
{
if ( wave )
wave->BufferCompleted();
}
IAudioDevice *Audio_CreateMacAudioQueueDevice( void )
{
wave = new CAudioDeviceAudioQueue;
if ( wave->Init() )
return wave;
delete wave;
wave = NULL;
return NULL;
}
void OnSndSurroundCvarChanged2( IConVar *pVar, const char *pOldString, float flOldValue );
void OnSndSurroundLegacyChanged2( IConVar *pVar, const char *pOldString, float flOldValue );
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CAudioDeviceAudioQueue::Init( void )
{
m_SndBufSize = 0;
m_sndBuffers = NULL;
m_pauseCount = 0;
m_bIsHeadphone = false;
m_buffersSent = 0;
m_buffersCompleted = 0;
m_pauseCount = 0;
m_bSoundsShutdown = false;
m_bFailed = false;
m_bRunning = false;
m_Queue = NULL;
static bool first = true;
if ( first )
{
snd_surround.SetValue( 2 );
snd_surround.InstallChangeCallback( &OnSndSurroundCvarChanged2 );
snd_legacy_surround.InstallChangeCallback( &OnSndSurroundLegacyChanged2 );
first = false;
}
OpenWaveOut();
if ( snd_firsttime )
{
DevMsg( "Wave sound initialized\n" );
}
return ValidWaveOut() && !m_bFailed;
}
void CAudioDeviceAudioQueue::Shutdown( void )
{
CloseWaveOut();
}
//-----------------------------------------------------------------------------
// WAV out device
//-----------------------------------------------------------------------------
inline bool CAudioDeviceAudioQueue::ValidWaveOut( void ) const
{
return m_sndBuffers != 0 && m_Queue;
}
//-----------------------------------------------------------------------------
// called by the mac audioqueue code when we run out of playback buffers
//-----------------------------------------------------------------------------
void AudioQueueIsRunningCallback( void* inClientData, AudioQueueRef inAQ, AudioQueuePropertyID inID)
{
CAudioDeviceAudioQueue* audioqueue = (CAudioDeviceAudioQueue*)inClientData;
UInt32 running = 0;
UInt32 size;
OSStatus err = AudioQueueGetProperty(inAQ, kAudioQueueProperty_IsRunning, &running, &size);
audioqueue->SetRunning( running != 0 );
//DevWarning( "AudioQueueStart %d\n", running );
}
//-----------------------------------------------------------------------------
// Opens the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceAudioQueue::OpenWaveOut( void )
{
if ( m_Queue )
return;
m_buffersSent = 0;
m_buffersCompleted = 0;
m_DataFormat.mSampleRate = SOUND_DMA_SPEED;
m_DataFormat.mFormatID = kAudioFormatLinearPCM;
m_DataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked;
m_DataFormat.mBytesPerPacket = 4; // 16-bit samples * 2 channels
m_DataFormat.mFramesPerPacket = 1;
m_DataFormat.mBytesPerFrame = 4; // 16-bit samples * 2 channels
m_DataFormat.mChannelsPerFrame = 2;
m_DataFormat.mBitsPerChannel = 16;
m_DataFormat.mReserved = 0;
// Create the audio queue that will be used to manage the array of audio
// buffers used to queue samples.
OSStatus err = AudioQueueNewOutput(&m_DataFormat, AudioCallback, this, NULL, NULL, 0, &m_Queue);
if ( err != noErr)
{
DevMsg( "Failed to create AudioQueue output %d\n", err );
m_bFailed = true;
return;
}
for ( int i = 0; i < NUM_BUFFERS_SOURCES; ++i)
{
err = AudioQueueAllocateBuffer( m_Queue, BUFFER_SIZE,&(m_Buffers[i]));
if ( err != noErr)
{
DevMsg( "Failed to AudioQueueAllocateBuffer output %d (%i)\n", err,i );
m_bFailed = true;
}
m_Buffers[i]->mAudioDataByteSize = BUFFER_SIZE;
Q_memset( m_Buffers[i]->mAudioData, 0, BUFFER_SIZE );
}
err = AudioQueuePrime( m_Queue, 0, NULL);
if ( err != noErr)
{
DevMsg( "Failed to create AudioQueue output %d\n", err );
m_bFailed = true;
return;
}
AudioQueueSetParameter( m_Queue, kAudioQueueParam_Volume, 1.0);
err = AudioQueueAddPropertyListener( m_Queue, kAudioQueueProperty_IsRunning, AudioQueueIsRunningCallback, this );
if ( err != noErr)
{
DevMsg( "Failed to create AudioQueue output %d\n", err );
m_bFailed = true;
return;
}
m_SndBufSize = NUM_BUFFERS_SOURCES*BUFFER_SIZE;
m_deviceSampleCount = m_SndBufSize / DeviceSampleBytes();
if ( !m_sndBuffers )
{
m_sndBuffers = malloc( m_SndBufSize );
memset( m_sndBuffers, 0x0, m_SndBufSize );
}
}
//-----------------------------------------------------------------------------
// Closes the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceAudioQueue::CloseWaveOut( void )
{
if ( ValidWaveOut() )
{
AudioQueueStop(m_Queue, true);
m_bRunning = false;
AudioQueueRemovePropertyListener( m_Queue, kAudioQueueProperty_IsRunning, AudioQueueIsRunningCallback, this );
for ( int i = 0; i < NUM_BUFFERS_SOURCES; i++ )
AudioQueueFreeBuffer( m_Queue, m_Buffers[i]);
AudioQueueDispose( m_Queue, true);
m_Queue = NULL;
}
if ( m_sndBuffers )
{
free( m_sndBuffers );
m_sndBuffers = NULL;
}
}
//-----------------------------------------------------------------------------
// Mixing setup
//-----------------------------------------------------------------------------
int64 CAudioDeviceAudioQueue::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
{
// soundtime - total samples that have been played out to hardware at dmaspeed
// paintedtime - total samples that have been mixed at speed
// endtime - target for samples in mixahead buffer at speed
int64 endtime = soundtime + mixAheadTime * SampleRate();
int samps = DeviceSampleCount() >> (ChannelCount()-1);
if ((int)(endtime - soundtime) > samps)
endtime = soundtime + samps;
if ((endtime - paintedtime) & 0x3)
{
// The difference between endtime and painted time should align on
// boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
endtime -= (endtime - paintedtime) & 0x3;
}
return endtime;
}
//-----------------------------------------------------------------------------
// Actually performs the mixing
//-----------------------------------------------------------------------------
void CAudioDeviceAudioQueue::PaintEnd( void )
{
int cblocks = 8 << 1;
//
// submit a few new sound blocks
//
// 44K sound support
while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
{
int iBuf = m_buffersSent&BUFF_MASK;
m_Buffers[iBuf]->mAudioDataByteSize = BUFFER_SIZE;
Q_memcpy( m_Buffers[iBuf]->mAudioData, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE);
// Queue the buffer for playback.
OSStatus err = AudioQueueEnqueueBuffer( m_Queue, m_Buffers[iBuf], 0, NULL);
if ( err != noErr)
{
DevMsg( "Failed to AudioQueueEnqueueBuffer output %d\n", err );
}
m_buffersSent++;
}
if ( !m_bRunning )
{
DevMsg( "Restarting sound playback\n" );
m_bRunning = true;
AudioQueueStart( m_Queue, NULL);
}
}
int CAudioDeviceAudioQueue::GetOutputPosition( void )
{
int s = m_buffersSent * BUFFER_SIZE;
s >>= SAMPLE_16BIT_SHIFT;
s &= (DeviceSampleCount()-1);
return s / ChannelCount();
}
//-----------------------------------------------------------------------------
// Pausing
//-----------------------------------------------------------------------------
void CAudioDeviceAudioQueue::Pause( void )
{
m_pauseCount++;
if (m_pauseCount == 1)
{
m_bRunning = false;
AudioQueueStop(m_Queue, true);
}
}
void CAudioDeviceAudioQueue::UnPause( void )
{
if ( m_pauseCount > 0 )
{
m_pauseCount--;
}
if ( m_pauseCount == 0 )
{
m_bRunning = true;
AudioQueueStart( m_Queue, NULL);
}
}
bool CAudioDeviceAudioQueue::IsActive( void )
{
return ( m_pauseCount == 0 );
}
void CAudioDeviceAudioQueue::ClearBuffer( void )
{
if ( !m_sndBuffers )
return;
Q_memset( m_sndBuffers, 0x0, DeviceSampleCount() * DeviceSampleBytes() );
}
void CAudioDeviceAudioQueue::UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up )
{
}
bool CAudioDeviceAudioQueue::BIsPlaying()
{
UInt32 isRunning;
UInt32 propSize = sizeof(isRunning);
OSStatus result = AudioQueueGetProperty( m_Queue, kAudioQueueProperty_IsRunning, &isRunning, &propSize);
return isRunning != 0;
}
void CAudioDeviceAudioQueue::TransferSamples( int end )
{
int64 lpaintedtime = g_paintedtime;
int64 endtime = end;
// resumes playback...
if ( m_sndBuffers )
{
S_TransferStereo16( m_sndBuffers, PAINTBUFFER, lpaintedtime, endtime );
}
}
static uint32 GetOSXSpeakerConfig()
{
return 2;
}
static uint32 GetSpeakerConfigForSurroundMode( int surroundMode, const char **pConfigDesc )
{
uint32 newSpeakerConfig = 2;
*pConfigDesc = "stereo speaker";
return newSpeakerConfig;
}
void OnSndSurroundCvarChanged2( IConVar *pVar, const char *pOldString, float flOldValue )
{
// if the old value is -1, we're setting this from the detect routine for the first time
// no need to reset the device
if ( flOldValue == -1 )
return;
// get the user's previous speaker config
uint32 speaker_config = GetOSXSpeakerConfig();
// get the new config
uint32 newSpeakerConfig = 0;
const char *speakerConfigDesc = "";
ConVarRef var( pVar );
newSpeakerConfig = GetSpeakerConfigForSurroundMode( var.GetInt(), &speakerConfigDesc );
// make sure the config has changed
if (newSpeakerConfig == speaker_config)
return;
// set new configuration
//SetWindowsSpeakerConfig(newSpeakerConfig);
Msg("Speaker configuration has been changed to %s.\n", speakerConfigDesc);
// restart sound system so it takes effect
//g_pSoundServices->RestartSoundSystem();
}
void OnSndSurroundLegacyChanged2( IConVar *pVar, const char *pOldString, float flOldValue )
{
}

View File

@@ -0,0 +1,14 @@
//========= Copyright (c) 1996-2010, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_MAC_AUDIOQUEUE_H
#define SND_DEV_MAC_AUDIOQUEUE_H
#pragma once
class IAudioDevice;
IAudioDevice *Audio_CreateMacAudioQueueDevice( void );
#endif // SND_DEV_MAC_AUDIOQUEUE_H

View File

@@ -0,0 +1,403 @@
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "audio_pch.h"
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern bool snd_firsttime;
#define NUM_BUFFERS_SOURCES 128
#define BUFF_MASK (NUM_BUFFERS_SOURCES - 1 )
#define BUFFER_SIZE 0x0400
//-----------------------------------------------------------------------------
//
// NOTE: This only allows 16-bit, stereo wave out
//
//-----------------------------------------------------------------------------
class CAudioDeviceOpenAL : public CAudioDeviceBase
{
public:
CAudioDeviceOpenAL()
{
m_pName = "OpenAL Audio";
m_nChannels = 2;
m_nSampleBits = 16;
m_nSampleRate = 44100;
m_bIsActive = true;
}
bool IsActive( void );
bool Init( void );
void Shutdown( void );
int GetOutputPosition( void );
void Pause( void );
void UnPause( void );
int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
void PaintEnd( void );
void ClearBuffer( void );
void UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up );
void TransferSamples( int end );
int DeviceSampleCount( void ) { return m_deviceSampleCount; }
private:
void OpenWaveOut( void );
void CloseWaveOut( void );
bool ValidWaveOut( void ) const;
ALuint m_Buffer[NUM_BUFFERS_SOURCES];
ALuint m_Source[1];
int m_SndBufSize;
void *m_sndBuffers;
int m_deviceSampleCount;
int m_buffersSent;
int m_buffersCompleted;
int m_pauseCount;
bool m_bHeadphone;
bool m_bSurround;
bool m_bSurroundCenter;
};
IAudioDevice *Audio_CreateOpenALDevice( void )
{
static CAudioDeviceOpenAL *wave = NULL;
if ( !wave )
{
wave = new CAudioDeviceOpenAL;
}
if ( wave->Init() )
return wave;
delete wave;
wave = NULL;
return NULL;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CAudioDeviceOpenAL::Init( void )
{
m_SndBufSize = 0;
m_sndBuffers = NULL;
m_pauseCount = 0;
m_bIsHeadphone = false;
m_buffersSent = 0;
m_buffersCompleted = 0;
m_pauseCount = 0;
OpenWaveOut();
if ( snd_firsttime )
{
DevMsg( "Wave sound initialized\n" );
}
return ValidWaveOut();
}
void CAudioDeviceOpenAL::Shutdown( void )
{
CloseWaveOut();
}
//-----------------------------------------------------------------------------
// WAV out device
//-----------------------------------------------------------------------------
inline bool CAudioDeviceOpenAL::ValidWaveOut( void ) const
{
return m_sndBuffers != 0;
}
//-----------------------------------------------------------------------------
// Opens the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceOpenAL::OpenWaveOut( void )
{
m_buffersSent = 0;
m_buffersCompleted = 0;
ALenum error;
ALCcontext *newContext = NULL;
ALCdevice *newDevice = NULL;
// Create a new OpenAL Device
// Pass NULL to specify the systemuse default output device
const ALCchar *initStr = (const ALCchar *)"\'( (sampling-rate 44100 ))";
newDevice = alcOpenDevice(initStr);
if (newDevice != NULL)
{
// Create a new OpenAL Context
// The new context will render to the OpenAL Device just created
ALCint attr[] = { ALC_FREQUENCY, SampleRate(), ALC_SYNC, AL_FALSE, 0 };
newContext = alcCreateContext(newDevice, attr );
if (newContext != NULL)
{
// Make the new context the Current OpenAL Context
alcMakeContextCurrent(newContext);
// Create some OpenAL Buffer Objects
alGenBuffers( NUM_BUFFERS_SOURCES, m_Buffer);
if((error = alGetError()) != AL_NO_ERROR)
{
DevMsg("Error Generating Buffers: ");
return;
}
// Create some OpenAL Source Objects
alGenSources(1, m_Source);
if(alGetError() != AL_NO_ERROR)
{
DevMsg("Error generating sources! \n");
return;
}
alListener3f( AL_POSITION,0.0f,0.0f,0.0f);
int i;
for ( i = 0; i < 1; i++ )
{
alSource3f( m_Source[i],AL_POSITION,0.0f,0.0f,0.0f );
alSourcef( m_Source[i], AL_PITCH, 1.0f );
alSourcef( m_Source[i], AL_GAIN, 1.0f );
}
}
}
m_SndBufSize = NUM_BUFFERS_SOURCES*BUFFER_SIZE;
m_deviceSampleCount = m_SndBufSize / DeviceSampleBytes();
if ( !m_sndBuffers )
{
m_sndBuffers = malloc( m_SndBufSize );
memset( m_sndBuffers, 0x0, m_SndBufSize );
}
}
//-----------------------------------------------------------------------------
// Closes the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceOpenAL::CloseWaveOut( void )
{
if ( ValidWaveOut() )
{
ALCcontext *context = NULL;
ALCdevice *device = NULL;
alSourceStop( m_Source[0] );
// Delete the Sources
alDeleteSources(1, m_Source);
// Delete the Buffers
alDeleteBuffers(NUM_BUFFERS_SOURCES, m_Buffer);
//Get active context
context = alcGetCurrentContext();
//Get device for active context
device = alcGetContextsDevice(context);
alcMakeContextCurrent( NULL );
alcSuspendContext(context);
//Release context
alcDestroyContext(context);
//Close device
alcCloseDevice(device);
}
if ( m_sndBuffers )
{
free( m_sndBuffers );
m_sndBuffers = NULL;
}
}
//-----------------------------------------------------------------------------
// Mixing setup
//-----------------------------------------------------------------------------
int64 CAudioDeviceOpenAL::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
{
// soundtime - total samples that have been played out to hardware at dmaspeed
// paintedtime - total samples that have been mixed at speed
// endtime - target for samples in mixahead buffer at speed
int64 endtime = soundtime + mixAheadTime * SampleRate();
int samps = DeviceSampleCount() >> (ChannelCount()-1);
if ((int)(endtime - soundtime) > samps)
endtime = soundtime + samps;
if ((endtime - paintedtime) & 0x3)
{
// The difference between endtime and painted time should align on
// boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
endtime -= (endtime - paintedtime) & 0x3;
}
return endtime;
}
//-----------------------------------------------------------------------------
// Actually performs the mixing
//-----------------------------------------------------------------------------
void CAudioDeviceOpenAL::PaintEnd( void )
{
if ( !m_sndBuffers )
return;
ALint state;
ALenum error;
int iloop;
int cblocks = 4 << 1;
ALint processed = 1;
while ( processed > 0 )
{
alGetSourcei( m_Source[ 0 ], AL_BUFFERS_PROCESSED, &processed);
if ( processed > 0 )
{
ALuint tempVal = 0;
alSourceUnqueueBuffers( m_Source[ 0 ], 1, &tempVal );
error = alGetError();
if ( error != AL_NO_ERROR && error != AL_INVALID_NAME )
{
DevMsg( "Error alSourceUnqueueBuffers %d\n", error );
}
else
{
m_buffersCompleted++; // this buffer has been played
}
}
}
//
// submit a few new sound blocks
//
// 44K sound support
while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
{
int iBuf = m_buffersSent&BUFF_MASK;
alBufferData( m_Buffer[iBuf], AL_FORMAT_STEREO16, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE, SampleRate() );
if ( (error = alGetError()) != AL_NO_ERROR )
{
DevMsg( "Error alBufferData %d %d\n", iBuf, error );
}
alSourceQueueBuffers( m_Source[0], 1, &m_Buffer[iBuf] );
if ( (error = alGetError() ) != AL_NO_ERROR )
{
DevMsg( "Error alSourceQueueBuffers %d %d\n", iBuf, error );
}
m_buffersSent++;
}
// make sure the stream is playing
alGetSourcei( m_Source[ 0 ], AL_SOURCE_STATE, &state);
if ( state != AL_PLAYING )
{
Warning( "Restarting sound playback\n" );
alSourcePlay( m_Source[0] );
if((error = alGetError()) != AL_NO_ERROR)
{
DevMsg( "Error alSourcePlay %d\n", error );
}
}
}
int CAudioDeviceOpenAL::GetOutputPosition( void )
{
int s = m_buffersSent * BUFFER_SIZE;
s >>= SAMPLE_16BIT_SHIFT;
s &= (DeviceSampleCount()-1);
return s / ChannelCount();
}
//-----------------------------------------------------------------------------
// Pausing
//-----------------------------------------------------------------------------
void CAudioDeviceOpenAL::Pause( void )
{
m_pauseCount++;
if (m_pauseCount == 1)
{
alSourceStop( m_Source[0] );
}
}
void CAudioDeviceOpenAL::UnPause( void )
{
if ( m_pauseCount > 0 )
{
m_pauseCount--;
}
if ( m_pauseCount == 0 )
alSourcePlay( m_Source[0] );
}
bool CAudioDeviceOpenAL::IsActive( void )
{
return ( m_pauseCount == 0 );
}
void CAudioDeviceOpenAL::ClearBuffer( void )
{
if ( !m_sndBuffers )
return;
Q_memset( m_sndBuffers, 0x0, DeviceSampleCount() * DeviceSampleBytes() );
}
void CAudioDeviceOpenAL::UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up )
{
}
void CAudioDeviceOpenAL::TransferSamples( int end )
{
int64 lpaintedtime = g_paintedtime;
int64 endtime = end;
// resumes playback...
if ( m_sndBuffers )
{
S_TransferStereo16( m_sndBuffers, PAINTBUFFER, lpaintedtime, endtime );
}
}

View File

@@ -0,0 +1,14 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_OPENAL_H
#define SND_DEV_OPENAL_H
#pragma once
class IAudioDevice;
IAudioDevice *Audio_CreateOpenALDevice( void );
#endif // SND_DEV_OPENAL_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_PS3AUDIO_H
#define SND_DEV_PS3AUDIO_H
#pragma once
#include "audio_pch.h"
#include "inetmessage.h"
#include "netmessages.h"
#include "engine/ienginevoice.h"
class IAudioDevice;
IAudioDevice *Audio_CreatePS3AudioDevice( bool bInitVoice );
#define PS3_SUPPORT_XVOICE
#ifdef PS3_SUPPORT_XVOICE
class CEngineVoicePs3 : public IEngineVoice
{
public:
CEngineVoicePs3();
static const float MAX_VOICE_BUFFER_TIME = 0.200f; // 200ms
void VoiceInit( void );
void VoiceShutdown( void );
void AddPlayerToVoiceList( XUID xPlayer, int iController, uint64 uiFlags );
void RemovePlayerFromVoiceList( XUID xPlayer, int iController );
bool VoiceUpdateData( int iCtrlr );
void GetVoiceData( int iCtrlr, CCLCMsg_VoiceData_t *pData );
void GetVoiceData( int iController, const byte **ppvVoiceDataBuffer, unsigned int *pnumVoiceDataBytes );
void VoiceSendData( int iCtrlr, INetChannel *pChannel );
void VoiceResetLocalData( int iCtrlr );
void PlayIncomingVoiceData( XUID xuid, const byte *pbData, unsigned int dwDataSize, const bool *bAudiblePlayers = NULL );
void UpdateHUDVoiceStatus( void );
void GetRemoteTalkers( int *pNumTalkers, XUID *pRemoteTalkers );
void SetPlaybackPriority( XUID remoteTalker, int iController, int iAllowPlayback );
bool IsLocalPlayerTalking( int controlerID );
bool IsPlayerTalking( XUID uid );
bool IsHeadsetPresent( int id );
void RemoveAllTalkers();
void PlayPortInterruptHandler();
private:
// Local chat data
static const uint8 m_numVoiceUsers = 1;
inline int GetVoiceUserIndex( int iController ) const { return 0; }
inline int GetVoiceDeviceNumber( int iController ) const { return 0; }
static const WORD m_ChatBufferSize = 16*1024;
BYTE m_ChatBuffer[ m_numVoiceUsers ][ m_ChatBufferSize ];
WORD m_wLocalDataSize[ m_numVoiceUsers ];
enum VoiceState_t
{
kVoiceNotInitialized,
kVoiceInit,
kVoiceOpen
};
VoiceState_t m_bUserRegistered[ m_numVoiceUsers ]; //This is to handle a bug in UnregisterLocalTalker where it crashes on
//unregistering a local talker who has not been registered if the
//controller id is non-0.
// Last voice data sent
float m_dwLastVoiceSend[ m_numVoiceUsers ];
//
// PS3 playback parameters
//
int CreateVoicePortsLocal( uint64 uiFlags );
uint32 m_memContainer;
uint32 m_portIMic, m_portOVoice, m_portIVoiceEcho, m_portOPcm, m_portOEarphone, m_portOSendForRemote;
struct RemoteTalker_t
{
XUID m_xuid;
uint32 m_portIRemoteVoice;
uint64 m_uiFlags;
float m_flLastTalkTimestamp;
};
int CreateVoicePortsRemote( RemoteTalker_t &rt );
CUtlVector< RemoteTalker_t > m_arrRemoteTalkers;
};
CEngineVoicePs3 *Audio_GetXVoice( void );
#endif
#endif // SND_DEV_PS3AUDIO_H

View File

@@ -0,0 +1,751 @@
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "audio_pch.h"
#if !DEDICATED
#include "tier0/dynfunction.h"
#include "avi/ibik.h"
// prevent some conflicts in SDL headers...
#undef M_PI
#include <stdint.h>
#ifndef _STDINT_H_
#define _STDINT_H_ 1
#endif
#include "SDL.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IVEngineClient* engineClient;
extern bool snd_firsttime;
extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, int volume[CCHANVOLUMES], int mixchans );
extern void S_SpatializeChannel( int nSlot, int volume[6], int master_vol, const Vector *psourceDir, float gain, float mono );
ConVar snd_mute_losefocus("snd_mute_losefocus", "1", FCVAR_ARCHIVE);
static ConVar sdl_speaker_channels( "sdl_speaker_channels", "-1", FCVAR_RELEASE|FCVAR_ARCHIVE );
static void OnSDLSpeakerChannelsChanged( IConVar *pVar, const char *pOldString, float flOldValue )
{
if ( atoi( pOldString ) != sdl_speaker_channels.GetInt() )
{
g_pSoundServices->RestartSoundSystem();
}
}
// 64K is about 1/3 second at 16-bit, stereo, 44100 Hz
// 44k: UNDONE - need to double buffers now that we're playing back at 44100?
#define WAV_BUFFERS 64
#define WAV_MASK (WAV_BUFFERS - 1)
#define WAV_BUFFER_SIZE 0x0400
#if 0
#define debugsdl printf
#else
static inline void debugsdl(const char *fmt, ...) {}
#endif
//-----------------------------------------------------------------------------
//
// NOTE: This only allows 16-bit, stereo wave out (!!! FIXME: but SDL supports 7.1, etc, too!)
//
//-----------------------------------------------------------------------------
class CAudioDeviceSDLAudio : public CAudioDeviceBase
{
public:
CAudioDeviceSDLAudio();
virtual ~CAudioDeviceSDLAudio();
bool IsActive( void );
bool Init( void );
void Shutdown( void );
void PaintEnd( void );
int GetOutputPosition( void );
void ChannelReset( int entnum, int channelIndex, float distanceMod );
void Pause( void );
void UnPause( void );
float MixDryVolume( void );
bool Should3DMix( void );
void StopAllSounds( void );
int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
void ClearBuffer( void );
void MixBegin( int sampleCount );
void MixUpsample( int sampleCount, int filtertype );
void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void TransferSamples( int end );
void SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
const char *DeviceName( void ) { return "SDL"; }
int DeviceChannels( void ) { return m_numChannels; }
int DeviceSampleBits( void ) { return 16; }
int DeviceSampleBytes( void ) { return 2; }
int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
int DeviceSampleCount( void ) { return m_deviceSampleCount; }
private:
SDL_AudioDeviceID m_devId;
static void SDLCALL AudioCallbackEntry(void *userdata, Uint8 * stream, int len);
void AudioCallback(Uint8 *stream, int len);
void OpenWaveOut( void );
void CloseWaveOut( void );
void AllocateOutputBuffers();
void FreeOutputBuffers();
bool ValidWaveOut( void ) const;
void TransferSurround16( void *pOutput, const portable_samplepair_t *pfront, const portable_samplepair_t *prear, const portable_samplepair_t *pcenter, int64 lpaintedtime, int64 endtime, int nChannels);
int m_numChannels;
int m_deviceSampleCount;
int m_buffersSent;
int m_pauseCount;
int m_readPos;
int m_partialWrite;
// Memory for the wave data
uint8_t *m_pBuffer;
bool m_bSurround;
bool m_bSurroundCenter;
bool m_bHeadphone;
};
static CAudioDeviceSDLAudio *g_wave = NULL;
//-----------------------------------------------------------------------------
// Constructor (just lookup SDL entry points, real work happens in this->Init())
//-----------------------------------------------------------------------------
CAudioDeviceSDLAudio::CAudioDeviceSDLAudio()
{
m_devId = 0;
m_numChannels = 2;
}
//-----------------------------------------------------------------------------
// Destructor. Make sure our global pointer gets set to NULL.
//-----------------------------------------------------------------------------
CAudioDeviceSDLAudio::~CAudioDeviceSDLAudio()
{
g_wave = NULL;
}
//-----------------------------------------------------------------------------
// Class factory
//-----------------------------------------------------------------------------
IAudioDevice *Audio_CreateSDLAudioDevice( void )
{
if ( !g_wave )
{
g_wave = new CAudioDeviceSDLAudio;
Assert( g_wave );
}
if ( g_wave && !g_wave->Init() )
{
delete g_wave;
g_wave = NULL;
}
return g_wave;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CAudioDeviceSDLAudio::Init( void )
{
// If we've already got a device open, then return. This allows folks to call
// Audio_CreateSDLAudioDevice() multiple times. CloseWaveOut() will free the
// device, and set m_devId to 0.
if( m_devId )
return true;
m_bSurround = false;
m_bSurroundCenter = false;
m_bHeadphone = false;
m_buffersSent = 0;
m_pauseCount = 0;
m_pBuffer = NULL;
m_readPos = 0;
m_partialWrite = 0;
m_devId = 0;
OpenWaveOut();
if ( snd_firsttime )
{
DevMsg( "Wave sound initialized\n" );
}
return ValidWaveOut();
}
void CAudioDeviceSDLAudio::Shutdown( void )
{
CloseWaveOut();
}
//-----------------------------------------------------------------------------
// WAV out device
//-----------------------------------------------------------------------------
inline bool CAudioDeviceSDLAudio::ValidWaveOut( void ) const
{
return m_devId != 0;
}
//-----------------------------------------------------------------------------
// Opens the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceSDLAudio::OpenWaveOut( void )
{
debugsdl("SDLAUDIO: OpenWaveOut...\n");
#ifndef WIN32
// Set these environment variables, in case we're using PulseAudio.
const char *appname = "Counter-Strike: Global Offensive"; // !!! FIXME: get this from elsewhere.
setenv("PULSE_PROP_application.name", appname, 1);
setenv("PULSE_PROP_media.role", "game", 1);
#endif
// !!! FIXME: specify channel map, etc
// !!! FIXME: set properties (role, icon, etc).
//#define SDLAUDIO_FAIL(fnstr) do { DevWarning(fnstr " failed"); CloseWaveOut(); return; } while (false)
//#define SDLAUDIO_FAIL(fnstr) do { printf("SDLAUDIO: " fnstr " failed: %s\n", SDL_GetError ? SDL_GetError() : "???"); CloseWaveOut(); return; } while (false)
#define SDLAUDIO_FAIL(fnstr) do { printf("SDLAUDIO: " fnstr " failed: %s\n", SDL_GetError() ); CloseWaveOut(); return; } while (false)
if (!SDL_WasInit(SDL_INIT_AUDIO))
{
if (SDL_InitSubSystem(SDL_INIT_AUDIO))
SDLAUDIO_FAIL("SDL_InitSubSystem(SDL_INIT_AUDIO)");
}
char target[128];
debugsdl("SDLAUDIO: Using SDL audio target '%s'\n", SDL_GetCurrentAudioDriver());
int nChannelsDesired = sdl_speaker_channels.GetInt();
if ( nChannelsDesired == 1 )
{
//This really means 'headphones' which we want 2 channels for
nChannelsDesired = 2;
m_bHeadphone = true;
}
else if ( nChannelsDesired <= 0 )
{
nChannelsDesired = 6;
}
// Open an audio device...
// !!! FIXME: let user specify a device?
// !!! FIXME: we can handle quad, 5.1, 7.1, etc here.
SDL_AudioSpec obtained;
m_devId = 0;
for ( m_devId = 0; m_devId == 0 && nChannelsDesired > 0; nChannelsDesired -= 2 )
{
SDL_AudioSpec desired;
memset(&desired, '\0', sizeof (desired));
desired.freq = SOUND_DMA_SPEED;
desired.format = AUDIO_S16SYS;
desired.samples = 2048;
desired.channels = nChannelsDesired;
desired.callback = &CAudioDeviceSDLAudio::AudioCallbackEntry;
desired.userdata = this;
m_devId = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
}
if (!m_devId)
SDLAUDIO_FAIL("SDL_OpenAudioDevice()");
m_bSurround = obtained.channels >= 4;
m_bSurroundCenter = obtained.channels >= 6;
m_numChannels = obtained.channels;
if ( sdl_speaker_channels.GetInt() == 1 && m_numChannels == 2 )
{
//'headphones' setting.
sdl_speaker_channels.SetValue( 1 );
}
else
{
sdl_speaker_channels.SetValue( m_numChannels );
}
#undef SDLAUDIO_FAIL
// We're now ready to feed audio data to SDL!
AllocateOutputBuffers();
SDL_PauseAudioDevice(m_devId, 0);
#if defined( BINK_VIDEO ) && defined( LINUX )
// Tells Bink to use SDL for its audio decoding
if ( g_pBIK && g_pBIK->SetSDLDevice( obtained.freq, obtained.format, obtained.channels ) == 0 )
{
Assert( 0 );
}
#endif
static bool first_time = true;
if ( first_time )
{
first_time = false;
sdl_speaker_channels.InstallChangeCallback( &OnSDLSpeakerChannelsChanged );
}
}
//-----------------------------------------------------------------------------
// Closes the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceSDLAudio::CloseWaveOut( void )
{
// none of these SDL_* functions are available to call if this is false.
if (m_devId)
{
SDL_CloseAudioDevice(m_devId);
m_devId = 0;
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
FreeOutputBuffers();
}
//-----------------------------------------------------------------------------
// Allocate output buffers
//-----------------------------------------------------------------------------
void CAudioDeviceSDLAudio::AllocateOutputBuffers()
{
// Allocate and lock memory for the waveform data.
const int nBufferSize = (WAV_BUFFER_SIZE * WAV_BUFFERS * DeviceChannels())/2;
m_pBuffer = new uint8_t[nBufferSize];
memset(m_pBuffer, '\0', nBufferSize);
m_readPos = 0;
m_partialWrite = 0;
m_deviceSampleCount = nBufferSize / DeviceSampleBytes();
}
//-----------------------------------------------------------------------------
// Free output buffers
//-----------------------------------------------------------------------------
void CAudioDeviceSDLAudio::FreeOutputBuffers()
{
delete[] m_pBuffer;
m_pBuffer = NULL;
}
//-----------------------------------------------------------------------------
// Mixing setup
//-----------------------------------------------------------------------------
int64 CAudioDeviceSDLAudio::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
{
// soundtime - total samples that have been played out to hardware at dmaspeed
// paintedtime - total samples that have been mixed at speed
// endtime - target for samples in mixahead buffer at speed
unsigned int endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
int samps = DeviceSampleCount() / DeviceChannels();
if ((int)(endtime - soundtime) > samps)
endtime = soundtime + samps;
if ((endtime - paintedtime) & 0x3)
{
// The difference between endtime and painted time should align on
// boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
endtime -= (endtime - paintedtime) & 0x3;
}
return endtime;
}
void CAudioDeviceSDLAudio::AudioCallbackEntry(void *userdata, Uint8 *stream, int len)
{
((CAudioDeviceSDLAudio *) userdata)->AudioCallback(stream, len);
}
void CAudioDeviceSDLAudio::AudioCallback(Uint8 *stream, int len)
{
if (!m_devId)
{
debugsdl("SDLAUDIO: uhoh, no audio device!\n");
return; // can this even happen?
}
const int totalWriteable = len;
Uint8 *stream_orig = stream;
debugsdl("SDLAUDIO: writable size is %d.\n", totalWriteable);
Assert(len <= (WAV_BUFFERS * WAV_BUFFER_SIZE));
while (len > 0)
{
// spaceAvailable == bytes before we overrun the end of the ring buffer.
const int spaceAvailable = ((WAV_BUFFERS * WAV_BUFFER_SIZE * DeviceChannels())/2 - m_readPos);
const int writeLen = (len < spaceAvailable) ? len : spaceAvailable;
if (writeLen > 0)
{
const uint8_t *buf = m_pBuffer + m_readPos;
debugsdl("SDLAUDIO: Writing %d bytes...\n", writeLen);
#if 0
static FILE *io = NULL;
if (io == NULL) io = fopen("dumpplayback.raw", "wb");
if (io != NULL) { fwrite(buf, writeLen, 1, io); fflush(io); }
#endif
if ( engineClient->IsActiveApp() == false && snd_mute_losefocus.GetBool() )
{
// The game is in the background and we are set to mute
// while in background so just play silence.
memset(stream, 0, writeLen);
}
else
{
memcpy(stream, buf, writeLen);
}
stream += writeLen;
len -= writeLen;
Assert(len >= 0);
}
m_readPos = (m_readPos + writeLen) % ((WAV_BUFFERS * WAV_BUFFER_SIZE * DeviceChannels())/2); // if still bytes to write to stream, we're rolling around the ring buffer.
}
#if defined( BINK_VIDEO ) && defined( LINUX )
// Mix in Bink movie audio if that stuff is playing.
g_pBIK->SDLMixerAudioCallback( stream_orig, totalWriteable );
#endif
// Translate between bytes written and buffers written.
m_partialWrite += totalWriteable;
m_buffersSent += m_partialWrite / WAV_BUFFER_SIZE;
m_partialWrite %= WAV_BUFFER_SIZE;
}
//-----------------------------------------------------------------------------
// Actually performs the mixing
//-----------------------------------------------------------------------------
void CAudioDeviceSDLAudio::PaintEnd( void )
{
debugsdl("SDLAUDIO: PaintEnd...\n");
#if 0 // !!! FIXME: this is the 1.3 headers, but not implemented yet in SDL.
if (SDL_AudioDeviceConnected(m_devId) != 1)
{
debugsdl("SDLAUDIO: Audio device was disconnected!\n");
Shutdown();
}
#endif
}
int CAudioDeviceSDLAudio::GetOutputPosition( void )
{
return (m_readPos >> SAMPLE_16BIT_SHIFT)/DeviceChannels();
}
//-----------------------------------------------------------------------------
// Pausing
//-----------------------------------------------------------------------------
void CAudioDeviceSDLAudio::Pause( void )
{
m_pauseCount++;
if (m_pauseCount == 1)
{
debugsdl("SDLAUDIO: PAUSE\n");
SDL_PauseAudioDevice(m_devId, 1);
}
}
void CAudioDeviceSDLAudio::UnPause( void )
{
if ( m_pauseCount > 0 )
{
m_pauseCount--;
if (m_pauseCount == 0)
{
debugsdl("SDLAUDIO: UNPAUSE\n");
SDL_PauseAudioDevice(m_devId, 0);
}
}
}
bool CAudioDeviceSDLAudio::IsActive( void )
{
return ( m_pauseCount == 0 );
}
float CAudioDeviceSDLAudio::MixDryVolume( void )
{
return 0;
}
bool CAudioDeviceSDLAudio::Should3DMix( void )
{
return false;
}
void CAudioDeviceSDLAudio::ClearBuffer( void )
{
int clear;
if ( !m_pBuffer )
return;
clear = 0;
Q_memset(m_pBuffer, clear, DeviceSampleCount() * DeviceSampleBytes() );
}
void CAudioDeviceSDLAudio::MixBegin( int sampleCount )
{
MIX_ClearAllPaintBuffers( sampleCount, false );
}
void CAudioDeviceSDLAudio::MixUpsample( int sampleCount, int filtertype )
{
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
int ifilter = ppaint->ifilter;
Assert (ifilter < CPAINTFILTERS);
S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
S_MixBufferUpsample2x( sampleCount, ppaint->pbufrear, &(ppaint->fltmemrear[ifilter][0]), CPAINTFILTERMEM, filtertype );
if ( ppaint->fsurround_center )
{
Assert( ppaint->pbufcenter );
S_MixBufferUpsample2x( sampleCount, ppaint->pbufcenter, &(ppaint->fltmemcenter[ifilter][0]), CPAINTFILTERMEM, filtertype );
}
}
ppaint->ifilter++;
}
void CAudioDeviceSDLAudio::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
return;
Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
Mix8MonoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround_center )
{
Assert( ppaint->pbufcenter );
Mix8MonoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], (byte *)pData, inputOffset, rateScaleFix, outCount );
}
}
}
void CAudioDeviceSDLAudio::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
return;
Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
Mix8StereoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround_center )
{
Assert( ppaint->pbufcenter );
Mix8StereoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], (byte *)pData, inputOffset, rateScaleFix, outCount );
}
}
}
void CAudioDeviceSDLAudio::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
return;
Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
Mix16MonoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround_center )
{
Assert( ppaint->pbufcenter );
Mix16MonoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], pData, inputOffset, rateScaleFix, outCount );
}
}
}
void CAudioDeviceSDLAudio::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
return;
Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
Mix16StereoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround_center )
{
Assert( ppaint->pbufcenter );
Mix16StereoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], pData, inputOffset, rateScaleFix, outCount );
}
}
}
void CAudioDeviceSDLAudio::ChannelReset( int entnum, int channelIndex, float distanceMod )
{
}
void CAudioDeviceSDLAudio::TransferSamples( int end )
{
int lpaintedtime = g_paintedtime;
int endtime = end;
// resumes playback...
if ( m_pBuffer )
{
if ( m_bSurround )
{
TransferSurround16( m_pBuffer, PAINTBUFFER, REARPAINTBUFFER, CENTERPAINTBUFFER, lpaintedtime, endtime, DeviceChannels() );
}
else
{
S_TransferStereo16( m_pBuffer, PAINTBUFFER, lpaintedtime, endtime );
}
}
}
void CAudioDeviceSDLAudio::SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
{
VPROF("CAudioDeviceSDLAudio::SpatializeChannel");
S_SpatializeChannel( nSlot, volume, master_vol, &sourceDir, gain, mono );
}
void CAudioDeviceSDLAudio::StopAllSounds( void )
{
}
void CAudioDeviceSDLAudio::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
{
//SX_RoomFX( endtime, filter, timefx );
DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
}
void CAudioDeviceSDLAudio::TransferSurround16( void *pOutput, const portable_samplepair_t *pfront, const portable_samplepair_t *prear, const portable_samplepair_t *pcenter, int64 lpaintedtime, int64 endtime, int nChannels)
{
const int volume = S_GetMasterVolume()*256;
const int* snd_front = (const int*)pfront;
const int* snd_rear = (const int*)prear;
const int* snd_center = (const int*)pcenter;
const int numSamples = (WAV_BUFFER_SIZE * WAV_BUFFERS)/4;
while(lpaintedtime < endtime)
{
const int lpos = lpaintedtime % numSamples;
int64 snd_linear_count = numSamples - lpos;
if ( snd_linear_count > endtime - lpaintedtime )
{
snd_linear_count = endtime - lpaintedtime;
}
short *snd_out = (short *)pOutput + lpos*nChannels;
for ( int i = 0; i < snd_linear_count; ++i )
{
const short* base = snd_out;
*snd_out++ = (snd_front[i*2] * volume) >> 8;
*snd_out++ = (snd_front[i*2+1] * volume) >> 8;
if ( nChannels >= 6 )
{
*snd_out++ = (snd_center[i*2] * volume) >> 8;
*snd_out++ = 0;
}
if ( nChannels >= 4 )
{
*snd_out++ = (snd_rear[i*2] * volume) >> 8;
*snd_out++ = (snd_rear[i*2+1] * volume) >> 8;
}
while ( snd_out - base < nChannels )
{
*snd_out++ = 0;
}
}
lpaintedtime += snd_linear_count;
snd_front += snd_linear_count*2;
snd_rear += snd_linear_count*2;
snd_center += snd_linear_count*2;
}
}
#endif // !DEDICATED

View File

@@ -0,0 +1,16 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_SDL_H
#define SND_DEV_SDL_H
#pragma once
class IAudioDevice;
IAudioDevice *Audio_CreateSDLAudioDevice( void );
#endif // SND_DEV_SDL_H

View File

@@ -0,0 +1,563 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "audio_pch.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern bool snd_firsttime;
extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, float volume[CCHANVOLUMES], int mixchans );
//extern void S_SpatializeChannel( int nSlot, int volume[6], int master_vol, const Vector *psourceDir, float gain, float mono );
// 64K is > 1 second at 16-bit, 22050 Hz
// 44k: UNDONE - need to double buffers now that we're playing back at 44100?
#define WAV_BUFFERS 64
#define WAV_MASK 0x3F
#define WAV_BUFFER_SIZE 0x0400
//-----------------------------------------------------------------------------
//
// NOTE: This only allows 16-bit, stereo wave out
//
//-----------------------------------------------------------------------------
class CAudioDeviceWave : public CAudioDeviceBase
{
public:
bool IsActive( void );
bool Init( void );
void Shutdown( void );
void PaintEnd( void );
int GetOutputPosition( void );
void ChannelReset( int entnum, int channelIndex, float distanceMod );
void Pause( void );
void UnPause( void );
float MixDryVolume( void );
bool Should3DMix( void );
void StopAllSounds( void );
int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
void ClearBuffer( void );
void MixBegin( int sampleCount );
void MixUpsample( int sampleCount, int filtertype );
void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
void TransferSamples( int end );
// void SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
const char *DeviceName( void ) { return "Windows WAVE"; }
int DeviceChannels( void ) { return 2; }
int DeviceSampleBits( void ) { return 16; }
int DeviceSampleBytes( void ) { return 2; }
int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
int DeviceSampleCount( void ) { return m_deviceSampleCount; }
private:
void OpenWaveOut( void );
void CloseWaveOut( void );
void AllocateOutputBuffers();
void FreeOutputBuffers();
void* AllocOutputMemory( int nSize, HGLOBAL &hMemory );
void FreeOutputMemory( HGLOBAL &hMemory );
bool ValidWaveOut( void ) const;
int m_deviceSampleCount;
int m_buffersSent;
int m_buffersCompleted;
int m_pauseCount;
// This is a single allocation for all wave headers (there are OUTPUT_BUFFER_COUNT of them)
HGLOBAL m_hWaveHdr;
// This is a single allocation for all wave data (there are OUTPUT_BUFFER_COUNT of them)
HANDLE m_hWaveData;
HWAVEOUT m_waveOutHandle;
// Memory for the wave data + wave headers
void *m_pBuffer;
LPWAVEHDR m_pWaveHdr;
};
//-----------------------------------------------------------------------------
// Class factory
//-----------------------------------------------------------------------------
IAudioDevice *Audio_CreateWaveDevice( void )
{
static CAudioDeviceWave *wave = NULL;
if ( !wave )
{
wave = new CAudioDeviceWave;
}
if ( wave->Init() )
return wave;
delete wave;
wave = NULL;
return NULL;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CAudioDeviceWave::Init( void )
{
m_buffersSent = 0;
m_buffersCompleted = 0;
m_pauseCount = 0;
m_waveOutHandle = 0;
m_pBuffer = NULL;
m_pWaveHdr = NULL;
m_hWaveHdr = NULL;
m_hWaveData = NULL;
OpenWaveOut();
if ( snd_firsttime )
{
DevMsg( "Wave sound initialized\n" );
}
return ValidWaveOut();
}
void CAudioDeviceWave::Shutdown( void )
{
CloseWaveOut();
}
//-----------------------------------------------------------------------------
// WAV out device
//-----------------------------------------------------------------------------
inline bool CAudioDeviceWave::ValidWaveOut( void ) const
{
return m_waveOutHandle != 0;
}
//-----------------------------------------------------------------------------
// Opens the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceWave::OpenWaveOut( void )
{
WAVEFORMATEX waveFormat;
memset( &waveFormat, 0, sizeof(waveFormat) );
// Select a PCM, 16-bit stereo playback device
waveFormat.cbSize = sizeof(waveFormat);
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = DeviceChannels();
waveFormat.wBitsPerSample = DeviceSampleBits();
waveFormat.nSamplesPerSec = DeviceDmaSpeed(); // DeviceSampleRate
waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
MMRESULT errorCode = waveOutOpen( &m_waveOutHandle, WAVE_MAPPER, &waveFormat, 0, 0L, CALLBACK_NULL );
while ( errorCode != MMSYSERR_NOERROR )
{
if ( errorCode != MMSYSERR_ALLOCATED )
{
DevWarning( "waveOutOpen failed\n" );
m_waveOutHandle = 0;
return;
}
int nRetVal = MessageBox( NULL,
"The sound hardware is in use by another app.\n\n"
"Select Retry to try to start sound again or Cancel to run with no sound.",
"Sound not available",
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION);
if ( nRetVal != IDRETRY )
{
DevWarning( "waveOutOpen failure--hardware already in use\n" );
m_waveOutHandle = 0;
return;
}
errorCode = waveOutOpen( &m_waveOutHandle, WAVE_MAPPER, &waveFormat, 0, 0L, CALLBACK_NULL );
}
AllocateOutputBuffers();
}
//-----------------------------------------------------------------------------
// Closes the windows wave out device
//-----------------------------------------------------------------------------
void CAudioDeviceWave::CloseWaveOut( void )
{
if ( ValidWaveOut() )
{
waveOutReset( m_waveOutHandle );
FreeOutputBuffers();
waveOutClose( m_waveOutHandle );
m_waveOutHandle = NULL;
}
}
//-----------------------------------------------------------------------------
// Alloc output memory
//-----------------------------------------------------------------------------
void* CAudioDeviceWave::AllocOutputMemory( int nSize, HGLOBAL &hMemory )
{
// Output memory for waveform data+hdrs must be
// globally allocated with GMEM_MOVEABLE and GMEM_SHARE flags.
hMemory = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, nSize );
if ( !hMemory )
{
DevWarning( "Sound: Out of memory.\n");
CloseWaveOut();
return NULL;
}
HPSTR lpData = (char *)GlobalLock( hMemory );
if ( !lpData )
{
DevWarning( "Sound: Failed to lock.\n");
GlobalFree( hMemory );
hMemory = NULL;
CloseWaveOut();
return NULL;
}
memset( lpData, 0, nSize );
return lpData;
}
//-----------------------------------------------------------------------------
// Free output memory
//-----------------------------------------------------------------------------
void CAudioDeviceWave::FreeOutputMemory( HGLOBAL &hMemory )
{
if ( hMemory )
{
GlobalUnlock( hMemory );
GlobalFree( hMemory );
hMemory = NULL;
}
}
//-----------------------------------------------------------------------------
// Allocate output buffers
//-----------------------------------------------------------------------------
void CAudioDeviceWave::AllocateOutputBuffers()
{
// Allocate and lock memory for the waveform data.
int nBufferSize = WAV_BUFFER_SIZE * WAV_BUFFERS;
HPSTR lpData = (char *)AllocOutputMemory( nBufferSize, m_hWaveData );
if ( !lpData )
return;
// Allocate and lock memory for the waveform header
int nHdrSize = sizeof( WAVEHDR ) * WAV_BUFFERS;
LPWAVEHDR lpWaveHdr = (LPWAVEHDR)AllocOutputMemory( nHdrSize, m_hWaveHdr );
if ( !lpWaveHdr )
return;
// After allocation, set up and prepare headers.
for ( int i=0 ; i < WAV_BUFFERS; i++ )
{
LPWAVEHDR lpHdr = lpWaveHdr + i;
lpHdr->dwBufferLength = WAV_BUFFER_SIZE;
lpHdr->lpData = lpData + (i * WAV_BUFFER_SIZE);
MMRESULT nResult = waveOutPrepareHeader( m_waveOutHandle, lpHdr, sizeof(WAVEHDR) );
if ( nResult != MMSYSERR_NOERROR )
{
DevWarning( "Sound: failed to prepare wave headers\n" );
CloseWaveOut();
return;
}
}
m_deviceSampleCount = nBufferSize / DeviceSampleBytes();
m_pBuffer = (void *)lpData;
m_pWaveHdr = lpWaveHdr;
}
//-----------------------------------------------------------------------------
// Free output buffers
//-----------------------------------------------------------------------------
void CAudioDeviceWave::FreeOutputBuffers()
{
// Unprepare headers.
if ( m_pWaveHdr )
{
for ( int i=0 ; i < WAV_BUFFERS; i++ )
{
waveOutUnprepareHeader( m_waveOutHandle, m_pWaveHdr+i, sizeof(WAVEHDR) );
}
}
m_pWaveHdr = NULL;
m_pBuffer = NULL;
FreeOutputMemory( m_hWaveData );
FreeOutputMemory( m_hWaveHdr );
}
//-----------------------------------------------------------------------------
// Mixing setup
//-----------------------------------------------------------------------------
int64 CAudioDeviceWave::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
{
// soundtime - total samples that have been played out to hardware at dmaspeed
// paintedtime - total samples that have been mixed at speed
// endtime - target for samples in mixahead buffer at speed
int64 endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
int samps = DeviceSampleCount() >> (DeviceChannels()-1);
if ((int)(endtime - soundtime) > samps)
endtime = soundtime + samps;
if ((endtime - paintedtime) & 0x3)
{
// The difference between endtime and painted time should align on
// boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
endtime -= (endtime - paintedtime) & 0x3;
}
return endtime;
}
//-----------------------------------------------------------------------------
// Actually performs the mixing
//-----------------------------------------------------------------------------
void CAudioDeviceWave::PaintEnd( void )
{
LPWAVEHDR h;
int wResult;
int cblocks;
//
// find which sound blocks have completed
//
while (1)
{
if ( m_buffersCompleted == m_buffersSent )
{
//DevMsg ("Sound overrun\n");
break;
}
if ( ! (m_pWaveHdr[ m_buffersCompleted & WAV_MASK].dwFlags & WHDR_DONE) )
{
break;
}
m_buffersCompleted++; // this buffer has been played
}
//
// submit a few new sound blocks
//
// 22K sound support
// 44k: UNDONE - double blocks out now that we're at 44k playback?
cblocks = 4 << 1;
while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
{
h = m_pWaveHdr + ( m_buffersSent&WAV_MASK );
m_buffersSent++;
/*
* Now the data block can be sent to the output device. The
* waveOutWrite function returns immediately and waveform
* data is sent to the output device in the background.
*/
wResult = waveOutWrite( m_waveOutHandle, h, sizeof(WAVEHDR) );
if (wResult != MMSYSERR_NOERROR)
{
Warning( "Failed to write block to device\n");
Shutdown();
return;
}
}
}
int CAudioDeviceWave::GetOutputPosition( void )
{
int s = m_buffersSent * WAV_BUFFER_SIZE;
s >>= SAMPLE_16BIT_SHIFT;
s &= (DeviceSampleCount()-1);
return s / DeviceChannels();
}
//-----------------------------------------------------------------------------
// Pausing
//-----------------------------------------------------------------------------
void CAudioDeviceWave::Pause( void )
{
m_pauseCount++;
if (m_pauseCount == 1)
{
waveOutReset( m_waveOutHandle );
}
}
void CAudioDeviceWave::UnPause( void )
{
if ( m_pauseCount > 0 )
{
m_pauseCount--;
}
}
bool CAudioDeviceWave::IsActive( void )
{
return ( m_pauseCount == 0 );
}
float CAudioDeviceWave::MixDryVolume( void )
{
return 0;
}
bool CAudioDeviceWave::Should3DMix( void )
{
return false;
}
void CAudioDeviceWave::ClearBuffer( void )
{
int clear;
if ( !m_pBuffer )
return;
clear = 0;
Q_memset(m_pBuffer, clear, DeviceSampleCount() * DeviceSampleBytes() );
}
void CAudioDeviceWave::MixBegin( int sampleCount )
{
MIX_ClearAllPaintBuffers( sampleCount, false );
}
void CAudioDeviceWave::MixUpsample( int sampleCount, int filtertype )
{
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
int ifilter = ppaint->ifilter;
Assert (ifilter < CPAINTFILTERS);
S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
ppaint->ifilter++;
}
void CAudioDeviceWave::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
float volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
return;
Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
}
void CAudioDeviceWave::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
float volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
return;
Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
}
void CAudioDeviceWave::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
float volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
return;
Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
}
void CAudioDeviceWave::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
float volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
return;
Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
}
void CAudioDeviceWave::ChannelReset( int entnum, int channelIndex, float distanceMod )
{
}
void CAudioDeviceWave::TransferSamples( int end )
{
int64 lpaintedtime = g_paintedtime;
int64 endtime = end;
// resumes playback...
if ( m_pBuffer )
{
S_TransferStereo16( m_pBuffer, PAINTBUFFER, lpaintedtime, endtime );
}
}
// temporarily deprecating to be sure which version of SpatializeChannel is used
/*void CAudioDeviceWave::SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
{
VPROF("CAudioDeviceWave::SpatializeChannel");
S_SpatializeChannel( nSlot, volume, master_vol, &sourceDir, gain, mono );
}
*/
void CAudioDeviceWave::StopAllSounds( void )
{
}
void CAudioDeviceWave::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
{
//SX_RoomFX( endtime, filter, timefx );
DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
}

View File

@@ -0,0 +1,14 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_WAVE_H
#define SND_DEV_WAVE_H
#pragma once
class IAudioDevice;
IAudioDevice *Audio_CreateWaveDevice( void );
#endif // SND_DEV_WAVE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef SND_DEV_XAUDIO_H
#define SND_DEV_XAUDIO_H
#pragma once
#include "audio_pch.h"
#include "inetmessage.h"
#include "netmessages.h"
#include "engine/ienginevoice.h"
class IAudioDevice;
IAudioDevice *Audio_CreateXAudioDevice( bool bInitVoice );
#if defined ( _X360 )
class CXboxVoice : public IEngineVoice
{
public:
CXboxVoice();
static const DWORD MAX_VOICE_BUFFER_TIME = 200; // 200ms
void VoiceInit( void );
void VoiceShutdown( void );
void AddPlayerToVoiceList( XUID xPlayer, int iController, uint64 uiFlags );
void RemovePlayerFromVoiceList( XUID xPlayer, int iController );
bool VoiceUpdateData( int iCtrlr );
void GetVoiceData( int iCtrlr, CCLCMsg_VoiceData_t *pData );
void GetVoiceData( int iController, const byte **ppvVoiceDataBuffer, unsigned int *pnumVoiceDataBytes );
void VoiceSendData( int iCtrlr, INetChannel *pChannel );
void VoiceResetLocalData( int iCtrlr );
void PlayIncomingVoiceData( XUID xuid, const byte *pbData, unsigned int dwDataSize, const bool *bAudiblePlayers = NULL );
void UpdateHUDVoiceStatus( void );
void GetRemoteTalkers( int *pNumTalkers, XUID *pRemoteTalkers );
void SetPlaybackPriority( XUID remoteTalker, int iController, int iAllowPlayback );
bool IsLocalPlayerTalking( int controlerID );
bool IsPlayerTalking( XUID uid );
bool IsHeadsetPresent( int id );
void RemoveAllTalkers();
private:
PIXHV2ENGINE m_pXHVEngine;
// Local chat data
static const WORD m_ChatBufferSize = XHV_VOICECHAT_MODE_PACKET_SIZE * XHV_MAX_VOICECHAT_PACKETS;
BYTE m_ChatBuffer[ XUSER_MAX_COUNT ][ m_ChatBufferSize ];
WORD m_wLocalDataSize[ XUSER_MAX_COUNT ];
bool m_bUserRegistered[ XUSER_MAX_COUNT ]; //This is to handle a bug in UnregisterLocalTalker where it crashes on
//unregistering a local talker who has not been registered if the
//controller id is non-0.
// Last voice data sent
DWORD m_dwLastVoiceSend[ XUSER_MAX_COUNT ];
};
CXboxVoice *Audio_GetXVoice( void );
IXAudio2 *Audio_GetXAudio2( void );
#endif
#endif // SND_DEV_XAUDIO_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_DMA_H
#define SND_DMA_H
#ifdef _WIN32
#pragma once
#endif
extern ConVar snd_obscured_gain_db;
extern ConVar snd_showstart;
extern ConVar snd_refdb;
extern ConVar snd_refdist;
extern float snd_refdb_dist_mult;
extern bool snd_initialized;
extern int g_snd_trace_count;
// convert sound db level to approximate sound source radius,
// used only for determining how much of sound is obscured by world
#define SND_RADIUS_MAX (20.0 * 12.0) // max sound source radius
#define SND_RADIUS_MIN (2.0 * 12.0) // min sound source radius
#define SND_DB_MAX 140.0 // max db of any sound source
#define SND_DB_MED 90.0 // db at which compression curve changes
#define SND_DB_MIN 60.0 // min db of any sound source
inline float dB_To_Radius ( float db )
{
return SND_RADIUS_MIN + (SND_RADIUS_MAX - SND_RADIUS_MIN) * (db - SND_DB_MIN) / (SND_DB_MAX - SND_DB_MIN);
}
class CScratchPad;
const int MASK_BLOCK_AUDIO = CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW;
#define SNDLVL_TO_DIST_MULT( sndlvl ) ( sndlvl ? ((snd_refdb_dist_mult / FastPow10( (float)sndlvl / 20 )) / snd_refdist.GetFloat()) : 0 )
#define DIST_MULT_TO_SNDLVL( dist_mult ) (soundlevel_t)(int)( dist_mult ? ( 20 * log10( (float)(snd_refdb_dist_mult / (dist_mult * snd_refdist.GetFloat()) )) ) : 0 )
float SND_GetGainFromMult( float gain, float dist_mult, vec_t dist );
float SND_GetDspMix( channel_t *pchannel, int idist, float flSndlvl );
bool SND_ChannelOkToTrace( channel_t *ch );
float SND_GetGainObscured( int nSlot, gain_t *gs, const channel_t *ch, const Vector &vecListenerOrigin, bool fplayersound, bool flooping, bool bAttenuated, bool bOkayToTrace, Vector *pOrigin = NULL );
float S_GetDashboarMusicMixValue( );
float SND_GetFacingDirection( channel_t *pChannel, const Vector &vecListenerOrigin, const QAngle &source_angles );
void SND_MergeVolumes( const float build_volumes[ MAX_SPLITSCREEN_CLIENTS ][CCHANVOLUMES/2], float volumes[CCHANVOLUMES/2] );
void ConvertListenerVectorTo2D( Vector *pvforward, const Vector *pvright );
void ChannelSetVolTargets( channel_t *pch, float *pvolumes, int ivol_offset, int cvol );
void S_StartSoundEntryByHash( HSOUNDSCRIPTHASH nHandle );
channel_t *S_FindChannelByScriptHash( HSOUNDSCRIPTHASH nHandle );
void S_StopChannel( channel_t *pChannel );
channel_t *S_FindChannelByGuid( int guid );
bool SND_IsInGame();
float SND_FadeToNewGain( gain_t *gs, const channel_t *ch, float gain_new );
bool SND_IsLongWave( channel_t pChannel );
float dB_To_Gain( float );
#endif // SND_DMA_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_ENV_FX_H
#define SND_ENV_FX_H
#if defined( _WIN32 )
#pragma once
#endif
//=====================================================================
// FX presets
//=====================================================================
#define SXROOM_OFF 0
#define SXROOM_GENERIC 1 // general, low reflective, diffuse room
#define SXROOM_METALIC_S 2 // highly reflective, parallel surfaces
#define SXROOM_METALIC_M 3
#define SXROOM_METALIC_L 4
#define SXROOM_TUNNEL_S 5 // resonant reflective, long surfaces
#define SXROOM_TUNNEL_M 6
#define SXROOM_TUNNEL_L 7
#define SXROOM_CHAMBER_S 8 // diffuse, moderately reflective surfaces
#define SXROOM_CHAMBER_M 9
#define SXROOM_CHAMBER_L 10
#define SXROOM_BRITE_S 11 // diffuse, highly reflective
#define SXROOM_BRITE_M 12
#define SXROOM_BRITE_L 13
#define SXROOM_WATER1 14 // underwater fx
#define SXROOM_WATER2 15
#define SXROOM_WATER3 16
#define SXROOM_CONCRETE_S 17 // bare, reflective, parallel surfaces
#define SXROOM_CONCRETE_M 18
#define SXROOM_CONCRETE_L 19
#define SXROOM_OUTSIDE1 20 // echoing, moderately reflective
#define SXROOM_OUTSIDE2 21 // echoing, dull
#define SXROOM_OUTSIDE3 22 // echoing, very dull
#define SXROOM_CAVERN_S 23 // large, echoing area
#define SXROOM_CAVERN_M 24
#define SXROOM_CAVERN_L 25
#define SXROOM_WEIRDO1 26
#define SXROOM_WEIRDO2 27
#define SXROOM_WEIRDO3 28
#define CSXROOM 29
#endif // SND_ENV_FX_H

View File

@@ -0,0 +1,40 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_FIXEDINT_H
#define SND_FIXEDINT_H
#if defined( _WIN32 )
#pragma once
#endif
// fixed point stuff for real-time resampling
#define FIX_BITS 28
#define FIX_SCALE (1 << FIX_BITS)
#define FIX_MASK ((1 << FIX_BITS)-1)
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE))
#define FIX(a) (((int)(a)) << FIX_BITS)
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS)
#define FIX_FRACTION(a,b) (FIX(a)/(b))
#define FIX_FRACPART(a) ((a) & FIX_MASK)
#define FIX_TODOUBLE(a) ((double)(a) / (double)FIX_SCALE)
typedef unsigned int fixedint;
#define FIX_BITS14 14
#define FIX_SCALE14 (1 << FIX_BITS14)
#define FIX_MASK14 ((1 << FIX_BITS14)-1)
#define FIX_FLOAT14(a) ((int)((a) * FIX_SCALE14))
#define FIX14(a) (((int)(a)) << FIX_BITS14)
#define FIX_INTPART14(a) (((int)(a)) >> FIX_BITS14)
#define FIX_FRACTION14(a,b) (FIX14(a)/(b))
#define FIX_FRACPART14(a) ((a) & FIX_MASK14)
#define FIX_14TODOUBLE(a) ((double)(a) / (double)FIX_SCALE14)
#define FIX_28TO14(a) ( (int)( ((unsigned int)(a)) >> (FIX_BITS - 14) ) )
#endif // SND_FIXEDINT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,107 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_MIX_BUF_H
#define SND_MIX_BUF_H
#if defined( _WIN32 )
#pragma once
#endif
// OPTIMIZE: note that making this larger will not increase performance (12/27/03)
#define PAINTBUFFER_SIZE 1020 // 44k: was 512
#define PAINTBUFFER (g_curpaintbuffer)
#define REARPAINTBUFFER (g_currearpaintbuffer)
#define CENTERPAINTBUFFER (g_curcenterpaintbuffer)
#define CPAINTBUFFERS 6
// !!! if this is changed, it much be changed in native assembly too !!!
struct portable_samplepair_t
{
int left;
int right;
};
// This should match the struct portable_samplepair_t
enum Channels
{
CHANNEL_LEFT = 0,
CHANNEL_RIGHT = 1,
};
// sound mixing buffer
#define CPAINTFILTERMEM 3
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
struct paintbuffer_t
{
bool factive; // if true, mix to this paintbuffer using flags
bool fsurround; // if true, mix to front and rear paintbuffers using flags
bool fsurround_center; // if true, mix to front, rear and center paintbuffers using flags
int flags; // SOUND_BUSS_ROOM, SOUND_BUSS_FACING, SOUND_BUSS_FACINGAWAY, SOUND_BUSS_SPEAKER, SOUND_BUSS_DRY
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
portable_samplepair_t *pbufrear; // rear mix buffer, for 4 channel mixing
portable_samplepair_t *pbufcenter; // center mix buffer, for 5 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM]; // filter memory, for upsampling with linear or cubic interpolation
portable_samplepair_t fltmemrear[CPAINTFILTERS][CPAINTFILTERMEM]; // filter memory, for upsampling with linear or cubic interpolation
portable_samplepair_t fltmemcenter[CPAINTFILTERS][CPAINTFILTERMEM]; // filter memory, for upsampling with linear or cubic interpolation
};
extern "C"
{
extern portable_samplepair_t *g_paintbuffer;
// temp paintbuffer - not included in main list of paintbuffers
extern portable_samplepair_t *g_temppaintbuffer;
extern paintbuffer_t *g_paintBuffers;
extern void MIX_SetCurrentPaintbuffer( int ipaintbuffer );
extern int MIX_GetCurrentPaintbufferIndex( void );
extern paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void );
extern void MIX_ClearAllPaintBuffers( int SampleCount, bool clearFilters );
extern bool MIX_InitAllPaintbuffers(void);
extern void MIX_FreeAllPaintbuffers(void);
extern portable_samplepair_t *g_curpaintbuffer;
extern portable_samplepair_t *g_currearpaintbuffer;
extern portable_samplepair_t *g_curcenterpaintbuffer;
};
// must be at least PAINTBUFFER_SIZE+1 for upsampling
#define PAINTBUFFER_MEM_SIZE (PAINTBUFFER_SIZE+4)
// size in samples of copy buffer used by pitch shifters in mixing
#if defined(_GAMECONSOLE)
#define TEMP_COPY_BUFFER_SIZE (PAINTBUFFER_MEM_SIZE * 2)
#else
// allow more memory for this on PC for developers to pitch-shift their way through dialog
#define TEMP_COPY_BUFFER_SIZE (PAINTBUFFER_MEM_SIZE * 4)
#endif
// hard clip input value to -32767 <= y <= 32767
#define CLIP(x) ((x) > 32767 ? 32767 : ((x) < -32767 ? -32767 : (x)))
// Branch-less version of CLIP on PPC - Much better.
FORCEINLINE
int iclip( int nInput )
{
int nResult = iclamp( nInput, -32767, +32767 ); // Interestingly it should actually be -32768 but the old code did not use the correct value. Keep the old value for the moment.
Assert( nResult == CLIP( nInput ) );
return nResult;
}
#endif // SND_MIX_BUF_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_MIXGROUP_MANAGER_H
#define SND_MIXGROUP_MANAGER_H
#ifdef _WIN32
#pragma once
#endif
enum MXRMixGroupFields_t
{
MXR_MIXGROUP_NONE = 0,
MXR_MIXGROUP_VOL,
MXR_MIXGROUP_LEVEL,
MXR_MIXGROUP_DSP,
MXR_MIXGROUP_SOLO,
MXR_MIXGROUP_MUTE
};
struct mixervalues_t
{
//public:
float volume;
float level;
float dsp;
mixervalues_t(void)
{
volume = 1.0;
level = 1.0;
dsp = 1.0;
}
};
void MXR_SetSoloActive(void);
bool MXR_LoadAllSoundMixers( void );
void MXR_ReleaseMemory( void );
int MXR_GetMixGroupListFromDirName( const char *pDirname, byte *pList, int listMax );
bool MXR_IsMusicGroup( int ruleIndex );
void MXR_GetMixGroupFromSoundsource( channel_t *pchan );
void MXR_GetValuesFromMixGroupIndex( mixervalues_t *mixValues, int imixgroup );
void MXR_GetVolFromMixGroup( channel_t *ch, mixervalues_t *mixValues, int *plast_mixgroupid );
char *MXR_GetGroupnameFromId( int mixgroupid );
int MXR_GetMixgroupFromName( const char *pszgroupname );
int MXR_GetFirstValidMixGroup( channel_t *pChannel );
void MXR_DebugShowMixVolumes( void );
#ifdef _DEBUG
void MXR_DebugSetMixGroupVolume( const CCommand &args );
#endif //_DEBUG
static void MXR_SetSoundMixer( const CCommand &args );
static void MXR_ListMixGroups( const CCommand &args );
void MXR_UpdateAllDuckerVolumes( void );
// // sound mixers
// int g_csoundmixers = 0; // total number of soundmixers found
// extern int g_cgrouprules; // total number of group rules found
// int g_cgroupclass = 0;
int MXR_GetMixLayerIndexFromName( const char *szmixlayername );
void S_SetMixGroupOfMixLayer( int nMixGroupIndex, int nMixLayerIndex, MXRMixGroupFields_t nMixGroupField, float flValue );
#endif // SND_MIXGROUP_MANAGER_H

View File

@@ -0,0 +1,392 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "audio_pch.h"
#include "snd_mp3_source.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CAudioSourceMP3::CAudioSourceMP3( CSfxTable *pSfx )
{
m_sampleRate = 44100;
m_pSfx = pSfx;
m_refCount = 0;
m_dataStart = 0;
char nameBuf[MAX_PATH];
FileHandle_t file = g_pSndIO->open( pSfx->GetFileName( nameBuf, sizeof(nameBuf) ) );
if ( (intp)file != -1 )
{
m_dataSize = g_pSndIO->size( file );
g_pSndIO->close( file );
}
else
{
m_dataSize = 0;
}
m_nCachedDataSize = 0;
m_bIsPlayOnce = false;
m_bIsSentenceWord = false;
}
CAudioSourceMP3::CAudioSourceMP3( CSfxTable *pSfx, CAudioSourceCachedInfo *info )
{
m_sampleRate = 44100;
m_pSfx = pSfx;
m_refCount = 0;
m_dataSize = info->DataSize();
m_dataStart = info->DataStart();
m_nCachedDataSize = 0;
m_bIsPlayOnce = false;
}
CAudioSourceMP3::~CAudioSourceMP3()
{
}
// mixer's references
void CAudioSourceMP3::ReferenceAdd( CAudioMixer * )
{
m_refCount++;
}
void CAudioSourceMP3::ReferenceRemove( CAudioMixer * )
{
m_refCount--;
if ( m_refCount == 0 && IsPlayOnce() )
{
SetPlayOnce( false ); // in case it gets used again
CacheUnload();
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CAudioSourceMP3::IsAsyncLoad()
{
if ( !m_AudioCacheHandle.IsValid() )
{
m_AudioCacheHandle.Get( GetType(), m_pSfx->IsPrecachedSound(), m_pSfx, &m_nCachedDataSize );
}
// If there's a bit of "cached data" then we don't have to lazy/async load (we still async load the remaining data,
// but we run from the cache initially)
return ( m_nCachedDataSize > 0 ) ? false : true;
}
// check reference count, return true if nothing is referencing this
bool CAudioSourceMP3::CanDelete( void )
{
return m_refCount > 0 ? false : true;
}
bool CAudioSourceMP3::GetStartupData()
{
char nameBuf[MAX_PATH];
FileHandle_t file = g_pSndIO->open( m_pSfx->GetFileName( nameBuf, sizeof(nameBuf) ) );
if ( !file )
{
return false;
}
m_dataSize = (int)g_pSndIO->size( file );
g_pSndIO->close( file );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CAudioSourceMP3::GetType()
{
return AUDIO_SOURCE_MP3;
}
void CAudioSourceMP3::GetCacheData( CAudioSourceCachedInfo *info )
{
info->SetSampleRate( m_sampleRate );
info->SetDataStart( 0 );
GetStartupData();
// Data size gets computed in GetStartupData!!!
info->SetDataSize( m_dataSize );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
char const *CAudioSourceMP3::GetFileName( char *pOutBuf, size_t bufLen )
{
return m_pSfx ? m_pSfx->GetFileName(pOutBuf, bufLen) : "NULL m_pSfx";
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAudioSourceMP3::CheckAudioSourceCache()
{
Assert( m_pSfx );
if ( !m_pSfx->IsPrecachedSound() )
{
return;
}
// This will "re-cache" this if it's not in this level's cache already
m_AudioCacheHandle.Get( GetType(), true, m_pSfx, &m_nCachedDataSize );
}
//-----------------------------------------------------------------------------
// Purpose: NULL the wave data pointer (we haven't loaded yet)
//-----------------------------------------------------------------------------
CAudioSourceMP3Cache::CAudioSourceMP3Cache( CSfxTable *pSfx ) :
CAudioSourceMP3( pSfx )
{
m_hCache = 0;
}
CAudioSourceMP3Cache::CAudioSourceMP3Cache( CSfxTable *pSfx, CAudioSourceCachedInfo *info ) :
CAudioSourceMP3( pSfx, info )
{
m_hCache = 0;
m_dataSize = info->DataSize();
m_dataStart = info->DataStart();
}
//-----------------------------------------------------------------------------
// Purpose: Free any wave data we've allocated
//-----------------------------------------------------------------------------
CAudioSourceMP3Cache::~CAudioSourceMP3Cache( void )
{
CacheUnload();
}
int CAudioSourceMP3Cache::GetCacheStatus( void )
{
bool bCacheValid;
int loaded = wavedatacache->IsDataLoadCompleted( m_hCache, &bCacheValid ) ? AUDIO_IS_LOADED : AUDIO_NOT_LOADED;
if ( !bCacheValid )
{
char nameBuf[MAX_PATH];
wavedatacache->RestartDataLoad( &m_hCache, m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), m_dataSize, m_dataStart );
}
return loaded;
}
void CAudioSourceMP3Cache::CacheLoad( void )
{
// Commence lazy load?
if ( m_hCache != 0 )
{
GetCacheStatus();
return;
}
char nameBuf[MAX_PATH];
m_hCache = wavedatacache->AsyncLoadCache( m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), m_dataSize, m_dataStart );
}
void CAudioSourceMP3Cache::CacheUnload( void )
{
if ( m_hCache != 0 )
{
wavedatacache->Unload( m_hCache );
}
}
char *CAudioSourceMP3Cache::GetDataPointer( void )
{
char *pMP3Data = NULL;
bool dummy = false;
if ( m_hCache == 0 )
{
CacheLoad();
}
char nameBuf[MAX_PATH];
wavedatacache->GetDataPointer(
m_hCache,
m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)),
m_dataSize,
m_dataStart,
(void **)&pMP3Data,
0,
&dummy );
return pMP3Data;
}
int CAudioSourceMP3Cache::GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
{
// how many bytes are available ?
int totalSampleCount = m_dataSize - samplePosition;
// may be asking for a sample out of range, clip at zero
if ( totalSampleCount < 0 )
totalSampleCount = 0;
// clip max output samples to max available
if ( sampleCount > totalSampleCount )
sampleCount = totalSampleCount;
// if we are returning some samples, store the pointer
if ( sampleCount )
{
// Starting past end of "preloaded" data, just use regular cache
if ( samplePosition >= m_nCachedDataSize )
{
*pData = GetDataPointer();
}
else
{
// Start async loader if we haven't already done so
CacheLoad();
// Return less data if we are about to run out of uncached data
if ( samplePosition + sampleCount >= m_nCachedDataSize )
{
sampleCount = m_nCachedDataSize - samplePosition;
}
// Point at preloaded/cached data from .cache file for now
*pData = GetCachedDataPointer();
}
if ( *pData )
{
*pData = (char *)*pData + samplePosition;
}
else
{
// Out of data or file i/o problem
sampleCount = 0;
}
}
return sampleCount;
}
CAudioMixer *CAudioSourceMP3Cache::CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, hrtf_info_t *pHRTFVector )
{
CAudioMixer *pMixer = CreateMP3Mixer( CreateWaveDataMemory(*this), &m_sampleRate );
if ( pMixer )
{
ReferenceAdd( pMixer );
soundError = SE_OK;
}
else
{
soundError = SE_CANT_CREATE_MIXER;
}
return pMixer;
}
CAudioSourceStreamMP3::CAudioSourceStreamMP3( CSfxTable *pSfx ) :
CAudioSourceMP3( pSfx )
{
}
CAudioSourceStreamMP3::CAudioSourceStreamMP3( CSfxTable *pSfx, CAudioSourceCachedInfo *info ) :
CAudioSourceMP3( pSfx, info )
{
m_dataSize = info->DataSize();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAudioSourceStreamMP3::Prefetch()
{
char nameBuf[MAX_PATH];
PrefetchDataStream( m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), 0, m_dataSize );
}
CAudioMixer *CAudioSourceStreamMP3::CreateMixer(int intialStreamPosition, int initialSkipSamples, bool bUpdateDelayForChoreo, SoundError &soundError, hrtf_info_t *pHRTFVector )
{
char nameBuf[MAX_PATH];
// BUGBUG: Source constructs the IWaveData, mixer frees it, fix this?
IWaveData *pWaveData = CreateWaveDataStream(*this, static_cast<IWaveStreamSource *>(this), m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), 0, m_dataSize, m_pSfx, 0, 0, soundError );
if ( pWaveData )
{
CAudioMixer *pMixer = CreateMP3Mixer( pWaveData, &m_sampleRate );
if ( pMixer )
{
ReferenceAdd( pMixer );
soundError = SE_OK;
return pMixer;
}
// no mixer but pWaveData was deleted in mixer's destructor
// so no need to delete
}
soundError = SE_CANT_CREATE_MIXER;
return NULL;
}
int CAudioSourceStreamMP3::GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
{
return 0;
}
bool Audio_IsMP3( const char *pName )
{
int len = strlen(pName);
if ( len > 4 )
{
if ( !Q_strnicmp( &pName[len - 4], ".mp3", 4 ) )
{
return true;
}
}
return false;
}
CAudioSource *Audio_CreateStreamedMP3( CSfxTable *pSfx )
{
CAudioSourceStreamMP3 *pMP3 = NULL;
CAudioSourceCachedInfo *info = audiosourcecache->GetInfo( CAudioSource::AUDIO_SOURCE_MP3, pSfx->IsPrecachedSound(), pSfx );
if ( info && info->DataSize() != 0 )
{
pMP3 = new CAudioSourceStreamMP3( pSfx, info );
}
else
{
pMP3 = new CAudioSourceStreamMP3( pSfx );
}
return pMP3;
}
CAudioSource *Audio_CreateMemoryMP3( CSfxTable *pSfx )
{
CAudioSourceMP3Cache *pMP3 = NULL;
CAudioSourceCachedInfo *info = audiosourcecache->GetInfo( CAudioSource::AUDIO_SOURCE_MP3, pSfx->IsPrecachedSound(), pSfx );
if ( info )
{
pMP3 = new CAudioSourceMP3Cache( pSfx, info );
}
else
{
pMP3 = new CAudioSourceMP3Cache( pSfx );
}
return pMP3;
}

View File

@@ -0,0 +1,185 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SND_MP3_SOURCE_H
#define SND_MP3_SOURCE_H
#ifdef _WIN32
#pragma once
#endif
#include "snd_audio_source.h"
#include "snd_wave_data.h"
#include "snd_sfx.h"
class IWaveData;
class CAudioMixer;
abstract_class CAudioSourceMP3 : public CAudioSource
{
public:
CAudioSourceMP3( CSfxTable *pSfx );
CAudioSourceMP3( CSfxTable *pSfx, CAudioSourceCachedInfo *info );
virtual ~CAudioSourceMP3();
// Create an instance (mixer) of this audio source
virtual CAudioMixer *CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, struct hrtf_info_t* pHRTFVec ) = 0;
virtual int GetType( void );
virtual void GetCacheData( CAudioSourceCachedInfo *info );
// Provide samples for the mixer. You can point pData at your own data, or if you prefer to copy the data,
// you can copy it into copyBuf and set pData to copyBuf.
virtual int GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] ) = 0;
virtual int SampleRate( void ) { return m_sampleRate; }
// Returns true if the source is a voice source.
// This affects the voice_overdrive behavior (all sounds get quieter when
// someone is speaking).
virtual bool IsVoiceSource() { return false; }
virtual bool IsPlayerVoice() { return false; }
virtual int SampleSize( void ) { return 1; }
// Total number of samples in this source. NOTE: Some sources are infinite (mic input), they should return
// a count equal to one second of audio at their current rate.
virtual int SampleCount( void ) { return m_dataSize; }
virtual int Format() { return 0; }
virtual int DataSize( void ) { return 0; }
virtual bool IsLooped( void ) { return false; }
virtual bool IsStereoWav( void ) { return false; }
virtual bool IsStreaming( void ) { return false; }
virtual int GetCacheStatus( void ) { return AUDIO_IS_LOADED; }
virtual void CacheLoad( void ) {}
virtual void CacheUnload( void ) {}
virtual CSentence *GetSentence( void ) { return NULL; }
virtual int GetQuality( void ) { return 0; }
virtual int ZeroCrossingBefore( int sample ) { return sample; }
virtual int ZeroCrossingAfter( int sample ) { return sample; }
// mixer's references
virtual void ReferenceAdd( CAudioMixer *pMixer );
virtual void ReferenceRemove( CAudioMixer *pMixer );
// check reference count, return true if nothing is referencing this
virtual bool CanDelete( void );
virtual bool IsAsyncLoad();
virtual void CheckAudioSourceCache();
virtual char const *GetFileName( char *pOutBuf, size_t bufLen );
virtual void SetPlayOnce( bool isPlayOnce ) { m_bIsPlayOnce = isPlayOnce; }
virtual bool IsPlayOnce() { return m_bIsPlayOnce; }
virtual void SetSentenceWord( bool bIsWord ) { m_bIsSentenceWord = bIsWord; }
virtual bool IsSentenceWord() { return m_bIsSentenceWord; }
virtual int SampleToStreamPosition( int samplePosition ) { return 0; }
virtual int StreamToSamplePosition( int streamPosition ) { return 0; }
protected:
//-----------------------------------------------------------------------------
// Purpose:
// Output : byte
//-----------------------------------------------------------------------------
inline byte *GetCachedDataPointer()
{
VPROF("CAudioSourceMP3::GetCachedDataPointer");
CAudioSourceCachedInfo *info = m_AudioCacheHandle.Get( CAudioSource::AUDIO_SOURCE_MP3, m_pSfx->IsPrecachedSound(), m_pSfx, &m_nCachedDataSize );
if ( !info )
{
Assert( !"CAudioSourceMP3::GetCachedDataPointer info == NULL" );
return NULL;
}
return (byte *)info->CachedData();
}
CAudioSourceCachedInfoHandle_t m_AudioCacheHandle;
int m_nCachedDataSize;
protected:
bool GetStartupData();
CSfxTable *m_pSfx;
int m_sampleRate;
int m_dataSize;
int m_dataStart;
int m_refCount;
bool m_bIsPlayOnce : 1;
bool m_bIsSentenceWord : 1;
};
//-----------------------------------------------------------------------------
// Purpose: Streaming MP3 file
//-----------------------------------------------------------------------------
class CAudioSourceStreamMP3 : public CAudioSourceMP3, public IWaveStreamSource
{
public:
CAudioSourceStreamMP3( CSfxTable *pSfx );
CAudioSourceStreamMP3( CSfxTable *pSfx, CAudioSourceCachedInfo *info );
~CAudioSourceStreamMP3() {}
bool IsStreaming( void ) { return true; }
bool IsStereoWav(void) { return false; }
CAudioMixer *CreateMixer(int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, struct hrtf_info_t* pHRTFVec);
int GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] );
// IWaveStreamSource
virtual int64 UpdateLoopingSamplePosition( int64 samplePosition )
{
return samplePosition;
}
virtual void UpdateSamples( char *pData, int sampleCount ) {}
virtual int GetLoopingInfo( int *pLoopBlock, int *pNumLeadingSamples, int *pNumTrailingSamples )
{
return 0;
}
virtual void Prefetch();
private:
CAudioSourceStreamMP3( const CAudioSourceStreamMP3 & ); // not implemented, not accessible
};
class CAudioSourceMP3Cache : public CAudioSourceMP3
{
public:
CAudioSourceMP3Cache( CSfxTable *pSfx );
CAudioSourceMP3Cache( CSfxTable *pSfx, CAudioSourceCachedInfo *info );
~CAudioSourceMP3Cache( void );
int GetCacheStatus( void );
void CacheLoad( void );
void CacheUnload( void );
// NOTE: "samples" are bytes for MP3
int GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] );
CAudioMixer *CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, struct hrtf_info_t* pHRTFVec );
virtual void Prefetch() {}
protected:
virtual char *GetDataPointer( void );
WaveCacheHandle_t m_hCache;
private:
CAudioSourceMP3Cache( const CAudioSourceMP3Cache & );
};
bool Audio_IsMP3( const char *pName );
CAudioSource *Audio_CreateStreamedMP3( CSfxTable *pSfx );
CAudioSource *Audio_CreateMemoryMP3( CSfxTable *pSfx );
CAudioMixer *CreateMP3Mixer( IWaveData *data, int *pSampleRate );
#endif // SND_MP3_SOURCE_H

View File

@@ -0,0 +1,220 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#include "audio_pch.h"
#include "sos_system.h"
#include "sos_entry_match_system.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar snd_sos_show_block_debug;
ConVar snd_sos_show_entry_match_free( "snd_sos_show_entry_match_free", "0" );
//-----------------------------------------------------------------------------
// CSosEntryMatch
//-----------------------------------------------------------------------------
bool CSosEntryMatch::IsAMatch( CSosEntryMatch *pEntryMatch )
{
bool bMatchString1 = true;
bool bMatchString2 = true;
bool bMatchInt1 = true;
bool bMatchInt2 = true;
bool bMatchInt3 = true;
if ( m_bMatchString1 )
{
if( m_bMatchSubString )
{
if ( V_stristr( pEntryMatch->m_nMatchString1, m_nMatchString1 ) == NULL )
{
bMatchString1 = false;
}
}
else
{
// optimize to be scripthandle
if ( V_stricmp( pEntryMatch->m_nMatchString1, m_nMatchString1 ) )
{
bMatchString1 = false;
}
}
}
if ( m_bMatchString2 )
{
if ( m_bMatchSubString )
{
if ( V_stristr( pEntryMatch->m_nMatchString2, m_nMatchString2 ) == NULL )
{
bMatchString2 = false;
}
}
else
{
// optimize to be scripthandle
if ( V_stricmp( pEntryMatch->m_nMatchString2, m_nMatchString2 ) )
{
bMatchString2 = false;
}
}
}
if ( m_bMatchInt1 )
{
if ( pEntryMatch->m_nMatchInt1 != m_nMatchInt1 )
{
bMatchInt1 = false;
}
}
if ( m_bMatchInt2 )
{
if ( pEntryMatch->m_nMatchInt2 != m_nMatchInt2 )
{
bMatchInt2 = false;
}
}
if ( m_bMatchInt3 )
{
if ( pEntryMatch->m_nMatchInt3 != m_nMatchInt3 )
{
bMatchInt3 = false;
}
}
if ( ( ( bMatchString1 && m_bMatchString1 ) || !m_bMatchString1 ) &&
( ( bMatchString2 && m_bMatchString2 ) || !m_bMatchString2 )&&
( ( bMatchInt1 && m_bMatchInt1 ) || !m_bMatchInt1 ) &&
( ( bMatchInt2 && m_bMatchInt2 ) || !m_bMatchInt2 ) &&
( ( bMatchInt3 && m_bMatchInt3 ) || !m_bMatchInt3 ) )
{
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// CSosEntryMatchList
//-----------------------------------------------------------------------------
void CSosEntryMatchList::Update()
{
uint32 bit = 1;
for ( int i = 0; i < SOS_BLOCKSYS_MAX_ENTRIES; i++, ( bit <<= 1 ) )
{
if ( !( m_Free & bit ) )
{
Assert( !m_vEntryMatchList[i]->m_bFree );
if( m_vEntryMatchList[i]->m_bTimed )
{
if ( m_vEntryMatchList[i]->m_flDuration > -1.0 && m_vEntryMatchList[i]->m_flStartTime > -1.0 )
{
float flCurTime = g_pSoundServices->GetClientTime();
if ( ( m_vEntryMatchList[i]->m_flDuration + m_vEntryMatchList[i]->m_flStartTime ) <= flCurTime )
{
if( snd_sos_show_entry_match_free.GetInt() )
{
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "\nFREEING MATCH ENTRY:\n");
m_vEntryMatchList[i]->Print();
}
m_vEntryMatchList[i]->Reset();
m_Free |= bit;
}
}
else
{
if( snd_sos_show_entry_match_free.GetInt() )
{
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "\nFREEING MATCH ENTRY:\n");
m_vEntryMatchList[i]->Print();
}
m_vEntryMatchList[i]->Reset();
m_Free |= bit;
}
}
if( snd_sos_show_block_debug.GetInt() )
{
m_vEntryMatchList[i]->Print();
}
}
}
}
int CSosEntryMatchList::GetFreeEntryIndex() const
{
uint32 bit = 1;
for( int i = 0; i < SOS_BLOCKSYS_MAX_ENTRIES; i++, ( bit <<= 1 ) )
{
if ( m_vEntryMatchList[i]->m_bFree )
{
Assert( m_Free & bit );
m_vEntryMatchList[i]->m_bFree = false;
m_Free &= ~bit;
return i;
}
}
return -1;
}
CSosManagedEntryMatch *CSosEntryMatchList::GetEntryFromIndex( int nIndex ) const
{
Assert( IsValidIndex( nIndex ) );
if ( IsValidIndex( nIndex ) )
{
return m_vEntryMatchList[ nIndex ];
}
else
{
return NULL;
}
}
CSosManagedEntryMatch *CSosEntryMatchList::GetFreeEntry( int &nIndex ) const
{
int nMatchEntryIndex = g_pSoundOperatorSystem->m_sosEntryBlockList.GetFreeEntryIndex();
CSosManagedEntryMatch *pSosEntryMatch = g_pSoundOperatorSystem->m_sosEntryBlockList.GetEntryFromIndex( nMatchEntryIndex );
if ( !pSosEntryMatch )
{
Log_Warning( LOG_SND_OPERATORS, "Error: EntryMatchList has no free slots!\n" );
nIndex = -1;
return NULL;
}
return pSosEntryMatch;
}
void CSosEntryMatchList::FreeEntry( int nIndex, bool bForce /* = false */ )
{
if ( !m_vEntryMatchList[ nIndex ]->m_bTimed || bForce )
{
m_vEntryMatchList[ nIndex ]->Reset();
m_Free |= GetBitForBitnum( nIndex );
}
}
bool CSosEntryMatchList::HasAMatch( CSosEntryMatch *pEntryMatch ) const
{
uint32 bit = 1;
for( int i = 0; i < SOS_BLOCKSYS_MAX_ENTRIES; i++, (bit <<= 1) )
{
if ( !( m_Free & bit ) && m_vEntryMatchList[i]->m_bActive )
{
Assert( !m_vEntryMatchList[i]->m_bFree );
if ( m_vEntryMatchList[i]->IsAMatch( pEntryMatch ) )
{
return true;
}
}
}
return false;
}
void CSosEntryMatchList::Print() const
{
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "\nCUE Operators:\n");
}

View File

@@ -0,0 +1,169 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_ENTRY_MATCH_SYSTEM_H
#define SOS_ENTRY_MATCH_SYSTEM_H
#ifdef _WIN32
#pragma once
#endif
#include "bitvec.h"
//#include "snd_channels.h"
// Externs the logging channel
DECLARE_LOGGING_CHANNEL( LOG_SND_OPERATORS );
extern Color StackColor;
//-----------------------------------------------------------------------------
//
// Match Entry system
//
//-----------------------------------------------------------------------------
class CSosEntryMatch
{
public:
CSosEntryMatch()
{
Reset();
}
void Reset()
{
m_nMatchString1[0] = '\n';
m_bMatchString1 = false;
m_nMatchString2[0] = '\n';
m_bMatchString2 = false;
m_bMatchSubString = false;
m_nMatchInt1 = -1;
m_bMatchInt1 = false;
m_nMatchInt2 = -1;
m_bMatchInt2 = false;
m_nMatchInt3 = -1;
m_bMatchInt3 = false;
}
bool IsAMatch( CSosEntryMatch *pEntryMatch );
public:
char m_nMatchString1[64];
bool m_bMatchString1;
char m_nMatchString2[64];
bool m_bMatchString2;
bool m_bMatchSubString;
int m_nMatchInt1;
bool m_bMatchInt1;
int m_nMatchInt2;
bool m_bMatchInt2;
int m_nMatchInt3;
bool m_bMatchInt3;
};
class CSosEntryMatchList;
class CSosManagedEntryMatch : public CSosEntryMatch
{
friend class CSosEntryMatchList;
void Reset()
{
CSosEntryMatch::Reset();
m_bActive = false;
m_bTimed = false;
m_flStartTime = -1.0;
m_flDuration = -1.0;
m_bFree = true;
}
public:
void Start()
{
m_flStartTime = g_pSoundServices->GetClientTime();
}
private:
void Print()
{
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match String 1: %s\n", m_nMatchString1 );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match String 1?: %s\n", m_bMatchString1 ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match String 2: %s\n", m_nMatchString2 );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match String 2?: %s\n", m_bMatchString2 ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match SubString ?: %s\n", m_bMatchSubString ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match Int 1: %i\n", m_nMatchInt1 );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match Int 1?: %s\n", m_bMatchInt1 ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match Int 2: %i\n", m_nMatchInt2 );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match Int 2?: %s\n", m_bMatchInt2 ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match Int 3: %i\n", m_nMatchInt3 );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Match Int 3?: %s\n", m_bMatchInt3 ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Timed ?: %s\n", m_bTimed ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Duration: %f\n", m_flDuration );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "StartTime: %f\n", m_flStartTime );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "StopTime: %f\n", m_flStartTime + m_flDuration );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "CurTime: %f\n", g_pSoundServices->GetClientTime() );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Active ?: %s\n", m_bActive ? "true" : "false" );
Log_Msg( LOG_SOUND_OPERATOR_SYSTEM, StackColor, "Free ?: %s\n", m_bFree ? "true" : "false" );
}
bool m_bFree;
public:
bool m_bActive;
bool m_bTimed;
float m_flStartTime;
float m_flDuration;
};
#define SOS_BLOCKSYS_MAX_ENTRIES 32
class CSosEntryMatchList
{
public:
~CSosEntryMatchList()
{
for( int i = 0; i < SOS_BLOCKSYS_MAX_ENTRIES; i++ )
{
delete m_vEntryMatchList[i];
m_vEntryMatchList[i] = NULL;
}
}
CSosEntryMatchList()
{
uint32 bit = 1;
for( int i = 0; i < SOS_BLOCKSYS_MAX_ENTRIES; i++, ( bit <<= 1 ) )
{
m_vEntryMatchList[i] = new CSosManagedEntryMatch;
m_vEntryMatchList[i]->Reset();
m_Free |= bit;
}
}
void Update();
inline void Start( int nIndex ) { m_vEntryMatchList[ nIndex ]->Start(); }
inline bool IsValidIndex( int nIndex ) const { return nIndex > -1 && nIndex < SOS_BLOCKSYS_MAX_ENTRIES; }
int GetFreeEntryIndex() const;
CSosManagedEntryMatch *GetEntryFromIndex( int nIndex ) const ;
CSosManagedEntryMatch *GetFreeEntry( int &nIndex ) const ;
void FreeEntry( int nIndex, bool bForce = false );
bool HasAMatch( CSosEntryMatch *pEntryMatch ) const;
void Print() const;
protected:
mutable uint32 m_Free;
CSosManagedEntryMatch *m_vEntryMatchList[ SOS_BLOCKSYS_MAX_ENTRIES ];
};
#endif // SOS_ENTRY_MATCH_SYSTEM_H

View File

@@ -0,0 +1,441 @@
//============ 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 ) );
}
}

View File

@@ -0,0 +1,170 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_H
#define SOS_OP_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_system.h"
#include "snd_channels.h"
// Externs the logging channel
DECLARE_LOGGING_CHANNEL( LOG_SND_OPERATORS );
#define THREAD_LOCK_SOUND() AUTO_LOCK( g_SndMutex )
#define VALUE_REF_CHAR '@'
#define CLOSE_SQ_BRACKET ']'
#define SOS_INPUT_FLOAT( memberName, memberCount ) \
float memberName[memberCount]; \
int memberName##Offset[memberCount];
#define SOS_OUTPUT_FLOAT( memberName, memberCount ) \
float memberName[memberCount];
#define SOS_INIT_INPUT_VAR( memberName, memberCount, value ) \
for( int i = 0; i < memberCount; i++ ) \
{ pStructMem->memberName[i] = value; pStructMem->memberName##Offset[i] = -1; }
#define SOS_INIT_OUTPUT_VAR( memberName, memberType, value ) \
for( int i = 0; i < memberType; i++ ) \
{ pStructMem->memberName[i] = value; }
#define SOS_REGISTER_INPUT( className, memberName, memberCount, memberString, type ) \
{ \
InputData_t inputData; \
inputData.m_nValueOffset = offsetof( className##_t, memberName ); \
inputData.m_nOffsetOffset = offsetof( className##_t, memberName##Offset ); \
inputData.m_Type = type; \
inputData.m_nCount = memberCount; \
int nIndex = m_vInputs.AddToTail( inputData ); \
m_vInputMap.Insert( memberString, nIndex ); \
}
#define SOS_REGISTER_INPUT_FLOAT( className, memberName, memberCount, memberString ) \
SOS_REGISTER_INPUT( className, memberName, memberCount, memberString, SO_FLOAT )
#define SOS_REGISTER_OUTPUT( className, memberName, memberCount, memberString, type ) \
{ \
OutputData_t outputData; \
outputData.m_nValueOffset = offsetof( className##_t, memberName ); \
outputData.m_Type = type; \
outputData.m_nCount = memberCount; \
int nIndex = m_vOutputs.AddToTail( outputData ); \
m_vOutputMap.Insert( memberString, nIndex ); \
}
#define SOS_REGISTER_OUTPUT_FLOAT( className, memberName, memberCount, memberString ) \
SOS_REGISTER_OUTPUT( className, memberName, memberCount, memberString, SO_FLOAT )
#define SOS_BEGIN_OPERATOR_CONSTRUCTOR( classname, operatorstring ) \
classname::classname() \
{
#define SOS_END_OPERATOR_CONSTRUCTOR( classname, operatorstring ) \
g_pSoundOperatorSystem->m_vOperatorCollection.Insert(operatorstring, this ); \
} \
classname g_##classname;
#define SOS_HEADER_DESC( classname ) \
public: \
classname(); \
virtual void SetDefaults( void *pVoidMem ) const ; \
virtual size_t GetSize() const { return sizeof( classname##_t ); } \
virtual void Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const ; \
virtual void Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const ; \
virtual void OpHelp( ) const ; \
virtual void ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pParamKV ) const ; \
//-----------------------------------------------------------------------------
// The CSosOperator class:
//
// Base class for all sound operators, each operator must override "execute"
//
//-----------------------------------------------------------------------------
struct CSosOperator_t
{
SOS_INPUT_FLOAT( m_flExecute, SO_SINGLE )
bool m_bExecuteOnce;
bool m_bHasExecuted;
};
class CSosOperator
{
public:
CSosOperator();
virtual ~CSosOperator() { } ;
int GetOutputOffset( const char *pOutputName ) const;
// Proposal to optimize this:
// For each InputData_t, we store a function pointer to handle the resolution.
// We would create a different resolve function for the major cases (write a float, write 3 floats, generic case - same as current implementation).
// When filling the inputs initially, we would store the optimal function pointer.
// Cost: 4 bytes per InputData_t
// One dynamic call instead of one static call (currently ResolveInputValue).
// But then in most cases, the implementation would more efficient (estimated at 4 to 10 times faster).
void ResolveInputValue( void *pInputDefault, int *pOffsetArray, short nDataCount, SODataType_t nDataType, void *pStackMem ) const;
void ResolveInputValues( void *pStructMem, void *pStackMem ) const;
void OffsetConnections( void *pVoidMem, size_t nOffset ) const;
bool BaseParseKV( CSosOperatorStack *pStack, CSosOperator_t *pStructMem, const char *pParamString, const char *pValueString ) const;
int ParseValueRef( CSosOperatorStack *pStack, const char *pParamString, const char *pValueString ) const;
void PrintBaseParams( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const;
void PrintIO( CSosOperator_t *pStructMem, CSosOperatorStack *pStack, int nLevel ) const;
int BaseParseHasArrayIndice( const char *pParamString ) const;
void SetBaseDefaults( void *pVoidMem ) const;
virtual void SetDefaults( void *pVoidMem ) const = 0;
virtual size_t GetSize() const = 0;
virtual void Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const = 0;
virtual void Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const = 0;
virtual void OpHelp( ) const = 0;
virtual void ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pParamKV ) const = 0;
virtual void StackInit( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex );
virtual void StackShutdown( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex );
protected:
public:
struct OutputData_t
{
size_t m_nValueOffset;
SODataType_t m_Type;
short m_nCount;
};
struct InputData_t
{
size_t m_nValueOffset;
size_t m_nOffsetOffset;
SODataType_t m_Type;
short m_nCount;
};
CUtlDict <int, int> m_vOutputMap;
CUtlVector < OutputData_t > m_vOutputs;
CUtlDict <int, int> m_vInputMap;
CUtlVector< InputData_t > m_vInputs;
};
#endif // SOS_OP_H

View File

@@ -0,0 +1,215 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_entry_match_system.h"
#include "sos_op_block_entry.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorBlockEntry
//
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorBlockEntry, "sys_block_entries" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorBlockEntry, m_flInputDuration, SO_SINGLE, "input_duration" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorBlockEntry, m_flInputActive, SO_SINGLE, "input_active" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorBlockEntry, "sys_block_entries" )
void CSosOperatorBlockEntry::StackShutdown( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex )
{
CSosOperatorBlockEntry_t *pStructMem = (CSosOperatorBlockEntry_t *)pVoidMem;
if( pStructMem->m_nEntryIndex > -1 )
{
//g_pSoundOperatorSystem->m_sosEntryBlockList.FreeEntry( pStructMem->m_nEntryIndex );
}
}
void CSosOperatorBlockEntry::SetDefaults( void *pVoidMem ) const
{
CSosOperatorBlockEntry_t *pStructMem = (CSosOperatorBlockEntry_t *)pVoidMem;
V_strncpy( pStructMem->m_nMatchEntryName, "", sizeof(pStructMem->m_nMatchEntryName) );
V_strncpy( pStructMem->m_nMatchSoundName, "", sizeof(pStructMem->m_nMatchSoundName) );
pStructMem->m_bMatchEntry = false;
pStructMem->m_bMatchSound = false;
pStructMem->m_bMatchEntity = false;
pStructMem->m_bMatchChannel = false;
pStructMem->m_bMatchSubString = false;
pStructMem->m_nEntryIndex = -1;
SOS_INIT_INPUT_VAR( m_flInputDuration, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputActive, SO_SINGLE, 1.0 )
}
void CSosOperatorBlockEntry::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
// THREAD_LOCK_SOUND();
CSosOperatorBlockEntry_t *pStructMem = (CSosOperatorBlockEntry_t *)pVoidMem;
if( pStructMem->m_nEntryIndex < 0 )
{
int nMatchEntryIndex = g_pSoundOperatorSystem->m_sosEntryBlockList.GetFreeEntryIndex();
CSosManagedEntryMatch *pSosEntryMatch = g_pSoundOperatorSystem->m_sosEntryBlockList.GetEntryFromIndex( nMatchEntryIndex );
if( !pSosEntryMatch )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, EntryMatchList has no free slots!\n", pStack->GetOperatorName( nOpIndex ) );
return;
}
pStructMem->m_nEntryIndex = nMatchEntryIndex;
pSosEntryMatch->m_bMatchString1 = pStructMem->m_bMatchEntry;
V_strncpy( pSosEntryMatch->m_nMatchString1, pStructMem->m_nMatchEntryName, sizeof( pSosEntryMatch->m_nMatchString1 ) );
// pSosEntryMatch->m_bMatchString2 = pStructMem->m_bMatchSound;
// V_strncpy( pSosEntryMatch->m_nMatchString2, pStructMem->m_nMatchSoundName, sizeof( pSosEntryMatch->m_nMatchString2 ) );
pSosEntryMatch->m_bMatchSubString = pStructMem->m_bMatchSubString;
pSosEntryMatch->m_bMatchInt1 = pStructMem->m_bMatchChannel;
pSosEntryMatch->m_nMatchInt1 = pScratchPad->m_nChannel;
pSosEntryMatch->m_bMatchInt2 = pStructMem->m_bMatchEntity;
pSosEntryMatch->m_nMatchInt2 = pScratchPad->m_nSoundSource;
pSosEntryMatch->Start();
}
CSosManagedEntryMatch *pSosEntryMatch = g_pSoundOperatorSystem->m_sosEntryBlockList.GetEntryFromIndex( pStructMem->m_nEntryIndex );
if( pSosEntryMatch )
{
// defaults for now
pSosEntryMatch->m_bActive = pStructMem->m_flInputActive[0] > 0.0 ? true : false;
pSosEntryMatch->m_flDuration = pStructMem->m_flInputDuration[0] >= 0.0 ? pStructMem->m_flInputDuration[0] : 0.0;
//pSosEntryMatch->m_bTimed = pSosEntryMatch->m_flDuration > -1 ? true : false;
pSosEntryMatch->m_bTimed = true;
}
}
void CSosOperatorBlockEntry::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorBlockEntry_t *pStructMem = (CSosOperatorBlockEntry_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
// Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sNumber Allowed: %i\n", nLevel, " ", pStructMem->m_nNumAllowed );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_entry: %s\n", nLevel, " ", pStructMem->m_bMatchEntry ? pStructMem->m_nMatchEntryName : "\"\"" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_sound: %s\n", nLevel, " ", pStructMem->m_bMatchSound ? pStructMem->m_nMatchSoundName : "\"\"" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_entity: %s\n", nLevel, " ", pStructMem->m_bMatchEntity ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_channel: %s\n", nLevel, " ", pStructMem->m_bMatchEntity ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_substring: %s\n", nLevel, " ", pStructMem->m_bMatchSubString ? "true" : "false" );
}
void CSosOperatorBlockEntry::OpHelp( ) const
{
}
void CSosOperatorBlockEntry::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorBlockEntry_t *pStructMem = (CSosOperatorBlockEntry_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "match_entry" ) )
{
pStructMem->m_bMatchEntry = true;
V_strncpy( pStructMem->m_nMatchEntryName, pValueString, sizeof(pStructMem->m_nMatchEntryName) );
}
// else if ( !V_strcasecmp( pParamString, "match_sound" ) )
// {
// pStructMem->m_bMatchSound = true;
// V_strncpy( pStructMem->m_nMatchSoundName, pValueString, sizeof(pStructMem->m_nMatchSoundName) );
// }
else if ( !V_strcasecmp( pParamString, "match_entity" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchEntity = true;
}
else
{
pStructMem->m_bMatchEntity = false;
}
}
else if ( !V_strcasecmp( pParamString, "match_channel" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchChannel = true;
}
else
{
pStructMem->m_bMatchChannel = false;
}
}
else if ( !V_strcasecmp( pParamString, "match_substring" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchSubString = true;
}
else
{
pStructMem->m_bMatchSubString = false;
}
}
// else if ( !V_strcasecmp( pParamString, "stop_oldest" ) )
// {
// if ( !V_strcasecmp( pValueString, "true" ) )
// {
// pStructMem->m_bStopOldest = true;
// }
// else
// {
// pStructMem->m_bStopOldest = false;
// }
// }
// else if ( !V_strcasecmp( pParamString, "num_allowed" ) )
// {
// pStructMem->m_nNumAllowed = V_atoi( pValueString );
// }
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,43 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_BLOCK_ENTRY_H
#define SOS_OP_BLOCK_ENTRY_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// stop other sound entries
//-----------------------------------------------------------------------------
struct CSosOperatorBlockEntry_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputActive, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputDuration, SO_SINGLE )
char m_nMatchEntryName[64];
bool m_bMatchEntry;
char m_nMatchSoundName[64];
bool m_bMatchSound;
bool m_bMatchSubString;
bool m_bMatchEntity;
bool m_bMatchChannel;
int m_nEntryIndex;
};
class CSosOperatorBlockEntry : public CSosOperator
{
virtual void StackShutdown( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex );
SOS_HEADER_DESC( CSosOperatorBlockEntry )
};
#endif // SOS_OP_BLOCK_ENTRY_H

View File

@@ -0,0 +1,186 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_convar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar snd_op_test_convar("snd_op_test_convar", "1.0", FCVAR_CHEAT );
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorSetConvar
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorSetConvar, "set_convar" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSetConvar, m_flInput, SO_SINGLE, "input" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorSetConvar, "set_convar" )
void CSosOperatorSetConvar::SetDefaults( void *pVoidMem ) const
{
CSosOperatorSetConvar_t *pStructMem = (CSosOperatorSetConvar_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
}
void CSosOperatorSetConvar::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorSetConvar_t *pStructMem = (CSosOperatorSetConvar_t *)pVoidMem;
if ( pStructMem->m_ConVarRef.IsValid() )
{
pStructMem->m_ConVarRef.SetValue( pStructMem->m_flInput[0] );
}
else
{
// The stored ref is not valid, maybe was not initialized at load time, let's try again
pStructMem->m_ConVarRef.Init( pStructMem->m_nConvar, true );
if ( pStructMem->m_ConVarRef.IsValid() )
{
pStructMem->m_ConVarRef.SetValue( pStructMem->m_flInput[0] ); // Great success! Will be cached for next time.
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Warning: Unable to set convar value: %s\n", pStructMem->m_nConvar );
}
}
}
void CSosOperatorSetConvar::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorSetConvar_t *pStructMem = (CSosOperatorSetConvar_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sconvar: %s\n", nLevel, " ", pStructMem->m_nConvar );
}
void CSosOperatorSetConvar::OpHelp( ) const
{
}
void CSosOperatorSetConvar::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorSetConvar_t *pStructMem = (CSosOperatorSetConvar_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "convar" ) )
{
V_strcpy_safe( pStructMem->m_nConvar, pValueString );
pStructMem->m_ConVarRef.Init( pValueString, true );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorConvar
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorConvar, "get_convar" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorConvar, m_flOutput, SO_SINGLE, "output" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorConvar, "get_convar" )
void CSosOperatorConvar::SetDefaults( void *pVoidMem ) const
{
CSosOperatorConvar_t *pStructMem = (CSosOperatorConvar_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 1.0 )
}
void CSosOperatorConvar::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorConvar_t *pStructMem = (CSosOperatorConvar_t *)pVoidMem;
float flValue;
if ( pStructMem->m_ConVarRef.IsValid() )
{
flValue = pStructMem->m_ConVarRef.GetFloat();
}
else
{
// The stored ref is not valid, maybe was not initialized at load time, let's try again
pStructMem->m_ConVarRef.Init( pStructMem->m_nConvar, true );
if ( pStructMem->m_ConVarRef.IsValid() )
{
flValue = pStructMem->m_ConVarRef.GetFloat(); // Great success! Will be cached for next time.
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Warning: Unable to acquire convar value: %s\n", pStructMem->m_nConvar );
flValue = 1.0;
}
}
pStructMem->m_flOutput[0] = flValue;
}
void CSosOperatorConvar::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorConvar_t *pStructMem = (CSosOperatorConvar_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sconvar: %s\n", nLevel, " ", pStructMem->m_nConvar );
}
void CSosOperatorConvar::OpHelp( ) const
{
}
void CSosOperatorConvar::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorConvar_t *pStructMem = (CSosOperatorConvar_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "convar" ) )
{
V_strcpy_safe( pStructMem->m_nConvar, pValueString );
pStructMem->m_ConVarRef.Init( pValueString, true );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,64 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_CONVAR_H
#define SOS_OP_CONVAR_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
#include "tier1/convar.h"
//-----------------------------------------------------------------------------
// simple operator for getting a convar value
//-----------------------------------------------------------------------------
struct CSosOperatorConvar_t : CSosOperator_t
{
CSosOperatorConvar_t()
:
m_ConVarRef( ( IConVar * )NULL )
{
// Do nothing...
}
char m_nConvar[64];
ConVarRef m_ConVarRef;
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorConvar : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorConvar )
};
//-----------------------------------------------------------------------------
// simple operator for setting a convar value
//-----------------------------------------------------------------------------
struct CSosOperatorSetConvar_t : CSosOperator_t
{
CSosOperatorSetConvar_t()
:
m_ConVarRef( ( IConVar * )NULL )
{
// Do nothing...
}
char m_nConvar[64];
ConVarRef m_ConVarRef;
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
};
class CSosOperatorSetConvar : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSetConvar )
};
#endif // SOS_OP_CONVAR_H

View File

@@ -0,0 +1,97 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_dashboard.h"
#include "snd_dma.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorDashboard
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorDashboard, "get_dashboard" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorDashboard, m_flOutput, SO_SINGLE, "output" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorDashboard, "get_dashboard" )
void CSosOperatorDashboard::SetDefaults( void *pVoidMem ) const
{
CSosOperatorDashboard_t *pStructMem = (CSosOperatorDashboard_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 1.0 )
pStructMem->m_bMusic = true;
}
void CSosOperatorDashboard::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorDashboard_t *pStructMem = (CSosOperatorDashboard_t *)pVoidMem;
float flValue = 1.0;
if ( pStructMem->m_bMusic )
{
flValue = S_GetDashboarMusicMixValue();
}
pStructMem->m_flOutput[0] = flValue;
}
void CSosOperatorDashboard::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorDashboard_t *pStructMem = (CSosOperatorDashboard_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
/// Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sDashboard: %s\n", nLevel, " ", pStructMem->m_nConvar );
}
void CSosOperatorDashboard::OpHelp( ) const
{
}
void CSosOperatorDashboard::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorDashboard_t *pStructMem = (CSosOperatorDashboard_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "ds_type" ) )
{
if ( !V_strcasecmp( pValueString, "music" ) )
{
pStructMem->m_bMusic = true;
}
else
{
pStructMem->m_bMusic = false;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,31 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_DASHBOARD_H
#define SOS_OP_DASHBOARD_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// simple operator for getting the dashboard value
//-----------------------------------------------------------------------------
struct CSosOperatorDashboard_t : CSosOperator_t
{
bool m_bMusic;
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorDashboard : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorDashboard )
};
#endif // SOS_OP_DASHBOARD

View File

@@ -0,0 +1,90 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_delta.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorDelta
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorDelta, "math_delta" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorDelta, m_flInput, SO_SINGLE, "input" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorDelta, m_flOutput, SO_SINGLE, "output" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorDelta, "math_delta" )
void CSosOperatorDelta::SetDefaults( void *pVoidMem ) const
{
CSosOperatorDelta_t *pStructMem = (CSosOperatorDelta_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 0.0 )
pStructMem->m_flLastInput = 0.0;
pStructMem->m_flLastTime = g_pSoundServices->GetHostTime();
}
void CSosOperatorDelta::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorDelta_t *pStructMem = (CSosOperatorDelta_t *)pVoidMem;
// need to normalize for frame time
pStructMem->m_flOutput[0] = pStructMem->m_flInput[0] - pStructMem->m_flLastInput;
pStructMem->m_flLastInput = pStructMem->m_flInput[0];
}
void CSosOperatorDelta::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorDelta_t *pStructMem = (CSosOperatorDelta_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorDelta::OpHelp( ) const
{
}
void CSosOperatorDelta::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorDelta_t *pStructMem = (CSosOperatorDelta_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,36 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_DELTA_H
#define SOS_OP_DELTA_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// get elapsed time
//-----------------------------------------------------------------------------
struct CSosOperatorDelta_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
float m_flLastInput;
float m_flLastTime;
};
class CSosOperatorDelta : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorDelta )
};
#endif // SOS_OP_DELTA_VALUE_H

View File

@@ -0,0 +1,95 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_distant_dsp.h"
#include "snd_dma.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorDistantDSP
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorDistantDSP, "calc_distant_dsp" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorDistantDSP, m_flOutput, SO_SINGLE, "output" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorDistantDSP, m_flInputDist, SO_SINGLE, "input_distance" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorDistantDSP, m_flInputLevel, SO_SINGLE, "input_level" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorDistantDSP, "calc_distant_dsp" )
void CSosOperatorDistantDSP::SetDefaults( void *pVoidMem ) const
{
CSosOperatorDistantDSP_t *pStructMem = (CSosOperatorDistantDSP_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputDist, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputLevel, SO_SINGLE, 65.0 )
}
void CSosOperatorDistantDSP::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorDistantDSP_t *pStructMem = (CSosOperatorDistantDSP_t *)pVoidMem;
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
pStructMem->m_flOutput[0] = SND_GetDspMix( pChannel, pStructMem->m_flInputDist[0], pStructMem->m_flInputLevel[0] );
}
void CSosOperatorDistantDSP::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
//CSosOperatorDistantDSP_t *pStructMem = (CSosOperatorDistantDSP_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorDistantDSP::OpHelp( ) const
{
}
void CSosOperatorDistantDSP::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorDistantDSP_t *pStructMem = (CSosOperatorDistantDSP_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,30 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_DISTANT_DSP_H
#define SOS_OP_DISTANT_DSP_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// basic dsp by distance operator
//-----------------------------------------------------------------------------
struct CSosOperatorDistantDSP_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputDist, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputLevel, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorDistantDSP : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorDistantDSP )
};
#endif // SOS_OP_DISTANT_DSP_H

View File

@@ -0,0 +1,192 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "client.h"
#include "sos_op.h"
#include "sos_op_entity_info.h"
#include "icliententitylist.h"
#include "icliententity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
// ConVar snd_sos_show_source_info("snd_sos_show_source_info", "0" );
//-----------------------------------------------------------------------------
// CSosOperatorEntityInfo
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorEntityInfo, "game_entity_info" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutPosition, SO_VEC3, "output_position" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutPosition_x, SO_SINGLE, "output_position_x" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutPosition_y, SO_SINGLE, "output_position_y" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutPosition_z, SO_SINGLE, "output_position_z" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutAngles, SO_VEC3, "output_angles" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutVelocityVector, SO_VEC3, "output_velocity_vector" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutVelocityVector_x, SO_SINGLE, "output_velocity_vector_x" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutVelocityVector_y, SO_SINGLE, "output_velocity_vector_y" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutVelocityVector_z, SO_SINGLE, "output_velocity_vector_z" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutVelocity, SO_SINGLE, "output_velocity" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntityInfo, m_flOutVelocityXY, SO_SINGLE, "output_velocity_xy" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorEntityInfo, m_flInputEntityIndex, SO_SINGLE, "input_entity_index" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorEntityInfo, "game_entity_info" )
void CSosOperatorEntityInfo::SetDefaults( void *pVoidMem ) const
{
CSosOperatorEntityInfo_t *pStructMem = (CSosOperatorEntityInfo_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutPosition, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition_x, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition_y, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition_z, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutAngles, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocity, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector_x, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector_y, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector_z, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityXY, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputEntityIndex, SO_SINGLE, 0.0 )
pStructMem->m_vecPrevPosition.Init();
pStructMem->m_flPrevTime = g_pSoundServices->GetHostTime();
}
void CSosOperatorEntityInfo::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
#ifndef DEDICATED
CSosOperatorEntityInfo_t *pStructMem = (CSosOperatorEntityInfo_t *)pVoidMem;
// for future use with splitscreen
int nCurIndex = (int) pStructMem->m_flInputEntityIndex[0];
if( nCurIndex < 0 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: %s, input_entity_index %i invalid\n", pStack->GetOperatorName( nOpIndex ), nCurIndex );
return;
}
Vector vEntityAbsPos;
vEntityAbsPos.Init( 0.0, 0.0, 0.0 );
IClientEntity *pClientEntity = entitylist->GetClientEntity(nCurIndex );
if ( pClientEntity )
{
vEntityAbsPos = pClientEntity->GetAbsOrigin();
}
// first frame init position to avoid, erroneous deltas, zero is best option
if( pStructMem->m_flPrevTime == 0.0 )
{
VectorCopy( ( pScratchPad->m_vPlayerOrigin[ nCurIndex ]), pStructMem->m_vecPrevPosition );
}
// calculate delta time for this operator updates
float flCurTime = g_ClientGlobalVariables.curtime;
float flDeltaTime = flCurTime - pStructMem->m_flPrevTime;
pStructMem->m_flPrevTime = flCurTime;
if( flDeltaTime > 0.0 )
{
// per/sec factor
float flPerSec = 1.0 / flDeltaTime;
pStructMem->m_flOutPosition[0] = vEntityAbsPos[0];
pStructMem->m_flOutPosition[1] = vEntityAbsPos[1];
pStructMem->m_flOutPosition[2] = vEntityAbsPos[2];
// this is temporary for accessing single elements in array, will be a [] "feature" later when there's time
pStructMem->m_flOutPosition_x[0] = pStructMem->m_flOutPosition[0];
pStructMem->m_flOutPosition_y[0] = pStructMem->m_flOutPosition[1];
pStructMem->m_flOutPosition_z[0] = pStructMem->m_flOutPosition[2];
// get raw velocity vector
Vector vPositionDelta;
vPositionDelta[0] = pStructMem->m_flOutPosition[0] - pStructMem->m_vecPrevPosition[0];
vPositionDelta[1] = pStructMem->m_flOutPosition[1] - pStructMem->m_vecPrevPosition[1];
vPositionDelta[2] = pStructMem->m_flOutPosition[2] - pStructMem->m_vecPrevPosition[2];
// scale vector to per/sec
Vector vVelocity = vPositionDelta * flPerSec;
pStructMem->m_flOutVelocityVector[0] = vVelocity[0];
pStructMem->m_flOutVelocityVector[1] = vVelocity[1];
pStructMem->m_flOutVelocityVector[2] = vVelocity[2];
// this is temporary for accessing single elements in array, will be a "feature" later when there's time
pStructMem->m_flOutVelocityVector_x[0] = pStructMem->m_flOutVelocityVector[0];
pStructMem->m_flOutVelocityVector_y[0] = pStructMem->m_flOutVelocityVector[1];
pStructMem->m_flOutVelocityVector_z[0] = pStructMem->m_flOutVelocityVector[2];
pStructMem->m_flOutVelocity[0] = vVelocity.Length();
pStructMem->m_flOutVelocityXY[0] = vVelocity.Length2D();
VectorCopy( vEntityAbsPos, pStructMem->m_vecPrevPosition );
}
#endif
}
void CSosOperatorEntityInfo::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorEntityInfo_t *pStructMem = (CSosOperatorEntityInfo_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorEntityInfo::OpHelp( ) const
{
}
void CSosOperatorEntityInfo::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorEntityInfo_t *pStructMem = (CSosOperatorEntityInfo_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,48 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_ENTITY_INFO_H
#define SOS_OP_ENTITY_INFO_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// simple operator for setting a single position
//-----------------------------------------------------------------------------
struct CSosOperatorEntityInfo_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutPosition, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutPosition_x, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutPosition_y, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutPosition_z, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutAngles, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutVelocity, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector_x, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector_y, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector_z, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityXY, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputEntityIndex, SO_SINGLE )
float m_flPrevTime;
Vector m_vecPrevPosition;
};
class CSosOperatorEntityInfo : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorEntityInfo )
};
#endif // SOS_OP_ENTITY_INFO_H

View File

@@ -0,0 +1,134 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "snd_dma.h"
#include "sos_op.h"
#include "sos_op_entry_time.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorEntryTime
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorEntryTime, "get_entry_time" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntryTime, m_flOutputEntryElapsed, SO_SINGLE, "output_entry_elapsed" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntryTime, m_flOutputSoundElapsed, SO_SINGLE, "output_sound_elapsed" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntryTime, m_flOutputStopElapsed, SO_SINGLE, "output_stop_elapsed" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorEntryTime, m_flOutputSoundDuration, SO_SINGLE, "output_sound_duration" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorEntryTime, "get_entry_time" )
void CSosOperatorEntryTime::SetDefaults( void *pVoidMem ) const
{
CSosOperatorEntryTime_t *pStructMem = (CSosOperatorEntryTime_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutputSoundDuration, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputSoundElapsed, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputStopElapsed, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputEntryElapsed, SO_SINGLE, 0.0 )
pStructMem->m_nScriptHash = SOUNDEMITTER_INVALID_HASH;
}
void CSosOperatorEntryTime::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorEntryTime_t *pStructMem = (CSosOperatorEntryTime_t *)pVoidMem;
channel_t *pTimeChannel = NULL;
if( pStructMem->m_nScriptHash != SOUNDEMITTER_INVALID_HASH )
{
pTimeChannel = S_FindChannelByScriptHash( pStructMem->m_nScriptHash );
}
else
{
pTimeChannel = S_FindChannelByGuid( pStack->GetChannelGuid() );
}
if( !pTimeChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
if( pTimeChannel->m_pStackList )
{
CSosOperatorStack *pTheStack = NULL;
pTheStack = pTimeChannel->m_pStackList->GetStack( CSosOperatorStack::SOS_UPDATE );
if( pTheStack )
{
pStructMem->m_flOutputEntryElapsed[0] = pTheStack->GetElapsedTime();
}
}
pStructMem->m_flOutputSoundElapsed[0] = S_GetElapsedTime( pTimeChannel ) * 0.01;
pStructMem->m_flOutputSoundDuration[0] = S_SoundDuration( pTimeChannel );
pStructMem->m_flOutputStopElapsed[0] = pStack->GetElapsedStopTime( );
}
void CSosOperatorEntryTime::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorEntryTime_t *pStructMem = (CSosOperatorEntryTime_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorEntryTime::OpHelp( ) const
{
}
void CSosOperatorEntryTime::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorEntryTime_t *pStructMem = (CSosOperatorEntryTime_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "entry" ) )
{
if ( !g_pSoundEmitterSystem )
{
DevWarning("Error: SoundEmitterSystem not initialized in engine!");
return;
}
pStructMem->m_nScriptHash = g_pSoundEmitterSystem->HashSoundName( pValueString );
if( !g_pSoundEmitterSystem->GetSoundNameForHash( pStructMem->m_nScriptHash ))
{
DevMsg( "Error: Invalid SoundEntry hash %i from entry %s", pStructMem->m_nScriptHash, pValueString );
return;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,37 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_ENTRY_TIME_H
#define SOS_OP_ENTRY_TIME_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// get elapsed time
//-----------------------------------------------------------------------------
struct CSosOperatorEntryTime_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutputSoundDuration, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputSoundElapsed, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputEntryElapsed, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputStopElapsed, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputHostElapsed, SO_SINGLE )
HSOUNDSCRIPTHASH m_nScriptHash;
};
class CSosOperatorEntryTime : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorEntryTime )
};
#endif // SOS_OP_ENTRY_TIME_H

View File

@@ -0,0 +1,195 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_falloff.h"
#include "snd_dma.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorFalloff
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorFalloff, "calc_falloff" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorFalloff, m_flOutput, SO_SINGLE, "output" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloff, m_flInputDist, SO_SINGLE, "input_distance" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloff, m_flInputLevel, SO_SINGLE, "input_level" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorFalloff, "calc_falloff" )
void CSosOperatorFalloff::SetDefaults( void *pVoidMem ) const
{
CSosOperatorFalloff_t *pStructMem = (CSosOperatorFalloff_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputDist, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputLevel, SO_SINGLE, 1.0 )
}
void CSosOperatorFalloff::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorFalloff_t *pStructMem = (CSosOperatorFalloff_t *)pVoidMem;
float flDistMult = SNDLVL_TO_DIST_MULT( pStructMem->m_flInputLevel[0] );
// the first arg used to be because there was a form of compression on the falloff
// based on overall volume level, we are not having volume effect our falloff
pStructMem->m_flOutput[0] = SND_GetGainFromMult( 1.0, flDistMult, pStructMem->m_flInputDist[0] );
}
void CSosOperatorFalloff::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorFalloff_t *pStructMem = (CSosOperatorFalloff_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorFalloff::OpHelp( ) const
{
}
void CSosOperatorFalloff::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorFalloff_t *pStructMem = (CSosOperatorFalloff_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorFalloffTail
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorFalloffTail, "calc_falloff_curve" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorFalloffTail, m_flOutput, SO_SINGLE, "output" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputDist, SO_SINGLE, "input_distance" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputExp, SO_SINGLE, "input_curve_amount" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputDistantMin, SO_SINGLE, "input_min" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputDistantMax, SO_SINGLE, "input_max" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputAtten, SO_SINGLE, "input_atten" )
// SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputTailMin, SO_SINGLE, "input_tail_min" )
// SOS_REGISTER_INPUT_FLOAT( CSosOperatorFalloffTail, m_flInputTailMax, SO_SINGLE, "input_tail_max" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorFalloffTail, "calc_falloff_curve" )
void CSosOperatorFalloffTail::SetDefaults( void *pVoidMem ) const
{
CSosOperatorFalloffTail_t *pStructMem = (CSosOperatorFalloffTail_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputDist, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputExp, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputDistantMin, SO_SINGLE, 36.0 )
SOS_INIT_INPUT_VAR( m_flInputDistantMax, SO_SINGLE, 360.0 )
SOS_INIT_INPUT_VAR( m_flInputAtten, SO_SINGLE, 360.0 )
// SOS_INIT_INPUT_VAR( m_flInputTailMin, SO_SINGLE, 240.0 )
// SOS_INIT_INPUT_VAR( m_flInputTailMax, SO_SINGLE, 540.0 )
}
#define SOP_FALLOFF_MIN_EXP 0.1f
void CSosOperatorFalloffTail::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorFalloffTail_t *pStructMem = (CSosOperatorFalloffTail_t *)pVoidMem;
float flDistance = pStructMem->m_flInputDist[0];
float flDistantMin = pStructMem->m_flInputDistantMin[0];
float flDistantMax = pStructMem->m_flInputDistantMax[0];
// float flTailMin = pStructMem->m_flInputTailMin[0];
// float flTailMax = pStructMem->m_flInputTailMax[0];
flDistantMax = flDistantMax > flDistantMin ? flDistantMax : flDistantMin;
// flTailMin < flDistantMax ? flTailMin : flDistantMax;
// flTailMax > flDistantMax ? flTailMax : flDistantMax;
float flResult;
if ( flDistance <= flDistantMin )
{
flResult = pStructMem->m_flInputAtten[0];
}
// else if ( flDistance >= flTailMax ||
// ( flDistance > flDistantMax && flTailMin == flDistantMax ) )
else if ( flDistance > flDistantMax )
{
flResult = 0.0;
}
// else if ( flDistance > flTailMin && flDistance < flTailMax )
// {
// flResult = 1.0 - ( ( flDistance - flTailMin ) / ( flTailMax - flTailMin ) );
// flResult *= FastPow( 1.0 - ( flTailMin - flDistantMin ) / ( flDistantMax - flDistantMin ), pStructMem->m_flInputDistantExp[0] );
// }
// else if ( flDistance > flDistantMin && flDistance <= flTailMin )
else // flDistance is between flDistantMin and flDistantMax
{
flResult = ( flDistance - flDistantMin ) / ( flDistantMax - flDistantMin );
flResult = (1.0 - FastPow( flResult, ( 1.0 + SOP_FALLOFF_MIN_EXP) - pStructMem->m_flInputExp[0] )) * pStructMem->m_flInputAtten[0];
}
pStructMem->m_flOutput[0] = flResult;
}
void CSosOperatorFalloffTail::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorFalloffTail_t *pStructMem = (CSosOperatorFalloffTail_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorFalloffTail::OpHelp() const
{
}
void CSosOperatorFalloffTail::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorFalloffTail_t *pStructMem = (CSosOperatorFalloffTail_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,53 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_FALLOFF_H
#define SOS_OP_FALLOFF_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// falloff
//-----------------------------------------------------------------------------
struct CSosOperatorFalloff_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputDist, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputLevel, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorFalloff : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFalloff )
};
//-----------------------------------------------------------------------------
// falloff
//-----------------------------------------------------------------------------
struct CSosOperatorFalloffTail_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputDist, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputAtten, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputDistantMin, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputDistantMax, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputExp, SO_SINGLE )
// SOS_INPUT_FLOAT( m_flInputTailMin, SO_SINGLE )
// SOS_INPUT_FLOAT( m_flInputTailMax, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorFalloffTail : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFalloffTail )
};
#endif // SOS_OP_FALLOFF

View File

@@ -0,0 +1,134 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "client.h"
#include "sos_op.h"
#include "sos_op_filters.h"
#include "icliententitylist.h"
#include "icliententity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
// ConVar snd_sos_show_source_info("snd_sos_show_source_info", "0" );
//-----------------------------------------------------------------------------
// CSosOperatorFloatFilter
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorFloatFilter, "math_float_filter" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorFloatFilter, m_flOutput, SO_SINGLE, "output" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFloatFilter, m_flInput, SO_SINGLE, "input" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorFloatFilter, m_flInputMaxVel, SO_SINGLE, "input_max_velocity" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorFloatFilter, "math_float_filter" )
void CSosOperatorFloatFilter::SetDefaults( void *pVoidMem ) const
{
CSosOperatorFloatFilter_t *pStructMem = (CSosOperatorFloatFilter_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
//pStructMem->m_flPrevTime = g_pSoundServices->GetHostTime();
pStructMem->m_flPrevTime = -1.0;
}
void CSosOperatorFloatFilter::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
#ifndef DEDICATED
CSosOperatorFloatFilter_t *pStructMem = (CSosOperatorFloatFilter_t *)pVoidMem;
// first frame init position to avoid, erroneous deltas, zero is best option
if( pStructMem->m_flPrevTime < 0.0 )
{
pStructMem->m_flOutput[0] = pStructMem->m_flInput[0];
pStructMem->m_flPrevTime = g_ClientGlobalVariables.curtime;
}
else
{
// calculate delta time for this operator updates
float flCurTime = g_ClientGlobalVariables.curtime;
float flDeltaTime = flCurTime - pStructMem->m_flPrevTime;
pStructMem->m_flPrevTime = flCurTime;
float flDeltaValue = pStructMem->m_flInput[0] - pStructMem->m_flOutput[0];
if( flDeltaTime > 0.0 && flDeltaValue != 0.0 )
{
float flMaxVel = pStructMem->m_flInputMaxVel[0];
// per/sec factor
float flPerSec = 1.0 / flDeltaTime;
float flValueVel = flPerSec * flDeltaValue;
if( fabs(flValueVel) > flMaxVel )
{
float flVector = ( flDeltaTime * (flMaxVel * ( flDeltaValue < 0.0 ? -1.0 : 1.0 )));
pStructMem->m_flOutput[0] += flVector;
}
else
{
pStructMem->m_flOutput[0] = pStructMem->m_flInput[0];
}
}
}
#endif
}
void CSosOperatorFloatFilter::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorFloatFilter_t *pStructMem = (CSosOperatorFloatFilter_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorFloatFilter::OpHelp( ) const
{
}
void CSosOperatorFloatFilter::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorFloatFilter_t *pStructMem = (CSosOperatorFloatFilter_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,35 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_FILTERS_H
#define SOS_OP_FILTERS_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// simple operator for setting a single position
//-----------------------------------------------------------------------------
struct CSosOperatorFloatFilter_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputMaxVel, SO_SINGLE )
float m_flPrevTime;
float m_flPrevValue;
};
class CSosOperatorFloatFilter : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFloatFilter )
};
#endif // SOS_OP_FILTERS_H

View File

@@ -0,0 +1,149 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_iterate_merge_speakers.h"
// #include "../../debugoverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorIterateAndMergeSpeakers_t
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorIterateAndMergeSpeakers, "iterate_merge_speakers" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorIterateAndMergeSpeakers, m_flInputMaxIterations, SO_SINGLE, "input_max_iterations" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorIterateAndMergeSpeakers, m_flOutputIndex, SO_SINGLE, "output_index" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorIterateAndMergeSpeakers, m_flOutputSpeakers, SO_SPEAKERS, "output" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorIterateAndMergeSpeakers, m_flInputSpeakers, SO_SPEAKERS, "input")
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorIterateAndMergeSpeakers, "iterate_merge_speakers" )
void CSosOperatorIterateAndMergeSpeakers::SetDefaults( void *pVoidMem ) const
{
CSosOperatorIterateAndMergeSpeakers_t *pStructMem = ( CSosOperatorIterateAndMergeSpeakers_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInputMaxIterations, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputSpeakers, SO_SPEAKERS, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputSpeakers, SO_SPEAKERS, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputIndex, SO_SINGLE, 0.0 )
pStructMem->m_nMaxIterations = 8;
pStructMem->m_nOperatorIndex = -1;
}
void CSosOperatorIterateAndMergeSpeakers::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorIterateAndMergeSpeakers_t *pStructMem = ( CSosOperatorIterateAndMergeSpeakers_t *)pVoidMem;
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
int nCurIndex = ( int )pStructMem->m_flOutputIndex[0];
int nLastIndex = MIN( ( int ) pStructMem->m_flInputMaxIterations[0], pStructMem->m_nMaxIterations );
if( nCurIndex == 0 )
{
for ( int i = 0; i < SO_MAX_SPEAKERS; i++ )
{
pStructMem->m_flOutputSpeakers[i] = 0.0;
}
}
// merge speaker volumes
for ( int v = 0; v < SO_MAX_SPEAKERS; ++v )
{
// switch ( g_SndMergeMethod )
// switch ( SND_MERGE_MAX )
// {
// default:
// case SND_MERGE_SUMANDCLIP:
// {
// pStructMem->m_flOutputSpeakers[v] = min( pStructMem->m_flInputSpeakers[v]+pStructMem->m_flOutputSpeakers[v], 1.0 );
// }
// break;
// case SND_MERGE_MAX:
// {
pStructMem->m_flOutputSpeakers[v] = MAX( pStructMem->m_flInputSpeakers[v], pStructMem->m_flOutputSpeakers[v] );
// }
// break;
// }
}
// are we done?
if ( nCurIndex < nLastIndex )
{
nCurIndex++;
pStructMem->m_flOutputIndex[0] = ( float )nCurIndex;
pStack->ExecuteIterator( pChannel, pScratchPad, pVoidMem, pStructMem->m_nStartOperatorName, &pStructMem->m_nOperatorIndex );
return;
}
else
{
// clear index for next time around
pStructMem->m_flOutputIndex[0] = 0.0;
return;
}
}
void CSosOperatorIterateAndMergeSpeakers::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorIterateAndMergeSpeakers_t *pStructMem = ( CSosOperatorIterateAndMergeSpeakers_t * )pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sIterate Op: %s\n", nLevel, " ", pStructMem->m_nStartOperatorName );
}
void CSosOperatorIterateAndMergeSpeakers::OpHelp( ) const
{
}
void CSosOperatorIterateAndMergeSpeakers::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorIterateAndMergeSpeakers_t *pStructMem = (CSosOperatorIterateAndMergeSpeakers_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "iterate_operator" ) )
{
Q_strncpy( pStructMem->m_nStartOperatorName, pValueString, sizeof(pStructMem->m_nStartOperatorName) );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,37 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_ITERATE_MERGE_H
#define SOS_OP_ITERATE_MERGE_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// calculate and merge multiple pass speaker volumes
//-----------------------------------------------------------------------------
struct CSosOperatorIterateAndMergeSpeakers_t : CSosOperator_t
{
char m_nStartOperatorName[64];
int m_nMaxIterations;
int m_nOperatorIndex;
SOS_OUTPUT_FLOAT( m_flOutputIndex, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputMaxIterations, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputSpeakers, SO_SPEAKERS )
SOS_OUTPUT_FLOAT( m_flOutputSpeakers, SO_SPEAKERS )
};
class CSosOperatorIterateAndMergeSpeakers : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorIterateAndMergeSpeakers )
};
#endif // SOS_OP_ITERATE_MERGE_H

View File

@@ -0,0 +1,89 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_map_name.h"
#include "snd_dma.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorMapName
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorMapName, "get_map_name" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorMapName, m_flOutput, SO_SINGLE, "output" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorMapName, "get_map_name" )
void CSosOperatorMapName::SetDefaults( void *pVoidMem ) const
{
CSosOperatorMapName_t *pStructMem = (CSosOperatorMapName_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 0.0 )
}
void CSosOperatorMapName::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
// CSosOperatorMapName_t *pStructMem = (CSosOperatorMapName_t *)pVoidMem;
}
void CSosOperatorMapName::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorMapName_t *pStructMem = (CSosOperatorMapName_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorMapName::OpHelp( ) const
{
}
void CSosOperatorMapName::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
extern IVEngineClient *engineClient;
CSosOperatorMapName_t *pStructMem = (CSosOperatorMapName_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "map_name" ) )
{
pStructMem->m_flOutput[0] = 0.0;
if( ! V_strcmp( engineClient->GetLevelNameShort(), pValueString ) )
{
pStructMem->m_flOutput[0] = 1.0;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,31 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_MAPNAME_H
#define SOS_OP_MAPNAME_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// mapname
//-----------------------------------------------------------------------------
struct CSosOperatorMapName_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorMapName : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorMapName )
};
#endif // SOS_OP_MAPNAME

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,296 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_MATH_H
#define SOS_OP_MATH_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
enum SOOpCurveType_t
{
SO_OP_CURVETYPE_NONE = 0,
SO_OP_CURVETYPE_STEP,
SO_OP_CURVETYPE_LINEAR,
};
enum SOOpType_t
{
SO_OP_NONE = 0,
SO_OP_SET,
SO_OP_ADD,
SO_OP_SUB,
SO_OP_MULT,
SO_OP_DIV,
SO_OP_MOD,
SO_OP_MAX,
SO_OP_MIN,
SO_OP_INV,
SO_OP_GT,
SO_OP_LT,
SO_OP_GTOE,
SO_OP_LTOE,
SO_OP_EQ,
SO_OP_NOT_EQ,
SO_OP_INV_SCALE,
SO_OP_POW
};
enum SOFunc1Type_t
{
SO_FUNC1_NONE = 0,
SO_FUNC1_SIN,
SO_FUNC1_ASIN,
SO_FUNC1_COS,
SO_FUNC1_ACOS,
SO_FUNC1_TAN,
SO_FUNC1_ATAN,
SO_FUNC1_SINH,
SO_FUNC1_ASINH,
SO_FUNC1_COSH,
SO_FUNC1_ACOSH,
SO_FUNC1_TANH,
SO_FUNC1_ATANH,
SO_FUNC1_EXP,
SO_FUNC1_EXPM1,
SO_FUNC1_EXP2,
SO_FUNC1_LOG,
SO_FUNC1_LOG2,
SO_FUNC1_LOG1P,
SO_FUNC1_LOG10,
SO_FUNC1_LOGB,
SO_FUNC1_FABS,
SO_FUNC1_SQRT,
SO_FUNC1_ERF,
SO_FUNC1_ERFC,
SO_FUNC1_GAMMA,
SO_FUNC1_LGAMMA,
SO_FUNC1_CEIL,
SO_FUNC1_FLOOR,
SO_FUNC1_RINT,
SO_FUNC1_NEARBYINT,
SO_FUNC1_RINTOL,
SO_FUNC1_ROUND,
SO_FUNC1_ROUNDTOL,
SO_FUNC1_TRUNC,
};
//-----------------------------------------------------------------------------
// simple operator for single argument functions
//-----------------------------------------------------------------------------
struct CSosOperatorFunc1_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput1, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOFunc1Type_t m_funcType;
bool m_bNormTrig;
};
class CSosOperatorFunc1 : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFunc1 )
};
//-----------------------------------------------------------------------------
// simple operator for setting a single scratchpad Expression
//-----------------------------------------------------------------------------
struct CSosOperatorFloat_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput1, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput2, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOOpType_t m_opType;
};
class CSosOperatorFloat : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFloat )
};
//-----------------------------------------------------------------------------
// simple operator for setting a single scratchpad Expression
//-----------------------------------------------------------------------------
struct CSosOperatorFloatAccumulate12_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput1, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput2, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput3, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput4, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput5, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput6, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput7, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput8, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput9, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput10, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput11, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInput12, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOOpType_t m_opType;
};
class CSosOperatorFloatAccumulate12 : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFloatAccumulate12 )
};
//-----------------------------------------------------------------------------
// simple operator for setting a single position
//-----------------------------------------------------------------------------
struct CSosOperatorVec3_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput1, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInput2, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutput, SO_VEC3 )
SOOpType_t m_opType;
};
class CSosOperatorVec3 : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorVec3 )
};
//-----------------------------------------------------------------------------
// simple operator for settting a single speaker scratchpad expression
//-----------------------------------------------------------------------------
struct CSosOperatorSpeakers_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput1, SO_SPEAKERS )
SOS_INPUT_FLOAT( m_flInput2, SO_SPEAKERS )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SPEAKERS )
SOOpType_t m_opType;
};
class CSosOperatorSpeakers : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSpeakers )
};
//-----------------------------------------------------------------------------
// distance between 2 positions
//-----------------------------------------------------------------------------
struct CSosOperatorSourceDistance_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputPos, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
bool m_b2D;
bool m_bForceNotPlayerSound;
};
class CSosOperatorSourceDistance : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSourceDistance )
};
//-----------------------------------------------------------------------------
// RemapValue
//-----------------------------------------------------------------------------
struct CSosOperatorRemapValue_t : CSosOperator_t
{
SOS_INPUT_FLOAT(m_flInputMin, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputMax, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputMapMin, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputMapMax, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInput, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
bool m_bClampRange;
bool m_bDefaultMax;
};
class CSosOperatorRemapValue : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorRemapValue )
};
//-----------------------------------------------------------------------------
// Curve4
//-----------------------------------------------------------------------------
struct CSosOperatorCurve4_t : CSosOperator_t
{
SOS_INPUT_FLOAT(m_flInputX1, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputY1, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputX2, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputY2, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputX3, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputY3, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputX4, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputY4, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInput, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOOpCurveType_t m_nCurveType;
};
class CSosOperatorCurve4 : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorCurve4 )
};
//-----------------------------------------------------------------------------
// Facing
//-----------------------------------------------------------------------------
struct CSosOperatorFacing_t : CSosOperator_t
{
SOS_INPUT_FLOAT(m_flInputAngles, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorFacing : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorFacing )
};
//-----------------------------------------------------------------------------
// Facing
//-----------------------------------------------------------------------------
struct CSosOperatorRandom_t : CSosOperator_t
{
SOS_INPUT_FLOAT(m_flInputMin, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputMax, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputSeed, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
bool m_bRoundToInt;
};
class CSosOperatorRandom : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorRandom )
};
//-----------------------------------------------------------------------------
// Logic Switch
//-----------------------------------------------------------------------------
struct CSosOperatorLogicSwitch_t : CSosOperator_t
{
SOS_INPUT_FLOAT(m_flInput1, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInput2, SO_SINGLE )
SOS_INPUT_FLOAT(m_flInputSwitch, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorLogicSwitch : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorLogicSwitch )
};
#endif // SOS_OP_MATH_H

View File

@@ -0,0 +1,149 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_mixer.h"
#include "snd_mixgroups.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorMixGroup
// Catchall operator
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorMixGroup, "get_soundmixer" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorMixGroup, m_flOutputVolume, SO_SINGLE, "output_volume" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorMixGroup, m_flOutputLevel, SO_SINGLE, "output_level" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorMixGroup, m_flOutputDSP, SO_SINGLE, "output_dsp" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorMixGroup, "get_soundmixer" )
void CSosOperatorMixGroup::SetDefaults( void *pVoidMem ) const
{
CSosOperatorMixGroup_t *pStructMem = (CSosOperatorMixGroup_t *)pVoidMem;
pStructMem->m_nMixGroupIndex = -1;
pStructMem->m_bSetMixGroupOnChannel = false;
SOS_INIT_OUTPUT_VAR( m_flOutputVolume, SO_SINGLE, 1.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputLevel, SO_SINGLE, 1.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputDSP, SO_SINGLE, 1.0 )
}
void CSosOperatorMixGroup::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorMixGroup_t *pStructMem = (CSosOperatorMixGroup_t *)pVoidMem;
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
if ( pStructMem->m_nMixGroupIndex < 0 )
{
char sndname[MAX_PATH];
pChannel->sfx->getname(sndname, sizeof(sndname));
MXR_GetMixGroupFromSoundsource( pChannel );
pStructMem->m_nMixGroupIndex = MXR_GetFirstValidMixGroup( pChannel );
// DevMsg( "***FILE: %s: INDEX: %i: MIXGROUP: %s\n", sndname, pStructMem->m_nMixGroupIndex, MXR_GetGroupnameFromId( pStructMem->m_nMixGroupIndex ));
if ( pStructMem->m_nMixGroupIndex < 0 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: MixGroup index error, %s, %s", sndname, MXR_GetGroupnameFromId( pStructMem->m_nMixGroupIndex ));
return;
}
}
if( pStructMem->m_bSetMixGroupOnChannel && pChannel )
{
pChannel->mixgroups[0] = pStructMem->m_nMixGroupIndex;
}
mixervalues_t mixValues;
MXR_GetValuesFromMixGroupIndex( &mixValues, pStructMem->m_nMixGroupIndex );
pStructMem->m_flOutputLevel[0] = mixValues.level;
pStructMem->m_flOutputVolume[0] = mixValues.volume;
pStructMem->m_flOutputDSP[0] = mixValues.dsp;
pChannel->last_mixgroupid = pStructMem->m_nMixGroupIndex;
}
void CSosOperatorMixGroup::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
CSosOperatorMixGroup_t *pStructMem = (CSosOperatorMixGroup_t *)pVoidMem;
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smixgroup: %s\n", nLevel, " ", MXR_GetGroupnameFromId( pStructMem->m_nMixGroupIndex ));
}
void CSosOperatorMixGroup::OpHelp( ) const
{
}
void CSosOperatorMixGroup::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorMixGroup_t *pStructMem = (CSosOperatorMixGroup_t *)pVoidMem;
bool bHasMixGroupIndex = false;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "set_mixgroup_to_channel" ) )
{
if ( !V_strcasecmp( pValueString, "false" ) )
{
pStructMem->m_bSetMixGroupOnChannel = false;
}
else if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bSetMixGroupOnChannel = true;
}
}
else if ( !V_strcasecmp( pParamString, "mixgroup" ) )
{
pStructMem->m_nMixGroupIndex = MXR_GetMixgroupFromName( pValueString );
if ( pStructMem->m_nMixGroupIndex > -1 )
{
bHasMixGroupIndex = true;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
/* if ( !bHasMixGroupIndex )
{
MXR_GetMixGroupFromSoundsource( pStructMem->m_pChannel );
pStructMem->m_nMixGroupIndex = MXR_GetFirstValidMixGroup( pStructMem->m_pChannel );
}
*/
}

View File

@@ -0,0 +1,34 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_MIXER_H
#define SOS_OP_MIXER_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// basic mixgroup operator
//-----------------------------------------------------------------------------
struct CSosOperatorMixGroup_t : CSosOperator_t
{
int m_nMixGroupIndex;
bool m_bSetMixGroupOnChannel;
SOS_OUTPUT_FLOAT( m_flOutputVolume, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputLevel, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputDSP, SO_SINGLE )
};
class CSosOperatorMixGroup : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorMixGroup )
};
#endif // SOS_OP_MIXER

View File

@@ -0,0 +1,163 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op_mixlayer.h"
// #include "cdll_engine_int.h"
#include "../../debugoverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorMixLayer
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorMixLayer, "sys_mixlayer" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorMixLayer, m_flInput, SO_SINGLE, "input" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorMixLayer, "sys_mixlayer" )
void CSosOperatorMixLayer::SetDefaults( void *pVoidMem ) const
{
CSosOperatorMixLayer_t *pStructMem = (CSosOperatorMixLayer_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
pStructMem->m_nFieldType = MXR_MIXGROUP_NONE;
pStructMem->m_nMixLayerIndex = -1;
pStructMem->m_nMixGroupIndex = -1;
}
void CSosOperatorMixLayer::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorMixLayer_t *pStructMem = (CSosOperatorMixLayer_t *)pVoidMem;
if( pStructMem->m_nMixGroupIndex < 0 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: MixLayer operator has invalid mix group index!\n" );
return;
}
if( pStructMem->m_nMixLayerIndex < 0 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: MixLayer operator has invalid mix layer index!\n" );
return;
}
S_SetMixGroupOfMixLayer( pStructMem->m_nMixGroupIndex, pStructMem->m_nMixLayerIndex, pStructMem->m_nFieldType, pStructMem->m_flInput[0] );
}
void CSosOperatorMixLayer::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorMixLayer_t *pStructMem = (CSosOperatorMixLayer_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
const char *pFieldTypeString = "none";
switch( pStructMem->m_nFieldType )
{
case MXR_MIXGROUP_VOL:
pFieldTypeString = "volume";
break;
case MXR_MIXGROUP_LEVEL:
pFieldTypeString = "level";
break;
case MXR_MIXGROUP_DSP:
pFieldTypeString = "dsp";
break;
case MXR_MIXGROUP_SOLO:
pFieldTypeString = "solo";
break;
case MXR_MIXGROUP_MUTE:
pFieldTypeString = "mute";
break;
default:
break;
}
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sField: %s\n", nLevel, " ", pFieldTypeString );
}
void CSosOperatorMixLayer::OpHelp( ) const
{
}
void CSosOperatorMixLayer::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorMixLayer_t *pStructMem = (CSosOperatorMixLayer_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "field" ) )
{
if ( !V_strcasecmp( pValueString, "volume" ) )
{
pStructMem->m_nFieldType = MXR_MIXGROUP_VOL;
}
else if ( !V_strcasecmp( pValueString, "level" ) )
{
pStructMem->m_nFieldType = MXR_MIXGROUP_LEVEL;
}
else if ( !V_strcasecmp( pValueString, "dsp" ) )
{
pStructMem->m_nFieldType = MXR_MIXGROUP_DSP;
}
else if ( !V_strcasecmp( pValueString, "solo" ) )
{
pStructMem->m_nFieldType = MXR_MIXGROUP_SOLO;
}
else if ( !V_strcasecmp( pValueString, "mute" ) )
{
pStructMem->m_nFieldType = MXR_MIXGROUP_MUTE;
}
}
else if ( !V_strcasecmp( pParamString, "mixlayer" ) )
{
int nMixLayerID = MXR_GetMixLayerIndexFromName( pValueString );
if ( nMixLayerID == -1 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Failed to get mix layer %s!\n", pValueString );
}
pStructMem->m_nMixLayerIndex = nMixLayerID;
}
else if ( !V_strcasecmp( pParamString, "mixgroup" ) )
{
int nMixGroupID = S_GetMixGroupIndex( pValueString );
if ( nMixGroupID == -1 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Failed to get mix group %s!\n", pValueString );
}
pStructMem->m_nMixGroupIndex = nMixGroupID;
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,34 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_MIXLAYER_H
#define SOS_OP_MIXLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
#include "snd_mixgroups.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
struct CSosOperatorMixLayer_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
MXRMixGroupFields_t m_nFieldType;
int m_nMixLayerIndex;
int m_nMixGroupIndex;
};
class CSosOperatorMixLayer : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorMixLayer )
};
#endif // SOS_OP_MIXLAYER_H

View File

@@ -0,0 +1,292 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_occlusion.h"
#include "snd_dma.h"
#include "../../cl_splitscreen.h"
#include "../../enginetrace.h"
#include "render.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
float S_CalcOcclusion( int nSlot, channel_t *ch, const Vector &vecListenerOrigin, Vector vSoundSource, float flOccludedDBLoss );
//-----------------------------------------------------------------------------
// CSosOperatorOcclusion
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorOcclusion, "calc_occlusion" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorOcclusion, m_flInputTraceInterval, SO_SINGLE, "input_trace_interval" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorOcclusion, m_flInputScalar, SO_SINGLE, "input_scalar" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorOcclusion, m_flInputPosition, SO_VEC3, "input_position" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorOcclusion, m_flOutput, SO_SINGLE, "output" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorOcclusion, "calc_occlusion" )
void CSosOperatorOcclusion::SetDefaults( void *pVoidMem ) const
{
CSosOperatorOcclusion_t *pStructMem = (CSosOperatorOcclusion_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInputScalar, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputPosition, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputTraceInterval, SO_SINGLE, -1.0 )
pStructMem->m_flLastTraceTime = -1.0;
pStructMem->m_flOccludedDBLoss = snd_obscured_gain_db.GetFloat();
}
void CSosOperatorOcclusion::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorOcclusion_t *pStructMem = (CSosOperatorOcclusion_t *)pVoidMem;
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
// scalar of 0.0 = off, do nothing
float flScalar = pStructMem->m_flInputScalar[0];
if( flScalar == 0.0 )
{
pStructMem->m_flOutput[0] = 1.0;
return;
}
float flCurHostTime = g_pSoundServices->GetHostTime();
bool bIntervalHasPassed = ( ( pStructMem->m_flInputTraceInterval[0] >= 0.0 &&
( pStructMem->m_flInputTraceInterval[0] <= ( flCurHostTime - pStructMem->m_flLastTraceTime ) ))
|| pChannel->flags.bfirstpass );
bool bOkToTrace = SND_ChannelOkToTrace( pChannel );
bool bDoNewTrace = true;
// During signon just apply regular state machine since world hasn't been
// created or settled yet...
if ( !SND_IsInGame() && !toolframework->InToolMode() )
{
bDoNewTrace = false;
}
if( ( !pChannel->flags.bfirstpass && !pChannel->flags.isSentence ) && !bIntervalHasPassed || !bOkToTrace )
{
bDoNewTrace = false;
}
float flResult = 0.0;
if( bDoNewTrace )
{
// Log_Msg( LOG_SND_OPERATORS, "UPDATING: Sound operator %s\n", pStack->GetOperatorName( nOpIndex ));
Vector vOrigin;
vOrigin[0] = pStructMem->m_flInputPosition[0];
vOrigin[1] = pStructMem->m_flInputPosition[1];
vOrigin[2] = pStructMem->m_flInputPosition[2];
// find the loudest, ie: least occluded ss player
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
float flGain = S_CalcOcclusion( hh,
pChannel,
pScratchPad->m_vPlayerOrigin[ hh ],
vOrigin,
pStructMem->m_flOccludedDBLoss );
// inverse scale
flGain = 1.0 - ( ( 1.0 - flGain ) * flScalar );
flGain = SND_FadeToNewGain( &(pChannel->gain[ hh ]), pChannel, flGain );
flResult = MAX( flResult, flGain );
}
pStructMem->m_flLastTraceTime = flCurHostTime;
}
else
{
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
float flGain = SND_FadeToNewGain( &(pChannel->gain[ hh ] ), pChannel, -1.0 );
flResult = MAX( flResult, flGain );
}
}
pStructMem->m_flOutput[0] = flResult;
}
void CSosOperatorOcclusion::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorOcclusion_t *pStructMem = (CSosOperatorOcclusion_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorOcclusion::OpHelp( ) const
{
}
void CSosOperatorOcclusion::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorOcclusion_t *pStructMem = (CSosOperatorOcclusion_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "occlusio_db_loss" ) )
{
pStructMem->m_flOccludedDBLoss = V_atof( pValueString ) ;
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
float S_CalcOcclusion( int nSlot, channel_t *ch, const Vector &vecListenerOrigin, Vector vSoundSource, float flOccludedDBLoss )
{
float gain = 1.0;
int count = 1;
trace_t tr;
CTraceFilterWorldOnly filter; // UNDONE: also test for static props?
Ray_t ray;
ray.Init( MainViewOrigin( nSlot ), vSoundSource );
g_pEngineTraceClient->TraceRay( ray, MASK_BLOCK_AUDIO, &filter, &tr );
// total traces this frame
g_snd_trace_count++;
if (tr.DidHit() && tr.fraction < 0.99)
{
// can't see center of sound source:
// build extents based on dB sndlvl of source,
// test to see how many extents are visible,
// drop gain by snd_gain_db per extent hidden
Vector vSoundSources[4];
soundlevel_t sndlvl = DIST_MULT_TO_SNDLVL( ch->dist_mult );
float radius;
Vector vsrc_forward;
Vector vsrc_right;
Vector vsrc_up;
Vector vecl;
Vector vecr;
Vector vecl2;
Vector vecr2;
int i;
// get radius
if ( ch->radius > 0 )
radius = ch->radius;
else
radius = dB_To_Radius( sndlvl); // approximate radius from soundlevel
// set up extent vSoundSources - on upward or downward diagonals, facing player
for (i = 0; i < 4; i++)
vSoundSources[i] = vSoundSource;
// vsrc_forward is normalized vector from sound source to listener
VectorSubtract( vecListenerOrigin, vSoundSource, vsrc_forward );
VectorNormalize( vsrc_forward );
VectorVectors( vsrc_forward, vsrc_right, vsrc_up );
VectorAdd( vsrc_up, vsrc_right, vecl );
// if src above listener, force 'up' vector to point down - create diagonals up & down
if ( vSoundSource.z > vecListenerOrigin.z + (10 * 12) )
vsrc_up.z = -vsrc_up.z;
VectorSubtract( vsrc_up, vsrc_right, vecr );
VectorNormalize( vecl );
VectorNormalize( vecr );
// get diagonal vectors from sound source
vecl2 = radius * vecl;
vecr2 = radius * vecr;
vecl = (radius / 2.0) * vecl;
vecr = (radius / 2.0) * vecr;
// vSoundSources from diagonal vectors
vSoundSources[0] += vecl;
vSoundSources[1] += vecr;
vSoundSources[2] += vecl2;
vSoundSources[3] += vecr2;
// drop gain for each point on radius diagonal that is obscured
for (count = 0, i = 0; i < 4; i++)
{
// UNDONE: some vSoundSources are in walls - in this case, trace from the wall hit location
Ray_t ray;
ray.Init( MainViewOrigin( nSlot ), vSoundSources[i] );
g_pEngineTraceClient->TraceRay( ray, MASK_BLOCK_AUDIO, &filter, &tr );
if (tr.DidHit() && tr.fraction < 0.99 && !tr.startsolid )
{
count++; // skip first obscured point: at least 2 points + center should be obscured to hear db loss
if (count > 1)
gain = gain * dB_To_Gain( flOccludedDBLoss );
}
}
}
if ( snd_showstart.GetInt() == 7)
{
static float g_drop_prev = 0;
float drop = (count-1) * flOccludedDBLoss;
if (drop != g_drop_prev)
{
DevMsg( "dB drop: %1.4f \n", drop);
g_drop_prev = drop;
}
}
return gain;
}

View File

@@ -0,0 +1,33 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_OCCLUSION_H
#define SOS_OP_OCCLUSION_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// Occlusion
//-----------------------------------------------------------------------------
struct CSosOperatorOcclusion_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputPosition, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputScalar, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputTraceInterval, SO_SINGLE )
float m_flLastTraceTime;
float m_flOccludedDBLoss;
};
class CSosOperatorOcclusion : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorOcclusion )
};
#endif // SOS_OP_OCCLUSION

View File

@@ -0,0 +1,255 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_opvar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorSetOpvarFloat
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorSetOpvarFloat, "set_opvar_float" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSetOpvarFloat, m_flInput, SO_SINGLE, "input" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorSetOpvarFloat, "set_opvar_float" )
void CSosOperatorSetOpvarFloat::SetDefaults( void *pVoidMem ) const
{
CSosOperatorSetOpvarFloat_t *pStructMem = (CSosOperatorSetOpvarFloat_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
pStructMem->m_nOpVarName[ 0 ] = 0;
}
void CSosOperatorSetOpvarFloat::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorSetOpvarFloat_t *pStructMem = (CSosOperatorSetOpvarFloat_t *)pVoidMem;
float flOpvarVal = pStructMem->m_flInput[0];
g_pSoundOperatorSystem->SetOpVarFloat( pStructMem->m_nOpVarName, flOpvarVal );
}
void CSosOperatorSetOpvarFloat::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorSetOpvarFloat_t *pStructMem = (CSosOperatorSetOpvarFloat_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sopvar: %s\n", nLevel, " ", pStructMem->m_nOpVarName );
}
void CSosOperatorSetOpvarFloat::OpHelp( ) const
{
}
void CSosOperatorSetOpvarFloat::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
extern IVEngineClient *engineClient;
CSosOperatorSetOpvarFloat_t *pStructMem = (CSosOperatorSetOpvarFloat_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "opvar" ) )
{
V_strncpy( pStructMem->m_nOpVarName, pValueString, ARRAYSIZE( pStructMem->m_nOpVarName ) );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorGetOpvarFloat
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorGetOpvarFloat, "get_opvar_float" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorGetOpvarFloat, m_flOutput, SO_SINGLE, "output" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorGetOpvarFloat, m_flOpVarExists, SO_SINGLE, "output_opvar_exists" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorGetOpvarFloat, "get_opvar_float" )
void CSosOperatorGetOpvarFloat::SetDefaults( void *pVoidMem ) const
{
CSosOperatorGetOpvarFloat_t *pStructMem = (CSosOperatorGetOpvarFloat_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOpVarExists, SO_SINGLE, 0.0 )
pStructMem->m_nOpVarName[ 0 ] = 0;
}
void CSosOperatorGetOpvarFloat::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorGetOpvarFloat_t *pStructMem = (CSosOperatorGetOpvarFloat_t *)pVoidMem;
float flOpvarVal = 0.0;
bool bExists = g_pSoundOperatorSystem->GetOpVarFloat( pStructMem->m_nOpVarName, flOpvarVal );
if( bExists )
{
pStructMem->m_flOpVarExists[0] = 1.0;
pStructMem->m_flOutput[0] = flOpvarVal;
}
else
{
pStructMem->m_flOpVarExists[0] = 0.0;
pStructMem->m_flOutput[0] = 0.0;
}
}
void CSosOperatorGetOpvarFloat::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorGetOpvarFloat_t *pStructMem = (CSosOperatorGetOpvarFloat_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sopvar: %s\n", nLevel, " ", pStructMem->m_nOpVarName );
}
void CSosOperatorGetOpvarFloat::OpHelp( ) const
{
}
void CSosOperatorGetOpvarFloat::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
extern IVEngineClient *engineClient;
CSosOperatorGetOpvarFloat_t *pStructMem = (CSosOperatorGetOpvarFloat_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "opvar" ) )
{
V_strncpy( pStructMem->m_nOpVarName, pValueString, ARRAYSIZE( pStructMem->m_nOpVarName ) );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorIncrementOpvarFloat
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorIncrementOpvarFloat, "increment_opvar_float" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorIncrementOpvarFloat, m_flInput, SO_SINGLE, "input" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorIncrementOpvarFloat, m_flOutput, SO_SINGLE, "output" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorIncrementOpvarFloat, m_flOpVarExists, SO_SINGLE, "output_opvar_exists" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorIncrementOpvarFloat, "increment_opvar_float" )
void CSosOperatorIncrementOpvarFloat::SetDefaults( void *pVoidMem ) const
{
CSosOperatorIncrementOpvarFloat_t *pStructMem = (CSosOperatorIncrementOpvarFloat_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOpVarExists, SO_SINGLE, 0.0 )
pStructMem->m_nOpVarName[ 0 ] = 0;
}
void CSosOperatorIncrementOpvarFloat::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorIncrementOpvarFloat_t *pStructMem = (CSosOperatorIncrementOpvarFloat_t *)pVoidMem;
float flOpvarVal = 0.0; //value of the opvar currently
float flOpvarNewVal = 0.0; //value that we'll set it to
float flOpvarInc = pStructMem->m_flInput[0]; //value to add
bool bExists = g_pSoundOperatorSystem->GetOpVarFloat( pStructMem->m_nOpVarName, flOpvarVal );
if( bExists )
{
flOpvarNewVal = flOpvarVal + flOpvarInc;
pStructMem->m_flOpVarExists[0] = 1.0;
pStructMem->m_flOutput[0] = flOpvarNewVal;
}
else
{
flOpvarNewVal = flOpvarInc;
pStructMem->m_flOpVarExists[0] = 0.0;
pStructMem->m_flOutput[0] = flOpvarNewVal;
}
g_pSoundOperatorSystem->SetOpVarFloat( pStructMem->m_nOpVarName, flOpvarNewVal );
}
void CSosOperatorIncrementOpvarFloat::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorIncrementOpvarFloat_t *pStructMem = (CSosOperatorIncrementOpvarFloat_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sopvar: %s\n", nLevel, " ", pStructMem->m_nOpVarName );
}
void CSosOperatorIncrementOpvarFloat::OpHelp( ) const
{
}
void CSosOperatorIncrementOpvarFloat::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
extern IVEngineClient *engineClient;
CSosOperatorIncrementOpvarFloat_t *pStructMem = (CSosOperatorIncrementOpvarFloat_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "opvar" ) )
{
V_strncpy( pStructMem->m_nOpVarName, pValueString, ARRAYSIZE( pStructMem->m_nOpVarName ) );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,65 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_OPVAR_H
#define SOS_OP_OPVAR_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// set opvar
//-----------------------------------------------------------------------------
struct CSosOperatorSetOpvarFloat_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
char m_nOpVarName[128];
};
class CSosOperatorSetOpvarFloat : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSetOpvarFloat )
};
//-----------------------------------------------------------------------------
// get opvar
//-----------------------------------------------------------------------------
struct CSosOperatorGetOpvarFloat_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOpVarExists, SO_SINGLE )
char m_nOpVarName[128];
};
class CSosOperatorGetOpvarFloat : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorGetOpvarFloat )
};
//-----------------------------------------------------------------------------
// increment opvar
//-----------------------------------------------------------------------------
struct CSosOperatorIncrementOpvarFloat_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOpVarExists, SO_SINGLE )
char m_nOpVarName[128];
};
class CSosOperatorIncrementOpvarFloat : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorIncrementOpvarFloat )
};
#endif // SOS_OP_OPVAR_H

View File

@@ -0,0 +1,258 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_output.h"
#include "snd_dma.h"
// #include "cdll_engine_int.h"
#include "../../debugoverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorOutput
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorOutput, "sys_output" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorOutput, m_flInputSpeakers, SO_SPEAKERS, "input_speakers" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorOutput, m_flInputVec3, SO_VEC3, "input_vec3")
SOS_REGISTER_INPUT_FLOAT( CSosOperatorOutput, m_flInputFloat, SO_SINGLE, "input_float")
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorOutput, "sys_output" )
void CSosOperatorOutput::SetDefaults( void *pVoidMem ) const
{
CSosOperatorOutput_t *pStructMem = (CSosOperatorOutput_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInputFloat, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputVec3, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputSpeakers, SO_SPEAKERS, 0.0 )
pStructMem->m_nOutType = SOS_OUT_NONE;
}
void CSosOperatorOutput::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorOutput_t *pStructMem = (CSosOperatorOutput_t *)pVoidMem;
if( pStructMem->m_nOutType == SOS_OUT_DELAY )
{
pScratchPad->m_flDelay = pStructMem->m_flInputFloat[0];
}
else if( pStructMem->m_nOutType == SOS_OUT_STOPHOLD )
{
SOSStopType_t stopType = pStack->GetStopType();
if( stopType != SOS_STOP_NONE && stopType != SOS_STOP_FORCE && stopType != SOS_STOP_QUEUE )
{
pStack->SetStopType( pStructMem->m_flInputFloat[0] > 0.0 ? SOS_STOP_HOLD : SOS_STOP_NORM );
}
}
else if( pStructMem->m_nOutType == SOS_OUT_BLOCK_START )
{
pScratchPad->m_bBlockStart = pStructMem->m_flInputFloat[0] > 0.0 ? true : false;
}
else
{
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
switch( pStructMem->m_nOutType )
{
case SOS_OUT_POSITION:
pChannel->origin[0] = pStructMem->m_flInputVec3[0];
pChannel->origin[1] = pStructMem->m_flInputVec3[1];
pChannel->origin[2] = pStructMem->m_flInputVec3[2];
break;
case SOS_OUT_DSP:
pChannel->dspmix = pStructMem->m_flInputFloat[0];
break;
case SOS_OUT_SPEAKERS: {
float fScaledVolumes[CCHANVOLUMES / 2];
for (int i = 0; i != CCHANVOLUMES / 2; ++i)
{
fScaledVolumes[i] = pStructMem->m_flInputSpeakers[i] * 255.0f;
}
ChannelSetVolTargets(pChannel, fScaledVolumes, IFRONT_LEFT, CCHANVOLUMES / 2);
break;
}
case SOS_OUT_FACING:
pChannel->dspface = (pStructMem->m_flInputFloat[0] * 2.0) - 1.0;
break;
case SOS_OUT_DISTVAR:
pChannel->distmix = pStructMem->m_flInputFloat[0];
break;
case SOS_OUT_PITCH:
pChannel->basePitch = (int)(pStructMem->m_flInputFloat[0] * 100);
pChannel->pitch = pStructMem->m_flInputFloat[0];
break;
case SOS_OUT_MIXLAYER_TRIGGER:
pChannel->last_vol = pStructMem->m_flInputFloat[0];
break;
case SOS_OUT_SAVE_RESTORE:
pChannel->flags.m_bShouldSaveRestore = pStructMem->m_flInputFloat[0] > 0.0 ? true : false;
break;
case SOS_OUT_PHONON_XFADE: {
pChannel->hrtf.lerp = pStructMem->m_flInputFloat[0];
break;
}
}
}
}
void CSosOperatorOutput::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorOutput_t *pStructMem = (CSosOperatorOutput_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
const char *pOutTypeString = "none";
switch( pStructMem->m_nOutType )
{
case SOS_OUT_VOLUME:
pOutTypeString = "volume";
break;
case SOS_OUT_POSITION:
pOutTypeString = "position";
break;
case SOS_OUT_DSP:
pOutTypeString = "dsp";
break;
case SOS_OUT_SPEAKERS:
pOutTypeString = "speakers";
break;
case SOS_OUT_FACING:
pOutTypeString = "facing";
break;
case SOS_OUT_DISTVAR:
pOutTypeString = "distvar";
break;
case SOS_OUT_PITCH:
pOutTypeString = "pitch";
break;
case SOS_OUT_DELAY:
pOutTypeString = "delay";
break;
case SOS_OUT_STOPHOLD:
pOutTypeString = "stop_hold";
break;
case SOS_OUT_MIXLAYER_TRIGGER:
pOutTypeString = "mixlayer_trigger";
break;
case SOS_OUT_SAVE_RESTORE:
pOutTypeString = "save_restore";
break;
case SOS_OUT_BLOCK_START:
pOutTypeString = "block_start";
break;
case SOS_OUT_PHONON_XFADE:
pOutTypeString = "phonon_xfade";
break;
}
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sOutput: %s\n", nLevel, " ", pOutTypeString );
}
void CSosOperatorOutput::OpHelp( ) const
{
}
void CSosOperatorOutput::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorOutput_t *pStructMem = (CSosOperatorOutput_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "output" ) )
{
if ( !V_strcasecmp( pValueString, "volume" ) )
{
pStructMem->m_nOutType = SOS_OUT_VOLUME;
}
else if ( !V_strcasecmp( pValueString, "dsp" ) )
{
pStructMem->m_nOutType = SOS_OUT_DSP;
}
else if ( !V_strcasecmp( pValueString, "position" ) )
{
pStructMem->m_nOutType = SOS_OUT_POSITION;
}
else if ( !V_strcasecmp( pValueString, "speakers" ) )
{
pStructMem->m_nOutType = SOS_OUT_SPEAKERS;
}
else if ( !V_strcasecmp( pValueString, "facing" ) )
{
pStructMem->m_nOutType = SOS_OUT_FACING;
}
else if ( !V_strcasecmp( pValueString, "distvar" ) )
{
pStructMem->m_nOutType = SOS_OUT_DISTVAR;
}
else if ( !V_strcasecmp( pValueString, "pitch" ) )
{
pStructMem->m_nOutType = SOS_OUT_PITCH;
}
else if ( !V_strcasecmp( pValueString, "delay" ) )
{
pStructMem->m_nOutType = SOS_OUT_DELAY;
}
else if ( !V_strcasecmp( pValueString, "stop_hold" ) )
{
pStructMem->m_nOutType = SOS_OUT_STOPHOLD;
}
else if ( !V_strcasecmp( pValueString, "mixlayer_trigger" ) )
{
pStructMem->m_nOutType = SOS_OUT_MIXLAYER_TRIGGER;
}
else if ( !V_strcasecmp( pValueString, "save_restore" ) )
{
pStructMem->m_nOutType = SOS_OUT_SAVE_RESTORE;
}
else if ( !V_strcasecmp( pValueString, "block_start" ) )
{
pStructMem->m_nOutType = SOS_OUT_BLOCK_START;
}
else if (!V_strcasecmp(pValueString, "phonon_xfade"))
{
pStructMem->m_nOutType = SOS_OUT_PHONON_XFADE;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,52 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_OUTPUT_H
#define SOS_OP_OUTPUT_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
enum SOSOutputType_t
{
SOS_OUT_NONE = 0,
SOS_OUT_VOLUME,
SOS_OUT_DSP,
SOS_OUT_POSITION,
SOS_OUT_SPEAKERS,
SOS_OUT_FACING,
SOS_OUT_DISTVAR,
SOS_OUT_PITCH,
SOS_OUT_DELAY,
SOS_OUT_STOPHOLD,
SOS_OUT_MIXLAYER_TRIGGER,
SOS_OUT_SAVE_RESTORE,
SOS_OUT_BLOCK_START,
SOS_OUT_PHONON_XFADE,
};
struct CSosOperatorOutput_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputFloat, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputVec3, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputSpeakers, SO_SPEAKERS )
SOSOutputType_t m_nOutType;
};
class CSosOperatorOutput : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorOutput )
};
#endif // SOS_OP_OUTPUT_H

View File

@@ -0,0 +1,107 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_platform.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorPlatform
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorPlatform, "sys_platform" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorPlatform, m_flOutput, SO_SINGLE, "output" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorPlatform, "sys_platform" )
void CSosOperatorPlatform::SetDefaults( void *pVoidMem ) const
{
CSosOperatorPlatform_t *pStructMem = (CSosOperatorPlatform_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SINGLE, 0.0 )
}
void CSosOperatorPlatform::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
// CSosOperatorPlatform_t *pStructMem = (CSosOperatorPlatform_t *)pVoidMem;
}
void CSosOperatorPlatform::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorPlatform_t *pStructMem = (CSosOperatorPlatform_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorPlatform::OpHelp( ) const
{
}
void CSosOperatorPlatform::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
extern IVEngineClient *engineClient;
CSosOperatorPlatform_t *pStructMem = (CSosOperatorPlatform_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "pc" ) )
{
if( IsPC( ) )
{
pStructMem->m_flOutput[0] = 1.0;
}
}
else if ( !V_strcasecmp( pParamString, "x360" ) )
{
if( IsX360( ) )
{
pStructMem->m_flOutput[0] = 1.0;
}
}
else if ( !V_strcasecmp( pParamString, "ps3" ) )
{
if( IsPS3( ) )
{
pStructMem->m_flOutput[0] = 1.0;
}
}
else if ( !V_strcasecmp( pParamString, "osx" ) )
{
if( IsOSX( ) )
{
pStructMem->m_flOutput[0] = 1.0;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,31 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_PLATFORM_H
#define SOS_OP_PLATFORM_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// mapname
//-----------------------------------------------------------------------------
struct CSosOperatorPlatform_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutput, SO_SINGLE )
};
class CSosOperatorPlatform : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorPlatform )
};
#endif // SOS_OP_PLATFORM_H

View File

@@ -0,0 +1,190 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "client.h"
#include "sos_op.h"
#include "sos_op_player_info.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
// ConVar snd_sos_show_source_info("snd_sos_show_source_info", "0" );
//-----------------------------------------------------------------------------
// CSosOperatorViewInfo
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorViewInfo, "game_view_info" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutPosition, SO_VEC3, "output_position" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutPosition_x, SO_SINGLE, "output_position_x" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutPosition_y, SO_SINGLE, "output_position_y" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutPosition_z, SO_SINGLE, "output_position_z" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutAngles, SO_VEC3, "output_angles" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutVelocityVector, SO_VEC3, "output_velocity_vector" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutVelocityVector_x, SO_SINGLE, "output_velocity_vector_x" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutVelocityVector_y, SO_SINGLE, "output_velocity_vector_y" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutVelocityVector_z, SO_SINGLE, "output_velocity_vector_z" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutVelocity, SO_FLOAT, "output_velocity" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutVelocityXY, SO_FLOAT, "output_velocity_xy" );
// SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorViewInfo, m_flOutSourceCount, SO_SINGLE, "output_source_count" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorViewInfo, m_flInputSourceIndex, SO_SINGLE, "input_source_index" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorViewInfo, "game_view_info" )
void CSosOperatorViewInfo::SetDefaults( void *pVoidMem ) const
{
CSosOperatorViewInfo_t *pStructMem = (CSosOperatorViewInfo_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutPosition, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition_x, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition_y, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition_z, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector_x, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector_y, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityVector_z, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocity, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVelocityXY, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutAngles, SO_VEC3, 0.0 )
// not yet fully supporting splitscreen in operators
// SOS_INIT_OUTPUT_VAR( m_flOutSourceCount, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputSourceIndex, SO_SINGLE, 0.0 )
pStructMem->m_vecPrevPosition.Init();
pStructMem->m_flPrevTime = g_pSoundServices->GetHostTime();
}
void CSosOperatorViewInfo::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
#ifndef DEDICATED
CSosOperatorViewInfo_t *pStructMem = (CSosOperatorViewInfo_t *)pVoidMem;
// for future use with splitscreen
int nCurIndex = (int) pStructMem->m_flInputSourceIndex[0];
if( nCurIndex > MAX_SPLITSCREEN_CLIENTS -1 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: %s, input_source_index %i is greater than MAX_SPLITSCREEN_CLIENTS, clamped\n", pStack->GetOperatorName( nOpIndex ), nCurIndex );
nCurIndex = MAX_SPLITSCREEN_CLIENTS -1;
}
else if ( nCurIndex < 0 )
{
Log_Warning( LOG_SND_OPERATORS, "Error: %s, input_source_index %i is invalid, clamped\n", pStack->GetOperatorName( nOpIndex ), nCurIndex );
nCurIndex = 0;
}
// first frame init position to avoid, erroneous deltas, zero is best option
if( pStructMem->m_flPrevTime == 0.0 )
{
VectorCopy( ( pScratchPad->m_vPlayerOrigin[ nCurIndex ]), pStructMem->m_vecPrevPosition );
}
// calculate delta time for this operator updates
float flCurTime = g_ClientGlobalVariables.curtime;
float flDeltaTime = flCurTime - pStructMem->m_flPrevTime;
pStructMem->m_flPrevTime = flCurTime;
if( flDeltaTime > 0.0 )
{
// per/sec factor
float flPerSec = 1.0 / flDeltaTime;
pStructMem->m_flOutPosition[0] = ( pScratchPad->m_vPlayerOrigin[ nCurIndex ] )[0];
pStructMem->m_flOutPosition[1] = ( pScratchPad->m_vPlayerOrigin[ nCurIndex ] )[1];
pStructMem->m_flOutPosition[2] = ( pScratchPad->m_vPlayerOrigin[ nCurIndex ] )[2];
// this is temporary for accessing single elements in array, will be a [] "feature" later when there's time
pStructMem->m_flOutPosition_x[0] = pStructMem->m_flOutPosition[0];
pStructMem->m_flOutPosition_y[0] = pStructMem->m_flOutPosition[1];
pStructMem->m_flOutPosition_z[0] = pStructMem->m_flOutPosition[2];
// get raw velocity vector
Vector vPositionDelta;
vPositionDelta[0] = pStructMem->m_flOutPosition[0] - pStructMem->m_vecPrevPosition[0];
vPositionDelta[1] = pStructMem->m_flOutPosition[1] - pStructMem->m_vecPrevPosition[1];
vPositionDelta[2] = pStructMem->m_flOutPosition[2] - pStructMem->m_vecPrevPosition[2];
// scale vector to per/sec
Vector vVelocity = vPositionDelta * flPerSec;
pStructMem->m_flOutVelocityVector[0] = vVelocity[0];
pStructMem->m_flOutVelocityVector[1] = vVelocity[1];
pStructMem->m_flOutVelocityVector[2] = vVelocity[2];
// this is temporary for accessing single elements in array, will be a "feature" later when there's time
pStructMem->m_flOutVelocityVector_x[0] = pStructMem->m_flOutVelocityVector[0];
pStructMem->m_flOutVelocityVector_y[0] = pStructMem->m_flOutVelocityVector[1];
pStructMem->m_flOutVelocityVector_z[0] = pStructMem->m_flOutVelocityVector[2];
pStructMem->m_flOutVelocity[0] = vVelocity.Length();
pStructMem->m_flOutVelocityXY[0] = vVelocity.Length2D();
VectorCopy( ( pScratchPad->m_vPlayerOrigin[ nCurIndex ] ), pStructMem->m_vecPrevPosition );
}
#endif
}
void CSosOperatorViewInfo::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorViewInfo_t *pStructMem = (CSosOperatorViewInfo_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorViewInfo::OpHelp( ) const
{
}
void CSosOperatorViewInfo::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorViewInfo_t *pStructMem = (CSosOperatorViewInfo_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,50 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_PLAYER_INFO_H
#define SOS_OP_PLAYER_INFO_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// simple operator for setting a single position
//-----------------------------------------------------------------------------
struct CSosOperatorViewInfo_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutPosition, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutPosition_x, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutPosition_y, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutPosition_z, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutAngles, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutVelocity, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector_x, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector_y, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityVector_z, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVelocityXY, SO_SINGLE )
// for splitscreen players, once it's actually in use
SOS_OUTPUT_FLOAT( m_flOutSourceCount, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputSourceIndex, SO_SINGLE )
float m_flPrevTime;
Vector m_vecPrevPosition;
};
class CSosOperatorViewInfo : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorViewInfo )
};
#endif // SOS_OP_PLAYER_INFO_H

View File

@@ -0,0 +1,149 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_pos_vec8.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorPosVec8
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorPosVec8, "util_pos_vec8" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorPosVec8, m_flOutPosition, SO_VEC3, "output_position" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorPosVec8, m_flOutMaxIndex, SO_SINGLE, "output_max_index" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputIndex, SO_SINGLE, "input_index" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputEntryCount, SO_SINGLE, "input_entry_count" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos0, SO_VEC3, "input_position_0" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos1, SO_VEC3, "input_position_1" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos2, SO_VEC3, "input_position_2" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos3, SO_VEC3, "input_position_3" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos4, SO_VEC3, "input_position_4" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos5, SO_VEC3, "input_position_5" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos6, SO_VEC3, "input_position_6" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPosVec8, m_flInputPos7, SO_VEC3, "input_position_7" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorPosVec8, "util_pos_vec8" )
void CSosOperatorPosVec8::SetDefaults( void *pVoidMem ) const
{
CSosOperatorPosVec8_t *pStructMem = (CSosOperatorPosVec8_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutPosition, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutMaxIndex, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputEntryCount, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputIndex, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos0, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos1, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos2, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos3, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos4, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos5, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos6, SO_VEC3, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPos7, SO_VEC3, 0.0 )
}
void CSosOperatorPosVec8::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorPosVec8_t *pStructMem = (CSosOperatorPosVec8_t *)pVoidMem;
int nIndex = (int)pStructMem->m_flInputIndex[0];
int nEntryCount = pStructMem->m_flInputEntryCount[0];
nIndex = ( nIndex >= nEntryCount ) ? nEntryCount - 1 : nIndex;
nIndex = ( nIndex < 0 ) ? 0 : nIndex;
float *pIndexedPos = pStructMem->m_flInputPos0;
switch( nIndex )
{
case 0:
pIndexedPos = pStructMem->m_flInputPos0;
break;
case 1:
pIndexedPos = pStructMem->m_flInputPos1;
break;
case 2:
pIndexedPos = pStructMem->m_flInputPos2;
break;
case 3:
pIndexedPos = pStructMem->m_flInputPos3;
break;
case 4:
pIndexedPos = pStructMem->m_flInputPos4;
break;
case 5:
pIndexedPos = pStructMem->m_flInputPos5;
break;
case 6:
pIndexedPos = pStructMem->m_flInputPos6;
break;
case 7:
pIndexedPos = pStructMem->m_flInputPos7;
break;
}
pStructMem->m_flOutPosition[0] = pIndexedPos[0];
pStructMem->m_flOutPosition[1] = pIndexedPos[1];
pStructMem->m_flOutPosition[2] = pIndexedPos[2];
pStructMem->m_flOutMaxIndex[0] = pStructMem->m_flInputEntryCount[0] - 1.0;
}
void CSosOperatorPosVec8::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorPosVec8_t *pStructMem = (CSosOperatorPosVec8_t *)pVoidMem;
NOTE_UNUSED( pStructMem );
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorPosVec8::OpHelp( ) const
{
}
void CSosOperatorPosVec8::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorPosVec8_t *pStructMem = (CSosOperatorPosVec8_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,41 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_POS_VEC8_H
#define SOS_OP_POS_VEC8_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// simple operator for setting a single position
//-----------------------------------------------------------------------------
struct CSosOperatorPosVec8_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutPosition, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutMaxIndex, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputIndex, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputEntryCount, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputPos0, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos1, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos2, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos3, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos4, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos5, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos6, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputPos7, SO_VEC3 )
};
class CSosOperatorPosVec8 : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorPosVec8 )
};
#endif // SOS_OP_POS_VEC8_H

View File

@@ -0,0 +1,336 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_source_info.h"
#include "snd_dma.h"
#include "soundinfo.h"
#include "cdll_engine_int.h"
#include "../../debugoverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
ConVar snd_sos_show_source_info("snd_sos_show_source_info", "0" );
//-----------------------------------------------------------------------------
// CSosOperatorSourceInfo
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorSourceInfo, "get_source_info" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutEntityIndex, SO_SINGLE, "output_entity_index" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutPosition, SO_VEC3, "output_position" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutAngles, SO_VEC3, "output_angles" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutRadius, SO_SINGLE, "output_radius" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutVolume, SO_SINGLE, "output_volume" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutLevel, SO_SINGLE, "output_level" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutPitch, SO_SINGLE, "output_pitch" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSourceInfo, m_flOutSourceCount, SO_SINGLE, "output_source_count" );
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSourceInfo, m_flInputSourceIndex, SO_SINGLE, "input_source_index" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorSourceInfo, "get_source_info" )
void CSosOperatorSourceInfo::SetDefaults( void *pVoidMem ) const
{
CSosOperatorSourceInfo_t *pStructMem = (CSosOperatorSourceInfo_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutEntityIndex, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPosition, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutAngles, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutRadius, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutVolume, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutLevel, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutPitch, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutSourceCount, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputSourceIndex, SO_SINGLE, 0.0 )
pStructMem->m_nSource = SO_SRC_EMITTER;
pStructMem->m_bGameExtraOrigins = true;
}
void CSosOperatorSourceInfo::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorSourceInfo_t *pStructMem = (CSosOperatorSourceInfo_t *)pVoidMem;
bool bUseEntity = ( pStructMem->m_nSource == SO_SRC_ENTITY );
int nSourceCount = pScratchPad->m_UtlVecMultiOrigins.Count();
// have we gotten our sources yet?
if( nSourceCount < 1 )
{
// update channel's position in case ent that made the sound is moving.
QAngle source_angles;
source_angles.Init(0.0, 0.0, 0.0);
// default entity to emitter in case there is no entity available
int nSoundSource = pScratchPad->m_nSoundSource;
int nEntChannel = pScratchPad->m_nChannel;
const char *pSoundName = pScratchPad->m_emitterInfoSoundName;
Vector vOrigin = pScratchPad->m_vEmitterInfoOrigin;
Vector vDirection = pScratchPad->m_vEmitterInfoDirection;
short nMasterVolume = (short) pScratchPad->m_flEmitterInfoMasterVolume * 255;
soundlevel_t nSoundLevel = pScratchPad->m_vEmitterInfoSoundLevel;
bool bIsLooping = pScratchPad->m_bIsLooping;
float flPitch = pScratchPad->m_bIsLooping;
int nSpeakerEntity = pScratchPad->m_nEmitterInfoSpeakerEntity;
Vector vListenerOrigin = pScratchPad->m_vBlendedListenerOrigin; // HACK FOR SPLITSCREEN, only client\c_func_tracktrain.cpp(100): CalcClosestPointOnLine( info.info.vListenerOrigin, vecStart, vecEnd, *info.pOrigin, &t ); every looked at listener origin in this structure...
Vector vEntOrigin = vOrigin;
float flRadius = 0.0;
SpatializationInfo_t si;
si.info.Set(
nSoundSource,
nEntChannel,
pSoundName,
vOrigin,
vDirection,
nMasterVolume,
nSoundLevel,
bIsLooping,
flPitch,
vListenerOrigin,
nSpeakerEntity,
0 ); // FIX SEEDING?
si.type = SpatializationInfo_t::SI_INSPATIALIZATION;
si.pOrigin = &vEntOrigin;
si.pAngles = &source_angles;
si.pflRadius = &flRadius;
CUtlVector< Vector > utlVecMultiOrigins;
si.m_pUtlVecMultiOrigins = &pScratchPad->m_UtlVecMultiOrigins;
CUtlVector< Vector > utlVecMultiAngles;
// si.m_pUtlVecMultiAngles = &pScratchPad->m_UtlVecMultiAngles;
// TODO: morasky, verify it's been handled
// if ( pChannel->soundsource != 0 && pChannel->radius == 0 )
// {
// si.pflRadius = &pChannel->radius;
// }
// this returns the position of the entity in vEntOrigin
//VPROF_("SoundServices->GetSoundSpatializtion", 2, VPROF_BUDGETGROUP_OTHER_SOUND, false, BUDGETFLAG_OTHER );
bUseEntity &= g_pSoundServices->GetSoundSpatialization( nSoundSource, si );
if( !bUseEntity )
{
si.pOrigin = &si.info.vOrigin;
}
#ifndef DEDICATED
// extra, non-entity related, game specific processing (portal2, multi-source, etc.)
if( pStructMem->m_bGameExtraOrigins )
{
g_ClientDLL->GetSoundSpatialization( si );
}
#endif
// TODO: morasky, verify it's been handled
// // just about pChannel->direction?!
// // if ( pChannel->flags.bUpdatePositions )
// {
// // angles -> forward vector
// AngleVectors( source_angles, &pChannel->direction );
// //XXX pChannel->origin = vEntOrigin;
// }
// // else
// {
// // vector -> angles
// VectorAngles( pChannel->direction, source_angles );
// }
// ???
// if ( IsPC() && pChannel->userdata != 0 )
// {
// g_pSoundServices->GetToolSpatialization( pChannel->userdata, pChannel->guid, si );
// if ( pChannel->flags.bUpdatePositions )
// {
// AngleVectors( source_angles, &pChannel->direction );
// //XXX pChannel->origin = vEntOrigin;
// }
// }
pScratchPad->m_vEntityInfoAngle = source_angles;
pScratchPad->m_vEntityInfoOrigin = vEntOrigin;
pScratchPad->m_flEntityInfoRadius = flRadius;
}
nSourceCount = pScratchPad->m_UtlVecMultiOrigins.Count();
pStructMem->m_flOutSourceCount[0] = (float) nSourceCount;
int nCurIndex = (int) pStructMem->m_flInputSourceIndex[0];
// BIG ERROR CHECK HERE!
if ( nCurIndex == 0 )
{
if ( pStructMem->m_nSource == SO_SRC_ENTITY )
{
pStructMem->m_flOutPosition[0] = pScratchPad->m_vEntityInfoOrigin[0];
pStructMem->m_flOutPosition[1] = pScratchPad->m_vEntityInfoOrigin[1];
pStructMem->m_flOutPosition[2] = pScratchPad->m_vEntityInfoOrigin[2];
pStructMem->m_flOutAngles[0] = pScratchPad->m_vEntityInfoAngle[0];
pStructMem->m_flOutAngles[1] = pScratchPad->m_vEntityInfoAngle[1];
pStructMem->m_flOutAngles[2] = pScratchPad->m_vEntityInfoAngle[2];
pStructMem->m_flOutRadius[0] = pScratchPad->m_flEntityInfoRadius;
}
else if ( pStructMem->m_nSource == SO_SRC_EMITTER )
{
pStructMem->m_flOutPosition[0] = pScratchPad->m_vEmitterInfoOrigin[0];
pStructMem->m_flOutPosition[1] = pScratchPad->m_vEmitterInfoOrigin[1];
pStructMem->m_flOutPosition[2] = pScratchPad->m_vEmitterInfoOrigin[2];
QAngle source_angles;
VectorAngles( pScratchPad->m_vEmitterInfoDirection, source_angles );
pStructMem->m_flOutAngles[0] = source_angles[0];
pStructMem->m_flOutAngles[1] = source_angles[1];
pStructMem->m_flOutAngles[2] = source_angles[2];
pStructMem->m_flOutRadius[0] = pScratchPad->m_nEmitterInfoRadius;
}
}
else
{
pStructMem->m_flOutPosition[0] = pScratchPad->m_UtlVecMultiOrigins[nCurIndex - 1][0];
pStructMem->m_flOutPosition[1] = pScratchPad->m_UtlVecMultiOrigins[nCurIndex - 1][1];
pStructMem->m_flOutPosition[2] = pScratchPad->m_UtlVecMultiOrigins[nCurIndex - 1][2];
// pStructMem->m_flOutAngles[0] = pScratchPad->m_vEntityInfoAngle[0];
// pStructMem->m_flOutAngles[1] = pScratchPad->m_vEntityInfoAngle[1];
// pStructMem->m_flOutAngles[2] = pScratchPad->m_vEntityInfoAngle[2];
// pStructMem->m_flOutRadius[0] = pScratchPad->m_flEntityInfoRadius;
}
pStructMem->m_flOutVolume[0] = pScratchPad->m_flEmitterInfoMasterVolume;
pStructMem->m_flOutLevel[0] = pScratchPad->m_vEmitterInfoSoundLevel;
pStructMem->m_flOutPitch[0] = pScratchPad->m_flEmitterInfoPitch;
pStructMem->m_flOutEntityIndex[0] = (float) pScratchPad->m_nSoundSource;
#ifndef DEDICATED
if( snd_sos_show_source_info.GetInt() )
{
Vector vDebug;
vDebug[0] = pStructMem->m_flOutPosition[0];
vDebug[1] = pStructMem->m_flOutPosition[1];
vDebug[2] = pStructMem->m_flOutPosition[2];
CDebugOverlay::AddTextOverlay( vDebug, 2.0f, g_pSoundEmitterSystem->GetSoundNameForHash( pStack->GetScriptHash() ) );
}
#endif
}
void CSosOperatorSourceInfo::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorSourceInfo_t *pStructMem = (CSosOperatorSourceInfo_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
switch( pStructMem->m_nSource )
{
case SO_SRC_EMITTER:
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sSource: emitter\n", nLevel, " " );
break;
case SO_SRC_ENTITY:
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sSource: entity\n", nLevel, " " );
break;
}
}
void CSosOperatorSourceInfo::OpHelp( ) const
{
}
void CSosOperatorSourceInfo::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorSourceInfo_t *pStructMem = (CSosOperatorSourceInfo_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "source" ) )
{
if ( !V_strcasecmp( pValueString, "none" ) )
{
pStructMem->m_nSource = SO_SRC_NONE;
}
else if ( !V_strcasecmp( pValueString, "emitter" ) )
{
pStructMem->m_nSource = SO_SRC_EMITTER;
}
else if ( !V_strcasecmp( pValueString, "entity" ) )
{
pStructMem->m_nSource = SO_SRC_ENTITY;
}
}
else if ( !V_strcasecmp( pParamString, "game_multi_origin" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bGameExtraOrigins = true;
}
else
{
pStructMem->m_bGameExtraOrigins = false;
}
}
// else
// {
// S_GetFloatFromString( pStructMem->m_vValues, pValueString, SO_POSITION_ARRAY_SIZE );
// }
// else if ( !V_strcasecmp( pParamString, "xpos" ) )
// {
// pStructMem->m_vValues[XPOSITION] = RandomInterval( ReadInterval( pValueString ) );
// }
// else if ( !V_strcasecmp( pParamString, "ypos" ) )
// {
// pStructMem->m_vValues[YPOSITION] = RandomInterval( ReadInterval( pValueString ) );
// }
// else if ( !V_strcasecmp( pParamString, "zpos" ) )
// {
// pStructMem->m_vValues[ZPOSITION] = RandomInterval( ReadInterval( pValueString ) );
// }
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,46 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_SOURCE_INFO_H
#define SOS_OP_SOURCE_INFO_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
enum SOValueSource_t
{
SO_SRC_NONE = 0,
SO_SRC_EMITTER,
SO_SRC_ENTITY
};
//-----------------------------------------------------------------------------
// simple operator for setting a single position
//-----------------------------------------------------------------------------
struct CSosOperatorSourceInfo_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutEntityIndex, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutPosition, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutAngles, SO_VEC3 )
SOS_OUTPUT_FLOAT( m_flOutRadius, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutVolume, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutLevel, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutPitch, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutSourceCount, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputSourceIndex, SO_SINGLE )
SOValueSource_t m_nSource;
bool m_bGameExtraOrigins;
};
class CSosOperatorSourceInfo : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSourceInfo )
};
#endif // SOS_OP_SOURCE_INFO_H

View File

@@ -0,0 +1,194 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_spatialize.h"
#include "snd_dma.h"
#include "../../cl_splitscreen.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorSpatializeSpeakers
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorSpatializeSpeakers, "calc_spatialize_speakers" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flOutput, SO_SPEAKERS, "output" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputRadiusMax, SO_SINGLE, "input_radius_max" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputRadiusMin, SO_SINGLE, "input_radius_min" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputTimeStartStereoSpread, SO_SINGLE, "input_time_start_stereo_spread")
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputTimeFinishStereoSpread, SO_SINGLE, "input_time_finish_stereo_spread")
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputFinalStereoSpread, SO_SINGLE, "input_final_stereo_spread")
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputRearStereoScale, SO_SINGLE, "input_rear_stereo_scale" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputDistance, SO_SINGLE, "input_distance" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorSpatializeSpeakers, m_flInputPosition, SO_VEC3, "input_position" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorSpatializeSpeakers, "calc_spatialize_speakers" )
void CSosOperatorSpatializeSpeakers::SetDefaults( void *pVoidMem ) const
{
CSosOperatorSpatializeSpeakers_t *pStructMem = (CSosOperatorSpatializeSpeakers_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInputRadiusMax, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputRadiusMin, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputTimeStartStereoSpread, SO_SINGLE, 0.0)
SOS_INIT_INPUT_VAR( m_flInputTimeFinishStereoSpread, SO_SINGLE, 0.0)
SOS_INIT_INPUT_VAR( m_flInputFinalStereoSpread, SO_SINGLE, 0.0)
SOS_INIT_INPUT_VAR( m_flInputRearStereoScale, SO_SINGLE, 0.75 )
SOS_INIT_INPUT_VAR( m_flInputDistance, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputPosition, SO_VEC3, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutput, SO_SPEAKERS, 0.0 )
}
void CSosOperatorSpatializeSpeakers::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorSpatializeSpeakers_t *pStructMem = (CSosOperatorSpatializeSpeakers_t *)pVoidMem;
float flRadius = pStructMem->m_flInputRadiusMax[0];
float flRadiusMin = pStructMem->m_flInputRadiusMin[0];
float flDist = pStructMem->m_flInputDistance[0];
float flRearStereoScale = pStructMem->m_flInputRearStereoScale[0];
flRadius = flRadius > 0.0 ? flRadius : 0.0;
flRadiusMin = flRadiusMin > 0.0 ? flRadiusMin : 0.0;
flRadiusMin = flRadiusMin < flRadius ? flRadiusMin : flRadius;
float flMono = 0.0;
if ( flDist <= flRadiusMin )
{
flMono = 1.0;
}
else if ( flDist >= flRadius )
{
flMono = 0.0;
}
else
{
flMono = ((flDist - flRadiusMin) / ( flRadius - flRadiusMin ));
}
if (flDist > flRadiusMin && pStructMem->m_flInputTimeStartStereoSpread[0] != pStructMem->m_flInputTimeFinishStereoSpread[0])
{
float flElapsedSpatialized = pStructMem->m_flInputTimeStartStereoSpread[0];
float flElapsedMono = pStructMem->m_flInputTimeFinishStereoSpread[0];
float flMax = flElapsedMono > flElapsedSpatialized ? flElapsedMono : flElapsedSpatialized;
float flMin = flElapsedMono < flElapsedSpatialized ? flElapsedMono : flElapsedSpatialized;
float flBeginSpatialized = flElapsedSpatialized >= flElapsedMono ? 0.0f : 1.0f;
float flEndSpatialized = 1.0f - flBeginSpatialized * pStructMem->m_flInputFinalStereoSpread[0];
float flSpatialized = 1.0 - flMono;
float flElapsed = 0.0f;
if (pChannel->sfx && pChannel->sfx->pSource && pChannel->pMixer)
{
const int nSamples = pChannel->sfx->pSource->SampleCount();
const int nPos = pChannel->pMixer->GetSamplePosition();
if (nSamples > 0)
{
flElapsed = float(nPos) / float(nSamples);
}
}
if (flElapsed <= flMin)
{
flSpatialized *= flBeginSpatialized;
}
else if (flElapsed >= flMax)
{
flSpatialized *= flEndSpatialized;
}
else
{
float ratio = (flElapsed - flMin) / (flMax - flMin);
flSpatialized *= ratio*flEndSpatialized + (1.0 - ratio)*flBeginSpatialized;
}
flMono = 1.0f - flSpatialized;
}
// if ( flRadius > 0.0 && ( flDist < flRadius ) )
// {
// float interval = flRadius - flRadiusMin;
// flMono = flDist - interval;
//
// if ( flMono < 0.0 )
// flMono = 0.0;
//
// flMono /= interval;
//
// // flMono is 0.0 -> 1.0 from radius 100% to radius 50%
// flMono = 1.0 - flMono;
// }
// fill out channel volumes for single sound source location
Vector vSourceVector;
Vector vPosition;
vPosition[0] = pStructMem->m_flInputPosition[0];
vPosition[1] = pStructMem->m_flInputPosition[1];
vPosition[2] = pStructMem->m_flInputPosition[2];
float build_volumes[ MAX_SPLITSCREEN_CLIENTS ][SO_MAX_SPEAKERS] = { 0.0 };
// collect up all ss players and merge them here
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
VectorSubtract( vPosition, pScratchPad->m_vPlayerOrigin[ hh ], vSourceVector );
VectorNormalize( vSourceVector );
Device_SpatializeChannel( hh, &build_volumes[hh][0], vSourceVector, flMono, flRearStereoScale );
}
SND_MergeVolumes( build_volumes, pStructMem->m_flOutput );
}
void CSosOperatorSpatializeSpeakers::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorSpatializeSpeakers_t *pStructMem = (CSosOperatorSpatializeSpeakers_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorSpatializeSpeakers::OpHelp( ) const
{
}
void CSosOperatorSpatializeSpeakers::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorSpatializeSpeakers_t *pStructMem = (CSosOperatorSpatializeSpeakers_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,38 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_SPATIALIZE_H
#define SOS_OP_SPATIALIZE_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// spatialize a sound in the speakers
//-----------------------------------------------------------------------------
struct CSosOperatorSpatializeSpeakers_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputPosition, SO_VEC3 )
SOS_INPUT_FLOAT( m_flInputDistance, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputRadiusMax, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputRadiusMin, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputTimeStartStereoSpread, SO_SINGLE)
SOS_INPUT_FLOAT( m_flInputTimeFinishStereoSpread, SO_SINGLE)
SOS_INPUT_FLOAT( m_flInputFinalStereoSpread, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputRearStereoScale, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutput, SO_SPEAKERS )
};
class CSosOperatorSpatializeSpeakers : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSpatializeSpeakers )
};
#endif // SOS_OP_SPATIALIZE_H

View File

@@ -0,0 +1,168 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_start_entry.h"
#include "snd_dma.h"
// #include "cdll_engine_int.h"
#include "../../debugoverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorStartEntry
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorStartEntry, "sys_start_entry" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorStartEntry, m_flInputStart, SO_SINGLE, "input_start")
SOS_REGISTER_INPUT_FLOAT( CSosOperatorStartEntry, m_flInputStartDelay, SO_SINGLE, "input_start_delay")
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorStartEntry, "sys_start_entry" )
void CSosOperatorStartEntry::SetDefaults( void *pVoidMem ) const
{
CSosOperatorStartEntry_t *pStructMem = (CSosOperatorStartEntry_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInputStart, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputStartDelay, SO_SINGLE, 0.0 )
pStructMem->m_nScriptHash = SOUNDEMITTER_INVALID_HASH;
pStructMem->m_nHasStarted = 0;
pStructMem->m_bTriggerOnce = false;
}
void CSosOperatorStartEntry::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorStartEntry_t *pStructMem = (CSosOperatorStartEntry_t *)pVoidMem;
if( pStructMem->m_flInputStart[0] > 0.0 && !( pStructMem->m_nHasStarted && pStructMem->m_bTriggerOnce ) )
{
pStructMem->m_nHasStarted = 1;
if ( !g_pSoundEmitterSystem )
{
Log_Warning( LOG_SND_OPERATORS, OpColor, "Error: SoundEmitterSystem not initialized in engine!");
return;
}
if( !g_pSoundEmitterSystem->GetSoundNameForHash( pStructMem->m_nScriptHash ) )
{
Log_Warning( LOG_SND_OPERATORS, OpColor, "Error: Invalid SoundEntry hash %i in operator %s\n", pStructMem->m_nScriptHash , pStack->GetOperatorName( nOpIndex ));
return;
}
// try to copy all these from the current channel?
// this all needs to GET ORGANIZED, some values should come from params some from channel via?? param switch? use copy methods
// also, most of this is redundant in that "startsoundentry" calls this same function
// still a bit messy !!
StartSoundParams_t startParams;
CSoundParameters pScriptParams;
gender_t gender = GENDER_NONE;
if ( !g_pSoundEmitterSystem->GetParametersForSoundEx( "SoundSciptHandle ERROR", pStructMem->m_nScriptHash, pScriptParams, gender, true ) )
{
//DevWarning("Error: Unable to get parameters for soundentry %s", startParams.m_pSoundEntryName );
return;
}
// don't actually need the soundfile yet
// if ( !pScriptParams.soundname[0] )
// return;
// copy emitter params
startParams.staticsound = ( pScriptParams.channel == CHAN_STATIC ) ? true : false;
startParams.entchannel = pScriptParams.channel;
// inherits location and entity
VectorCopy( pScratchPad->m_vEmitterInfoOrigin, startParams.origin );
startParams.soundsource = pScratchPad->m_nSoundSource;
startParams.fvol = pScriptParams.volume;
startParams.soundlevel = pScriptParams.soundlevel;
// startParams.flags = sound.nFlags;
startParams.pitch = pScriptParams.pitch;
startParams.fromserver = false;
startParams.delay = pScriptParams.delay_msec;
// startParams.speakerentity = sound.nSpeakerEntity;
//startParams.m_bIsScriptHandle = ( pScriptParams.m_nSoundEntryVersion > 1 );
startParams.m_bIsScriptHandle = true;
startParams.m_nSoundScriptHash = pStructMem->m_nScriptHash;
g_pSoundOperatorSystem->QueueStartEntry( startParams, pStructMem->m_flInputStartDelay[0], false );
}
}
void CSosOperatorStartEntry::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorStartEntry_t *pStructMem = (CSosOperatorStartEntry_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sEntry Script Hash: %i\n", nLevel, " ", pStructMem->m_nScriptHash );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sEntry Name: %s\n", nLevel, " ", g_pSoundEmitterSystem->GetSoundNameForHash( pStructMem->m_nScriptHash ) );
}
void CSosOperatorStartEntry::OpHelp( ) const
{
}
void CSosOperatorStartEntry::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorStartEntry_t *pStructMem = (CSosOperatorStartEntry_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ))
{
}
else if ( !V_strcasecmp( pParamString, "entry_name" ) )
{
if ( !g_pSoundEmitterSystem )
{
DevWarning("Error: SoundEmitterSystem not initialized in engine!");
return;
}
pStructMem->m_nScriptHash = g_pSoundEmitterSystem->HashSoundName( pValueString );
if( !g_pSoundEmitterSystem->GetSoundNameForHash( pStructMem->m_nScriptHash ))
{
// DevMsg( "Error: Invalid SoundEntry index %i from entry %s operator %s", pStructMem->m_nScriptHandle, pValueString, pStack->GetOperatorName( nOpIndex ) );
DevMsg( "Error: Invalid SoundEntry hash %i from entry %s", pStructMem->m_nScriptHash, pValueString );
return;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,35 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_START_ENTRY_H
#define SOS_OP_START_ENTRY_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
struct CSosOperatorStartEntry_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputStart, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputStartDelay, SO_SINGLE )
HSOUNDSCRIPTHASH m_nScriptHash;
int m_nHasStarted;
bool m_bTriggerOnce;
};
class CSosOperatorStartEntry : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorStartEntry )
};
#endif // SOS_OP_START_ENTRY_H

View File

@@ -0,0 +1,363 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "snd_dma.h"
#include "sos_op.h"
#include "sos_entry_match_system.h"
#include "sos_op_stop_entry.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar snd_sos_show_operator_stop_entry("snd_sos_show_operator_stop_entry", "0", FCVAR_CHEAT );
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorStopEntry
//
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorStopEntry, "sys_stop_entries" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorStopEntry, m_flInputMaxVoices, SO_SINGLE, "input_max_entries" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorStopEntry, m_flInputStopDelay, SO_SINGLE, "input_stop_delay" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorStopEntry, m_flOutputVoicesMatching, SO_SINGLE, "output_entries_matching" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorStopEntry, m_flOutputIndexOfThis, SO_SINGLE, "output_this_matches_index" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorStopEntry, "sys_stop_entries" )
void CSosOperatorStopEntry::SetDefaults( void *pVoidMem ) const
{
CSosOperatorStopEntry_t *pStructMem = (CSosOperatorStopEntry_t *)pVoidMem;
V_strncpy( pStructMem->m_nMatchEntryName, "", sizeof(pStructMem->m_nMatchEntryName) );
V_strncpy( pStructMem->m_nMatchSoundName, "", sizeof(pStructMem->m_nMatchSoundName) );
pStructMem->m_bMatchEntry = false;
pStructMem->m_bMatchSound = false;
pStructMem->m_bMatchEntity = false;
pStructMem->m_bMatchChannel = false;
pStructMem->m_bMatchSubString = false;
pStructMem->m_bStopOldest = true;
pStructMem->m_bStopThis = false;
pStructMem->m_bMatchThisEntry = false;
pStructMem->m_bInvertMatch = false;
SOS_INIT_INPUT_VAR( m_flInputMaxVoices, SO_SINGLE, 1.0 )
SOS_INIT_INPUT_VAR( m_flInputStopDelay, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputVoicesMatching, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputIndexOfThis, SO_SINGLE, 0.0 )
}
static int __cdecl ChannelLongestElapsedTimeSortFunc( const int *nChannelIndexA, const int *nChannelIndexB )
{
return ( S_GetElapsedTimeByGuid( channels[ *nChannelIndexA ].guid ) > S_GetElapsedTimeByGuid( channels[ *nChannelIndexB ].guid ) );
}
// static int __cdecl ChannelLeastVolumeSortFunc( const int *nChannelIndexA, const int *nChannelIndexB )
// {
// return ( S_GetElapsedTimeByGuid( channels[ *nChannelIndexA ]. ) < S_GetElapsedTimeByGuid( channels[ *nChannelIndexB ].guid ) );
// }
void CSosOperatorStopEntry::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorStopEntry_t *pStructMem = (CSosOperatorStopEntry_t *)pVoidMem;
if( pStructMem->m_bStopThis )
{
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
if ( snd_sos_show_operator_stop_entry.GetInt() )
{
Print( pVoidMem, pStack, nOpIndex, 0 );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sStopping: %s : elapsed time: %f.2\n", 1, " ", g_pSoundEmitterSystem->GetSoundNameForHash( pChannel->m_nSoundScriptHash ), S_GetElapsedTime( pChannel ) * .001 );
}
g_pSoundOperatorSystem->QueueStopChannel( pChannel->guid, pStructMem->m_flInputStopDelay[0] );
return;
}
if( pScratchPad->m_nSoundScriptHash == SOUNDEMITTER_INVALID_HASH &&
pStructMem->m_bMatchThisEntry )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s scratchpad has invalid script hash, \"match_this_entry\" set to false\n", pStack->GetOperatorName( nOpIndex ));
pStructMem->m_bMatchThisEntry = false;
}
CSosEntryMatch sosEntryMatch;
sosEntryMatch.m_bMatchString1 = pStructMem->m_bMatchEntry;
V_strncpy( sosEntryMatch.m_nMatchString1, pStructMem->m_nMatchEntryName, sizeof( sosEntryMatch.m_nMatchString1 ) );
sosEntryMatch.m_bMatchString2 = pStructMem->m_bMatchSound;
V_strncpy( sosEntryMatch.m_nMatchString2, pStructMem->m_nMatchSoundName, sizeof( sosEntryMatch.m_nMatchString2 ) );
sosEntryMatch.m_bMatchSubString = pStructMem->m_bMatchSubString;
sosEntryMatch.m_bMatchInt1 = pStructMem->m_bMatchChannel;
sosEntryMatch.m_nMatchInt1 = pScratchPad->m_nChannel;
sosEntryMatch.m_bMatchInt2 = pStructMem->m_bMatchEntity;
sosEntryMatch.m_nMatchInt2 = pScratchPad->m_nSoundSource;
sosEntryMatch.m_bMatchInt3 = pStructMem->m_bMatchThisEntry;
sosEntryMatch.m_nMatchInt3 = pScratchPad->m_nSoundScriptHash;
CUtlVector< int > vMatchingIndices;
CChannelList list;
g_ActiveChannels.GetActiveChannels( list );
int nThisIndex = 0;
for ( int i = 0; i < list.Count(); i++ )
{
sosEntryMatch.m_bMatchString1 = pStructMem->m_bMatchEntry;
int ch_idx = list.GetChannelIndex(i);
// skip uninitiated entries (like this one!)
if ( ! channels[ch_idx].sfx )
{
continue;
}
if ( channels[ch_idx].sfx->pSource && channels[ch_idx].sfx->pSource->GetType() == CAudioSource::AUDIO_SOURCE_VOICE )
{
continue;
}
if( pChannel && &channels[ch_idx] == pChannel )
{
continue;
}
bool bIsAMatch = false;
bool bInvertMatch = false;
// this should probably explicitly check for soundentry_version
if( channels[ch_idx].m_nSoundScriptHash == SOUNDEMITTER_INVALID_HASH && pStructMem->m_bMatchEntry )
{
if( pStructMem->m_bInvertMatch )
{
bInvertMatch = true;
}
else
{
continue;
}
}
if( !bInvertMatch )
{
CSosEntryMatch sosChanMatch;
if ( sosEntryMatch.m_bMatchString1 && channels[ch_idx].m_nSoundScriptHash != SOUNDEMITTER_INVALID_HASH )
{
const char *pEntryName = g_pSoundEmitterSystem->GetSoundNameForHash( channels[ch_idx].m_nSoundScriptHash );
if ( !pEntryName )
{
pEntryName = "";
}
V_strncpy( sosChanMatch.m_nMatchString1, pEntryName, sizeof( sosChanMatch.m_nMatchString1 ) );
}
else
{
sosEntryMatch.m_bMatchString1 = false;
}
if ( sosEntryMatch.m_bMatchString2 )
{
channels[ch_idx].sfx->GetFileName( sosChanMatch.m_nMatchString2, sizeof( sosChanMatch.m_nMatchString2 ) );
}
sosChanMatch.m_nMatchInt1 = channels[ch_idx].entchannel;
sosChanMatch.m_nMatchInt2 = channels[ch_idx].soundsource;
sosChanMatch.m_nMatchInt3 = channels[ch_idx].m_nSoundScriptHash;
bIsAMatch = sosEntryMatch.IsAMatch( &sosChanMatch );
bIsAMatch = ( bIsAMatch && !pStructMem->m_bInvertMatch ) || ( !bIsAMatch && pStructMem->m_bInvertMatch );
}
if ( bIsAMatch || bInvertMatch )
{
int nNewIndex = vMatchingIndices.AddToTail( ch_idx );
if( pChannel && &channels[ ch_idx ] == pChannel )
{
nThisIndex = nNewIndex;
}
}
}
pStructMem->m_flOutputVoicesMatching[0] = ( float ) vMatchingIndices.Count();
pStructMem->m_flOutputIndexOfThis[0] = ( float ) nThisIndex;
if ( vMatchingIndices.Count() > (int) pStructMem->m_flInputMaxVoices[0] )
{
if( pStructMem->m_bStopOldest )
{
vMatchingIndices.Sort( &ChannelLongestElapsedTimeSortFunc );
}
for( int i = (int) pStructMem->m_flInputMaxVoices[0]; i < vMatchingIndices.Count(); i++ )
{
if ( snd_sos_show_operator_stop_entry.GetInt() )
{
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sStopping: %s : elapsed time: %f.2\n", 1, " ", g_pSoundEmitterSystem->GetSoundNameForHash( channels[ vMatchingIndices[ i ] ].m_nSoundScriptHash ), S_GetElapsedTime( &channels[ vMatchingIndices[ i ] ] ) * .001 );
}
g_pSoundOperatorSystem->QueueStopChannel( channels[ vMatchingIndices[ i ] ].guid, pStructMem->m_flInputStopDelay[0] );
}
}
}
void CSosOperatorStopEntry::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorStopEntry_t *pStructMem = (CSosOperatorStopEntry_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
// Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sNumber Allowed: %i\n", nLevel, " ", pStructMem->m_nNumAllowed );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_entry: %s\n", nLevel, " ", pStructMem->m_bMatchEntry ? pStructMem->m_nMatchEntryName : "\"\"" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_sound: %s\n", nLevel, " ", pStructMem->m_bMatchSound ? pStructMem->m_nMatchSoundName : "\"\"" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_entity: %s\n", nLevel, " ", pStructMem->m_bMatchEntity ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_channel: %s\n", nLevel, " ", pStructMem->m_bMatchEntity ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_substring: %s\n", nLevel, " ", pStructMem->m_bMatchSubString ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_this_entry: %s\n", nLevel, " ", pStructMem->m_bMatchThisEntry ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sstop_oldest: %s\n", nLevel, " ", pStructMem->m_bStopOldest ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sinvert_match: %s\n", nLevel, " ", pStructMem->m_bInvertMatch ? "true" : "false" );
}
void CSosOperatorStopEntry::OpHelp( ) const
{
}
void CSosOperatorStopEntry::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorStopEntry_t *pStructMem = (CSosOperatorStopEntry_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "match_this_entry" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchThisEntry = true;
}
else
{
pStructMem->m_bMatchChannel = false;
}
}
else if ( !V_strcasecmp( pParamString, "match_entry" ) )
{
pStructMem->m_bMatchEntry = true;
V_strncpy( pStructMem->m_nMatchEntryName, pValueString, sizeof(pStructMem->m_nMatchEntryName) );
}
else if ( !V_strcasecmp( pParamString, "match_sound" ) )
{
pStructMem->m_bMatchSound = true;
V_strncpy( pStructMem->m_nMatchSoundName, pValueString, sizeof(pStructMem->m_nMatchSoundName) );
}
else if ( !V_strcasecmp( pParamString, "match_entity" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchEntity = true;
}
else
{
pStructMem->m_bMatchEntity = false;
}
}
else if ( !V_strcasecmp( pParamString, "match_channel" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchChannel = true;
}
else
{
pStructMem->m_bMatchChannel = false;
}
}
else if ( !V_strcasecmp( pParamString, "match_substring" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bMatchSubString = true;
}
else
{
pStructMem->m_bMatchSubString = false;
}
}
else if ( !V_strcasecmp( pParamString, "stop_oldest" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bStopOldest = true;
}
else
{
pStructMem->m_bStopOldest = false;
}
}
else if ( !V_strcasecmp( pParamString, "stop_this_entry" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bStopThis = true;
}
else
{
pStructMem->m_bStopThis = false;
}
}
else if ( !V_strcasecmp( pParamString, "invert_match" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bInvertMatch = true;
}
else
{
pStructMem->m_bInvertMatch = false;
}
}
// else if ( !V_strcasecmp( pParamString, "num_allowed" ) )
// {
// pStructMem->m_nNumAllowed = V_atoi( pValueString );
// }
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,44 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_STOP_ENTRY_H
#define SOS_OP_STOP_ENTRY_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// stop other sound entries
//-----------------------------------------------------------------------------
struct CSosOperatorStopEntry_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputMaxVoices, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputStopDelay, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputVoicesMatching, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputIndexOfThis, SO_SINGLE )
char m_nMatchEntryName[64];
bool m_bMatchEntry;
char m_nMatchSoundName[64];
bool m_bMatchSound;
bool m_bMatchSubString;
bool m_bMatchEntity;
bool m_bMatchChannel;
bool m_bStopOldest;
bool m_bStopThis;
bool m_bMatchThisEntry;
bool m_bInvertMatch;
};
class CSosOperatorStopEntry : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorStopEntry )
};
#endif // SOS_OP_STOP_ENTRY_H

View File

@@ -0,0 +1,82 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "snd_dma.h"
#include "sos_op.h"
#include "sos_op_sys_time.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorSysTime
// Setting a single, simple scratch pad Expression
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorSysTime, "get_sys_time" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSysTime, m_flOutputClientElapsed, SO_SINGLE, "output_client_time" );
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorSysTime, m_flOutputHostElapsed, SO_SINGLE, "output_host_time" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorSysTime, "get_sys_time" )
void CSosOperatorSysTime::SetDefaults( void *pVoidMem ) const
{
CSosOperatorSysTime_t *pStructMem = (CSosOperatorSysTime_t *)pVoidMem;
SOS_INIT_OUTPUT_VAR( m_flOutputClientElapsed, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputHostElapsed, SO_SINGLE, 0.0 )
}
void CSosOperatorSysTime::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorSysTime_t *pStructMem = (CSosOperatorSysTime_t *)pVoidMem;
pStructMem->m_flOutputHostElapsed[0] = g_pSoundServices->GetHostTime();
pStructMem->m_flOutputClientElapsed[0] = g_pSoundServices->GetClientTime();
}
void CSosOperatorSysTime::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorSysTime_t *pStructMem = (CSosOperatorSysTime_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorSysTime::OpHelp( ) const
{
}
void CSosOperatorSysTime::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorSysTime_t *pStructMem = (CSosOperatorSysTime_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,33 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_SYS_TIME_H
#define SOS_OP_SYS_TIME_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// get elapsed time
//-----------------------------------------------------------------------------
struct CSosOperatorSysTime_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutputClientElapsed, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputHostElapsed, SO_SINGLE )
};
class CSosOperatorSysTime : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorSysTime )
};
#endif // SOS_OP_SYS_TIME_H

View File

@@ -0,0 +1,745 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "snd_dma.h"
#include "sos_op.h"
#include "sos_op_tracks.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorGetTrackSyncPoint_t
//
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorGetTrackSyncPoint, "get_track_syncpoint" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorGetTrackSyncPoint, m_flInputMinTimeToNextSync, SO_SINGLE, "input_min_time_to_next_sync" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorGetTrackSyncPoint, m_flInputMaxTimeToNextSync, SO_SINGLE, "input_max_time_to_next_sync" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorGetTrackSyncPoint, m_flOutputFirstSyncPoint, SO_SINGLE, "output_first_syncpoint" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorGetTrackSyncPoint, m_flOutputLastSyncPoint, SO_SINGLE, "output_last_syncpoint" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorGetTrackSyncPoint, m_flOutputTimeToNextSync, SO_SINGLE, "output_time_to_next_syncpoint" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorGetTrackSyncPoint, "get_track_syncpoint" )
void CSosOperatorGetTrackSyncPoint::SetDefaults( void *pVoidMem ) const
{
CSosOperatorGetTrackSyncPoint_t *pStructMem = (CSosOperatorGetTrackSyncPoint_t *)pVoidMem;
V_strncpy( pStructMem->m_nMatchEntryName, "", sizeof(pStructMem->m_nMatchEntryName) );
V_strncpy( pStructMem->m_nSyncPointListName, "", sizeof(pStructMem->m_nSyncPointListName ) );
/// V_strncpy( pStructMem->m_nMatchSoundName, "", sizeof(pStructMem->m_nMatchSoundName) );
// pStructMem->m_bMatchEntry = false;
// pStructMem->m_bMatchSound = false;
// pStructMem->m_bMatchEntity = false;
// pStructMem->m_bMatchChannel = false;
// pStructMem->m_bMatchSubString = false;
// pStructMem->m_bStopOldest = true;
// pStructMem->m_bStopThis = false;
SOS_INIT_INPUT_VAR( m_flInputMinTimeToNextSync, SO_SINGLE, 0.0 )
SOS_INIT_INPUT_VAR( m_flInputMaxTimeToNextSync, SO_SINGLE, 1000.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputTimeToNextSync, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputFirstSyncPoint, SO_SINGLE, 0.0 )
pStructMem->m_bDataFromThis = false;
pStructMem->m_bMatchEntry = false;
pStructMem->m_bSubtractMinTimeToSync = true;
pStructMem->m_bSubtractMinTimeToSyncFromLastSync = false;
pStructMem->m_bSubtractFirstSyncFromLastSync = true;
}
static int __cdecl ChannelLongestElapsedTimeSortFunc( const int *nChannelIndexA, const int *nChannelIndexB )
{
return ( S_GetElapsedTimeByGuid( channels[ *nChannelIndexA ].guid ) > S_GetElapsedTimeByGuid( channels[ *nChannelIndexB ].guid ) );
}
// static int __cdecl ChannelLeastVolumeSortFunc( const int *nChannelIndexA, const int *nChannelIndexB )
// {
// return ( S_GetElapsedTimeByGuid( channels[ *nChannelIndexA ]. ) < S_GetElapsedTimeByGuid( channels[ *nChannelIndexB ].guid ) );
// }
void CSosOperatorGetTrackSyncPoint::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorGetTrackSyncPoint_t *pStructMem = (CSosOperatorGetTrackSyncPoint_t *)pVoidMem;
track_data_t trackData;
pStack->GetTrackData( trackData );
// HSOUNDSCRIPTHASH nSoundScriptHashHandle = SOUNDEMITTER_INVALID_HASH;
float fElapsedTime = 0.0;
float fDuration = 0.0;
KeyValues *pSyncPointList = NULL;
if( ! pStructMem->m_bDataFromThis )
{
CChannelList list;
g_ActiveChannels.GetActiveChannels( list );
for ( int i = 0; i < list.Count(); i++ )
{
int ch_idx = list.GetChannelIndex(i);
// skip uninitiated entries (like this one!)
if ( ! channels[ch_idx].sfx )
{
continue;
}
if( pChannel && &channels[ch_idx] == pChannel )
{
continue;
}
// this should probably explicitly check for soundentry_version
if( channels[ch_idx].m_nSoundScriptHash == SOUNDEMITTER_INVALID_HASH )
{
continue;
}
KeyValues *pOperatorKV = g_pSoundEmitterSystem->GetOperatorKVByHandle( channels[ch_idx].m_nSoundScriptHash );
if ( !pOperatorKV )
{
// Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s cannot find operator KV data\n", pStack->GetOperatorName( nOpIndex ));
continue;
}
track_data_t chanTrackData;
S_GetTrackData( pOperatorKV, chanTrackData );
if( chanTrackData.m_nTrackNumber != trackData.m_nSyncTrackNumber )
{
continue;
}
// getting elapsed time from entry time due to mp3 weirdness
fElapsedTime = S_GetElapsedTimeByGuid( channels[ ch_idx ].guid ) * 0.01;
// if ( channels[ch_idx].m_pStackList )
// {
// CSosOperatorStack *pTheStack = NULL;
// pTheStack = channels[ch_idx].m_pStackList->GetStack( CSosOperatorStack::SOS_UPDATE );
//
// if ( pTheStack )
// {
// fElapsedTime = pTheStack->GetElapsedTime();
// }
// }
fDuration = chanTrackData.m_flEndPoint - chanTrackData.m_flStartPoint;
// fDuration = S_SoundDuration( &channels[ ch_idx ] );
fElapsedTime = fmod( fElapsedTime, fDuration );
pSyncPointList = pStack->GetSyncPointsKV( pOperatorKV, pStructMem->m_nSyncPointListName );
break;
}
}
else
{
// nSoundScriptHashHandle = pStack->GetScriptHash();
pSyncPointList = pStack->GetSyncPointsKV( pStructMem->m_nSyncPointListName );
}
CUtlVector< float > vSyncPoints;
if( pSyncPointList )
{
for ( KeyValues *pValue = pSyncPointList->GetFirstValue(); pValue; pValue = pValue->GetNextValue() )
{
vSyncPoints.AddToTail( pValue->GetFloat() );
}
}
else
{
//Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s cannot find track syncpoint KV data\n", pStack->GetOperatorName( nOpIndex ));
return;
}
float fMinTimeToSyncPoint = pStructMem->m_flInputMaxTimeToNextSync[0];
for( int i = 0; i < vSyncPoints.Count(); i++ )
{
float fDiff = vSyncPoints[i] - fElapsedTime;
if( fDiff > 0 && fDiff < fMinTimeToSyncPoint && fDiff > pStructMem->m_flInputMinTimeToNextSync[0] )
{
fMinTimeToSyncPoint = fDiff;
}
}
fMinTimeToSyncPoint = fMinTimeToSyncPoint - ( pStructMem->m_bSubtractMinTimeToSync ? pStructMem->m_flInputMinTimeToNextSync[0] : 0.0 );
pStructMem->m_flOutputTimeToNextSync[0] = fMinTimeToSyncPoint;
float fLastSyncPoint = 0.0;
int nIndexToLastSyncPoint = vSyncPoints.Count() > 0 ? vSyncPoints.Count() - 1 : -1;
if( nIndexToLastSyncPoint >= 0 )
{
fLastSyncPoint = vSyncPoints[ nIndexToLastSyncPoint ] - ( pStructMem->m_bSubtractMinTimeToSyncFromLastSync ? pStructMem->m_flInputMinTimeToNextSync[0] : 0.0 );
fLastSyncPoint = fLastSyncPoint - ( pStructMem->m_bSubtractFirstSyncFromLastSync ? vSyncPoints[0] : 0.0 );
}
pStructMem->m_flOutputLastSyncPoint[0] = fLastSyncPoint;
if( vSyncPoints.Count() > 0 )
{
pStructMem->m_flOutputFirstSyncPoint[0] = vSyncPoints[0];
}
else
{
pStructMem->m_flOutputFirstSyncPoint[0] = 0.0;
}
// pStructMem->m_flOutputVoicesMatching[0] = ( float ) vMatchingIndices.Count();
// pStructMem->m_flOutputIndexOfThis[0] = ( float ) nThisIndex;
//
}
void CSosOperatorGetTrackSyncPoint::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorGetTrackSyncPoint_t *pStructMem = (CSosOperatorGetTrackSyncPoint_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
// Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sNumber Allowed: %i\n", nLevel, " ", pStructMem->m_nNumAllowed );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*smatch_entry: %s\n", nLevel, " ", pStructMem->m_bMatchEntry ? pStructMem->m_nMatchEntryName : "\"\"" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*ssyncpoint_list: %s\n", nLevel, " ", pStructMem->m_nSyncPointListName );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*sthis_entry_syncpoints: %s\n", nLevel, " ", pStructMem->m_bDataFromThis ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*ssubtract_min_time_from_next: %s\n", nLevel, " ", pStructMem->m_bSubtractMinTimeToSync ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*ssubtract_min_time_from_last: %s\n", nLevel, " ", pStructMem->m_bSubtractMinTimeToSyncFromLastSync ? "true" : "false" );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*ssubtract_first_from_last: %s\n", nLevel, " ", pStructMem->m_bSubtractFirstSyncFromLastSync ? "true" : "false" );
}
void CSosOperatorGetTrackSyncPoint::OpHelp( ) const
{
}
void CSosOperatorGetTrackSyncPoint::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorGetTrackSyncPoint_t *pStructMem = (CSosOperatorGetTrackSyncPoint_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "match_entry" ) )
{
pStructMem->m_bMatchEntry = true;
V_strncpy( pStructMem->m_nMatchEntryName, pValueString, sizeof(pStructMem->m_nMatchEntryName) );
}
else if ( !V_strcasecmp( pParamString, "syncpoint_list" ) )
{
V_strncpy( pStructMem->m_nSyncPointListName, pValueString, sizeof( pStructMem->m_nSyncPointListName ) );
}
else if ( !V_strcasecmp( pParamString, "this_entry_syncpoints" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bDataFromThis = true;
}
else
{
pStructMem->m_bDataFromThis = false;
}
}
else if ( !V_strcasecmp( pParamString, "subtract_min_time_from_next" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bSubtractMinTimeToSync = true;
}
else
{
pStructMem->m_bSubtractMinTimeToSync = false;
}
}
else if ( !V_strcasecmp( pParamString, "subtract_min_time_from_last" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bSubtractMinTimeToSyncFromLastSync = true;
}
else
{
pStructMem->m_bSubtractMinTimeToSyncFromLastSync = false;
}
}
else if ( !V_strcasecmp( pParamString, "subtract_first_from_last" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bSubtractFirstSyncFromLastSync = true;
}
else
{
pStructMem->m_bSubtractFirstSyncFromLastSync = false;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorQueueToTrack_t
//
//-----------------------------------------------------------------------------
ConVar snd_sos_show_queuetotrack("snd_sos_show_queuetotrack", "0", FCVAR_CHEAT );
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorQueueToTrack, "track_queue" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorQueueToTrack, m_flOutputTimeToNextSync, SO_SINGLE, "output_time_to_next_syncpoint" )
SOS_REGISTER_OUTPUT_FLOAT( CSosOperatorQueueToTrack, m_flOutputTimeToStart, SO_SINGLE, "output_time_to_start" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorQueueToTrack, "track_queue" )
void CSosOperatorQueueToTrack::SetDefaults( void *pVoidMem ) const
{
CSosOperatorQueueToTrack_t *pStructMem = (CSosOperatorQueueToTrack_t *)pVoidMem;
V_strncpy( pStructMem->m_nSyncPointListName, "", sizeof(pStructMem->m_nSyncPointListName ) );
SOS_INIT_OUTPUT_VAR( m_flOutputTimeToNextSync, SO_SINGLE, 0.0 )
SOS_INIT_OUTPUT_VAR( m_flOutputTimeToStart, SO_SINGLE, 0.0 )
}
void CSosOperatorQueueToTrack::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorQueueToTrack_t *pStructMem = (CSosOperatorQueueToTrack_t *)pVoidMem;
track_data_t trackData;
pStack->GetTrackData( trackData );
float fElapsedTime = 0.0;
float fDuration = 0.0;
float flMinTimeToSyncPoint = 0.0;
KeyValues *pSyncPointList = NULL;
channel_t *pCurrentChannelOnThisTrack = NULL;
int nThisTrackIndex = g_pSoundOperatorSystem->m_vTrackDict.Find( trackData.m_pTrackName );
if( g_pSoundOperatorSystem->m_vTrackDict.IsValidIndex( nThisTrackIndex ) )
{
pCurrentChannelOnThisTrack = g_pSoundOperatorSystem->m_vTrackDict[nThisTrackIndex];
if( pCurrentChannelOnThisTrack && pCurrentChannelOnThisTrack->m_nSoundScriptHash != SOUNDEMITTER_INVALID_HASH )
{
KeyValues *pOperatorKV = g_pSoundEmitterSystem->GetOperatorKVByHandle( pCurrentChannelOnThisTrack->m_nSoundScriptHash );
if ( pOperatorKV )
{
track_data_t thatTrackData;
S_GetTrackData( pOperatorKV, thatTrackData );
if( !S_TrackHasPriority( trackData, thatTrackData ) )
{
if( snd_sos_show_queuetotrack.GetInt() )
{
Log_Warning( LOG_SND_OPERATORS, "QUEUETOTRACK: %s priority blocked by %s\n", g_pSoundEmitterSystem->GetSoundNameForHash( pStack->GetScriptHash() ), g_pSoundEmitterSystem->GetSoundNameForHash( pCurrentChannelOnThisTrack->m_nSoundScriptHash ));
}
pScratchPad->m_flDelayToQueue = 0.0;
pScratchPad->m_bBlockStart = true;
return;
}
}
}
}
// if there's nothing playing on the sync track do we just play?
// currently YES
channel_t *pCurrentChannelOnSyncTrack = NULL;
int nTrackIndex = g_pSoundOperatorSystem->m_vTrackDict.Find( trackData.m_pSyncTrackName );
if( g_pSoundOperatorSystem->m_vTrackDict.IsValidIndex( nTrackIndex ) )
{
pCurrentChannelOnSyncTrack = g_pSoundOperatorSystem->m_vTrackDict[nTrackIndex];
if( pCurrentChannelOnSyncTrack && pCurrentChannelOnSyncTrack->m_nSoundScriptHash != SOUNDEMITTER_INVALID_HASH )
{
KeyValues *pOperatorKV = g_pSoundEmitterSystem->GetOperatorKVByHandle( pCurrentChannelOnSyncTrack->m_nSoundScriptHash );
if ( pOperatorKV )
{
track_data_t syncTrackData;
S_GetTrackData( pOperatorKV, syncTrackData );
fElapsedTime = S_GetElapsedTimeByGuid( pCurrentChannelOnSyncTrack->guid ) * 0.01;
// fDuration = S_SoundDuration( pCurrentChannelOnSyncTrack );
fDuration = syncTrackData.m_flEndPoint - syncTrackData.m_flStartPoint;
fElapsedTime = fmod( fElapsedTime, fDuration );
pSyncPointList = pStack->GetSyncPointsKV( pOperatorKV, pStructMem->m_nSyncPointListName );
// collect up sync points
CUtlVector< float > vSyncPoints;
if( pSyncPointList )
{
for ( KeyValues *pValue = pSyncPointList->GetFirstValue(); pValue; pValue = pValue->GetNextValue() )
{
vSyncPoints.AddToTail( pValue->GetFloat() );
}
}
else
{
//Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s cannot find track syncpoint KV data\n", pStack->GetOperatorName( nOpIndex ));
return;
}
flMinTimeToSyncPoint = fDuration;
bool bFoundSyncPoint = false;
for( int i = 0; i < vSyncPoints.Count(); i++ )
{
float fDiff = vSyncPoints[i] - fElapsedTime;
if( fDiff > 0 && fDiff < flMinTimeToSyncPoint && fDiff > trackData.m_flStartPoint )
{
bFoundSyncPoint = true;
flMinTimeToSyncPoint = fDiff;
}
}
if( bFoundSyncPoint )
{
pStructMem->m_flOutputTimeToNextSync[0] = flMinTimeToSyncPoint;
// subtract start point
flMinTimeToSyncPoint = flMinTimeToSyncPoint - trackData.m_flStartPoint;
pStructMem->m_flOutputTimeToStart[0] = flMinTimeToSyncPoint;
}
else
{
pStructMem->m_flOutputTimeToNextSync[0] = 0.0;
pStructMem->m_flOutputTimeToStart[0] = 0.0;
flMinTimeToSyncPoint = 0.0;
}
if( snd_sos_show_queuetotrack.GetInt() )
{
Log_Warning( LOG_SND_OPERATORS, "QUEUETOTRACK: %s queued with a delay of %f\n", g_pSoundEmitterSystem->GetSoundNameForHash( pStack->GetScriptHash() ), flMinTimeToSyncPoint);
}
}
}
}
pScratchPad->m_flDelayToQueue = flMinTimeToSyncPoint;
}
void CSosOperatorQueueToTrack::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorQueueToTrack_t *pStructMem = (CSosOperatorQueueToTrack_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*ssyncpoint_list: %s\n", nLevel, " ", pStructMem->m_nSyncPointListName );
}
void CSosOperatorQueueToTrack::OpHelp( ) const
{
}
void CSosOperatorQueueToTrack::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorQueueToTrack_t *pStructMem = (CSosOperatorQueueToTrack_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "syncpoint_list" ) )
{
V_strncpy( pStructMem->m_nSyncPointListName, pValueString, sizeof( pStructMem->m_nSyncPointListName ) );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorPlayOnTrack_t
//
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorPlayOnTrack, "track_update" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorPlayOnTrack, "track_update" )
void CSosOperatorPlayOnTrack::SetDefaults( void *pVoidMem ) const
{
CSosOperatorPlayOnTrack_t *pStructMem = (CSosOperatorPlayOnTrack_t *)pVoidMem;
pStructMem->m_nAutoQueueEndPointScriptHash = SOUNDEMITTER_INVALID_HASH;
pStructMem->m_trackData.SetDefaults();
pStructMem->m_bHasTriggeredAutoQue = false;
pStructMem->m_bStopChannelOnTrack = true;
}
void CSosOperatorPlayOnTrack::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
if( !pChannel )
{
Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s requires valid channel pointer, being called without one\n", pStack->GetOperatorName( nOpIndex ));
return;
}
CSosOperatorPlayOnTrack_t *pStructMem = (CSosOperatorPlayOnTrack_t *)pVoidMem;
// first time
if( !pStructMem->m_bHasExecuted )
{
if( pStructMem->m_bStopChannelOnTrack )
{
g_pSoundOperatorSystem->StopChannelOnTrack( pStructMem->m_trackData.m_pTrackName, false, pStructMem->m_trackData.m_flStartPoint );
}
g_pSoundOperatorSystem->SetChannelOnTrack( pStructMem->m_trackData.m_pTrackName, pChannel );
}
// in the case that the incoming cue has a starttime longer than the time left on the track, there will be silence.
// punt for now
// ( pStack->GetStopType() == SOS_STOP_NONE || ( pStack->GetStopType() == SOS_STOP_QUEUE ) ) ) //&& ( pStack->GetStopTime() > pStructMem->m_trackData.m_flStartPoint )
if ( pStructMem->m_nAutoQueueEndPointScriptHash != SOUNDEMITTER_INVALID_HASH &&
pStack->GetStopType() == SOS_STOP_NONE )
{
float fThisChannelsElapsedTime = S_GetElapsedTime( pChannel ) * 0.01;
float fTimeToTrigger = pStructMem->m_trackData.m_flEndPoint - pStructMem->m_fAutoQueueStartPoint;
if( ( fThisChannelsElapsedTime >= fTimeToTrigger ) &&
!pStructMem->m_bHasTriggeredAutoQue )
{
// copied from start_entry.... UGH, PROPAGATING UGLINESS!!
StartSoundParams_t startParams;
CSoundParameters pScriptParams;
gender_t gender = GENDER_NONE;
if ( !g_pSoundEmitterSystem->GetParametersForSoundEx( "SoundSciptHandle ERROR", pStructMem->m_nAutoQueueEndPointScriptHash, pScriptParams, gender, true ) )
{
//DevWarning("Error: Unable to get parameters for soundentry %s", startParams.m_pSoundEntryName );
return;
}
// don't actually need the soundfile yet
// if ( !pScriptParams.soundname[0] )
// return;
// copy emitter params
startParams.staticsound = ( pScriptParams.channel == CHAN_STATIC ) ? true : false;
startParams.entchannel = pScriptParams.channel;
// inherits location and entity
VectorCopy( pScratchPad->m_vEmitterInfoOrigin, startParams.origin );
startParams.soundsource = pScratchPad->m_nSoundSource;
startParams.fvol = pScriptParams.volume;
startParams.soundlevel = pScriptParams.soundlevel;
// startParams.flags = sound.nFlags;
startParams.pitch = pScriptParams.pitch;
startParams.fromserver = false;
startParams.delay = pScriptParams.delay_msec;
// startParams.speakerentity = sound.nSpeakerEntity;
//startParams.m_bIsScriptHandle = ( pScriptParams.m_nSoundEntryVersion > 1 );
startParams.m_bIsScriptHandle = true;
startParams.m_nSoundScriptHash = pStructMem->m_nAutoQueueEndPointScriptHash;
g_pSoundOperatorSystem->QueueStartEntry( startParams, 0.0, false );
pStructMem->m_bHasTriggeredAutoQue = true;
g_pSoundOperatorSystem->RemoveChannelFromTrack( pStructMem->m_trackData.m_pTrackName, pStack->GetChannelGuid() );
}
}
}
void CSosOperatorPlayOnTrack::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
// CSosOperatorPlayOnTrack_t *pStructMem = (CSosOperatorPlayOnTrack_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
}
void CSosOperatorPlayOnTrack::OpHelp( ) const
{
}
void CSosOperatorPlayOnTrack::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorPlayOnTrack_t *pStructMem = (CSosOperatorPlayOnTrack_t *)pVoidMem;
pStack->GetTrackData( pStructMem->m_trackData );
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "autoqueue_entry_at_end_point" ) )
{
if ( !g_pSoundEmitterSystem )
{
DevWarning("Error: SoundEmitterSystem not initialized in engine!");
return;
}
pStructMem->m_nAutoQueueEndPointScriptHash = g_pSoundEmitterSystem->HashSoundName( pValueString );
if( !g_pSoundEmitterSystem->GetSoundNameForHash( pStructMem->m_nAutoQueueEndPointScriptHash ))
{
// DevMsg( "Error: Invalid SoundEntry index %i from entry %s operator %s", pStructMem->m_nScriptHandle, pValueString, pStack->GetOperatorName( nOpIndex ) );
DevMsg( "Error: Invalid SoundEntry hash %i from entry %s", pStructMem->m_nAutoQueueEndPointScriptHash, pValueString );
pStructMem->m_nAutoQueueEndPointScriptHash = SOUNDEMITTER_INVALID_HASH;
}
else
{
KeyValues *pOperatorKV = g_pSoundEmitterSystem->GetOperatorKVByHandle( pStructMem->m_nAutoQueueEndPointScriptHash );
if ( !pOperatorKV )
{
// Log_Warning( LOG_SND_OPERATORS, "Error: Sound operator %s cannot find operator KV data\n", pStack->GetOperatorName( nOpIndex ));
pStructMem->m_fAutoQueueStartPoint = 0.0;
}
else
{
track_data_t trackData;
S_GetTrackData( pOperatorKV, trackData );
pStructMem->m_fAutoQueueStartPoint = trackData.m_flStartPoint;
}
}
}
else if ( !V_strcasecmp( pParamString, "stop_channel_on_track" ) )
{
if ( !V_strcasecmp( pValueString, "true" ) )
{
pStructMem->m_bStopChannelOnTrack = true;
}
else if ( !V_strcasecmp( pValueString, "false" ) )
{
pStructMem->m_bStopChannelOnTrack = false;
}
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s Unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}
//-----------------------------------------------------------------------------
// CSosOperatorStopTrack_t
//
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorStopTrack, "track_stop" )
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorStopTrack, "track_stop" )
void CSosOperatorStopTrack::SetDefaults( void *pVoidMem ) const
{
CSosOperatorStopTrack_t *pStructMem = (CSosOperatorStopTrack_t *)pVoidMem;
pStructMem->m_nTrackName[0] = 0;
}
void CSosOperatorStopTrack::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorStopTrack_t *pStructMem = (CSosOperatorStopTrack_t *)pVoidMem;
g_pSoundOperatorSystem->StopChannelOnTrack( pStructMem->m_nTrackName );
// add stopall and delay as "features"
// g_pSoundOperatorSystem->StopChannelOnTrack( pStructMem->m_nTrackName, bStopAllQueued, flDelay );
}
void CSosOperatorStopTrack::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
CSosOperatorStopTrack_t *pStructMem = (CSosOperatorStopTrack_t *)pVoidMem;
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
Log_Msg( LOG_SND_OPERATORS, OpColor, "%*strack: %s\n", nLevel, " ", pStructMem->m_nTrackName );
}
void CSosOperatorStopTrack::OpHelp( ) const
{
}
void CSosOperatorStopTrack::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorStopTrack_t *pStructMem = (CSosOperatorStopTrack_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else if ( !V_strcasecmp( pParamString, "track_name" ) )
{
V_strncpy( pStructMem->m_nTrackName, pValueString, sizeof(pStructMem->m_nTrackName ) );
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s Unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,104 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_TRACKS_H
#define SOS_OP_TRACKS_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// get sync data
//-----------------------------------------------------------------------------
struct CSosOperatorGetTrackSyncPoint_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInputMinTimeToNextSync, SO_SINGLE )
SOS_INPUT_FLOAT( m_flInputMaxTimeToNextSync, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputFirstSyncPoint, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputLastSyncPoint, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputTimeToNextSync, SO_SINGLE )
//
char m_nSyncPointListName[64];
char m_nMatchEntryName[64];
bool m_bMatchEntry;
// bool m_bMatchEntry;
// char m_nMatchSoundName[64];
// bool m_bMatchSound;
// bool m_bMatchSubString;
// bool m_bMatchEntity;
// bool m_bMatchChannel;
// bool m_bStopOldest;
// bool m_bStopThis;
bool m_bDataFromThis;
bool m_bSubtractMinTimeToSync;
bool m_bSubtractMinTimeToSyncFromLastSync;
bool m_bSubtractFirstSyncFromLastSync;
};
class CSosOperatorGetTrackSyncPoint : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorGetTrackSyncPoint )
};
//-----------------------------------------------------------------------------
// queue to a track
//-----------------------------------------------------------------------------
struct CSosOperatorQueueToTrack_t : CSosOperator_t
{
SOS_OUTPUT_FLOAT( m_flOutputTimeToStart, SO_SINGLE )
SOS_OUTPUT_FLOAT( m_flOutputTimeToNextSync, SO_SINGLE )
char m_nSyncPointListName[64];
};
class CSosOperatorQueueToTrack : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorQueueToTrack )
};
//-----------------------------------------------------------------------------
// play on a track
//-----------------------------------------------------------------------------
struct CSosOperatorPlayOnTrack_t : CSosOperator_t
{
// SOS_OUTPUT_FLOAT( m_flOutputTimeToStart, SO_SINGLE )
// SOS_OUTPUT_FLOAT( m_flOutputTimeToNextSync, SO_SINGLE )
// char m_nSyncPointListName[64];
HSOUNDSCRIPTHASH m_nAutoQueueEndPointScriptHash;
track_data_t m_trackData;
float m_fAutoQueueStartPoint;
bool m_bHasTriggeredAutoQue;
bool m_bStopChannelOnTrack;
};
class CSosOperatorPlayOnTrack : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorPlayOnTrack )
};
//-----------------------------------------------------------------------------
// stop channel(s) a track
//-----------------------------------------------------------------------------
struct CSosOperatorStopTrack_t : CSosOperator_t
{
char m_nTrackName[64];
};
class CSosOperatorStopTrack : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorStopTrack )
};
#endif // SOS_OP_TRACKS_H

View File

@@ -0,0 +1,79 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//===============================================================================
#include "audio_pch.h"
#include "tier2/interval.h"
#include "sos_op.h"
#include "sos_op_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern Color OpColor;
extern Color ConnectColor;
extern Color ResultColor;
//-----------------------------------------------------------------------------
// CSosOperatorPrintFloat
// Catchall operator
//-----------------------------------------------------------------------------
SOS_BEGIN_OPERATOR_CONSTRUCTOR( CSosOperatorPrintFloat, "util_print_float" )
SOS_REGISTER_INPUT_FLOAT( CSosOperatorPrintFloat, m_flInput, SO_SINGLE, "input" );
SOS_END_OPERATOR_CONSTRUCTOR( CSosOperatorPrintFloat, "util_print_float" )
void CSosOperatorPrintFloat::SetDefaults( void *pVoidMem ) const
{
CSosOperatorPrintFloat_t *pStructMem = (CSosOperatorPrintFloat_t *)pVoidMem;
SOS_INIT_INPUT_VAR( m_flInput, SO_SINGLE, 0.0 )
}
void CSosOperatorPrintFloat::Execute( void *pVoidMem, channel_t *pChannel, CScratchPad *pScratchPad, CSosOperatorStack *pStack, int nOpIndex ) const
{
CSosOperatorPrintFloat_t *pStructMem = (CSosOperatorPrintFloat_t *)pVoidMem;
Log_Msg( LOG_SND_OPERATORS, OpColor, "SOS PRINT FLOAT: %s: %f\n", pStack->GetOperatorName( nOpIndex ), pStructMem->m_flInput[0] );
}
void CSosOperatorPrintFloat::Print( void *pVoidMem, CSosOperatorStack *pStack, int nOpIndex, int nLevel ) const
{
PrintBaseParams( pVoidMem, pStack, nOpIndex, nLevel );
// CSosOperatorPrintFloat_t *pStructMem = (CSosOperatorPrintFloat_t *)pVoidMem;
}
void CSosOperatorPrintFloat::OpHelp( ) const
{
}
void CSosOperatorPrintFloat::ParseKV( CSosOperatorStack *pStack, void *pVoidMem, KeyValues *pOpKeys ) const
{
CSosOperatorPrintFloat_t *pStructMem = (CSosOperatorPrintFloat_t *)pVoidMem;
KeyValues *pParams = pOpKeys->GetFirstSubKey();
while ( pParams )
{
const char *pParamString = pParams->GetName();
const char *pValueString = pParams->GetString();
if ( pParamString && *pParamString )
{
if ( pValueString && *pValueString )
{
if ( BaseParseKV( pStack, (CSosOperator_t *)pStructMem, pParamString, pValueString ) )
{
}
else
{
Log_Warning( LOG_SND_OPERATORS, "Error: Operator %s, unknown sound operator attribute %s\n", pStack->m_pCurrentOperatorName, pParamString );
}
}
}
pParams = pParams->GetNextKey();
}
}

View File

@@ -0,0 +1,30 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#ifndef SOS_OP_UTIL_H
#define SOS_OP_UTIL_H
#ifdef _WIN32
#pragma once
#endif
#include "sos_op.h"
//-----------------------------------------------------------------------------
// basic mixgroup operator
//-----------------------------------------------------------------------------
struct CSosOperatorPrintFloat_t : CSosOperator_t
{
SOS_INPUT_FLOAT( m_flInput, SO_SINGLE )
};
class CSosOperatorPrintFloat : public CSosOperator
{
SOS_HEADER_DESC( CSosOperatorPrintFloat )
};
#endif // SOS_OP_UTIL

Some files were not shown because too many files have changed in this diff Show More