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