示例#1
0
文件: ALu.c 项目: johndpope/Medusa
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);
}
示例#2
0
num_errors DoPass2( section_ptr sec, unsigned_8 *contents, orl_sec_size size,
                    label_list sec_label_list, ref_list sec_ref_list )
// perform pass 2 on one section
{
    struct pass2        data;
    label_entry         l_entry;
    dis_dec_ins         decoded;
    char                name[ MAX_INS_NAME ];
    char                ops[ MAX_OBJ_NAME + 24 ];       // at most 1 label/relocation per instruction, plus room for registers, brackets and other crap
    dis_inst_flags      flags;
    scantab_ptr         st;
    int                 is_intel;
    sa_disasm_struct    sds;
    char                *FPU_fixup;
    int                 pos_tabs;
    bool                is32bit;

    routineBase = 0;
    st = sec->scan;
    data.size = size;
    sds.data = contents;
    sds.last = size - 1;
    l_entry = NULL;
    if( sec_label_list != NULL ) {
        l_entry = sec_label_list->first;
    }
    if( sec_ref_list != NULL ) {
        data.r_entry = sec_ref_list->first;
    } else {
        data.r_entry = NULL;
    }
    data.disassembly_errors = 0;

    if( source_mix ) {
        GetSourceFile( sec );
    }

    PrintHeader( sec );
    if( size && sec_label_list )
        PrintAssumeHeader( sec );
    flags.u.all = DIF_NONE;
    if( GetMachineType() == ORL_MACHINE_TYPE_I386 ) {
        if( ( GetFormat() != ORL_OMF ) ||
            ( ORLSecGetFlags( sec->shnd ) & ORL_SEC_FLAG_USE_32 ) ) {
            flags.u.x86 = DIF_X86_USE32_FLAGS;
        }
        is_intel = 1;
    } else {
        is_intel = IsIntelx86();
    }
    is32bit = ( size >= 0x10000 );
    for( data.loop = 0; data.loop < size; data.loop += decoded.size ) {

        // process data in code segment
        while( st && ( data.loop > st->end ) ) {
            st = st->next;
        }
        if( st && ( data.loop >= st->start ) ) {
            decoded.size = 0;
            processDataInCode( sec, contents, &data, st->end - data.loop, &l_entry );
            st = st->next;
            continue;
        }
        // data may not be listed in scan table, but a fixup at this offset will
        // give it away
        while( data.r_entry && ( data.r_entry->offset < data.loop ) ) {
            data.r_entry = data.r_entry->next;
        }
        FPU_fixup = processFpuEmulatorFixup( &data.r_entry, data.loop );
        if( data.r_entry && ( data.r_entry->offset == data.loop ) ) {
            if( is_intel || IsDataReloc( data.r_entry ) ) {
                // we just skip the data
                decoded.size = 0;
                processDataInCode( sec, contents, &data, RelocSize( data.r_entry ), &l_entry );
                continue;
            }
        }

        if( source_mix ) {
            MixSource( data.loop );
        }
        DisDecodeInit( &DHnd, &decoded );
        decoded.flags.u.all |= flags.u.all;
        sds.offs = data.loop;
        DisDecode( &DHnd, &sds, &decoded );
        if( sec_label_list ) {
            l_entry = handleLabels( sec->name, data.loop, data.loop + decoded.size, l_entry, size );
            if( ( l_entry != NULL )
                && ( l_entry->offset > data.loop )
                && ( l_entry->offset < data.loop + decoded.size ) ) {
                /*
                    If we have a label planted in the middle of this
                    instruction (see inline memchr for example), put
                    out a couple of data bytes, and then restart decode
                    and label process from offset of actual label.
                */
                decoded.size = 0;
                processDataInCode( sec, contents, &data, l_entry->offset - data.loop, &l_entry );
                continue;
            }
        }
        DisFormat( &DHnd, &data, &decoded, DFormat, name, sizeof( name ), ops, sizeof( ops ) );
        if( FPU_fixup != NULL ) {
            if( !(DFormat & DFF_ASM) ) {
                BufferAlignToTab( PREFIX_SIZE_TABS );
            }
            BufferStore( "\t%sFPU fixup %s\n", CommentString, FPU_fixup );
        }
        if( !(DFormat & DFF_ASM) ) {
            unsigned_64     *tmp_64;
            unsigned_32     *tmp_32;
            unsigned_16     *tmp_16;

            tmp_64 = (unsigned_64 *)(contents + data.loop);
            tmp_32 = (unsigned_32 *)(contents + data.loop);
            tmp_16 = (unsigned_16 *)(contents + data.loop);
            if( DHnd.need_bswap ) {
                switch( DisInsSizeInc( &DHnd ) ) {
                //case 8: SWAP_64( *tmp_64 );
                //    break;
                case 4: SWAP_32( *tmp_32 );
                    break;
                case 2: SWAP_16( *tmp_16 );
                    break;
                default:
                    break;
                }
            }
            PrintLinePrefixAddress( data.loop, is32bit );
            PrintLinePrefixData( contents, data.loop, size, DisInsSizeInc( &DHnd ), decoded.size );
            BufferAlignToTab( PREFIX_SIZE_TABS );
        }
        BufferStore( "\t%s", name );
        if( *ops != '\0' ) {
            pos_tabs = ( DisInsNameMax( &DHnd ) + TAB_WIDTH ) / TAB_WIDTH + 1;
            if( !(DFormat & DFF_ASM) ) {
                pos_tabs += PREFIX_SIZE_TABS;
            }
            BufferAlignToTab( pos_tabs );
            BufferConcat( ops );
        }
        BufferConcatNL();
        BufferPrint();
    }
    if( sec_label_list ) {
        l_entry = handleLabels( sec->name, size, (orl_sec_offset)-1, l_entry, size );
    }
    if( !(DFormat & DFF_ASM) ) {
        routineSize = data.loop - routineBase;
        BufferConcatNL();
        BufferMsg( ROUTINE_SIZE );
        BufferStore(" %d ", routineSize );
        BufferMsg( BYTES );
        BufferConcat(",    ");
        BufferMsg( ROUTINE_BASE );
        BufferStore(" %s + %04X\n\n", sec->name, routineBase );
        BufferPrint();
    }
    if( source_mix ) {
        EndSourceMix();
    }
    PrintTail( sec );
    return( data.disassembly_errors );
}