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