mirror of
https://github.com/rehlds/revoice.git
synced 2025-04-24 07:13:37 +03:00
VoiceEncoder_Opus.cpp reworked, refactoring, fix Compress
This commit is contained in:
parent
5f71fde202
commit
8a547601db
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
VoiceEncoder_Opus::VoiceEncoder_Opus() : m_bitrate(32000), m_samplerate(8000)
|
VoiceEncoder_Opus::VoiceEncoder_Opus() : m_bitrate(32000), m_samplerate(8000)
|
||||||
{
|
{
|
||||||
m_nCurFrame = 0;
|
m_nEncodeSeq = 0;
|
||||||
m_nLastFrame = 0;
|
m_nDecodeSeq = 0;
|
||||||
m_pEncoder = nullptr;
|
m_pEncoder = nullptr;
|
||||||
m_pDecoder = nullptr;
|
m_pDecoder = nullptr;
|
||||||
}
|
}
|
||||||
@ -23,8 +23,8 @@ VoiceEncoder_Opus::~VoiceEncoder_Opus()
|
|||||||
|
|
||||||
bool VoiceEncoder_Opus::Init(int quality)
|
bool VoiceEncoder_Opus::Init(int quality)
|
||||||
{
|
{
|
||||||
m_nCurFrame = 0;
|
m_nEncodeSeq = 0;
|
||||||
m_nLastFrame = 0;
|
m_nDecodeSeq = 0;
|
||||||
m_PacketLossConcealment = true;
|
m_PacketLossConcealment = true;
|
||||||
|
|
||||||
int encSizeBytes = opus_encoder_get_size(MAX_CHANNELS);
|
int encSizeBytes = opus_encoder_get_size(MAX_CHANNELS);
|
||||||
@ -71,33 +71,36 @@ bool VoiceEncoder_Opus::ResetState()
|
|||||||
|
|
||||||
int VoiceEncoder_Opus::Compress(const char *pUncompressedIn, int nSamplesIn, char *pCompressed, int maxCompressedBytes, bool bFinal)
|
int VoiceEncoder_Opus::Compress(const char *pUncompressedIn, int nSamplesIn, char *pCompressed, int maxCompressedBytes, bool bFinal)
|
||||||
{
|
{
|
||||||
if ((nSamplesIn + GetNumQueuedEncodingSamples()) < FRAME_SIZE && !bFinal) {
|
if ((nSamplesIn + GetNumQueuedEncodingSamples()) < FRAME_SIZE && !bFinal)
|
||||||
|
{
|
||||||
m_bufOverflowBytes.Put(pUncompressedIn, nSamplesIn * BYTES_PER_SAMPLE);
|
m_bufOverflowBytes.Put(pUncompressedIn, nSamplesIn * BYTES_PER_SAMPLE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nSamples = nSamplesIn;
|
int nSamples = nSamplesIn;
|
||||||
int nSamplesRemaining = nSamples % FRAME_SIZE;
|
int nSamplesRemaining = nSamplesIn % FRAME_SIZE;
|
||||||
char *pUncompressed = (char *)pUncompressedIn;
|
char *pUncompressed = (char *)pUncompressedIn;
|
||||||
|
|
||||||
|
CUtlBuffer buf;
|
||||||
if (m_bufOverflowBytes.TellPut() || (nSamplesRemaining && bFinal))
|
if (m_bufOverflowBytes.TellPut() || (nSamplesRemaining && bFinal))
|
||||||
{
|
{
|
||||||
CUtlBuffer buf;
|
|
||||||
buf.Put(m_bufOverflowBytes.Base(), m_bufOverflowBytes.TellPut());
|
buf.Put(m_bufOverflowBytes.Base(), m_bufOverflowBytes.TellPut());
|
||||||
buf.Put(pUncompressedIn, nSamplesIn * BYTES_PER_SAMPLE);
|
buf.Put(pUncompressedIn, nSamplesIn * BYTES_PER_SAMPLE);
|
||||||
m_bufOverflowBytes.Clear();
|
m_bufOverflowBytes.Clear();
|
||||||
|
|
||||||
nSamples = (buf.TellPut() / 2);
|
nSamples = (buf.TellPut() / BYTES_PER_SAMPLE);
|
||||||
nSamplesRemaining = nSamples % FRAME_SIZE;
|
nSamplesRemaining = (buf.TellPut() / BYTES_PER_SAMPLE) % FRAME_SIZE;
|
||||||
|
|
||||||
if (bFinal && nSamplesRemaining)
|
if (bFinal && nSamplesRemaining)
|
||||||
{
|
{
|
||||||
for (int i = FRAME_SIZE - nSamplesRemaining; i > 0; i--) {
|
// fill samples with silence
|
||||||
|
for (int i = FRAME_SIZE - nSamplesRemaining; i > 0; i--)
|
||||||
|
{
|
||||||
buf.PutShort(0);
|
buf.PutShort(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
nSamples = (buf.TellPut() / 2);
|
nSamples = (buf.TellPut() / BYTES_PER_SAMPLE);
|
||||||
nSamplesRemaining = nSamples % FRAME_SIZE;
|
nSamplesRemaining = (buf.TellPut() / BYTES_PER_SAMPLE) % FRAME_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pUncompressed = (char *)buf.Base();
|
pUncompressed = (char *)buf.Base();
|
||||||
@ -108,34 +111,39 @@ int VoiceEncoder_Opus::Compress(const char *pUncompressedIn, int nSamplesIn, cha
|
|||||||
char *pWritePos = pCompressed;
|
char *pWritePos = pCompressed;
|
||||||
char *pWritePosMax = pCompressed + maxCompressedBytes;
|
char *pWritePosMax = pCompressed + maxCompressedBytes;
|
||||||
|
|
||||||
int nBlocks = nSamples - nSamplesRemaining;
|
int nChunks = nSamples - nSamplesRemaining;
|
||||||
while (nBlocks > 0)
|
if (nChunks > 0)
|
||||||
|
{
|
||||||
|
int nRemainingSamples = (nChunks - 1) / FRAME_SIZE + 1;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
uint16 *pWritePayloadSize = (uint16 *)pWritePos;
|
uint16 *pWritePayloadSize = (uint16 *)pWritePos;
|
||||||
pWritePos += sizeof(uint16); // leave 2 bytes for the frame size (will be written after encoding)
|
pWritePos += sizeof(uint16); // leave 2 bytes for the frame size (will be written after encoding)
|
||||||
|
|
||||||
if (m_PacketLossConcealment)
|
if (m_PacketLossConcealment)
|
||||||
{
|
{
|
||||||
*(uint16 *)pWritePos = m_nCurFrame++;
|
*(uint16 *)pWritePos = m_nEncodeSeq++;
|
||||||
pWritePos += sizeof(uint16);
|
pWritePos += sizeof(uint16);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nBytes = (pWritePosMax - pWritePos > 0x7FFF) ? 0x7FFF : (pWritePosMax - pWritePos);
|
int nBytes = ((pWritePosMax - pWritePos) < 0x7FFF) ? (pWritePosMax - pWritePos) : 0x7FFF;
|
||||||
int nWriteBytes = opus_encode(m_pEncoder, (const opus_int16 *)psRead, FRAME_SIZE, (unsigned char *)pWritePos, nBytes);
|
int nWriteBytes = opus_encode(m_pEncoder, (const opus_int16 *)psRead, FRAME_SIZE, (unsigned char *)pWritePos, nBytes);
|
||||||
|
|
||||||
nBlocks -= FRAME_SIZE;
|
psRead += MAX_FRAME_SIZE;
|
||||||
psRead += FRAME_SIZE * 2;
|
|
||||||
pWritePos += nWriteBytes;
|
pWritePos += nWriteBytes;
|
||||||
|
|
||||||
|
nRemainingSamples--;
|
||||||
*pWritePayloadSize = nWriteBytes;
|
*pWritePayloadSize = nWriteBytes;
|
||||||
}
|
}
|
||||||
|
while (nRemainingSamples > 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_bufOverflowBytes.Clear();
|
m_bufOverflowBytes.Clear();
|
||||||
|
|
||||||
if (nSamplesRemaining)
|
if (nSamplesRemaining)
|
||||||
{
|
{
|
||||||
Assert((char *)psRead == pUncompressed + ((nSamples - nSamplesRemaining) * sizeof(uint16)));
|
Assert((char *)psRead == pUncompressed + ((nSamples - nSamplesRemaining) * sizeof(int16)));
|
||||||
m_bufOverflowBytes.Put(pUncompressed + ((nSamples - nSamplesRemaining) * sizeof(uint16)), 2 * nSamplesRemaining);
|
m_bufOverflowBytes.Put(pUncompressed + ((nSamples - nSamplesRemaining) * sizeof(int16)), nSamplesRemaining * BYTES_PER_SAMPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bFinal)
|
if (bFinal)
|
||||||
@ -148,7 +156,7 @@ int VoiceEncoder_Opus::Compress(const char *pUncompressedIn, int nSamplesIn, cha
|
|||||||
pWritePos += sizeof(uint16);
|
pWritePos += sizeof(uint16);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nCurFrame = 0;
|
m_nEncodeSeq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pWritePos - pCompressed;
|
return pWritePos - pCompressed;
|
||||||
@ -162,69 +170,74 @@ int VoiceEncoder_Opus::Decompress(const char *pCompressed, int compressedBytes,
|
|||||||
char *pWritePos = pUncompressed;
|
char *pWritePos = pUncompressed;
|
||||||
char *pWritePosMax = &pUncompressed[maxUncompressedBytes];
|
char *pWritePosMax = &pUncompressed[maxUncompressedBytes];
|
||||||
|
|
||||||
int nPayloadSize;
|
|
||||||
|
|
||||||
while (pReadPos < pReadPosMax)
|
while (pReadPos < pReadPosMax)
|
||||||
{
|
{
|
||||||
nPayloadSize = *(uint16 *)pReadPos;
|
uint16 nPayloadSize = *(uint16 *)pReadPos;
|
||||||
pReadPos += sizeof(uint16);
|
pReadPos += sizeof(uint16);
|
||||||
|
|
||||||
if (nPayloadSize == 0xFFFF) {
|
if (nPayloadSize == 0xFFFF)
|
||||||
m_nLastFrame = 0;
|
{
|
||||||
ResetState();
|
ResetState();
|
||||||
|
m_nDecodeSeq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_PacketLossConcealment)
|
if (m_PacketLossConcealment)
|
||||||
{
|
{
|
||||||
uint16 nCurFrame = *(uint16 *)pReadPos;
|
uint16 nCurSeq = *(uint16 *)pReadPos;
|
||||||
pReadPos += sizeof(uint16);
|
pReadPos += sizeof(uint16);
|
||||||
|
|
||||||
if (nCurFrame < m_nLastFrame)
|
if (nCurSeq < m_nDecodeSeq)
|
||||||
{
|
{
|
||||||
ResetState();
|
ResetState();
|
||||||
}
|
}
|
||||||
else if (nCurFrame != m_nLastFrame)
|
else if (nCurSeq != m_nDecodeSeq)
|
||||||
{
|
{
|
||||||
int nPacketLoss = nCurFrame - m_nLastFrame;
|
int nPacketLoss = nCurSeq - m_nDecodeSeq;
|
||||||
if (nPacketLoss > MAX_PACKET_LOSS) {
|
if (nPacketLoss > MAX_PACKET_LOSS) {
|
||||||
nPacketLoss = MAX_PACKET_LOSS;
|
nPacketLoss = MAX_PACKET_LOSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nPacketLoss; i++)
|
for (int i = 0; i < nPacketLoss; i++)
|
||||||
{
|
{
|
||||||
if (pWritePos + (FRAME_SIZE * 2) >= pWritePosMax)
|
if ((pWritePos + MAX_FRAME_SIZE) >= pWritePosMax)
|
||||||
|
{
|
||||||
|
Assert(false);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int nBytes = opus_decode(m_pDecoder, 0, 0, (opus_int16 *)pWritePos, FRAME_SIZE, 0);
|
int nBytes = opus_decode(m_pDecoder, 0, 0, (opus_int16 *)pWritePos, FRAME_SIZE, 0);
|
||||||
if (nBytes <= 0)
|
if (nBytes <= 0)
|
||||||
{
|
{
|
||||||
// raw corrupted
|
// raw corrupted
|
||||||
return 0;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pWritePos += nBytes * 2;
|
pWritePos += nBytes * BYTES_PER_SAMPLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nLastFrame = nCurFrame + 1;
|
m_nDecodeSeq = nCurSeq + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pReadPos + nPayloadSize) > pReadPosMax) {
|
if ((pReadPos + nPayloadSize) > pReadPosMax)
|
||||||
|
{
|
||||||
Assert(false);
|
Assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pWritePosMax < pWritePos + (FRAME_SIZE * 2)) {
|
if ((pWritePos + MAX_FRAME_SIZE) > pWritePosMax)
|
||||||
|
{
|
||||||
Assert(false);
|
Assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(pWritePos, 0, FRAME_SIZE * 2);
|
memset(pWritePos, 0, MAX_FRAME_SIZE);
|
||||||
|
|
||||||
if (nPayloadSize == 0)
|
if (nPayloadSize == 0)
|
||||||
{
|
{
|
||||||
pWritePos += FRAME_SIZE * 2;
|
// DTX (discontinued transmission)
|
||||||
|
pWritePos += MAX_FRAME_SIZE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,11 +245,13 @@ int VoiceEncoder_Opus::Decompress(const char *pCompressed, int compressedBytes,
|
|||||||
if (nBytes <= 0)
|
if (nBytes <= 0)
|
||||||
{
|
{
|
||||||
// raw corrupted
|
// raw corrupted
|
||||||
return 0;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pWritePos += nBytes * BYTES_PER_SAMPLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pReadPos += nPayloadSize;
|
pReadPos += nPayloadSize;
|
||||||
pWritePos += nBytes * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (pWritePos - pUncompressed) / BYTES_PER_SAMPLE;
|
return (pWritePos - pUncompressed) / BYTES_PER_SAMPLE;
|
||||||
|
@ -18,8 +18,8 @@ private:
|
|||||||
int m_samplerate;
|
int m_samplerate;
|
||||||
int m_bitrate;
|
int m_bitrate;
|
||||||
|
|
||||||
uint16 m_nCurFrame;
|
uint16 m_nEncodeSeq;
|
||||||
uint16 m_nLastFrame;
|
uint16 m_nDecodeSeq;
|
||||||
|
|
||||||
bool m_PacketLossConcealment;
|
bool m_PacketLossConcealment;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ public:
|
|||||||
virtual bool Init(int quality);
|
virtual bool Init(int quality);
|
||||||
virtual void Release();
|
virtual void Release();
|
||||||
virtual bool ResetState();
|
virtual bool ResetState();
|
||||||
virtual int Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal);
|
virtual int Compress(const char *pUncompressedBytes, int nSamplesIn, char *pCompressed, int maxCompressedBytes, bool bFinal);
|
||||||
virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes);
|
virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes);
|
||||||
|
|
||||||
int GetNumQueuedEncodingSamples() const { return m_bufOverflowBytes.TellPut() / BYTES_PER_SAMPLE; }
|
int GetNumQueuedEncodingSamples() const { return m_bufOverflowBytes.TellPut() / BYTES_PER_SAMPLE; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user