duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

libchdr_flac.c (10967B)


      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 <string.h>
     12 
     13 #include <libchdr/flac.h>
     14 #define DR_FLAC_IMPLEMENTATION
     15 #define DR_FLAC_NO_STDIO
     16 #include <dr_libs/dr_flac.h>
     17 
     18 /***************************************************************************
     19  *  FLAC DECODER
     20  ***************************************************************************
     21  */
     22 
     23 static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes);
     24 static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin);
     25 static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata);
     26 static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes);
     27 
     28 
     29 /* getters (valid after reset) */
     30 static uint32_t sample_rate(flac_decoder *decoder)  { return decoder->sample_rate; }
     31 static uint8_t channels(flac_decoder *decoder)  { return decoder->channels; }
     32 static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
     33 
     34 /*-------------------------------------------------
     35  *  flac_decoder - constructor
     36  *-------------------------------------------------
     37  */
     38 
     39 int flac_decoder_init(flac_decoder *decoder)
     40 {
     41 	decoder->decoder = NULL;
     42 	decoder->sample_rate = 0;
     43 	decoder->channels = 0;
     44 	decoder->bits_per_sample = 0;
     45 	decoder->compressed_offset = 0;
     46 	decoder->compressed_start = NULL;
     47 	decoder->compressed_length = 0;
     48 	decoder->compressed2_start = NULL;
     49 	decoder->compressed2_length = 0;
     50 	decoder->uncompressed_offset = 0;
     51 	decoder->uncompressed_length = 0;
     52 	decoder->uncompressed_swap = 0;
     53 	return 0;
     54 }
     55 
     56 /*-------------------------------------------------
     57  *  flac_decoder - destructor
     58  *-------------------------------------------------
     59  */
     60 
     61 void flac_decoder_free(flac_decoder* decoder)
     62 {
     63 	if ((decoder != NULL) && (decoder->decoder != NULL)) {
     64 		drflac_close(decoder->decoder);
     65 		decoder->decoder = NULL;
     66 	}
     67 }
     68 
     69 /*-------------------------------------------------
     70  *  reset - reset state with the original
     71  *  parameters
     72  *-------------------------------------------------
     73  */
     74 
     75 static int flac_decoder_internal_reset(flac_decoder* decoder)
     76 {
     77 	decoder->compressed_offset = 0;
     78 	flac_decoder_free(decoder);
     79 	decoder->decoder = drflac_open_with_metadata(
     80 		flac_decoder_read_callback, flac_decoder_seek_callback,
     81 		flac_decoder_metadata_callback, decoder, NULL);
     82 	return (decoder->decoder != NULL);
     83 }
     84 
     85 /*-------------------------------------------------
     86  *  reset - reset state with new memory parameters
     87  *  and a custom-generated header
     88  *-------------------------------------------------
     89  */
     90 
     91 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)
     92 {
     93 	/* modify the template header with our parameters */
     94 	static const uint8_t s_header_template[0x2a] =
     95 	{
     96 		0x66, 0x4C, 0x61, 0x43,                         /* +00: 'fLaC' stream header */
     97 		0x80,                                           /* +04: metadata block type 0 (STREAMINFO), */
     98 								/*      flagged as last block */
     99 		0x00, 0x00, 0x22,                               /* +05: metadata block length = 0x22 */
    100 		0x00, 0x00,                                     /* +08: minimum block size */
    101 		0x00, 0x00,                                     /* +0A: maximum block size */
    102 		0x00, 0x00, 0x00,                               /* +0C: minimum frame size (0 == unknown) */
    103 		0x00, 0x00, 0x00,                               /* +0F: maximum frame size (0 == unknown) */
    104 		0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, /* +12: sample rate (0x0ac44 == 44100), */
    105 								/*      numchannels (2), sample bits (16), */
    106 								/*      samples in stream (0 == unknown) */
    107 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* +1A: MD5 signature (0 == none) */
    108 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* +2A: start of stream data */
    109 	};
    110 	memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
    111 	decoder->custom_header[0x08] = decoder->custom_header[0x0a] = (block_size*num_channels) >> 8;
    112 	decoder->custom_header[0x09] = decoder->custom_header[0x0b] = (block_size*num_channels) & 0xff;
    113 	decoder->custom_header[0x12] = sample_rate >> 12;
    114 	decoder->custom_header[0x13] = sample_rate >> 4;
    115 	decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
    116 
    117 	/* configure the header ahead of the provided buffer */
    118 	decoder->compressed_start = (const uint8_t *)(decoder->custom_header);
    119 	decoder->compressed_length = sizeof(decoder->custom_header);
    120 	decoder->compressed2_start = (const uint8_t *)(buffer);
    121 	decoder->compressed2_length = length;
    122 	return flac_decoder_internal_reset(decoder);
    123 }
    124 
    125 /*-------------------------------------------------
    126  *  decode_interleaved - decode to an interleaved
    127  *  sound stream
    128  *-------------------------------------------------
    129  */
    130 
    131 int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
    132 {
    133 	/* configure the uncompressed buffer */
    134 	memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
    135 	decoder->uncompressed_start[0] = samples;
    136 	decoder->uncompressed_offset = 0;
    137 	decoder->uncompressed_length = num_samples;
    138 	decoder->uncompressed_swap = swap_endian;
    139 
    140 #define	BUFFER	2352	/* bytes per CD audio sector */
    141 	int16_t buffer[BUFFER];
    142 	uint32_t buf_samples = BUFFER / channels(decoder);
    143 	/* loop until we get everything we want */
    144 	while (decoder->uncompressed_offset < decoder->uncompressed_length) {
    145 		uint32_t frames = (num_samples < buf_samples ? num_samples : buf_samples);
    146 		if (!drflac_read_pcm_frames_s16(decoder->decoder, frames, buffer))
    147 			return 0;
    148 		flac_decoder_write_callback(decoder, buffer, frames*sizeof(*buffer)*channels(decoder));
    149 		num_samples -= frames;
    150 	}
    151 	return 1;
    152 }
    153 
    154 /*-------------------------------------------------
    155  *  finish - finish up the decode
    156  *-------------------------------------------------
    157  */
    158 
    159 uint32_t flac_decoder_finish(flac_decoder* decoder)
    160 {
    161 	/* get the final decoding position and move forward */
    162 	drflac *flac = decoder->decoder;
    163 	uint64_t position = decoder->compressed_offset;
    164 
    165 	/* ugh... there's no function to obtain bytes used in drflac :-/ */
    166 	position -= DRFLAC_CACHE_L2_LINES_REMAINING(&flac->bs) * sizeof(drflac_cache_t);
    167 	position -= DRFLAC_CACHE_L1_BITS_REMAINING(&flac->bs) / 8;
    168 	position -= flac->bs.unalignedByteCount;
    169 
    170 	/* adjust position if we provided the header */
    171 	if (position == 0)
    172 		return 0;
    173 	if (decoder->compressed_start == (const uint8_t *)(decoder->custom_header))
    174 		position -= decoder->compressed_length;
    175 
    176 	flac_decoder_free(decoder);
    177 	return position;
    178 }
    179 
    180 /*-------------------------------------------------
    181  *  read_callback - handle reads from the input
    182  *  stream
    183  *-------------------------------------------------
    184  */
    185 
    186 #define MIN(x, y) ((x) < (y) ? (x) : (y))
    187 
    188 static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes)
    189 {
    190 	flac_decoder* decoder = (flac_decoder*)userdata;
    191 	uint8_t *dst = buffer;
    192 
    193 	/* copy from primary buffer first */
    194 	uint32_t outputpos = 0;
    195 	if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length)
    196 	{
    197 		uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
    198 		memcpy(&dst[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
    199 		outputpos += bytes_to_copy;
    200 		decoder->compressed_offset += bytes_to_copy;
    201 	}
    202 
    203 	/* once we're out of that, copy from the secondary buffer */
    204 	if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
    205 	{
    206 		uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
    207 		memcpy(&dst[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
    208 		outputpos += bytes_to_copy;
    209 		decoder->compressed_offset += bytes_to_copy;
    210 	}
    211 
    212 	return outputpos;
    213 }
    214 
    215 /*-------------------------------------------------
    216  *  metadata_callback - handle STREAMINFO metadata
    217  *-------------------------------------------------
    218  */
    219 
    220 static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata)
    221 {
    222 	flac_decoder *decoder = userdata;
    223 
    224 	/* ignore all but STREAMINFO metadata */
    225 	if (metadata->type != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO)
    226 		return;
    227 
    228 	/* parse out the data we care about */
    229 	decoder->sample_rate = metadata->data.streaminfo.sampleRate;
    230 	decoder->bits_per_sample = metadata->data.streaminfo.bitsPerSample;
    231 	decoder->channels = metadata->data.streaminfo.channels;
    232 }
    233 
    234 /*-------------------------------------------------
    235  *  write_callback - handle writes to the output
    236  *  stream
    237  *-------------------------------------------------
    238  */
    239 
    240 static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes)
    241 {
    242 	int sampnum, chan;
    243 	int shift, blocksize;
    244 	flac_decoder * decoder = (flac_decoder *)userdata;
    245 	int16_t *sampbuf = (int16_t *)buffer;
    246 	int sampch = channels(decoder);
    247 	uint32_t offset = decoder->uncompressed_offset;
    248 	uint16_t usample;
    249 
    250 	/* interleaved case */
    251 	shift = decoder->uncompressed_swap ? 8 : 0;
    252 	blocksize = bytes / (sampch * sizeof(sampbuf[0]));
    253 	if (decoder->uncompressed_start[1] == NULL)
    254 	{
    255 		int16_t *dest = decoder->uncompressed_start[0] + offset * sampch;
    256 		for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
    257 			for (chan = 0; chan < sampch; chan++) {
    258 				usample = (uint16_t)*sampbuf++;
    259 				*dest++ = (int16_t)((usample << shift) | (usample >> shift));
    260 			}
    261 	}
    262 
    263 	/* non-interleaved case */
    264 	else
    265 	{
    266 		for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
    267 			for (chan = 0; chan < sampch; chan++) {
    268 				usample = (uint16_t)*sampbuf++;
    269 				if (decoder->uncompressed_start[chan] != NULL)
    270 					decoder->uncompressed_start[chan][offset] = (int16_t) ((usample << shift) | (usample >> shift));
    271 			}
    272 	}
    273 	decoder->uncompressed_offset = offset;
    274 }
    275 
    276 
    277 /*-------------------------------------------------
    278  *  seek_callback - handle seeks on the output
    279  *  stream
    280  *-------------------------------------------------
    281  */
    282 
    283 static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin)
    284 {
    285 	flac_decoder * decoder = (flac_decoder *)userdata;
    286 	uint32_t length = decoder->compressed_length + decoder->compressed2_length;
    287 
    288 	if (origin == drflac_seek_origin_start) {
    289 		uint32_t pos = offset;
    290 		if (pos <= length) {
    291 			decoder->compressed_offset = pos;
    292 			return 1;
    293 		}
    294 	} else if (origin == drflac_seek_origin_current) {
    295 		uint32_t pos = decoder->compressed_offset + offset;
    296 		if (pos <= length) {
    297 			decoder->compressed_offset = pos;
    298 			return 1;
    299 		}
    300 	}
    301 	return 0;
    302 }
    303