/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <syslog.h>

#include "cras_audio_format.h"

/* Table for allowed alternatives when doing channel re-mapping.
 * When channel_alt[X][Y] is non-zero, it's allowed to map channel
 * from X to Y. */
static const int channel_alt[CRAS_CH_MAX][CRAS_CH_MAX] = {
	/*FL FR RL RR FC LFE SL SR RC FLC FRC */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* FL */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* FR */
	{ 0, 0, 0, 0, 0, 0, +1, 0, 0, 0, +0 }, /* RL */
	{ 0, 0, 0, 0, 0, 0, +0, 1, 0, 0, +0 }, /* RR */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* FC */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* LFE */
	{ 0, 0, 1, 0, 0, 0, +0, 0, 0, 0, +0 }, /* SL */
	{ 0, 0, 0, 1, 0, 0, +0, 0, 0, 0, +0 }, /* SR */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* RC */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* FLC */
	{ 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, +0 }, /* FRC */
};

/* Create an audio format structure. */
struct cras_audio_format *cras_audio_format_create(snd_pcm_format_t format,
						   size_t frame_rate,
						   size_t num_channels)
{
	struct cras_audio_format *fmt;
	unsigned i;

	fmt = (struct cras_audio_format *)calloc(1, sizeof(*fmt));
	if (fmt == NULL)
		return fmt;

	fmt->format = format;
	fmt->frame_rate = frame_rate;
	fmt->num_channels = num_channels;

	/* Set a default working channel layout according to num_channels.
	 * Initialize all other channel position to -1(not set)
	 */
	for (i = 0; i < CRAS_CH_MAX; i++)
		fmt->channel_layout[i] = (i < num_channels) ? i : -1;

	return fmt;
}

int cras_audio_format_set_channel_layout(struct cras_audio_format *format,
					 const int8_t layout[CRAS_CH_MAX])
{
	int i;

	/* Check that the max channel index should not exceed the
	 * channel count set in format.
	 */
	for (i = 0; i < CRAS_CH_MAX; i++)
		if (layout[i] < -1 || layout[i] >= (int)format->num_channels)
			return -EINVAL;

	for (i = 0; i < CRAS_CH_MAX; i++)
		format->channel_layout[i] = layout[i];

	return 0;
}

/* Verifies if all channel_layout[i] are in [-1, fmt->num_channels). */
bool cras_audio_format_valid(const struct cras_audio_format *fmt)
{
	int i;
	for (i = 0; i < CRAS_CH_MAX; i++) {
		if (fmt->channel_layout[i] < -1 ||
		    fmt->channel_layout[i] >= (int)fmt->num_channels) {
			return false;
		}
	}
	return true;
}

/* Destroy an audio format struct created with cras_audio_format_crate. */
void cras_audio_format_destroy(struct cras_audio_format *fmt)
{
	free(fmt);
}

float **cras_channel_conv_matrix_alloc(size_t in_ch, size_t out_ch)
{
	size_t i;
	float **p;
	p = (float **)calloc(out_ch, sizeof(*p));
	if (p == NULL)
		return NULL;
	for (i = 0; i < out_ch; i++) {
		p[i] = (float *)calloc(in_ch, sizeof(*p[i]));
		if (p[i] == NULL)
			goto alloc_err;
	}
	return p;

alloc_err:
	if (p)
		cras_channel_conv_matrix_destroy(p, out_ch);
	return NULL;
}

void cras_channel_conv_matrix_destroy(float **p, size_t out_ch)
{
	size_t i;
	for (i = 0; i < out_ch; i++)
		free(p[i]);
	free(p);
}

float **cras_channel_conv_matrix_create(const struct cras_audio_format *in,
					const struct cras_audio_format *out)
{
	int i;
	float **mtx;

	for (i = 0; i < CRAS_CH_MAX; i++) {
		if (in->channel_layout[i] >= (int)in->num_channels ||
		    out->channel_layout[i] >= (int)out->num_channels) {
			syslog(LOG_ERR, "Fail to create conversion matrix "
					"due to invalid channel layout");
			return NULL;
		}
	}

	mtx = cras_channel_conv_matrix_alloc(in->num_channels,
					     out->num_channels);

	/* For the in/out format pair which has the same set of channels
	 * in use, create a permutation matrix for them.
	 */
	for (i = 0; i < CRAS_CH_MAX; i++) {
		if (in->channel_layout[i] == -1 && out->channel_layout[i] == -1)
			continue;
		if (in->channel_layout[i] != -1 && out->channel_layout[i] != -1)
			mtx[out->channel_layout[i]][in->channel_layout[i]] = 1;
		else if (in->channel_layout[i] != -1) {
			/* When the same channel does not appear at output
			 * channel layout. Look up for allowed channel
			 * alternatives.
			 */
			int alt;
			for (alt = 0; alt <= CRAS_CH_MAX; alt++) {
				if (alt == CRAS_CH_MAX)
					goto fail;
				if (channel_alt[i][alt] &&
				    in->channel_layout[alt] == -1 &&
				    out->channel_layout[alt] != -1) {
					mtx[out->channel_layout[alt]]
					   [in->channel_layout[i]] = 1;
					break;
				}
			}
		}
	}

	return mtx;
fail:
	cras_channel_conv_matrix_destroy(mtx, out->num_channels);
	return NULL;
}
