Merge pull request #350 from sonninnos/audio-update

Libretro: Update audio before video_cb
This commit is contained in:
ds22x 2024-05-14 23:47:33 +02:00 committed by GitHub
commit c921b37bd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 786 additions and 588 deletions

View File

@ -397,6 +397,16 @@ int cdd_load(char *filename, char *header)
return -1;
}
#ifdef __LIBRETRO__
if (config.cd_precache)
{
log_cb(RETRO_LOG_INFO, "Pre-caching \"%s\" ...\n", filename);
if (chd_precache(cdd.chd.file) != CHDERR_NONE)
return -1;
log_cb(RETRO_LOG_INFO, "Pre-cache done.\n");
}
#endif
/* retrieve CHD header */
head = chd_get_header(cdd.chd.file);

View File

@ -1,7 +1,6 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
*/
/***************************************************************************
* copyright-holders:Aaron Giles
***************************************************************************
bitstream.c
@ -9,8 +8,8 @@
***************************************************************************/
#include "bitstream.h"
#include <stdlib.h>
#include <libchdr/bitstream.h>
/***************************************************************************
* INLINE FUNCTIONS
@ -108,9 +107,10 @@ uint32_t bitstream_read_offset(struct bitstream* bitstream)
}
//-------------------------------------------------
// flush - flush to the nearest byte
//-------------------------------------------------
/*-------------------------------------------------
* flush - flush to the nearest byte
*-------------------------------------------------
*/
uint32_t bitstream_flush(struct bitstream* bitstream)
{

View File

@ -1,6 +1,6 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
***************************************************************************
bitstream.h

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
cdrom.c
@ -15,12 +15,12 @@
schemes will differ after track 1!
***************************************************************************/
#ifdef WANT_RAW_DATA_SECTOR
#include <assert.h>
#include <string.h>
#include "cdrom.h"
#include <libchdr/cdrom.h>
#ifdef WANT_RAW_DATA_SECTOR
/***************************************************************************
DEBUGGING
@ -64,8 +64,6 @@ void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
#define LOG(x)
#endif
/***************************************************************************
CONSTANTS
***************************************************************************/
@ -92,8 +90,6 @@ void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
/** @brief 43 bytes each. */
#define ECC_Q_COMP 43
/**
* @brief -------------------------------------------------
* ECC lookup tables pre-calculated tables for ECC data calcs
@ -301,16 +297,16 @@ static const uint16_t qoffsets[ECC_Q_NUM_BYTES][ECC_Q_COMP] =
{ 0x867,0x003,0x05b,0x0b3,0x10b,0x163,0x1bb,0x213,0x26b,0x2c3,0x31b,0x373,0x3cb,0x423,0x47b,0x4d3,0x52b,0x583,0x5db,0x633,0x68b,0x6e3,0x73b,0x793,0x7eb,0x843,0x89b,0x037,0x08f,0x0e7,0x13f,0x197,0x1ef,0x247,0x29f,0x2f7,0x34f,0x3a7,0x3ff,0x457,0x4af,0x507,0x55f }
};
/*-------------------------------------------------
* ecc_source_byte - return data from the sector
* at the given offset, masking anything
* particular to a mode
*-------------------------------------------------
*/
//-------------------------------------------------
// ecc_source_byte - return data from the sector
// at the given offset, masking anything
// particular to a mode
//-------------------------------------------------
static inline uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
INLINE uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
{
// in mode 2 always treat these as 0 bytes
/* in mode 2 always treat these as 0 bytes */
return (sector[MODE_OFFSET] == 2 && offset < 4) ? 0x00 : sector[SYNC_OFFSET + SYNC_NUM_BYTES + offset];
}
@ -330,8 +326,9 @@ static inline uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, uint8_t *val1, uint8_t *val2)
{
int component;
*val1 = *val2 = 0;
for (int component = 0; component < rowlen; component++)
for (component = 0; component < rowlen; component++)
{
*val1 ^= ecc_source_byte(sector, row[component]);
*val2 ^= ecc_source_byte(sector, row[component]);
@ -355,8 +352,9 @@ void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, u
int ecc_verify(const uint8_t *sector)
{
// first verify P bytes
for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
int byte;
/* first verify P bytes */
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
{
uint8_t val1, val2;
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &val1, &val2);
@ -364,8 +362,8 @@ int ecc_verify(const uint8_t *sector)
return 0;
}
// then verify Q bytes
for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
/* then verify Q bytes */
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
{
uint8_t val1, val2;
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &val1, &val2);
@ -388,12 +386,13 @@ int ecc_verify(const uint8_t *sector)
void ecc_generate(uint8_t *sector)
{
// first verify P bytes
for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
int byte;
/* first verify P bytes */
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &sector[ECC_P_OFFSET + byte], &sector[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte]);
// then verify Q bytes
for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
/* then verify Q bytes */
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &sector[ECC_Q_OFFSET + byte], &sector[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
}

View File

@ -1,6 +1,6 @@
/* license:BSD-3-Clause */
/* copyright-holders:Aaron Giles */
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
cdrom.h
@ -14,15 +14,14 @@
#define __CDROM_H__
#include <stdint.h>
#include <libchdr/chdconfig.h>
/***************************************************************************
CONSTANTS
***************************************************************************/
/* tracks are padded to a multiple of this many frames */
#define CD_TRACK_PADDING (4)
#define CD_TRACK_PADDING (4)
#define CD_MAX_TRACKS (99) /* AFAIK the theoretical limit */
#define CD_MAX_SECTOR_DATA (2352)
#define CD_MAX_SUBCODE_DATA (96)
@ -53,8 +52,8 @@ enum
CD_SUB_NONE /* no subcode data stored */
};
#define CD_FLAG_GDROM 0x00000001 // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
#define CD_FLAG_GDROMLE 0x00000002 // legacy GD-ROM, with little-endian CDDA data
#define CD_FLAG_GDROM 0x00000001 /* disc is a GD-ROM, all tracks should be stored with GD-ROM metadata */
#define CD_FLAG_GDROMLE 0x00000002 /* legacy GD-ROM, with little-endian CDDA data */
/***************************************************************************
FUNCTION PROTOTYPES
@ -67,4 +66,45 @@ void ecc_generate(uint8_t *sector);
void ecc_clear(uint8_t *sector);
#endif
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE uint32_t msf_to_lba(uint32_t msf)
{
return ( ((msf&0x00ff0000)>>16) * 60 * 75) + (((msf&0x0000ff00)>>8) * 75) + ((msf&0x000000ff)>>0);
}
INLINE uint32_t lba_to_msf(uint32_t lba)
{
uint8_t m, s, f;
m = lba / (60 * 75);
lba -= m * (60 * 75);
s = lba / 75;
f = lba % 75;
return ((m / 10) << 20) | ((m % 10) << 16) |
((s / 10) << 12) | ((s % 10) << 8) |
((f / 10) << 4) | ((f % 10) << 0);
}
/**
* segacd needs it like this.. investigate
* Angelo also says PCE tracks often start playing at the
* wrong address.. related?
**/
INLINE uint32_t lba_to_msf_alt(int lba)
{
uint32_t ret = 0;
ret |= ((lba / (60 * 75))&0xff)<<16;
ret |= (((lba / 75) % 60)&0xff)<<8;
ret |= ((lba % 75)&0xff)<<0;
return ret;
}
#endif /* __CDROM_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -46,8 +46,8 @@
extern "C" {
#endif
#include "coretypes.h"
#include <libchdr/coretypes.h>
#include <libchdr/chdconfig.h>
/***************************************************************************
@ -194,12 +194,21 @@ extern "C" {
#define CHDFLAGS_IS_WRITEABLE 0x00000002
#define CHDFLAGS_UNDEFINED 0xfffffffc
#define CHD_MAKE_TAG(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
/* compression types */
#define CHDCOMPRESSION_NONE 0
#define CHDCOMPRESSION_ZLIB 1
#define CHDCOMPRESSION_ZLIB_PLUS 2
#define CHDCOMPRESSION_AV 3
#define CHD_CODEC_NONE 0
#define CHD_CODEC_ZLIB CHD_MAKE_TAG('z','l','i','b')
/* general codecs with CD frontend */
#define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')
#define CHD_CODEC_CD_LZMA CHD_MAKE_TAG('c','d','l','z')
#define CHD_CODEC_CD_FLAC CHD_MAKE_TAG('c','d','f','l')
/* A/V codec configuration parameters */
#define AV_CODEC_COMPRESS_CONFIG 1
#define AV_CODEC_DECOMPRESS_CONFIG 2
@ -212,33 +221,34 @@ extern "C" {
#define CHD_MDFLAGS_CHECKSUM 0x01 /* indicates data is checksummed */
/* standard hard disk metadata */
#define HARD_DISK_METADATA_TAG 0x47444444 /* 'GDDD' */
#define HARD_DISK_METADATA_TAG CHD_MAKE_TAG('G','D','D','D')
#define HARD_DISK_METADATA_FORMAT "CYLS:%d,HEADS:%d,SECS:%d,BPS:%d"
/* hard disk identify information */
#define HARD_DISK_IDENT_METADATA_TAG 0x49444e54 /* 'IDNT' */
#define HARD_DISK_IDENT_METADATA_TAG CHD_MAKE_TAG('I','D','N','T')
/* hard disk key information */
#define HARD_DISK_KEY_METADATA_TAG 0x4b455920 /* 'KEY ' */
#define HARD_DISK_KEY_METADATA_TAG CHD_MAKE_TAG('K','E','Y',' ')
/* pcmcia CIS information */
#define PCMCIA_CIS_METADATA_TAG 0x43495320 /* 'CIS ' */
#define PCMCIA_CIS_METADATA_TAG CHD_MAKE_TAG('C','I','S',' ')
/* standard CD-ROM metadata */
#define CDROM_OLD_METADATA_TAG 0x43484344 /* 'CHCD' */
#define CDROM_TRACK_METADATA_TAG 0x43485452 /* 'CHTR' */
#define CDROM_OLD_METADATA_TAG CHD_MAKE_TAG('C','H','C','D')
#define CDROM_TRACK_METADATA_TAG CHD_MAKE_TAG('C','H','T','R')
#define CDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d"
#define CDROM_TRACK_METADATA2_TAG 0x43485432 /* 'CHT2' */
#define CDROM_TRACK_METADATA2_TAG CHD_MAKE_TAG('C','H','T','2')
#define CDROM_TRACK_METADATA2_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
#define GDROM_TRACK_METADATA_TAG 0x43484744 /* 'CHTD' */
#define GDROM_OLD_METADATA_TAG CHD_MAKE_TAG('C','H','G','T')
#define GDROM_TRACK_METADATA_TAG CHD_MAKE_TAG('C', 'H', 'G', 'D')
#define GDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PAD:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
/* standard A/V metadata */
#define AV_METADATA_TAG 0x41564156 /* 'AVAV' */
#define AV_METADATA_TAG CHD_MAKE_TAG('A','V','A','V')
#define AV_METADATA_FORMAT "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d"
/* A/V laserdisc frame metadata */
#define AV_LD_METADATA_TAG 0x41564C44 /* 'AVLD' */
#define AV_LD_METADATA_TAG CHD_MAKE_TAG('A','V','L','D')
/* CHD open values */
#define CHD_OPEN_READ 1
@ -305,9 +315,9 @@ struct _chd_header
UINT8 parentmd5[CHD_MD5_BYTES]; /* overall MD5 checksum of parent */
UINT8 sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
UINT8 rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
UINT8 parentsha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum of parent */
UINT8 parentsha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum of parent */
UINT32 unitbytes; /* TODO V5 */
UINT64 unitcount; /* TODO V5 */
UINT64 unitcount; /* TODO V5 */
UINT32 hunkcount; /* TODO V5 */
/* map information */
@ -337,6 +347,19 @@ struct _chd_verify_result
FUNCTION PROTOTYPES
***************************************************************************/
#ifdef _MSC_VER
#ifdef CHD_DLL
#ifdef CHD_DLL_EXPORTS
#define CHD_EXPORT __declspec(dllexport)
#else
#define CHD_EXPORT __declspec(dllimport)
#endif
#else
#define CHD_EXPORT
#endif
#else
#define CHD_EXPORT __attribute__ ((visibility("default")))
#endif
/* ----- CHD file management ----- */
@ -347,25 +370,27 @@ struct _chd_verify_result
/* chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
/* open an existing CHD file */
chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
/* precache underlying file */
CHD_EXPORT chd_error chd_precache(chd_file *chd);
/* close a CHD file */
void chd_close(chd_file *chd);
CHD_EXPORT void chd_close(chd_file *chd);
/* return the associated core_file */
core_file *chd_core_file(chd_file *chd);
CHD_EXPORT core_file *chd_core_file(chd_file *chd);
/* return an error string for the given CHD error */
const char *chd_error_string(chd_error err);
CHD_EXPORT const char *chd_error_string(chd_error err);
/* ----- CHD header management ----- */
/* return a pointer to the extracted CHD header data */
const chd_header *chd_get_header(chd_file *chd);
CHD_EXPORT const chd_header *chd_get_header(chd_file *chd);
@ -373,14 +398,14 @@ const chd_header *chd_get_header(chd_file *chd);
/* ----- core data read/write ----- */
/* read one hunk from the CHD file */
chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer);
CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer);
/* ----- metadata management ----- */
/* get indexed metadata of a particular sort */
chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags);
CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags);
@ -388,10 +413,10 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex,
/* ----- codec interfaces ----- */
/* set internal codec parameters */
chd_error chd_codec_config(chd_file *chd, int param, void *config);
CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config);
/* return a string description of a codec */
const char *chd_get_codec_name(UINT32 codec);
CHD_EXPORT const char *chd_get_codec_name(UINT32 codec);
#ifdef __cplusplus
}

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
flac.c
@ -10,28 +10,35 @@
#include <assert.h>
#include <string.h>
#include "flac.h"
//**************************************************************************
// FLAC DECODER
//**************************************************************************
#include <libchdr/flac.h>
#define DR_FLAC_IMPLEMENTATION
#include <dr_libs/dr_flac.h>
static FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes);
static void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
/***************************************************************************
* FLAC DECODER
***************************************************************************
*/
static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes);
static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin);
static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata);
static void flac_decoder_write_callback(void *userdata, void *buffer, size_t len);
/* getters (valid after reset) */
static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
/*-------------------------------------------------
* flac_decoder - constructor
*-------------------------------------------------
*/
void flac_decoder_init(flac_decoder *decoder)
int flac_decoder_init(flac_decoder *decoder)
{
decoder->decoder = FLAC__stream_decoder_new();
decoder->decoder = NULL;
decoder->sample_rate = 0;
decoder->channels = 0;
decoder->bits_per_sample = 0;
@ -43,6 +50,7 @@ void flac_decoder_init(flac_decoder *decoder)
decoder->uncompressed_offset = 0;
decoder->uncompressed_length = 0;
decoder->uncompressed_swap = 0;
return 0;
}
/*-------------------------------------------------
@ -53,10 +61,10 @@ void flac_decoder_init(flac_decoder *decoder)
void flac_decoder_free(flac_decoder* decoder)
{
if ((decoder != NULL) && (decoder->decoder != NULL))
FLAC__stream_decoder_delete(decoder->decoder);
drflac_close(decoder->decoder);
decoder->decoder = NULL;
}
/*-------------------------------------------------
* reset - reset state with the original
* parameters
@ -66,21 +74,13 @@ void flac_decoder_free(flac_decoder* decoder)
static int flac_decoder_internal_reset(flac_decoder* decoder)
{
decoder->compressed_offset = 0;
if (FLAC__stream_decoder_init_stream(decoder->decoder,
&flac_decoder_read_callback_static,
NULL,
&flac_decoder_tell_callback_static,
NULL,
NULL,
&flac_decoder_write_callback_static,
&flac_decoder_metadata_callback_static,
&flac_decoder_error_callback_static, decoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
return 0;
return FLAC__stream_decoder_process_until_end_of_metadata(decoder->decoder);
flac_decoder_free(decoder);
decoder->decoder = drflac_open_with_metadata(
flac_decoder_read_callback, flac_decoder_seek_callback,
flac_decoder_metadata_callback, decoder, NULL);
return (decoder->decoder != NULL);
}
/*-------------------------------------------------
* reset - reset state with new memory parameters
* and a custom-generated header
@ -94,43 +94,46 @@ int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_
{
0x66, 0x4C, 0x61, 0x43, /* +00: 'fLaC' stream header */
0x80, /* +04: metadata block type 0 (STREAMINFO), */
/* flagged as last block */
/* flagged as last block */
0x00, 0x00, 0x22, /* +05: metadata block length = 0x22 */
0x00, 0x00, /* +08: minimum block size */
0x00, 0x00, /* +0A: maximum block size */
0x00, 0x00, 0x00, /* +0C: minimum frame size (0 == unknown) */
0x00, 0x00, 0x00, /* +0F: maximum frame size (0 == unknown) */
0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, /* +12: sample rate (0x0ac44 == 44100), */
/* numchannels (2), sample bits (16), */
/* samples in stream (0 == unknown) */
/* numchannels (2), sample bits (16), */
/* samples in stream (0 == unknown) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* +1A: MD5 signature (0 == none) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* */
/* +2A: start of stream data */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* +2A: start of stream data */
};
memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = block_size >> 8;
decoder->custom_header[0x09] = decoder->custom_header[0x0b] = block_size & 0xff;
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = (block_size*num_channels) >> 8;
decoder->custom_header[0x09] = decoder->custom_header[0x0b] = (block_size*num_channels) & 0xff;
decoder->custom_header[0x12] = sample_rate >> 12;
decoder->custom_header[0x13] = sample_rate >> 4;
decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
/* configure the header ahead of the provided buffer */
decoder->compressed_start = (const FLAC__byte *)(decoder->custom_header);
decoder->compressed_start = (const uint8_t *)(decoder->custom_header);
decoder->compressed_length = sizeof(decoder->custom_header);
decoder->compressed2_start = (const FLAC__byte *)(buffer);
decoder->compressed2_start = (const uint8_t *)(buffer);
decoder->compressed2_length = length;
return flac_decoder_internal_reset(decoder);
}
/*-------------------------------------------------
* decode_interleaved - decode to an interleaved
* sound stream
*-------------------------------------------------
*/
#define BUFFER 2352 /* bytes per CD audio sector */
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
{
int16_t buffer[BUFFER];
uint32_t buf_samples;
/* configure the uncompressed buffer */
memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
decoder->uncompressed_start[0] = samples;
@ -138,45 +141,18 @@ int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uin
decoder->uncompressed_length = num_samples;
decoder->uncompressed_swap = swap_endian;
buf_samples = BUFFER / channels(decoder);
/* loop until we get everything we want */
while (decoder->uncompressed_offset < decoder->uncompressed_length)
if (!FLAC__stream_decoder_process_single(decoder->decoder))
while (decoder->uncompressed_offset < decoder->uncompressed_length) {
uint32_t frames = (num_samples < buf_samples ? num_samples : buf_samples);
if (!drflac_read_pcm_frames_s16(decoder->decoder, frames, buffer))
return 0;
flac_decoder_write_callback(decoder, buffer, frames*sizeof(*buffer)*channels(decoder));
num_samples -= frames;
}
return 1;
}
#if 0
/*
*-------------------------------------------------
* decode - decode to an multiple independent
* data streams
*-------------------------------------------------
*/
bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_endian)
{
/* make sure we don't have too many channels */
int chans = channels();
if (chans > ARRAY_LENGTH(m_uncompressed_start))
return false;
/* configure the uncompressed buffer */
memset(m_uncompressed_start, 0, sizeof(m_uncompressed_start));
for (int curchan = 0; curchan < chans; curchan++)
m_uncompressed_start[curchan] = samples[curchan];
m_uncompressed_offset = 0;
m_uncompressed_length = num_samples;
m_uncompressed_swap = swap_endian;
/* loop until we get everything we want */
while (m_uncompressed_offset < m_uncompressed_length)
if (!FLAC__stream_decoder_process_single(m_decoder))
return false;
return true;
}
#endif
/*-------------------------------------------------
* finish - finish up the decode
*-------------------------------------------------
@ -185,19 +161,24 @@ bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_end
uint32_t flac_decoder_finish(flac_decoder* decoder)
{
/* get the final decoding position and move forward */
FLAC__uint64 position = 0;
FLAC__stream_decoder_get_decode_position(decoder->decoder, &position);
FLAC__stream_decoder_finish(decoder->decoder);
drflac *flac = decoder->decoder;
uint64_t position = decoder->compressed_offset;
/* ugh... there's no function to obtain bytes used in drflac :-/ */
position -= DRFLAC_CACHE_L2_LINES_REMAINING(&flac->bs) * sizeof(drflac_cache_t);
position -= DRFLAC_CACHE_L1_BITS_REMAINING(&flac->bs) / 8;
position -= flac->bs.unalignedByteCount;
/* adjust position if we provided the header */
if (position == 0)
return 0;
if (decoder->compressed_start == (const FLAC__byte *)(decoder->custom_header))
if (decoder->compressed_start == (const uint8_t *)(decoder->custom_header))
position -= decoder->compressed_length;
flac_decoder_free(decoder);
return position;
}
/*-------------------------------------------------
* read_callback - handle reads from the input
* stream
@ -206,128 +187,119 @@ uint32_t flac_decoder_finish(flac_decoder* decoder)
#define MIN(x, y) ((x) < (y) ? (x) : (y))
FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes)
{
return flac_decoder_read_callback(client_data, buffer, bytes);
}
FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes)
{
flac_decoder* decoder = (flac_decoder*)client_data;
uint32_t expected = *bytes;
flac_decoder* decoder = (flac_decoder*)userdata;
uint8_t *dst = buffer;
/* copy from primary buffer first */
uint32_t outputpos = 0;
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length)
if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length)
{
uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
memcpy(&buffer[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
memcpy(&dst[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy;
}
/* once we're out of that, copy from the secondary buffer */
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
{
uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
memcpy(&buffer[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
memcpy(&dst[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy;
}
*bytes = outputpos;
/* return based on whether we ran out of data */
return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
return outputpos;
}
/*-------------------------------------------------
* metadata_callback - handle STREAMINFO metadata
*-------------------------------------------------
*/
void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata)
{
flac_decoder *fldecoder;
flac_decoder *decoder = userdata;
/* ignore all but STREAMINFO metadata */
if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO)
if (metadata->type != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO)
return;
/* parse out the data we care about */
fldecoder = (flac_decoder *)(client_data);
fldecoder->sample_rate = metadata->data.stream_info.sample_rate;
fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
fldecoder->channels = metadata->data.stream_info.channels;
decoder->sample_rate = metadata->data.streaminfo.sampleRate;
decoder->bits_per_sample = metadata->data.streaminfo.bitsPerSample;
decoder->channels = metadata->data.streaminfo.channels;
}
/*-------------------------------------------------
* tell_callback - handle requests to find out
* where in the input stream we are
*-------------------------------------------------
*/
FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
{
*absolute_byte_offset = ((flac_decoder *)client_data)->compressed_offset;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
/*-------------------------------------------------
* write_callback - handle writes to the output
* stream
*-------------------------------------------------
*/
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
return flac_decoder_write_callback(client_data, frame, buffer);
}
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void *client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes)
{
int sampnum, chan;
int shift, blocksize;
flac_decoder * decoder = (flac_decoder *)client_data;
assert(frame->header.channels == decoder->channels);
int shift, blocksize;
flac_decoder * decoder = (flac_decoder *)userdata;
int16_t *sampbuf = (int16_t *)buffer;
int sampch = channels(decoder);
uint32_t offset = decoder->uncompressed_offset;
uint16_t usample;
/* interleaved case */
shift = decoder->uncompressed_swap ? 8 : 0;
blocksize = frame->header.blocksize;
blocksize = bytes / (sampch * sizeof(sampbuf[0]));
if (decoder->uncompressed_start[1] == NULL)
{
int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels;
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
for (chan = 0; chan < frame->header.channels; chan++)
*dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift));
int16_t *dest = decoder->uncompressed_start[0] + offset * sampch;
for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
*dest++ = (int16_t)((usample << shift) | (usample >> shift));
}
}
/* non-interleaved case */
else
{
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
for (chan = 0; chan < frame->header.channels; chan++)
for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
if (decoder->uncompressed_start[chan] != NULL)
decoder->uncompressed_start[chan][decoder->uncompressed_offset] = (int16_t) ( (((uint16_t)(buffer[chan][sampnum])) << shift) | ( ((uint16_t)(buffer[chan][sampnum])) >> shift) );
decoder->uncompressed_start[chan][offset] = (int16_t) ((usample << shift) | (usample >> shift));
}
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
decoder->uncompressed_offset = offset;
}
/**
* @fn void flac_decoder::error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
*
* @brief -------------------------------------------------
* error_callback - handle errors (ignore them)
* -------------------------------------------------.
*
* @param decoder The decoder.
* @param status The status.
* @param [in,out] client_data If non-null, information describing the client.
/*-------------------------------------------------
* seek_callback - handle seeks on the output
* stream
*-------------------------------------------------
*/
void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin)
{
flac_decoder * decoder = (flac_decoder *)userdata;
uint32_t length = decoder->compressed_length + decoder->compressed2_length;
if (origin == drflac_seek_origin_start) {
uint32_t pos = offset;
if (pos <= length) {
decoder->compressed_offset = pos;
return 1;
}
} else if (origin == drflac_seek_origin_current) {
uint32_t pos = decoder->compressed_offset + offset;
if (pos <= length) {
decoder->compressed_offset = pos;
return 1;
}
}
return 0;
}

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
flac.h
@ -14,38 +14,37 @@
#define __FLAC_H__
#include <stdint.h>
#include "FLAC/ordinals.h"
#include "FLAC/stream_decoder.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
typedef struct _flac_decoder flac_decoder;
struct _flac_decoder {
// output state
FLAC__StreamDecoder* decoder; // actual encoder
uint32_t sample_rate; // decoded sample rate
uint8_t channels; // decoded number of channels
uint8_t bits_per_sample; // decoded bits per sample
uint32_t compressed_offset; // current offset in compressed data
const FLAC__byte * compressed_start; // start of compressed data
uint32_t compressed_length; // length of compressed data
const FLAC__byte * compressed2_start; // start of compressed data
uint32_t compressed2_length; // length of compressed data
int16_t * uncompressed_start[8]; // pointer to start of uncompressed data (up to 8 streams)
uint32_t uncompressed_offset; // current position in uncompressed data
uint32_t uncompressed_length; // length of uncompressed data
int uncompressed_swap; // swap uncompressed sample data
uint8_t custom_header[0x2a]; // custom header
/* output state */
void * decoder; /* actual encoder */
uint32_t sample_rate; /* decoded sample rate */
uint8_t channels; /* decoded number of channels */
uint8_t bits_per_sample; /* decoded bits per sample */
uint32_t compressed_offset; /* current offset in compressed data */
const uint8_t * compressed_start; /* start of compressed data */
uint32_t compressed_length; /* length of compressed data */
const uint8_t * compressed2_start; /* start of compressed data */
uint32_t compressed2_length; /* length of compressed data */
int16_t * uncompressed_start[8]; /* pointer to start of uncompressed data (up to 8 streams) */
uint32_t uncompressed_offset; /* current position in uncompressed data */
uint32_t uncompressed_length; /* length of uncompressed data */
int uncompressed_swap; /* swap uncompressed sample data */
uint8_t custom_header[0x2a]; /* custom header */
};
// ======================> flac_decoder
/* ======================> flac_decoder */
void flac_decoder_init(flac_decoder* decoder);
int flac_decoder_init(flac_decoder* decoder);
void flac_decoder_free(flac_decoder* decoder);
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);
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian);
uint32_t flac_decoder_finish(flac_decoder* decoder);
#endif // __FLAC_H__
#endif /* __FLAC_H__ */

View File

@ -1,6 +1,6 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
****************************************************************************
huffman.c
@ -101,7 +101,7 @@
#include <stdio.h>
#include <string.h>
#include "huffman.h"
#include <libchdr/huffman.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
@ -112,10 +112,9 @@
#define MAKE_LOOKUP(code,bits) (((code) << 5) | ((bits) & 0x1f))
/***************************************************************************
* IMPLEMENTATION
* **************************************************************************
***************************************************************************
*/
/*-------------------------------------------------
@ -126,7 +125,8 @@
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
{
struct huffman_decoder* decoder;
struct huffman_decoder* decoder = NULL;
/* limit to 24 bits */
if (maxbits > 24)
return NULL;
@ -181,10 +181,10 @@ uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* b
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
enum huffman_error error;
int numbits, curnode;
enum huffman_error error;
/* bits per entry depends on the maxbits */
int numbits;
int curnode;
if (decoder->maxbits >= 16)
numbits = 5;
else if (decoder->maxbits >= 8)
@ -243,19 +243,18 @@ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, stru
enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
int start;
int last = 0;
int count = 0;
int index;
int curcode;
uint32_t temp;
enum huffman_error error;
uint8_t rlefullbits = 0;
int index, count = 0;
int start;
uint32_t temp;
enum huffman_error error;
/* start by parsing the lengths for the small tree */
struct huffman_decoder* smallhuff = create_huffman_decoder(24, 6);
smallhuff->huffnode[0].numbits = bitstream_read(bitbuf, 3);
start = bitstream_read(bitbuf, 3) + 1;
for (index = 1; index < 24; index++)
{
if (index < start || count == 7)
@ -310,7 +309,6 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
}
/*-------------------------------------------------
* compute_tree_from_histo - common backend for
* computing a tree based on the data histogram
@ -319,15 +317,16 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
{
/* compute the number of data items in the histogram */
int i;
uint32_t upperweight;
uint32_t lowerweight = 0;
uint32_t lowerweight;
uint32_t upperweight;
/* compute the number of data items in the histogram */
uint32_t sdatacount = 0;
for (i = 0; i < decoder->numcodes; i++)
sdatacount += decoder->datahisto[i];
/* binary search to achieve the optimum encoding */
lowerweight = 0;
upperweight = sdatacount * 2;
while (1)
{
@ -352,8 +351,6 @@ enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decod
return huffman_assign_canonical_codes(decoder);
}
/***************************************************************************
* INTERNAL FUNCTIONS
***************************************************************************
@ -376,7 +373,6 @@ static int huffman_tree_node_compare(const void *item1, const void *item2)
return (int)node1->bits - (int)node2->bits;
}
/*-------------------------------------------------
* build_tree - build a huffman tree based on the
* data distribution
@ -385,11 +381,12 @@ static int huffman_tree_node_compare(const void *item1, const void *item2)
int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
{
int nextalloc;
int curcode;
int nextalloc;
int listitems = 0;
int maxbits = 0;
/* make a list of all non-zero nodes */
struct node_t** list = (struct node_t**)malloc(sizeof(struct node_t*) * decoder->numcodes * 2);
int curcode, listitems = 0;
memset(decoder->huffnode, 0, decoder->numcodes * sizeof(decoder->huffnode[0]));
for (curcode = 0; curcode < decoder->numcodes; curcode++)
if (decoder->datahisto[curcode] != 0)
@ -403,24 +400,27 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
if (decoder->huffnode[curcode].weight == 0)
decoder->huffnode[curcode].weight = 1;
}
/*
#if 0
fprintf(stderr, "Pre-sort:\n");
for (int i = 0; i < listitems; i++) {
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
}
*/
#endif
/* sort the list by weight, largest weight first */
qsort(&list[0], listitems, sizeof(list[0]), huffman_tree_node_compare);
/*
#if 0
fprintf(stderr, "Post-sort:\n");
for (int i = 0; i < listitems; i++) {
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
}
fprintf(stderr, "===================\n");
*/
#endif
/* now build the tree */
nextalloc = decoder->numcodes;
while (listitems > 1)
{
int curitem;
@ -453,7 +453,7 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
node->numbits = 0;
node->bits = 0;
// if we have a non-zero weight, compute the number of bits
/* if we have a non-zero weight, compute the number of bits */
if (node->weight > 0)
{
/* determine the number of bits for this node */
@ -469,7 +469,6 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
return maxbits;
}
/*-------------------------------------------------
* assign_canonical_codes - assign canonical codes
* to all the nodes based on the number of bits
@ -479,9 +478,9 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
{
int curcode, codelen;
uint32_t curstart = 0;
/* build up a histogram of bit lengths */
int curcode, codelen;
uint32_t bithisto[33] = { 0 };
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
@ -512,7 +511,6 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
return HUFFERR_NONE;
}
/*-------------------------------------------------
* build_lookup_table - build a lookup table for
* fast decoding
@ -521,8 +519,8 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
void huffman_build_lookup_table(struct huffman_decoder* decoder)
{
/* iterate over all codes */
int curcode;
/* iterate over all codes */
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
/* process all nodes which have non-zero bits */

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
huffman.h
@ -13,12 +13,13 @@
#ifndef __HUFFMAN_H__
#define __HUFFMAN_H__
#include "bitstream.h"
#include <libchdr/bitstream.h>
//**************************************************************************
// CONSTANTS
//**************************************************************************
/***************************************************************************
* CONSTANTS
***************************************************************************
*/
enum huffman_error
{
@ -31,49 +32,50 @@ enum huffman_error
HUFFERR_TOO_MANY_CONTEXTS
};
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
typedef uint16_t lookup_value;
// a node in the huffman tree
/* a node in the huffman tree */
struct node_t
{
struct node_t* parent; // pointer to parent node
uint32_t count; // number of hits on this node
uint32_t weight; // assigned weight of this node
uint32_t bits; // bits used to encode the node
uint8_t numbits; // number of bits needed for this node
struct node_t* parent; /* pointer to parent node */
uint32_t count; /* number of hits on this node */
uint32_t weight; /* assigned weight of this node */
uint32_t bits; /* bits used to encode the node */
uint8_t numbits; /* number of bits needed for this node */
};
// ======================> huffman_context_base
/* ======================> huffman_context_base */
// context class for decoding
/* context class for decoding */
struct huffman_decoder
{
// internal state
uint32_t numcodes; // number of total codes being processed
uint8_t maxbits; // maximum bits per code
uint8_t prevdata; // value of the previous data (for delta-RLE encoding)
int rleremaining; // number of RLE bytes remaining (for delta-RLE encoding)
lookup_value * lookup; // pointer to the lookup table
struct node_t * huffnode; // array of nodes
uint32_t * datahisto; // histogram of data values
/* internal state */
uint32_t numcodes; /* number of total codes being processed */
uint8_t maxbits; /* maximum bits per code */
uint8_t prevdata; /* value of the previous data (for delta-RLE encoding) */
int rleremaining; /* number of RLE bytes remaining (for delta-RLE encoding) */
lookup_value * lookup; /* pointer to the lookup table */
struct node_t * huffnode; /* array of nodes */
uint32_t * datahisto; /* histogram of data values */
// array versions of the info we need
//node_t* huffnode_array; //[_NumCodes];
//lookup_value* lookup_array; //[1 << _MaxBits];
/* array versions of the info we need */
#if 0
node_t* huffnode_array; /* [_NumCodes]; */
lookup_value* lookup_array; /* [1 << _MaxBits]; */
#endif
};
// ======================> huffman_decoder
/* ======================> huffman_decoder */
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits);
void delete_huffman_decoder(struct huffman_decoder* decoder);
// single item operations
/* single item operations */
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf);
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf);

View File

@ -86,7 +86,7 @@ struct blip_t
#define BLIP_BUFFER_STATE_BUFFER_SIZE 16
typedef struct blip_buffer_state_t
struct blip_buffer_state_t
{
fixed_t offset;
#ifdef BLIP_MONO

View File

@ -2528,7 +2528,7 @@ static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
/* handle an error */
if (err != CHDERR_NONE)
free(data);
zlib_codec_free(data);
return err;
}

View File

@ -152,7 +152,7 @@ static const void *g_rom_data = NULL;
static size_t g_rom_size = 0;
static char *save_dir = NULL;
static retro_log_printf_t log_cb;
retro_log_printf_t log_cb;
static retro_video_refresh_t video_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;
@ -400,7 +400,7 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten
if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP))
{
if (log_cb)
log_cb(RETRO_LOG_ERROR, "Unable to open CD BIOS: %s.\n", filename);
log_cb(RETRO_LOG_ERROR, "Unable to open CD BIOS: \"%s\".\n", filename);
return 0;
}
@ -426,7 +426,7 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten
size = maxsize;
if (log_cb)
log_cb(RETRO_LOG_INFO, "INFORMATION - Loading %d bytes ...\n", size);
log_cb(RETRO_LOG_INFO, "Loading %d bytes ...\n", size);
/* Read into buffer */
left = size;
@ -1710,6 +1710,15 @@ static void check_variables(bool first_run)
config.cd_latency = 0;
}
var.key = "genesis_plus_gx_cd_precache";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{
if (!var.value || !strcmp(var.value, "disabled"))
config.cd_precache = 0;
else
config.cd_precache = 1;
}
var.key = "genesis_plus_gx_add_on";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{
@ -3806,6 +3815,8 @@ void retro_run(void)
bool updated = false;
int vwoffset = 0;
int bmdoffset = 0;
int soundbuffer_size = 0;
is_running = true;
#ifdef HAVE_OVERCLOCK
@ -3894,6 +3905,8 @@ void retro_run(void)
system_frame_sms(do_skip);
}
soundbuffer_size = audio_update(soundbuffer);
if (bitmap.viewport.changed & 9)
{
bool geometry_updated = update_viewport();
@ -3956,7 +3969,7 @@ void retro_run(void)
video_cb(NULL, vwidth - vwoffset, vheight, 720 * 2);
}
audio_cb(soundbuffer, audio_update(soundbuffer));
audio_cb(soundbuffer, soundbuffer_size);
}
#undef CHUNKSIZE

View File

@ -936,9 +936,9 @@ struct retro_core_option_v2_definition option_defs_us[] = {
},
{
"genesis_plus_gx_cd_latency",
"CD access time",
"CD Access Time",
NULL,
"Simulate original CD hardware latency when initiating a read or seeking to a specific location on loaded disc. This is required by a few CD games that crash if CD data is available too soon and also fixes CD audio desync issues in some games. Disabling this can be useful with MSU-MD games as it makes CD audio tracks loops more seamless.",
"Simulate original CD hardware latency when initiating a read or seeking to a specific location on loaded disc. This is required by a few CD games that crash if CD data is available too soon and also fixes CD audio desync issues in some games. Disabling this can be useful with MSU-MD games as it makes CD audio tracks loops more seamless.",
NULL,
"hacks",
{
@ -948,6 +948,20 @@ struct retro_core_option_v2_definition option_defs_us[] = {
},
"enabled"
},
{
"genesis_plus_gx_cd_precache",
"CD Image Cache",
NULL,
"Load CD image to memory on startup. CHD supported only. Restart Required.",
NULL,
"hacks",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled"
},
#ifdef USE_PER_SOUND_CHANNELS_CONFIG
{
"genesis_plus_gx_show_advanced_audio_settings",

View File

@ -136,6 +136,7 @@ typedef struct
uint8 enhanced_vscroll;
uint8 enhanced_vscroll_limit;
uint8 cd_latency;
bool cd_precache;
#ifdef USE_PER_SOUND_CHANNELS_CONFIG
unsigned int psg_ch_volumes[4];
int32 md_ch_volumes[6];
@ -161,6 +162,7 @@ extern char MS_BIOS_JP[256];
extern void osd_input_update(void);
extern int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
extern void ROMCheatUpdate(void);
extern retro_log_printf_t log_cb;
#ifndef cdStream
#define cdStream RFILE