| /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef CRAS_AUDIO_FORMAT_H_ |
| #define CRAS_AUDIO_FORMAT_H_ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <stdbool.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #ifdef __ANDROID__ |
| #include <hardware/audio.h> |
| #include <tinyalsa/asoundlib.h> |
| #define PCM_FORMAT_WIDTH(format) pcm_format_to_bits(format) |
| typedef enum pcm_format snd_pcm_format_t; |
| |
| /* libasound audio formats. */ |
| #define SND_PCM_FORMAT_UNKNOWN -1 |
| #define SND_PCM_FORMAT_U8 1 |
| #define SND_PCM_FORMAT_S16_LE 2 |
| #define SND_PCM_FORMAT_S24_LE 6 |
| #define SND_PCM_FORMAT_S32_LE 10 |
| |
| static inline int audio_format_to_cras_format(audio_format_t audio_format) |
| { |
| switch (audio_format) { |
| case AUDIO_FORMAT_PCM_16_BIT: |
| return SND_PCM_FORMAT_S16_LE; |
| case AUDIO_FORMAT_PCM_8_BIT: |
| return SND_PCM_FORMAT_U8; |
| case AUDIO_FORMAT_PCM_32_BIT: |
| return SND_PCM_FORMAT_S32_LE; |
| case AUDIO_FORMAT_PCM_8_24_BIT: |
| return SND_PCM_FORMAT_S24_LE; |
| default: |
| return SND_PCM_FORMAT_UNKNOWN; |
| } |
| } |
| #else |
| #include <alsa/asoundlib.h> |
| #define PCM_FORMAT_WIDTH(format) snd_pcm_format_physical_width(format) |
| #endif |
| |
| /* Identifiers for each channel in audio stream. */ |
| enum CRAS_CHANNEL { |
| /* First nine channels matches the |
| * snd_mixer_selem_channel_id_t values. |
| */ |
| CRAS_CH_FL, |
| CRAS_CH_FR, |
| CRAS_CH_RL, |
| CRAS_CH_RR, |
| CRAS_CH_FC, |
| CRAS_CH_LFE, |
| CRAS_CH_SL, |
| CRAS_CH_SR, |
| CRAS_CH_RC, |
| /* Channels defined both in channel_layout.h and |
| * alsa channel mapping API. */ |
| CRAS_CH_FLC, |
| CRAS_CH_FRC, |
| /* Must be the last one */ |
| CRAS_CH_MAX, |
| }; |
| |
| /* Audio format. */ |
| struct cras_audio_format { |
| snd_pcm_format_t format; |
| size_t frame_rate; /* Hz */ |
| |
| // TODO(hychao): use channel_layout to replace num_channels |
| size_t num_channels; |
| |
| /* Channel layout whose value represents the index of each |
| * CRAS_CHANNEL in the layout. Value -1 means the channel is |
| * not used. For example: 0,1,2,3,4,5,-1,-1,-1,-1,-1 means the |
| * channel order is FL,FR,RL,RR,FC. |
| */ |
| int8_t channel_layout[CRAS_CH_MAX]; |
| }; |
| |
| /* Packed version of audio format, for use in messages. We cannot modify |
| * the above structure to keep binary compatibility with Chromium. |
| * If cras_audio_format ever changes, merge the 2 structures. |
| */ |
| struct __attribute__((__packed__)) cras_audio_format_packed { |
| int32_t format; |
| uint32_t frame_rate; |
| uint32_t num_channels; |
| int8_t channel_layout[CRAS_CH_MAX]; |
| }; |
| |
| static inline void pack_cras_audio_format(struct cras_audio_format_packed *dest, |
| const struct cras_audio_format *src) |
| { |
| dest->format = src->format; |
| dest->frame_rate = src->frame_rate; |
| dest->num_channels = src->num_channels; |
| memcpy(dest->channel_layout, src->channel_layout, |
| sizeof(src->channel_layout)); |
| } |
| |
| static inline struct cras_audio_format |
| unpack_cras_audio_format(const struct cras_audio_format_packed *src) |
| { |
| struct cras_audio_format dest; |
| dest.format = (snd_pcm_format_t)src->format; |
| dest.frame_rate = src->frame_rate; |
| dest.num_channels = src->num_channels; |
| memcpy(dest.channel_layout, src->channel_layout, |
| sizeof(src->channel_layout)); |
| return dest; |
| } |
| |
| /* Returns the number of bytes per sample. |
| * This is bits per smaple / 8 * num_channels. |
| */ |
| static inline size_t cras_get_format_bytes(const struct cras_audio_format *fmt) |
| { |
| const int bytes = PCM_FORMAT_WIDTH(fmt->format) / 8; |
| return (size_t)bytes * fmt->num_channels; |
| } |
| |
| /* Sets channel layout to a default value where channels [0, num_channels] are |
| * placed to the same position of its channel index, otherwise set to -1. */ |
| static inline void |
| cras_audio_format_set_default_channel_layout(struct cras_audio_format *format) |
| { |
| unsigned int i; |
| for (i = 0; i < CRAS_CH_MAX; i++) |
| format->channel_layout[i] = i < format->num_channels ? i : -1; |
| } |
| |
| /* Create an audio format structure. */ |
| struct cras_audio_format *cras_audio_format_create(snd_pcm_format_t format, |
| size_t frame_rate, |
| size_t num_channels); |
| |
| /* Destroy an audio format struct created with cras_audio_format_crate. */ |
| void cras_audio_format_destroy(struct cras_audio_format *fmt); |
| |
| /* Returns true if the audio format is valid */ |
| bool cras_audio_format_valid(const struct cras_audio_format *fmt); |
| |
| /* Sets the channel layout for given format. |
| * format - The format structure to carry channel layout info |
| * layout - An integer array representing the position of each |
| * channel in enum CRAS_CHANNEL |
| */ |
| int cras_audio_format_set_channel_layout(struct cras_audio_format *format, |
| const int8_t layout[CRAS_CH_MAX]); |
| |
| /* Allocates an empty channel conversion matrix of given size. */ |
| float **cras_channel_conv_matrix_alloc(size_t in_ch, size_t out_ch); |
| |
| /* Destroys the channel conversion matrix. */ |
| void cras_channel_conv_matrix_destroy(float **mtx, size_t out_ch); |
| |
| /* Creates channel conversion matrix for given input and output format. |
| * Returns NULL if the conversion is not supported between the channel |
| * layouts specified in input/ouput formats. |
| */ |
| float **cras_channel_conv_matrix_create(const struct cras_audio_format *in, |
| const struct cras_audio_format *out); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* CRAS_AUDIO_FORMAT_H_ */ |