Пример #1
0
static ALuint OSSCaptureProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    oss_data *data = (oss_data*)pDevice->ExtraData;
    int frameSize;
    int amt;

    SetRTPriority();

    frameSize = aluFrameSizeFromFormat(pDevice->Format);

    while(!data->killNow)
    {
        amt = read(data->fd, data->mix_data, data->data_size);
        if(amt < 0)
        {
            AL_PRINT("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;
}
Пример #2
0
static void* thread_function(void* arg)
{
    ALCdevice* device = (ALCdevice*)arg;
    AndroidData* data = (AndroidData*)device->ExtraData;

    JNIEnv* env;
    (*javaVM)->AttachCurrentThread(javaVM, &env, NULL);

    (*env)->PushLocalFrame(env, 2);

    int sampleRateInHz = device->Frequency;
    int channelConfig = aluChannelsFromFormat(device->Format) == 1 ? CHANNEL_CONFIGURATION_MONO : CHANNEL_CONFIGURATION_STEREO;
    int audioFormat = aluBytesFromFormat(device->Format) == 1 ? ENCODING_PCM_8BIT : ENCODING_PCM_16BIT;

    int bufferSizeInBytes = (*env)->CallStaticIntMethod(env, cAudioTrack, 
        mGetMinBufferSize, sampleRateInHz, channelConfig, audioFormat) / 4;

    int bufferSizeInSamples = bufferSizeInBytes / aluFrameSizeFromFormat(device->Format);

    jobject track = (*env)->NewObject(env, cAudioTrack, mAudioTrack,
        STREAM_MUSIC, sampleRateInHz, channelConfig, audioFormat, device->NumUpdates * bufferSizeInBytes, MODE_STREAM);

    (*env)->CallNonvirtualVoidMethod(env, track, cAudioTrack, mPlay);

    jarray buffer = (*env)->NewByteArray(env, bufferSizeInBytes);

    while (data->running)
    {
        void* pBuffer = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL);

        if (pBuffer)
        {
            aluMixData(device, pBuffer, bufferSizeInSamples);
            (*env)->ReleasePrimitiveArrayCritical(env, buffer, pBuffer, 0);

            (*env)->CallNonvirtualIntMethod(env, track, cAudioTrack, mWrite, buffer, 0, bufferSizeInBytes);
        }
        else
        {
            AL_PRINT("Failed to get pointer to array bytes");
        }
    }
    
    (*env)->CallNonvirtualVoidMethod(env, track, cAudioTrack, mStop);
    (*env)->CallNonvirtualVoidMethod(env, track, cAudioTrack, mRelease);

    (*env)->PopLocalFrame(env, NULL);

    (*javaVM)->DetachCurrentThread(javaVM);
    return NULL;
}
Пример #3
0
AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* plValues)
{
    ALCcontext    *pContext;
    ALCdevice     *device;
    ALbuffer      *ALBuf;

    pContext = GetContextSuspended();
    if(!pContext) return;

    device = pContext->Device;
    if(!plValues)
        alSetError(pContext, AL_INVALID_VALUE);
    else if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL)
        alSetError(pContext, AL_INVALID_NAME);
    else
    {
        switch(eParam)
        {
        case AL_LOOP_POINTS:
            if(ALBuf->refcount > 0)
                alSetError(pContext, AL_INVALID_OPERATION);
            else if(plValues[0] < 0 || plValues[1] < 0 ||
                    plValues[0] >= plValues[1] || ALBuf->size == 0)
                alSetError(pContext, AL_INVALID_VALUE);
            else
            {
                ALint maxlen = ALBuf->size / aluFrameSizeFromFormat(ALBuf->format);
                if(plValues[0] > maxlen || plValues[1] > maxlen)
                    alSetError(pContext, AL_INVALID_VALUE);
                else
                {
                    ALBuf->LoopStart = plValues[0];
                    ALBuf->LoopEnd = plValues[1];
                }
            }
            break;

        default:
            alSetError(pContext, AL_INVALID_ENUM);
            break;
        }
    }

    ProcessContext(pContext);
}
Пример #4
0
static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
{
    WinMMData *pData = (WinMMData*)pDevice->ExtraData;
    ALuint ulSamples = (unsigned long)lSamples;
    ALuint ulBytes, ulBytesToCopy;
    ALuint ulCapturedSamples;
    ALuint ulReadOffset;
    ALuint frameSize = aluFrameSizeFromFormat(pDevice->Format);

    // Check that we have the requested numbers of Samples
    ulCapturedSamples = (pData->ulWriteCapturedDataPos -
                         pData->ulReadCapturedDataPos) /
                        frameSize;
    if(ulSamples > ulCapturedSamples)
    {
        alcSetError(pDevice, ALC_INVALID_VALUE);
        return;
    }

    ulBytes = ulSamples * frameSize;

    // Get Read Offset
    ulReadOffset = (pData->ulReadCapturedDataPos % pData->ulCapturedDataSize);

    // Check for wrap-around condition
    if ((ulReadOffset + ulBytes) > pData->ulCapturedDataSize)
    {
        // Copy data from last Read position to end of data
        ulBytesToCopy = pData->ulCapturedDataSize - ulReadOffset;
        memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytesToCopy);

        // Copy rest of the data from the start of the captured data
        memcpy(((char *)pBuffer) + ulBytesToCopy, pData->pCapturedSampleData, ulBytes - ulBytesToCopy);
    }
    else
    {
        // Copy data from the read position in the captured data
        memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytes);
    }

    // Update Read Position
    pData->ulReadCapturedDataPos += ulBytes;
}
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;
}
Пример #6
0
static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
{
    snd_pcm_hw_params_t *p;
    snd_pcm_uframes_t bufferSizeInFrames;
    snd_pcm_format_t format;
    ALuint frameSize;
    alsa_data *data;
    char driver[64];
    char *err;
    int i;

    if(!alsa_load())
        return ALC_FALSE;

    strncpy(driver, GetConfigValue("alsa", "capture", "default"), sizeof(driver)-1);
    driver[sizeof(driver)-1] = 0;

    if(!allCaptureDevNameMap)
        allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames);

    if(!deviceName)
        deviceName = allCaptureDevNameMap[0].name;
    else
    {
        size_t idx;

        for(idx = 0;idx < numCaptureDevNames;idx++)
        {
            if(allCaptureDevNameMap[idx].name &&
               strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0)
            {
                if(idx > 0)
                    sprintf(driver, "plughw:%d,%d", allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev);
                break;
            }
        }
        if(idx == numCaptureDevNames)
            return ALC_FALSE;
    }

    data = (alsa_data*)calloc(1, sizeof(alsa_data));

    i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
    if(i < 0)
    {
        Sleep(200);
        i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
    }
    if(i < 0)
    {
        AL_PRINT("Could not open capture device '%s': %s\n", driver, psnd_strerror(i));
        free(data);
        return ALC_FALSE;
    }

    switch(aluBytesFromFormat(pDevice->Format))
    {
        case 1:
            format = SND_PCM_FORMAT_U8;
            break;
        case 2:
            format = SND_PCM_FORMAT_S16;
            break;
        case 4:
            format = SND_PCM_FORMAT_FLOAT;
            break;
        default:
            AL_PRINT("Unknown format: 0x%x\n", pDevice->Format);
            goto error;
    }

    err = NULL;
    bufferSizeInFrames = pDevice->UpdateSize * pDevice->NumUpdates;
    psnd_pcm_hw_params_malloc(&p);

    if((i=psnd_pcm_hw_params_any(data->pcmHandle, p)) < 0)
        err = "any";
    /* set interleaved access */
    if(i >= 0 && (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
        err = "set access";
    /* set format (implicitly sets sample bits) */
    if(i >= 0 && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0)
        err = "set format";
    /* set channels (implicitly sets frame bits) */
    if(i >= 0 && (i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(pDevice->Format))) < 0)
        err = "set channels";
    /* set rate (implicitly constrains period/buffer parameters) */
    if(i >= 0 && (i=psnd_pcm_hw_params_set_rate(data->pcmHandle, p, pDevice->Frequency, 0)) < 0)
        err = "set rate near";
    /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
    if(i >= 0 && (i=psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0)
        err = "set buffer size near";
    /* install and prepare hardware configuration */
    if(i >= 0 && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
        err = "set params";
    if(i < 0)
    {
        AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
        psnd_pcm_hw_params_free(p);
        goto error;
    }

    if((i=psnd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0)
    {
        AL_PRINT("get size failed: %s\n", psnd_strerror(i));
        psnd_pcm_hw_params_free(p);
        goto error;
    }

    psnd_pcm_hw_params_free(p);

    frameSize = aluFrameSizeFromFormat(pDevice->Format);

    data->ring = CreateRingBuffer(frameSize, pDevice->UpdateSize*pDevice->NumUpdates);
    if(!data->ring)
    {
        AL_PRINT("ring buffer create failed\n");
        goto error;
    }

    data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames);
    data->buffer = malloc(data->size);
    if(!data->buffer)
    {
        AL_PRINT("buffer malloc failed\n");
        goto error;
    }

    pDevice->szDeviceName = strdup(deviceName);

    pDevice->ExtraData = data;
    return ALC_TRUE;

error:
    free(data->buffer);
    DestroyRingBuffer(data->ring);
    psnd_pcm_close(data->pcmHandle);
    free(data);

    pDevice->ExtraData = NULL;
    return ALC_FALSE;
}
static ALCboolean pulse_reset_playback( ALCdevice* device ) //{{{
{
	pulse_data* data = device->ExtraData;
	pa_stream_flags_t flags = 0;
	pa_channel_map chanmap;

	ppa_threaded_mainloop_lock( data->loop );

	if ( !ConfigValueExists( NULL, "format" ) )
	{
		pa_operation* o;
		o = ppa_context_get_sink_info_by_name( data->context, data->device_name, sink_info_callback, device );

		while ( ppa_operation_get_state( o ) == PA_OPERATION_RUNNING )
		{
			ppa_threaded_mainloop_wait( data->loop );
		}

		ppa_operation_unref( o );
	}

	if ( !ConfigValueExists( NULL, "frequency" ) )
	{
		flags |= PA_STREAM_FIX_RATE;
	}

	data->frame_size = aluFrameSizeFromFormat( device->Format );
	data->attr.minreq = -1;
	data->attr.prebuf = -1;
	data->attr.fragsize = -1;
	data->attr.tlength = device->UpdateSize * device->NumUpdates *
	                     data->frame_size;
	data->attr.maxlength = data->attr.tlength;

	switch ( aluBytesFromFormat( device->Format ) )
	{
		case 1:
			data->spec.format = PA_SAMPLE_U8;
			break;

		case 2:
			data->spec.format = PA_SAMPLE_S16NE;
			break;

		case 4:
			data->spec.format = PA_SAMPLE_FLOAT32NE;
			break;

		default:
			AL_PRINT( "Unknown format: 0x%x\n", device->Format );
			ppa_threaded_mainloop_unlock( data->loop );
			return ALC_FALSE;
	}

	data->spec.rate = device->Frequency;
	data->spec.channels = aluChannelsFromFormat( device->Format );

	if ( ppa_sample_spec_valid( &data->spec ) == 0 )
	{
		AL_PRINT( "Invalid sample format\n" );
		ppa_threaded_mainloop_unlock( data->loop );
		return ALC_FALSE;
	}

	if ( !ppa_channel_map_init_auto( &chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX ) )
	{
		AL_PRINT( "Couldn't build map for channel count (%d)!\n", data->spec.channels );
		ppa_threaded_mainloop_unlock( data->loop );
		return ALC_FALSE;
	}

	SetDefaultWFXChannelOrder( device );

	data->stream = connect_playback_stream( device, flags, &data->attr, &data->spec, &chanmap );

	if ( !data->stream )
	{
		ppa_threaded_mainloop_unlock( data->loop );
		return ALC_FALSE;
	}

	ppa_stream_set_state_callback( data->stream, stream_state_callback2, device );

	data->spec = *( ppa_stream_get_sample_spec( data->stream ) );

	if ( device->Frequency != data->spec.rate )
	{
		pa_operation* o;

		/* Server updated our playback rate, so modify the buffer attribs
		 * accordingly. */
		data->attr.tlength = ( ALuint64 )( data->attr.tlength / data->frame_size ) *
		                     data->spec.rate / device->Frequency * data->frame_size;
		data->attr.maxlength = data->attr.tlength;

		o = ppa_stream_set_buffer_attr( data->stream, &data->attr,
		                                stream_success_callback, device );

		while ( ppa_operation_get_state( o ) == PA_OPERATION_RUNNING )
		{
			ppa_threaded_mainloop_wait( data->loop );
		}

		ppa_operation_unref( o );

		device->Frequency = data->spec.rate;
	}

	stream_buffer_attr_callback( data->stream, device );
#if PA_CHECK_VERSION(0,9,15)

	if ( ppa_stream_set_buffer_attr_callback )
	{
		ppa_stream_set_buffer_attr_callback( data->stream, stream_buffer_attr_callback, device );
	}

#endif
	ppa_stream_set_moved_callback( data->stream, stream_device_callback, device );

	stream_write_callback( data->stream, data->attr.tlength, device );
	ppa_stream_set_write_callback( data->stream, stream_write_callback, device );

	ppa_threaded_mainloop_unlock( data->loop );
	return ALC_TRUE;
} //}}}
static ALCboolean pulse_open_capture( ALCdevice* device, const ALCchar* device_name ) //{{{
{
	char* pulse_name = NULL;
	pulse_data* data;
	pa_stream_flags_t flags = 0;
	pa_stream_state_t state;
	pa_channel_map chanmap;

	if ( !pulse_load() )
	{
		return ALC_FALSE;
	}

	if ( !allCaptureDevNameMap )
	{
		probe_devices( AL_TRUE );
	}

	if ( !device_name )
	{
		device_name = allCaptureDevNameMap[0].name;
	}
	else
	{
		ALuint i;

		for ( i = 0; i < numCaptureDevNames; i++ )
		{
			if ( strcmp( device_name, allCaptureDevNameMap[i].name ) == 0 )
			{
				pulse_name = allCaptureDevNameMap[i].device_name;
				break;
			}
		}

		if ( i == numCaptureDevNames )
		{
			return ALC_FALSE;
		}
	}

	if ( pulse_open( device, device_name ) == ALC_FALSE )
	{
		return ALC_FALSE;
	}

	data = device->ExtraData;
	ppa_threaded_mainloop_lock( data->loop );

	data->samples = device->UpdateSize * device->NumUpdates;
	data->frame_size = aluFrameSizeFromFormat( device->Format );

	if ( !( data->ring = CreateRingBuffer( data->frame_size, data->samples ) ) )
	{
		ppa_threaded_mainloop_unlock( data->loop );
		goto fail;
	}

	data->attr.minreq = -1;
	data->attr.prebuf = -1;
	data->attr.maxlength = data->frame_size * data->samples;
	data->attr.tlength = -1;
	data->attr.fragsize = min( data->frame_size * data->samples,
	                           10 * device->Frequency / 1000 );

	data->spec.rate = device->Frequency;
	data->spec.channels = aluChannelsFromFormat( device->Format );

	switch ( aluBytesFromFormat( device->Format ) )
	{
		case 1:
			data->spec.format = PA_SAMPLE_U8;
			break;

		case 2:
			data->spec.format = PA_SAMPLE_S16NE;
			break;

		case 4:
			data->spec.format = PA_SAMPLE_FLOAT32NE;
			break;

		default:
			AL_PRINT( "Unknown format: 0x%x\n", device->Format );
			ppa_threaded_mainloop_unlock( data->loop );
			goto fail;
	}

	if ( ppa_sample_spec_valid( &data->spec ) == 0 )
	{
		AL_PRINT( "Invalid sample format\n" );
		ppa_threaded_mainloop_unlock( data->loop );
		goto fail;
	}

	if ( !ppa_channel_map_init_auto( &chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX ) )
	{
		AL_PRINT( "Couldn't build map for channel count (%d)!\n", data->spec.channels );
		ppa_threaded_mainloop_unlock( data->loop );
		goto fail;
	}

	data->stream = ppa_stream_new( data->context, "Capture Stream", &data->spec, &chanmap );

	if ( !data->stream )
	{
		AL_PRINT( "pa_stream_new() failed: %s\n",
		          ppa_strerror( ppa_context_errno( data->context ) ) );

		ppa_threaded_mainloop_unlock( data->loop );
		goto fail;
	}

	ppa_stream_set_state_callback( data->stream, stream_state_callback, data->loop );

	flags |= PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY;

	if ( ppa_stream_connect_record( data->stream, pulse_name, &data->attr, flags ) < 0 )
	{
		AL_PRINT( "Stream did not connect: %s\n",
		          ppa_strerror( ppa_context_errno( data->context ) ) );

		ppa_stream_unref( data->stream );
		data->stream = NULL;

		ppa_threaded_mainloop_unlock( data->loop );
		goto fail;
	}

	while ( ( state = ppa_stream_get_state( data->stream ) ) != PA_STREAM_READY )
	{
		if ( !PA_STREAM_IS_GOOD( state ) )
		{
			AL_PRINT( "Stream did not get ready: %s\n",
			          ppa_strerror( ppa_context_errno( data->context ) ) );

			ppa_stream_unref( data->stream );
			data->stream = NULL;

			ppa_threaded_mainloop_unlock( data->loop );
			goto fail;
		}

		ppa_threaded_mainloop_wait( data->loop );
	}

	ppa_stream_set_state_callback( data->stream, stream_state_callback2, device );

	ppa_threaded_mainloop_unlock( data->loop );
	return ALC_TRUE;

fail:
	pulse_close( device );
	return ALC_FALSE;
} //}}}
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;
}
Пример #10
0
static ALCboolean DSoundResetPlayback(ALCdevice *device)
{
    DSoundData *pData = (DSoundData*)device->ExtraData;
    DSBUFFERDESC DSBDescription;
    WAVEFORMATEXTENSIBLE OutputType;
    DWORD frameSize = 0;
    ALenum format = 0;
    DWORD speakers;
    HRESULT hr;

    memset(&OutputType, 0, sizeof(OutputType));

    hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
    if(SUCCEEDED(hr) && ConfigValueExists(NULL, "format"))
    {
        if(aluChannelsFromFormat(device->Format) == 1)
            speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
        else if(aluChannelsFromFormat(device->Format) == 2)
            speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0);
        else if(aluChannelsFromFormat(device->Format) == 4)
            speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0);
        else if(aluChannelsFromFormat(device->Format) == 6)
            speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0);
        else if(aluChannelsFromFormat(device->Format) == 8)
            speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0);
        else
        {
            AL_PRINT("Unknown format: 0x%x\n", device->Format);
            return ALC_FALSE;
        }
    }
    if(SUCCEEDED(hr))
    {
        speakers = DSSPEAKER_CONFIG(speakers);
        if(speakers == DSSPEAKER_MONO)
        {
            if(aluBytesFromFormat(device->Format) == 1)
                format = AL_FORMAT_MONO8;
            else if(aluBytesFromFormat(device->Format) == 2)
                format = AL_FORMAT_MONO16;
            else if(aluBytesFromFormat(device->Format) == 4)
                format = AL_FORMAT_MONO_FLOAT32;
            OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
        }
        else if(speakers == DSSPEAKER_STEREO)
        {
            if(aluBytesFromFormat(device->Format) == 1)
                format = AL_FORMAT_STEREO8;
            else if(aluBytesFromFormat(device->Format) == 2)
                format = AL_FORMAT_STEREO16;
            else if(aluBytesFromFormat(device->Format) == 4)
                format = AL_FORMAT_STEREO_FLOAT32;
            OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                       SPEAKER_FRONT_RIGHT;
        }
        else if(speakers == DSSPEAKER_QUAD)
        {
            if(aluBytesFromFormat(device->Format) == 1)
                format = AL_FORMAT_QUAD8;
            else if(aluBytesFromFormat(device->Format) == 2)
                format = AL_FORMAT_QUAD16;
            else if(aluBytesFromFormat(device->Format) == 4)
                format = AL_FORMAT_QUAD32;
            OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                       SPEAKER_FRONT_RIGHT |
                                       SPEAKER_BACK_LEFT |
                                       SPEAKER_BACK_RIGHT;
        }
        else if(speakers == DSSPEAKER_5POINT1)
        {
            if(aluBytesFromFormat(device->Format) == 1)
                format = AL_FORMAT_51CHN8;
            else if(aluBytesFromFormat(device->Format) == 2)
                format = AL_FORMAT_51CHN16;
            else if(aluBytesFromFormat(device->Format) == 4)
                format = AL_FORMAT_51CHN32;
            OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                       SPEAKER_FRONT_RIGHT |
                                       SPEAKER_FRONT_CENTER |
                                       SPEAKER_LOW_FREQUENCY |
                                       SPEAKER_BACK_LEFT |
                                       SPEAKER_BACK_RIGHT;
        }
        else if(speakers == DSSPEAKER_7POINT1)
        {
            if(aluBytesFromFormat(device->Format) == 1)
                format = AL_FORMAT_71CHN8;
            else if(aluBytesFromFormat(device->Format) == 2)
                format = AL_FORMAT_71CHN16;
            else if(aluBytesFromFormat(device->Format) == 4)
                format = AL_FORMAT_71CHN32;
            OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                       SPEAKER_FRONT_RIGHT |
                                       SPEAKER_FRONT_CENTER |
                                       SPEAKER_LOW_FREQUENCY |
                                       SPEAKER_BACK_LEFT |
                                       SPEAKER_BACK_RIGHT |
                                       SPEAKER_SIDE_LEFT |
                                       SPEAKER_SIDE_RIGHT;
        }
        else
            format = device->Format;
        frameSize = aluFrameSizeFromFormat(format);

        OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
        OutputType.Format.nChannels = aluChannelsFromFormat(format);
        OutputType.Format.wBitsPerSample = aluBytesFromFormat(format) * 8;
        OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
        OutputType.Format.nSamplesPerSec = device->Frequency;
        OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign;
        OutputType.Format.cbSize = 0;
    }

    if(OutputType.Format.nChannels > 2 || OutputType.Format.wBitsPerSample > 16)
    {
        OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
        OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
        OutputType.Format.cbSize = 22;
        if(OutputType.Format.wBitsPerSample == 32)
            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
        else
            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
    }
    else
    {
        if(SUCCEEDED(hr))
        {
            memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
            DSBDescription.dwSize=sizeof(DSBUFFERDESC);
            DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
            hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL);
        }
        if(SUCCEEDED(hr))
            hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format);
    }

    if(SUCCEEDED(hr))
    {
        memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
        DSBDescription.dwSize=sizeof(DSBUFFERDESC);
        DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
        DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * frameSize;
        DSBDescription.lpwfxFormat=&OutputType.Format;
        hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
    }

    if(SUCCEEDED(hr))
        hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);

    if(SUCCEEDED(hr))
    {
        device->Format = format;
        SetDefaultWFXChannelOrder(device);
        pData->thread = StartThread(DSoundProc, device);
        if(!pData->thread)
            hr = E_FAIL;
    }

    if(FAILED(hr))
    {
        if (pData->DSsbuffer)
            IDirectSoundBuffer_Release(pData->DSsbuffer);
        pData->DSsbuffer = NULL;
        if (pData->DSpbuffer)
            IDirectSoundBuffer_Release(pData->DSpbuffer);
        pData->DSpbuffer = NULL;
        return ALC_FALSE;
    }

    return ALC_TRUE;
}
Пример #11
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;
}
Пример #12
0
static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
    PaStreamParameters inParams;
    ALuint frame_size;
    pa_data *data;
    PaError err;

    if(!deviceName)
        deviceName = pa_device;
    else if(strcmp(deviceName, pa_device) != 0)
        return ALC_FALSE;

    if(!pa_load())
        return ALC_FALSE;

    data = (pa_data*)calloc(1, sizeof(pa_data));
    if(data == NULL)
    {
        alcSetError(device, ALC_OUT_OF_MEMORY);
        return ALC_FALSE;
    }

    frame_size = aluFrameSizeFromFormat(device->Format);
    data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
    if(data->ring == NULL)
    {
        alcSetError(device, ALC_OUT_OF_MEMORY);
        goto error;
    }

    inParams.device = GetConfigValueInt("port", "capture", -1);
    if(inParams.device < 0)
        inParams.device = pPa_GetDefaultOutputDevice();
    inParams.suggestedLatency = 0.0f;
    inParams.hostApiSpecificStreamInfo = NULL;

    switch(aluBytesFromFormat(device->Format))
    {
        case 1:
            inParams.sampleFormat = paUInt8;
            break;
        case 2:
            inParams.sampleFormat = paInt16;
            break;
        case 4:
            inParams.sampleFormat = paFloat32;
            break;
        default:
            AL_PRINT("Unknown format: 0x%x\n", device->Format);
            goto error;
    }
    inParams.channelCount = aluChannelsFromFormat(device->Format);

    err = pPa_OpenStream(&data->stream, &inParams, NULL, device->Frequency,
                         paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
    if(err != paNoError)
    {
        AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
        goto error;
    }

    device->szDeviceName = strdup(deviceName);

    device->ExtraData = data;
    return ALC_TRUE;

error:
    DestroyRingBuffer(data->ring);
    free(data);
    return ALC_FALSE;
}
Пример #13
0
static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
{
    WinMMData *pData = (WinMMData*)pDevice->ExtraData;
    ALCuint lCapturedBytes = (pData->ulWriteCapturedDataPos - pData->ulReadCapturedDataPos);
    return lCapturedBytes / aluFrameSizeFromFormat(pDevice->Format);
}