diff options
Diffstat (limited to 'src/audio/buf.c')
-rw-r--r-- | src/audio/buf.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/audio/buf.c b/src/audio/buf.c new file mode 100644 index 00000000..e61164d4 --- /dev/null +++ b/src/audio/buf.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are met: | ||
5 | |||
6 | 1. Redistributions of source code must retain the above copyright notice, this | ||
7 | list of conditions and the following disclaimer. | ||
8 | 2. Redistributions in binary form must reproduce the above copyright notice, | ||
9 | this list of conditions and the following disclaimer in the documentation | ||
10 | and/or other materials provided with the distribution. | ||
11 | |||
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | ||
22 | |||
23 | #include "buf.h" | ||
24 | |||
25 | iDefineTypeConstruction(InputBuf) | ||
26 | |||
27 | void init_InputBuf(iInputBuf *d) { | ||
28 | init_Mutex(&d->mtx); | ||
29 | init_Condition(&d->changed); | ||
30 | init_Block(&d->data, 0); | ||
31 | d->isComplete = iTrue; | ||
32 | } | ||
33 | |||
34 | void deinit_InputBuf(iInputBuf *d) { | ||
35 | deinit_Block(&d->data); | ||
36 | deinit_Condition(&d->changed); | ||
37 | deinit_Mutex(&d->mtx); | ||
38 | } | ||
39 | |||
40 | size_t size_InputBuf(const iInputBuf *d) { | ||
41 | return size_Block(&d->data); | ||
42 | } | ||
43 | |||
44 | /*----------------------------------------------------------------------------------------------*/ | ||
45 | |||
46 | iDefineTypeConstructionArgs(SampleBuf, (SDL_AudioFormat format, size_t numChannels, size_t count), | ||
47 | format, numChannels, count) | ||
48 | |||
49 | void init_SampleBuf(iSampleBuf *d, SDL_AudioFormat format, size_t numChannels, size_t count) { | ||
50 | d->format = format; | ||
51 | d->numChannels = numChannels; | ||
52 | d->sampleSize = SDL_AUDIO_BITSIZE(format) / 8 * numChannels; | ||
53 | d->count = count + 1; /* considered empty if head==tail */ | ||
54 | d->data = malloc(d->sampleSize * d->count); | ||
55 | d->head = 0; | ||
56 | d->tail = 0; | ||
57 | init_Condition(&d->moreNeeded); | ||
58 | } | ||
59 | |||
60 | void deinit_SampleBuf(iSampleBuf *d) { | ||
61 | deinit_Condition(&d->moreNeeded); | ||
62 | free(d->data); | ||
63 | } | ||
64 | |||
65 | size_t size_SampleBuf(const iSampleBuf *d) { | ||
66 | return d->head - d->tail; | ||
67 | } | ||
68 | |||
69 | size_t vacancy_SampleBuf(const iSampleBuf *d) { | ||
70 | return d->count - size_SampleBuf(d) - 1; | ||
71 | } | ||
72 | |||
73 | iBool isFull_SampleBuf(const iSampleBuf *d) { | ||
74 | return vacancy_SampleBuf(d) == 0; | ||
75 | } | ||
76 | |||
77 | void write_SampleBuf(iSampleBuf *d, const void *samples, const size_t n) { | ||
78 | iAssert(n <= vacancy_SampleBuf(d)); | ||
79 | const size_t headPos = d->head % d->count; | ||
80 | const size_t avail = d->count - headPos; | ||
81 | if (n > avail) { | ||
82 | const char *in = samples; | ||
83 | memcpy(ptr_SampleBuf_(d, headPos), in, d->sampleSize * avail); | ||
84 | in += d->sampleSize * avail; | ||
85 | memcpy(ptr_SampleBuf_(d, 0), in, d->sampleSize * (n - avail)); | ||
86 | } | ||
87 | else { | ||
88 | memcpy(ptr_SampleBuf_(d, headPos), samples, d->sampleSize * n); | ||
89 | } | ||
90 | d->head += n; | ||
91 | } | ||
92 | |||
93 | void read_SampleBuf(iSampleBuf *d, const size_t n, void *samples_out) { | ||
94 | iAssert(n <= size_SampleBuf(d)); | ||
95 | const size_t tailPos = d->tail % d->count; | ||
96 | const size_t avail = d->count - tailPos; | ||
97 | if (n > avail) { | ||
98 | char *out = samples_out; | ||
99 | memcpy(out, ptr_SampleBuf_(d, tailPos), d->sampleSize * avail); | ||
100 | out += d->sampleSize * avail; | ||
101 | memcpy(out, ptr_SampleBuf_(d, 0), d->sampleSize * (n - avail)); | ||
102 | } | ||
103 | else { | ||
104 | memcpy(samples_out, ptr_SampleBuf_(d, tailPos), d->sampleSize * n); | ||
105 | } | ||
106 | d->tail += n; | ||
107 | } | ||