1#ifndef WUFF_INTERNAL_H
2#define WUFF_INTERNAL_H
3
4#define WUFF_BUFFER_MIN_SIZE 4096
5#define WUFF_BUFFER_MAX_SIZE 2097152
6#define WUFF_STREAM_MIN_SIZE 36
7#define WUFF_HEADER_MIN_SIZE 16
8#define WUFF_HEADER_FETCH_SIZE 80
9
10#define WUFF_FORMAT_PCM 1
11#define WUFF_FORMAT_IEEE_FLOAT 3
12#define WUFF_FORMAT_EXTENSIBLE 0xFFFE
13
14
15#define WUFF_RIFF_CHUNK_ID wuff_get_chunk_id("RIFF")
16#define WUFF_WAVE_CHUNK_ID wuff_get_chunk_id("WAVE")
17#define WUFF_FORMAT_CHUNK_ID wuff_get_chunk_id("fmt ")
18#define WUFF_DATA_CHUNK_ID wuff_get_chunk_id("data")
19
20#define WUFF_STATUS_BAIL() if (wuff_status < 0) return wuff_status;
21
22
23static WUFF_INLINE wuff_uint32 wuff_get_uint32(wuff_uint8 * data)
24{
25 return data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24);
26}
27
28static WUFF_INLINE wuff_uint16 wuff_get_uint16(wuff_uint8 * data)
29{
30 return data[0] + (data[1] << 8);
31}
32
33struct wuff_chunk_header
34{
35 wuff_uint32 id;
36 wuff_uint32 size;
37};
38
39static WUFF_INLINE wuff_uint32 wuff_get_chunk_id(const char txt[5])
40{
41 const wuff_uint8 * id = (wuff_uint8*) txt;
42 wuff_uint32 int_id;
43 wuff_uint8 * id_bytes = (wuff_uint8 *)&int_id;
44 id_bytes[0] = id[0];
45 id_bytes[1] = id[1];
46 id_bytes[2] = id[2];
47 id_bytes[3] = id[3];
48
49 return int_id;
50}
51
52static WUFF_INLINE void wuff_copy_chunk_header_data(struct wuff_chunk_header * chunk, wuff_uint8 * data)
53{
54 wuff_uint8 * id = (wuff_uint8 *)&chunk->id;
55 id[0] = data[0];
56 id[1] = data[1];
57 id[2] = data[2];
58 id[3] = data[3];
59
60 chunk->size = wuff_get_uint32(data + 4);
61}
62
63struct wuff_stream_header
64{
65 wuff_uint64 size;
66 wuff_uint64 offset;
67
68 wuff_uint16 format;
69 wuff_uint16 channels;
70 wuff_uint32 sample_rate;
71 wuff_uint16 bits_per_sample;
72 wuff_uint16 bytes_per_sample;
73 size_t block_size;
74};
75
76struct wuff_stream_data
77{
78 wuff_uint64 size;
79 wuff_uint64 offset;
80};
81
82struct wuff_buffer
83{
84 wuff_uint8 * data;
85 wuff_uint64 bytes_left;
86 size_t size;
87 size_t offset;
88 size_t end;
89};
90
91struct wuff_output
92{
93 wuff_uint16 format;
94 size_t bytes_per_sample;
95 size_t block_size;
96 size_t block_offset;
97 void (* function)(wuff_uint8 *, wuff_uint8 *, size_t, wuff_uint8, wuff_uint8, wuff_uint8);
98};
99
100struct wuff_stream
101{
102 wuff_uint64 size;
103 wuff_uint64 length;
104 wuff_uint16 format;
105
106 wuff_uint64 position;
107
108 struct wuff_stream_header header;
109 struct wuff_stream_data data;
110};
111
112struct wuff_handle
113{
114 struct wuff_stream stream;
115 struct wuff_buffer buffer;
116 struct wuff_output output;
117 struct wuff_callback * callback;
118 void * userdata;
119};
120
121
122/* Initializes the stream, allocates the buffer, and sets the output format. */
123/* Expects a nulled wuff_handle and the callbacks set and ready. */
124WUFF_INTERN_API wuff_sint32 wuff_setup(struct wuff_handle * handle);
125
126/* Cleans the stream up, frees the buffer and the wuff_handle. */
127WUFF_INTERN_API wuff_sint32 wuff_cleanup(struct wuff_handle * handle);
128
129/* Called by wuff_setup. Initializes the stream by reading the data from the */
130/* callbacks, searching for headers and stream information. */
131WUFF_INTERN_API wuff_sint32 wuff_init_stream(struct wuff_handle * handle);
132
133/* Searches for a specific chunk id and stops before another if it's not 0. */
134/* If the id in wuff_chunk_header is not 0, it will be checked too and if */
135/* they match, then the function will return immediately. */
136/* Expects offset to point to the file position of a chunk and */
137/* wuff_chunk_header to have the size of this chunk. */
138WUFF_INTERN_API wuff_sint32 wuff_search_chunk(struct wuff_handle * handle, struct wuff_chunk_header * chunk, wuff_uint64 * offset, wuff_uint32 id, wuff_uint32 stop_id);
139
140/* Sets the output struct of the stream to the new format. */
141WUFF_INTERN_API wuff_sint32 wuff_set_output_format(struct wuff_handle * handle, wuff_uint16);
142
143/* Checks if the number of bits per samples is supported and writes the */
144/* output identifier to the 16-bit integer. */
145WUFF_INTERN_API wuff_sint32 wuff_check_bits(wuff_uint16 bits, wuff_uint16 * format);
146
147/* Calculates the number of samples that have to be requested from the buffer */
148/* by also taking the truncated samples at the start and end into account. */
149/* The return value is the number of samples needed. */
150WUFF_INTERN_API size_t wuff_calculate_samples(size_t target_size, wuff_uint8 sample_size, wuff_uint8 * head, wuff_uint8 * tail);
151
152
153/* Allocates the buffer for the input stream. */
154/* Expects the stream to be initialized, as format information is needed. */
155WUFF_INTERN_API wuff_sint32 wuff_buffer_alloc(struct wuff_handle * handle);
156
157/* Fills the buffer with new data. */
158WUFF_INTERN_API wuff_sint32 wuff_buffer_fill(struct wuff_handle * handle);
159
160/* Marks all bytes in the buffer as free. */
161WUFF_INTERN_API wuff_sint32 wuff_buffer_clear(struct wuff_handle * handle);
162
163/* Requests samples and a pointer to them. */
164/* The number of samples may be lower than requested. */
165WUFF_INTERN_API wuff_sint32 wuff_buffer_request(struct wuff_handle * handle, wuff_uint8 ** buffer, size_t * samples);
166
167/* Releases the number of samples from the buffer. */
168WUFF_INTERN_API wuff_sint32 wuff_buffer_release(struct wuff_handle * handle, size_t samples);
169
170
171#endif /* WUFF_INTERNAL_H */
172