Пример #1
0
void aluInitMixer(void)
{
    ALuint i;
    for(i = 0;i < FRACTIONONE;i++)
    {
        ALfloat mu = (ALfloat)i / FRACTIONONE;
        ResampleCoeffs[i][0] = lanc2(mu - -1.0f);
        ResampleCoeffs[i][1] = lanc2(mu -  0.0f);
        ResampleCoeffs[i][2] = lanc2(mu -  1.0f);
        ResampleCoeffs[i][3] = lanc2(mu -  2.0f);
    }

    MixHrtfSamples = SelectHrtfMixer();
    MixSamples = SelectMixer();
    ResampleSamples = SelectResampler(DefaultResampler);
}
Пример #2
0
ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
{
    static const ALfloat angles_Mono[1] = { 0.0f };
    static const ALfloat angles_Stereo[2] = { -30.0f, 30.0f };
    static const ALfloat angles_Rear[2] = { -150.0f, 150.0f };
    static const ALfloat angles_Quad[4] = { -45.0f, 45.0f, -135.0f, 135.0f };
    static const ALfloat angles_X51[6] = { -30.0f, 30.0f, 0.0f, 0.0f,
                                           -110.0f, 110.0f };
    static const ALfloat angles_X61[7] = { -30.0f, 30.0f, 0.0f, 0.0f,
                                           180.0f, -90.0f, 90.0f };
    static const ALfloat angles_X71[8] = { -30.0f, 30.0f, 0.0f, 0.0f,
                                           -110.0f, 110.0f, -90.0f, 90.0f };

    static const enum Channel chans_Mono[1] = { FRONT_CENTER };
    static const enum Channel chans_Stereo[2] = { FRONT_LEFT, FRONT_RIGHT };
    static const enum Channel chans_Rear[2] = { BACK_LEFT, BACK_RIGHT };
    static const enum Channel chans_Quad[4] = { FRONT_LEFT, FRONT_RIGHT,
                                                BACK_LEFT, BACK_RIGHT };
    static const enum Channel chans_X51[6] = { FRONT_LEFT, FRONT_RIGHT,
                                               FRONT_CENTER, LFE,
                                               BACK_LEFT, BACK_RIGHT };
    static const enum Channel chans_X61[7] = { FRONT_LEFT, FRONT_RIGHT,
                                               FRONT_CENTER, LFE, BACK_CENTER,
                                               SIDE_LEFT, SIDE_RIGHT };
    static const enum Channel chans_X71[8] = { FRONT_LEFT, FRONT_RIGHT,
                                               FRONT_CENTER, LFE,
                                               BACK_LEFT, BACK_RIGHT,
                                               SIDE_LEFT, SIDE_RIGHT };

    ALCdevice *Device = ALContext->Device;
    ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
    ALbufferlistitem *BufferListItem;
    enum DevFmtChannels DevChans;
    enum FmtChannels Channels;
    ALfloat (*SrcMatrix)[MAXCHANNELS];
    ALfloat DryGain, DryGainHF;
    ALfloat WetGain[MAX_SENDS];
    ALfloat WetGainHF[MAX_SENDS];
    ALint NumSends, Frequency;
    const ALfloat *SpeakerGain;
    const ALfloat *angles = NULL;
    const enum Channel *chans = NULL;
    enum Resampler Resampler;
    ALint num_channels = 0;
    ALboolean VirtualChannels;
    ALfloat Pitch;
    ALfloat cw;
    ALuint pos;
    ALint i, c;

    /* Get device properties */
    DevChans  = ALContext->Device->FmtChans;
    NumSends  = ALContext->Device->NumAuxSends;
    Frequency = ALContext->Device->Frequency;

    /* Get listener properties */
    ListenerGain = ALContext->Listener.Gain;

    /* Get source properties */
    SourceVolume    = ALSource->flGain;
    MinVolume       = ALSource->flMinGain;
    MaxVolume       = ALSource->flMaxGain;
    Pitch           = ALSource->flPitch;
    Resampler       = ALSource->Resampler;
    VirtualChannels = ALSource->VirtualChannels;

    /* Calculate the stepping value */
    Channels = FmtMono;
    BufferListItem = ALSource->queue;
    while(BufferListItem != NULL)
    {
        ALbuffer *ALBuffer;
        if((ALBuffer=BufferListItem->buffer) != NULL)
        {
            ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels /
                                              ALSource->SampleSize;
            maxstep -= ResamplerPadding[Resampler] +
                       ResamplerPrePadding[Resampler] + 1;
            maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);

            Pitch = Pitch * ALBuffer->Frequency / Frequency;
            if(Pitch > (ALfloat)maxstep)
                ALSource->Params.Step = maxstep<<FRACTIONBITS;
            else
            {
                ALSource->Params.Step = Pitch*FRACTIONONE;
                if(ALSource->Params.Step == 0)
                    ALSource->Params.Step = 1;
            }

            Channels = ALBuffer->FmtChannels;

            if(ALSource->VirtualChannels && (Device->Flags&DEVICE_USE_HRTF))
                ALSource->Params.DoMix = SelectHrtfMixer(ALBuffer,
                       (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER :
                                                              Resampler);
            else
                ALSource->Params.DoMix = SelectMixer(ALBuffer,
                       (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER :
                                                              Resampler);
            break;
        }
        BufferListItem = BufferListItem->next;
    }
Пример #3
0
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
{
    ALuint SamplesToDo;
    ALeffectslot **slot, **slot_end;
    ALvoice *voice, *voice_end;
    ALCcontext *ctx;
    FPUCtl oldMode;
    ALuint i, c;

    SetMixerFPUMode(&oldMode);

    while(size > 0)
    {
        ALfloat (*OutBuffer)[BUFFERSIZE];
        ALuint OutChannels;

        IncrementRef(&device->MixCount);

        OutBuffer = device->DryBuffer;
        OutChannels = device->NumChannels;

        SamplesToDo = minu(size, BUFFERSIZE);
        for(c = 0;c < OutChannels;c++)
            memset(OutBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
        if(device->Hrtf)
        {
            /* Set OutBuffer/OutChannels to correspond to the actual output
             * with HRTF. Make sure to clear them too. */
            OutBuffer += OutChannels;
            OutChannels = 2;
            for(c = 0;c < OutChannels;c++)
                memset(OutBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
        }

        V0(device->Backend,lock)();
        V(device->Synth,process)(SamplesToDo, OutBuffer, OutChannels);

        ctx = ATOMIC_LOAD(&device->ContextList);
        while(ctx)
        {
            ALenum DeferUpdates = ctx->DeferUpdates;
            ALenum UpdateSources = AL_FALSE;

            if(!DeferUpdates)
                UpdateSources = ATOMIC_EXCHANGE(ALenum, &ctx->UpdateSources, AL_FALSE);

            if(UpdateSources)
                CalcListenerParams(ctx->Listener);

            /* source processing */
            voice = ctx->Voices;
            voice_end = voice + ctx->VoiceCount;
            while(voice != voice_end)
            {
                ALsource *source = voice->Source;
                if(!source) goto next;

                if(source->state != AL_PLAYING && source->state != AL_PAUSED)
                {
                    voice->Source = NULL;
                    goto next;
                }

                if(!DeferUpdates && (ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) ||
                                     UpdateSources))
                    voice->Update(voice, source, ctx);

                if(source->state != AL_PAUSED)
                    MixSource(voice, source, device, SamplesToDo);
            next:
                voice++;
            }

            /* effect slot processing */
            slot = VECTOR_ITER_BEGIN(ctx->ActiveAuxSlots);
            slot_end = VECTOR_ITER_END(ctx->ActiveAuxSlots);
            while(slot != slot_end)
            {
                if(!DeferUpdates && ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
                    V((*slot)->EffectState,update)(device, *slot);

                V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0],
                                                device->DryBuffer, device->NumChannels);

                for(i = 0;i < SamplesToDo;i++)
                    (*slot)->WetBuffer[0][i] = 0.0f;

                slot++;
            }

            ctx = ctx->next;
        }

        slot = &device->DefaultSlot;
        if(*slot != NULL)
        {
            if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
                V((*slot)->EffectState,update)(device, *slot);

            V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0],
                                            device->DryBuffer, device->NumChannels);

            for(i = 0;i < SamplesToDo;i++)
                (*slot)->WetBuffer[0][i] = 0.0f;
        }

        /* Increment the clock time. Every second's worth of samples is
         * converted and added to clock base so that large sample counts don't
         * overflow during conversion. This also guarantees an exact, stable
         * conversion. */
        device->SamplesDone += SamplesToDo;
        device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES;
        device->SamplesDone %= device->Frequency;
        V0(device->Backend,unlock)();

        if(device->Hrtf)
        {
            HrtfMixerFunc HrtfMix = SelectHrtfMixer();
            ALuint irsize = GetHrtfIrSize(device->Hrtf);
            for(c = 0;c < device->NumChannels;c++)
                HrtfMix(OutBuffer, device->DryBuffer[c], 0, device->Hrtf_Offset,
                    0, irsize, &device->Hrtf_Params[c], &device->Hrtf_State[c],
                    SamplesToDo
                );
            device->Hrtf_Offset += SamplesToDo;
        }
        else if(device->Bs2b)
        {
            /* Apply binaural/crossfeed filter */
            for(i = 0;i < SamplesToDo;i++)
            {
                float samples[2];
                samples[0] = device->DryBuffer[0][i];
                samples[1] = device->DryBuffer[1][i];
                bs2b_cross_feed(device->Bs2b, samples);
                device->DryBuffer[0][i] = samples[0];
                device->DryBuffer[1][i] = samples[1];
            }
        }

        if(buffer)
        {
#define WRITE(T, a, b, c, d) do {               \
    Write_##T((a), (b), (c), (d));              \
    buffer = (T*)buffer + (c)*(d);              \
} while(0)
            switch(device->FmtType)
            {
                case DevFmtByte:
                    WRITE(ALbyte, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
                case DevFmtUByte:
                    WRITE(ALubyte, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
                case DevFmtShort:
                    WRITE(ALshort, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
                case DevFmtUShort:
                    WRITE(ALushort, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
                case DevFmtInt:
                    WRITE(ALint, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
                case DevFmtUInt:
                    WRITE(ALuint, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
                case DevFmtFloat:
                    WRITE(ALfloat, OutBuffer, buffer, SamplesToDo, OutChannels);
                    break;
            }
#undef WRITE
        }

        size -= SamplesToDo;
        IncrementRef(&device->MixCount);
    }

    RestoreFPUMode(&oldMode);
}