1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
4 //
5 // Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com>
6
7 /**
8 * \file audio/pcm_converter/pcm_converter.c
9 * \brief PCM converter common functions
10 * \authors Karol Trzcinski <karolx.trzcinski@linux.intel.com>
11 */
12
13 #include <sof/audio/audio_stream.h>
14 #include <sof/audio/pcm_converter.h>
15 #include <sof/debug/panic.h>
16
pcm_convert_as_linear(const struct audio_stream * source,uint32_t ioffset,struct audio_stream * sink,uint32_t ooffset,uint32_t samples,pcm_converter_lin_func converter)17 int pcm_convert_as_linear(const struct audio_stream *source, uint32_t ioffset,
18 struct audio_stream *sink, uint32_t ooffset,
19 uint32_t samples, pcm_converter_lin_func converter)
20 {
21 const int s_size_in = audio_stream_sample_bytes(source);
22 const int s_size_out = audio_stream_sample_bytes(sink);
23 const int log2_s_size_in = ffs(s_size_in) - 1;
24 const int log2_s_size_out = ffs(s_size_out) - 1;
25 char *r_ptr = audio_stream_get_frag(source, source->r_ptr, ioffset,
26 s_size_in);
27 char *w_ptr = audio_stream_get_frag(sink, sink->w_ptr, ooffset,
28 s_size_out);
29 int i = 0;
30 int chunk;
31 int N1, N2;
32
33 /* assert enough avail/free samples in source and sink buffer */
34 if (audio_stream_get_avail_samples(source) < samples + ioffset)
35 return -EINVAL;
36 if (audio_stream_get_free_samples(sink) < samples + ooffset)
37 return -EINVAL;
38
39 while (i < samples) {
40 /* calculate chunk size */
41 /* "">> log2_s_size" is equal "/ s_size" here */
42 N1 = audio_stream_bytes_without_wrap(source, r_ptr) >>
43 log2_s_size_in;
44 N2 = audio_stream_bytes_without_wrap(sink, w_ptr) >>
45 log2_s_size_out;
46 chunk = MIN(N1, N2);
47 chunk = MIN(chunk, samples - i);
48
49 /* run conversion on linear memory region */
50 converter(r_ptr, w_ptr, chunk);
51
52 /* move pointers */
53 r_ptr = audio_stream_wrap(source, r_ptr + chunk * s_size_in);
54 w_ptr = audio_stream_wrap(sink, w_ptr + chunk * s_size_out);
55 i += chunk;
56 }
57
58 return samples;
59 }
60