• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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)
20 typedef 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 
audio_format_to_cras_format(audio_format_t audio_format)29 static 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. */
50 enum 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. */
72 struct 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  */
91 struct __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 
pack_cras_audio_format(struct cras_audio_format_packed * dest,const struct cras_audio_format * src)98 static 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 
108 static inline void
unpack_cras_audio_format(struct cras_audio_format * dest,const struct cras_audio_format_packed * src)109 unpack_cras_audio_format(struct cras_audio_format *dest,
110 			 const struct cras_audio_format_packed *src)
111 {
112 	dest->format = (snd_pcm_format_t)src->format;
113 	dest->frame_rate = src->frame_rate;
114 	dest->num_channels = src->num_channels;
115 	memcpy(dest->channel_layout, src->channel_layout,
116 	       sizeof(src->channel_layout));
117 }
118 
119 /* Returns the number of bytes per sample.
120  * This is bits per smaple / 8 * num_channels.
121  */
cras_get_format_bytes(const struct cras_audio_format * fmt)122 static inline size_t cras_get_format_bytes(const struct cras_audio_format *fmt)
123 {
124 	const int bytes = PCM_FORMAT_WIDTH(fmt->format) / 8;
125 	return (size_t)bytes * fmt->num_channels;
126 }
127 
128 /* Sets channel layout to a default value where channels [0, num_channels] are
129  * placed to the same position of its channel index, otherwise set to -1. */
130 static inline void
cras_audio_format_set_default_channel_layout(struct cras_audio_format * format)131 cras_audio_format_set_default_channel_layout(struct cras_audio_format *format)
132 {
133 	unsigned int i;
134 	for (i = 0; i < CRAS_CH_MAX; i++)
135 		format->channel_layout[i] = i < format->num_channels ? i : -1;
136 }
137 
138 /* Create an audio format structure. */
139 struct cras_audio_format *cras_audio_format_create(snd_pcm_format_t format,
140 						   size_t frame_rate,
141 						   size_t num_channels);
142 
143 /* Destroy an audio format struct created with cras_audio_format_crate. */
144 void cras_audio_format_destroy(struct cras_audio_format *fmt);
145 
146 /* Sets the channel layout for given format.
147  *    format - The format structure to carry channel layout info
148  *    layout - An integer array representing the position of each
149  *        channel in enum CRAS_CHANNEL
150  */
151 int cras_audio_format_set_channel_layout(struct cras_audio_format *format,
152 					 const int8_t layout[CRAS_CH_MAX]);
153 
154 /* Allocates an empty channel conversion matrix of given size. */
155 float **cras_channel_conv_matrix_alloc(size_t in_ch, size_t out_ch);
156 
157 /* Destroys the channel conversion matrix. */
158 void cras_channel_conv_matrix_destroy(float **mtx, size_t out_ch);
159 
160 /* Creates channel conversion matrix for given input and output format.
161  * Returns NULL if the conversion is not supported between the channel
162  * layouts specified in input/ouput formats.
163  */
164 float **cras_channel_conv_matrix_create(const struct cras_audio_format *in,
165 					const struct cras_audio_format *out);
166 
167 #ifdef __cplusplus
168 }
169 #endif
170 
171 #endif /* CRAS_AUDIO_FORMAT_H_ */
172