From da09f7ba44f1ed6ba565e0b2e53c702bf389db1c Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 15 Nov 2010 02:40:31 +0000 Subject: [PATCH] Me having lots of fun with voice chat. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3656 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 4 +- engine/client/cl_input.c | 7 +- engine/client/cl_main.c | 8 +- engine/client/cl_parse.c | 6 + engine/client/image.c | 8 +- engine/client/r_surf.c | 6 + engine/client/snd_directx.c | 59 ++-- engine/client/snd_dma.c | 233 ++++++++++++++- engine/client/snd_mix.c | 2 +- engine/client/sound.h | 5 + engine/common/bothdefs.h | 2 +- engine/common/protocol.h | 31 +- engine/d3d/d3d_backend.c | 2 + engine/gl/gl_alias.c | 76 +++++ engine/gl/gl_backend.c | 2 +- engine/libs/speex/speex.h | 424 +++++++++++++++++++++++++++ engine/libs/speex/speex_bits.h | 174 +++++++++++ engine/libs/speex/speex_buffer.h | 68 +++++ engine/libs/speex/speex_callbacks.h | 134 +++++++++ engine/libs/speex/speex_echo.h | 123 ++++++++ engine/libs/speex/speex_header.h | 94 ++++++ engine/libs/speex/speex_jitter.h | 197 +++++++++++++ engine/libs/speex/speex_preprocess.h | 190 ++++++++++++ engine/libs/speex/speex_resampler.h | 340 +++++++++++++++++++++ engine/libs/speex/speex_stereo.h | 91 ++++++ engine/libs/speex/speex_types.h | 126 ++++++++ engine/server/botlib.h | 2 +- engine/server/server.h | 16 +- engine/server/sv_main.c | 11 +- engine/server/sv_send.c | 3 + engine/server/sv_user.c | 169 ++++++++++- engine/server/svq3_game.c | 5 + 32 files changed, 2521 insertions(+), 97 deletions(-) create mode 100644 engine/libs/speex/speex.h create mode 100644 engine/libs/speex/speex_bits.h create mode 100644 engine/libs/speex/speex_buffer.h create mode 100644 engine/libs/speex/speex_callbacks.h create mode 100644 engine/libs/speex/speex_echo.h create mode 100644 engine/libs/speex/speex_header.h create mode 100644 engine/libs/speex/speex_jitter.h create mode 100644 engine/libs/speex/speex_preprocess.h create mode 100644 engine/libs/speex/speex_resampler.h create mode 100644 engine/libs/speex/speex_stereo.h create mode 100644 engine/libs/speex/speex_types.h diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 5518b4caa..e2953284c 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -427,9 +427,9 @@ qboolean CL_GetDemoMessage (void) olddemotime = 0; return 0; } - if (demtime<= cl.gametime && cl.gametime)// > dem_lasttime+demtime) + if ((cls.timedemo && cls.netchan.last_received == (float)realtime) || (!cls.timedemo && demtime<= cl.gametime && cl.gametime))// > dem_lasttime+demtime) { - if (demtime <= cl.gametime-1||cls.timedemo) + if (demtime <= cl.gametime-1) { demtime = cl.gametime; cls.netchan.last_received = realtime; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index f84021274..1d9ce59f8 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1438,7 +1438,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf) void CL_SendCmd (double frametime, qboolean mainloop) { sizebuf_t buf; - qbyte data[512]; + qbyte data[1024]; int i, plnum; usercmd_t *cmd; float wantfps; @@ -1768,6 +1768,11 @@ void CL_SendCmd (double frametime, qboolean mainloop) dropcount = 0; } +#ifdef PEXT2_VOICECHAT + if (cls.fteprotocolextensions2 & PEXT2_VOICECHAT) + S_TransmitVoiceChat(clc_voicechat, &buf); +#endif + // // deliver the message // diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f6aea004c..da8cba38c 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -394,6 +394,9 @@ void CL_SupportedFTEExtensions(int *pext1, int *pext2) #endif fteprotextsupported2 |= PEXT2_PRYDONCURSOR; +#ifdef PEXT2_VOICECHAT + fteprotextsupported2 |= PEXT2_VOICECHAT; +#endif fteprotextsupported &= strtoul(cl_pext_mask.string, NULL, 16); // fteprotextsupported2 &= strtoul(cl_pext2_mask.string, NULL, 16); @@ -3358,11 +3361,6 @@ void Host_Frame (double time) if (cl.paused) cl.gametimemark += time; - -#ifdef VOICECHAT - CLVC_Poll(); -#endif - /* if (cl_maxfps.value) fps = cl_maxfps.value;//max(30.0, min(cl_maxfps.value, 72.0)); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index bfce43808..296a5cc43 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -4961,6 +4961,12 @@ void CL_ParseServerMessage (void) S_StopSound(i>>3, i&7); break; +#ifdef PEXT2_VOICECHAT + case svcfte_voicechat: + S_ParseVoiceChat(); + break; +#endif + case svc_updatefrags: Sbar_Changed (); i = MSG_ReadByte (); diff --git a/engine/client/image.c b/engine/client/image.c index 28c9da2e9..39d90b788 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -897,6 +897,10 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i #define LIBJPEG_LOADED() (1) #endif +#ifndef JPEG_FALSE +#define JPEG_boolean boolean +#endif + #define qjpeg_create_compress(cinfo) \ qjpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_compress_struct)) @@ -955,10 +959,6 @@ qboolean LibJPEG_Init(void) return LIBJPEG_LOADED(); } -#ifndef JPEG_FALSE -#define JPEG_boolean boolean -#endif - /*begin jpeg read*/ struct my_error_mgr { diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 3ec2b9969..225f0ecd2 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -2557,6 +2557,12 @@ void Surf_BuildLightmaps (void) lightmap_bgra = true; lightmap_bytes = 4; + if (atof(qglGetString(GL_VERSION)) < 1.2) + { + lightmap_bgra = false; + lightmap_bytes = 3; + } + for (j=1 ; j 1400) //figure out how much we need to empty it by, and if that's enough to be worthwhile. - filled = 1400; - else if (filled < 1400) - return; - - if ((filled/inputwidth) & 1) //force even numbers of samples - filled -= inputwidth; - - pBuffer = BZ_Malloc(filled*inputwidth); + if (filled > maxbytes) //figure out how much we need to empty it by, and if that's enough to be worthwhile. + filled = maxbytes; + else if (filled < minbytes) + return 0; +// filled /= inputwidth; +// filled *= inputwidth; // Lock free space in the DS - hr = IDirectSoundCaptureBuffer_Lock ( DSCaptureBuffer, lastreadpos, filled, (void **) &lpbuf1, &dwsize1, - (void **) &lpbuf2, &dwsize2, 0); + hr = IDirectSoundCaptureBuffer_Lock(DSCaptureBuffer, lastreadpos, filled, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy from DS to the buffer - memcpy( pBuffer, lpbuf1, dwsize1); + memcpy(buffer, lpbuf1, dwsize1); if(lpbuf2 != NULL) { - memcpy( pBuffer+dwsize1, lpbuf2, dwsize2); + memcpy(buffer+dwsize1, lpbuf2, dwsize2); } // Update our buffer offset and unlock sound buffer lastreadpos = (lastreadpos + dwsize1 + dwsize2) % bufferbytes; - IDirectSoundCaptureBuffer_Unlock ( DSCaptureBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); + IDirectSoundCaptureBuffer_Unlock(DSCaptureBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); } else { - BZ_Free(pBuffer); - return; + return 0; } - - SNDVC_MicInput(pBuffer, filled, wfxFormat.nSamplesPerSec, inputwidth); - BZ_Free(pBuffer); + return filled; } -void (*pDSOUND_UpdateCapture) (void) = &DSOUND_UpdateCapture; +unsigned int (*pDSOUND_UpdateCapture) (unsigned char *buffer, unsigned int minbytes, unsigned int maxbytes) = &DSOUND_UpdateCapture; #endif diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 40220846f..209e2a4fa 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -152,16 +152,232 @@ void S_SoundInfo_f(void) } } -void (*pDSOUND_UpdateCapture) (void); -void S_RunCapture(void) +#ifdef VOICECHAT +#include "speex/speex.h" +#include "speex/speex_preprocess.h" +struct { + qboolean inited; + qboolean loaded; + dllhandle_t *speexlib; + dllhandle_t *speexdsplib; + + SpeexBits encbits; + void *encoder; + SpeexPreprocessState *preproc; + unsigned int framesize; + unsigned int samplerate; + + SpeexBits decbits[MAX_CLIENTS]; + void *decoder[MAX_CLIENTS]; + unsigned char decseq[MAX_CLIENTS]; +} s_speex; + +const SpeexMode *(VARGS *qspeex_lib_get_mode)(int mode); +void (VARGS *qspeex_bits_init)(SpeexBits *bits); +void (VARGS *qspeex_bits_reset)(SpeexBits *bits); +int (VARGS *qspeex_bits_write)(SpeexBits *bits, char *bytes, int max_len); + +SpeexPreprocessState *(VARGS *qspeex_preprocess_state_init)(int frame_size, int sampling_rate); +int (VARGS *qspeex_preprocess_ctl)(SpeexPreprocessState *st, int request, void *ptr); +int (VARGS *qspeex_preprocess_run)(SpeexPreprocessState *st, spx_int16_t *x); + +void * (VARGS *qspeex_encoder_init)(const SpeexMode *mode); +int (VARGS *qspeex_encoder_ctl)(void *state, int request, void *ptr); +int (VARGS *qspeex_encode_int)(void *state, spx_int16_t *in, SpeexBits *bits); + +void *(VARGS *qspeex_decoder_init)(const SpeexMode *mode); +int (VARGS *qspeex_decode_int)(void *state, SpeexBits *bits, spx_int16_t *out); +void (VARGS *qspeex_bits_read_from)(SpeexBits *bits, char *bytes, int len); + +dllfunction_t qspeexfuncs[] = +{ + {(void*)&qspeex_lib_get_mode, "speex_lib_get_mode"}, + {(void*)&qspeex_bits_init, "speex_bits_init"}, + {(void*)&qspeex_bits_reset, "speex_bits_reset"}, + {(void*)&qspeex_bits_write, "speex_bits_write"}, + + {(void*)&qspeex_encoder_init, "speex_encoder_init"}, + {(void*)&qspeex_encoder_ctl, "speex_encoder_ctl"}, + {(void*)&qspeex_encode_int, "speex_encode_int"}, + + {(void*)&qspeex_decoder_init, "speex_decoder_init"}, + {(void*)&qspeex_decode_int, "speex_decode_int"}, + {(void*)&qspeex_bits_read_from, "speex_bits_read_from"}, + + {NULL} +}; +dllfunction_t qspeexdspfuncs[] = +{ + {(void*)&qspeex_preprocess_state_init, "speex_preprocess_state_init"}, + {(void*)&qspeex_preprocess_ctl, "speex_preprocess_ctl"}, + {(void*)&qspeex_preprocess_run, "speex_preprocess_run"}, + + {NULL} +}; + +qboolean S_Speex_Init(void) +{ + int i; + const SpeexMode *mode; + if (s_speex.inited) + return s_speex.loaded; + s_speex.inited = true; + + s_speex.speexlib = Sys_LoadLibrary("libspeex", qspeexfuncs); + if (!s_speex.speexlib) + { + Con_Printf("libspeex not found. Voice chat not available.\n"); + return false; + } + + s_speex.speexdsplib = Sys_LoadLibrary("libspeexdsp", qspeexdspfuncs); + if (!s_speex.speexdsplib) + { + Con_Printf("libspeexdsp not found. Voice chat not available.\n"); + return false; + } + + mode = qspeex_lib_get_mode(SPEEX_MODEID_NB); + + + qspeex_bits_init(&s_speex.encbits); + qspeex_bits_reset(&s_speex.encbits); + + s_speex.encoder = qspeex_encoder_init(mode); + + qspeex_encoder_ctl(s_speex.encoder, SPEEX_GET_FRAME_SIZE, &s_speex.framesize); + qspeex_encoder_ctl(s_speex.encoder, SPEEX_GET_SAMPLING_RATE, &s_speex.samplerate); + + s_speex.preproc = qspeex_preprocess_state_init(s_speex.framesize, s_speex.samplerate); + + i = 1; + qspeex_preprocess_ctl(s_speex.preproc, SPEEX_PREPROCESS_SET_DENOISE, &i); + + i = 1; + qspeex_preprocess_ctl(s_speex.preproc, SPEEX_PREPROCESS_SET_AGC, &i); + + for (i = 0; i < MAX_CLIENTS; i++) + { + qspeex_bits_init(&s_speex.decbits[i]); + qspeex_bits_reset(&s_speex.decbits[i]); + s_speex.decoder[i] = qspeex_decoder_init(mode); + } + s_speex.loaded = true; + return s_speex.loaded; +} + +void S_ParseVoiceChat(void) +{ + unsigned int sender = MSG_ReadByte(); + int bytes; + unsigned char data[1024], *start; + short decodebuf[1024]; + unsigned int decodesamps, len, newseq, drops; + unsigned char seq; + seq = MSG_ReadByte(); + bytes = MSG_ReadShort(); + if (bytes > sizeof(data)) + { + MSG_ReadSkip(bytes); + return; + } + MSG_ReadData(data, bytes); + + sender &= MAX_CLIENTS-1; + + decodesamps = 0; + newseq = 0; + drops = 0; + start = data; + while (bytes > 0) + { + if (decodesamps + s_speex.framesize > sizeof(decodebuf)/sizeof(decodebuf[0])) + { + S_RawAudio(sender, (qbyte*)decodebuf, 11025, decodesamps, 1, 2); + decodesamps = 0; + } + + if (s_speex.decseq[sender] != seq) + { + qspeex_decode_int(s_speex.decoder[sender], NULL, decodebuf + decodesamps); + s_speex.decseq[sender]++; + drops++; + } + else + { + bytes--; + len = *start++; + qspeex_bits_read_from(&s_speex.decbits[sender], start, len); + bytes -= len; + start += len; + qspeex_decode_int(s_speex.decoder[sender], &s_speex.decbits[sender], decodebuf + decodesamps); + newseq++; + } + decodesamps += s_speex.framesize; + } + s_speex.decseq[sender] += newseq; + + if (drops) + Con_Printf("%i dropped audio frames\n", drops); + + if (decodesamps > 0) + S_RawAudio(sender, (qbyte*)decodebuf, 11025, decodesamps, 1, 2); +} + +unsigned int (*pDSOUND_UpdateCapture) (unsigned char *buffer, unsigned int minbytes, unsigned int maxbytes); +void S_TransmitVoiceChat(unsigned char clc, sizebuf_t *buf) +{ + static unsigned char capturebuf[32768]; + static unsigned int capturepos;//in bytes + static unsigned int encsequence;//in frames + unsigned char outbuf[1024]; + unsigned int outpos;//in bytes + unsigned int encpos;//in bytes + unsigned short *start; + unsigned char initseq;//in frames + //add new drivers in order or desirability. if (pDSOUND_UpdateCapture) { - pDSOUND_UpdateCapture(); + capturepos += pDSOUND_UpdateCapture((unsigned char*)capturebuf + capturepos, 64, sizeof(capturebuf) - capturepos); + } + else + { return; } + + if (!S_Speex_Init()) + return; + + initseq = encsequence; + for (encpos = 0, outpos = 0; capturepos-encpos >= s_speex.framesize*2 && sizeof(outbuf)-outpos > 64; ) + { + start = (short*)(capturebuf + encpos); + + qspeex_preprocess_run(s_speex.preproc, start); + + qspeex_bits_reset(&s_speex.encbits); + qspeex_encode_int(s_speex.encoder, start, &s_speex.encbits); + outbuf[outpos] = qspeex_bits_write(&s_speex.encbits, outbuf+outpos+1, sizeof(outbuf) - (outpos+1)); + outpos += 1+outbuf[outpos]; + encpos += s_speex.framesize*2; + encsequence++; + } + + if (outpos && buf->maxsize - buf->cursize >= outpos+4) + { + MSG_WriteByte(buf, clc); + MSG_WriteByte(buf, initseq); + MSG_WriteShort(buf, outpos); + SZ_Write(buf, outbuf, outpos); + } + + /*remove sent data*/ + memmove(capturebuf, capturebuf + encpos, capturepos-encpos); + capturepos -= encpos; } +#endif sounddriver pOPENAL_InitCard; @@ -1415,8 +1631,6 @@ void S_Update (void) { soundcardinfo_t *sc; - S_RunCapture(); - for (sc = sndcardinfo; sc; sc = sc->next) S_UpdateCard(sc); } @@ -1435,8 +1649,6 @@ void S_ExtraUpdate (void) if (snd_noextraupdate.ival) return; // don't pollute timings - S_RunCapture(); - for (sc = sndcardinfo; sc; sc = sc->next) S_Update_(sc); } @@ -1655,7 +1867,8 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, { if (!s->inuse) { - free = s; + if (!free) + free = s; continue; } if (s->id == sourceid) @@ -1719,8 +1932,8 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, for (i = 0; i < si->total_chans; i++) if (si->channel[i].sfx == &s->sfx) { - if (prepadl > si->channel[i].pos) - prepadl = si->channel[i].pos; + if (prepadl > (si->channel[i].pos>>8)) + prepadl = (si->channel[i].pos>>8); break; } } diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index d5f687514..3a904c490 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -169,7 +169,7 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime) if ((ch->pos>>PITCHSHIFT) > scache->length) //cache was flushed and gamedir changed. { ch->pos = scache->length*ch->rate; - ch->end = scache->length*ch->rate; + ch->end = scache->length; } diff --git a/engine/client/sound.h b/engine/client/sound.h index 1a3917f3e..4a6bc13ac 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -147,6 +147,11 @@ void S_StopSoundCard (soundcardinfo_t *sc, int entnum, int entchannel); void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc); void S_ResetFailedLoad(void); +#ifdef VOICECHAT +void S_ParseVoiceChat(void); +void S_TransmitVoiceChat(unsigned char clc, sizebuf_t *buf); +#endif + qboolean S_IsPlayingSomewhere(sfx_t *s); void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, qbyte *data); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 567a0c161..e83b33ae5 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -199,7 +199,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PSET_CLASSIC //#define PSET_DARKPLACES -// #define VOICECHAT //not added yet. + //#define VOICECHAT //not added yet. //these things were moved to plugins. #endif diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 7182c20e4..62b1b6590 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -55,7 +55,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //#define PEXT_NEVERUSED 0x02000000 //Client is able to cope with 64 players. Wow. #define PEXT_SHOWPIC 0x04000000 #define PEXT_SETATTACHMENT 0x08000000 //md3 tags (needs networking, they need to lerp). -//#define PEXT2_NEVERUSED 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs) +//#define PEXT_NEVERUSED 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs) #define PEXT_CHUNKEDDOWNLOADS 0x20000000 //alternate file download method. Hopefully it'll give quadroupled download speed, especially on higher pings. #ifdef CSQC_DAT @@ -71,6 +71,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #define PEXT2_PRYDONCURSOR 0x00000001 +#ifdef VOICECHAT +#define PEXT2_VOICECHAT 0x00000002 +#endif //#define PEXT2_64PLAYERS 0x02000000 //Client is able to cope with 64 players. Wow. //#define PEXT2_PK3DOWNLOADS 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs) @@ -268,6 +271,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcfte_pointparticles1 82 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 #define svcfte_cgamepacket 83 +#define svcfte_voicechat 84 //fitz svcs @@ -341,20 +345,21 @@ enum clcq2_ops_e // // client to server // -#define clc_bad 0 -#define clc_nop 1 -#define clc_disconnect 2 //nq only -#define clc_move 3 // [[usercmd_t] -#define clc_stringcmd 4 // [string] message -#define clc_delta 5 // [qbyte] sequence number, requests delta compression of message -#define clc_tmove 6 // teleport request, spectator only -#define clc_upload 7 // teleport request, spectator only +#define clc_bad 0 +#define clc_nop 1 +#define clc_disconnect 2 //nq only +#define clc_move 3 // [[usercmd_t] +#define clc_stringcmd 4 // [string] message +#define clc_delta 5 // [qbyte] sequence number, requests delta compression of message +#define clc_tmove 6 // teleport request, spectator only +#define clc_upload 7 // teleport request, spectator only -#define clcdp_ackframe 50 -#define clcdp_ackdownloaddata 51 +#define clcdp_ackframe 50 +#define clcdp_ackdownloaddata 51 -#define clc_qcrequest 81 -#define clc_prydoncursor 82 +#define clc_qcrequest 81 +#define clc_prydoncursor 82 +#define clc_voicechat 83 //============================================== diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 2e6d7d1af..c30a24645 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -2093,6 +2093,8 @@ static void BE_GenModelBatches(batch_t **batches) continue; R_GAlias_GenerateBatches(ent, batches); break; + case mod_sprite: + break; } break; case RT_SPRITE: diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 344f2dba1..96b954487 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1008,6 +1008,82 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) } } +#if 0 +void R_Sprite_GenerateBatches(entity_t *e, batch_t **batches) +{ + galiasinfo_t *inf; + model_t *clmodel; + shader_t *shader; + batch_t *b; + int surfnum; + + texnums_t *skin; + + if (r_refdef.externalview && e->flags & Q2RF_WEAPONMODEL) + return; + + clmodel = e->model; + + if (!(e->flags & Q2RF_WEAPONMODEL)) + { + if (R_CullEntityBox (e, clmodel->mins, clmodel->maxs)) + return; +#ifdef RTLIGHTS + if (BE_LightCullModel(e->origin, clmodel)) + return; + } + else + { + if (BE_LightCullModel(r_origin, clmodel)) + return; +#endif + } + + if (clmodel->tainted) + { + if (!ruleset_allow_modified_eyes.ival && !strcmp(clmodel->name, "progs/eyes.mdl")) + return; + } + + inf = RMod_Extradata (clmodel); + + if (!e->model || e->forcedshader) + { + //fixme + return; + } + else + { + frame = R_GetSpriteFrame (e); + psprite = e->model->cache.data; + sprtype = psprite->type; + shader = frame->shader; + } + + if (shader) + { + b = BE_GetTempBatch(); + if (!b) + break; + + b->buildmeshes = R_Sprite_DrawBatch; + b->ent = e; + b->mesh = NULL; + b->firstmesh = 0; + b->meshes = 1; + b->skin = frame-; + b->texture = NULL; + b->shader = frame->shader; + b->lightmap = -1; + b->surf_first = surfnum; + b->flags = 0; + b->vbo = 0; + b->next = batches[shader->sort]; + batches[shader->sort] = b; + } +} +#endif + //returns the rotated offset of the two points in result void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result) { diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index bd9c21e87..435a4a7d1 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -442,7 +442,7 @@ void GL_SelectTexture(int target) qglClientActiveTextureARB(target + mtexid0); qglActiveTextureARB(target + mtexid0); } - else + else if (qglSelectTextureSGIS) qglSelectTextureSGIS(target + mtexid0); } diff --git a/engine/libs/speex/speex.h b/engine/libs/speex/speex.h new file mode 100644 index 000000000..82ba01623 --- /dev/null +++ b/engine/libs/speex/speex.h @@ -0,0 +1,424 @@ +/* Copyright (C) 2002-2006 Jean-Marc Valin*/ +/** + @file speex.h + @brief Describes the different modes of the codec +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SPEEX_H +#define SPEEX_H +/** @defgroup Codec Speex encoder and decoder + * This is the Speex codec itself. + * @{ + */ + +#include "speex/speex_bits.h" +#include "speex/speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Values allowed for *ctl() requests */ + +/** Set enhancement on/off (decoder only) */ +#define SPEEX_SET_ENH 0 +/** Get enhancement state (decoder only) */ +#define SPEEX_GET_ENH 1 + +/*Would be SPEEX_SET_FRAME_SIZE, but it's (currently) invalid*/ +/** Obtain frame size used by encoder/decoder */ +#define SPEEX_GET_FRAME_SIZE 3 + +/** Set quality value */ +#define SPEEX_SET_QUALITY 4 +/** Get current quality setting */ +/* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */ + +/** Set sub-mode to use */ +#define SPEEX_SET_MODE 6 +/** Get current sub-mode in use */ +#define SPEEX_GET_MODE 7 + +/** Set low-band sub-mode to use (wideband only)*/ +#define SPEEX_SET_LOW_MODE 8 +/** Get current low-band mode in use (wideband only)*/ +#define SPEEX_GET_LOW_MODE 9 + +/** Set high-band sub-mode to use (wideband only)*/ +#define SPEEX_SET_HIGH_MODE 10 +/** Get current high-band mode in use (wideband only)*/ +#define SPEEX_GET_HIGH_MODE 11 + +/** Set VBR on (1) or off (0) */ +#define SPEEX_SET_VBR 12 +/** Get VBR status (1 for on, 0 for off) */ +#define SPEEX_GET_VBR 13 + +/** Set quality value for VBR encoding (0-10) */ +#define SPEEX_SET_VBR_QUALITY 14 +/** Get current quality value for VBR encoding (0-10) */ +#define SPEEX_GET_VBR_QUALITY 15 + +/** Set complexity of the encoder (0-10) */ +#define SPEEX_SET_COMPLEXITY 16 +/** Get current complexity of the encoder (0-10) */ +#define SPEEX_GET_COMPLEXITY 17 + +/** Set bit-rate used by the encoder (or lower) */ +#define SPEEX_SET_BITRATE 18 +/** Get current bit-rate used by the encoder or decoder */ +#define SPEEX_GET_BITRATE 19 + +/** Define a handler function for in-band Speex request*/ +#define SPEEX_SET_HANDLER 20 + +/** Define a handler function for in-band user-defined request*/ +#define SPEEX_SET_USER_HANDLER 22 + +/** Set sampling rate used in bit-rate computation */ +#define SPEEX_SET_SAMPLING_RATE 24 +/** Get sampling rate used in bit-rate computation */ +#define SPEEX_GET_SAMPLING_RATE 25 + +/** Reset the encoder/decoder memories to zero*/ +#define SPEEX_RESET_STATE 26 + +/** Get VBR info (mostly used internally) */ +#define SPEEX_GET_RELATIVE_QUALITY 29 + +/** Set VAD status (1 for on, 0 for off) */ +#define SPEEX_SET_VAD 30 + +/** Get VAD status (1 for on, 0 for off) */ +#define SPEEX_GET_VAD 31 + +/** Set Average Bit-Rate (ABR) to n bits per seconds */ +#define SPEEX_SET_ABR 32 +/** Get Average Bit-Rate (ABR) setting (in bps) */ +#define SPEEX_GET_ABR 33 + +/** Set DTX status (1 for on, 0 for off) */ +#define SPEEX_SET_DTX 34 +/** Get DTX status (1 for on, 0 for off) */ +#define SPEEX_GET_DTX 35 + +/** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */ +#define SPEEX_SET_SUBMODE_ENCODING 36 +/** Get submode encoding in each frame */ +#define SPEEX_GET_SUBMODE_ENCODING 37 + +/*#define SPEEX_SET_LOOKAHEAD 38*/ +/** Returns the lookahead used by Speex */ +#define SPEEX_GET_LOOKAHEAD 39 + +/** Sets tuning for packet-loss concealment (expected loss rate) */ +#define SPEEX_SET_PLC_TUNING 40 +/** Gets tuning for PLC */ +#define SPEEX_GET_PLC_TUNING 41 + +/** Sets the max bit-rate allowed in VBR mode */ +#define SPEEX_SET_VBR_MAX_BITRATE 42 +/** Gets the max bit-rate allowed in VBR mode */ +#define SPEEX_GET_VBR_MAX_BITRATE 43 + +/** Turn on/off input/output high-pass filtering */ +#define SPEEX_SET_HIGHPASS 44 +/** Get status of input/output high-pass filtering */ +#define SPEEX_GET_HIGHPASS 45 + +/** Get "activity level" of the last decoded frame, i.e. + how much damage we cause if we remove the frame */ +#define SPEEX_GET_ACTIVITY 47 + + +/* Preserving compatibility:*/ +/** Equivalent to SPEEX_SET_ENH */ +#define SPEEX_SET_PF 0 +/** Equivalent to SPEEX_GET_ENH */ +#define SPEEX_GET_PF 1 + + + + +/* Values allowed for mode queries */ +/** Query the frame size of a mode */ +#define SPEEX_MODE_FRAME_SIZE 0 + +/** Query the size of an encoded frame for a particular sub-mode */ +#define SPEEX_SUBMODE_BITS_PER_FRAME 1 + + + +/** Get major Speex version */ +#define SPEEX_LIB_GET_MAJOR_VERSION 1 +/** Get minor Speex version */ +#define SPEEX_LIB_GET_MINOR_VERSION 3 +/** Get micro Speex version */ +#define SPEEX_LIB_GET_MICRO_VERSION 5 +/** Get extra Speex version */ +#define SPEEX_LIB_GET_EXTRA_VERSION 7 +/** Get Speex version string */ +#define SPEEX_LIB_GET_VERSION_STRING 9 + +/*#define SPEEX_LIB_SET_ALLOC_FUNC 10 +#define SPEEX_LIB_GET_ALLOC_FUNC 11 +#define SPEEX_LIB_SET_FREE_FUNC 12 +#define SPEEX_LIB_GET_FREE_FUNC 13 + +#define SPEEX_LIB_SET_WARNING_FUNC 14 +#define SPEEX_LIB_GET_WARNING_FUNC 15 +#define SPEEX_LIB_SET_ERROR_FUNC 16 +#define SPEEX_LIB_GET_ERROR_FUNC 17 +*/ + +/** Number of defined modes in Speex */ +#define SPEEX_NB_MODES 3 + +/** modeID for the defined narrowband mode */ +#define SPEEX_MODEID_NB 0 + +/** modeID for the defined wideband mode */ +#define SPEEX_MODEID_WB 1 + +/** modeID for the defined ultra-wideband mode */ +#define SPEEX_MODEID_UWB 2 + +struct SpeexMode; + + +/* Prototypes for mode function pointers */ + +/** Encoder state initialization function */ +typedef void *(*encoder_init_func)(const struct SpeexMode *mode); + +/** Encoder state destruction function */ +typedef void (*encoder_destroy_func)(void *st); + +/** Main encoding function */ +typedef int (*encode_func)(void *state, void *in, SpeexBits *bits); + +/** Function for controlling the encoder options */ +typedef int (*encoder_ctl_func)(void *state, int request, void *ptr); + +/** Decoder state initialization function */ +typedef void *(*decoder_init_func)(const struct SpeexMode *mode); + +/** Decoder state destruction function */ +typedef void (*decoder_destroy_func)(void *st); + +/** Main decoding function */ +typedef int (*decode_func)(void *state, SpeexBits *bits, void *out); + +/** Function for controlling the decoder options */ +typedef int (*decoder_ctl_func)(void *state, int request, void *ptr); + + +/** Query function for a mode */ +typedef int (*mode_query_func)(const void *mode, int request, void *ptr); + +/** Struct defining a Speex mode */ +typedef struct SpeexMode { + /** Pointer to the low-level mode data */ + const void *mode; + + /** Pointer to the mode query function */ + mode_query_func query; + + /** The name of the mode (you should not rely on this to identify the mode)*/ + const char *modeName; + + /**ID of the mode*/ + int modeID; + + /**Version number of the bitstream (incremented every time we break + bitstream compatibility*/ + int bitstream_version; + + /** Pointer to encoder initialization function */ + encoder_init_func enc_init; + + /** Pointer to encoder destruction function */ + encoder_destroy_func enc_destroy; + + /** Pointer to frame encoding function */ + encode_func enc; + + /** Pointer to decoder initialization function */ + decoder_init_func dec_init; + + /** Pointer to decoder destruction function */ + decoder_destroy_func dec_destroy; + + /** Pointer to frame decoding function */ + decode_func dec; + + /** ioctl-like requests for encoder */ + encoder_ctl_func enc_ctl; + + /** ioctl-like requests for decoder */ + decoder_ctl_func dec_ctl; + +} SpeexMode; + +/** + * Returns a handle to a newly created Speex encoder state structure. For now, + * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes + * may be added. Note that for now if you have more than one channels to + * encode, you need one state per channel. + * + * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) + * @return A newly created encoder state or NULL if state allocation fails + */ +void *speex_encoder_init(const SpeexMode *mode); + +/** Frees all resources associated to an existing Speex encoder state. + * @param state Encoder state to be destroyed */ +void speex_encoder_destroy(void *state); + +/** Uses an existing encoder state to encode one frame of speech pointed to by + "in". The encoded bit-stream is saved in "bits". + @param state Encoder state + @param in Frame that will be encoded with a +-2^15 range. This data MAY be + overwritten by the encoder and should be considered uninitialised + after the call. + @param bits Bit-stream where the data will be written + @return 0 if frame needs not be transmitted (DTX only), 1 otherwise + */ +int speex_encode(void *state, float *in, SpeexBits *bits); + +/** Uses an existing encoder state to encode one frame of speech pointed to by + "in". The encoded bit-stream is saved in "bits". + @param state Encoder state + @param in Frame that will be encoded with a +-2^15 range + @param bits Bit-stream where the data will be written + @return 0 if frame needs not be transmitted (DTX only), 1 otherwise + */ +int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits); + +/** Used like the ioctl function to control the encoder parameters + * + * @param state Encoder state + * @param request ioctl-type request (one of the SPEEX_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_encoder_ctl(void *state, int request, void *ptr); + + +/** Returns a handle to a newly created decoder state structure. For now, + * the mode argument can be &nb_mode or &wb_mode . In the future, more modes + * may be added. Note that for now if you have more than one channels to + * decode, you need one state per channel. + * + * @param mode Speex mode (one of speex_nb_mode or speex_wb_mode) + * @return A newly created decoder state or NULL if state allocation fails + */ +void *speex_decoder_init(const SpeexMode *mode); + +/** Frees all resources associated to an existing decoder state. + * + * @param state State to be destroyed + */ +void speex_decoder_destroy(void *state); + +/** Uses an existing decoder state to decode one frame of speech from + * bit-stream bits. The output speech is saved written to out. + * + * @param state Decoder state + * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) + * @param out Where to write the decoded frame + * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) + */ +int speex_decode(void *state, SpeexBits *bits, float *out); + +/** Uses an existing decoder state to decode one frame of speech from + * bit-stream bits. The output speech is saved written to out. + * + * @param state Decoder state + * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) + * @param out Where to write the decoded frame + * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) + */ +int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out); + +/** Used like the ioctl function to control the encoder parameters + * + * @param state Decoder state + * @param request ioctl-type request (one of the SPEEX_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_decoder_ctl(void *state, int request, void *ptr); + + +/** Query function for mode information + * + * @param mode Speex mode + * @param request ioctl-type request (one of the SPEEX_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_mode_query(const SpeexMode *mode, int request, void *ptr); + +/** Functions for controlling the behavior of libspeex + * @param request ioctl-type request (one of the SPEEX_LIB_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_lib_ctl(int request, void *ptr); + +/** Default narrowband mode */ +extern const SpeexMode speex_nb_mode; + +/** Default wideband mode */ +extern const SpeexMode speex_wb_mode; + +/** Default "ultra-wideband" mode */ +extern const SpeexMode speex_uwb_mode; + +/** List of all modes available */ +extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES]; + +/** Obtain one of the modes available */ +const SpeexMode * speex_lib_get_mode (int mode); + +#ifndef WIN32 +/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */ +#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode)) +#endif + +#ifdef __cplusplus +} +#endif + +/** @}*/ +#endif diff --git a/engine/libs/speex/speex_bits.h b/engine/libs/speex/speex_bits.h new file mode 100644 index 000000000..a26fb4ce0 --- /dev/null +++ b/engine/libs/speex/speex_bits.h @@ -0,0 +1,174 @@ +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file speex_bits.h + @brief Handles bit packing/unpacking +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef BITS_H +#define BITS_H +/** @defgroup SpeexBits SpeexBits: Bit-stream manipulations + * This is the structure that holds the bit-stream when encoding or decoding + * with Speex. It allows some manipulations as well. + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Bit-packing data structure representing (part of) a bit-stream. */ +typedef struct SpeexBits { + char *chars; /**< "raw" data */ + int nbBits; /**< Total number of bits stored in the stream*/ + int charPtr; /**< Position of the byte "cursor" */ + int bitPtr; /**< Position of the bit "cursor" within the current char */ + int owner; /**< Does the struct "own" the "raw" buffer (member "chars") */ + int overflow;/**< Set to one if we try to read past the valid data */ + int buf_size;/**< Allocated size for buffer */ + int reserved1; /**< Reserved for future use */ + void *reserved2; /**< Reserved for future use */ +} SpeexBits; + +/** Initializes and allocates resources for a SpeexBits struct */ +void speex_bits_init(SpeexBits *bits); + +/** Initializes SpeexBits struct using a pre-allocated buffer*/ +void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size); + +/** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */ +void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size); + +/** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/ +void speex_bits_destroy(SpeexBits *bits); + +/** Resets bits to initial value (just after initialization, erasing content)*/ +void speex_bits_reset(SpeexBits *bits); + +/** Rewind the bit-stream to the beginning (ready for read) without erasing the content */ +void speex_bits_rewind(SpeexBits *bits); + +/** Initializes the bit-stream from the data in an area of memory */ +void speex_bits_read_from(SpeexBits *bits, char *bytes, int len); + +/** Append bytes to the bit-stream + * + * @param bits Bit-stream to operate on + * @param bytes pointer to the bytes what will be appended + * @param len Number of bytes of append + */ +void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len); + +/** Write the content of a bit-stream to an area of memory + * + * @param bits Bit-stream to operate on + * @param bytes Memory location where to write the bits + * @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer) + * @return Number of bytes written to the "bytes" buffer +*/ +int speex_bits_write(SpeexBits *bits, char *bytes, int max_len); + +/** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */ +int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len); + +/** Append bits to the bit-stream + * @param bits Bit-stream to operate on + * @param data Value to append as integer + * @param nbBits number of bits to consider in "data" + */ +void speex_bits_pack(SpeexBits *bits, int data, int nbBits); + +/** Interpret the next bits in the bit-stream as a signed integer + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to interpret + * @return A signed integer represented by the bits read + */ +int speex_bits_unpack_signed(SpeexBits *bits, int nbBits); + +/** Interpret the next bits in the bit-stream as an unsigned integer + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to interpret + * @return An unsigned integer represented by the bits read + */ +unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits); + +/** Returns the number of bytes in the bit-stream, including the last one even if it is not "full" + * + * @param bits Bit-stream to operate on + * @return Number of bytes in the stream + */ +int speex_bits_nbytes(SpeexBits *bits); + +/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to look for + * @return Value of the bits peeked, interpreted as unsigned + */ +unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits); + +/** Get the value of the next bit in the stream, without modifying the + * "cursor" position + * + * @param bits Bit-stream to operate on + * @return Value of the bit peeked (one bit only) + */ +int speex_bits_peek(SpeexBits *bits); + +/** Advances the position of the "bit cursor" in the stream + * + * @param bits Bit-stream to operate on + * @param n Number of bits to advance + */ +void speex_bits_advance(SpeexBits *bits, int n); + +/** Returns the number of bits remaining to be read in a stream + * + * @param bits Bit-stream to operate on + * @return Number of bits that can still be read from the stream + */ +int speex_bits_remaining(SpeexBits *bits); + +/** Insert a terminator so that the data can be sent as a packet while auto-detecting + * the number of frames in each packet + * + * @param bits Bit-stream to operate on + */ +void speex_bits_insert_terminator(SpeexBits *bits); + +#ifdef __cplusplus +} +#endif + +/* @} */ +#endif diff --git a/engine/libs/speex/speex_buffer.h b/engine/libs/speex/speex_buffer.h new file mode 100644 index 000000000..df56f5f18 --- /dev/null +++ b/engine/libs/speex/speex_buffer.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: speex_buffer.h + This is a very simple ring buffer implementation. It is not thread-safe + so you need to do your own locking. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SPEEX_BUFFER_H +#define SPEEX_BUFFER_H + +#include "speex/speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct SpeexBuffer_; +typedef struct SpeexBuffer_ SpeexBuffer; + +SpeexBuffer *speex_buffer_init(int size); + +void speex_buffer_destroy(SpeexBuffer *st); + +int speex_buffer_write(SpeexBuffer *st, void *data, int len); + +int speex_buffer_writezeros(SpeexBuffer *st, int len); + +int speex_buffer_read(SpeexBuffer *st, void *data, int len); + +int speex_buffer_get_available(SpeexBuffer *st); + +int speex_buffer_resize(SpeexBuffer *st, int len); + +#ifdef __cplusplus +} +#endif + +#endif + + + + diff --git a/engine/libs/speex/speex_callbacks.h b/engine/libs/speex/speex_callbacks.h new file mode 100644 index 000000000..6f450b3a3 --- /dev/null +++ b/engine/libs/speex/speex_callbacks.h @@ -0,0 +1,134 @@ +/* Copyright (C) 2002 Jean-Marc Valin*/ +/** + @file speex_callbacks.h + @brief Describes callback handling and in-band signalling +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SPEEX_CALLBACKS_H +#define SPEEX_CALLBACKS_H +/** @defgroup SpeexCallbacks Various definitions for Speex callbacks supported by the decoder. + * @{ + */ + +#include "speex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Total number of callbacks */ +#define SPEEX_MAX_CALLBACKS 16 + +/* Describes all the in-band requests */ + +/*These are 1-bit requests*/ +/** Request for perceptual enhancement (1 for on, 0 for off) */ +#define SPEEX_INBAND_ENH_REQUEST 0 +/** Reserved */ +#define SPEEX_INBAND_RESERVED1 1 + +/*These are 4-bit requests*/ +/** Request for a mode change */ +#define SPEEX_INBAND_MODE_REQUEST 2 +/** Request for a low mode change */ +#define SPEEX_INBAND_LOW_MODE_REQUEST 3 +/** Request for a high mode change */ +#define SPEEX_INBAND_HIGH_MODE_REQUEST 4 +/** Request for VBR (1 on, 0 off) */ +#define SPEEX_INBAND_VBR_QUALITY_REQUEST 5 +/** Request to be sent acknowledge */ +#define SPEEX_INBAND_ACKNOWLEDGE_REQUEST 6 +/** Request for VBR (1 for on, 0 for off) */ +#define SPEEX_INBAND_VBR_REQUEST 7 + +/*These are 8-bit requests*/ +/** Send a character in-band */ +#define SPEEX_INBAND_CHAR 8 +/** Intensity stereo information */ +#define SPEEX_INBAND_STEREO 9 + +/*These are 16-bit requests*/ +/** Transmit max bit-rate allowed */ +#define SPEEX_INBAND_MAX_BITRATE 10 + +/*These are 32-bit requests*/ +/** Acknowledge packet reception */ +#define SPEEX_INBAND_ACKNOWLEDGE 12 + +/** Callback function type */ +typedef int (*speex_callback_func)(SpeexBits *bits, void *state, void *data); + +/** Callback information */ +typedef struct SpeexCallback { + int callback_id; /**< ID associated to the callback */ + speex_callback_func func; /**< Callback handler function */ + void *data; /**< Data that will be sent to the handler */ + void *reserved1; /**< Reserved for future use */ + int reserved2; /**< Reserved for future use */ +} SpeexCallback; + +/** Handle in-band request */ +int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state); + +/** Standard handler for mode request (change mode, no questions asked) */ +int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for high mode request (change high mode, no questions asked) */ +int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for in-band characters (write to stderr) */ +int speex_std_char_handler(SpeexBits *bits, void *state, void *data); + +/** Default handler for user-defined requests: in this case, just ignore */ +int speex_default_user_handler(SpeexBits *bits, void *state, void *data); + + + +/** Standard handler for low mode request (change low mode, no questions asked) */ +int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for VBR request (Set VBR, no questions asked) */ +int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for enhancer request (Turn enhancer on/off, no questions asked) */ +int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for VBR quality request (Set VBR quality, no questions asked) */ +int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data); + + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif diff --git a/engine/libs/speex/speex_echo.h b/engine/libs/speex/speex_echo.h new file mode 100644 index 000000000..77a78468e --- /dev/null +++ b/engine/libs/speex/speex_echo.h @@ -0,0 +1,123 @@ +/* Copyright (C) Jean-Marc Valin */ +/** + @file speex_echo.h + @brief Echo cancellation +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SPEEX_ECHO_H +#define SPEEX_ECHO_H +/** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller + * This is the acoustic echo canceller module. + * @{ + */ +#include "speex/speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Obtain frame size used by the AEC */ +#define SPEEX_ECHO_GET_FRAME_SIZE 3 + +/** Set sampling rate */ +#define SPEEX_ECHO_SET_SAMPLING_RATE 24 +/** Get sampling rate */ +#define SPEEX_ECHO_GET_SAMPLING_RATE 25 + +/** Internal echo canceller state. Should never be accessed directly. */ +struct SpeexEchoState_; + +/** @class SpeexEchoState + * This holds the state of the echo canceller. You need one per channel. +*/ + +/** Internal echo canceller state. Should never be accessed directly. */ +typedef struct SpeexEchoState_ SpeexEchoState; + +/** Creates a new echo canceller state + * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) + * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) + * @return Newly-created echo canceller state + */ +SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length); + +/** Destroys an echo canceller state + * @param st Echo canceller state +*/ +void speex_echo_state_destroy(SpeexEchoState *st); + +/** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added + * to playback in this form) + * + * @param st Echo canceller state + * @param rec Signal from the microphone (near end + far end echo) + * @param play Signal played to the speaker (received from far end) + * @param out Returns near-end signal with echo removed + */ +void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); + +/** Performs echo cancellation a frame (deprecated) */ +void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out, spx_int32_t *Yout); + +/** Perform echo cancellation using internal playback buffer, which is delayed by two frames + * to account for the delay introduced by most soundcards (but it could be off!) + * @param st Echo canceller state + * @param rec Signal from the microphone (near end + far end echo) + * @param out Returns near-end signal with echo removed +*/ +void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out); + +/** Let the echo canceller know that a frame was just queued to the soundcard + * @param st Echo canceller state + * @param play Signal played to the speaker (received from far end) +*/ +void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play); + +/** Reset the echo canceller to its original state + * @param st Echo canceller state + */ +void speex_echo_state_reset(SpeexEchoState *st); + +/** Used like the ioctl function to control the echo canceller parameters + * + * @param st Echo canceller state + * @param request ioctl-type request (one of the SPEEX_ECHO_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown + */ +int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr); + +#ifdef __cplusplus +} +#endif + + +/** @}*/ +#endif diff --git a/engine/libs/speex/speex_header.h b/engine/libs/speex/speex_header.h new file mode 100644 index 000000000..f85b2496a --- /dev/null +++ b/engine/libs/speex/speex_header.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file speex_header.h + @brief Describes the Speex header +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#ifndef SPEEX_HEADER_H +#define SPEEX_HEADER_H +/** @defgroup SpeexHeader SpeexHeader: Makes it easy to write/parse an Ogg/Speex header + * This is the Speex header for the Ogg encapsulation. You don't need that if you just use RTP. + * @{ + */ + +#include "speex/speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct SpeexMode; + +/** Length of the Speex header identifier */ +#define SPEEX_HEADER_STRING_LENGTH 8 + +/** Maximum number of characters for encoding the Speex version number in the header */ +#define SPEEX_HEADER_VERSION_LENGTH 20 + +/** Speex header info for file-based formats */ +typedef struct SpeexHeader { + char speex_string[SPEEX_HEADER_STRING_LENGTH]; /**< Identifies a Speex bit-stream, always set to "Speex " */ + char speex_version[SPEEX_HEADER_VERSION_LENGTH]; /**< Speex version */ + spx_int32_t speex_version_id; /**< Version for Speex (for checking compatibility) */ + spx_int32_t header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + spx_int32_t rate; /**< Sampling rate used */ + spx_int32_t mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + spx_int32_t mode_bitstream_version; /**< Version ID of the bit-stream */ + spx_int32_t nb_channels; /**< Number of channels encoded */ + spx_int32_t bitrate; /**< Bit-rate used */ + spx_int32_t frame_size; /**< Size of frames */ + spx_int32_t vbr; /**< 1 for a VBR encoding, 0 otherwise */ + spx_int32_t frames_per_packet; /**< Number of frames stored per Ogg packet */ + spx_int32_t extra_headers; /**< Number of additional headers after the comments */ + spx_int32_t reserved1; /**< Reserved for future use, must be zero */ + spx_int32_t reserved2; /**< Reserved for future use, must be zero */ +} SpeexHeader; + +/** Initializes a SpeexHeader using basic information */ +void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const struct SpeexMode *m); + +/** Creates the header packet from the header itself (mostly involves endianness conversion) */ +char *speex_header_to_packet(SpeexHeader *header, int *size); + +/** Creates a SpeexHeader from a packet */ +SpeexHeader *speex_packet_to_header(char *packet, int size); + +/** Frees the memory allocated by either speex_header_to_packet() or speex_packet_to_header() */ +void speex_header_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif diff --git a/engine/libs/speex/speex_jitter.h b/engine/libs/speex/speex_jitter.h new file mode 100644 index 000000000..d68674b13 --- /dev/null +++ b/engine/libs/speex/speex_jitter.h @@ -0,0 +1,197 @@ +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file speex_jitter.h + @brief Adaptive jitter buffer for Speex +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SPEEX_JITTER_H +#define SPEEX_JITTER_H +/** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer + * This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size + * to maintain good quality and low latency. + * @{ + */ + +#include "speex/speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic adaptive jitter buffer state */ +struct JitterBuffer_; + +/** Generic adaptive jitter buffer state */ +typedef struct JitterBuffer_ JitterBuffer; + +/** Definition of an incoming packet */ +typedef struct _JitterBufferPacket JitterBufferPacket; + +/** Definition of an incoming packet */ +struct _JitterBufferPacket { + char *data; /**< Data bytes contained in the packet */ + spx_uint32_t len; /**< Length of the packet in bytes */ + spx_uint32_t timestamp; /**< Timestamp for the packet */ + spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */ + spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */ + spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */ +}; + +/** Packet has been retrieved */ +#define JITTER_BUFFER_OK 0 +/** Packet is lost or is late */ +#define JITTER_BUFFER_MISSING 1 +/** A "fake" packet is meant to be inserted here to increase buffering */ +#define JITTER_BUFFER_INSERTION 2 +/** There was an error in the jitter buffer */ +#define JITTER_BUFFER_INTERNAL_ERROR -1 +/** Invalid argument */ +#define JITTER_BUFFER_BAD_ARGUMENT -2 + + +/** Set minimum amount of extra buffering required (margin) */ +#define JITTER_BUFFER_SET_MARGIN 0 +/** Get minimum amount of extra buffering required (margin) */ +#define JITTER_BUFFER_GET_MARGIN 1 +/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */ + +/** Get the amount of available packets currently buffered */ +#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3 +/** Included because of an early misspelling (will remove in next release) */ +#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3 + +/** Assign a function to destroy unused packet. When setting that, the jitter + buffer no longer copies packet data. */ +#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4 +/** */ +#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5 + +/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */ +#define JITTER_BUFFER_SET_DELAY_STEP 6 +/** */ +#define JITTER_BUFFER_GET_DELAY_STEP 7 + +/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */ +#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8 +#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9 + +/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss + should be half of that or less. */ +#define JITTER_BUFFER_SET_MAX_LATE_RATE 10 +#define JITTER_BUFFER_GET_MAX_LATE_RATE 11 + +/** Equivalent cost of one percent late packet in timestamp units */ +#define JITTER_BUFFER_SET_LATE_COST 12 +#define JITTER_BUFFER_GET_LATE_COST 13 + + +/** Initialises jitter buffer + * + * @param step_size Starting value for the size of concleanment packets and delay + adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP + and JITTER_BUFFER_GET_CONCEALMENT_SIZE. + * @return Newly created jitter buffer state + */ +JitterBuffer *jitter_buffer_init(int step_size); + +/** Restores jitter buffer to its original state + * + * @param jitter Jitter buffer state + */ +void jitter_buffer_reset(JitterBuffer *jitter); + +/** Destroys jitter buffer + * + * @param jitter Jitter buffer state + */ +void jitter_buffer_destroy(JitterBuffer *jitter); + +/** Put one packet into the jitter buffer + * + * @param jitter Jitter buffer state + * @param packet Incoming packet +*/ +void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet); + +/** Get one packet from the jitter buffer + * + * @param jitter Jitter buffer state + * @param packet Returned packet + * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee) + * @param current_timestamp Timestamp for the returned packet +*/ +int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset); + +/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp. + * This is mainly useful for media where a single "frame" can be split into several packets. + * + * @param jitter Jitter buffer state + * @param packet Returned packet + */ +int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet); + +/** Get pointer timestamp of jitter buffer + * + * @param jitter Jitter buffer state +*/ +int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter); + +/** Advance by one tick + * + * @param jitter Jitter buffer state +*/ +void jitter_buffer_tick(JitterBuffer *jitter); + +/** Telling the jitter buffer about the remaining data in the application buffer + * @param jitter Jitter buffer state + * @param rem Amount of data buffered by the application (timestamp units) + */ +void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem); + +/** Used like the ioctl function to control the jitter buffer parameters + * + * @param jitter Jitter buffer state + * @param request ioctl-type request (one of the JITTER_BUFFER_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown +*/ +int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr); + +int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/engine/libs/speex/speex_preprocess.h b/engine/libs/speex/speex_preprocess.h new file mode 100644 index 000000000..a0d3aa3dc --- /dev/null +++ b/engine/libs/speex/speex_preprocess.h @@ -0,0 +1,190 @@ +/* Copyright (C) 2003 Epic Games + Written by Jean-Marc Valin */ +/** + * @file speex_preprocess.h + * @brief Speex preprocessor. The preprocess can do noise suppression, + * residual echo suppression (after using the echo canceller), automatic + * gain control (AGC) and voice activity detection (VAD). +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SPEEX_PREPROCESS_H +#define SPEEX_PREPROCESS_H +/** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor + * This is the Speex preprocessor. The preprocess can do noise suppression, + * residual echo suppression (after using the echo canceller), automatic + * gain control (AGC) and voice activity detection (VAD). + * @{ + */ + +#include "speex/speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** State of the preprocessor (one per channel). Should never be accessed directly. */ +struct SpeexPreprocessState_; + +/** State of the preprocessor (one per channel). Should never be accessed directly. */ +typedef struct SpeexPreprocessState_ SpeexPreprocessState; + + +/** Creates a new preprocessing state. You MUST create one state per channel processed. + * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms). Must be + * the same value as that used for the echo canceller for residual echo cancellation to work. + * @param sampling_rate Sampling rate used for the input. + * @return Newly created preprocessor state +*/ +SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate); + +/** Destroys a preprocessor state + * @param st Preprocessor state to destroy +*/ +void speex_preprocess_state_destroy(SpeexPreprocessState *st); + +/** Preprocess a frame + * @param st Preprocessor state + * @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init(). + * @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on. +*/ +int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x); + +/** Preprocess a frame (deprecated, use speex_preprocess_run() instead)*/ +int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo); + +/** Update preprocessor state, but do not compute the output + * @param st Preprocessor state + * @param x Audio sample vector (in only). Must be same size as specified in speex_preprocess_state_init(). +*/ +void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x); + +/** Used like the ioctl function to control the preprocessor parameters + * @param st Preprocessor state + * @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown +*/ +int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr); + + + +/** Set preprocessor denoiser state */ +#define SPEEX_PREPROCESS_SET_DENOISE 0 +/** Get preprocessor denoiser state */ +#define SPEEX_PREPROCESS_GET_DENOISE 1 + +/** Set preprocessor Automatic Gain Control state */ +#define SPEEX_PREPROCESS_SET_AGC 2 +/** Get preprocessor Automatic Gain Control state */ +#define SPEEX_PREPROCESS_GET_AGC 3 + +/** Set preprocessor Voice Activity Detection state */ +#define SPEEX_PREPROCESS_SET_VAD 4 +/** Get preprocessor Voice Activity Detection state */ +#define SPEEX_PREPROCESS_GET_VAD 5 + +/** Set preprocessor Automatic Gain Control level */ +#define SPEEX_PREPROCESS_SET_AGC_LEVEL 6 +/** Get preprocessor Automatic Gain Control level */ +#define SPEEX_PREPROCESS_GET_AGC_LEVEL 7 + +/** Set preprocessor dereverb state */ +#define SPEEX_PREPROCESS_SET_DEREVERB 8 +/** Get preprocessor dereverb state */ +#define SPEEX_PREPROCESS_GET_DEREVERB 9 + +/** Set preprocessor dereverb level */ +#define SPEEX_PREPROCESS_SET_DEREVERB_LEVEL 10 +/** Get preprocessor dereverb level */ +#define SPEEX_PREPROCESS_GET_DEREVERB_LEVEL 11 + +/** Set preprocessor dereverb decay */ +#define SPEEX_PREPROCESS_SET_DEREVERB_DECAY 12 +/** Get preprocessor dereverb decay */ +#define SPEEX_PREPROCESS_GET_DEREVERB_DECAY 13 + +/** Set probability required for the VAD to go from silence to voice */ +#define SPEEX_PREPROCESS_SET_PROB_START 14 +/** Get probability required for the VAD to go from silence to voice */ +#define SPEEX_PREPROCESS_GET_PROB_START 15 + +/** Set probability required for the VAD to stay in the voice state (integer percent) */ +#define SPEEX_PREPROCESS_SET_PROB_CONTINUE 16 +/** Get probability required for the VAD to stay in the voice state (integer percent) */ +#define SPEEX_PREPROCESS_GET_PROB_CONTINUE 17 + +/** Set maximum attenuation of the noise in dB (negative number) */ +#define SPEEX_PREPROCESS_SET_NOISE_SUPPRESS 18 +/** Get maximum attenuation of the noise in dB (negative number) */ +#define SPEEX_PREPROCESS_GET_NOISE_SUPPRESS 19 + +/** Set maximum attenuation of the residual echo in dB (negative number) */ +#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS 20 +/** Get maximum attenuation of the residual echo in dB (negative number) */ +#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS 21 + +/** Set maximum attenuation of the residual echo in dB when near end is active (negative number) */ +#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE 22 +/** Get maximum attenuation of the residual echo in dB when near end is active (negative number) */ +#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE 23 + +/** Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL for no residual echo suppression) */ +#define SPEEX_PREPROCESS_SET_ECHO_STATE 24 +/** Get the corresponding echo canceller state */ +#define SPEEX_PREPROCESS_GET_ECHO_STATE 25 + +/** Set maximal gain increase in dB/second (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_INCREMENT 26 + +/** Get maximal gain increase in dB/second (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_INCREMENT 27 + +/** Set maximal gain decrease in dB/second (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_DECREMENT 28 + +/** Get maximal gain decrease in dB/second (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_DECREMENT 29 + +/** Set maximal gain in dB (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 30 + +/** Get maximal gain in dB (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31 + +/* Can't set loudness */ +/** Get loudness */ +#define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33 + +#ifdef __cplusplus +} +#endif + +/** @}*/ +#endif diff --git a/engine/libs/speex/speex_resampler.h b/engine/libs/speex/speex_resampler.h new file mode 100644 index 000000000..54eef8d7b --- /dev/null +++ b/engine/libs/speex/speex_resampler.h @@ -0,0 +1,340 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: speex_resampler.h + Resampling code + + The design goals of this code are: + - Very fast algorithm + - Low memory requirement + - Good *perceptual* quality (and not best SNR) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef SPEEX_RESAMPLER_H +#define SPEEX_RESAMPLER_H + +#ifdef OUTSIDE_SPEEX + +/********* WARNING: MENTAL SANITY ENDS HERE *************/ + +/* If the resampler is defined outside of Speex, we change the symbol names so that + there won't be any clash if linking with Speex later on. */ + +/* #define RANDOM_PREFIX your software name here */ +#ifndef RANDOM_PREFIX +#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes" +#endif + +#define CAT_PREFIX2(a,b) a ## b +#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) + +#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) +#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) +#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) +#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float) +#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int) +#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float) +#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int) +#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate) +#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate) +#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac) +#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio) +#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality) +#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) +#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) +#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) +#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) +#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) +#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency) +#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency) +#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) +#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) +#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) + +#define spx_int16_t short +#define spx_int32_t int +#define spx_uint16_t unsigned short +#define spx_uint32_t unsigned int + +#else /* OUTSIDE_SPEEX */ + +#include "speex/speex_types.h" + +#endif /* OUTSIDE_SPEEX */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPEEX_RESAMPLER_QUALITY_MAX 10 +#define SPEEX_RESAMPLER_QUALITY_MIN 0 +#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 +#define SPEEX_RESAMPLER_QUALITY_VOIP 3 +#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 + +enum { + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + + RESAMPLER_ERR_MAX_ERROR +}; + +struct SpeexResamplerState_; +typedef struct SpeexResamplerState_ SpeexResamplerState; + +/** Create a new resampler with integer input and output rates. + * @param nb_channels Number of channels to be processed + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Create a new resampler with fractional input/output rates. The sampling + * rate ratio is an arbitrary rational number with both the numerator and + * denominator being 32-bit integers. + * @param nb_channels Number of channels to be processed + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Destroy a resampler state. + * @param st Resampler state + */ +void speex_resampler_destroy(SpeexResamplerState *st); + +/** Resample a float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the + * number of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_float(SpeexResamplerState *st, + spx_uint32_t channel_index, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); + +/** Resample an int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_int(SpeexResamplerState *st, + spx_uint32_t channel_index, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Resample an interleaved float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); + +/** Resample an interleaved int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Set (change) the input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + */ +int speex_resampler_set_rate(SpeexResamplerState *st, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz) copied. + * @param out_rate Output sampling rate (integer number of Hz) copied. + */ +void speex_resampler_get_rate(SpeexResamplerState *st, + spx_uint32_t *in_rate, + spx_uint32_t *out_rate); + +/** Set (change) the input/output sampling rates and resampling ratio + * (fractional values in Hz supported). + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + */ +int speex_resampler_set_rate_frac(SpeexResamplerState *st, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current resampling ratio. This will be reduced to the least + * common denominator. + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio copied + * @param ratio_den Denominator of the sampling rate ratio copied + */ +void speex_resampler_get_ratio(SpeexResamplerState *st, + spx_uint32_t *ratio_num, + spx_uint32_t *ratio_den); + +/** Set (change) the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +int speex_resampler_set_quality(SpeexResamplerState *st, + int quality); + +/** Get the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +void speex_resampler_get_quality(SpeexResamplerState *st, + int *quality); + +/** Set (change) the input stride. + * @param st Resampler state + * @param stride Input stride + */ +void speex_resampler_set_input_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the input stride. + * @param st Resampler state + * @param stride Input stride copied + */ +void speex_resampler_get_input_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Set (change) the output stride. + * @param st Resampler state + * @param stride Output stride + */ +void speex_resampler_set_output_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the output stride. + * @param st Resampler state copied + * @param stride Output stride + */ +void speex_resampler_get_output_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Get the latency in input samples introduced by the resampler. + * @param st Resampler state + */ +int speex_resampler_get_input_latency(SpeexResamplerState *st); + +/** Get the latency in output samples introduced by the resampler. + * @param st Resampler state + */ +int speex_resampler_get_output_latency(SpeexResamplerState *st); + +/** Make sure that the first samples to go out of the resamplers don't have + * leading zeros. This is only useful before starting to use a newly created + * resampler. It is recommended to use that when resampling an audio file, as + * it will generate a file with the same length. For real-time processing, + * it is probably easier not to use this call (so that the output duration + * is the same for the first frame). + * @param st Resampler state + */ +int speex_resampler_skip_zeros(SpeexResamplerState *st); + +/** Reset a resampler so a new (unrelated) stream can be processed. + * @param st Resampler state + */ +int speex_resampler_reset_mem(SpeexResamplerState *st); + +/** Returns the English meaning for an error code + * @param err Error code + * @return English string + */ +const char *speex_resampler_strerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/engine/libs/speex/speex_stereo.h b/engine/libs/speex/speex_stereo.h new file mode 100644 index 000000000..a259713b8 --- /dev/null +++ b/engine/libs/speex/speex_stereo.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2002 Jean-Marc Valin*/ +/** + @file speex_stereo.h + @brief Describes the handling for intensity stereo +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef STEREO_H +#define STEREO_H +/** @defgroup SpeexStereoState SpeexStereoState: Handling Speex stereo files + * This describes the Speex intensity stereo encoding/decoding + * @{ + */ + +#include "speex/speex_types.h" +#include "speex/speex_bits.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** If you access any of these fields directly, I'll personally come and bite you */ +typedef struct SpeexStereoState { + float balance; /**< Left/right balance info */ + float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ + float smooth_left; /**< Smoothed left channel gain */ + float smooth_right; /**< Smoothed right channel gain */ + float reserved1; /**< Reserved for future use */ + float reserved2; /**< Reserved for future use */ +} SpeexStereoState; + +/** Deprecated. Use speex_stereo_state_init() instead. */ +#define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} + +/** Initialise/create a stereo stereo state */ +SpeexStereoState *speex_stereo_state_init(); + +/** Reset/re-initialise an already allocated stereo state */ +void speex_stereo_state_reset(SpeexStereoState *stereo); + +/** Destroy a stereo stereo state */ +void speex_stereo_state_destroy(SpeexStereoState *stereo); + +/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ +void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); + +/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ +void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits); + +/** Transforms a mono frame into a stereo frame using intensity stereo info */ +void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo); + +/** Transforms a mono frame into a stereo frame using intensity stereo info */ +void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo); + +/** Callback handler for intensity stereo info */ +int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif diff --git a/engine/libs/speex/speex_types.h b/engine/libs/speex/speex_types.h new file mode 100644 index 000000000..852fed801 --- /dev/null +++ b/engine/libs/speex/speex_types.h @@ -0,0 +1,126 @@ +/* speex_types.h taken from libogg */ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ + + ********************************************************************/ +/** + @file speex_types.h + @brief Speex types +*/ +#ifndef _SPEEX_TYPES_H +#define _SPEEX_TYPES_H + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t spx_int32_t; + typedef _G_uint32_t spx_uint32_t; + typedef _G_int16_t spx_int16_t; + typedef _G_uint16_t spx_uint16_t; +# elif defined(__MINGW32__) + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; +# elif defined(__MWERKS__) + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; +# else + /* MSVC/Borland */ + typedef __int32 spx_int32_t; + typedef unsigned __int32 spx_uint32_t; + typedef __int16 spx_int16_t; + typedef unsigned __int16 spx_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 spx_int16_t; + typedef UInt16 spx_uint16_t; + typedef SInt32 spx_int32_t; + typedef UInt32 spx_uint32_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short spx_int16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int spx_int32_t; + typedef unsigned spx_uint32_t; + typedef short spx_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef signed int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef long spx_int32_t; + typedef unsigned long spx_uint32_t; + +#elif defined(CONFIG_TI_C6X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#else + +# include + +#endif + +#endif /* _SPEEX_TYPES_H */ diff --git a/engine/server/botlib.h b/engine/server/botlib.h index 76ff4fa46..29b1f4e39 100644 --- a/engine/server/botlib.h +++ b/engine/server/botlib.h @@ -430,7 +430,7 @@ typedef struct botlib_export_s } botlib_export_t; //linking of bot library -botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import ); +botlib_export_t *QDECL GetBotLibAPI( int apiVersion, botlib_import_t *import ); /* Library variables: diff --git a/engine/server/server.h b/engine/server/server.h index 64d9072f8..5b1d64787 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -324,13 +324,6 @@ typedef struct //merge? } q3client_frame_t; #endif -#define MAXCACHEDSOUNDBUFFERS 8 -typedef struct { - int socket; - qboolean floodingbuffers; //not enough sound causes this. Sound is then only mixed when full. - qbyte *buffer[MAXCACHEDSOUNDBUFFERS]; -} svvoicechat_t; - #define MAX_BACK_BUFFERS 16 typedef struct client_s @@ -474,7 +467,9 @@ typedef struct client_s int lastsequence_acknoledged; - svvoicechat_t voicechat; + unsigned int voice_read; + unsigned char voice_mute[MAX_CLIENTS/8]; + qboolean voice_active; #ifdef SVCHAT svchat_t chat; @@ -1040,6 +1035,11 @@ int SV_PMTypeForClient (client_t *cl); void SV_UserInit (void); qboolean SV_TogglePause (client_t *cl); +#ifdef PEXT2_VOICECHAT +void SV_VoiceInitClient(client_t *client); +void SV_VoiceSendPacket(client_t *client, sizebuf_t *buf); +#endif + void SV_ClientThink (void); void SV_Begin_Core(client_t *split); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 4e92f1136..8e9e8fd44 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2376,6 +2376,10 @@ client_t *SVC_DirectConnect(void) SV_ClientPrintf(newcl, PRINT_CHAT, "%s\n", sv_motd[i].string); } +#ifdef PEXT2_VOICECHAT + SV_VoiceInitClient(newcl); +#endif + newcl->fteprotocolextensions &= ~PEXT_SPLITSCREEN; for (clients = 1; clients < numssclients; clients++) { @@ -3473,10 +3477,6 @@ void SV_MVDStream_Poll(void); return; } -#ifdef VOICECHAT - SVVC_Frame(sv_voicechat.value); -#endif - // check timeouts SV_CheckTimeouts (); @@ -3872,6 +3872,9 @@ void SV_InitLocal (void) #endif svs.fteprotocolextensions2 |= PEXT2_PRYDONCURSOR; +#ifdef PEXT2_VOICECHAT + svs.fteprotocolextensions2 |= PEXT2_VOICECHAT; +#endif // if (svs.protocolextensions) // Info_SetValueForStarKey (svs.info, "*"DISTRIBUTION"_ext", va("%x", svs.protocolextensions), MAX_SERVERINFO_STRING); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index b322ce921..f69478a48 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1724,6 +1724,9 @@ qboolean SV_SendClientDatagram (client_t *client) // possibly a nails update SV_WriteEntitiesToClient (client, &msg, false); } +#ifdef PEXT2_VOICECHAT + SV_VoiceSendPacket(client, &msg); +#endif } // copy the accumulated multicast datagram diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index d25f0b470..6329a9c55 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -2085,9 +2085,148 @@ void SV_NextUpload (void) host_client->uploadfn, p); } } - } +#ifdef VOICECHAT +#define VOICE_RING_SIZE 512 +struct +{ + struct voice_ring_s + { + unsigned int sender; + unsigned char receiver[MAX_CLIENTS/8]; + unsigned char seq; + unsigned int datalen; + unsigned char data[1024]; + } ring[VOICE_RING_SIZE]; + unsigned int write; +} voice; +void SV_VoiceReadPacket(void) +{ + unsigned int j, cln; + struct voice_ring_s *ring; + unsigned short bytes; + client_t *cl; + unsigned char seq = MSG_ReadByte(); + /*read the data from the client*/ + bytes = MSG_ReadShort(); + ring = &voice.ring[voice.write & (VOICE_RING_SIZE-1)]; + if (bytes > sizeof(ring->data) || host_client->ismuted) + { + MSG_ReadSkip(bytes); + return; + } + else + { + voice.write++; + MSG_ReadData(ring->data, bytes); + } + ring->datalen = bytes; + ring->sender = host_client - svs.clients; + ring->seq = seq; + + /*figure out which team members are meant to receive it*/ + for (j = 0; j < MAX_CLIENTS/8; j++) + ring->receiver[j] = 0; + for (j = 0, cl = svs.clients; j < sv.allocated_client_slots; j++, cl++) + { +// if (cl == host_client) +// continue; + + if (cl->state != cs_spawned && cl->state != cs_connected) + continue; + if (host_client->spectator && !sv_spectalk.ival) + if (!cl->spectator) + continue; + + if (teamplay.ival) + { + // the spectator team + if (host_client->spectator) + { + if (!cl->spectator) + continue; + } + else + { + if (strcmp(cl->team, host_client->team) || cl->spectator) + continue; // on different teams + } + } + + //make sure we don't send the say to the same client 20 times due to splitscreen + if (cl->controller) + cln = cl->controller - svs.clients; + else + cln = j; + + ring->receiver[cln>>3] |= 1<<(cln&3); + } +} +void SV_VoiceInitClient(client_t *client) +{ + client->voice_active = true; + client->voice_read = voice.write; + memset(client->voice_mute, 0, sizeof(client->voice_mute)); +} +void SV_VoiceSendPacket(client_t *client, sizebuf_t *buf) +{ + unsigned int clno = client - svs.clients; + qboolean send; + struct voice_ring_s *ring; + + if (!(client->fteprotocolextensions2 & PEXT2_VOICECHAT)) + return; + if (!client->voice_active || client->num_backbuf) + { + client->voice_read = voice.write; + return; + } + + while(client->voice_read < voice.write) + { + /*they might be too far behind*/ + if (client->voice_read+VOICE_RING_SIZE < voice.write) + client->voice_read = voice.write - VOICE_RING_SIZE; + + ring = &voice.ring[(client->voice_read) & (VOICE_RING_SIZE-1)]; + + /*figure out if it was for us*/ + if (ring->receiver[clno>>3] & (1<<(clno&3))) + send = true; + else + send = false; + + if (client->voice_mute[ring->sender>>3] & (1<<(ring->sender&3))) + send = false; + + /*additional ways to block it*/ + if (client->download) + send = false; + + client->voice_read++; + + if (send) + { + MSG_WriteByte(buf, svcfte_voicechat); + MSG_WriteByte(buf, ring->sender); + MSG_WriteByte(buf, ring->seq); + MSG_WriteShort(buf, ring->datalen); + SZ_Write(buf, ring->data, ring->datalen); + } + } +} + +void SV_Voice_MuteAll(void) +{ + host_client->voice_active = false; +} +void SV_Voice_UnmuteAll(void) +{ + host_client->voice_active = true; +} +#endif + //Use of this function is on name only. //Be aware that the maps directory should be restricted based on weather the file was from a pack file //this is to preserve copyright - please do not breach due to a bug. @@ -3616,7 +3755,7 @@ void SV_SetUpClientEdict (client_t *cl, edict_t *ent) ent->xv->maxspeed = cl->maxspeed = sv_maxspeed.value; ent->v->movetype = MOVETYPE_NOCLIP; - cl->old_frags = ent->v->frags = 0; + ent->v->frags = 0; cl->connection_started = realtime; } /* @@ -3706,6 +3845,7 @@ void Cmd_Join_f (void) PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); // send notification to all clients + host_client->old_frags = host_client->edict->v->frags; host_client->sendinfo = true; SV_LogPlayer(host_client, "joined"); @@ -3799,6 +3939,7 @@ void Cmd_Observe_f (void) sv_player->v->movetype = MOVETYPE_NOCLIP; // send notification to all clients + host_client->old_frags = host_client->edict->v->frags; host_client->sendinfo = true; SV_LogPlayer(host_client, "observing"); @@ -3963,6 +4104,11 @@ ucmd_t ucmds[] = {"demolist", SV_UserCmdMVDList_f}, {"demoinfo", SV_MVDInfo_f}, +#ifdef VOICECHAT + {"muteall", SV_Voice_MuteAll}, + {"unmuteall", SV_Voice_UnmuteAll}, +#endif + {NULL, NULL} }; @@ -5511,7 +5657,6 @@ SV_ExecuteClientMessage The current net_message is parsed for the given client =================== */ -void SV_ClientThink (void); void SV_ExecuteClientMessage (client_t *cl) { client_t *split; @@ -5850,7 +5995,11 @@ haveannothergo: case clc_upload: SV_NextUpload(); break; - +#ifdef PEXT2_VOICECHAT + case clc_voicechat: + SV_VoiceReadPacket(); + break; +#endif } } @@ -6325,7 +6474,7 @@ SV_UserFriction ================== */ -void SV_UserFriction (void) +static void SV_UserFriction (void) { extern cvar_t sv_stopspeed; float *vel; @@ -6370,7 +6519,7 @@ void SV_UserFriction (void) vel[2] = vel[2] * newspeed; } -void SV_Accelerate (void) +static void SV_Accelerate (void) { int i; float addspeed, accelspeed, currentspeed; @@ -6387,7 +6536,7 @@ void SV_Accelerate (void) velocity[i] += accelspeed*wishdir[i]; } -void SV_AirAccelerate (vec3_t wishveloc) +static void SV_AirAccelerate (vec3_t wishveloc) { int i; float addspeed, wishspd, accelspeed, currentspeed; @@ -6414,7 +6563,7 @@ SV_AirMove =================== */ -void SV_AirMove (void) +static void SV_AirMove (void) { int i; vec3_t wishvel; @@ -6471,7 +6620,7 @@ void SV_AirMove (void) } } -void SV_WaterMove (void) +static void SV_WaterMove (void) { int i; vec3_t wishvel; @@ -6548,7 +6697,7 @@ void SV_WaterMove (void) velocity[i] += accelspeed * wishvel[i]; } -void SV_WaterJump (void) +static void SV_WaterJump (void) { if (sv.time > sv_player->v->teleport_time || !sv_player->v->waterlevel) diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 3cff77728..94e80c814 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -8,6 +8,7 @@ float RadiusFromBounds (vec3_t mins, vec3_t maxs); #define USEBOTLIB +#define BOTLIB_STATIC #ifdef USEBOTLIB @@ -27,6 +28,9 @@ float RadiusFromBounds (vec3_t mins, vec3_t maxs); botlib_export_t *FTE_GetBotLibAPI(int apiVersion, botlib_import_t *import) { //a stub that will prevent botlib from loading. +#ifdef BOTLIB_STATIC + return GetBotLibAPI(apiVersion, import); +#else static void *botlib; static botlib_export_t *(QDECL *pGetBotLibAPI)(int apiVersion, botlib_import_t *import); @@ -40,6 +44,7 @@ botlib_export_t *FTE_GetBotLibAPI(int apiVersion, botlib_import_t *import) if (!botlib) return NULL; return pGetBotLibAPI(apiVersion, import); +#endif } botlib_export_t *botlib;