Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libchdr/flac.c
2 views
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
20
static FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
21
FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes);
22
static void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
23
static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
24
static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
25
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
26
static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
27
28
/* getters (valid after reset) */
29
static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
30
static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
31
static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
32
static uint32_t total_samples(flac_decoder *decoder) { return FLAC__stream_decoder_get_total_samples(decoder->decoder); }
33
static FLAC__StreamDecoderState state(flac_decoder *decoder) { return FLAC__stream_decoder_get_state(decoder->decoder); }
34
static 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
41
void 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
62
void 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
74
static 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
96
int 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
136
int 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
159
bool 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
187
uint32_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
210
FLAC__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
215
FLAC__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
250
void 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
270
FLAC__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
282
FLAC__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
287
FLAC__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
329
void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
330
{
331
}
332
333