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

View File

@@ -0,0 +1,264 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "milesbase.h"
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static int s_MilesRefCount = 0;
void IncrementRefMiles()
{
if(s_MilesRefCount == 0)
{
#ifdef WIN32
AIL_set_redist_directory( "." );
#elif defined( OSX )
AIL_set_redist_directory( "osx32" );
#elif defined( LINUX )
#ifdef PLATFORM_64BITS
AIL_set_redist_directory( "bin/linux64" );
#else
AIL_set_redist_directory( "bin/linux32" );
#endif
#else
Assert( !"Using default MSS_REDIST_DIR_NAME - this will most likely fail." );
AIL_set_redist_directory( MSS_REDIST_DIR_NAME );
#endif
AIL_startup();
}
++s_MilesRefCount;
}
void DecrementRefMiles()
{
Assert(s_MilesRefCount > 0);
--s_MilesRefCount;
if(s_MilesRefCount == 0)
{
CProvider::FreeAllProviders();
AIL_shutdown();
}
}
// ------------------------------------------------------------------------ //
// CProvider functions.
// ------------------------------------------------------------------------ //
CProvider *CProvider::s_pHead = NULL;
CProvider::CProvider( HPROVIDER hProvider )
{
m_hProvider = hProvider;
// Add to the global list of CProviders.
m_pNext = s_pHead;
s_pHead = this;
}
CProvider::~CProvider()
{
RIB_free_provider_library( m_hProvider );
// Remove from the global list.
CProvider **ppPrev = &s_pHead;
for ( CProvider *pCur=s_pHead; pCur; pCur=pCur->m_pNext )
{
if ( pCur == this )
{
*ppPrev = m_pNext;
return;
}
ppPrev = &pCur->m_pNext;
}
}
CProvider* CProvider::FindProvider( HPROVIDER hProvider )
{
for ( CProvider *pCur=s_pHead; pCur; pCur=pCur->m_pNext )
{
if ( pCur->GetProviderHandle() == hProvider )
{
return pCur;
}
}
return NULL;
}
void CProvider::FreeAllProviders()
{
CProvider *pNext;
for ( CProvider *pCur=s_pHead; pCur; pCur=pNext )
{
pNext = pCur->m_pNext;
delete pCur;
}
}
HPROVIDER CProvider::GetProviderHandle()
{
return m_hProvider;
}
// ------------------------------------------------------------------------ //
// ASISTRUCT functions.
// ------------------------------------------------------------------------ //
ASISTRUCT::ASISTRUCT()
{
Clear();
IncrementRefMiles();
}
ASISTRUCT::~ASISTRUCT()
{
Shutdown();
DecrementRefMiles();
}
void ASISTRUCT::Clear()
{
m_pProvider = NULL;
ASI_stream_open = NULL;
ASI_stream_process = NULL;
ASI_stream_close = NULL;
ASI_stream_property = NULL;
ASI_stream_seek = NULL;
OUTPUT_BITS = NULL;
OUTPUT_CHANNELS = NULL;
INPUT_BITS = NULL;
INPUT_CHANNELS = NULL;
POSITION = NULL;
m_stream = NULL;
}
bool ASISTRUCT::Init( void *pCallbackObject, const char *pInputFileType, const char *pOutputFileType, AILASIFETCHCB cb )
{
// Get the provider.
HPROVIDER hProvider = RIB_find_files_provider( "ASI codec",
"Output file types", pOutputFileType, "Input file types", pInputFileType );
if ( !hProvider )
return false;
m_pProvider = CProvider::FindProvider( hProvider );
if ( !m_pProvider )
{
m_pProvider = new CProvider( hProvider );
}
if ( !m_pProvider )
return false;
RIB_INTERFACE_ENTRY ASISTR[] =
{
FN( ASI_stream_property ),
FN( ASI_stream_open ),
FN( ASI_stream_close ),
FN( ASI_stream_process ),
PR( "Output sample rate", OUTPUT_RATE ),
PR( "Output sample width", OUTPUT_BITS ),
PR( "Output channels", OUTPUT_CHANNELS ),
PR( "Input sample rate", INPUT_RATE ),
PR( "Input sample width", INPUT_BITS ),
PR( "Input channels", INPUT_CHANNELS ),
PR( "Minimum input block size", INPUT_BLOCK_SIZE ),
PR( "Position", POSITION ),
};
RIBRESULT result = RIB_request( m_pProvider->GetProviderHandle(), "ASI stream", ASISTR );
if(result != RIB_NOERR)
return false;
// This function doesn't exist for the voice DLLs, but it's not fatal in that case.
RIB_INTERFACE_ENTRY seekFn[] =
{
FN( ASI_stream_seek ),
};
result = RIB_request( m_pProvider->GetProviderHandle(), "ASI stream", seekFn );
if(result != RIB_NOERR)
ASI_stream_seek = NULL;
m_stream = ASI_stream_open( (MSS_ALLOC_TYPE *)MSS_CALLBACK_ALIGNED_NAME( MSS_alloc_info ),
(MSS_FREE_TYPE *)MSS_CALLBACK_ALIGNED_NAME( MSS_free_info ),
(UINTa)pCallbackObject, cb, 0);
if(!m_stream)
return false;
return true;
}
void ASISTRUCT::Shutdown()
{
if ( m_pProvider )
{
if (m_stream && ASI_stream_close)
{
ASI_stream_close(m_stream);
m_stream = NULL;
}
//m_pProvider->Release();
m_pProvider = NULL;
}
Clear();
}
int ASISTRUCT::Process( void *pBuffer, unsigned int bufferSize )
{
return ASI_stream_process( m_stream, pBuffer, bufferSize );
}
bool ASISTRUCT::IsActive() const
{
return m_stream != NULL ? true : false;
}
unsigned int ASISTRUCT::GetProperty( HPROPERTY hProperty )
{
uint32 nValue = 0;
if ( ASI_stream_property( m_stream, hProperty, &nValue, NULL, NULL ) )
{
return nValue;
}
return 0;
}
void ASISTRUCT::Seek( int position )
{
if ( !ASI_stream_seek )
Error( "ASI_stream_seek called, but it doesn't exist." );
ASI_stream_seek( m_stream, (S32)position );
}

View File

@@ -0,0 +1,87 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MILESBASE_H
#define MILESBASE_H
#ifdef _WIN32
#pragma once
#endif
// windows.h / platform.h conflicts
#pragma warning(disable:4005)
#pragma warning(disable:4201) // nameless struct/union (mmssystem.h has this)
#include "miles/mss.h"
class CProvider
{
public:
CProvider( HPROVIDER hProvider );
static CProvider* FindProvider( HPROVIDER hProvider );
static void FreeAllProviders();
HPROVIDER GetProviderHandle();
private:
~CProvider();
private:
HPROVIDER m_hProvider;
static CProvider *s_pHead;
CProvider *m_pNext;
};
// This holds the handles and function pointers we want from a compressor/decompressor.
class ASISTRUCT
{
public:
ASISTRUCT();
~ASISTRUCT();
bool Init( void *pCallbackObject, const char *pInputFileType,
const char *pOutputFileType, AILASIFETCHCB cb );
void Shutdown();
int Process( void *pBuffer, unsigned int bufferSize );
bool IsActive() const;
unsigned int GetProperty( HPROPERTY attribute );
void Seek( int position );
public:
HPROPERTY OUTPUT_BITS;
HPROPERTY OUTPUT_CHANNELS;
HPROPERTY OUTPUT_RATE;
HPROPERTY INPUT_BITS;
HPROPERTY INPUT_CHANNELS;
HPROPERTY INPUT_RATE;
HPROPERTY INPUT_BLOCK_SIZE;
HPROPERTY POSITION;
private:
void Clear();
private:
ASI_STREAM_OPEN ASI_stream_open;
ASI_STREAM_PROCESS ASI_stream_process;
ASI_STREAM_CLOSE ASI_stream_close;
ASI_STREAM_SEEK ASI_stream_seek;
ASI_STREAM_PROPERTY ASI_stream_property;
HASISTREAM m_stream;
CProvider *m_pProvider;
};
extern void IncrementRefMiles();
extern void DecrementRefMiles();
#endif // MILESBASE_H

View File

@@ -0,0 +1,167 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "interface.h"
#include "milesbase.h"
#include "vaudio/ivaudio.h"
#include "dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static S32 AILCALLBACK AudioStreamEventCB( UINTa user, void *dest, S32 bytes_requested, S32 offset )
{
IAudioStreamEvent *pThis = static_cast<IAudioStreamEvent*>( (void *)user);
#if defined( OSX ) && !defined( PLATFORM_64BITS )
// save of the args to local stack vars before we screw with ESP
volatile void *newDest = dest;
volatile S32 newBytes = bytes_requested;
volatile S32 newOffset = offset;
volatile void *oldESP;
// now move ESP to be aligned to 16-bytes
asm volatile(
"movl %%esp,%0\n"
"subl $16,%%esp\n"
"andl $-0x10,%%esp\n"
: "=m" (oldESP) : : "%esp");
int val = pThis->StreamRequestData( (void *)newDest, newBytes, newOffset );
// undo the alignment
asm( "movl %0,%%esp\n" ::"m" (oldESP) );
return val;
#else
return pThis->StreamRequestData( dest, bytes_requested, offset );
#endif
}
class CMilesMP3 : public IAudioStream
{
public:
CMilesMP3();
bool Init( IAudioStreamEvent *pHandler );
virtual ~CMilesMP3();
// IAudioStream functions
virtual int Decode( void *pBuffer, unsigned int bufferSize );
virtual int GetOutputBits();
virtual int GetOutputRate();
virtual int GetOutputChannels();
virtual unsigned int GetPosition();
virtual void SetPosition( unsigned int position );
private:
ASISTRUCT m_decoder;
};
CMilesMP3::CMilesMP3()
{
}
bool CMilesMP3::Init( IAudioStreamEvent *pHandler )
{
return m_decoder.Init( pHandler, ".MP3", ".RAW", &AudioStreamEventCB );
}
CMilesMP3::~CMilesMP3()
{
m_decoder.Shutdown();
}
// IAudioStream functions
int CMilesMP3::Decode( void *pBuffer, unsigned int bufferSize )
{
return m_decoder.Process( pBuffer, bufferSize );
}
int CMilesMP3::GetOutputBits()
{
return m_decoder.GetProperty( m_decoder.OUTPUT_BITS );
}
int CMilesMP3::GetOutputRate()
{
return m_decoder.GetProperty( m_decoder.OUTPUT_RATE );
}
int CMilesMP3::GetOutputChannels()
{
return m_decoder.GetProperty( m_decoder.OUTPUT_CHANNELS );
}
unsigned int CMilesMP3::GetPosition()
{
return m_decoder.GetProperty( m_decoder.POSITION );
}
// NOTE: Only supports seeking forward right now
void CMilesMP3::SetPosition( unsigned int position )
{
m_decoder.Seek( position );
}
class CVAudio : public IVAudio
{
public:
CVAudio()
{
// Assume the user will be creating multiple miles objects, so
// keep miles running while this exists
IncrementRefMiles();
}
virtual ~CVAudio()
{
DecrementRefMiles();
}
IAudioStream *CreateMP3StreamDecoder( IAudioStreamEvent *pEventHandler )
{
CMilesMP3 *pMP3 = new CMilesMP3;
if ( !pMP3->Init( pEventHandler ) )
{
delete pMP3;
return NULL;
}
return pMP3;
}
void DestroyMP3StreamDecoder( IAudioStream *pDecoder )
{
delete pDecoder;
}
void *CreateMilesAudioEngine()
{
IncrementRefMiles();
HDIGDRIVER hDriver = AIL_open_digital_driver( 44100, 16, MSS_MC_51_DISCRETE, 0 );
return (void *)hDriver;
}
void DestroyMilesAudioEngine( void *pEngine )
{
HDIGDRIVER hDriver = HDIGDRIVER(pEngine);
AIL_close_digital_driver( hDriver );
DecrementRefMiles();
}
};
void* CreateVoiceCodec_CVAudio()
{
return new CVAudio;
}
EXPOSE_INTERFACE_FN(CreateVoiceCodec_CVAudio, IVAudio, VAUDIO_INTERFACE_VERSION );

View File

@@ -0,0 +1,52 @@
//-----------------------------------------------------------------------------
// VAUDIO_MILES.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,..\frame_encoder,..\.."
}
$Linker
{
$SystemLibraries "iconv" [$OSXALL]
$SystemLibraries "openal" [$LINUXALL]
}
}
$Project "VAudio_Miles"
{
$Folder "Source Files"
{
$File "milesbase.cpp"
$File "mp3_miles.cpp"
$File "..\frame_encoder\voice_codec_frame.cpp"
$File "voice_codec_miles.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\tier1\interface.h"
$File "$SRCDIR\public\vaudio\ivaudio.h"
$File "milesbase.h"
$File "$SRCDIR\common\miles\mss.h"
}
$Folder "Link Libraries"
{
$File "$SRCDIR\lib\common\mss32.lib" [$WIN32]
$File "$SRCDIR\lib\common\mss64.lib" [$WIN64]
$File "$SRCDIR\lib\osx32\release\libMilesX86.dylib" [$OSX32]
$File "$SRCDIR\lib\osx64\release\libMilesX64.dylib" [$OSX64]
$File "$SRCDIR\lib\linux32\release\libMiles.so" [$LINUX32]
$ImpLibExternal "Miles" [$LINUX64]
}
}

View File

@@ -0,0 +1,318 @@
//========= Copyright <20> 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")