Initial attempt at timestretching implementation.
[calfbox.git] / fifo.h
blobd9446cdbf5d47752cf7df42b9591288021c8562c
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2013 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef CBOX_FIFO_H
20 #define CBOX_FIFO_H
22 #include <assert.h>
23 #include <stdint.h>
24 #include <glib.h>
25 #include <string.h>
27 struct cbox_fifo
29 uint8_t *data;
30 uint32_t size;
31 uint64_t pad; // ensure the write-related and read-related structs are on 64 bit boundary
32 uint32_t write_count;
33 uint32_t write_offset;
34 uint32_t read_count;
35 uint32_t read_offset;
38 extern struct cbox_fifo *cbox_fifo_new(uint32_t size);
40 static inline uint32_t cbox_fifo_readsize(struct cbox_fifo *fifo);
41 static inline uint32_t cbox_fifo_writespace(struct cbox_fifo *fifo);
42 static inline gboolean cbox_fifo_read_atomic(struct cbox_fifo *fifo, void *dest, uint32_t bytes);
43 static inline gboolean cbox_fifo_write_atomic(struct cbox_fifo *fifo, const void *src, uint32_t bytes);
44 static inline gboolean cbox_fifo_peek(struct cbox_fifo *fifo, void *dest, uint32_t bytes);
45 static inline gboolean cbox_fifo_consume(struct cbox_fifo *fifo, uint32_t bytes);
47 extern void cbox_fifo_destroy(struct cbox_fifo *fifo);
50 static inline uint32_t cbox_fifo_readsize(struct cbox_fifo *fifo)
52 return fifo->write_count - fifo->read_count;
55 static inline uint32_t cbox_fifo_writespace(struct cbox_fifo *fifo)
57 return fifo->size - (fifo->write_count - fifo->read_count);
60 static inline gboolean cbox_fifo_read_impl(struct cbox_fifo *fifo, void *dest, uint32_t bytes, gboolean advance)
62 __sync_synchronize();
63 if (fifo->write_count - fifo->read_count < bytes)
64 return FALSE;
66 if (dest)
68 uint32_t ofs = fifo->read_count - fifo->read_offset;
69 assert(ofs >= 0 && ofs < fifo->size);
70 if (ofs + bytes > fifo->size)
72 uint8_t *dstb = dest;
73 uint32_t firstpart = fifo->size - ofs;
74 memcpy(dstb, fifo->data + ofs, firstpart);
75 memcpy(dstb + firstpart, fifo->data, bytes - firstpart);
77 else
78 memcpy(dest, fifo->data + ofs, bytes);
81 if (advance)
83 __sync_synchronize();
84 // Make sure data are copied before signalling that they can be overwritten
85 fifo->read_count += bytes;
86 if (fifo->read_count - fifo->read_offset >= fifo->size)
87 fifo->read_offset += fifo->size;
89 __sync_synchronize();
91 return TRUE;
94 static inline gboolean cbox_fifo_read_atomic(struct cbox_fifo *fifo, void *dest, uint32_t bytes)
96 return cbox_fifo_read_impl(fifo, dest, bytes, TRUE);
99 static inline gboolean cbox_fifo_peek(struct cbox_fifo *fifo, void *dest, uint32_t bytes)
101 return cbox_fifo_read_impl(fifo, dest, bytes, FALSE);
104 static inline gboolean cbox_fifo_consume(struct cbox_fifo *fifo, uint32_t bytes)
106 return cbox_fifo_read_impl(fifo, NULL, bytes, TRUE);
109 static inline gboolean cbox_fifo_write_atomic(struct cbox_fifo *fifo, const void *src, uint32_t bytes)
111 if (fifo->size - (fifo->write_count - fifo->read_count) < bytes)
112 return FALSE;
114 uint32_t ofs = fifo->write_count - fifo->write_offset;
115 assert(ofs >= 0 && ofs < fifo->size);
116 if (ofs + bytes > fifo->size)
118 const uint8_t *srcb = src;
119 uint32_t firstpart = fifo->size - ofs;
120 memcpy(fifo->data + ofs, srcb, firstpart);
121 memcpy(fifo->data, srcb + firstpart, bytes - firstpart);
123 else
124 memcpy(fifo->data + ofs, src, bytes);
126 // Make sure data are in the buffer before announcing the availability
127 __sync_synchronize();
128 fifo->write_count += bytes;
129 if (fifo->write_count - fifo->write_offset >= fifo->size)
130 fifo->write_offset += fifo->size;
132 return TRUE;
136 #endif