⛏️ index : haiku.git

/*
 * Copyright 2008, Axel DΓΆrfler, axeld@pinc-software.de.
 * Copyright (c) 2002-2007, Jerome Duval (jerome.duval@free.fr)
 *
 * Distributed under the terms of the MIT License.
 */


#include "MultiAudioUtility.h"

#include <errno.h>

#include <MediaDefs.h>


const float kSampleRates[] = {
	8000.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0,
	48000.0, 64000.0, 88200.0, 96000.0, 176400.0, 192000.0, 384000.0, 1536000.0
};
const uint32 kSampleRateCount = sizeof(kSampleRates) / sizeof(kSampleRates[0]);


template<typename T> static status_t
call_driver(int device, int32 op, T* data)
{
	if (ioctl(device, op, data, sizeof(T)) != 0)
		return errno;

	return B_OK;
}


namespace MultiAudio {


float
convert_to_sample_rate(uint32 rate)
{
	for (uint32 i = 0; i < kSampleRateCount; i++) {
		if (rate & 1)
			return kSampleRates[i];

		rate >>= 1;
	}

	return 0.0;
}


uint32
convert_from_sample_rate(float rate)
{
	for (uint32 i = 0; i < kSampleRateCount; i++) {
		if (rate <= kSampleRates[i])
			return 1 << i;
	}

	return 0;
}


uint32
convert_to_media_format(uint32 format)
{
	switch (format) {
		case B_FMT_FLOAT:
			return media_raw_audio_format::B_AUDIO_FLOAT;
		case B_FMT_18BIT:
		case B_FMT_20BIT:
		case B_FMT_24BIT:
		case B_FMT_32BIT:
			return media_raw_audio_format::B_AUDIO_INT;
		case B_FMT_16BIT:
			return media_raw_audio_format::B_AUDIO_SHORT;
		case B_FMT_8BIT_S:
			return media_raw_audio_format::B_AUDIO_CHAR;
		case B_FMT_8BIT_U:
			return media_raw_audio_format::B_AUDIO_UCHAR;

		default:
			return 0;
	}
}


int16
convert_to_valid_bits(uint32 format)
{
	switch (format) {
		case B_FMT_18BIT:
			return 18;
		case B_FMT_20BIT:
			return 20;
		case B_FMT_24BIT:
			return 24;
		case B_FMT_32BIT:
			return 32;

		default:
			return 0;
	}
}


uint32
convert_from_media_format(uint32 format)
{
	switch (format) {
		case media_raw_audio_format::B_AUDIO_FLOAT:
			return B_FMT_FLOAT;
		case media_raw_audio_format::B_AUDIO_INT:
			return B_FMT_32BIT;
		case media_raw_audio_format::B_AUDIO_SHORT:
			return B_FMT_16BIT;
		case media_raw_audio_format::B_AUDIO_CHAR:
			return B_FMT_8BIT_S;
		case media_raw_audio_format::B_AUDIO_UCHAR:
			return B_FMT_8BIT_U;

		default:
			return 0;
	}
}


uint32
select_sample_rate(uint32 rate)
{
	// highest rate
	uint32 crate = B_SR_1536000;
	while (crate != 0) {
		if (rate & crate)
			return crate;
		crate >>= 1;
	}
	return 0;
}


uint32
select_format(uint32 format)
{
	// best format
	// TODO ensure we support this format
	/*if (format & B_FMT_FLOAT)
		return B_FMT_FLOAT;*/
	if (format & B_FMT_32BIT)
		return B_FMT_32BIT;
	if (format & B_FMT_24BIT)
		return B_FMT_24BIT;
	if (format & B_FMT_20BIT)
		return B_FMT_20BIT;
	if (format & B_FMT_18BIT)
		return B_FMT_18BIT;
	if (format & B_FMT_16BIT)
		return B_FMT_16BIT;
	if (format & B_FMT_8BIT_S)
		return B_FMT_8BIT_S;
	if (format & B_FMT_8BIT_U)
		return B_FMT_8BIT_U;

	return 0;
}


status_t
get_description(int device, multi_description* description)
{
	return call_driver(device, B_MULTI_GET_DESCRIPTION, description);
}


status_t
get_enabled_channels(int device, multi_channel_enable* enable)
{
	return call_driver(device, B_MULTI_GET_ENABLED_CHANNELS, enable);
}


status_t
set_enabled_channels(int device, multi_channel_enable* enable)
{
	return call_driver(device, B_MULTI_SET_ENABLED_CHANNELS, enable);
}


status_t
get_global_format(int device, multi_format_info* info)
{
	return call_driver(device, B_MULTI_GET_GLOBAL_FORMAT, info);
}


status_t
set_global_format(int device, multi_format_info* info)
{
	return call_driver(device, B_MULTI_SET_GLOBAL_FORMAT, info);
}


status_t
get_buffers(int device, multi_buffer_list* list)
{
	return call_driver(device, B_MULTI_GET_BUFFERS, list);
}


status_t
buffer_exchange(int device, multi_buffer_info* info)
{
	return call_driver(device, B_MULTI_BUFFER_EXCHANGE, info);
}


status_t
list_mix_controls(int device, multi_mix_control_info* info)
{
	return call_driver(device, B_MULTI_LIST_MIX_CONTROLS, info);
}


status_t
get_mix(int device, multi_mix_value_info* info)
{
	return call_driver(device, B_MULTI_GET_MIX, info);
}


status_t
set_mix(int device, multi_mix_value_info* info)
{
	return call_driver(device, B_MULTI_SET_MIX, info);
}


}	// namespace MultiAudio