summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorXANTRONIX Development2022-02-02 00:12:09 -0500
committerXANTRONIX Development2022-02-02 00:12:09 -0500
commit37566c51d0e80fbf3837b6527c501727521e92cd (patch)
treec8af3ea836c2b91c41bd02145d4f769ed219be15 /src
parent45a040e8d17da6550dd389725bc7c482ba99f6ab (diff)
downloadxas-37566c51d0e80fbf3837b6527c501727521e92cd.tar.gz
xas-37566c51d0e80fbf3837b6527c501727521e92cd.tar.bz2
xas-37566c51d0e80fbf3837b6527c501727521e92cd.zip
nailed it
Diffstat (limited to 'src')
-rw-r--r--src/audio.c78
1 files changed, 49 insertions, 29 deletions
diff --git a/src/audio.c b/src/audio.c
index 8853164..10f7a34 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -106,50 +106,70 @@ static inline void *ptr(xas_audio_stream *stream, void *buf, size_t index) {
ssize_t xas_audio_stream_write(xas_audio_stream *stream,
void *samples,
size_t count) {
- size_t left = count,
- index = 0;
+ size_t index_i = 0;
- if (stream->buffer_count > 0) {
- size_t remainder = stream->buffer_size - stream->buffer_count;
+ if (stream->buffer_count + count > stream->buffer_size) {
+ /*
+ * If the number of samples offered, plus the number of items currently
+ * in the buffer exceeds the buffer size, fill the buffer to capacity
+ * and flush it.
+ */
+ size_t remaining = stream->buffer_size - stream->buffer_count;
memcpy(ptr(stream, stream + 1, stream->buffer_count),
- ptr(stream, samples, 0),
- stream->sample_size * stream->channels * remainder);
+ ptr(stream, samples, index_i),
+ remaining * stream->sample_size * stream->channels);
- stream->buffer_count += remainder;
-
- if (stream_flush(stream) < 0) {
- goto error_stream_flush;
- }
-
- left -= remainder;
- index += remainder;
- }
-
- while (left > stream->buffer_size) {
if (stream->drain(stream->ctx,
- ptr(stream, samples, index),
+ ptr(stream, stream + 1, 0),
stream->buffer_size,
stream) < 0) {
goto error_stream_drain;
}
- left -= stream->buffer_size;
- index += stream->buffer_size;
- }
+ index_i += remaining;
- memcpy(ptr(stream, stream + 1, 0),
- ptr(stream, samples, index),
- stream->sample_size * stream->channels * left);
-
- stream->buffer_count = left;
+ stream->buffer_count = 0;
+ }
- index += left;
+ /*
+ * While there are still samples to buffer or flush...
+ */
+ while (index_i < count) {
+ size_t remaining = count - index_i;
+
+ if (remaining >= stream->buffer_size) {
+ /*
+ * If the number of samples remaining is greater than the target
+ * buffer size, then drain directly from the source buffer to the
+ * output an amount equal to the buffer size.
+ */
+ if (stream->drain(stream->ctx,
+ ptr(stream, samples, index_i),
+ stream->buffer_size,
+ stream) < 0) {
+ goto error_stream_drain;
+ }
+
+ index_i += stream->buffer_size;
+ } else {
+ /*
+ * Enough of the input has been drained that it can be copied to
+ * the target buffer.
+ */
+ memcpy(ptr(stream, stream + 1, stream->buffer_count),
+ ptr(stream, samples, index_i),
+ remaining * stream->sample_size * stream->channels);
+
+ index_i += remaining;
+
+ stream->buffer_count += remaining;
+ }
+ }
- return index;
+ return 0;
error_stream_drain:
-error_stream_flush:
return -1;
}