You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
4.4 KiB
217 lines
4.4 KiB
/* |
|
s_mouth.c - animate mouth |
|
Copyright (C) 2010 Uncle Mike |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
*/ |
|
|
|
#include "common.h" |
|
#include "sound.h" |
|
#include "client.h" |
|
#include "const.h" |
|
|
|
#define CAVGSAMPLES 10 |
|
|
|
void SND_InitMouth( int entnum, int entchannel ) |
|
{ |
|
if(( entchannel == CHAN_VOICE || entchannel == CHAN_STREAM ) && entnum > 0 ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
|
|
// init mouth movement vars |
|
clientEntity = CL_GetEntityByIndex( entnum ); |
|
|
|
if( clientEntity ) |
|
{ |
|
clientEntity->mouth.mouthopen = 0; |
|
clientEntity->mouth.sndcount = 0; |
|
clientEntity->mouth.sndavg = 0; |
|
} |
|
} |
|
} |
|
|
|
void SND_CloseMouth( channel_t *ch ) |
|
{ |
|
if( ch->entchannel == CHAN_VOICE || ch->entchannel == CHAN_STREAM ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
|
|
clientEntity = CL_GetEntityByIndex( ch->entnum ); |
|
|
|
if( clientEntity ) |
|
{ |
|
// shut mouth |
|
clientEntity->mouth.mouthopen = 0; |
|
} |
|
} |
|
} |
|
|
|
void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
signed char *pdata = NULL; |
|
mouth_t *pMouth = NULL; |
|
int scount, pos = 0; |
|
int savg, data; |
|
uint i; |
|
|
|
clientEntity = CL_GetEntityByIndex( ch->entnum ); |
|
if( !clientEntity ) return; |
|
|
|
pMouth = &clientEntity->mouth; |
|
|
|
if( ch->isSentence ) |
|
{ |
|
if( ch->currentWord ) |
|
pos = ch->currentWord->sample; |
|
} |
|
else pos = ch->pMixer.sample; |
|
|
|
count = S_GetOutputData( pSource, (void**)&pdata, pos, count, ch->use_loop ); |
|
if( pdata == NULL ) return; |
|
|
|
i = 0; |
|
scount = pMouth->sndcount; |
|
savg = 0; |
|
|
|
while( i < count && scount < CAVGSAMPLES ) |
|
{ |
|
data = pdata[i]; |
|
savg += abs( data ); |
|
|
|
i += 80 + ((byte)data & 0x1F); |
|
scount++; |
|
} |
|
|
|
pMouth->sndavg += savg; |
|
pMouth->sndcount = (byte)scount; |
|
|
|
if( pMouth->sndcount >= CAVGSAMPLES ) |
|
{ |
|
pMouth->mouthopen = pMouth->sndavg / CAVGSAMPLES; |
|
pMouth->sndavg = 0; |
|
pMouth->sndcount = 0; |
|
} |
|
} |
|
|
|
void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
short *pdata = NULL; |
|
mouth_t *pMouth = NULL; |
|
int savg, data; |
|
int scount, pos = 0; |
|
uint i; |
|
|
|
clientEntity = CL_GetEntityByIndex( ch->entnum ); |
|
if( !clientEntity ) return; |
|
|
|
pMouth = &clientEntity->mouth; |
|
|
|
if( ch->isSentence ) |
|
{ |
|
if( ch->currentWord ) |
|
pos = ch->currentWord->sample; |
|
} |
|
else pos = ch->pMixer.sample; |
|
|
|
count = S_GetOutputData( pSource, (void**)&pdata, pos, count, ch->use_loop ); |
|
if( pdata == NULL ) return; |
|
|
|
i = 0; |
|
scount = pMouth->sndcount; |
|
savg = 0; |
|
|
|
while( i < count && scount < CAVGSAMPLES ) |
|
{ |
|
data = pdata[i]; |
|
data = (bound( -32767, data, 0x7ffe ) >> 8); |
|
savg += abs( data ); |
|
|
|
i += 80 + ((byte)data & 0x1F); |
|
scount++; |
|
} |
|
|
|
pMouth->sndavg += savg; |
|
pMouth->sndcount = (byte)scount; |
|
|
|
if( pMouth->sndcount >= CAVGSAMPLES ) |
|
{ |
|
pMouth->mouthopen = pMouth->sndavg / CAVGSAMPLES; |
|
pMouth->sndavg = 0; |
|
pMouth->sndcount = 0; |
|
} |
|
} |
|
|
|
void SND_ForceInitMouth( int entnum ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
|
|
clientEntity = CL_GetEntityByIndex( entnum ); |
|
|
|
if ( clientEntity ) |
|
{ |
|
clientEntity->mouth.mouthopen = 0; |
|
clientEntity->mouth.sndavg = 0; |
|
clientEntity->mouth.sndcount = 0; |
|
} |
|
} |
|
|
|
void SND_ForceCloseMouth( int entnum ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
|
|
clientEntity = CL_GetEntityByIndex( entnum ); |
|
|
|
if ( clientEntity ) |
|
clientEntity->mouth.mouthopen = 0; |
|
} |
|
|
|
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count ) |
|
{ |
|
cl_entity_t *clientEntity; |
|
mouth_t *pMouth = NULL; |
|
int savg, data; |
|
int scount = 0; |
|
uint i; |
|
|
|
clientEntity = CL_GetEntityByIndex( ch->entnum ); |
|
if( !clientEntity ) return; |
|
|
|
pMouth = &clientEntity->mouth; |
|
|
|
if( pData == NULL ) |
|
return; |
|
|
|
i = 0; |
|
scount = pMouth->sndcount; |
|
savg = 0; |
|
|
|
while ( i < count && scount < CAVGSAMPLES ) |
|
{ |
|
data = pData[i].left; // mono sound anyway |
|
data = ( bound( -32767, data, 0x7ffe ) >> 8 ); |
|
savg += abs( data ); |
|
|
|
i += 80 + ( (byte)data & 0x1F ); |
|
scount++; |
|
} |
|
|
|
pMouth->sndavg += savg; |
|
pMouth->sndcount = (byte)scount; |
|
|
|
if ( pMouth->sndcount >= CAVGSAMPLES ) |
|
{ |
|
pMouth->mouthopen = pMouth->sndavg / CAVGSAMPLES; |
|
pMouth->sndavg = 0; |
|
pMouth->sndcount = 0; |
|
} |
|
} |