Code Coverage Report for src/decode/stb_vorbis.c


Hit Total Coverage
Lines: 123 123 100.0%
Branches: 368 368 100.0%

1 /*
2 * libnogg: a decoder library for Ogg Vorbis streams
3 * Copyright (c) 2014-2024 Andrew Church <achurch@achurch.org>
4 *
5 * This software may be copied and redistributed under certain conditions;
6 * see the file "COPYING" in the source code distribution for details.
7 * NO WARRANTY is provided with this software.
8 */
9
10 /*
11 * This decoder implementation is based on the public-domain stb_vorbis.c
12 * decoder (version 0.99996) from <http://nothings.org/stb_vorbis/>.
13 * It shares the following limitations with that implementation:
14 * - Lossless sample truncation at the beginning of the stream
15 * (negative initial sample position) is ignored.
16 * - Only a single Ogg bitstream per stream is supported.
17 */
18
19 #include "include/nogg.h"
20 #include "src/common.h"
21 #include "src/decode/common.h"
22 #include "src/decode/crc32.h"
23 #include "src/decode/decode.h"
24 #include "src/decode/io.h"
25 #include "src/decode/packet.h"
26 #include "src/decode/setup.h"
27 #include "src/util/memory.h"
28
29 #include <string.h>
30
31 /*************************************************************************/
32 /**************************** Helper routines ****************************/
33 /*************************************************************************/
34
35 /**
36 * create_handle: Create a new stb_vorbis handle with the given parameters.
37 * Implements stb_vorbis_open_callbacks() and stb_vorbis_open_packet().
38 *
39 * [Parameters]
40 * As for stb_vorbis_open_callbacks() and stb_vorbis_open_packet().
41 * [Return value]
42 * New stb_vorbis handle, or NULL on error.
43 */
44 static stb_vorbis *create_handle(
45 int32_t (*read_callback)(void *opaque, void *buf, int32_t len),
46 void (*seek_callback)(void *opaque, int64_t offset),
47 int64_t (*tell_callback)(void *opaque), void *io_opaque,
48 void *mem_opaque, int64_t length,
49 const void *id_packet, int32_t id_packet_len,
50 const void *setup_packet, int32_t setup_packet_len,
51 unsigned int options, int *error_ret)
52 {
53 stb_vorbis *handle = mem_alloc(mem_opaque, sizeof(*handle), 0);
54 (18/18) if (!handle) {
55 *error_ret = VORBIS_outofmem;
56 return NULL;
57 }
58 memset(handle, 0, sizeof(*handle));
59
60 handle->read_callback = read_callback;
61 handle->seek_callback = seek_callback;
62 handle->tell_callback = tell_callback;
63 handle->io_opaque = io_opaque;
64 handle->mem_opaque = mem_opaque;
65 handle->packet_mode = (id_packet != NULL);
66 handle->stream_len = length;
67 handle->error = VORBIS__no_error;
68
69 handle->fast_huffman_length = 10;
70 (18/18) if (options & VORBIS_OPTION_FAST_HUFFMAN_LENGTH_FLAG) {
71 const int fast_bits = VORBIS_OPTION_FAST_HUFFMAN_LENGTH_VALUE(options);
72 (18/18) if (fast_bits <= 24) {
73 handle->fast_huffman_length = fast_bits;
74 }
75 }
76 handle->fast_huffman_mask =
77 (UINT32_C(1) << handle->fast_huffman_length) - 1;
78 handle->huffman_binary_search =
79 ((options & VORBIS_OPTION_NO_HUFFMAN_BINARY_SEARCH) == 0);
80 handle->divides_in_residue =
81 ((options & VORBIS_OPTION_DIVIDES_IN_RESIDUE) != 0);
82 handle->divides_in_codebook =
83 ((options & VORBIS_OPTION_DIVIDES_IN_CODEBOOK) != 0);
84 handle->scan_for_next_page =
85 ((options & VORBIS_OPTION_SCAN_FOR_NEXT_PAGE) != 0);
86
87 (18/18) if (!start_decoder(handle, id_packet, id_packet_len,
88 setup_packet, setup_packet_len)) {
89 *error_ret = handle->error;
90 stb_vorbis_close(handle);
91 return NULL;
92 }
93
94 return handle;
95 }
96
97 /*************************************************************************/
98 /************************** Interface routines ***************************/
99 /*************************************************************************/
100
101 stb_vorbis *stb_vorbis_open_callbacks(
102 int32_t (*read_callback)(void *opaque, void *buf, int32_t len),
103 void (*seek_callback)(void *opaque, int64_t offset),
104 int64_t (*tell_callback)(void *opaque), void *io_opaque,
105 void *mem_opaque, int64_t length, unsigned int options, int *error_ret)
106 {
107 return create_handle(read_callback, seek_callback, tell_callback,
108 io_opaque, mem_opaque, length, NULL, 0, NULL, 0,
109 options, error_ret);
110 }
111
112 /*-----------------------------------------------------------------------*/
113
114 stb_vorbis *stb_vorbis_open_packet(
115 void *mem_opaque, const void *id_packet, int32_t id_packet_len,
116 const void *setup_packet, int32_t setup_packet_len,
117 unsigned int options, int *error_ret)
118 {
119 return create_handle(NULL, NULL, NULL, NULL, mem_opaque, -1, id_packet,
120 id_packet_len, setup_packet, setup_packet_len,
121 options, error_ret);
122 }
123
124 /*-----------------------------------------------------------------------*/
125
126 void stb_vorbis_close(stb_vorbis *handle)
127 {
128 (18/18) if (handle->codebooks) {
129 (18/18) for (int i = 0; i < handle->codebook_count; i++) {
130 Codebook *book = &handle->codebooks[i];
131 mem_free(handle->mem_opaque, book->codeword_lengths);
132 mem_free(handle->mem_opaque, book->multiplicands);
133 mem_free(handle->mem_opaque, book->codewords);
134 mem_free(handle->mem_opaque, book->fast_huffman);
135 mem_free(handle->mem_opaque, book->sorted_codewords);
136 /* book->sorted_values points one entry past the allocated
137 * address (see notes in setup.c). */
138 (18/18) if (book->sorted_values) {
139 mem_free(handle->mem_opaque, book->sorted_values-1);
140 }
141 }
142 mem_free(handle->mem_opaque, handle->codebooks);
143 }
144
145 (18/18) if (handle->floor_config) {
146 (18/18) for (int i = 0; i < handle->floor_count; i++) {
147 Floor *floor = &handle->floor_config[i];
148 (18/18) if (handle->floor_types[i] == 0) {
149 mem_free(handle->mem_opaque, floor->floor0.map[0]);
150 }
151 }
152 mem_free(handle->mem_opaque, handle->floor_config);
153 }
154
155 (18/18) if (handle->residue_config) {
156 (18/18) for (int i = 0; i < handle->residue_count; i++) {
157 Residue *res = &handle->residue_config[i];
158 (18/18) if (res->classdata) {
159 mem_free(handle->mem_opaque, res->classdata[0]);
160 mem_free(handle->mem_opaque, res->classdata);
161 }
162 mem_free(handle->mem_opaque, res->residue_books);
163 }
164 mem_free(handle->mem_opaque, handle->residue_config);
165 }
166
167 (18/18) if (handle->mapping) {
168 (18/18) for (int i = 0; i < handle->mapping_count; i++) {
169 mem_free(handle->mem_opaque, handle->mapping[i].coupling);
170 }
171 mem_free(handle->mem_opaque, handle->mapping[0].mux);
172 mem_free(handle->mem_opaque, handle->mapping);
173 }
174
175 #ifndef USE_LOOKUP_TABLES
176 (8/8) for (int i = 0; i < 2; i++) {
177 mem_free(handle->mem_opaque, handle->A[i]);
178 mem_free(handle->mem_opaque, handle->B[i]);
179 mem_free(handle->mem_opaque, handle->C[i]);
180 mem_free(handle->mem_opaque, handle->bit_reverse[i]);
181 mem_free(handle->mem_opaque, handle->window_weights[i]);
182 }
183 #endif
184
185 mem_free(handle->mem_opaque, handle->channel_buffers[0]);
186 mem_free(handle->mem_opaque, handle->outputs);
187 mem_free(handle->mem_opaque, handle->previous_window);
188 mem_free(handle->mem_opaque, handle->coefficients);
189 mem_free(handle->mem_opaque, handle->final_Y);
190 mem_free(handle->mem_opaque, handle->classifications);
191 mem_free(handle->mem_opaque, handle->imdct_temp_buf);
192
193 mem_free(handle->mem_opaque, handle);
194 }
195
196 /*-----------------------------------------------------------------------*/
197
198 STBVorbisError stb_vorbis_get_error(stb_vorbis *handle)
199 {
200 const STBVorbisError last_error = handle->error;
201 handle->error = VORBIS__no_error;
202 return last_error;
203 }
204
205 /*-----------------------------------------------------------------------*/
206
207 stb_vorbis_info stb_vorbis_get_info(stb_vorbis *handle)
208 {
209 return ((stb_vorbis_info){
210 .sample_rate = handle->sample_rate,
211 .nominal_bitrate = handle->nominal_bitrate,
212 .min_bitrate = handle->min_bitrate,
213 .max_bitrate = handle->max_bitrate,
214 .channels = handle->channels,
215 /* The maximum data size that can be returned for a frame is in
216 * the case of a long block preceded by another long block and
217 * followed by a short block. */
218 .max_frame_size = handle->blocksize[1]*3/4 - handle->blocksize[0]/4,
219 });
220 }
221
222 /*-----------------------------------------------------------------------*/
223
224 uint64_t stb_vorbis_tell_pcm(stb_vorbis *handle)
225 {
226 (18/18) return handle->current_loc_valid ? handle->current_loc : 0;
227 }
228
229 /*-----------------------------------------------------------------------*/
230
231 uint64_t stb_vorbis_tell_bits(stb_vorbis *handle)
232 {
233 (18/18) if (handle->stream_len >= 0) {
234 uint64_t byte_pos = (*handle->tell_callback)(handle->io_opaque);
235 (18/18) if (handle->segment_size > 0) {
236 byte_pos -= handle->segment_size;
237 byte_pos += handle->segment_pos;
238 }
239 return byte_pos * 8 - max(handle->valid_bits, 0);
240 } else {
241 return 0;
242 }
243 }
244
245 /*-----------------------------------------------------------------------*/
246
247 void stb_vorbis_reset_eof(stb_vorbis *handle)
248 {
249 handle->eof = false;
250 }
251
252 /*-----------------------------------------------------------------------*/
253
254 bool stb_vorbis_get_frame_float(stb_vorbis *handle, float ***output_ret,
255 int *len_ret)
256 {
257 ASSERT(!handle->packet_mode);
258
259 int len;
260 (18/18) if (!vorbis_decode_packet(handle, &len)) {
261 return false;
262 }
263 *len_ret = len;
264 *output_ret = handle->outputs;
265 return true;
266 }
267
268 /*-----------------------------------------------------------------------*/
269
270 bool stb_vorbis_decode_packet_float(
271 stb_vorbis *handle, const void *packet, int32_t packet_len,
272 float ***output_ret, int *len_ret)
273 {
274 ASSERT(handle->packet_mode);
275
276 int len;
277 (18/18) if (!vorbis_decode_packet_direct(handle, packet, packet_len, &len)) {
278 return false;
279 }
280 *len_ret = len;
281 *output_ret = handle->outputs;
282 return true;
283 }
284
285 /*************************************************************************/
286 /*************************************************************************/