C++程序  |  171行  |  5 KB

/* Copyright (c) 2013 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.
 */

#ifndef CRAS_AUDIO_FORMAT_H_
#define CRAS_AUDIO_FORMAT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <string.h>

#ifdef __ANDROID__
#include <hardware/audio.h>
#include <tinyalsa/asoundlib.h>
#define PCM_FORMAT_WIDTH(format) pcm_format_to_bits(format)
typedef enum pcm_format snd_pcm_format_t;

/* libasound audio formats. */
#define SND_PCM_FORMAT_UNKNOWN -1
#define SND_PCM_FORMAT_U8       1
#define SND_PCM_FORMAT_S16_LE   2
#define SND_PCM_FORMAT_S24_LE   6
#define SND_PCM_FORMAT_S32_LE  10

static inline int audio_format_to_cras_format(audio_format_t audio_format)
{
    switch (audio_format) {
    case AUDIO_FORMAT_PCM_16_BIT:
        return SND_PCM_FORMAT_S16_LE;
    case AUDIO_FORMAT_PCM_8_BIT:
        return SND_PCM_FORMAT_U8;
    case AUDIO_FORMAT_PCM_32_BIT:
        return SND_PCM_FORMAT_S32_LE;
    case AUDIO_FORMAT_PCM_8_24_BIT:
        return SND_PCM_FORMAT_S24_LE;
    default:
        return SND_PCM_FORMAT_UNKNOWN;
    }
}
#else
#include <alsa/asoundlib.h>
#define PCM_FORMAT_WIDTH(format) snd_pcm_format_physical_width(format)
#endif

/* Identifiers for each channel in audio stream. */
enum CRAS_CHANNEL {
	/* First nine channels matches the
	 * snd_mixer_selem_channel_id_t values.
	 */
	CRAS_CH_FL,
	CRAS_CH_FR,
	CRAS_CH_RL,
	CRAS_CH_RR,
	CRAS_CH_FC,
	CRAS_CH_LFE,
	CRAS_CH_SL,
	CRAS_CH_SR,
	CRAS_CH_RC,
	/* Channels defined both in channel_layout.h and
	 * alsa channel mapping API. */
	CRAS_CH_FLC,
	CRAS_CH_FRC,
	/* Must be the last one */
	CRAS_CH_MAX,
};

/* Audio format. */
struct cras_audio_format {
	snd_pcm_format_t format;
	size_t frame_rate; /* Hz */

	// TODO(hychao): use channel_layout to replace num_channels
	size_t num_channels;

	/* Channel layout whose value represents the index of each
	 * CRAS_CHANNEL in the layout. Value -1 means the channel is
	 * not used. For example: 0,1,2,3,4,5,-1,-1,-1,-1,-1 means the
	 * channel order is FL,FR,RL,RR,FC.
	 */
	int8_t channel_layout[CRAS_CH_MAX];
};

/* Packed version of audio format, for use in messages. We cannot modify
 * the above structure to keep binary compatibility with Chromium.
 * If cras_audio_format ever changes, merge the 2 structures.
 */
struct __attribute__ ((__packed__)) cras_audio_format_packed {
	int32_t format;
	uint32_t frame_rate;
	uint32_t num_channels;
	int8_t channel_layout[CRAS_CH_MAX];
};

static inline void pack_cras_audio_format(struct cras_audio_format_packed* dest,
					  const struct cras_audio_format* src)
{
	dest->format = src->format;
	dest->frame_rate = src->frame_rate;
	dest->num_channels = src->num_channels;
	memcpy(dest->channel_layout, src->channel_layout,
		sizeof(src->channel_layout));
}

static inline void unpack_cras_audio_format(struct cras_audio_format* dest,
				     const struct cras_audio_format_packed* src)
{
	dest->format = (snd_pcm_format_t)src->format;
	dest->frame_rate = src->frame_rate;
	dest->num_channels = src->num_channels;
	memcpy(dest->channel_layout, src->channel_layout,
		sizeof(src->channel_layout));
}

/* Returns the number of bytes per sample.
 * This is bits per smaple / 8 * num_channels.
 */
static inline size_t cras_get_format_bytes(const struct cras_audio_format *fmt)
{
	const int bytes = PCM_FORMAT_WIDTH(fmt->format) / 8;
	return (size_t)bytes * fmt->num_channels;
}

/* Sets channel layout to a default value where channels [0, num_channels] are
 * placed to the same position of its channel index, otherwise set to -1. */
static inline void cras_audio_format_set_default_channel_layout(
		struct cras_audio_format *format)
{
	unsigned int i;
	for (i = 0; i < CRAS_CH_MAX; i++)
		format->channel_layout[i] = i < format->num_channels ? i : -1;
}

/* 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);

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

/* Sets the channel layout for given format.
 *    format - The format structure to carry channel layout info
 *    layout - An integer array representing the position of each
 *        channel in enum CRAS_CHANNEL
 */
int cras_audio_format_set_channel_layout(struct cras_audio_format *format,
					 const int8_t layout[CRAS_CH_MAX]);

/* Allocates an empty channel conversion matrix of given size. */
float** cras_channel_conv_matrix_alloc(size_t in_ch, size_t out_ch);

/* Destroys the channel conversion matrix. */
void cras_channel_conv_matrix_destroy(float **mtx, size_t out_ch);

/* Creates channel conversion matrix for given input and output format.
 * Returns NULL if the conversion is not supported between the channel
 * layouts specified in input/ouput formats.
 */
float **cras_channel_conv_matrix_create(const struct cras_audio_format *in,
					const struct cras_audio_format *out);

#ifdef __cplusplus
}
#endif

#endif /* CRAS_AUDIO_FORMAT_H_ */