initial
This commit is contained in:
10
engine/audio/audio_pch.cpp
Normal file
10
engine/audio/audio_pch.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "audio_pch.h"
|
||||
409
engine/audio/private/MPAFile.cpp
Normal file
409
engine/audio/private/MPAFile.cpp
Normal 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;
|
||||
}
|
||||
125
engine/audio/private/MPAFile.h
Normal file
125
engine/audio/private/MPAFile.h
Normal 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
|
||||
336
engine/audio/private/MPAHeader.cpp
Normal file
336
engine/audio/private/MPAHeader.cpp
Normal 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
|
||||
};
|
||||
116
engine/audio/private/MPAHeader.h
Normal file
116
engine/audio/private/MPAHeader.h
Normal 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
|
||||
308
engine/audio/private/VBRHeader.cpp
Normal file
308
engine/audio/private/VBRHeader.cpp
Normal 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;
|
||||
}
|
||||
|
||||
73
engine/audio/private/VBRHeader.h
Normal file
73
engine/audio/private/VBRHeader.h
Normal 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
|
||||
10
engine/audio/private/audio_pch.cpp
Normal file
10
engine/audio/private/audio_pch.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "audio_pch.h"
|
||||
78
engine/audio/private/audio_pch.h
Normal file
78
engine/audio/private/audio_pch.h
Normal 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
|
||||
307
engine/audio/private/circularbuffer.cpp
Normal file
307
engine/audio/private/circularbuffer.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
|
||||
99
engine/audio/private/circularbuffer.h
Normal file
99
engine/audio/private/circularbuffer.h
Normal 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
124
engine/audio/private/eax.h
Normal 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
|
||||
|
||||
234
engine/audio/private/posix_stubs.h
Normal file
234
engine/audio/private/posix_stubs.h
Normal 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
|
||||
|
||||
251
engine/audio/private/snd_channels.h
Normal file
251
engine/audio/private/snd_channels.h
Normal 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
|
||||
21
engine/audio/private/snd_convars.h
Normal file
21
engine/audio/private/snd_convars.h
Normal 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
|
||||
1250
engine/audio/private/snd_dev_common.cpp
Normal file
1250
engine/audio/private/snd_dev_common.cpp
Normal file
File diff suppressed because it is too large
Load Diff
45
engine/audio/private/snd_dev_common.h
Normal file
45
engine/audio/private/snd_dev_common.h
Normal 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
|
||||
2093
engine/audio/private/snd_dev_direct.cpp
Normal file
2093
engine/audio/private/snd_dev_direct.cpp
Normal file
File diff suppressed because it is too large
Load Diff
14
engine/audio/private/snd_dev_direct.h
Normal file
14
engine/audio/private/snd_dev_direct.h
Normal 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
|
||||
481
engine/audio/private/snd_dev_mac_audioqueue.cpp
Normal file
481
engine/audio/private/snd_dev_mac_audioqueue.cpp
Normal 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 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
14
engine/audio/private/snd_dev_mac_audioqueue.h
Normal file
14
engine/audio/private/snd_dev_mac_audioqueue.h
Normal 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
|
||||
403
engine/audio/private/snd_dev_openal.cpp
Normal file
403
engine/audio/private/snd_dev_openal.cpp
Normal 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 system‚use 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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
14
engine/audio/private/snd_dev_openal.h
Normal file
14
engine/audio/private/snd_dev_openal.h
Normal 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
|
||||
2023
engine/audio/private/snd_dev_ps3audio.cpp
Normal file
2023
engine/audio/private/snd_dev_ps3audio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
90
engine/audio/private/snd_dev_ps3audio.h
Normal file
90
engine/audio/private/snd_dev_ps3audio.h
Normal 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
|
||||
751
engine/audio/private/snd_dev_sdl.cpp
Normal file
751
engine/audio/private/snd_dev_sdl.cpp
Normal 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
|
||||
|
||||
16
engine/audio/private/snd_dev_sdl.h
Normal file
16
engine/audio/private/snd_dev_sdl.h
Normal 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
|
||||
|
||||
|
||||
563
engine/audio/private/snd_dev_wave.cpp
Normal file
563
engine/audio/private/snd_dev_wave.cpp
Normal 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 );
|
||||
}
|
||||
14
engine/audio/private/snd_dev_wave.h
Normal file
14
engine/audio/private/snd_dev_wave.h
Normal 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
|
||||
1067
engine/audio/private/snd_dev_xaudio.cpp
Normal file
1067
engine/audio/private/snd_dev_xaudio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
66
engine/audio/private/snd_dev_xaudio.h
Normal file
66
engine/audio/private/snd_dev_xaudio.h
Normal 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
|
||||
10017
engine/audio/private/snd_dma.cpp
Normal file
10017
engine/audio/private/snd_dma.cpp
Normal file
File diff suppressed because it is too large
Load Diff
68
engine/audio/private/snd_dma.h
Normal file
68
engine/audio/private/snd_dma.h
Normal 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
|
||||
12358
engine/audio/private/snd_dsp.cpp
Normal file
12358
engine/audio/private/snd_dsp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
61
engine/audio/private/snd_env_fx.h
Normal file
61
engine/audio/private/snd_env_fx.h
Normal 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
|
||||
40
engine/audio/private/snd_fixedint.h
Normal file
40
engine/audio/private/snd_fixedint.h
Normal 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
|
||||
5438
engine/audio/private/snd_mix.cpp
Normal file
5438
engine/audio/private/snd_mix.cpp
Normal file
File diff suppressed because it is too large
Load Diff
107
engine/audio/private/snd_mix_buf.h
Normal file
107
engine/audio/private/snd_mix_buf.h
Normal 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
|
||||
2751
engine/audio/private/snd_mixgroups.cpp
Normal file
2751
engine/audio/private/snd_mixgroups.cpp
Normal file
File diff suppressed because it is too large
Load Diff
70
engine/audio/private/snd_mixgroups.h
Normal file
70
engine/audio/private/snd_mixgroups.h
Normal 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
|
||||
392
engine/audio/private/snd_mp3_source.cpp
Normal file
392
engine/audio/private/snd_mp3_source.cpp
Normal 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;
|
||||
}
|
||||
|
||||
185
engine/audio/private/snd_mp3_source.h
Normal file
185
engine/audio/private/snd_mp3_source.h
Normal 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
|
||||
220
engine/audio/private/snd_op_sys/sos_entry_match_system.cpp
Normal file
220
engine/audio/private/snd_op_sys/sos_entry_match_system.cpp
Normal 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");
|
||||
}
|
||||
169
engine/audio/private/snd_op_sys/sos_entry_match_system.h
Normal file
169
engine/audio/private/snd_op_sys/sos_entry_match_system.h
Normal 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
|
||||
441
engine/audio/private/snd_op_sys/sos_op.cpp
Normal file
441
engine/audio/private/snd_op_sys/sos_op.cpp
Normal 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 ) );
|
||||
}
|
||||
}
|
||||
170
engine/audio/private/snd_op_sys/sos_op.h
Normal file
170
engine/audio/private/snd_op_sys/sos_op.h
Normal 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
|
||||
215
engine/audio/private/snd_op_sys/sos_op_block_entry.cpp
Normal file
215
engine/audio/private/snd_op_sys/sos_op_block_entry.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
43
engine/audio/private/snd_op_sys/sos_op_block_entry.h
Normal file
43
engine/audio/private/snd_op_sys/sos_op_block_entry.h
Normal 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
|
||||
186
engine/audio/private/snd_op_sys/sos_op_convar.cpp
Normal file
186
engine/audio/private/snd_op_sys/sos_op_convar.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
64
engine/audio/private/snd_op_sys/sos_op_convar.h
Normal file
64
engine/audio/private/snd_op_sys/sos_op_convar.h
Normal 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
|
||||
97
engine/audio/private/snd_op_sys/sos_op_dashboard.cpp
Normal file
97
engine/audio/private/snd_op_sys/sos_op_dashboard.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
31
engine/audio/private/snd_op_sys/sos_op_dashboard.h
Normal file
31
engine/audio/private/snd_op_sys/sos_op_dashboard.h
Normal 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
|
||||
90
engine/audio/private/snd_op_sys/sos_op_delta.cpp
Normal file
90
engine/audio/private/snd_op_sys/sos_op_delta.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
36
engine/audio/private/snd_op_sys/sos_op_delta.h
Normal file
36
engine/audio/private/snd_op_sys/sos_op_delta.h
Normal 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
|
||||
95
engine/audio/private/snd_op_sys/sos_op_distant_dsp.cpp
Normal file
95
engine/audio/private/snd_op_sys/sos_op_distant_dsp.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
30
engine/audio/private/snd_op_sys/sos_op_distant_dsp.h
Normal file
30
engine/audio/private/snd_op_sys/sos_op_distant_dsp.h
Normal 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
|
||||
192
engine/audio/private/snd_op_sys/sos_op_entity_info.cpp
Normal file
192
engine/audio/private/snd_op_sys/sos_op_entity_info.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
48
engine/audio/private/snd_op_sys/sos_op_entity_info.h
Normal file
48
engine/audio/private/snd_op_sys/sos_op_entity_info.h
Normal 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
|
||||
134
engine/audio/private/snd_op_sys/sos_op_entry_time.cpp
Normal file
134
engine/audio/private/snd_op_sys/sos_op_entry_time.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
37
engine/audio/private/snd_op_sys/sos_op_entry_time.h
Normal file
37
engine/audio/private/snd_op_sys/sos_op_entry_time.h
Normal 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
|
||||
195
engine/audio/private/snd_op_sys/sos_op_falloff.cpp
Normal file
195
engine/audio/private/snd_op_sys/sos_op_falloff.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
53
engine/audio/private/snd_op_sys/sos_op_falloff.h
Normal file
53
engine/audio/private/snd_op_sys/sos_op_falloff.h
Normal 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
|
||||
134
engine/audio/private/snd_op_sys/sos_op_filters.cpp
Normal file
134
engine/audio/private/snd_op_sys/sos_op_filters.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
35
engine/audio/private/snd_op_sys/sos_op_filters.h
Normal file
35
engine/audio/private/snd_op_sys/sos_op_filters.h
Normal 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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
89
engine/audio/private/snd_op_sys/sos_op_map_name.cpp
Normal file
89
engine/audio/private/snd_op_sys/sos_op_map_name.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
31
engine/audio/private/snd_op_sys/sos_op_map_name.h
Normal file
31
engine/audio/private/snd_op_sys/sos_op_map_name.h
Normal 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
|
||||
1917
engine/audio/private/snd_op_sys/sos_op_math.cpp
Normal file
1917
engine/audio/private/snd_op_sys/sos_op_math.cpp
Normal file
File diff suppressed because it is too large
Load Diff
296
engine/audio/private/snd_op_sys/sos_op_math.h
Normal file
296
engine/audio/private/snd_op_sys/sos_op_math.h
Normal 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
|
||||
149
engine/audio/private/snd_op_sys/sos_op_mixer.cpp
Normal file
149
engine/audio/private/snd_op_sys/sos_op_mixer.cpp
Normal 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 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
34
engine/audio/private/snd_op_sys/sos_op_mixer.h
Normal file
34
engine/audio/private/snd_op_sys/sos_op_mixer.h
Normal 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
|
||||
163
engine/audio/private/snd_op_sys/sos_op_mixlayer.cpp
Normal file
163
engine/audio/private/snd_op_sys/sos_op_mixlayer.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
34
engine/audio/private/snd_op_sys/sos_op_mixlayer.h
Normal file
34
engine/audio/private/snd_op_sys/sos_op_mixlayer.h
Normal 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
|
||||
292
engine/audio/private/snd_op_sys/sos_op_occlusion.cpp
Normal file
292
engine/audio/private/snd_op_sys/sos_op_occlusion.cpp
Normal 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;
|
||||
|
||||
}
|
||||
33
engine/audio/private/snd_op_sys/sos_op_occlusion.h
Normal file
33
engine/audio/private/snd_op_sys/sos_op_occlusion.h
Normal 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
|
||||
255
engine/audio/private/snd_op_sys/sos_op_opvar.cpp
Normal file
255
engine/audio/private/snd_op_sys/sos_op_opvar.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
65
engine/audio/private/snd_op_sys/sos_op_opvar.h
Normal file
65
engine/audio/private/snd_op_sys/sos_op_opvar.h
Normal 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
|
||||
258
engine/audio/private/snd_op_sys/sos_op_output.cpp
Normal file
258
engine/audio/private/snd_op_sys/sos_op_output.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
52
engine/audio/private/snd_op_sys/sos_op_output.h
Normal file
52
engine/audio/private/snd_op_sys/sos_op_output.h
Normal 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
|
||||
107
engine/audio/private/snd_op_sys/sos_op_platform.cpp
Normal file
107
engine/audio/private/snd_op_sys/sos_op_platform.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
31
engine/audio/private/snd_op_sys/sos_op_platform.h
Normal file
31
engine/audio/private/snd_op_sys/sos_op_platform.h
Normal 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
|
||||
190
engine/audio/private/snd_op_sys/sos_op_player_info.cpp
Normal file
190
engine/audio/private/snd_op_sys/sos_op_player_info.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
50
engine/audio/private/snd_op_sys/sos_op_player_info.h
Normal file
50
engine/audio/private/snd_op_sys/sos_op_player_info.h
Normal 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
|
||||
149
engine/audio/private/snd_op_sys/sos_op_pos_vec8.cpp
Normal file
149
engine/audio/private/snd_op_sys/sos_op_pos_vec8.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
41
engine/audio/private/snd_op_sys/sos_op_pos_vec8.h
Normal file
41
engine/audio/private/snd_op_sys/sos_op_pos_vec8.h
Normal 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
|
||||
336
engine/audio/private/snd_op_sys/sos_op_source_info.cpp
Normal file
336
engine/audio/private/snd_op_sys/sos_op_source_info.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
46
engine/audio/private/snd_op_sys/sos_op_source_info.h
Normal file
46
engine/audio/private/snd_op_sys/sos_op_source_info.h
Normal 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
|
||||
194
engine/audio/private/snd_op_sys/sos_op_spatialize.cpp
Normal file
194
engine/audio/private/snd_op_sys/sos_op_spatialize.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
38
engine/audio/private/snd_op_sys/sos_op_spatialize.h
Normal file
38
engine/audio/private/snd_op_sys/sos_op_spatialize.h
Normal 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
|
||||
168
engine/audio/private/snd_op_sys/sos_op_start_entry.cpp
Normal file
168
engine/audio/private/snd_op_sys/sos_op_start_entry.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
35
engine/audio/private/snd_op_sys/sos_op_start_entry.h
Normal file
35
engine/audio/private/snd_op_sys/sos_op_start_entry.h
Normal 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
|
||||
363
engine/audio/private/snd_op_sys/sos_op_stop_entry.cpp
Normal file
363
engine/audio/private/snd_op_sys/sos_op_stop_entry.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
44
engine/audio/private/snd_op_sys/sos_op_stop_entry.h
Normal file
44
engine/audio/private/snd_op_sys/sos_op_stop_entry.h
Normal 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
|
||||
82
engine/audio/private/snd_op_sys/sos_op_sys_time.cpp
Normal file
82
engine/audio/private/snd_op_sys/sos_op_sys_time.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
33
engine/audio/private/snd_op_sys/sos_op_sys_time.h
Normal file
33
engine/audio/private/snd_op_sys/sos_op_sys_time.h
Normal 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
|
||||
745
engine/audio/private/snd_op_sys/sos_op_tracks.cpp
Normal file
745
engine/audio/private/snd_op_sys/sos_op_tracks.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
104
engine/audio/private/snd_op_sys/sos_op_tracks.h
Normal file
104
engine/audio/private/snd_op_sys/sos_op_tracks.h
Normal 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
|
||||
79
engine/audio/private/snd_op_sys/sos_op_util.cpp
Normal file
79
engine/audio/private/snd_op_sys/sos_op_util.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
30
engine/audio/private/snd_op_sys/sos_op_util.h
Normal file
30
engine/audio/private/snd_op_sys/sos_op_util.h
Normal 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
Reference in New Issue
Block a user