Example #1
0
File: alsa.c Project: 9heart/DT3
static ALCuint alsa_available_samples(ALCdevice *Device)
{
    alsa_data *data = (alsa_data*)Device->ExtraData;
    snd_pcm_sframes_t avail;

    avail = (Device->Connected ? snd_pcm_avail_update(data->pcmHandle) : 0);
    if(avail < 0)
    {
        ERR("avail update failed: %s\n", snd_strerror(avail));

        if((avail=snd_pcm_recover(data->pcmHandle, avail, 1)) >= 0)
        {
            if(data->doCapture)
                avail = snd_pcm_start(data->pcmHandle);
            if(avail >= 0)
                avail = snd_pcm_avail_update(data->pcmHandle);
        }
        if(avail < 0)
        {
            ERR("restore error: %s\n", snd_strerror(avail));
            aluHandleDisconnect(Device);
        }
    }
    while(avail > 0)
    {
        snd_pcm_sframes_t amt;

        amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
        if(avail < amt) amt = avail;

        amt = snd_pcm_readi(data->pcmHandle, data->buffer, amt);
        if(amt < 0)
        {
            ERR("read error: %s\n", snd_strerror(amt));

            if(amt == -EAGAIN)
                continue;
            if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0)
            {
                if(data->doCapture)
                    amt = snd_pcm_start(data->pcmHandle);
                if(amt >= 0)
                    amt = snd_pcm_avail_update(data->pcmHandle);
            }
            if(amt < 0)
            {
                ERR("restore error: %s\n", snd_strerror(amt));
                aluHandleDisconnect(Device);
                break;
            }
            avail = amt;
            continue;
        }

        WriteRingBuffer(data->ring, data->buffer, amt);
        avail -= amt;
    }

    return RingBufferSize(data->ring);
}
Example #2
0
static ALCenum pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
{
    pulse_data *data = device->ExtraData;
    ALCuint todo = samples * pa_frame_size(&data->spec);

    pa_threaded_mainloop_lock(data->loop);
    /* Capture is done in fragment-sized chunks, so we loop until we get all
     * that's available */
    data->last_readable -= todo;
    while(todo > 0)
    {
        size_t rem = todo;

        if(data->cap_len == 0)
        {
            pa_stream_state_t state;

            state = pa_stream_get_state(data->stream);
            if(!PA_STREAM_IS_GOOD(state))
            {
                aluHandleDisconnect(device);
                break;
            }
            if(pa_stream_peek(data->stream, &data->cap_store, &data->cap_len) < 0)
            {
                ERR("pa_stream_peek() failed: %s\n",
                    pa_strerror(pa_context_errno(data->context)));
                aluHandleDisconnect(device);
                break;
            }
            data->cap_remain = data->cap_len;
        }
        if(rem > data->cap_remain)
            rem = data->cap_remain;

        memcpy(buffer, data->cap_store, rem);

        buffer = (ALbyte*)buffer + rem;
        todo -= rem;

        data->cap_store = (ALbyte*)data->cap_store + rem;
        data->cap_remain -= rem;
        if(data->cap_remain == 0)
        {
            pa_stream_drop(data->stream);
            data->cap_len = 0;
        }
    }
    if(todo > 0)
        memset(buffer, ((device->FmtType==DevFmtUByte) ? 0x80 : 0), todo);
    pa_threaded_mainloop_unlock(data->loop);

    return ALC_NO_ERROR;
}
Example #3
0
static ALCuint qsa_available_samples(ALCdevice* device)
{
    qsa_data* data=(qsa_data*)device->ExtraData;
    snd_pcm_channel_status_t status;
    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
    ALint free_size;
    int rstatus;

    memset(&status, 0, sizeof (status));
    status.channel=SND_PCM_CHANNEL_CAPTURE;
    snd_pcm_plugin_status(data->pcmHandle, &status);
    if ((status.status==SND_PCM_STATUS_OVERRUN) ||
        (status.status==SND_PCM_STATUS_READY))
    {
        if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
        {
            ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
            aluHandleDisconnect(device);
            return 0;
        }

        snd_pcm_capture_go(data->pcmHandle);
        return 0;
    }

    free_size=data->csetup.buf.block.frag_size*data->csetup.buf.block.frags;
    free_size-=status.free;

    return free_size/frame_size;
}
Example #4
0
static ALuint OSSCaptureProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    oss_data *data = (oss_data*)pDevice->ExtraData;
    int frameSize;
    int amt;

    SetRTPriority();

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

    while(!data->killNow)
    {
        amt = read(data->fd, data->mix_data, data->data_size);
        if(amt < 0)
        {
            ERR("read failed: %s\n", strerror(errno));
            aluHandleDisconnect(pDevice);
            break;
        }
        if(amt == 0)
        {
            Sleep(1);
            continue;
        }
        if(data->doCapture)
            WriteRingBuffer(data->ring, data->mix_data, amt/frameSize);
    }

    return 0;
}
Example #5
0
static ALuint sndio_proc(ALvoid *ptr)
{
    ALCdevice *device = ptr;
    sndio_data *data = device->ExtraData;
    ALsizei frameSize;
    size_t wrote;

    SetRTPriority();

    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");
                aluHandleDisconnect(device);
                break;
            }

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

    return 0;
}
Example #6
0
static ALuint ALSANoMMapProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    alsa_data *data = (alsa_data*)Device->ExtraData;
    snd_pcm_sframes_t avail;
    char *WritePtr;

    SetRTPriority();

    while(!data->killNow)
    {
        int state = verify_state(data->pcmHandle);
        if(state < 0)
        {
            ERR("Invalid state detected: %s\n", snd_strerror(state));
            aluHandleDisconnect(Device);
            break;
        }

        WritePtr = data->buffer;
        avail = data->size / snd_pcm_frames_to_bytes(data->pcmHandle, 1);
        aluMixData(Device, WritePtr, avail);

        while(avail > 0)
        {
            int ret = snd_pcm_writei(data->pcmHandle, WritePtr, avail);
            switch (ret)
            {
            case -EAGAIN:
                continue;
            case -ESTRPIPE:
            case -EPIPE:
            case -EINTR:
                ret = snd_pcm_recover(data->pcmHandle, ret, 1);
                if(ret < 0)
                    avail = 0;
                break;
            default:
                if (ret >= 0)
                {
                    WritePtr += snd_pcm_frames_to_bytes(data->pcmHandle, ret);
                    avail -= ret;
                }
                break;
            }
            if (ret < 0)
            {
                ret = snd_pcm_prepare(data->pcmHandle);
                if(ret < 0)
                    break;
            }
        }
    }

    return 0;
}
Example #7
0
static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{
{
    ALCdevice *Device = pdata;

    if(ppa_stream_get_state(stream) == PA_STREAM_FAILED)
    {
        AL_PRINT("Received stream failure!\n");
        aluHandleDisconnect(Device);
    }
}//}}}
Example #8
0
static void context_state_callback2(pa_context *context, void *pdata) //{{{
{
    ALCdevice *Device = pdata;

    if(ppa_context_get_state(context) == PA_CONTEXT_FAILED)
    {
        AL_PRINT("Received context failure!\n");
        aluHandleDisconnect(Device);
    }
}//}}}
Example #9
0
static void DSoundStartCapture(ALCdevice *device)
{
    DSoundCaptureData *pData = device->ExtraData;
    HRESULT hr;

    hr = IDirectSoundCaptureBuffer_Start(pData->DSCbuffer, DSCBSTART_LOOPING);
    if(FAILED(hr))
    {
        ERR("start failed: 0x%08lx\n", hr);
        aluHandleDisconnect(device);
    }
}
Example #10
0
static void context_state_callback2(pa_context *context, void *pdata) //{{{
{
    ALCdevice *Device = pdata;
    pulse_data *data = Device->ExtraData;

    if(pa_context_get_state(context) == PA_CONTEXT_FAILED)
    {
        ERR("Received context failure!\n");
        aluHandleDisconnect(Device);
    }
    pa_threaded_mainloop_signal(data->loop, 0);
}//}}}
Example #11
0
static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{
{
    ALCdevice *Device = pdata;
    pulse_data *data = Device->ExtraData;

    if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
    {
        ERR("Received stream failure!\n");
        aluHandleDisconnect(Device);
    }
    pa_threaded_mainloop_signal(data->loop, 0);
}//}}}
Example #12
0
static void DSoundStopCapture(ALCdevice *device)
{
    DSoundCaptureData *data = device->ExtraData;
    HRESULT hr;

    hr = IDirectSoundCaptureBuffer_Stop(data->DSCbuffer);
    if(FAILED(hr))
    {
        ERR("stop failed: 0x%08lx\n", hr);
        aluHandleDisconnect(device);
    }
}
Example #13
0
static ALuint ALSANoMMapProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    alsa_data *data = (alsa_data*)pDevice->ExtraData;
    snd_pcm_sframes_t avail;
    char *WritePtr;

    while(!data->killNow)
    {
        int state = verify_state(data->pcmHandle);
        if(state < 0)
        {
            AL_PRINT("Invalid state detected: %s\n", psnd_strerror(state));
            aluHandleDisconnect(pDevice);
            break;
        }

        WritePtr = data->buffer;
        avail = data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1);
        aluMixData(pDevice, WritePtr, avail);

        while(avail > 0)
        {
            int ret = psnd_pcm_writei(data->pcmHandle, WritePtr, avail);
            switch (ret)
            {
            case -EAGAIN:
                continue;
            case -ESTRPIPE:
                while((ret=psnd_pcm_resume(data->pcmHandle)) == -EAGAIN)
                    Sleep(1);
                break;
            case -EPIPE:
                break;
            default:
                if (ret >= 0)
                {
                    WritePtr += psnd_pcm_frames_to_bytes(data->pcmHandle, ret);
                    avail -= ret;
                }
                break;
            }
            if (ret < 0)
            {
                ret = psnd_pcm_prepare(data->pcmHandle);
                if(ret < 0)
                    break;
            }
        }
    }

    return 0;
}
Example #14
0
static void alsa_start_capture(ALCdevice *Device)
{
    alsa_data *data = (alsa_data*)Device->ExtraData;
    int err;

    err = snd_pcm_start(data->pcmHandle);
    if(err < 0)
    {
        ERR("start failed: %s\n", snd_strerror(err));
        aluHandleDisconnect(Device);
    }
    else
        data->doCapture = AL_TRUE;
}
Example #15
0
static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
{
    DSoundCaptureData *pData = pDevice->ExtraData;
    DWORD dwRead, dwCursor, dwBufferBytes, dwNumBytes;
    void *pvAudio1, *pvAudio2;
    DWORD dwAudioBytes1, dwAudioBytes2;
    DWORD FrameSize;
    HRESULT hr;

    if(!pDevice->Connected)
        goto done;

    FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
    dwBufferBytes = pData->dwBufferBytes;
    dwCursor = pData->dwCursor;

    hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pData->DSCbuffer, NULL, &dwRead);
    if(SUCCEEDED(hr))
    {
        dwNumBytes = (dwBufferBytes + dwRead - dwCursor) % dwBufferBytes;
        if(dwNumBytes == 0)
            goto done;
        hr = IDirectSoundCaptureBuffer_Lock(pData->DSCbuffer,
                                            dwCursor, dwNumBytes,
                                            &pvAudio1, &dwAudioBytes1,
                                            &pvAudio2, &dwAudioBytes2, 0);
    }
    if(SUCCEEDED(hr))
    {
        WriteRingBuffer(pData->pRing, pvAudio1, dwAudioBytes1/FrameSize);
        if(pvAudio2 != NULL)
            WriteRingBuffer(pData->pRing, pvAudio2, dwAudioBytes2/FrameSize);
        hr = IDirectSoundCaptureBuffer_Unlock(pData->DSCbuffer,
                                              pvAudio1, dwAudioBytes1,
                                              pvAudio2, dwAudioBytes2);
        pData->dwCursor = (dwCursor + dwAudioBytes1 + dwAudioBytes2) % dwBufferBytes;
    }

    if(FAILED(hr))
    {
        ERR("update failed: 0x%08lx\n", hr);
        aluHandleDisconnect(pDevice);
    }

done:
    return RingBufferSize(pData->pRing);
}
Example #16
0
static ALCuint DSoundAvailableSamples(ALCdevice *Device)
{
    DSoundCaptureData *data = Device->ExtraData;
    DWORD ReadCursor, LastCursor, BufferBytes, NumBytes;
    VOID *ReadPtr1, *ReadPtr2;
    DWORD ReadCnt1,  ReadCnt2;
    DWORD FrameSize;
    HRESULT hr;

    if(!Device->Connected)
        goto done;

    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
    BufferBytes = data->BufferBytes;
    LastCursor = data->Cursor;

    hr = IDirectSoundCaptureBuffer_GetCurrentPosition(data->DSCbuffer, NULL, &ReadCursor);
    if(SUCCEEDED(hr))
    {
        NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes;
        if(NumBytes == 0)
            goto done;
        hr = IDirectSoundCaptureBuffer_Lock(data->DSCbuffer, LastCursor, NumBytes,
                                            &ReadPtr1, &ReadCnt1,
                                            &ReadPtr2, &ReadCnt2, 0);
    }
    if(SUCCEEDED(hr))
    {
        WriteRingBuffer(data->Ring, ReadPtr1, ReadCnt1/FrameSize);
        if(ReadPtr2 != NULL)
            WriteRingBuffer(data->Ring, ReadPtr2, ReadCnt2/FrameSize);
        hr = IDirectSoundCaptureBuffer_Unlock(data->DSCbuffer,
                                              ReadPtr1, ReadCnt1,
                                              ReadPtr2, ReadCnt2);
        data->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes;
    }

    if(FAILED(hr))
    {
        ERR("update failed: 0x%08lx\n", hr);
        aluHandleDisconnect(Device);
    }

done:
    return RingBufferSize(data->Ring);
}
Example #17
0
static ALuint ALSANoMMapCaptureProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    alsa_data *data = (alsa_data*)pDevice->ExtraData;
    snd_pcm_sframes_t avail;

    while(!data->killNow)
    {
        int state = verify_state(data->pcmHandle);
        if(state < 0)
        {
            AL_PRINT("Invalid state detected: %s\n", psnd_strerror(state));
            aluHandleDisconnect(pDevice);
            break;
        }

        avail = (snd_pcm_uframes_t)data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1);
        avail = psnd_pcm_readi(data->pcmHandle, data->buffer, avail);
        switch(avail)
        {
            case -EAGAIN:
                continue;
            case -ESTRPIPE:
                while((avail=psnd_pcm_resume(data->pcmHandle)) == -EAGAIN)
                    Sleep(1);
                break;
            case -EPIPE:
                break;
            default:
                if (avail >= 0 && data->doCapture)
                    WriteRingBuffer(data->ring, data->buffer, avail);
                break;
        }
        if(avail < 0)
        {
            avail = psnd_pcm_prepare(data->pcmHandle);
            if(avail < 0)
                AL_PRINT("prepare error: %s\n", psnd_strerror(avail));
        }
    }

    return 0;
}
static ALuint OSSProc( ALvoid* ptr )
{
	ALCdevice* pDevice = ( ALCdevice* )ptr;
	oss_data* data = ( oss_data* )pDevice->ExtraData;
	ALint frameSize;
	ssize_t wrote;

	SetRTPriority();

	frameSize = aluFrameSizeFromFormat( pDevice->Format );

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

		aluMixData( pDevice, WritePtr, len / frameSize );

		while ( len > 0 && !data->killNow )
		{
			wrote = write( data->fd, WritePtr, len );

			if ( wrote < 0 )
			{
				if ( errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR )
				{
					AL_PRINT( "write failed: %s\n", strerror( errno ) );
					aluHandleDisconnect( pDevice );
					break;
				}

				Sleep( 1 );
				continue;
			}

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

	return 0;
}
Example #19
0
static ALCuint pulse_available_samples(ALCdevice *device)
{
    pulse_data *data = device->ExtraData;
    size_t readable = data->cap_remain;

    if(device->Connected)
    {
        ssize_t got = pa_stream_readable_size(data->stream);
        if(got < 0)
        {
            ERR("pa_stream_readable_size() failed: %s\n", pa_strerror(got));
            aluHandleDisconnect(device);
        }
        else if((size_t)got > data->cap_len)
            readable += got - data->cap_len;
    }

    if(data->last_readable < readable)
        data->last_readable = readable;
    return data->last_readable / pa_frame_size(&data->spec);
}
Example #20
0
static int ALCsolarisBackend_mixerProc(void *ptr)
{
    ALCsolarisBackend *self = ptr;
    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
    struct timeval timeout;
    ALubyte *write_ptr;
    ALint frame_size;
    ALint to_write;
    ssize_t wrote;
    fd_set wfds;
    int sret;

    SetRTPriority();
    althrd_setname(althrd_current(), MIXER_THREAD_NAME);

    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);

    ALCsolarisBackend_lock(self);
    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
          ATOMIC_LOAD(&device->Connected, almemory_order_acquire) != DeviceConnect_Disconnected)
    {
        FD_ZERO(&wfds);
        FD_SET(self->fd, &wfds);
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        ALCsolarisBackend_unlock(self);
        sret = select(self->fd+1, NULL, &wfds, NULL, &timeout);
        ALCsolarisBackend_lock(self);
        if(sret < 0)
        {
            if(errno == EINTR)
                continue;
            ERR("select failed: %s\n", strerror(errno));
            aluHandleDisconnect(device, "Failed to wait for playback buffer: %s", strerror(errno));
            break;
        }
        else if(sret == 0)
        {
            WARN("select timeout\n");
            continue;
        }

        write_ptr = self->mix_data;
        to_write = self->data_size;
        aluMixData(device, write_ptr, to_write/frame_size);
        while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
        {
            wrote = write(self->fd, write_ptr, to_write);
            if(wrote < 0)
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
                    continue;
                ERR("write failed: %s\n", strerror(errno));
                aluHandleDisconnect(device, "Failed to write playback samples: %s",
                                    strerror(errno));
                break;
            }

            to_write -= wrote;
            write_ptr += wrote;
        }
    }
    ALCsolarisBackend_unlock(self);

    return 0;
}
Example #21
0
static ALuint ALSAProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    alsa_data *data = (alsa_data*)pDevice->ExtraData;
    const snd_pcm_channel_area_t *areas = NULL;
    snd_pcm_sframes_t avail, commitres;
    snd_pcm_uframes_t offset, frames;
    char *WritePtr;
    int err;

    while(!data->killNow)
    {
        int state = verify_state(data->pcmHandle);
        if(state < 0)
        {
            AL_PRINT("Invalid state detected: %s\n", psnd_strerror(state));
            aluHandleDisconnect(pDevice);
            break;
        }

        avail = psnd_pcm_avail_update(data->pcmHandle);
        if(avail < 0)
        {
            AL_PRINT("available update failed: %s\n", psnd_strerror(avail));
            continue;
        }

        // make sure there's frames to process
        if(avail >= 0 && avail < (snd_pcm_sframes_t)pDevice->UpdateSize)
        {
            if(state != SND_PCM_STATE_RUNNING)
            {
                err = psnd_pcm_start(data->pcmHandle);
                if(err < 0)
                {
                    AL_PRINT("start failed: %s\n", psnd_strerror(err));
                    continue;
                }
            }
            if(psnd_pcm_wait(data->pcmHandle, 1000) == 0)
                AL_PRINT("Wait timeout... buffer size too low?\n");
            continue;
        }
        avail -= avail%pDevice->UpdateSize;

        // it is possible that contiguous areas are smaller, thus we use a loop
        while(avail > 0)
        {
            frames = avail;

            err = psnd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames);
            if(err < 0)
            {
                AL_PRINT("mmap begin error: %s\n", psnd_strerror(err));
                break;
            }

            WritePtr = (char*)areas->addr + (offset * areas->step / 8);
            aluMixData(pDevice, WritePtr, frames);

            commitres = psnd_pcm_mmap_commit(data->pcmHandle, offset, frames);
            if(commitres < 0 || (commitres-frames) != 0)
            {
                AL_PRINT("mmap commit error: %s\n",
                         psnd_strerror(commitres >= 0 ? -EPIPE : commitres));
                break;
            }

            avail -= frames;
        }
    }

    return 0;
}
Example #22
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;
}
Example #23
0
File: opensl.c Project: dns/CLove
static int ALCopenslPlayback_mixerProc(void *arg)
{
    ALCopenslPlayback *self = arg;
    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
    SLAndroidSimpleBufferQueueItf bufferQueue;
    ll_ringbuffer_data_t data[2];
    SLPlayItf player;
    SLresult result;
    size_t padding;

    SetRTPriority();
    althrd_setname(althrd_current(), MIXER_THREAD_NAME);

    result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                                                       &bufferQueue);
    PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
    if(SL_RESULT_SUCCESS == result)
    {
        result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
        PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY");
    }
    if(SL_RESULT_SUCCESS != result)
    {
        ALCopenslPlayback_lock(self);
        aluHandleDisconnect(device);
        ALCopenslPlayback_unlock(self);
        return 1;
    }

    /* NOTE: The ringbuffer will be larger than the desired buffer metrics.
     * Calculate the amount of extra space so we know how much to keep unused.
     */
    padding = ll_ringbuffer_write_space(self->mRing) - device->NumUpdates;

    ALCopenslPlayback_lock(self);
    while(ATOMIC_LOAD_SEQ(&self->mKillNow) == AL_FALSE && device->Connected)
    {
        size_t todo, len0, len1;

        if(ll_ringbuffer_write_space(self->mRing) <= padding)
        {
            SLuint32 state = 0;

            result = VCALL(player,GetPlayState)(&state);
            PRINTERR(result, "player->GetPlayState");
            if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING)
            {
                result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
                PRINTERR(result, "player->SetPlayState");
            }
            if(SL_RESULT_SUCCESS != result)
            {
                aluHandleDisconnect(device);
                break;
            }

            /* NOTE: Unfortunately, there is an unavoidable race condition
             * here. It's possible for the process() method to run, updating
             * the read pointer and signaling the condition variable, in
             * between checking the write size and waiting for the condition
             * variable here. This will cause alcnd_wait to wait until the
             * *next* process() invocation signals the condition variable
             * again.
             *
             * However, this should only happen if the mixer is running behind
             * anyway (as ideally we'll be asleep in alcnd_wait by the time the
             * process() method is invoked), so this behavior is not completely
             * unwarranted. It's unfortunate since it'll be wasting time
             * sleeping that could be used to catch up, but there's no way
             * around it without blocking in the process() method.
             */
            if(ll_ringbuffer_write_space(self->mRing) <= padding)
            {
                alcnd_wait(&self->mCond, &STATIC_CAST(ALCbackend,self)->mMutex);
                continue;
            }
        }

        ll_ringbuffer_get_write_vector(self->mRing, data);
        todo = data[0].len+data[1].len - padding;

        len0 = minu(todo, data[0].len);
        len1 = minu(todo-len0, data[1].len);

        aluMixData(device, data[0].buf, len0*device->UpdateSize);
        for(size_t i = 0;i < len0;i++)
        {
            result = VCALL(bufferQueue,Enqueue)(data[0].buf, device->UpdateSize*self->mFrameSize);
            PRINTERR(result, "bufferQueue->Enqueue");
            if(SL_RESULT_SUCCESS == result)
                ll_ringbuffer_write_advance(self->mRing, 1);

            data[0].buf += device->UpdateSize*self->mFrameSize;
        }

        if(len1 > 0)
        {
            aluMixData(device, data[1].buf, len1*device->UpdateSize);
            for(size_t i = 0;i < len1;i++)
            {
                result = VCALL(bufferQueue,Enqueue)(data[1].buf, device->UpdateSize*self->mFrameSize);
                PRINTERR(result, "bufferQueue->Enqueue");
                if(SL_RESULT_SUCCESS == result)
                    ll_ringbuffer_write_advance(self->mRing, 1);

                data[1].buf += device->UpdateSize*self->mFrameSize;
            }
        }
    }
    ALCopenslPlayback_unlock(self);

    return 0;
}
Example #24
0
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;
}
Example #25
0
static ALuint DSoundProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    DSoundData *pData = (DSoundData*)pDevice->ExtraData;
    DSBCAPS DSBCaps;
    DWORD LastCursor = 0;
    DWORD PlayCursor;
    VOID *WritePtr1, *WritePtr2;
    DWORD WriteCnt1,  WriteCnt2;
    DWORD FrameSize;
    DWORD FragSize;
    DWORD avail;
    HRESULT err;

    SetRTPriority();

    memset(&DSBCaps, 0, sizeof(DSBCaps));
    DSBCaps.dwSize = sizeof(DSBCaps);
    err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
    if(FAILED(err))
    {
        AL_PRINT("Failed to get buffer caps: 0x%lx\n", err);
        aluHandleDisconnect(pDevice);
        return 1;
    }

    FrameSize = aluFrameSizeFromFormat(pDevice->Format);
    FragSize = pDevice->UpdateSize * FrameSize;

    IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
    while(!pData->killNow)
    {
        // Get current play and write cursors
        IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
        avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;

        if(avail < FragSize)
        {
            Sleep(1);
            continue;
        }
        avail -= avail%FragSize;

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

        // If the buffer is lost, restore it, play and lock
        if(err == DSERR_BUFFERLOST)
        {
            err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
            if(SUCCEEDED(err))
                err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
            if(SUCCEEDED(err))
                err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &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(pDevice, WritePtr1, WriteCnt1/FrameSize);
            aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize);

            // Unlock output buffer only when successfully locked
            IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
        }
        else
            AL_PRINT("Buffer lock error: %#lx\n", err);

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

    return 0;
}
Example #26
0
static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
{
    qsa_data* data=(qsa_data*)device->ExtraData;
    char* read_ptr;
    snd_pcm_channel_status_t status;
    fd_set rfds;
    int selectret;
    struct timeval timeout;
    int bytes_read;
    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
    ALint len=samples*frame_size;
    int rstatus;

    read_ptr=buffer;

    while (len>0)
    {
        FD_ZERO(&rfds);
        FD_SET(data->audio_fd, &rfds);
        timeout.tv_sec=2;
        timeout.tv_usec=0;

        /* Select also works like time slice to OS */
        bytes_read=0;
        selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout);
        switch (selectret)
        {
            case -1:
                 aluHandleDisconnect(device);
                 return ALC_INVALID_DEVICE;
            case 0:
                 break;
            default:
                 if (FD_ISSET(data->audio_fd, &rfds))
                 {
                     bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len);
                     break;
                 }
                 break;
        }

        if (bytes_read<=0)
        {
            if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
            {
                continue;
            }

            memset(&status, 0, sizeof (status));
            status.channel=SND_PCM_CHANNEL_CAPTURE;
            snd_pcm_plugin_status(data->pcmHandle, &status);

            /* we need to reinitialize the sound channel if we've overrun the buffer */
            if ((status.status==SND_PCM_STATUS_OVERRUN) ||
                (status.status==SND_PCM_STATUS_READY))
            {
                if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
                {
                    ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
                    aluHandleDisconnect(device);
                    return ALC_INVALID_DEVICE;
                }
                snd_pcm_capture_go(data->pcmHandle);
            }
        }
        else
        {
            read_ptr+=bytes_read;
            len-=bytes_read;
        }
    }

    return ALC_NO_ERROR;
}
Example #27
0
FORCE_ALIGN static int qsa_proc_playback(void* ptr)
{
    ALCdevice* device=(ALCdevice*)ptr;
    qsa_data* data=(qsa_data*)device->ExtraData;
    char* write_ptr;
    int avail;
    snd_pcm_channel_status_t status;
    struct sched_param param;
    fd_set wfds;
    int selectret;
    struct timeval timeout;

    SetRTPriority();
    althrd_setname(althrd_current(), MIXER_THREAD_NAME);

    /* Increase default 10 priority to 11 to avoid jerky sound */
    SchedGet(0, 0, &param);
    param.sched_priority=param.sched_curpriority+1;
    SchedSet(0, 0, SCHED_NOCHANGE, &param);

    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);

    while (!data->killNow)
    {
        ALint len=data->size;
        write_ptr=data->buffer;

        avail=len/frame_size;
        aluMixData(device, write_ptr, avail);

        while (len>0 && !data->killNow)
        {
            FD_ZERO(&wfds);
            FD_SET(data->audio_fd, &wfds);
            timeout.tv_sec=2;
            timeout.tv_usec=0;

            /* Select also works like time slice to OS */
            selectret=select(data->audio_fd+1, NULL, &wfds, NULL, &timeout);
            switch (selectret)
            {
                case -1:
                     aluHandleDisconnect(device);
                     return 1;
                case 0:
                     break;
                default:
                     if (FD_ISSET(data->audio_fd, &wfds))
                     {
                         break;
                     }
                     break;
            }

            int wrote=snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);

            if (wrote<=0)
            {
                if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
                {
                    continue;
                }

                memset(&status, 0, sizeof (status));
                status.channel=SND_PCM_CHANNEL_PLAYBACK;

                snd_pcm_plugin_status(data->pcmHandle, &status);

                /* we need to reinitialize the sound channel if we've underrun the buffer */
                if ((status.status==SND_PCM_STATUS_UNDERRUN) ||
                    (status.status==SND_PCM_STATUS_READY))
                {
                    if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
                    {
                        aluHandleDisconnect(device);
                        break;
                    }
                }
            }
            else
            {
                write_ptr+=wrote;
                len-=wrote;
            }
        }
    }

    return 0;
}
static ALuint WaveProc( ALvoid* ptr )
{
	ALCdevice* pDevice = ( ALCdevice* )ptr;
	wave_data* data = ( wave_data* )pDevice->ExtraData;
	ALuint frameSize;
	ALuint now, last;
	size_t fs;
	ALuint avail;
	union
	{
		short s;
		char b[sizeof( short )];
	} uSB;

	uSB.s = 1;
	frameSize = aluFrameSizeFromFormat( pDevice->Format );

	last = timeGetTime() << 8;

	while ( !data->killNow && pDevice->Connected )
	{
		now = timeGetTime() << 8;

		avail = ( ALuint64 )( now - last ) * pDevice->Frequency / ( 1000 << 8 );

		if ( avail < pDevice->UpdateSize )
		{
			Sleep( 1 );
			continue;
		}

		while ( avail >= pDevice->UpdateSize )
		{
			aluMixData( pDevice, data->buffer, pDevice->UpdateSize );

			if ( uSB.b[0] != 1 )
			{
				ALubyte* bytes = data->buffer;
				ALuint i;

				if ( aluBytesFromFormat( pDevice->Format ) == 1 )
				{
					for ( i = 0; i < data->size; i++ )
					{
						fputc( bytes[i], data->f );
					}
				}
				else if ( aluBytesFromFormat( pDevice->Format ) == 2 )
				{
					for ( i = 0; i < data->size; i++ )
					{
						fputc( bytes[i ^ 1], data->f );
					}
				}
				else if ( aluBytesFromFormat( pDevice->Format ) == 4 )
				{
					for ( i = 0; i < data->size; i++ )
					{
						fputc( bytes[i ^ 3], data->f );
					}
				}
			}
			else
				fs = fwrite( data->buffer, frameSize, pDevice->UpdateSize,
				             data->f );

			if ( ferror( data->f ) )
			{
				AL_PRINT( "Error writing to file\n" );
				aluHandleDisconnect( pDevice );
				break;
			}

			avail -= pDevice->UpdateSize;
			last += ( ALuint64 )pDevice->UpdateSize * ( 1000 << 8 ) / pDevice->Frequency;
		}
	}

	return 0;
}
Example #29
0
static ALCenum alsa_capture_samples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
{
    alsa_data *data = (alsa_data*)Device->ExtraData;

    if(data->ring)
    {
        ReadRingBuffer(data->ring, Buffer, Samples);
        return ALC_NO_ERROR;
    }

    data->last_avail -= Samples;
    while(Device->Connected && Samples > 0)
    {
        snd_pcm_sframes_t amt = 0;

        if(data->size > 0)
        {
            /* First get any data stored from the last stop */
            amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
            if((snd_pcm_uframes_t)amt > Samples) amt = Samples;

            amt = snd_pcm_frames_to_bytes(data->pcmHandle, amt);
            memmove(Buffer, data->buffer, amt);

            if(data->size > amt)
            {
                memmove(data->buffer, data->buffer+amt, data->size - amt);
                data->size -= amt;
            }
            else
            {
                free(data->buffer);
                data->buffer = NULL;
                data->size = 0;
            }
            amt = snd_pcm_bytes_to_frames(data->pcmHandle, amt);
        }
        else if(data->doCapture)
            amt = snd_pcm_readi(data->pcmHandle, Buffer, Samples);
        if(amt < 0)
        {
            ERR("read error: %s\n", snd_strerror(amt));

            if(amt == -EAGAIN)
                continue;
            if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0)
            {
                amt = snd_pcm_start(data->pcmHandle);
                if(amt >= 0)
                    amt = snd_pcm_avail_update(data->pcmHandle);
            }
            if(amt < 0)
            {
                ERR("restore error: %s\n", snd_strerror(amt));
                aluHandleDisconnect(Device);
                break;
            }
            /* If the amount available is less than what's asked, we lost it
             * during recovery. So just give silence instead. */
            if((snd_pcm_uframes_t)amt < Samples)
                break;
            continue;
        }

        Buffer = (ALbyte*)Buffer + amt;
        Samples -= amt;
    }
    if(Samples > 0)
        memset(Buffer, ((Device->FmtType == DevFmtUByte) ? 0x80 : 0),
               snd_pcm_frames_to_bytes(data->pcmHandle, Samples));

    return ALC_NO_ERROR;
}
Example #30
0
static ALuint WaveProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    wave_data *data = (wave_data*)pDevice->ExtraData;
    ALuint frameSize;
    ALuint now, start;
    ALuint64 avail, done;
    size_t fs;
    union {
        short s;
        char b[sizeof(short)];
    } uSB;
    const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
                            pDevice->Frequency / 2;

    uSB.s = 1;
    frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);

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

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

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

            if(uSB.b[0] != 1)
            {
                ALuint bytesize = BytesFromDevFmt(pDevice->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, pDevice->UpdateSize,
                            data->f);
            if(ferror(data->f))
            {
                AL_PRINT("Error writing to file\n");
                aluHandleDisconnect(pDevice);
                break;
            }
        }
    }

    return 0;
}