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 /**
9 * \file include/sof/audio/audio_stream.h
10 * \brief Audio Stream API definition
11 * \author Karol Trzcinski <karolx.trzcinski@linux.intel.com>
12 */
13
14 #ifndef __SOF_AUDIO_AUDIO_STREAM_H__
15 #define __SOF_AUDIO_AUDIO_STREAM_H__
16
17 #include <sof/audio/format.h>
18 #include <sof/compiler_attributes.h>
19 #include <rtos/panic.h>
20 #include <sof/math/numbers.h>
21 #include <rtos/alloc.h>
22 #include <rtos/cache.h>
23 #include <ipc/stream.h>
24 #include <ipc4/base-config.h>
25
26 #include <stdbool.h>
27 #include <stdint.h>
28
29 /** \addtogroup audio_stream_api Audio Stream API
30 * @{
31 */
32
33 /**
34 * Audio stream is a circular buffer aware of audio format of the data
35 * in the buffer so provides API for reading and writing not only bytes,
36 * but also samples and frames.
37 *
38 * Audio stream does not perform any memory allocations. A client (a component
39 * buffer or dma) must allocate the memory for the underlying data buffer and
40 * provide it to the initialization routine.
41 *
42 * Once the client is done with reading/writing the data, it must commit the
43 * consumption/production and update the buffer state by calling
44 * audio_stream_consume()/audio_stream_produce() (just a single call following
45 * series of reads/writes).
46 */
47 struct audio_stream {
48 /* runtime data */
49 uint32_t size; /**< Runtime buffer size in bytes (period multiple) */
50 uint32_t avail; /**< Available bytes for reading */
51 uint32_t free; /**< Free bytes for writing */
52 void *w_ptr; /**< Buffer write pointer */
53 void *r_ptr; /**< Buffer read position */
54 void *addr; /**< Buffer base address */
55 void *end_addr; /**< Buffer end address */
56
57 /* runtime stream params */
58 enum sof_ipc_frame frame_fmt; /**< Sample data format */
59 enum sof_ipc_frame valid_sample_fmt;
60
61 uint32_t rate; /**< Number of data frames per second [Hz] */
62 uint16_t channels; /**< Number of samples in each frame */
63
64 /** alignment limit of stream copy, this value indicates how many
65 * integer frames which can meet both byte align and frame align
66 * requirement. it should be set in component prepare or param functions
67 */
68 uint16_t frame_align;
69
70 /**
71 * alignment limit of stream copy, alignment is the frame_align_shift-th
72 * power of 2 bytes. it should be set in component prepare or param functions
73 */
74 uint16_t frame_align_shift;
75
76 bool overrun_permitted; /**< indicates whether overrun is permitted */
77 bool underrun_permitted; /**< indicates whether underrun is permitted */
78 };
79
80 /**
81 * Retrieves readable address of a sample at specified index (see versions of
82 * this macro specialized for various sample types).
83 * @param buffer Buffer.
84 * @param idx Index of sample.
85 * @param size Size of sample in bytes.
86 * @return Pointer to the sample.
87 *
88 * Once the consumer finishes reading samples from the buffer, it should
89 * "commit" the operation and update the buffer state by calling
90 * audio_stream_consume().
91 *
92 * @note Components should call comp_update_buffer_consume().
93 *
94 * @see audio_stream_get_frag().
95 * @see audio_stream_consume().
96 * @see comp_update_buffer_consume().
97 */
98 #define audio_stream_read_frag(buffer, idx, size) \
99 audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, size)
100
101 /**
102 * Retrieves readable address of a signed 16-bit sample at specified index.
103 * @param buffer Buffer.
104 * @param idx Index of sample.
105 * @return Pointer to the sample.
106 *
107 * @see audio_stream_get_frag().
108 */
109 #define audio_stream_read_frag_s16(buffer, idx) \
110 audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, sizeof(int16_t))
111
112 /**
113 * Retrieves readable address of a signed 32-bit sample at specified index.
114 * @param buffer Buffer.
115 * @param idx Index of sample.
116 * @return Pointer to the sample.
117 *
118 * @see audio_stream_get_frag().
119 */
120 #define audio_stream_read_frag_s32(buffer, idx) \
121 audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, sizeof(int32_t))
122
123 /**
124 * Retrieves writeable address of a sample at specified index (see versions of
125 * this macro specialized for various sample types).
126 * @param buffer Buffer.
127 * @param idx Index of sample.
128 * @param size Size of sample in bytes.
129 * @return Pointer to the space for sample.
130 *
131 * Once the producer finishes writing samples to the buffer, it should
132 * "commit" the operation and update the buffer state by calling
133 * audio_stream_produce().
134 *
135 * @note Components should call comp_update_buffer_produce().
136 *
137 * @see audio_stream_get_frag().
138 * @see audio_stream_produce().
139 * @see comp_update_buffer_produce().
140 */
141 #define audio_stream_write_frag(buffer, idx, size) \
142 audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, size)
143
144 /**
145 * Retrieves writeable address of a signed 16-bit sample at specified index.
146 * @param buffer Buffer.
147 * @param idx Index of sample.
148 * @return Pointer to the space for sample.
149 *
150 * @see audio_stream_get_frag().
151 */
152 #define audio_stream_write_frag_s16(buffer, idx) \
153 audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, sizeof(int16_t))
154
155 /**
156 * Retrieves writeable address of a signed 32-bit sample at specified index.
157 * @param buffer Buffer.
158 * @param idx Index of sample.
159 * @return Pointer to the space for sample.
160 *
161 * @see audio_stream_get_frag().
162 */
163 #define audio_stream_write_frag_s32(buffer, idx) \
164 audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, sizeof(int32_t))
165
166 /**
167 * Retrieves address of sample (space for sample) at specified index within
168 * the buffer. Index is interpreted as an offset relative to the specified
169 * pointer, rollover is ensured.
170 * @param buffer Circular buffer.
171 * @param ptr Pointer to start from, it may be either read or write pointer.
172 * @param idx Index of the sample.
173 * @param sample_size Size of the sample in bytes.
174 * @return Pointer to the sample.
175 */
176 #define audio_stream_get_frag(buffer, ptr, idx, sample_size) \
177 audio_stream_wrap(buffer, (char *)(ptr) + ((idx) * (sample_size)))
178
179 /**
180 * Applies parameters to the buffer.
181 * @param buffer Buffer.
182 * @param params Parameters (frame format, rate, number of channels).
183 * @return 0 if succeeded, error code otherwise.
184 */
audio_stream_set_params(struct audio_stream __sparse_cache * buffer,struct sof_ipc_stream_params * params)185 static inline int audio_stream_set_params(struct audio_stream __sparse_cache *buffer,
186 struct sof_ipc_stream_params *params)
187 {
188 if (!params)
189 return -EINVAL;
190
191 buffer->frame_fmt = params->frame_fmt;
192 buffer->rate = params->rate;
193 buffer->channels = params->channels;
194
195 return 0;
196 }
197
198 /**
199 * Calculates period size in bytes based on component stream's parameters.
200 * @param buf Component buffer.
201 * @return Period size in bytes.
202 */
audio_stream_frame_bytes(const struct audio_stream __sparse_cache * buf)203 static inline uint32_t audio_stream_frame_bytes(const struct audio_stream __sparse_cache *buf)
204 {
205 return get_frame_bytes(buf->frame_fmt, buf->channels);
206 }
207
208 /**
209 * Calculates sample size in bytes based on component stream's parameters.
210 * @param buf Component buffer.
211 * @return Size of sample in bytes.
212 */
audio_stream_sample_bytes(const struct audio_stream __sparse_cache * buf)213 static inline uint32_t audio_stream_sample_bytes(const struct audio_stream __sparse_cache *buf)
214 {
215 return get_sample_bytes(buf->frame_fmt);
216 }
217
218 /**
219 * Return the frames that meet the align requirement of both byte_align and
220 * frame_align_req.
221 * @param byte_align Processing byte alignment requirement.
222 * @param frame_align_req Processing frames alignment requirement.
223 * @param frame_size Size of the frame in bytes.
224 * @return frame number.
225 */
audio_stream_frame_align_get(const uint32_t byte_align,const uint32_t frame_align_req,uint32_t frame_size)226 static inline uint32_t audio_stream_frame_align_get(const uint32_t byte_align,
227 const uint32_t frame_align_req,
228 uint32_t frame_size)
229 {
230 /* Figure out how many frames are needed to meet the byte_align alignment requirements */
231 uint32_t frame_num = byte_align / gcd(byte_align, frame_size);
232
233 /** return the lcm of frame_num and frame_align_req*/
234 return frame_align_req * frame_num / gcd(frame_num, frame_align_req);
235 }
236
237 /**
238 * Set frame_align_shift and frame_align of stream according to byte_align and
239 * frame_align_req alignment requirement. Once the channel number,frame size
240 * are determined,the frame_align and frame_align_shift are determined too.
241 * these two feature will be used in audio_stream_get_avail_frames_aligned
242 * to calculate the available frames. it should be called in component prepare
243 * or param functions only once before stream copy. if someone forgets to call
244 * this first, there would be unexampled error such as nothing is copied at all.
245 * @param byte_align Processing byte alignment requirement.
246 * @param frame_align_req Processing frames alignment requirement.
247 * @param stream Sink or source stream structure which to be set.
248 */
audio_stream_init_alignment_constants(const uint32_t byte_align,const uint32_t frame_align_req,struct audio_stream __sparse_cache * stream)249 static inline void audio_stream_init_alignment_constants(const uint32_t byte_align,
250 const uint32_t frame_align_req,
251 struct audio_stream __sparse_cache *stream)
252 {
253 uint32_t process_size;
254 uint32_t frame_size = audio_stream_frame_bytes(stream);
255
256 stream->frame_align = audio_stream_frame_align_get(byte_align, frame_align_req, frame_size);
257 process_size = stream->frame_align * frame_size;
258 stream->frame_align_shift = (is_power_of_2(process_size) ? 31 : 32) - clz(process_size);
259 }
260
261 /**
262 * Calculates period size in bytes based on component stream's parameters.
263 * @param buf Component buffer.
264 * @param frames Number of processing frames.
265 * @return Period size in bytes.
266 */
audio_stream_period_bytes(const struct audio_stream __sparse_cache * buf,uint32_t frames)267 static inline uint32_t audio_stream_period_bytes(const struct audio_stream __sparse_cache *buf,
268 uint32_t frames)
269 {
270 return frames * audio_stream_frame_bytes(buf);
271 }
272
273 /**
274 * Verifies the pointer and performs rollover when reached the end of
275 * the buffer.
276 * @param buffer Buffer accessed by the pointer.
277 * @param ptr Pointer
278 * @return Pointer, adjusted if necessary.
279 */
audio_stream_wrap(const struct audio_stream __sparse_cache * buffer,void * ptr)280 static inline void *audio_stream_wrap(const struct audio_stream __sparse_cache *buffer,
281 void *ptr)
282 {
283 if (ptr >= buffer->end_addr)
284 ptr = (char *)buffer->addr +
285 ((char *)ptr - (char *)buffer->end_addr);
286
287 assert((intptr_t)ptr <= (intptr_t)buffer->end_addr);
288
289 return ptr;
290 }
291
292 /**
293 * Verifies the pointer and performs rollover when reached the end of
294 * the buffer.
295 * @param buffer Buffer accessed by the pointer.
296 * @param ptr Pointer
297 * @return Pointer, adjusted if necessary.
298 */
audio_stream_rewind_wrap(const struct audio_stream __sparse_cache * buffer,void * ptr)299 static inline void *audio_stream_rewind_wrap(const struct audio_stream __sparse_cache *buffer,
300 void *ptr)
301 {
302 if (ptr < buffer->addr)
303 ptr = (char *)buffer->end_addr - ((char *)buffer->addr - (char *)ptr);
304
305 assert((intptr_t)ptr >= (intptr_t)buffer->addr);
306
307 return ptr;
308 }
309
310 /**
311 * Calculates available data in bytes, handling underrun_permitted behaviour
312 * @param stream Stream pointer
313 * @return amount of data available for processing in bytes
314 */
315 static inline uint32_t
audio_stream_get_avail_bytes(const struct audio_stream __sparse_cache * stream)316 audio_stream_get_avail_bytes(const struct audio_stream __sparse_cache *stream)
317 {
318 /*
319 * In case of underrun-permitted stream, report buffer full instead of
320 * empty. This way, any data present in such stream is processed at
321 * regular pace, but buffer will never be seen as completely empty by
322 * clients, and in turn will not cause underrun/XRUN.
323 */
324 if (stream->underrun_permitted)
325 return stream->avail != 0 ? stream->avail : stream->size;
326
327 return stream->avail;
328 }
329
330 /**
331 * Calculates available data in samples, handling underrun_permitted behaviour
332 * @param stream Stream pointer
333 * @return amount of data available for processing in samples
334 */
335 static inline uint32_t
audio_stream_get_avail_samples(const struct audio_stream __sparse_cache * stream)336 audio_stream_get_avail_samples(const struct audio_stream __sparse_cache *stream)
337 {
338 return audio_stream_get_avail_bytes(stream) /
339 audio_stream_sample_bytes(stream);
340 }
341
342 /**
343 * Calculates available data in frames, handling underrun_permitted behaviour
344 * @param stream Stream pointer
345 * @return amount of data available for processing in frames
346 */
347 static inline uint32_t
audio_stream_get_avail_frames(const struct audio_stream __sparse_cache * stream)348 audio_stream_get_avail_frames(const struct audio_stream __sparse_cache *stream)
349 {
350 return audio_stream_get_avail_bytes(stream) /
351 audio_stream_frame_bytes(stream);
352 }
353
354 /**
355 * Calculates free space in bytes, handling overrun_permitted behaviour
356 * @param stream Stream pointer
357 * @return amount of space free in bytes
358 */
359 static inline uint32_t
audio_stream_get_free_bytes(const struct audio_stream __sparse_cache * stream)360 audio_stream_get_free_bytes(const struct audio_stream __sparse_cache *stream)
361 {
362 /*
363 * In case of overrun-permitted stream, report buffer empty instead of
364 * full. This way, if there's any actual free space for data it is
365 * processed at regular pace, but buffer will never be seen as
366 * completely full by clients, and in turn will not cause overrun/XRUN.
367 */
368 if (stream->overrun_permitted)
369 return stream->free != 0 ? stream->free : stream->size;
370
371 return stream->free;
372 }
373
374 /**
375 * Calculates free space in samples, handling overrun_permitted behaviour
376 * @param stream Stream pointer
377 * @return amount of space free in samples
378 */
379 static inline uint32_t
audio_stream_get_free_samples(const struct audio_stream __sparse_cache * stream)380 audio_stream_get_free_samples(const struct audio_stream __sparse_cache *stream)
381 {
382 return audio_stream_get_free_bytes(stream) /
383 audio_stream_sample_bytes(stream);
384 }
385
386 /**
387 * Calculates free space in frames, handling overrun_permitted behaviour
388 * @param stream Stream pointer
389 * @return amount of space free in frames
390 */
391 static inline uint32_t
audio_stream_get_free_frames(const struct audio_stream __sparse_cache * stream)392 audio_stream_get_free_frames(const struct audio_stream __sparse_cache *stream)
393 {
394 return audio_stream_get_free_bytes(stream) /
395 audio_stream_frame_bytes(stream);
396 }
397
398 /**
399 * Verifies whether specified number of bytes can be copied from source buffer
400 * to sink buffer.
401 * @param source Source buffer.
402 * @param sink Sink buffer.
403 * @param bytes Number of bytes to copy.
404 * @return 0 if there is enough data in source and enough free space in sink.
405 * @return 1 if there is not enough free space in sink.
406 * @return -1 if there is not enough data in source.
407 */
audio_stream_can_copy_bytes(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,uint32_t bytes)408 static inline int audio_stream_can_copy_bytes(const struct audio_stream __sparse_cache *source,
409 const struct audio_stream __sparse_cache *sink,
410 uint32_t bytes)
411 {
412 /* check for underrun */
413 if (audio_stream_get_avail_bytes(source) < bytes)
414 return -1;
415
416 /* check for overrun */
417 if (audio_stream_get_free_bytes(sink) < bytes)
418 return 1;
419
420 /* we are good to copy */
421 return 0;
422 }
423
424 /**
425 * Computes maximum number of bytes that can be copied from source buffer to
426 * sink buffer, verifying number of bytes available in source vs. free space
427 * available in sink.
428 * @param source Source buffer.
429 * @param sink Sink buffer.
430 * @return Number of bytes.
431 */
432 static inline uint32_t
audio_stream_get_copy_bytes(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink)433 audio_stream_get_copy_bytes(const struct audio_stream __sparse_cache *source,
434 const struct audio_stream __sparse_cache *sink)
435 {
436 uint32_t avail = audio_stream_get_avail_bytes(source);
437 uint32_t free = audio_stream_get_free_bytes(sink);
438
439 if (avail > free)
440 return free;
441 else
442 return avail;
443 }
444
445 /**
446 * Computes maximum number of frames that can be copied from source buffer
447 * to sink buffer, verifying number of available source frames vs. free
448 * space available in sink.
449 * @param source Source buffer.
450 * @param sink Sink buffer.
451 * @return Number of frames.
452 */
453 static inline uint32_t
audio_stream_avail_frames(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink)454 audio_stream_avail_frames(const struct audio_stream __sparse_cache *source,
455 const struct audio_stream __sparse_cache *sink)
456 {
457 uint32_t src_frames = audio_stream_get_avail_frames(source);
458 uint32_t sink_frames = audio_stream_get_free_frames(sink);
459
460 return MIN(src_frames, sink_frames);
461 }
462
463 /**
464 * Computes maximum number of frames aligned that can be copied from
465 * source buffer to sink buffer, verifying number of available source
466 * frames vs. free space available in sink.
467 * @param source Buffer of source.
468 * @param sink Buffer of sink.
469 * @return Number of frames.
470 */
471 static inline uint32_t
audio_stream_avail_frames_aligned(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink)472 audio_stream_avail_frames_aligned(const struct audio_stream __sparse_cache *source,
473 const struct audio_stream __sparse_cache *sink)
474 {
475 uint32_t src_frames = (audio_stream_get_avail_bytes(source) >> source->frame_align_shift)
476 * source->frame_align;
477 uint32_t sink_frames = (audio_stream_get_free_bytes(sink) >> sink->frame_align_shift)
478 * sink->frame_align;
479
480 return MIN(src_frames, sink_frames);
481 }
482
483 /**
484 * Updates the buffer state after writing to the buffer.
485 * @param buffer Buffer to update.
486 * @param bytes Number of written bytes.
487 */
audio_stream_produce(struct audio_stream __sparse_cache * buffer,uint32_t bytes)488 static inline void audio_stream_produce(struct audio_stream __sparse_cache *buffer,
489 uint32_t bytes)
490 {
491 buffer->w_ptr = audio_stream_wrap(buffer,
492 (char *)buffer->w_ptr + bytes);
493
494 /* "overwrite" old data in circular wrap case */
495 if (bytes > audio_stream_get_free_bytes(buffer))
496 buffer->r_ptr = buffer->w_ptr;
497
498 /* calculate available bytes */
499 if (buffer->r_ptr < buffer->w_ptr)
500 buffer->avail = (char *)buffer->w_ptr - (char *)buffer->r_ptr;
501 else if (buffer->r_ptr == buffer->w_ptr)
502 buffer->avail = buffer->size; /* full */
503 else
504 buffer->avail = buffer->size -
505 ((char *)buffer->r_ptr - (char *)buffer->w_ptr);
506
507 /* calculate free bytes */
508 buffer->free = buffer->size - buffer->avail;
509 }
510
511 /**
512 * Updates the buffer state after reading from the buffer.
513 * @param buffer Buffer to update.
514 * @param bytes Number of read bytes.
515 */
audio_stream_consume(struct audio_stream __sparse_cache * buffer,uint32_t bytes)516 static inline void audio_stream_consume(struct audio_stream __sparse_cache *buffer,
517 uint32_t bytes)
518 {
519 buffer->r_ptr = audio_stream_wrap(buffer,
520 (char *)buffer->r_ptr + bytes);
521
522 /* calculate available bytes */
523 if (buffer->r_ptr < buffer->w_ptr)
524 buffer->avail = (char *)buffer->w_ptr - (char *)buffer->r_ptr;
525 else if (buffer->r_ptr == buffer->w_ptr)
526 buffer->avail = 0; /* empty */
527 else
528 buffer->avail = buffer->size -
529 ((char *)buffer->r_ptr - (char *)buffer->w_ptr);
530
531 /* calculate free bytes */
532 buffer->free = buffer->size - buffer->avail;
533 }
534
535 /**
536 * Resets the buffer.
537 * @param buffer Buffer to reset.
538 */
audio_stream_reset(struct audio_stream __sparse_cache * buffer)539 static inline void audio_stream_reset(struct audio_stream __sparse_cache *buffer)
540 {
541 /* reset read and write pointer to buffer bas */
542 buffer->w_ptr = buffer->addr;
543 buffer->r_ptr = buffer->addr;
544
545 /* free space is buffer size */
546 buffer->free = buffer->size;
547
548 /* there are no avail samples at reset */
549 buffer->avail = 0;
550 }
551
552 /**
553 * Initializes the buffer with specified memory block and size.
554 * @param buffer Buffer to initialize.
555 * @param buff_addr Address of the memory block to assign.
556 * @param size Size of the memory block in bytes.
557 */
audio_stream_init(struct audio_stream __sparse_cache * buffer,void * buff_addr,uint32_t size)558 static inline void audio_stream_init(struct audio_stream __sparse_cache *buffer,
559 void *buff_addr, uint32_t size)
560 {
561 buffer->size = size;
562 buffer->addr = buff_addr;
563 buffer->end_addr = (char *)buffer->addr + size;
564 audio_stream_reset(buffer);
565 }
566
567 /**
568 * Invalidates (in DSP d-cache) the buffer in range [r_ptr, r_ptr+bytes],
569 * with rollover if necessary.
570 * @param buffer Buffer.
571 * @param bytes Size of the fragment to invalidate.
572 */
audio_stream_invalidate(struct audio_stream __sparse_cache * buffer,uint32_t bytes)573 static inline void audio_stream_invalidate(struct audio_stream __sparse_cache *buffer,
574 uint32_t bytes)
575 {
576 uint32_t head_size = bytes;
577 uint32_t tail_size = 0;
578
579 /* check for potential wrap */
580 if ((char *)buffer->r_ptr + bytes > (char *)buffer->end_addr) {
581 head_size = (char *)buffer->end_addr - (char *)buffer->r_ptr;
582 tail_size = bytes - head_size;
583 }
584
585 dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->r_ptr, head_size);
586 if (tail_size)
587 dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->addr,
588 tail_size);
589 }
590
591 /**
592 * Writes back (from DSP d-cache) the buffer in range [w_ptr, w_ptr+bytes],
593 * with rollover if necessary.
594 * @param buffer Buffer.
595 * @param bytes Size of the fragment to write back.
596 */
audio_stream_writeback(struct audio_stream __sparse_cache * buffer,uint32_t bytes)597 static inline void audio_stream_writeback(struct audio_stream __sparse_cache *buffer,
598 uint32_t bytes)
599 {
600 uint32_t head_size = bytes;
601 uint32_t tail_size = 0;
602
603 /* check for potential wrap */
604 if ((char *)buffer->w_ptr + bytes > (char *)buffer->end_addr) {
605 head_size = (char *)buffer->end_addr - (char *)buffer->w_ptr;
606 tail_size = bytes - head_size;
607 }
608
609 dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, head_size);
610 if (tail_size)
611 dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->addr,
612 tail_size);
613 }
614
615 /**
616 * @brief Calculates numbers of bytes to buffer wrap.
617 * @param source Stream to get information from.
618 * @param ptr Read or write pointer from source
619 * @return Number of data samples to buffer wrap.
620 */
621 static inline int
audio_stream_bytes_without_wrap(const struct audio_stream __sparse_cache * source,const void * ptr)622 audio_stream_bytes_without_wrap(const struct audio_stream __sparse_cache *source,
623 const void *ptr)
624 {
625 assert((intptr_t)source->end_addr >= (intptr_t)ptr);
626 return (intptr_t)source->end_addr - (intptr_t)ptr;
627 }
628
629 /**
630 * @brief Calculates numbers of bytes to buffer wrap when reading stream
631 * backwards from current sample pointed by ptr towards begin.
632 * @param source Stream to get information from.
633 * @param ptr Read or write pointer from source
634 * @return Number of bytes to buffer wrap. For number of samples calculate
635 * need to add size of sample to returned bytes count.
636 */
637 static inline int
audio_stream_rewind_bytes_without_wrap(const struct audio_stream __sparse_cache * source,const void * ptr)638 audio_stream_rewind_bytes_without_wrap(const struct audio_stream __sparse_cache *source,
639 const void *ptr)
640 {
641 assert((intptr_t)ptr >= (intptr_t)source->addr);
642 int to_begin = (intptr_t)ptr - (intptr_t)source->addr;
643 return to_begin;
644 }
645
646 /**
647 * @brief Calculates numbers of s16 samples to buffer wrap when buffer
648 * is read forward towards end address.
649 * @param source Stream to get information from.
650 * @param ptr Read or write pointer from source
651 * @return Number of data s16 samples until circular wrap need at end
652 */
653 static inline int
audio_stream_samples_without_wrap_s16(const struct audio_stream __sparse_cache * source,const void * ptr)654 audio_stream_samples_without_wrap_s16(const struct audio_stream __sparse_cache *source,
655 const void *ptr)
656 {
657 int to_end = (int16_t *)source->end_addr - (int16_t *)ptr;
658
659 assert((intptr_t)source->end_addr >= (intptr_t)ptr);
660 return to_end;
661 }
662
663 /**
664 * @brief Calculates numbers of s24 samples to buffer wrap when buffer
665 * is read forward towards end address.
666 * @param source Stream to get information from.
667 * @param ptr Read or write pointer from source
668 * @return Number of data s24 samples until circular wrap need at end
669 */
670 static inline int
audio_stream_samples_without_wrap_s24(const struct audio_stream __sparse_cache * source,const void * ptr)671 audio_stream_samples_without_wrap_s24(const struct audio_stream __sparse_cache *source,
672 const void *ptr)
673 {
674 int to_end = (int32_t *)source->end_addr - (int32_t *)ptr;
675
676 assert((intptr_t)source->end_addr >= (intptr_t)ptr);
677 return to_end;
678 }
679
680 /**
681 * @brief Calculates numbers of s32 samples to buffer wrap when buffer
682 * is read forward towards end address.
683 * @param source Stream to get information from.
684 * @param ptr Read or write pointer from source
685 * @return Number of data s32 samples until circular wrap need at end
686 */
687 static inline int
audio_stream_samples_without_wrap_s32(const struct audio_stream __sparse_cache * source,const void * ptr)688 audio_stream_samples_without_wrap_s32(const struct audio_stream __sparse_cache *source,
689 const void *ptr)
690 {
691 int to_end = (int32_t *)source->end_addr - (int32_t *)ptr;
692
693 assert((intptr_t)source->end_addr >= (intptr_t)ptr);
694 return to_end;
695 }
696
697 /**
698 * @brief Calculates numbers of frames to buffer wrap and return
699 * minimum of calculated value.
700 * @param source Stream to get information from.
701 * @param ptr Read or write pointer from source
702 * @return Number of data frames to buffer wrap.
703 */
704 static inline uint32_t
audio_stream_frames_without_wrap(const struct audio_stream __sparse_cache * source,const void * ptr)705 audio_stream_frames_without_wrap(const struct audio_stream __sparse_cache *source,
706 const void *ptr)
707 {
708 uint32_t bytes = audio_stream_bytes_without_wrap(source, ptr);
709 uint32_t frame_bytes = audio_stream_frame_bytes(source);
710
711 return bytes / frame_bytes;
712 }
713
714 /**
715 * Copies data from source buffer to sink buffer.
716 * @param source Source buffer.
717 * @param ioffset Offset (in samples) in source buffer to start reading from.
718 * @param sink Sink buffer.
719 * @param ooffset Offset (in samples) in sink buffer to start writing to.
720 * @param samples Number of samples to copy.
721 * @return number of processed samples.
722 */
723 int audio_stream_copy(const struct audio_stream __sparse_cache *source, uint32_t ioffset,
724 struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples);
725
726 /**
727 * Copies data from linear source buffer to circular sink buffer.
728 * @param linear_source Source buffer.
729 * @param ioffset Offset (in samples) in source buffer to start reading from.
730 * @param sink Sink buffer.
731 * @param ooffset Offset (in samples) in sink buffer to start writing to.
732 * @param samples Number of samples to copy.
733 */
734 void audio_stream_copy_from_linear(const void *linear_source, int ioffset,
735 struct audio_stream __sparse_cache *sink, int ooffset,
736 unsigned int samples);
737
738 /**
739 * Copies data from circular source buffer to linear sink buffer.
740 * @param source Source buffer.
741 * @param ioffset Offset (in samples) in source buffer to start reading from.
742 * @param linear_sink Sink buffer.
743 * @param ooffset Offset (in samples) in sink buffer to start writing to.
744 * @param samples Number of samples to copy.
745 */
746 void audio_stream_copy_to_linear(const struct audio_stream __sparse_cache *source, int ioffset,
747 void *linear_sink, int ooffset, unsigned int samples);
748
749 /**
750 * Writes zeros in range [w_ptr, w_ptr+bytes], with rollover if necessary.
751 * @param buffer Buffer.
752 * @param bytes Size of the fragment to write zero.
753 * @return 0 if there is enough free space in buffer.
754 * @return 1 if there is not enough free space in buffer.
755 */
audio_stream_set_zero(struct audio_stream __sparse_cache * buffer,uint32_t bytes)756 static inline int audio_stream_set_zero(struct audio_stream __sparse_cache *buffer,
757 uint32_t bytes)
758 {
759 uint32_t head_size = bytes;
760 uint32_t tail_size = 0;
761
762 /* check for overrun */
763 if (audio_stream_get_free_bytes(buffer) < bytes)
764 return 1;
765
766 /* check for potential wrap */
767 if ((char *)buffer->w_ptr + bytes > (char *)buffer->end_addr) {
768 head_size = (char *)buffer->end_addr - (char *)buffer->w_ptr;
769 tail_size = bytes - head_size;
770 }
771
772 memset(buffer->w_ptr, 0, head_size);
773 if (tail_size)
774 memset(buffer->addr, 0, tail_size);
775
776 return 0;
777 }
778
audio_stream_fmt_conversion(enum ipc4_bit_depth depth,enum ipc4_bit_depth valid,enum sof_ipc_frame __sparse_cache * frame_fmt,enum sof_ipc_frame __sparse_cache * valid_fmt,enum ipc4_sample_type type)779 static inline void audio_stream_fmt_conversion(enum ipc4_bit_depth depth,
780 enum ipc4_bit_depth valid,
781 enum sof_ipc_frame __sparse_cache *frame_fmt,
782 enum sof_ipc_frame __sparse_cache *valid_fmt,
783 enum ipc4_sample_type type)
784 {
785 /* IPC4_DEPTH_16BIT (16) <---> SOF_IPC_FRAME_S16_LE (0)
786 * IPC4_DEPTH_24BIT (24) <---> SOF_IPC_FRAME_S24_4LE (1)
787 * IPC4_DEPTH_32BIT (32) <---> SOF_IPC_FRAME_S32_LE (2)
788 */
789 *frame_fmt = (depth >> 3) - 2;
790 *valid_fmt = (valid >> 3) - 2;
791
792 /* really 24_3LE */
793 if (valid == 24 && depth == 24) {
794 *frame_fmt = SOF_IPC_FRAME_S24_3LE;
795 *valid_fmt = SOF_IPC_FRAME_S24_3LE;
796 }
797
798 if (type == IPC4_TYPE_FLOAT && depth == 32) {
799 *frame_fmt = SOF_IPC_FRAME_FLOAT;
800 *valid_fmt = SOF_IPC_FRAME_FLOAT;
801 }
802 }
803 /** @}*/
804
805 #endif /* __SOF_AUDIO_AUDIO_STREAM_H__ */
806