1 /* Copyright 2018 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 FLOAT_BUFFER_H_
7 #define FLOAT_BUFFER_H_
8
9 #include "byte_buffer.h"
10
11 /*
12 * Circular buffer storing deinterleaved floating point data.
13 * Members:
14 * fp - Pointer to be filled wtih read/write position of the buffer.
15 * num_channels - Number of channels.
16 */
17 struct float_buffer {
18 struct byte_buffer *buf;
19 float **fp;
20 unsigned int num_channels;
21 };
22
23 /*
24 * Creates an float_buffer.
25 * Args:
26 * max_size - The max number of frames this buffer may store.
27 * num_channels - Number of channels of the deinterleaved data.
28 */
29 static inline struct float_buffer *
float_buffer_create(unsigned int max_size,unsigned int num_channels)30 float_buffer_create(unsigned int max_size, unsigned int num_channels)
31 {
32 struct float_buffer *b;
33
34 b = (struct float_buffer *)calloc(1, sizeof(*b));
35
36 b->num_channels = num_channels;
37 b->fp = (float **)malloc(num_channels * sizeof(float *));
38 b->buf = (struct byte_buffer *)calloc(
39 1, sizeof(struct byte_buffer) +
40 sizeof(float) * max_size * num_channels);
41 b->buf->max_size = max_size;
42 b->buf->used_size = max_size;
43 return b;
44 }
45
46 /* Destroys the float buffer. */
float_buffer_destroy(struct float_buffer ** b)47 static inline void float_buffer_destroy(struct float_buffer **b)
48 {
49 if (*b == NULL)
50 return;
51
52 byte_buffer_destroy(&(*b)->buf);
53 free((*b)->fp);
54 free(*b);
55 *b = NULL;
56 }
57
58 /* Gets the write pointer of given float_buffer. */
float_buffer_write_pointer(struct float_buffer * b)59 static inline float *const *float_buffer_write_pointer(struct float_buffer *b)
60 {
61 unsigned int i;
62 float *data = (float *)b->buf->bytes;
63
64 for (i = 0; i < b->num_channels; i++, data += b->buf->max_size)
65 b->fp[i] = data + b->buf->write_idx;
66 return b->fp;
67 }
68
69 /* Gets the number of frames can write to the float_buffer. */
float_buffer_writable(struct float_buffer * b)70 static inline unsigned int float_buffer_writable(struct float_buffer *b)
71 {
72 return buf_writable(b->buf);
73 }
74
75 /* Marks |nwritten| of frames as written to float_buffer. */
float_buffer_written(struct float_buffer * b,unsigned int nwritten)76 static inline void float_buffer_written(struct float_buffer *b,
77 unsigned int nwritten)
78 {
79 buf_increment_write(b->buf, nwritten);
80 }
81
82 /* Gets the read pointer of given float_buffer. */
float_buffer_read_pointer(struct float_buffer * b,unsigned int offset,unsigned int * readable)83 static inline float *const *float_buffer_read_pointer(struct float_buffer *b,
84 unsigned int offset,
85 unsigned int *readable)
86 {
87 unsigned int i;
88 float *data = (float *)b->buf->bytes;
89 unsigned int nread = buf_readable(b->buf);
90
91 if (offset >= buf_queued(b->buf)) {
92 *readable = 0;
93 offset = 0;
94 } else if (offset >= nread) {
95 /* wraps */
96 offset = offset + b->buf->read_idx - b->buf->max_size;
97 *readable = MIN(*readable, b->buf->write_idx - offset);
98 } else {
99 *readable = MIN(*readable, nread - offset);
100 offset += b->buf->read_idx;
101 }
102
103 for (i = 0; i < b->num_channels; i++, data += b->buf->max_size)
104 b->fp[i] = data + offset;
105 return b->fp;
106 }
107
108 /* Gets the buffer level in frames queued in float_buffer. */
float_buffer_level(struct float_buffer * b)109 static inline unsigned int float_buffer_level(struct float_buffer *b)
110 {
111 return buf_queued(b->buf);
112 }
113
114 /* Resets float_buffer to initial state. */
float_buffer_reset(struct float_buffer * b)115 static inline void float_buffer_reset(struct float_buffer *b)
116 {
117 buf_reset(b->buf);
118 }
119
120 /* Marks |nread| frames as read in float_buffer. */
float_buffer_read(struct float_buffer * b,unsigned int nread)121 static inline void float_buffer_read(struct float_buffer *b, unsigned int nread)
122 {
123 buf_increment_read(b->buf, nread);
124 }
125
126 #endif /* FLOAT_BUFFER_H_ */
127