[Opentnl-cvs] tnl/zap voiceCodec.cpp,NONE,1.1 voiceCodec.h,NONE,1.1 UIGame.cpp,1.20,1.21 UIGame.h,1.
Brought to you by:
mark_frohnmayer,
s_alanet
From: Mark F. <mar...@us...> - 2004-05-08 22:01:25
|
Update of /cvsroot/opentnl/tnl/zap In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25789/zap Modified Files: UIGame.cpp UIGame.h ZAP.vcproj gameType.cpp gameType.h Added Files: voiceCodec.cpp voiceCodec.h Log Message: Added new voice codec abstraction classes --- NEW FILE: voiceCodec.h --- //----------------------------------------------------------------------------------- // // Torque Network Library - ZAP example multiplayer vector graphics space game // Copyright (C) 2004 GarageGames.com, Inc. // For more information see http://www.opentnl.org // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // For use in products that are not compatible with the terms of the GNU // General Public License, alternative licensing options are available // from GarageGames.com. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //------------------------------------------------------------------------------------ #ifndef _VOICECODEC_H_ #define _VOICECODEC_H_ #ifndef _TNL_BYTEBUFFER_H_ #include "tnlByteBuffer.h" #endif using namespace TNL; namespace Zap { /// The VoiceEncoder class is an abstract base class for the various /// voice compression algorithms supported by Zap - initially just the /// HawkVoice variable bitrate LPC10 codec. It takes an arbitrary buffer /// of 16 bit samples at 8KHz and returns a compressed buffer. The /// original buffer is modified to contain any samples that were not used /// due to unfilled frame sizing. class VoiceEncoder : public Object { virtual U32 getSamplesPerFrame() = 0; virtual U32 getMaxCompressedFrameSize() = 0; virtual U32 compressFrame(S16 *samplePtr, U8 *outputPtr) = 0; public: ByteBufferPtr compressBuffer(ByteBufferPtr sampleBuffer); }; /// The VoiceDecoder class is an abstract base class for the various /// voice decompression algorithms supported by Zap - initially just the /// HawkVoice variable bitrate LPC10 codec. It takes a buffer compressed /// with the appropriate VoiceEncoder analogue and returns the decompressed /// 16 bit sample buffer. class VoiceDecoder : public Object { virtual U32 getSamplesPerFrame() = 0; virtual U32 getAvgCompressedFrameSize() = 0; virtual U32 decompressFrame(S16 *framePtr, U8 *inputPtr) = 0; public: ByteBufferPtr decompressBuffer(ByteBufferRef compressedBuffer); }; /// The LPC10VoiceEncoder class implements the HawkVoice LPC10 codec /// compressor. class LPC10VoiceEncoder : public VoiceEncoder { void *encoderState; U32 getSamplesPerFrame(); U32 getMaxCompressedFrameSize(); U32 compressFrame(S16 *samplePtr, U8 *outputPtr); public: LPC10VoiceEncoder(); ~LPC10VoiceEncoder(); }; /// The LPC10VoiceDecoder class implements the HawkVoice LPC10 codec /// decompressor. class LPC10VoiceDecoder : public VoiceDecoder { void *decoderState; U32 getSamplesPerFrame(); U32 getAvgCompressedFrameSize(); U32 decompressFrame(S16 *framePtr, U8 *inputPtr); public: LPC10VoiceDecoder(); ~LPC10VoiceDecoder(); }; }; #endif --- NEW FILE: voiceCodec.cpp --- //----------------------------------------------------------------------------------- // // Torque Network Library - ZAP example multiplayer vector graphics space game // Copyright (C) 2004 GarageGames.com, Inc. // For more information see http://www.opentnl.org // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // For use in products that are not compatible with the terms of the GNU // General Public License, alternative licensing options are available // from GarageGames.com. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //------------------------------------------------------------------------------------ #include "voiceCodec.h" #include "lpc10.h" namespace Zap { ByteBufferPtr VoiceEncoder::compressBuffer(ByteBufferPtr sampleBuffer) { U32 sampleCount = sampleBuffer->getBufferSize() >> 1; U32 spf = getSamplesPerFrame(); U32 framesUsed = U32(sampleCount / spf); if(framesUsed) { U32 samplesUsed = framesUsed * spf; U32 maxSize = getMaxCompressedFrameSize() * framesUsed; ByteBufferPtr ret = new ByteBuffer(maxSize); U8 *compressedPtr = ret->getBuffer(); S16 *samplePtr = (S16 *) sampleBuffer->getBuffer(); U32 len = 0; for(U32 i = 0; i < samplesUsed; i += spf) len += compressFrame(samplePtr + i, compressedPtr + len); ret->resize(len); U32 newSize = (sampleCount - samplesUsed) * sizeof(U16); memcpy(samplePtr, samplePtr + samplesUsed, newSize); sampleBuffer->resize(newSize); return ret; } return NULL; } ByteBufferPtr VoiceDecoder::decompressBuffer(ByteBufferRef compressedBuffer) { U32 spf = getSamplesPerFrame(); U32 avgCompressedSize = getAvgCompressedFrameSize(); U32 compressedSize = compressedBuffer.getBufferSize(); // guess the total number of frames: U32 guessFrameCount = (compressedSize / avgCompressedSize) + 1; ByteBufferPtr ret = new ByteBuffer(spf * sizeof(S16) * guessFrameCount); U32 p = 0; U8 *inputPtr = (U8 *) compressedBuffer.getBuffer(); U32 frameCount = 0; S16 *samplePtr = (S16 *) ret->getBuffer(); for(U32 i = 0; i < compressedSize; i += p) { if(frameCount == guessFrameCount) { guessFrameCount = frameCount + ( (compressedSize - i) / avgCompressedSize ) + 1; ret->resize(spf * sizeof(S16) * guessFrameCount); samplePtr = (S16 *) ret->getBuffer(); } p = decompressFrame(samplePtr + frameCount * spf, inputPtr + i); frameCount++; } ret->resize(frameCount * spf * sizeof(S16)); return ret; } LPC10VoiceEncoder::LPC10VoiceEncoder() { encoderState = create_lpc10_encoder_state(); init_lpc10_encoder_state((lpc10_encoder_state *) encoderState); } LPC10VoiceEncoder::~LPC10VoiceEncoder() { destroy_lpc10_encoder_state((lpc10_encoder_state *) encoderState); } U32 LPC10VoiceEncoder::getSamplesPerFrame() { return LPC10_SAMPLES_PER_FRAME; } U32 LPC10VoiceEncoder::getMaxCompressedFrameSize() { return LPC10_ENCODED_FRAME_SIZE; } U32 LPC10VoiceEncoder::compressFrame(S16 *samplePtr, U8 *outputPtr) { return vbr_lpc10_encode(samplePtr, outputPtr, (lpc10_encoder_state *) encoderState); } LPC10VoiceDecoder::LPC10VoiceDecoder() { decoderState = create_lpc10_decoder_state(); init_lpc10_decoder_state((lpc10_decoder_state *) decoderState); } LPC10VoiceDecoder::~LPC10VoiceDecoder() { destroy_lpc10_decoder_state((lpc10_decoder_state *) decoderState); } U32 LPC10VoiceDecoder::getSamplesPerFrame() { return LPC10_SAMPLES_PER_FRAME; } U32 LPC10VoiceDecoder::getAvgCompressedFrameSize() { return (LPC10_ENCODED_FRAME_SIZE + 1) >> 1; } U32 LPC10VoiceDecoder::decompressFrame(S16 *framePtr, U8 *inputPtr) { int p; vbr_lpc10_decode(inputPtr, framePtr, (lpc10_decoder_state *) decoderState, &p); return (U32) p; } }; Index: gameType.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/gameType.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** gameType.cpp 8 May 2004 00:03:51 -0000 1.21 --- gameType.cpp 8 May 2004 22:01:13 -0000 1.22 *************** *** 433,438 **** cref.wantsScoreboardUpdates = false; cref.ping = 0; ! cref.decoderState = create_lpc10_decoder_state(); ! init_lpc10_decoder_state(cref.decoderState); cref.voiceSFX = new SFXObject(SFXVoice, NULL, 1, Point(), Point()); --- 433,438 ---- cref.wantsScoreboardUpdates = false; cref.ping = 0; ! cref.decoder = new LPC10VoiceDecoder(); ! cref.voiceSFX = new SFXObject(SFXVoice, NULL, 1, Point(), Point()); *************** *** 462,466 **** { S32 clientIndex = findClientIndexByName(name); - destroy_lpc10_decoder_state(mClientList[clientIndex].decoderState); gGameUserInterface.displayMessage(Color(0.6f, 0.6f, 0.8f), "%s left the game.", name.getString()); --- 462,465 ---- *************** *** 626,641 **** if(clientIndex != -1) { ! S16 frame[LPC10_SAMPLES_PER_FRAME]; ! int p = 0, decodeLen = 0; ! ByteBufferPtr playBuffer = new ByteBuffer(0); ! ! for(U32 i = 0; i < voiceBuffer.getBufferSize(); i += p) ! { ! int frameLen = vbr_lpc10_decode((unsigned char *) voiceBuffer.getBuffer() + i, frame, mClientList[clientIndex].decoderState, &p); ! playBuffer->resize((decodeLen + frameLen) * 2); ! ! memcpy(playBuffer->getBuffer() + decodeLen * 2, frame, frameLen * 2); ! decodeLen += frameLen; ! } //logprintf("Decoded buffer size %d", playBuffer->getBufferSize()); --- 625,629 ---- if(clientIndex != -1) { ! ByteBufferPtr playBuffer = mClientList[clientIndex].decoder->decompressBuffer(voiceBuffer); //logprintf("Decoded buffer size %d", playBuffer->getBufferSize()); Index: gameType.h =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/gameType.h,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** gameType.h 8 May 2004 00:03:51 -0000 1.11 --- gameType.h 8 May 2004 22:01:13 -0000 1.12 *************** *** 31,35 **** #include "timer.h" #include "sfx.h" ! #include "lpc10.h" namespace Zap --- 31,35 ---- #include "timer.h" #include "sfx.h" ! #include "voiceCodec.h" namespace Zap *************** *** 54,58 **** SafePtr<GameConnection> clientConnection; RefPtr<SFXObject> voiceSFX; ! lpc10_decoder_state *decoderState; U32 ping; ClientRef() { ping = 0; score = 0; } --- 54,59 ---- SafePtr<GameConnection> clientConnection; RefPtr<SFXObject> voiceSFX; ! RefPtr<VoiceDecoder> decoder; ! U32 ping; ClientRef() { ping = 0; score = 0; } Index: ZAP.vcproj =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/ZAP.vcproj,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** ZAP.vcproj 7 May 2004 02:21:46 -0000 1.13 --- ZAP.vcproj 8 May 2004 22:01:13 -0000 1.14 *************** *** 313,316 **** --- 313,322 ---- </File> <File + RelativePath=".\voiceCodec.cpp"> + </File> + <File + RelativePath=".\voiceCodec.h"> + </File> + <File RelativePath=".\winJoystick.cpp"> </File> Index: UIGame.h =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/UIGame.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** UIGame.h 7 May 2004 02:21:46 -0000 1.6 --- UIGame.h 8 May 2004 22:01:13 -0000 1.7 *************** *** 34,37 **** --- 34,38 ---- #include "timer.h" #include "sfx.h" + #include "voiceCodec.h" namespace Zap *************** *** 85,88 **** --- 86,91 ---- Timer mVoiceAudioTimer; RefPtr<SFXObject> mVoiceSfx; + RefPtr<VoiceEncoder> mVoiceEncoder; + ByteBufferPtr mUnusedAudio; public: Index: UIGame.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/zap/UIGame.cpp,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** UIGame.cpp 8 May 2004 00:03:51 -0000 1.20 --- UIGame.cpp 8 May 2004 22:01:13 -0000 1.21 *************** *** 61,64 **** --- 61,65 ---- mRecordingAudio = false; mMaxAudioSample = 0; + mVoiceEncoder = new LPC10VoiceEncoder; } *************** *** 525,537 **** } - static lpc10_encoder_state *encoderState = NULL; - void GameUserInterface::startRecordingAudio() { if(!mRecordingAudio) { - encoderState = create_lpc10_encoder_state(); - init_lpc10_encoder_state(encoderState); - mUnusedAudio = new ByteBuffer(0); mRecordingAudio = true; --- 526,533 ---- *************** *** 539,542 **** --- 535,542 ---- mVoiceAudioTimer.reset(FirstVoiceAudioSampleTime); SFXObject::startRecording(); + + // trim the start of the capture buffer: + SFXObject::captureSamples(mUnusedAudio); + mUnusedAudio->resize(0); } } *************** *** 547,555 **** { processRecordingAudio(); ! destroy_lpc10_encoder_state(encoderState); mRecordingAudio = false; SFXObject::stopRecording(); mVoiceSfx = NULL; } } --- 547,556 ---- { processRecordingAudio(); ! SFXObject::stopRecording(); mRecordingAudio = false; SFXObject::stopRecording(); mVoiceSfx = NULL; + mUnusedAudio = NULL; } } *************** *** 558,563 **** { SFXObject::captureSamples(mUnusedAudio); ! U32 sampleCount = mUnusedAudio->getBufferSize() / 2; S16 *samplePtr = (S16 *) mUnusedAudio->getBuffer(); mMaxAudioSample = 0; --- 559,565 ---- { SFXObject::captureSamples(mUnusedAudio); ! ByteBufferPtr sendBuffer = mVoiceEncoder->compressBuffer(mUnusedAudio); + U32 sampleCount = mUnusedAudio->getBufferSize() / 2; S16 *samplePtr = (S16 *) mUnusedAudio->getBuffer(); mMaxAudioSample = 0; *************** *** 567,592 **** mMaxAudioSample = samplePtr[i]; ! U32 useCount = U32(sampleCount / LPC10_SAMPLES_PER_FRAME) * LPC10_SAMPLES_PER_FRAME; ! //U32 useCount = sampleCount - (sampleCount % LPC10_SAMPLES_PER_FRAME); ! ! if(useCount) ! { ! U32 unusedCount = sampleCount - useCount; ! ! U8 codingBuffer[2048]; ! U32 len = 0; ! ! for(U32 i = 0; i < useCount; i += LPC10_SAMPLES_PER_FRAME) ! len += vbr_lpc10_encode(samplePtr + i, codingBuffer + len, encoderState); ! ! memcpy(mUnusedAudio->getBuffer(), mUnusedAudio->getBuffer() + useCount * 2, unusedCount * 2); ! mUnusedAudio->resize(unusedCount * 2); ! ! ByteBuffer sendBuffer(codingBuffer, len); ! //logprintf("Encoded %d samples in %d bytes", useCount, len); ! GameType *gt = gClientGame->getGameType(); if(gt) ! gt->c2sVoiceChat(OptionsMenuUserInterface::echoVoice, sendBuffer); } } --- 569,577 ---- mMaxAudioSample = samplePtr[i]; ! if(sendBuffer.isValid()) ! { GameType *gt = gClientGame->getGameType(); if(gt) ! gt->c2sVoiceChat(OptionsMenuUserInterface::echoVoice, *(sendBuffer.getPointer())); } } |