1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2019 Intel Corporation. All rights reserved.
4 *
5 * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
6 */
7
8 /**
9 * \file audio/pcm_converter.h
10 * \brief PCM converter header file
11 * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com>
12 */
13
14 #ifndef __SOF_AUDIO_PCM_CONVERTER_H__
15 #define __SOF_AUDIO_PCM_CONVERTER_H__
16
17 #include <ipc/stream.h>
18
19 #include <stddef.h>
20 #include <stdint.h>
21
22 struct audio_stream;
23
24 #if __XCC__
25 #include <xtensa/config/core-isa.h>
26 #endif
27
28 #ifndef UNIT_TEST
29 #if __XCC__ && XCHAL_HAVE_HIFI3 && CONFIG_FORMAT_CONVERT_HIFI3
30 #define PCM_CONVERTER_HIFI3
31 #else
32 #define PCM_CONVERTER_GENERIC
33 #endif
34 #endif /* UNIT_TEST */
35
36 /**
37 * \brief PCM conversion function interface for data in circular buffer
38 * \param source buffer with samples to process, read pointer is not modified
39 * \param ioffset offset to first sample in source stream
40 * \param sink output buffer, write pointer is not modified
41 * \param ooffset offset to first sample in sink stream
42 * \param samples number of samples to convert
43 * \return error code or number of processed samples.
44 */
45 typedef int (*pcm_converter_func)(const struct audio_stream *source,
46 uint32_t ioffset, struct audio_stream *sink,
47 uint32_t ooffset, uint32_t samples);
48
49 /**
50 * \brief PCM conversion function interface for data in linear buffer
51 * \param psrc linear memory region with samples to process
52 * \param pdst linear memory region for output
53 * \param samples number of samples to convert
54 */
55 typedef void (*pcm_converter_lin_func)(const void *psrc, void *pdst,
56 uint32_t samples);
57
58 /** \brief PCM conversion functions map. */
59 struct pcm_func_map {
60 enum sof_ipc_frame source; /**< source frame format */
61 enum sof_ipc_frame sink; /**< sink frame format */
62 pcm_converter_func func; /**< PCM conversion function */
63 };
64
65 /** \brief Map of formats with dedicated conversion functions. */
66 extern const struct pcm_func_map pcm_func_map[];
67
68 /** \brief Number of conversion functions. */
69 extern const size_t pcm_func_count;
70
71 /**
72 * \brief Retrieves PCM conversion function.
73 * \param[in] in Source frame format.
74 * \param[in] out Sink frame format.
75 */
76 static inline pcm_converter_func
pcm_get_conversion_function(enum sof_ipc_frame in,enum sof_ipc_frame out)77 pcm_get_conversion_function(enum sof_ipc_frame in,
78 enum sof_ipc_frame out)
79 {
80 uint32_t i;
81
82 for (i = 0; i < pcm_func_count; i++) {
83 if (in != pcm_func_map[i].source)
84 continue;
85 if (out != pcm_func_map[i].sink)
86 continue;
87
88 return pcm_func_map[i].func;
89 }
90
91 return NULL;
92 }
93
94 /** \brief PCM conversion functions mapfor different size of valid bit and container. */
95 struct pcm_func_vc_map {
96 enum sof_ipc_frame source; /**< source frame container format */
97 enum sof_ipc_frame valid_src_bits; /**< source frame format */
98 enum sof_ipc_frame sink; /**< sink frame container format */
99 enum sof_ipc_frame valid_sink_bits; /**< sink frame format */
100 pcm_converter_func func; /**< PCM conversion function */
101 };
102
103 /** \brief Map of formats with dedicated conversion functions. */
104 extern const struct pcm_func_vc_map pcm_func_vc_map[];
105
106 /** \brief Number of conversion functions. */
107 extern const size_t pcm_func_vc_count;
108
109 /**
110 * \brief Retrieves PCM conversion function for different container size.
111 * \param in_bits is source container format.
112 * \param valid_in_bits is source valid sample format.
113 * \param out_bits is sink container format.
114 * \param valid_out_bits is sink valid sample format.
115 */
116 static inline pcm_converter_func
pcm_get_conversion_vc_function(enum sof_ipc_frame in_bits,enum sof_ipc_frame valid_in_bits,enum sof_ipc_frame out_bits,enum sof_ipc_frame valid_out_bits)117 pcm_get_conversion_vc_function(enum sof_ipc_frame in_bits,
118 enum sof_ipc_frame valid_in_bits,
119 enum sof_ipc_frame out_bits,
120 enum sof_ipc_frame valid_out_bits)
121 {
122 uint32_t i;
123
124 for (i = 0; i < pcm_func_vc_count; i++) {
125 if (in_bits != pcm_func_vc_map[i].source)
126 continue;
127 if (valid_in_bits != pcm_func_vc_map[i].valid_src_bits)
128 continue;
129 if (out_bits != pcm_func_vc_map[i].sink)
130 continue;
131 if (valid_out_bits != pcm_func_vc_map[i].valid_sink_bits)
132 continue;
133
134 return pcm_func_vc_map[i].func;
135 }
136
137 return NULL;
138 }
139
140 /**
141 * \brief Convert data from circular buffer using converter working on linear
142 * memory space
143 * \param source buffer with samples to process, read pointer is not modified
144 * \param ioffset offset to first sample in source stream
145 * \param sink output buffer, write pointer is not modified
146 * \param ooffset offset to first sample in sink stream
147 * \param samples number of samples to convert
148 * \param converter core conversion function working on linear memory regions
149 * \return error code or number of processed samples
150 */
151 int pcm_convert_as_linear(const struct audio_stream *source, uint32_t ioffset,
152 struct audio_stream *sink, uint32_t ooffset,
153 uint32_t samples, pcm_converter_lin_func converter);
154
155 #endif /* __SOF_AUDIO_PCM_CONVERTER_H__ */
156