initial
This commit is contained in:
39
engine/voice_codecs/frame_encoder/iframeencoder.h
Normal file
39
engine/voice_codecs/frame_encoder/iframeencoder.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef IFRAMEENCODER_H
|
||||
#define IFRAMEENCODER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
// A frame encoder is a codec that encodes and decodes data in fixed-size frames.
|
||||
// VoiceCodec_Frame handles queuing of data and the IVoiceCodec interface.
|
||||
abstract_class IFrameEncoder
|
||||
{
|
||||
public:
|
||||
virtual ~IFrameEncoder() {}
|
||||
|
||||
// This is called by VoiceCodec_Frame to see if it can initialize..
|
||||
// Fills in the uncompressed and encoded frame size (both are in BYTES).
|
||||
virtual bool Init(int quality, int &rawFrameSize, int &encodedFrameSize) = 0;
|
||||
|
||||
virtual void Release() = 0;
|
||||
|
||||
// pUncompressed is 8-bit signed mono sound data with 'rawFrameSize' bytes.
|
||||
// pCompressed is the size of encodedFrameSize.
|
||||
virtual void EncodeFrame(const char *pUncompressed, char *pCompressed) = 0;
|
||||
|
||||
// pCompressed is encodedFrameSize.
|
||||
// pDecompressed is where the 8-bit signed mono samples are stored and has space for 'rawFrameSize' bytes.
|
||||
virtual void DecodeFrame(const char *pCompressed, char *pDecompressed) = 0;
|
||||
|
||||
// Some codecs maintain state between Compress and Decompress calls. This should clear that state.
|
||||
virtual bool ResetState() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // IFRAMEENCODER_H
|
||||
155
engine/voice_codecs/frame_encoder/voice_codec_frame.cpp
Normal file
155
engine/voice_codecs/frame_encoder/voice_codec_frame.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "audio/public/ivoicecodec.h"
|
||||
#include <string.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "iframeencoder.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// VoiceCodec_Frame can be used to wrap a frame encoder for the engine. As it gets sound data, it will queue it
|
||||
// until it has enough for a frame, then it will compress it. Same thing for decompression.
|
||||
class VoiceCodec_Frame : public IVoiceCodec
|
||||
{
|
||||
public:
|
||||
enum {MAX_FRAMEBUFFER_SAMPLES=1024};
|
||||
|
||||
VoiceCodec_Frame(IFrameEncoder *pEncoder)
|
||||
{
|
||||
m_nEncodeBufferSamples = 0;
|
||||
m_nRawBytes = m_nRawSamples = m_nEncodedBytes = 0;
|
||||
m_pFrameEncoder = pEncoder;
|
||||
}
|
||||
|
||||
virtual ~VoiceCodec_Frame()
|
||||
{
|
||||
if(m_pFrameEncoder)
|
||||
m_pFrameEncoder->Release();
|
||||
}
|
||||
|
||||
virtual bool Init( int quality )
|
||||
{
|
||||
if(m_pFrameEncoder && m_pFrameEncoder->Init(quality, m_nRawBytes, m_nEncodedBytes))
|
||||
{
|
||||
m_nRawSamples = m_nRawBytes >> 1;
|
||||
Assert(m_nRawBytes <= MAX_FRAMEBUFFER_SAMPLES && m_nEncodedBytes <= MAX_FRAMEBUFFER_SAMPLES);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_pFrameEncoder)
|
||||
m_pFrameEncoder->Release();
|
||||
|
||||
m_pFrameEncoder = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual int Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal)
|
||||
{
|
||||
if(!m_pFrameEncoder)
|
||||
return 0;
|
||||
|
||||
const short *pUncompressed = (const short*)pUncompressedBytes;
|
||||
|
||||
int nCompressedBytes = 0;
|
||||
while((nSamples + m_nEncodeBufferSamples) >= m_nRawSamples && (maxCompressedBytes - nCompressedBytes) >= m_nEncodedBytes)
|
||||
{
|
||||
// Get the data block out.
|
||||
short samples[MAX_FRAMEBUFFER_SAMPLES];
|
||||
memcpy(samples, m_EncodeBuffer, m_nEncodeBufferSamples*BYTES_PER_SAMPLE);
|
||||
memcpy(&samples[m_nEncodeBufferSamples], pUncompressed, (m_nRawSamples - m_nEncodeBufferSamples) * BYTES_PER_SAMPLE);
|
||||
nSamples -= m_nRawSamples - m_nEncodeBufferSamples;
|
||||
pUncompressed += m_nRawSamples - m_nEncodeBufferSamples;
|
||||
m_nEncodeBufferSamples = 0;
|
||||
|
||||
// Compress it.
|
||||
m_pFrameEncoder->EncodeFrame((const char*)samples, &pCompressed[nCompressedBytes]);
|
||||
nCompressedBytes += m_nEncodedBytes;
|
||||
}
|
||||
|
||||
// Store the remaining samples.
|
||||
int nNewSamples = min(nSamples, min(m_nRawSamples-m_nEncodeBufferSamples, m_nRawSamples));
|
||||
if(nNewSamples)
|
||||
{
|
||||
memcpy(&m_EncodeBuffer[m_nEncodeBufferSamples], &pUncompressed[nSamples - nNewSamples], nNewSamples*BYTES_PER_SAMPLE);
|
||||
m_nEncodeBufferSamples += nNewSamples;
|
||||
}
|
||||
|
||||
// If it must get the last data, just pad with zeros..
|
||||
if(bFinal && m_nEncodeBufferSamples && (maxCompressedBytes - nCompressedBytes) >= m_nEncodedBytes)
|
||||
{
|
||||
memset(&m_EncodeBuffer[m_nEncodeBufferSamples], 0, (m_nRawSamples - m_nEncodeBufferSamples) * BYTES_PER_SAMPLE);
|
||||
m_pFrameEncoder->EncodeFrame((const char*)m_EncodeBuffer, &pCompressed[nCompressedBytes]);
|
||||
nCompressedBytes += m_nEncodedBytes;
|
||||
m_nEncodeBufferSamples = 0;
|
||||
}
|
||||
|
||||
return nCompressedBytes;
|
||||
}
|
||||
|
||||
virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes)
|
||||
{
|
||||
if(!m_pFrameEncoder)
|
||||
return 0;
|
||||
|
||||
Assert((compressedBytes % m_nEncodedBytes) == 0);
|
||||
int nDecompressedBytes = 0;
|
||||
int curCompressedByte = 0;
|
||||
while((compressedBytes - curCompressedByte) >= m_nEncodedBytes && (maxUncompressedBytes - nDecompressedBytes) >= m_nRawBytes)
|
||||
{
|
||||
m_pFrameEncoder->DecodeFrame( pCompressed ? &pCompressed[curCompressedByte] : NULL, &pUncompressed[nDecompressedBytes]);
|
||||
curCompressedByte += m_nEncodedBytes;
|
||||
nDecompressedBytes += m_nRawBytes;
|
||||
}
|
||||
|
||||
return nDecompressedBytes / BYTES_PER_SAMPLE;
|
||||
}
|
||||
|
||||
virtual bool ResetState()
|
||||
{
|
||||
if(m_pFrameEncoder)
|
||||
return m_pFrameEncoder->ResetState();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
// The codec encodes and decodes samples in fixed-size blocks, so we queue up uncompressed and decompressed data
|
||||
// until we have blocks large enough to give to the codec.
|
||||
short m_EncodeBuffer[MAX_FRAMEBUFFER_SAMPLES];
|
||||
int m_nEncodeBufferSamples;
|
||||
|
||||
IFrameEncoder *m_pFrameEncoder;
|
||||
int m_nRawBytes, m_nRawSamples;
|
||||
int m_nEncodedBytes;
|
||||
};
|
||||
|
||||
|
||||
IVoiceCodec* CreateVoiceCodec_Frame(IFrameEncoder *pEncoder)
|
||||
{
|
||||
return new VoiceCodec_Frame(pEncoder);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user