26 |
#define DEFAULT_WRAP_ELEMENTS 1024 |
#define DEFAULT_WRAP_ELEMENTS 1024 |
27 |
|
|
28 |
#include <string.h> |
#include <string.h> |
|
#include <stdio.h> |
|
|
|
|
|
#include <sys/types.h> |
|
|
#include <pthread.h> |
|
29 |
|
|
30 |
#include "atomic.h" |
#include "atomic.h" |
31 |
|
|
97 |
__inline T *get_write_ptr(); |
__inline T *get_write_ptr(); |
98 |
__inline void increment_read_ptr(int cnt) { |
__inline void increment_read_ptr(int cnt) { |
99 |
atomic_set(&read_ptr , (atomic_read(&read_ptr) + cnt) & size_mask); |
atomic_set(&read_ptr , (atomic_read(&read_ptr) + cnt) & size_mask); |
100 |
} |
} |
101 |
__inline void set_read_ptr(int val) { |
__inline void set_read_ptr(int val) { |
102 |
atomic_set(&read_ptr , val); |
atomic_set(&read_ptr , val); |
103 |
} |
} |
104 |
|
|
105 |
__inline void increment_write_ptr(int cnt) { |
__inline void increment_write_ptr(int cnt) { |
106 |
atomic_set(&write_ptr, (atomic_read(&write_ptr) + cnt) & size_mask); |
atomic_set(&write_ptr, (atomic_read(&write_ptr) + cnt) & size_mask); |
107 |
} |
} |
108 |
|
|
109 |
/* this function increments the write_ptr by cnt, if the buffer wraps then |
/* this function increments the write_ptr by cnt, if the buffer wraps then |
110 |
subtract size from the write_ptr value so that it stays within 0<write_ptr<size |
subtract size from the write_ptr value so that it stays within 0<write_ptr<size |
115 |
interpolation. So that the audio thread sees the ringbuffer like a linear space |
interpolation. So that the audio thread sees the ringbuffer like a linear space |
116 |
which allows us to use faster routines. |
which allows us to use faster routines. |
117 |
When the buffer wraps the wrap part is memcpy()ied to the beginning of the buffer |
When the buffer wraps the wrap part is memcpy()ied to the beginning of the buffer |
118 |
and the write ptr incremented accordingly. |
and the write ptr incremented accordingly. |
119 |
*/ |
*/ |
120 |
__inline void increment_write_ptr_with_wrap(int cnt) { |
__inline void increment_write_ptr_with_wrap(int cnt) { |
121 |
int w=atomic_read(&write_ptr); |
int w=atomic_read(&write_ptr); |
124 |
w -= size; |
w -= size; |
125 |
memcpy(&buf[0], &buf[size], w*sizeof(T)); |
memcpy(&buf[0], &buf[size], w*sizeof(T)); |
126 |
//printf("DEBUG !!!! increment_write_ptr_with_wrap: buffer wrapped, elements wrapped = %d (wrap_elements %d)\n",w,wrap_elements); |
//printf("DEBUG !!!! increment_write_ptr_with_wrap: buffer wrapped, elements wrapped = %d (wrap_elements %d)\n",w,wrap_elements); |
127 |
} |
} |
128 |
atomic_set(&write_ptr, w); |
atomic_set(&write_ptr, w); |
129 |
} |
} |
130 |
|
|
131 |
/* this function returns the available write space in the buffer |
/* this function returns the available write space in the buffer |
132 |
when the read_ptr > write_ptr it returns the space inbetween, otherwise |
when the read_ptr > write_ptr it returns the space inbetween, otherwise |
167 |
/* this function adjusts the number of elements to write into the ringbuffer |
/* this function adjusts the number of elements to write into the ringbuffer |
168 |
in a way that the size boundary is avoided and that the wrap space always gets |
in a way that the size boundary is avoided and that the wrap space always gets |
169 |
entirely filled. |
entirely filled. |
170 |
cnt contains the write_space_to_end_with_wrap() amount while |
cnt contains the write_space_to_end_with_wrap() amount while |
171 |
capped_cnt contains a capped amount of samples to read. |
capped_cnt contains a capped amount of samples to read. |
172 |
normally capped_cnt == cnt but in some cases eg when the disk thread needs |
normally capped_cnt == cnt but in some cases eg when the disk thread needs |
173 |
to refill tracks with smaller blocks because lots of streams require immediate |
to refill tracks with smaller blocks because lots of streams require immediate |
174 |
refill because lots of notes were started simultaneously. |
refill because lots of notes were started simultaneously. |
175 |
In that case we set for example capped_cnt to a fixed amount (< cnt, eg 64k), |
In that case we set for example capped_cnt to a fixed amount (< cnt, eg 64k), |
176 |
which helps to reduce the buffer refill latencies that occur between streams. |
which helps to reduce the buffer refill latencies that occur between streams. |
177 |
the first if() checks if the current write_ptr + capped_cnt resides within |
the first if() checks if the current write_ptr + capped_cnt resides within |
178 |
the wrap area but is < size+wrap_elements. in that case we cannot return |
the wrap area but is < size+wrap_elements. in that case we cannot return |
179 |
capped_cnt because it would lead to a write_ptr wrapping and only a partial fill |
capped_cnt because it would lead to a write_ptr wrapping and only a partial fill |
180 |
of wrap space which would lead to errors. So we simply return cnt which ensures |
of wrap space which would lead to errors. So we simply return cnt which ensures |
181 |
that the the entire wrap space will get filled correctly. |
that the the entire wrap space will get filled correctly. |
182 |
In all other cases (which are not problematic because no write_ptr wrapping |
In all other cases (which are not problematic because no write_ptr wrapping |
183 |
occurs) we simply return capped_cnt. |
occurs) we simply return capped_cnt. |
184 |
*/ |
*/ |
185 |
__inline int adjust_write_space_to_avoid_boundary(int cnt, int capped_cnt) { |
__inline int adjust_write_space_to_avoid_boundary(int cnt, int capped_cnt) { |
285 |
} |
} |
286 |
|
|
287 |
to_read = cnt > free_cnt ? free_cnt : cnt; |
to_read = cnt > free_cnt ? free_cnt : cnt; |
288 |
|
|
289 |
cnt2 = priv_read_ptr + to_read; |
cnt2 = priv_read_ptr + to_read; |
290 |
|
|
291 |
if (cnt2 > size) { |
if (cnt2 > size) { |
295 |
n1 = to_read; |
n1 = to_read; |
296 |
n2 = 0; |
n2 = 0; |
297 |
} |
} |
298 |
|
|
299 |
memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T)); |
memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T)); |
300 |
priv_read_ptr = (priv_read_ptr + n1) & size_mask; |
priv_read_ptr = (priv_read_ptr + n1) & size_mask; |
301 |
|
|
325 |
} |
} |
326 |
|
|
327 |
to_write = cnt > free_cnt ? free_cnt : cnt; |
to_write = cnt > free_cnt ? free_cnt : cnt; |
328 |
|
|
329 |
cnt2 = priv_write_ptr + to_write; |
cnt2 = priv_write_ptr + to_write; |
330 |
|
|
331 |
if (cnt2 > size) { |
if (cnt2 > size) { |