LAGonauta / MetaAudio

GoldSrc engine plugin for 3D sound
GNU General Public License v2.0
98 stars 14 forks source link

NPC mouth issue #35

Open BlackShadow opened 2 years ago

BlackShadow commented 2 years ago

NPC's doesn't move their mouth when high quality sound file used.

LAGonauta commented 2 years ago

Would it be possible to upload a sample for testing?

BlackShadow commented 2 years ago

There you go:

https://streamable.com/mn2gv2

If you don't use Half-Life's standard Mono WAV files, this happens

hzqst commented 2 years ago

First of all,

This is because vannila GoldSrc handles mouth movement in S_MixChannelsToPaintbuffer (basically where GoldSrc paint raw wave data into paintbuffer and finally transfer them into DirectSound output driver) and call SND_MoveMouth while voicing.

However MetaAudio never paints or mix sound channel by itself (it is all done by Alure software driver) so nothing goes into S_MixChannelsToPaintbuffer.

void S_MixChannelsToPaintbuffer(...){
//...
if (ch->entchannel == CHAN_STREAM || ch->entchannel == CHAN_VOICE)
                            SND_MoveMouth(ch, sc, count);
//...
}

And modify mouth controller for current entity according to the voice volume.

void SND_MoveMouth(channel_t *ch, sfxcache_t *sc, int count)
{
    int data;
    signed char *pdata;
    int i;
    int savg;
    int scount;
    cl_entity_t *pent;

    pdata = (signed char *)sc->data + ch->pos;
    i = 0;
    scount = cl_entities[ch->entnum].mouth.sndcount;
    savg = 0;
    pent = &cl_entities[ch->entnum];

    while (i < count && scount < CAVGSAMPLES)
    {
        data = pdata[i];
        savg += abs(data);

        i += 80 + ((byte)data & 0x1F);
        scount++;
    }

    pent->mouth.sndavg += savg;
    pent->mouth.sndcount = (byte)scount;

    if (pent->mouth.sndcount >= CAVGSAMPLES)
    {
        pent->mouth.mouthopen = pent->mouth.sndavg / CAVGSAMPLES;
        pent->mouth.sndavg = 0;
        pent->mouth.sndcount = 0;
    }
}

How to fix :

We can iterate every stream/voice channel in channel_manager and simulate the SND_MoveMouth with volume from Alure driver instead of stupid raw bytes calculation i += 80 + ((byte)data & 0x1F);