1 /*
2     Copyright © 2020, Luna Nielsen
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors: Luna Nielsen
6 */
7 module vorbisfile;
8 import core.stdc.config;
9 
10 alias ogg_int64_t = long;
11 alias ogg_uint64_t = ulong;
12 alias ogg_int32_t = int;
13 alias ogg_uint32_t = uint;
14 alias ogg_int16_t = short;
15 alias ogg_uint16_t = ushort;
16 
17 struct vorbis_info {
18     int _version; // Renamed from "version", since that's a keyword in D
19     int channels;
20     int rate;
21     c_long bitrate_upper;
22     c_long bitrate_nominal;
23     c_long bitrate_lower;
24     c_long bitrate_window;
25 
26     void *codec_setup;
27 }
28 
29 struct vorbis_dsp_state {
30     int analysisp;
31     vorbis_info* vi;
32     float** pcm;
33     float** pcmret;
34     int pcm_storage;
35     int pcm_current;
36     int pcm_returned;
37     int preextrapolate;
38     int eofflag;
39     c_long lW;
40     c_long W;
41     c_long nW;
42     c_long centerW;
43     ogg_int64_t granulepos;
44     ogg_int64_t sequence;
45     ogg_int64_t glue_bits;
46     ogg_int64_t time_bits;
47     ogg_int64_t floor_bits;
48     ogg_int64_t res_bits;
49     void* backend_state;
50 }
51 
52 struct vorbis_comment {
53     char** user_comments;
54     int* comment_lengths;
55     int comments;
56     char* vendor;
57 }
58 
59 struct alloc_chain {
60     void* ptr;
61     alloc_chain* next;
62 }
63 
64 struct vorbis_block {
65     float** pcm;
66     oggpack_buffer opb;
67     c_long lW;
68     c_long W;
69     c_long nW;
70     int pcmend;
71     int mode;
72     int eofflag;
73     ogg_int64_t granulepos;
74     ogg_int64_t sequence;
75     vorbis_dsp_state* vd;
76     void* localstore;
77     c_long localtop;
78     c_long localalloc;
79     c_long totaluse;
80     alloc_chain* reap;
81     c_long glue_bits;
82     c_long time_bits;
83     c_long floor_bits;
84     c_long res_bits;
85     void* internal;
86 }
87 
88 
89 struct ogg_iovec_t {
90     void* iov_base;
91     size_t iov_len;
92 }
93 
94 struct oggpack_buffer {
95     c_long endbyte;
96     int endbit;
97     ubyte* buffer;
98     ubyte* ptr;
99     c_long storage;
100 }
101 
102 struct ogg_page {
103     ubyte* header;
104     c_long header_len;
105     ubyte* _body;       // originally named "body", but that's a keyword in D.
106     c_long body_len;
107 }
108 
109 struct ogg_stream_state {
110     ubyte* body_data;
111     c_long body_storage;
112     c_long body_fill;
113     c_long body_returned;
114     int* lacing_vals;
115     ogg_int64_t* granule_vals;
116     c_long lacing_storage;
117     c_long lacing_fill;
118     c_long lacing_packet;
119     c_long lacing_returned;
120     ubyte[282] header;
121     int header_fill;
122     int e_o_s;
123     int b_o_s;
124     c_long serialno;
125     c_long pageno;
126     ogg_int64_t packetno;
127     ogg_int64_t granulepos;
128 }
129 
130 struct ogg_packet {
131     ubyte* packet;
132     c_long bytes;
133     c_long b_o_s;
134     c_long e_o_s;
135     ogg_int64_t granulepos;
136     ogg_int64_t packetno;
137 }
138 
139 struct ogg_sync_state {
140     ubyte* data;
141     int storage;
142     int fill;
143     int returned;
144 
145     int unsynced;
146     int headerbytes;
147     int bodybytes;
148 }
149 
150 struct ov_callbacks {
151     extern(C) nothrow {
152         size_t function(void*, size_t, size_t, void*) read_func;
153         int function(void*, ogg_int64_t, int) seek_func;
154         int function(void*) close_func;
155         c_long function(void*) tell_func;
156     }
157 }
158 
159 enum {
160     NOTOPEN =0,
161     PARTOPEN =1,
162     OPENED =2,
163     STREAMSET =3,
164     INITSET =4,
165     
166     OV_FALSE      = -1,
167     OV_EOF        = -2,
168     OV_HOLE       = -3,
169     OV_EREAD      = -128,
170     OV_EFAULT     = -129,
171     OV_EIMPL      = -130,
172     OV_EINVAL     = -131,
173     OV_ENOTVORBIS = -132,
174     OV_EBADHEADER = -133,
175     OV_EVERSION   = -134,
176     OV_ENOTAUDIO  = -135,
177     OV_EBADPACKET = -136,
178     OV_EBADLINK   = -137,
179     OV_ENOSEEK    = -138,
180 }
181 
182 struct OggVorbis_File {
183     void* datasource;
184     int seekable;
185     ogg_int64_t offset;
186     ogg_int64_t end;
187     ogg_sync_state oy;
188     int links;
189     ogg_int64_t* offsets;
190     ogg_int64_t* dataoffsets;
191     c_long* serialnos;
192     ogg_int64_t* pcmlengths;
193     vorbis_info* vi;
194     vorbis_comment* vc;
195     ogg_int64_t pcm_offset;
196     int ready_state;
197     c_long current_serialno;
198     int current_link;
199     double bittrack;
200     double samptrack;
201     ogg_stream_state os;
202     vorbis_dsp_state vd;
203     vorbis_block vb;
204     ov_callbacks callbacks;
205 }
206 
207 extern(C) @nogc nothrow __gshared:
208 int ov_clear(OggVorbis_File*);
209 int ov_fopen(const(char)*, OggVorbis_File*);
210 int ov_open_callbacks(void* datasource, OggVorbis_File*, const(char)*, c_long, ov_callbacks);
211 int ov_test_callbacks(void*, OggVorbis_File*, const(char)*, c_long, ov_callbacks);
212 int ov_test_open(OggVorbis_File*);
213 c_long ov_bitrate(OggVorbis_File*, int);
214 c_long ov_bitrate_instant(OggVorbis_File*);
215 c_long ov_streams(OggVorbis_File*);
216 c_long ov_seekable(OggVorbis_File*);
217 c_long ov_serialnumber(OggVorbis_File*, int);
218 ogg_int64_t ov_raw_total(OggVorbis_File*, int);
219 ogg_int64_t ov_pcm_total(OggVorbis_File*, int);
220 double ov_time_total(OggVorbis_File*, int);
221 int ov_raw_seek(OggVorbis_File*, ogg_int64_t);
222 int ov_pcm_seek(OggVorbis_File*, ogg_int64_t);
223 int ov_pcm_seek_page(OggVorbis_File*, ogg_int64_t);
224 int ov_time_seek(OggVorbis_File*, double);
225 int ov_time_seek_page(OggVorbis_File*, double);
226 int ov_raw_seek_lap(OggVorbis_File*, ogg_int64_t);
227 int ov_pcm_seek_lap(OggVorbis_File*, ogg_int64_t);
228 int ov_pcm_seek_page_lap(OggVorbis_File*, ogg_int64_t);
229 int ov_time_seek_lap(OggVorbis_File*, double);
230 int ov_time_seek_page_lap(OggVorbis_File*, double);
231 ogg_int64_t ov_raw_tell(OggVorbis_File*);
232 ogg_int64_t ov_pcm_tell(OggVorbis_File*);
233 double ov_time_tell(OggVorbis_File*);
234 vorbis_info* ov_info(OggVorbis_File*, int);
235 vorbis_comment* ov_comment(OggVorbis_File*, int);
236 c_long ov_read_float(OggVorbis_File*, float***, int, int*);
237 c_long ov_read(OggVorbis_File*, byte*, int, int, int, int, int*);
238 int ov_crosslap(OggVorbis_File*, OggVorbis_File*);
239 int ov_halfrate(OggVorbis_File*, int);
240 int ov_halfrate_p(OggVorbis_File*);