1 // license:BSD-3-Clause
\r
2 // copyright-holders:Aaron Giles
\r
3 /***************************************************************************
\r
7 FLAC compression wrappers
\r
9 ***************************************************************************/
\r
15 //**************************************************************************
\r
17 //**************************************************************************
\r
19 static FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
\r
20 FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes);
\r
21 static void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
\r
22 static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
\r
23 static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
\r
24 FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
\r
25 static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
\r
27 // getters (valid after reset)
\r
28 static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
\r
29 static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
\r
30 static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
\r
31 static uint32_t total_samples(flac_decoder *decoder) { return FLAC__stream_decoder_get_total_samples(decoder->decoder); }
\r
32 static FLAC__StreamDecoderState state(flac_decoder *decoder) { return FLAC__stream_decoder_get_state(decoder->decoder); }
\r
33 static const char *state_string(flac_decoder *decoder) { return FLAC__stream_decoder_get_resolved_state_string(decoder->decoder); }
\r
35 //-------------------------------------------------
\r
36 // flac_decoder - constructor
\r
37 //-------------------------------------------------
\r
39 void flac_decoder_init(flac_decoder *decoder)
\r
41 decoder->decoder = FLAC__stream_decoder_new();
\r
42 decoder->sample_rate = 0;
\r
43 decoder->channels = 0;
\r
44 decoder->bits_per_sample = 0;
\r
45 decoder->compressed_offset = 0;
\r
46 decoder->compressed_start = NULL;
\r
47 decoder->compressed_length = 0;
\r
48 decoder->compressed2_start = NULL;
\r
49 decoder->compressed2_length = 0;
\r
50 decoder->uncompressed_offset = 0;
\r
51 decoder->uncompressed_length = 0;
\r
52 decoder->uncompressed_swap = 0;
\r
55 //-------------------------------------------------
\r
56 // flac_decoder - destructor
\r
57 //-------------------------------------------------
\r
59 void flac_decoder_free(flac_decoder* decoder)
\r
61 if ((decoder != NULL) && (decoder->decoder != NULL))
\r
62 FLAC__stream_decoder_delete(decoder->decoder);
\r
66 //-------------------------------------------------
\r
67 // reset - reset state with the original
\r
69 //-------------------------------------------------
\r
71 static int flac_decoder_internal_reset(flac_decoder* decoder)
\r
73 decoder->compressed_offset = 0;
\r
74 if (FLAC__stream_decoder_init_stream(decoder->decoder,
\r
75 &flac_decoder_read_callback_static,
\r
77 &flac_decoder_tell_callback_static,
\r
80 &flac_decoder_write_callback_static,
\r
81 &flac_decoder_metadata_callback_static,
\r
82 &flac_decoder_error_callback_static, decoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
\r
84 return FLAC__stream_decoder_process_until_end_of_metadata(decoder->decoder);
\r
89 //-------------------------------------------------
\r
90 // reset - reset state with new memory parameters
\r
91 // and a custom-generated header
\r
92 //-------------------------------------------------
\r
94 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)
\r
96 // modify the template header with our parameters
\r
97 static const uint8_t s_header_template[0x2a] =
\r
99 0x66, 0x4C, 0x61, 0x43, // +00: 'fLaC' stream header
\r
100 0x80, // +04: metadata block type 0 (STREAMINFO),
\r
101 // flagged as last block
\r
102 0x00, 0x00, 0x22, // +05: metadata block length = 0x22
\r
103 0x00, 0x00, // +08: minimum block size
\r
104 0x00, 0x00, // +0A: maximum block size
\r
105 0x00, 0x00, 0x00, // +0C: minimum frame size (0 == unknown)
\r
106 0x00, 0x00, 0x00, // +0F: maximum frame size (0 == unknown)
\r
107 0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, // +12: sample rate (0x0ac44 == 44100),
\r
108 // numchannels (2), sample bits (16),
\r
109 // samples in stream (0 == unknown)
\r
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // +1A: MD5 signature (0 == none)
\r
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //
\r
112 // +2A: start of stream data
\r
114 memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
\r
115 decoder->custom_header[0x08] = decoder->custom_header[0x0a] = block_size >> 8;
\r
116 decoder->custom_header[0x09] = decoder->custom_header[0x0b] = block_size & 0xff;
\r
117 decoder->custom_header[0x12] = sample_rate >> 12;
\r
118 decoder->custom_header[0x13] = sample_rate >> 4;
\r
119 decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
\r
121 // configure the header ahead of the provided buffer
\r
122 decoder->compressed_start = (const FLAC__byte *)(decoder->custom_header);
\r
123 decoder->compressed_length = sizeof(decoder->custom_header);
\r
124 decoder->compressed2_start = (const FLAC__byte *)(buffer);
\r
125 decoder->compressed2_length = length;
\r
126 return flac_decoder_internal_reset(decoder);
\r
130 //-------------------------------------------------
\r
131 // decode_interleaved - decode to an interleaved
\r
133 //-------------------------------------------------
\r
135 int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
\r
137 // configure the uncompressed buffer
\r
138 memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
\r
139 decoder->uncompressed_start[0] = samples;
\r
140 decoder->uncompressed_offset = 0;
\r
141 decoder->uncompressed_length = num_samples;
\r
142 decoder->uncompressed_swap = swap_endian;
\r
144 // loop until we get everything we want
\r
145 while (decoder->uncompressed_offset < decoder->uncompressed_length)
\r
146 if (!FLAC__stream_decoder_process_single(decoder->decoder))
\r
153 //-------------------------------------------------
\r
154 // decode - decode to an multiple independent
\r
156 //-------------------------------------------------
\r
158 bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_endian)
\r
160 // make sure we don't have too many channels
\r
161 int chans = channels();
\r
162 if (chans > ARRAY_LENGTH(m_uncompressed_start))
\r
165 // configure the uncompressed buffer
\r
166 memset(m_uncompressed_start, 0, sizeof(m_uncompressed_start));
\r
167 for (int curchan = 0; curchan < chans; curchan++)
\r
168 m_uncompressed_start[curchan] = samples[curchan];
\r
169 m_uncompressed_offset = 0;
\r
170 m_uncompressed_length = num_samples;
\r
171 m_uncompressed_swap = swap_endian;
\r
173 // loop until we get everything we want
\r
174 while (m_uncompressed_offset < m_uncompressed_length)
\r
175 if (!FLAC__stream_decoder_process_single(m_decoder))
\r
181 //-------------------------------------------------
\r
182 // finish - finish up the decode
\r
183 //-------------------------------------------------
\r
185 uint32_t flac_decoder_finish(flac_decoder* decoder)
\r
187 // get the final decoding position and move forward
\r
188 FLAC__uint64 position = 0;
\r
189 FLAC__stream_decoder_get_decode_position(decoder->decoder, &position);
\r
190 FLAC__stream_decoder_finish(decoder->decoder);
\r
192 // adjust position if we provided the header
\r
195 if (decoder->compressed_start == (const FLAC__byte *)(decoder->custom_header))
\r
196 position -= decoder->compressed_length;
\r
201 //-------------------------------------------------
\r
202 // read_callback - handle reads from the input
\r
204 //-------------------------------------------------
\r
206 #define MIN(x, y) ((x) < (y) ? (x) : (y))
\r
208 FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
\r
210 return flac_decoder_read_callback(client_data, buffer, bytes);
\r
213 FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes)
\r
215 flac_decoder* decoder = (flac_decoder*)client_data;
\r
217 uint32_t expected = *bytes;
\r
219 // copy from primary buffer first
\r
220 uint32_t outputpos = 0;
\r
221 if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length)
\r
223 uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
\r
224 memcpy(&buffer[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
\r
225 outputpos += bytes_to_copy;
\r
226 decoder->compressed_offset += bytes_to_copy;
\r
229 // once we're out of that, copy from the secondary buffer
\r
230 if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
\r
232 uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
\r
233 memcpy(&buffer[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
\r
234 outputpos += bytes_to_copy;
\r
235 decoder->compressed_offset += bytes_to_copy;
\r
237 *bytes = outputpos;
\r
239 // return based on whether we ran out of data
\r
240 return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
\r
244 //-------------------------------------------------
\r
245 // metadata_callback - handle STREAMINFO metadata
\r
246 //-------------------------------------------------
\r
248 void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
\r
250 flac_decoder *fldecoder;
\r
251 // ignore all but STREAMINFO metadata
\r
252 if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO)
\r
255 // parse out the data we care about
\r
256 fldecoder = (flac_decoder *)(client_data);
\r
257 fldecoder->sample_rate = metadata->data.stream_info.sample_rate;
\r
258 fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
\r
259 fldecoder->channels = metadata->data.stream_info.channels;
\r
263 //-------------------------------------------------
\r
264 // tell_callback - handle requests to find out
\r
265 // where in the input stream we are
\r
266 //-------------------------------------------------
\r
268 FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
\r
270 *absolute_byte_offset = ((flac_decoder *)client_data)->compressed_offset;
\r
271 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
\r
275 //-------------------------------------------------
\r
276 // write_callback - handle writes to the output
\r
278 //-------------------------------------------------
\r
280 FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
\r
282 return flac_decoder_write_callback(client_data, frame, buffer);
\r
285 FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void *client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
\r
287 int shift, blocksize;
\r
288 flac_decoder * decoder = (flac_decoder *)client_data;
\r
290 assert(frame->header.channels == channels(decoder));
\r
292 // interleaved case
\r
293 shift = decoder->uncompressed_swap ? 8 : 0;
\r
294 blocksize = frame->header.blocksize;
\r
296 if (decoder->uncompressed_start[1] == NULL)
\r
299 int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels;
\r
300 for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
\r
301 for (chan = 0; chan < frame->header.channels; chan++)
\r
302 *dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift));
\r
305 // non-interleaved case
\r
309 for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
\r
310 for (chan = 0; chan < frame->header.channels; chan++)
\r
311 if (decoder->uncompressed_start[chan] != NULL)
\r
312 decoder->uncompressed_start[chan][decoder->uncompressed_offset] = (int16_t) ( (((uint16_t)(buffer[chan][sampnum])) << shift) | ( ((uint16_t)(buffer[chan][sampnum])) >> shift) );
\r
314 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
\r
318 * @fn void flac_decoder::error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
\r
320 * @brief -------------------------------------------------
\r
321 * error_callback - handle errors (ignore them)
\r
322 * -------------------------------------------------.
\r
324 * @param decoder The decoder.
\r
325 * @param status The status.
\r
326 * @param [in,out] client_data If non-null, information describing the client.
\r
329 void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
\r