Exemple #1
0
static int
rdpsnd_alsa_play(rdpsndDevicePlugin * devplugin, char * data, int size)
{
	struct alsa_device_data * alsa_data;
	uint8 * decoded_data;
	int decoded_size;
	char * src;
	uint8 * resampled_data;
	int len;
	int error;
	int frames;
	int rbytes_per_frame;
	int sbytes_per_frame;
	char * pindex;
	char * end;

	alsa_data = (struct alsa_device_data *) devplugin->device_data;
	if (alsa_data->out_handle == 0)
	{
		return 0;
	}

	if (alsa_data->wformat == 0x11)
	{
		decoded_data = alsa_data->pDecodeImaAdpcm(&alsa_data->adpcm,
			(uint8 *) data, size, alsa_data->source_channels, alsa_data->block_size, &decoded_size);
		size = decoded_size;
		src = (char *) decoded_data;
	}
	else
	{
		decoded_data = NULL;
		src = data;
	}

	LLOGLN(10, ("rdpsnd_alsa_play: size %d", size));

	sbytes_per_frame = alsa_data->source_channels * alsa_data->bytes_per_channel;
	rbytes_per_frame = alsa_data->actual_channels * alsa_data->bytes_per_channel;
	if ((size % sbytes_per_frame) != 0)
	{
		LLOGLN(0, ("rdpsnd_alsa_play: error len mod"));
		return 1;
	}

	if ((alsa_data->source_rate == alsa_data->actual_rate) &&
		(alsa_data->source_channels == alsa_data->actual_channels))
	{
		resampled_data = NULL;
	}
	else
	{
		resampled_data = alsa_data->pResample((uint8 *) src, alsa_data->bytes_per_channel,
			alsa_data->source_channels, alsa_data->source_rate, size / sbytes_per_frame,
			alsa_data->actual_channels, alsa_data->actual_rate, &frames);
		LLOGLN(10, ("rdpsnd_alsa_play: resampled %d frames at %d to %d frames at %d",
			size / sbytes_per_frame, alsa_data->source_rate, frames, alsa_data->actual_rate));
		size = frames * rbytes_per_frame;
		src = (char *) resampled_data;
	}

	pindex = src;
	end = pindex + size;
	while (pindex < end)
	{
		len = end - pindex;
		frames = len / rbytes_per_frame;
		error = snd_pcm_writei(alsa_data->out_handle, pindex, frames);
		if (error == -EPIPE)
		{
			LLOGLN(0, ("rdpsnd_alsa_play: underrun occurred"));
			snd_pcm_recover(alsa_data->out_handle, error, 0);
			error = 0;
		}
		else if (error < 0)
		{
			LLOGLN(0, ("rdpsnd_alsa_play: error len %d", error));
			snd_pcm_close(alsa_data->out_handle);
			alsa_data->out_handle = 0;
			rdpsnd_alsa_open(devplugin);
			break;
		}
		pindex += error * rbytes_per_frame;
	}

	if (resampled_data)
		free(resampled_data);
	if (decoded_data)
		free(decoded_data);

	return 0;
}
Exemple #2
0
static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size)
{
    rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device;
    uint8* decoded_data;
    int decoded_size;
    uint8* src;
    uint8* resampled_data;
    int len;
    int error;
    int frames;
    int rbytes_per_frame;
    int sbytes_per_frame;
    uint8* pindex;
    uint8* end;

    if (alsa->out_handle == 0)
        return;

    if (alsa->wformat == 0x11)
    {
        decoded_data = dsp_decode_ima_adpcm(&alsa->adpcm,
                                            data, size, alsa->source_channels, alsa->block_size, &decoded_size);
        size = decoded_size;
        src = decoded_data;
    }
    else
    {
        decoded_data = NULL;
        src = data;
    }

    sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel;
    rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
    if ((size % sbytes_per_frame) != 0)
    {
        DEBUG_WARN("error len mod");
        return;
    }

    if ((alsa->source_rate == alsa->actual_rate) &&
            (alsa->source_channels == alsa->actual_channels))
    {
        resampled_data = NULL;
    }
    else
    {
        resampled_data = dsp_resample(src, alsa->bytes_per_channel,
                                      alsa->source_channels, alsa->source_rate, size / sbytes_per_frame,
                                      alsa->actual_channels, alsa->actual_rate, &frames);
        DEBUG_SVC("resampled %d frames at %d to %d frames at %d",
                  size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
        size = frames * rbytes_per_frame;
        src = resampled_data;
    }

    pindex = src;
    end = pindex + size;
    while (pindex < end)
    {
        len = end - pindex;
        frames = len / rbytes_per_frame;
        error = snd_pcm_writei(alsa->out_handle, pindex, frames);
        if (error == -EPIPE)
        {
            snd_pcm_recover(alsa->out_handle, error, 0);
            error = 0;
        }
        else if (error < 0)
        {
            DEBUG_WARN("error %d", error);
            snd_pcm_close(alsa->out_handle);
            alsa->out_handle = 0;
            rdpsnd_alsa_open(device, NULL, alsa->latency);
            break;
        }
        pindex += error * rbytes_per_frame;
    }

    if (resampled_data)
        xfree(resampled_data);
    if (decoded_data)
        xfree(decoded_data);
}