Merge pull request #502 from justinweiss/restrict-threaded-rendering-drivers
[pcsx_rearmed.git] / deps / libchdr / flac.c
CommitLineData
9c659ffe 1/* license:BSD-3-Clause
2 * copyright-holders:Aaron Giles
3***************************************************************************
4
5 flac.c
6
7 FLAC compression wrappers
8
9***************************************************************************/
10
11#include <assert.h>
12#include <string.h>
13#include "flac.h"
14
15/***************************************************************************
16 * FLAC DECODER
17 ***************************************************************************
18 */
19
20static FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
21FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes);
22static void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
23static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
24static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
25FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
26static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
27
28/* getters (valid after reset) */
29static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
30static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
31static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
32static uint32_t total_samples(flac_decoder *decoder) { return FLAC__stream_decoder_get_total_samples(decoder->decoder); }
33static FLAC__StreamDecoderState state(flac_decoder *decoder) { return FLAC__stream_decoder_get_state(decoder->decoder); }
34static const char *state_string(flac_decoder *decoder) { return FLAC__stream_decoder_get_resolved_state_string(decoder->decoder); }
35
36/*-------------------------------------------------
37 * flac_decoder - constructor
38 *-------------------------------------------------
39 */
40
41void flac_decoder_init(flac_decoder *decoder)
42{
43 decoder->decoder = FLAC__stream_decoder_new();
44 decoder->sample_rate = 0;
45 decoder->channels = 0;
46 decoder->bits_per_sample = 0;
47 decoder->compressed_offset = 0;
48 decoder->compressed_start = NULL;
49 decoder->compressed_length = 0;
50 decoder->compressed2_start = NULL;
51 decoder->compressed2_length = 0;
52 decoder->uncompressed_offset = 0;
53 decoder->uncompressed_length = 0;
54 decoder->uncompressed_swap = 0;
55}
56
57/*-------------------------------------------------
58 * flac_decoder - destructor
59 *-------------------------------------------------
60 */
61
62void flac_decoder_free(flac_decoder* decoder)
63{
64 if ((decoder != NULL) && (decoder->decoder != NULL))
65 FLAC__stream_decoder_delete(decoder->decoder);
66}
67
68/*-------------------------------------------------
69 * reset - reset state with the original
70 * parameters
71 *-------------------------------------------------
72 */
73
74static int flac_decoder_internal_reset(flac_decoder* decoder)
75{
76 decoder->compressed_offset = 0;
77 if (FLAC__stream_decoder_init_stream(decoder->decoder,
78 &flac_decoder_read_callback_static,
79 NULL,
80 &flac_decoder_tell_callback_static,
81 NULL,
82 NULL,
83 &flac_decoder_write_callback_static,
84 &flac_decoder_metadata_callback_static,
85 &flac_decoder_error_callback_static, decoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
86 return 0;
87 return FLAC__stream_decoder_process_until_end_of_metadata(decoder->decoder);
88}
89
90/*-------------------------------------------------
91 * reset - reset state with new memory parameters
92 * and a custom-generated header
93 *-------------------------------------------------
94 */
95
96int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length)
97{
98 /* modify the template header with our parameters */
99 static const uint8_t s_header_template[0x2a] =
100 {
101 0x66, 0x4C, 0x61, 0x43, /* +00: 'fLaC' stream header */
102 0x80, /* +04: metadata block type 0 (STREAMINFO), */
103 /* flagged as last block */
104 0x00, 0x00, 0x22, /* +05: metadata block length = 0x22 */
105 0x00, 0x00, /* +08: minimum block size */
106 0x00, 0x00, /* +0A: maximum block size */
107 0x00, 0x00, 0x00, /* +0C: minimum frame size (0 == unknown) */
108 0x00, 0x00, 0x00, /* +0F: maximum frame size (0 == unknown) */
109 0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, /* +12: sample rate (0x0ac44 == 44100), */
110 /* numchannels (2), sample bits (16), */
111 /* samples in stream (0 == unknown) */
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* +1A: MD5 signature (0 == none) */
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* +2A: start of stream data */
114 };
115 memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
116 decoder->custom_header[0x08] = decoder->custom_header[0x0a] = block_size >> 8;
117 decoder->custom_header[0x09] = decoder->custom_header[0x0b] = block_size & 0xff;
118 decoder->custom_header[0x12] = sample_rate >> 12;
119 decoder->custom_header[0x13] = sample_rate >> 4;
120 decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
121
122 /* configure the header ahead of the provided buffer */
123 decoder->compressed_start = (const FLAC__byte *)(decoder->custom_header);
124 decoder->compressed_length = sizeof(decoder->custom_header);
125 decoder->compressed2_start = (const FLAC__byte *)(buffer);
126 decoder->compressed2_length = length;
127 return flac_decoder_internal_reset(decoder);
128}
129
130/*-------------------------------------------------
131 * decode_interleaved - decode to an interleaved
132 * sound stream
133 *-------------------------------------------------
134 */
135
136int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
137{
138 /* configure the uncompressed buffer */
139 memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
140 decoder->uncompressed_start[0] = samples;
141 decoder->uncompressed_offset = 0;
142 decoder->uncompressed_length = num_samples;
143 decoder->uncompressed_swap = swap_endian;
144
145 /* loop until we get everything we want */
146 while (decoder->uncompressed_offset < decoder->uncompressed_length)
147 if (!FLAC__stream_decoder_process_single(decoder->decoder))
148 return 0;
149 return 1;
150}
151
152#if 0
153/*-------------------------------------------------
154 * decode - decode to an multiple independent
155 * data streams
156 *-------------------------------------------------
157 */
158
159bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_endian)
160{
161 /* make sure we don't have too many channels */
162 int chans = channels();
163 if (chans > ARRAY_LENGTH(m_uncompressed_start))
164 return false;
165
166 /* configure the uncompressed buffer */
167 memset(m_uncompressed_start, 0, sizeof(m_uncompressed_start));
168 for (int curchan = 0; curchan < chans; curchan++)
169 m_uncompressed_start[curchan] = samples[curchan];
170 m_uncompressed_offset = 0;
171 m_uncompressed_length = num_samples;
172 m_uncompressed_swap = swap_endian;
173
174 /* loop until we get everything we want */
175 while (m_uncompressed_offset < m_uncompressed_length)
176 if (!FLAC__stream_decoder_process_single(m_decoder))
177 return false;
178 return true;
179}
180#endif
181
182/*-------------------------------------------------
183 * finish - finish up the decode
184 *-------------------------------------------------
185 */
186
187uint32_t flac_decoder_finish(flac_decoder* decoder)
188{
189 /* get the final decoding position and move forward */
190 FLAC__uint64 position = 0;
191 FLAC__stream_decoder_get_decode_position(decoder->decoder, &position);
192 FLAC__stream_decoder_finish(decoder->decoder);
193
194 /* adjust position if we provided the header */
195 if (position == 0)
196 return 0;
197 if (decoder->compressed_start == (const FLAC__byte *)(decoder->custom_header))
198 position -= decoder->compressed_length;
199 return position;
200}
201
202/*-------------------------------------------------
203 * read_callback - handle reads from the input
204 * stream
205 *-------------------------------------------------
206 */
207
208#define MIN(x, y) ((x) < (y) ? (x) : (y))
209
210FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
211{
212 return flac_decoder_read_callback(client_data, buffer, bytes);
213}
214
215FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes)
216{
217 flac_decoder* decoder = (flac_decoder*)client_data;
218
219 uint32_t expected = *bytes;
220
221 /* copy from primary buffer first */
222 uint32_t outputpos = 0;
223 if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length)
224 {
225 uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
226 memcpy(&buffer[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
227 outputpos += bytes_to_copy;
228 decoder->compressed_offset += bytes_to_copy;
229 }
230
231 /* once we're out of that, copy from the secondary buffer */
232 if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
233 {
234 uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
235 memcpy(&buffer[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
236 outputpos += bytes_to_copy;
237 decoder->compressed_offset += bytes_to_copy;
238 }
239 *bytes = outputpos;
240
241 /* return based on whether we ran out of data */
242 return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
243}
244
245/*-------------------------------------------------
246 * metadata_callback - handle STREAMINFO metadata
247 *-------------------------------------------------
248 */
249
250void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
251{
252 flac_decoder *fldecoder;
253 /* ignore all but STREAMINFO metadata */
254 if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO)
255 return;
256
257 /* parse out the data we care about */
258 fldecoder = (flac_decoder *)(client_data);
259 fldecoder->sample_rate = metadata->data.stream_info.sample_rate;
260 fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
261 fldecoder->channels = metadata->data.stream_info.channels;
262}
263
264/*-------------------------------------------------
265 * tell_callback - handle requests to find out
266 * where in the input stream we are
267 *-------------------------------------------------
268 */
269
270FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
271{
272 *absolute_byte_offset = ((flac_decoder *)client_data)->compressed_offset;
273 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
274}
275
276/*-------------------------------------------------
277 * write_callback - handle writes to the output
278 * stream
279 *-------------------------------------------------
280 */
281
282FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
283{
284 return flac_decoder_write_callback(client_data, frame, buffer);
285}
286
287FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void *client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
288{
289 int sampnum, chan;
290 int shift, blocksize;
291 flac_decoder * decoder = (flac_decoder *)client_data;
292
293 assert(frame->header.channels == channels(decoder));
294
295 /* interleaved case */
296 shift = decoder->uncompressed_swap ? 8 : 0;
297 blocksize = frame->header.blocksize;
298 if (decoder->uncompressed_start[1] == NULL)
299 {
300 int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels;
301 for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
302 for (chan = 0; chan < frame->header.channels; chan++)
303 *dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift));
304 }
305
306 /* non-interleaved case */
307 else
308 {
309 for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
310 for (chan = 0; chan < frame->header.channels; chan++)
311 if (decoder->uncompressed_start[chan] != NULL)
312 decoder->uncompressed_start[chan][decoder->uncompressed_offset] = (int16_t) ( (((uint16_t)(buffer[chan][sampnum])) << shift) | ( ((uint16_t)(buffer[chan][sampnum])) >> shift) );
313 }
314 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
315}
316
317/**
318 * @fn void flac_decoder::error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
319 *
320 * @brief -------------------------------------------------
321 * error_callback - handle errors (ignore them)
322 * -------------------------------------------------.
323 *
324 * @param decoder The decoder.
325 * @param status The status.
326 * @param [in,out] client_data If non-null, information describing the client.
327 */
328
329void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
330{
331}