Blame libfreerdp/codec/audio.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Audio Formats
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#include <freerdp/codec/audio.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("codec")
Packit 1fb8d4
Packit 1fb8d4
UINT32 audio_format_compute_time_length(const AUDIO_FORMAT* format, size_t size)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 mstime;
Packit 1fb8d4
	UINT32 wSamples;
Packit 1fb8d4
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * [MSDN-AUDIOFORMAT]:
Packit 1fb8d4
	 * http://msdn.microsoft.com/en-us/library/ms713497.aspx
Packit 1fb8d4
	 */
Packit 1fb8d4
Packit 1fb8d4
	if (format->wBitsPerSample)
Packit 1fb8d4
	{
Packit 1fb8d4
		wSamples = (size * 8) / format->wBitsPerSample;
Packit 1fb8d4
		mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		mstime = 0;
Packit 1fb8d4
Packit 1fb8d4
		if (format->wFormatTag == WAVE_FORMAT_GSM610)
Packit 1fb8d4
		{
Packit 1fb8d4
			UINT16 nSamplesPerBlock;
Packit 1fb8d4
Packit 1fb8d4
			if ((format->cbSize == 2) && (format->data))
Packit 1fb8d4
			{
Packit 1fb8d4
				nSamplesPerBlock = *((UINT16*) format->data);
Packit 1fb8d4
				wSamples = (size / format->nBlockAlign) * nSamplesPerBlock;
Packit 1fb8d4
				mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG,  "audio_format_compute_time_length: invalid WAVE_FORMAT_GSM610 format");
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG,  "audio_format_compute_time_length: unknown format %"PRIu16"", format->wFormatTag);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return mstime;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
char* audio_format_get_tag_string(UINT16 wFormatTag)
Packit 1fb8d4
{
Packit 1fb8d4
	switch (wFormatTag)
Packit 1fb8d4
	{
Packit 1fb8d4
		case WAVE_FORMAT_PCM:
Packit 1fb8d4
			return "WAVE_FORMAT_PCM";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_ADPCM:
Packit 1fb8d4
			return "WAVE_FORMAT_ADPCM";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_ALAW:
Packit 1fb8d4
			return "WAVE_FORMAT_ALAW";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_MULAW:
Packit 1fb8d4
			return "WAVE_FORMAT_MULAW";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_DVI_ADPCM:
Packit 1fb8d4
			return "WAVE_FORMAT_DVI_ADPCM";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_GSM610:
Packit 1fb8d4
			return "WAVE_FORMAT_GSM610";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_MSG723:
Packit 1fb8d4
			return "WAVE_FORMAT_MSG723";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
Packit 1fb8d4
			return "WAVE_FORMAT_DSPGROUP_TRUESPEECH	";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_MPEGLAYER3:
Packit 1fb8d4
			return "WAVE_FORMAT_MPEGLAYER3";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_WMAUDIO2:
Packit 1fb8d4
			return "WAVE_FORMAT_WMAUDIO2";
Packit 1fb8d4
Packit 1fb8d4
		case WAVE_FORMAT_AAC_MS:
Packit 1fb8d4
			return "WAVE_FORMAT_AAC_MS";
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return "WAVE_FORMAT_UNKNOWN";
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_Print(log, level,
Packit 1fb8d4
	           "%s:\t wFormatTag: 0x%04"PRIX16" nChannels: %"PRIu16" nSamplesPerSec: %"PRIu32" "
Packit 1fb8d4
	           "nAvgBytesPerSec: %"PRIu32" nBlockAlign: %"PRIu16" wBitsPerSample: %"PRIu16" cbSize: %"PRIu16"",
Packit 1fb8d4
	           audio_format_get_tag_string(format->wFormatTag), format->wFormatTag,
Packit 1fb8d4
	           format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec,
Packit 1fb8d4
	           format->nBlockAlign, format->wBitsPerSample, format->cbSize);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT16 index;
Packit 1fb8d4
	const AUDIO_FORMAT* format;
Packit 1fb8d4
Packit 1fb8d4
	if (formats)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_Print(log, level,  "AUDIO_FORMATS (%"PRIu16") ={", count);
Packit 1fb8d4
Packit 1fb8d4
		for (index = 0; index < count; index++)
Packit 1fb8d4
		{
Packit 1fb8d4
			format = &formats[index];
Packit 1fb8d4
			WLog_Print(log, level,  "\t");
Packit 1fb8d4
			audio_format_print(log, level, format);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		WLog_Print(log, level,  "}");
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!s || !format)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 18)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT16(s, format->wFormatTag);
Packit 1fb8d4
	Stream_Read_UINT16(s, format->nChannels);
Packit 1fb8d4
	Stream_Read_UINT32(s, format->nSamplesPerSec);
Packit 1fb8d4
	Stream_Read_UINT32(s, format->nAvgBytesPerSec);
Packit 1fb8d4
	Stream_Read_UINT16(s, format->nBlockAlign);
Packit 1fb8d4
	Stream_Read_UINT16(s, format->wBitsPerSample);
Packit 1fb8d4
	Stream_Read_UINT16(s, format->cbSize);
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < format->cbSize)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	format->data = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (format->cbSize > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		format->data = malloc(format->cbSize);
Packit 1fb8d4
Packit 1fb8d4
		if (!format->data)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read(s, format->data, format->cbSize);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!s || !format)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!Stream_EnsureRemainingCapacity(s, 18 + format->cbSize))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Write_UINT16(s, format->wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
Packit 1fb8d4
	Stream_Write_UINT16(s, format->nChannels); /* nChannels */
Packit 1fb8d4
	Stream_Write_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */
Packit 1fb8d4
	Stream_Write_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */
Packit 1fb8d4
	Stream_Write_UINT16(s, format->nBlockAlign); /* nBlockAlign */
Packit 1fb8d4
	Stream_Write_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */
Packit 1fb8d4
	Stream_Write_UINT16(s, format->cbSize); /* cbSize */
Packit 1fb8d4
Packit 1fb8d4
	if (format->cbSize > 0)
Packit 1fb8d4
		Stream_Write(s, format->data, format->cbSize);
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL audio_format_copy(const AUDIO_FORMAT* srcFormat, AUDIO_FORMAT* dstFormat)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!srcFormat || !dstFormat)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	*dstFormat = *srcFormat;
Packit 1fb8d4
Packit 1fb8d4
	if (srcFormat->cbSize > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		dstFormat->data = malloc(srcFormat->cbSize);
Packit 1fb8d4
Packit 1fb8d4
		if (!dstFormat->data)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		memcpy(dstFormat->data, srcFormat->data, dstFormat->cbSize);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!with || !what)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (with->wFormatTag != WAVE_FORMAT_UNKNOWN)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (with->wFormatTag != what->wFormatTag)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (with->nChannels != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (with->nChannels != what->nChannels)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (with->nSamplesPerSec != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (with->nSamplesPerSec != what->nSamplesPerSec)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (with->wBitsPerSample != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (with->wBitsPerSample != what->wBitsPerSample)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL audio_format_valid(const AUDIO_FORMAT* format)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!format)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (format->nChannels == 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (format->nSamplesPerSec == 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
AUDIO_FORMAT* audio_format_new(void)
Packit 1fb8d4
{
Packit 1fb8d4
	return audio_formats_new(1);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
AUDIO_FORMAT* audio_formats_new(size_t count)
Packit 1fb8d4
{
Packit 1fb8d4
	return calloc(count, sizeof(AUDIO_FORMAT));
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void audio_format_free(AUDIO_FORMAT* format)
Packit 1fb8d4
{
Packit 1fb8d4
	if (format)
Packit 1fb8d4
		free(format->data);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t index;
Packit 1fb8d4
Packit 1fb8d4
	if (formats)
Packit 1fb8d4
	{
Packit 1fb8d4
		for (index = 0; index < count; index++)
Packit 1fb8d4
		{
Packit 1fb8d4
			AUDIO_FORMAT* format = &formats[index];
Packit 1fb8d4
			audio_format_free(format);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		free(formats);
Packit 1fb8d4
	}
Packit 1fb8d4
}