Exemple #1
0
AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2)
{
    ALCdevice *device;
    ALCcontext *context;
    ALenum err;

    context = GetContextRef();
    if(!context) return;

    if(!(event == AL_NOTEOFF_SOFT || event == AL_NOTEON_SOFT ||
            event == AL_KEYPRESSURE_SOFT || event == AL_CONTROLLERCHANGE_SOFT ||
            event == AL_PROGRAMCHANGE_SOFT || event == AL_CHANNELPRESSURE_SOFT ||
            event == AL_PITCHBEND_SOFT))
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    if(!(channel >= 0 && channel <= 15))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    if(!(param1 >= 0 && param1 <= 127))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    if(!(param2 >= 0 && param2 <= 127))
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);

    device = context->Device;
    ALCdevice_Lock(device);
    err = MidiSynth_insertEvent(device->Synth, time, event|channel, param1, param2);
    ALCdevice_Unlock(device);
    if(err != AL_NO_ERROR)
        alSetError(context, err);

done:
    ALCcontext_DecRef(context);
}
Exemple #2
0
AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size)
{
    ALCdevice *device;
    ALCcontext *context;
    ALenum err;
    ALsizei i;

    context = GetContextRef();
    if(!context) return;

    if(!data || size < 0)
        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    for(i = 0; i < size; i++)
    {
        if((data[i]&0x80))
            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
    }

    device = context->Device;
    ALCdevice_Lock(device);
    err = MidiSynth_insertSysExEvent(device->Synth, time, data, size);
    ALCdevice_Unlock(device);
    if(err != AL_NO_ERROR)
        alSetError(context, err);

done:
    ALCcontext_DecRef(context);
}
Exemple #3
0
AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
{
    ALCcontext *context;
    ALCdevice *device;
    MidiSynth *synth;
    ALint64SOFT value = 0;

    context = GetContextRef();
    if(!context) return 0;

    switch(pname)
    {
    case AL_DOPPLER_FACTOR:
        value = (ALint64SOFT)context->DopplerFactor;
        break;

    case AL_DOPPLER_VELOCITY:
        value = (ALint64SOFT)context->DopplerVelocity;
        break;

    case AL_DISTANCE_MODEL:
        value = (ALint64SOFT)context->DistanceModel;
        break;

    case AL_SPEED_OF_SOUND:
        value = (ALint64SOFT)context->SpeedOfSound;
        break;

    case AL_DEFERRED_UPDATES_SOFT:
        value = (ALint64SOFT)context->DeferUpdates;
        break;

    case AL_MIDI_CLOCK_SOFT:
        device = context->Device;
        ALCdevice_Lock(device);
        value = MidiSynth_getTime(device->Synth);
        ALCdevice_Unlock(device);
        break;

    case AL_SOUNDFONTS_SIZE_SOFT:
        device = context->Device;
        synth = device->Synth;
        value = (ALint64SOFT)synth->NumSoundfonts;
        break;

    case AL_MIDI_STATE_SOFT:
        device = context->Device;
        value = (ALint64SOFT)MidiSynth_getState(device->Synth);
        break;

    default:
        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
    }

done:
    ALCcontext_DecRef(context);

    return value;
}
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
{
    ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
    ALeffectStateFactory *factory;

    if(newtype != EffectSlot->Effect.Type)
    {
        ALeffectState *State;
        FPUCtl oldMode;

        factory = getFactoryByType(newtype);
        if(!factory)
        {
            ERR("Failed to find factory for effect type 0x%04x\n", newtype);
            return AL_INVALID_ENUM;
        }
        State = V0(factory,create)();
        if(!State)
            return AL_OUT_OF_MEMORY;

        SetMixerFPUMode(&oldMode);
        /* FIXME: This just needs to prevent the device from being reset during
         * the state's device update, so the list lock in ALc.c should do here.
         */
        ALCdevice_Lock(Device);
        State->OutBuffer = Device->Dry.Buffer;
        State->OutChannels = Device->Dry.NumChannels;
        if(V(State,deviceUpdate)(Device) == AL_FALSE)
        {
            ALCdevice_Unlock(Device);
            RestoreFPUMode(&oldMode);
            DELETE_OBJ(State);
            return AL_OUT_OF_MEMORY;
        }
        ALCdevice_Unlock(Device);
        RestoreFPUMode(&oldMode);

        if(!effect)
        {
            EffectSlot->Effect.Type = AL_EFFECT_NULL;
            memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
        }
        else
        {
            EffectSlot->Effect.Type = effect->type;
            memcpy(&EffectSlot->Effect.Props, &effect->Props, sizeof(EffectSlot->Effect.Props));
        }

        EffectSlot->Effect.State = State;
        UpdateEffectSlotProps(EffectSlot, AL_TRUE);
    }
    else if(effect)
    {
        memcpy(&EffectSlot->Effect.Props, &effect->Props, sizeof(EffectSlot->Effect.Props));
        UpdateEffectSlotProps(EffectSlot, AL_FALSE);
    }

    return AL_NO_ERROR;
}
Exemple #5
0
AL_API void AL_APIENTRY alMidiResetSOFT(void)
{
    ALCdevice *device;
    ALCcontext *context;
    MidiSynth *synth;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    synth = device->Synth;

    WriteLock(&synth->Lock);
    MidiSynth_setState(synth, AL_INITIAL);

    ALCdevice_Lock(device);
    V0(synth,reset)();
    ALCdevice_Unlock(device);
    WriteUnlock(&synth->Lock);

    ALCcontext_DecRef(context);
}
Exemple #6
0
AL_API void AL_APIENTRY alMidiStopSOFT(void)
{
    ALCdevice *device;
    ALCcontext *context;
    MidiSynth *synth;

    context = GetContextRef();
    if(!context) return;

    device = context->Device;
    synth = device->Synth;

    WriteLock(&synth->Lock);
    V(synth,setState)(AL_STOPPED);

    ALCdevice_Lock(device);
    V0(synth,stop)();
    ALCdevice_Unlock(device);
    WriteUnlock(&synth->Lock);

    ALCcontext_DecRef(context);
}
Exemple #7
0
static ALuint sndio_proc(ALvoid *ptr)
{
    ALCdevice *device = ptr;
    sndio_data *data = device->ExtraData;
    ALsizei frameSize;
    size_t wrote;

    SetRTPriority();
    SetThreadName(MIXER_THREAD_NAME);

    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);

    while(!data->killNow && device->Connected)
    {
        ALsizei len = data->data_size;
        ALubyte *WritePtr = data->mix_data;

        aluMixData(device, WritePtr, len/frameSize);
        while(len > 0 && !data->killNow)
        {
            wrote = sio_write(data->sndHandle, WritePtr, len);
            if(wrote == 0)
            {
                ERR("sio_write failed\n");
                ALCdevice_Lock(device);
                aluHandleDisconnect(device);
                ALCdevice_Unlock(device);
                break;
            }

            len -= wrote;
            WritePtr += wrote;
        }
    }

    return 0;
}
Exemple #8
0
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
{
    ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
    ALeffectStateFactory *factory;

    if(newtype != EffectSlot->EffectType)
    {
        ALeffectState *State;
        FPUCtl oldMode;

        factory = getFactoryByType(newtype);
        if(!factory)
        {
            ERR("Failed to find factory for effect type 0x%04x\n", newtype);
            return AL_INVALID_ENUM;
        }
        State = V0(factory,create)();
        if(!State)
            return AL_OUT_OF_MEMORY;

        SetMixerFPUMode(&oldMode);

        ALCdevice_Lock(Device);
        if(V(State,deviceUpdate)(Device) == AL_FALSE)
        {
            ALCdevice_Unlock(Device);
            RestoreFPUMode(&oldMode);
            DELETE_OBJ(State);
            return AL_OUT_OF_MEMORY;
        }

        State = ExchangePtr((XchgPtr*)&EffectSlot->EffectState, State);
        if(!effect)
        {
            memset(&EffectSlot->EffectProps, 0, sizeof(EffectSlot->EffectProps));
            EffectSlot->EffectType = AL_EFFECT_NULL;
        }
        else
        {
            memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
            EffectSlot->EffectType = effect->type;
        }

        /* FIXME: This should be done asynchronously, but since the EffectState
         * object was changed, it needs an update before its Process method can
         * be called. */
        ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_FALSE);
        V(EffectSlot->EffectState,update)(Device, EffectSlot);
        ALCdevice_Unlock(Device);

        RestoreFPUMode(&oldMode);

        DELETE_OBJ(State);
        State = NULL;
    }
    else
    {
        if(effect)
        {
            ALCdevice_Lock(Device);
            memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
            ALCdevice_Unlock(Device);
            ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_TRUE);
        }
    }

    return AL_NO_ERROR;
}
static ALuint DSoundPlaybackProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData;
    DSBCAPS DSBCaps;
    DWORD LastCursor = 0;
    DWORD PlayCursor;
    VOID *WritePtr1, *WritePtr2;
    DWORD WriteCnt1,  WriteCnt2;
    BOOL Playing = FALSE;
    DWORD FrameSize;
    DWORD FragSize;
    DWORD avail;
    HRESULT err;

    SetRTPriority();

    memset(&DSBCaps, 0, sizeof(DSBCaps));
    DSBCaps.dwSize = sizeof(DSBCaps);
    err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps);
    if(FAILED(err))
    {
        ERR("Failed to get buffer caps: 0x%lx\n", err);
        ALCdevice_Lock(Device);
        aluHandleDisconnect(Device);
        ALCdevice_Unlock(Device);
        return 1;
    }

    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
    FragSize = Device->UpdateSize * FrameSize;

    IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL);
    while(!data->killNow)
    {
        // Get current play cursor
        IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL);
        avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;

        if(avail < FragSize)
        {
            if(!Playing)
            {
                err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING);
                if(FAILED(err))
                {
                    ERR("Failed to play buffer: 0x%lx\n", err);
                    ALCdevice_Lock(Device);
                    aluHandleDisconnect(Device);
                    ALCdevice_Unlock(Device);
                    return 1;
                }
                Playing = TRUE;
            }

            avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
            if(avail != WAIT_OBJECT_0)
                ERR("WaitForSingleObjectEx error: 0x%lx\n", avail);
            continue;
        }
        avail -= avail%FragSize;

        // Lock output buffer
        WriteCnt1 = 0;
        WriteCnt2 = 0;
        err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);

        // If the buffer is lost, restore it and lock
        if(err == DSERR_BUFFERLOST)
        {
            WARN("Buffer lost, restoring...\n");
            err = IDirectSoundBuffer_Restore(data->Buffer);
            if(SUCCEEDED(err))
            {
                Playing = FALSE;
                LastCursor = 0;
                err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
            }
        }

        // Successfully locked the output buffer
        if(SUCCEEDED(err))
        {
            // If we have an active context, mix data directly into output buffer otherwise fill with silence
            aluMixData(Device, WritePtr1, WriteCnt1/FrameSize);
            aluMixData(Device, WritePtr2, WriteCnt2/FrameSize);

            // Unlock output buffer only when successfully locked
            IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
        }
        else
        {
            ERR("Buffer lock error: %#lx\n", err);
            ALCdevice_Lock(Device);
            aluHandleDisconnect(Device);
            ALCdevice_Unlock(Device);
            return 1;
        }

        // Update old write cursor location
        LastCursor += WriteCnt1+WriteCnt2;
        LastCursor %= DSBCaps.dwBufferBytes;
    }

    return 0;
}
Exemple #10
0
static ALuint WaveProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    wave_data *data = (wave_data*)Device->ExtraData;
    ALuint frameSize;
    ALuint now, start;
    ALuint64 avail, done;
    size_t fs;
    const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 /
                            Device->Frequency / 2;

    frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);

    done = 0;
    start = timeGetTime();
    while(!data->killNow && Device->Connected)
    {
        now = timeGetTime();

        avail = (ALuint64)(now-start) * Device->Frequency / 1000;
        if(avail < done)
        {
            /* Timer wrapped (50 days???). Add the remainder of the cycle to
             * the available count and reset the number of samples done */
            avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done;
            done = 0;
        }
        if(avail-done < Device->UpdateSize)
        {
            Sleep(restTime);
            continue;
        }

        while(avail-done >= Device->UpdateSize)
        {
            aluMixData(Device, data->buffer, Device->UpdateSize);
            done += Device->UpdateSize;

            if(!IS_LITTLE_ENDIAN)
            {
                ALuint bytesize = BytesFromDevFmt(Device->FmtType);
                ALubyte *bytes = data->buffer;
                ALuint i;

                if(bytesize == 1)
                {
                    for(i = 0;i < data->size;i++)
                        fputc(bytes[i], data->f);
                }
                else if(bytesize == 2)
                {
                    for(i = 0;i < data->size;i++)
                        fputc(bytes[i^1], data->f);
                }
                else if(bytesize == 4)
                {
                    for(i = 0;i < data->size;i++)
                        fputc(bytes[i^3], data->f);
                }
            }
            else
            {
                fs = fwrite(data->buffer, frameSize, Device->UpdateSize,
                            data->f);
                fs = fs;
            }
            if(ferror(data->f))
            {
                ERR("Error writing to file\n");
                ALCdevice_Lock(Device);
                aluHandleDisconnect(Device);
                ALCdevice_Unlock(Device);
                break;
            }
        }
    }

    return 0;
}
Exemple #11
0
static ALuint MMDevApiProc(ALvoid *ptr)
{
    ALCdevice *device = ptr;
    MMDevApiData *data = device->ExtraData;
    UINT32 buffer_len, written;
    ALuint update_size, len;
    BYTE *buffer;
    HRESULT hr;

    hr = CoInitialize(NULL);
    if(FAILED(hr))
    {
        ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
        ALCdevice_Lock(device);
        aluHandleDisconnect(device);
        ALCdevice_Unlock(device);
        return 0;
    }

    SetRTPriority();

    update_size = device->UpdateSize;
    buffer_len = update_size * device->NumUpdates;
    while(!data->killNow)
    {
        hr = IAudioClient_GetCurrentPadding(data->client, &written);
        if(FAILED(hr))
        {
            ERR("Failed to get padding: 0x%08lx\n", hr);
            ALCdevice_Lock(device);
            aluHandleDisconnect(device);
            ALCdevice_Unlock(device);
            break;
        }
        data->Padding = written;

        len = buffer_len - written;
        if(len < update_size)
        {
            DWORD res;
            res = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
            if(res != WAIT_OBJECT_0)
                ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
            continue;
        }
        len -= len%update_size;

        hr = IAudioRenderClient_GetBuffer(data->render, len, &buffer);
        if(SUCCEEDED(hr))
        {
            ALCdevice_Lock(device);
            aluMixData(device, buffer, len);
            data->Padding = written + len;
            ALCdevice_Unlock(device);
            hr = IAudioRenderClient_ReleaseBuffer(data->render, len, 0);
        }
        if(FAILED(hr))
        {
            ERR("Failed to buffer data: 0x%08lx\n", hr);
            ALCdevice_Lock(device);
            aluHandleDisconnect(device);
            ALCdevice_Unlock(device);
            break;
        }
    }
    data->Padding = 0;

    CoUninitialize();
    return 0;
}