]> git.bts.cx Git - benzene.git/blob - src/bz/audio/ogg.c
Sprites
[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 }