]> git.bts.cx Git - benzene.git/blob - src/bz/audio/ogg.c
Fixed Aseprite rendering system
[benzene.git] / src / bz / audio / ogg.c
1 #include <bz/audio/ogg.h>
2
3 #include <bz/memory/allocator.h>
4 #include <bz/resources/resource.h>
5 #include <bz/types/identifier_internal.h>
6
7 #include <stb_vorbis.c>
8
9 struct BZAudioOGGStream {
10         BZAudioOGGStreamDetails details;
11         BZResourceID handle;
12         size_t dataBlockSize;
13 //      uint8_t *dataBlock;
14 //      uint32_t rate;
15 //      uint8_t channels;
16         stb_vorbis *vorbis;
17 };
18
19 BZAudioOGGStream *bzAudioOpenOGGStream(BZAudioOGGStreamDetails *detailsOut, BZMemoryArenaID arena, const char *identifierFmt, ...) {
20         bzMakeIdentifier(identifier, identifierFmt);
21
22         BZAudioOGGStream *stream = bzMemoryAlloc(arena, sizeof(BZAudioOGGStream));
23
24         stream->handle = bzResourcesOpenResource("music", "assets/music/%s.ogg", identifier);
25         
26         size_t initialSize = 128;
27         int memoryConsumed, error;
28         for (;;) {
29                 bzResourcesSeek(stream->handle, 0);
30
31                 void *initialData = bzMemoryAllocTmp(arena, initialSize);// FIXME, realloc
32                 bzResourcesReadBytes(stream->handle, initialData, initialSize);
33
34                 stream->vorbis = stb_vorbis_open_pushdata(initialData, initialSize, &memoryConsumed, &error, NULL); // FIXME, temp memory
35                 if (stream->vorbis != NULL) {
36                         break;
37                 }
38                 bzAssert(error == VORBIS_need_more_data);
39                 initialSize <<= 1;
40                 bzMemoryArenaResetTmp(arena);
41         }
42
43         bzResourcesSeek(stream->handle, memoryConsumed);
44
45         stb_vorbis_info info = stb_vorbis_get_info(stream->vorbis);
46
47         stream->details = (BZAudioOGGStreamDetails) {
48                 .rate = info.sample_rate,
49                 .channels = info.channels,
50                 .maxSamples = info.max_frame_size,
51         };
52
53         if (detailsOut != NULL) {
54                 *detailsOut = stream->details;
55         }
56
57         stream->dataBlockSize = info.temp_memory_required;
58
59         //*outputSizeOut = stream->dataBlockSize;
60
61 //      stream->dataBlock = bzMemoryAlloc(arena, stream->dataBlockSize);
62
63 //      stream->rate = info.sample_rate;
64 //      stream->channels = info.channels;
65
66         //bzResourcesCloseResource(handle);
67
68         return stream;
69 }
70 //size_t *samplesOut, uint32_t *rateOut, uint8_t *channelsOut, 
71
72 void bzAudioResetOGGData(BZAudioOGGStream *stream) {
73         bzResourcesSeek(stream->handle, 0);
74         stb_vorbis_flush_pushdata(stream->vorbis);
75 }
76
77 size_t bzAudioQueryOGGData(BZAudioOGGStream *stream, size_t maxDataSize, float *data) {
78         float **output;
79         size_t samples = 0;
80
81         void *dataBlock = alloca(stream->dataBlockSize); // FIXME
82
83         for (;;) {
84                 size_t offset = bzResourcesTell(stream->handle);
85                 bzResourcesReadBytes(stream->handle, dataBlock, stream->dataBlockSize);
86                 size_t bytesUsed = stb_vorbis_decode_frame_pushdata(stream->vorbis, dataBlock, stream->dataBlockSize, NULL, &output, &samples);
87                 if (bytesUsed == 0 && samples == 0) {
88                         break;
89                 }
90                 //bzAssert(bytesUsed != 0 || samples != 0);
91                 bzResourcesSeek(stream->handle, offset + bytesUsed);
92                 if (samples > 0) {
93                         break;
94                 }
95         }
96
97         for (size_t i = 0, out = 0; i < samples; ++i) {
98                 for (size_t j = 0; j < stream->details.channels; ++j, ++out) {
99                         data[out] = output[j][i];
100                 }
101         }
102
103         return samples * stream->details.channels * sizeof(float);
104 }
105
106 void bzAudioCloseOGGStream(BZAudioOGGStream *stream) {
107         stb_vorbis_close(stream->vorbis);
108         bzResourcesCloseResource(stream->handle);
109 }