1/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#ifndef CRAS_AUDIO_FORMAT_H_
7#define CRAS_AUDIO_FORMAT_H_
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13#include <stdint.h>
14#include <string.h>
15
16#ifdef __ANDROID__
17#include <hardware/audio.h>
18#include <tinyalsa/asoundlib.h>
19#define PCM_FORMAT_WIDTH(format) pcm_format_to_bits(format)
20typedef enum pcm_format snd_pcm_format_t;
21
22/* libasound audio formats. */
23#define SND_PCM_FORMAT_UNKNOWN -1
24#define SND_PCM_FORMAT_U8       1
25#define SND_PCM_FORMAT_S16_LE   2
26#define SND_PCM_FORMAT_S24_LE   6
27#define SND_PCM_FORMAT_S32_LE  10
28
29static inline int audio_format_to_cras_format(audio_format_t audio_format)
30{
31    switch (audio_format) {
32    case AUDIO_FORMAT_PCM_16_BIT:
33        return SND_PCM_FORMAT_S16_LE;
34    case AUDIO_FORMAT_PCM_8_BIT:
35        return SND_PCM_FORMAT_U8;
36    case AUDIO_FORMAT_PCM_32_BIT:
37        return SND_PCM_FORMAT_S32_LE;
38    case AUDIO_FORMAT_PCM_8_24_BIT:
39        return SND_PCM_FORMAT_S24_LE;
40    default:
41        return SND_PCM_FORMAT_UNKNOWN;
42    }
43}
44#else
45#include <alsa/asoundlib.h>
46#define PCM_FORMAT_WIDTH(format) snd_pcm_format_physical_width(format)
47#endif
48
49/* Identifiers for each channel in audio stream. */
50enum CRAS_CHANNEL {
51	/* First nine channels matches the
52	 * snd_mixer_selem_channel_id_t values.
53	 */
54	CRAS_CH_FL,
55	CRAS_CH_FR,
56	CRAS_CH_RL,
57	CRAS_CH_RR,
58	CRAS_CH_FC,
59	CRAS_CH_LFE,
60	CRAS_CH_SL,
61	CRAS_CH_SR,
62	CRAS_CH_RC,
63	/* Channels defined both in channel_layout.h and
64	 * alsa channel mapping API. */
65	CRAS_CH_FLC,
66	CRAS_CH_FRC,
67	/* Must be the last one */
68	CRAS_CH_MAX,
69};
70
71/* Audio format. */
72struct cras_audio_format {
73	snd_pcm_format_t format;
74	size_t frame_rate; /* Hz */
75
76	// TODO(hychao): use channel_layout to replace num_channels
77	size_t num_channels;
78
79	/* Channel layout whose value represents the index of each
80	 * CRAS_CHANNEL in the layout. Value -1 means the channel is
81	 * not used. For example: 0,1,2,3,4,5,-1,-1,-1,-1,-1 means the
82	 * channel order is FL,FR,RL,RR,FC.
83	 */
84	int8_t channel_layout[CRAS_CH_MAX];
85};
86
87/* Packed version of audio format, for use in messages. We cannot modify
88 * the above structure to keep binary compatibility with Chromium.
89 * If cras_audio_format ever changes, merge the 2 structures.
90 */
91struct __attribute__ ((__packed__)) cras_audio_format_packed {
92	int32_t format;
93	uint32_t frame_rate;
94	uint32_t num_channels;
95	int8_t channel_layout[CRAS_CH_MAX];
96};
97
98static inline void pack_cras_audio_format(struct cras_audio_format_packed* dest,
99					  const struct cras_audio_format* src)
100{
101	dest->format = src->format;
102	dest->frame_rate = src->frame_rate;
103	dest->num_channels = src->num_channels;
104	memcpy(dest->channel_layout, src->channel_layout,
105		sizeof(src->channel_layout));
106}
107
108static inline void unpack_cras_audio_format(struct cras_audio_format* dest,
109				     const struct cras_audio_format_packed* src)
110{
111	dest->format = (snd_pcm_format_t)src->format;
112	dest->frame_rate = src->frame_rate;
113	dest->num_channels = src->num_channels;
114	memcpy(dest->channel_layout, src->channel_layout,
115		sizeof(src->channel_layout));
116}
117
118/* Returns the number of bytes per sample.
119 * This is bits per smaple / 8 * num_channels.
120 */
121static inline size_t cras_get_format_bytes(const struct cras_audio_format *fmt)
122{
123	const int bytes = PCM_FORMAT_WIDTH(fmt->format) / 8;
124	return (size_t)bytes * fmt->num_channels;
125}
126
127/* Create an audio format structure. */
128struct cras_audio_format *cras_audio_format_create(snd_pcm_format_t format,
129						   size_t frame_rate,
130						   size_t num_channels);
131
132/* Destroy an audio format struct created with cras_audio_format_crate. */
133void cras_audio_format_destroy(struct cras_audio_format *fmt);
134
135/* Sets the channel layout for given format.
136 *    format - The format structure to carry channel layout info
137 *    layout - An integer array representing the position of each
138 *        channel in enum CRAS_CHANNEL
139 */
140int cras_audio_format_set_channel_layout(struct cras_audio_format *format,
141					 const int8_t layout[CRAS_CH_MAX]);
142
143/* Allocates an empty channel conversion matrix of given size. */
144float** cras_channel_conv_matrix_alloc(size_t in_ch, size_t out_ch);
145
146/* Destroys the channel conversion matrix. */
147void cras_channel_conv_matrix_destroy(float **mtx, size_t out_ch);
148
149/* Creates channel conversion matrix for given input and output format.
150 * Returns NULL if the conversion is not supported between the channel
151 * layouts specified in input/ouput formats.
152 */
153float **cras_channel_conv_matrix_create(const struct cras_audio_format *in,
154					const struct cras_audio_format *out);
155
156#ifdef __cplusplus
157}
158#endif
159
160#endif /* CRAS_AUDIO_FORMAT_H_ */
161