Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/cubeb/src/cubeb_ring_array.h
4246 views
1
/*
2
* Copyright © 2016 Mozilla Foundation
3
*
4
* This program is made available under an ISC-style license. See the
5
* accompanying file LICENSE for details.
6
*/
7
8
#ifndef CUBEB_RING_ARRAY_H
9
#define CUBEB_RING_ARRAY_H
10
11
#include "cubeb_utils.h"
12
#include <CoreAudio/CoreAudioTypes.h>
13
14
/** Ring array of pointers is used to hold buffers. In case that
15
asynchronous producer/consumer callbacks do not arrive in a
16
repeated order the ring array stores the buffers and fetch
17
them in the correct order. */
18
19
typedef struct {
20
AudioBuffer * buffer_array; /**< Array that hold pointers of the allocated
21
space for the buffers. */
22
unsigned int tail; /**< Index of the last element (first to deliver). */
23
unsigned int count; /**< Number of elements in the array. */
24
unsigned int capacity; /**< Total length of the array. */
25
} ring_array;
26
27
static int
28
single_audiobuffer_init(AudioBuffer * buffer, uint32_t bytesPerFrame,
29
uint32_t channelsPerFrame, uint32_t frames)
30
{
31
assert(buffer);
32
assert(bytesPerFrame > 0 && channelsPerFrame && frames > 0);
33
34
size_t size = bytesPerFrame * frames;
35
buffer->mData = operator new(size);
36
if (buffer->mData == NULL) {
37
return CUBEB_ERROR;
38
}
39
PodZero(static_cast<char *>(buffer->mData), size);
40
41
buffer->mNumberChannels = channelsPerFrame;
42
buffer->mDataByteSize = size;
43
44
return CUBEB_OK;
45
}
46
47
/** Initialize the ring array.
48
@param ra The ring_array pointer of allocated structure.
49
@retval 0 on success. */
50
static int
51
ring_array_init(ring_array * ra, uint32_t capacity, uint32_t bytesPerFrame,
52
uint32_t channelsPerFrame, uint32_t framesPerBuffer)
53
{
54
assert(ra);
55
if (capacity == 0 || bytesPerFrame == 0 || channelsPerFrame == 0 ||
56
framesPerBuffer == 0) {
57
return CUBEB_ERROR_INVALID_PARAMETER;
58
}
59
ra->capacity = capacity;
60
ra->tail = 0;
61
ra->count = 0;
62
63
ra->buffer_array = new AudioBuffer[ra->capacity];
64
PodZero(ra->buffer_array, ra->capacity);
65
if (ra->buffer_array == NULL) {
66
return CUBEB_ERROR;
67
}
68
69
for (unsigned int i = 0; i < ra->capacity; ++i) {
70
if (single_audiobuffer_init(&ra->buffer_array[i], bytesPerFrame,
71
channelsPerFrame,
72
framesPerBuffer) != CUBEB_OK) {
73
return CUBEB_ERROR;
74
}
75
}
76
77
return CUBEB_OK;
78
}
79
80
/** Destroy the ring array.
81
@param ra The ring_array pointer.*/
82
static void
83
ring_array_destroy(ring_array * ra)
84
{
85
assert(ra);
86
if (ra->buffer_array == NULL) {
87
return;
88
}
89
for (unsigned int i = 0; i < ra->capacity; ++i) {
90
if (ra->buffer_array[i].mData) {
91
operator delete(ra->buffer_array[i].mData);
92
}
93
}
94
delete[] ra->buffer_array;
95
}
96
97
/** Get the allocated buffer to be stored with fresh data.
98
@param ra The ring_array pointer.
99
@retval Pointer of the allocated space to be stored with fresh data or NULL
100
if full. */
101
static AudioBuffer *
102
ring_array_get_free_buffer(ring_array * ra)
103
{
104
assert(ra && ra->buffer_array);
105
assert(ra->buffer_array[0].mData != NULL);
106
if (ra->count == ra->capacity) {
107
return NULL;
108
}
109
110
assert(ra->count == 0 || (ra->tail + ra->count) % ra->capacity != ra->tail);
111
AudioBuffer * ret = &ra->buffer_array[(ra->tail + ra->count) % ra->capacity];
112
113
++ra->count;
114
assert(ra->count <= ra->capacity);
115
116
return ret;
117
}
118
119
/** Get the next available buffer with data.
120
@param ra The ring_array pointer.
121
@retval Pointer of the next in order data buffer or NULL if empty. */
122
static AudioBuffer *
123
ring_array_get_data_buffer(ring_array * ra)
124
{
125
assert(ra && ra->buffer_array);
126
assert(ra->buffer_array[0].mData != NULL);
127
128
if (ra->count == 0) {
129
return NULL;
130
}
131
AudioBuffer * ret = &ra->buffer_array[ra->tail];
132
133
ra->tail = (ra->tail + 1) % ra->capacity;
134
assert(ra->tail < ra->capacity);
135
136
assert(ra->count > 0);
137
--ra->count;
138
139
return ret;
140
}
141
142
#endif // CUBEB_RING_ARRAY_H
143
144