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