Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

318 lines
7.4 KiB

//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "quakedef.h"
#include "iframeencoder.h"
#include "interface.h"
#include "milesbase.h"
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void Con_Printf( const char *pMsg, ... )
{
}
class FrameEncoder_Miles : public IFrameEncoder
{
protected:
virtual ~FrameEncoder_Miles();
public:
FrameEncoder_Miles();
virtual bool Init(int quality, int &rawFrameSize, int &encodedFrameSize);
virtual void Release();
virtual void EncodeFrame(const char *pUncompressed, char *pCompressed);
virtual void DecodeFrame(const char *pCompressed, char *pDecompressed);
virtual bool ResetState();
public:
void Shutdown();
static S32 AILCALLBACK EncodeStreamCB(
UINTa user, // User value passed to ASI_open_stream()
void *dest, // Location to which stream data should be copied by app
S32 bytes_requested, // # of bytes requested by ASI codec
S32 offset // If not -1, application should seek to this point in stream
);
static S32 AILCALLBACK DecodeStreamCB(
UINTa user, // User value passed to ASI_open_stream()
void *dest, // Location to which stream data should be copied by app
S32 bytes_requested, // # of bytes requested by ASI codec
S32 offset // If not -1, application should seek to this point in stream
);
void FigureOutFrameSizes();
private:
// Encoder stuff.
ASISTRUCT m_Encoder;
// Decoder stuff.
ASISTRUCT m_Decoder;
// Destination for encoding and decoding.
const char *m_pSrc;
int m_SrcLen;
int m_CurSrcPos;
// Frame sizes..
int m_nRawBytes;
int m_nEncodedBytes;
};
// ------------------------------------------------------------------------ //
// Helper functions.
// ------------------------------------------------------------------------ //
void Convert16UnsignedToSigned(short *pDest, int nSamples)
{
for(int i=0; i < nSamples; i++)
{
int val = *((unsigned short*)&pDest[i]) - (1 << 15);
pDest[i] = (short)val;
}
}
void Convert16SignedToUnsigned(short *pDest, int nSamples)
{
for(int i=0; i < nSamples; i++)
{
int val = *((short*)&pDest[i]) + (1 << 15);
*((unsigned short*)&pDest[i]) = (unsigned short)val;
}
}
// ------------------------------------------------------------------------ //
// FrameEncoder_Miles functions.
// ------------------------------------------------------------------------ //
FrameEncoder_Miles::FrameEncoder_Miles()
{
}
FrameEncoder_Miles::~FrameEncoder_Miles()
{
Shutdown();
}
bool FrameEncoder_Miles::Init(int quality, int &rawFrameSize, int &encodedFrameSize)
{
Shutdown();
// This tells what protocol we're using.
C8 suffix[128] = ".v12"; // (.v12, .v24, .v29, or .raw)
// encoder converts from RAW to v12
if ( !m_Encoder.Init( (void *)this, ".RAW", suffix, &FrameEncoder_Miles::EncodeStreamCB ) )
{
Con_Printf("(FrameEncoder_Miles): Can't initialize ASI encoder.\n");
Shutdown();
return false;
}
// decoder converts from v12 to RAW
if ( !m_Decoder.Init( (void *)this, suffix, ".RAW", &FrameEncoder_Miles::DecodeStreamCB ) )
{
Con_Printf("(FrameEncoder_Miles): Can't initialize ASI decoder.\n");
Shutdown();
return false;
}
FigureOutFrameSizes();
// Output..
rawFrameSize = m_nRawBytes * 2; // They'll be using 16-bit samples and we're quantizing to 8-bit.
encodedFrameSize = m_nEncodedBytes;
return true;
}
void FrameEncoder_Miles::Release()
{
delete this;
}
void FrameEncoder_Miles::EncodeFrame(const char *pUncompressedBytes, char *pCompressed)
{
char samples[1024];
if(!m_Encoder.IsActive() || m_nRawBytes > sizeof(samples))
return;
const short *pUncompressed = (const short*)pUncompressedBytes;
for(int i=0; i < m_nRawBytes; i++)
samples[i] = (char)(pUncompressed[i] >> 8);
m_pSrc = samples;
m_SrcLen = m_nRawBytes;
m_CurSrcPos = 0;
U32 len = m_Encoder.Process( pCompressed, m_nEncodedBytes );
if ( len != (U32)m_nEncodedBytes )
{
Assert(0);
}
}
void FrameEncoder_Miles::DecodeFrame(const char *pCompressed, char *pDecompressed)
{
if(!m_Decoder.IsActive())
return;
m_pSrc = pCompressed;
m_SrcLen = m_nEncodedBytes;
m_CurSrcPos = 0;
U32 outputSize = m_nRawBytes*2;
U32 len = m_Decoder.Process( pDecompressed, outputSize );
if (len != outputSize)
{
Assert(0);
}
}
void FrameEncoder_Miles::Shutdown()
{
m_Decoder.Shutdown();
m_Encoder.Shutdown();
}
bool FrameEncoder_Miles::ResetState()
{
if(!m_Decoder.IsActive() || !m_Encoder.IsActive())
return true;
for(int i=0; i < 2; i++)
{
char data[2048], compressed[2048];
memset(data, 0, sizeof(data));
m_pSrc = data;
m_SrcLen = m_nRawBytes;
m_CurSrcPos = 0;
U32 len = m_Encoder.Process( compressed, m_nEncodedBytes );
if ( len != (U32)m_nEncodedBytes )
{
Assert(0);
}
m_pSrc = compressed;
m_SrcLen = m_nEncodedBytes;
m_CurSrcPos = 0;
m_Decoder.Process( data, m_nRawBytes * 2 );
}
// Encode and decode a couple frames of zeros.
return true;
}
S32 AILCALLBACK FrameEncoder_Miles::EncodeStreamCB(
UINTa user, // User value passed to ASI_open_stream()
void *dest, // Location to which stream data should be copied by app
S32 bytes_requested, // # of bytes requested by ASI codec
S32 offset // If not -1, application should seek to this point in stream
)
{
FrameEncoder_Miles *pThis = (FrameEncoder_Miles*)user;
Assert(pThis && offset == -1);
// Figure out how many samples we can safely give it.
int maxSamples = pThis->m_SrcLen - pThis->m_CurSrcPos;
int samplesToGive = MIN(maxSamples, bytes_requested/2);
// Convert to 16-bit signed mono.
short *pOut = (short*)dest;
for(int i=0; i < samplesToGive; i++)
{
pOut[i] = pThis->m_pSrc[pThis->m_CurSrcPos+i] << 8;
}
pThis->m_CurSrcPos += samplesToGive;
return samplesToGive * 2;
}
S32 AILCALLBACK FrameEncoder_Miles::DecodeStreamCB(
UINTa user, // User value passed to ASI_open_stream()
void *dest, // Location to which stream data should be copied by app
S32 bytes_requested, // # of bytes requested by ASI codec
S32 offset // If not -1, application should seek to this point in stream
)
{
FrameEncoder_Miles *pThis = (FrameEncoder_Miles*)user;
Assert(pThis && offset == -1);
int maxBytes = pThis->m_SrcLen - pThis->m_CurSrcPos;
int bytesToGive = MIN(maxBytes, bytes_requested);
memcpy(dest, &pThis->m_pSrc[pThis->m_CurSrcPos], bytesToGive);
pThis->m_CurSrcPos += bytesToGive;
return bytesToGive;
}
void FrameEncoder_Miles::FigureOutFrameSizes()
{
// Figure out the frame sizes. It is probably not prudent in general to assume fixed frame sizes with Miles codecs
// but it works with the voxware codec right now and simplifies things a lot.
m_nRawBytes = (int)m_Encoder.GetProperty( m_Encoder.INPUT_BLOCK_SIZE );
char uncompressed[1024];
char compressed[1024];
Assert(m_nRawBytes <= sizeof(uncompressed));
m_pSrc = uncompressed;
m_SrcLen = m_nRawBytes;
m_CurSrcPos = 0;
m_nEncodedBytes = (int)m_Encoder.Process( compressed, sizeof(compressed) );
}
class IVoiceCodec;
extern IVoiceCodec* CreateVoiceCodec_Frame(IFrameEncoder *pEncoder);
void* CreateVoiceCodec_Miles()
{
IFrameEncoder *pEncoder = new FrameEncoder_Miles;
if(!pEncoder)
return NULL;
return CreateVoiceCodec_Frame(pEncoder);
}
EXPOSE_INTERFACE_FN(CreateVoiceCodec_Miles, IVoiceCodec, "vaudio_miles")