dep/libchdr: Update to a03e693

This commit is contained in:
Connor McLaughlin 2022-04-03 20:27:06 +10:00
parent ef6e18a1b2
commit 6b8486674f
12 changed files with 12610 additions and 181 deletions

View file

@ -1,4 +1,5 @@
add_library(libchdr add_library(libchdr
include/dr_libs/dr_flac.h
include/libchdr/bitstream.h include/libchdr/bitstream.h
include/libchdr/cdrom.h include/libchdr/cdrom.h
include/libchdr/chd.h include/libchdr/chd.h

File diff suppressed because it is too large Load diff

View file

@ -347,7 +347,7 @@ struct _chd_verify_result
FUNCTION PROTOTYPES FUNCTION PROTOTYPES
***************************************************************************/ ***************************************************************************/
#ifdef WIN32 #ifdef _MSC_VER
#ifdef CHD_DLL #ifdef CHD_DLL
#ifdef CHD_DLL_EXPORTS #ifdef CHD_DLL_EXPORTS
#define CHD_EXPORT __declspec(dllexport) #define CHD_EXPORT __declspec(dllexport)
@ -355,7 +355,6 @@ struct _chd_verify_result
#define CHD_EXPORT __declspec(dllimport) #define CHD_EXPORT __declspec(dllimport)
#endif #endif
#else #else
// Static library.
#define CHD_EXPORT #define CHD_EXPORT
#endif #endif
#else #else
@ -393,6 +392,8 @@ CHD_EXPORT const char *chd_error_string(chd_error err);
/* return a pointer to the extracted CHD header data */ /* return a pointer to the extracted CHD header data */
CHD_EXPORT const chd_header *chd_get_header(chd_file *chd); CHD_EXPORT const chd_header *chd_get_header(chd_file *chd);
/* read CHD header data from file into the pointed struct */
CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header);

View file

@ -3,8 +3,8 @@
/* Configure CHDR features here */ /* Configure CHDR features here */
#define WANT_RAW_DATA_SECTOR 1 #define WANT_RAW_DATA_SECTOR 1
#define WANT_SUBCODE 0 #define WANT_SUBCODE 1
#define NEED_CACHE_HUNK 0 #define NEED_CACHE_HUNK 1
#define VERIFY_BLOCK_CRC 0 #define VERIFY_BLOCK_CRC 1
#endif #endif

View file

@ -4,12 +4,21 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#ifdef __LIBRETRO__ #ifdef USE_LIBRETRO_VFS
#include <streams/file_stream_transforms.h> #include <streams/file_stream_transforms.h>
#endif #endif
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
#if defined(__PS3__) || defined(__PSL1GHT__)
#undef UINT32
#undef UINT16
#undef UINT8
#undef INT32
#undef INT16
#undef INT8
#endif
typedef uint64_t UINT64; typedef uint64_t UINT64;
typedef uint32_t UINT32; typedef uint32_t UINT32;
typedef uint16_t UINT16; typedef uint16_t UINT16;
@ -22,17 +31,33 @@ typedef int8_t INT8;
#define core_file FILE #define core_file FILE
#define core_fopen(file) fopen(file, "rb") #define core_fopen(file) fopen(file, "rb")
#if defined USE_LIBRETRO_VFS
#define core_fseek fseek #define core_fseek fseek
#define core_ftell ftell
#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WIN64__)
#define core_fseek _fseeki64
#define core_ftell _ftelli64
#elif defined(_LARGEFILE_SOURCE) && defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
#define core_fseek fseeko64
#define core_ftell ftello64
#elif defined(__PS3__) && !defined(__PSL1GHT__) || defined(__SWITCH__)
#define core_fseek(x,y,z) fseek(x,(off_t)y,z)
#define core_ftell(x) (off_t)ftell(x)
#else
#define core_fseek fseeko
#define core_ftell ftello
#endif
#define core_fread(fc, buff, len) fread(buff, 1, len, fc) #define core_fread(fc, buff, len) fread(buff, 1, len, fc)
#define core_fclose fclose #define core_fclose fclose
#define core_ftell ftell
static inline size_t core_fsize(core_file *f) static UINT64 core_fsize(core_file *f)
{ {
long rv; UINT64 rv;
long p = ftell(f); UINT64 p = core_ftell(f);
fseek(f, 0, SEEK_END); core_fseek(f, 0, SEEK_END);
rv = ftell(f); rv = core_ftell(f);
fseek(f, p, SEEK_SET); core_fseek(f, p, SEEK_SET);
return rv; return rv;
} }

View file

@ -14,7 +14,6 @@
#define __FLAC_H__ #define __FLAC_H__
#include <stdint.h> #include <stdint.h>
#include <FLAC/all.h>
/*************************************************************************** /***************************************************************************
* TYPE DEFINITIONS * TYPE DEFINITIONS
@ -24,14 +23,14 @@
typedef struct _flac_decoder flac_decoder; typedef struct _flac_decoder flac_decoder;
struct _flac_decoder { struct _flac_decoder {
/* output state */ /* output state */
FLAC__StreamDecoder* decoder; /* actual encoder */ void * decoder; /* actual encoder */
uint32_t sample_rate; /* decoded sample rate */ uint32_t sample_rate; /* decoded sample rate */
uint8_t channels; /* decoded number of channels */ uint8_t channels; /* decoded number of channels */
uint8_t bits_per_sample; /* decoded bits per sample */ uint8_t bits_per_sample; /* decoded bits per sample */
uint32_t compressed_offset; /* current offset in compressed data */ uint32_t compressed_offset; /* current offset in compressed data */
const FLAC__byte * compressed_start; /* start of compressed data */ const uint8_t * compressed_start; /* start of compressed data */
uint32_t compressed_length; /* length of compressed data */ uint32_t compressed_length; /* length of compressed data */
const FLAC__byte * compressed2_start; /* start of compressed data */ const uint8_t * compressed2_start; /* start of compressed data */
uint32_t compressed2_length; /* length 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) */ 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_offset; /* current position in uncompressed data */
@ -42,7 +41,7 @@ struct _flac_decoder {
/* ======================> 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); 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_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); int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian);

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\msvc\vsprops\Configurations.props" /> <Import Project="..\msvc\vsprops\Configurations.props" />
<ItemGroup Condition="'$(Configuration)'!='DebugUWP' And '$(Configuration)'!='ReleaseUWP'"> <ItemGroup Condition="'$(Configuration)'!='DebugUWP' And '$(Configuration)'!='ReleaseUWP'">
<ProjectReference Include="..\libFLAC\libFLAC.vcxproj"> <ProjectReference Include="..\libFLAC\libFLAC.vcxproj">
<Project>{97cbd3cb-cbc7-4d52-abde-f0ae7b794a5d}</Project> <Project>{97cbd3cb-cbc7-4d52-abde-f0ae7b794a5d}</Project>
@ -13,7 +12,6 @@
<Project>{7ff9fdb9-d504-47db-a16a-b08071999620}</Project> <Project>{7ff9fdb9-d504-47db-a16a-b08071999620}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\libchdr_bitstream.c" /> <ClCompile Include="src\libchdr_bitstream.c" />
<ClCompile Include="src\libchdr_cdrom.c" /> <ClCompile Include="src\libchdr_cdrom.c" />
@ -22,6 +20,7 @@
<ClCompile Include="src\libchdr_huffman.c" /> <ClCompile Include="src\libchdr_huffman.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="include\dr_libs\dr_flac.h" />
<ClInclude Include="include\libchdr\bitstream.h" /> <ClInclude Include="include\libchdr\bitstream.h" />
<ClInclude Include="include\libchdr\cdrom.h" /> <ClInclude Include="include\libchdr\cdrom.h" />
<ClInclude Include="include\libchdr\chd.h" /> <ClInclude Include="include\libchdr\chd.h" />
@ -30,13 +29,10 @@
<ClInclude Include="include\libchdr\flac.h" /> <ClInclude Include="include\libchdr\flac.h" />
<ClInclude Include="include\libchdr\huffman.h" /> <ClInclude Include="include\libchdr\huffman.h" />
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}</ProjectGuid> <ProjectGuid>{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}</ProjectGuid>
</PropertyGroup> </PropertyGroup>
<Import Project="..\msvc\vsprops\StaticLibrary.props" /> <Import Project="..\msvc\vsprops\StaticLibrary.props" />
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>
@ -44,6 +40,5 @@
<AdditionalIncludeDirectories>$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\lzma\include;$(SolutionDir)dep\libFLAC\include;$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\lzma\include;$(SolutionDir)dep\libFLAC\include;$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<Import Project="..\msvc\vsprops\Targets.props" /> <Import Project="..\msvc\vsprops\Targets.props" />
</Project> </Project>

View file

@ -15,5 +15,6 @@
<ClInclude Include="include\libchdr\huffman.h" /> <ClInclude Include="include\libchdr\huffman.h" />
<ClInclude Include="include\libchdr\bitstream.h" /> <ClInclude Include="include\libchdr\bitstream.h" />
<ClInclude Include="include\libchdr\cdrom.h" /> <ClInclude Include="include\libchdr\cdrom.h" />
<ClInclude Include="include\dr_libs\dr_flac.h" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -15,7 +15,7 @@
schemes will differ after track 1! schemes will differ after track 1!
***************************************************************************/ ***************************************************************************/
#include <assert.h>
#include <string.h> #include <string.h>
#include <libchdr/cdrom.h> #include <libchdr/cdrom.h>

View file

@ -50,6 +50,9 @@
#include "LzmaEnc.h" #include "LzmaEnc.h"
#include "LzmaDec.h" #include "LzmaDec.h"
#if defined(__PS3__) || defined(__PSL1GHT__)
#define __MACTYPES__
#endif
#include "zlib.h" #include "zlib.h"
#undef TRUE #undef TRUE
@ -430,7 +433,7 @@ static void *lzma_fast_alloc(void *p, size_t size)
addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES); addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
if (addr==NULL) if (addr==NULL)
return NULL; return NULL;
for (int scan = 0; scan < MAX_LZMA_ALLOCS; scan++) for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{ {
if (codec->allocptr[scan] == NULL) if (codec->allocptr[scan] == NULL)
{ {
@ -794,8 +797,7 @@ static chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
#endif #endif
/* flac decoder init */ /* flac decoder init */
flac_decoder_init(&cdfl->decoder); if (flac_decoder_init(&cdfl->decoder))
if (cdfl->decoder.decoder == NULL)
return CHDERR_OUT_OF_MEMORY; return CHDERR_OUT_OF_MEMORY;
return CHDERR_NONE; return CHDERR_NONE;
@ -1161,7 +1163,7 @@ static inline int chd_compressed(chd_header* header) {
static chd_error decompress_v5_map(chd_file* chd, chd_header* header) static chd_error decompress_v5_map(chd_file* chd, chd_header* header)
{ {
int result = 0; int result = 0;
int hunknum; uint32_t hunknum;
int repcount = 0; int repcount = 0;
uint8_t lastcomp = 0; uint8_t lastcomp = 0;
uint32_t last_self = 0; uint32_t last_self = 0;
@ -1383,8 +1385,15 @@ CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent,
EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION); EARLY_EXIT(err = CHDERR_UNSUPPORTED_VERSION);
/* if we need a parent, make sure we have one */ /* if we need a parent, make sure we have one */
if (parent == NULL && (newchd->header.flags & CHDFLAGS_HAS_PARENT)) if (parent == NULL)
{
/* Detect parent requirement for versions below 5 */
if (newchd->header.version < 5 && newchd->header.flags & CHDFLAGS_HAS_PARENT)
EARLY_EXIT(err = CHDERR_REQUIRES_PARENT); EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
/* Detection for version 5 and above - if parentsha1 != 0, we have a parent */
else if (newchd->header.version >= 5 && memcmp(nullsha1, newchd->header.parentsha1, sizeof(newchd->header.parentsha1)) != 0)
EARLY_EXIT(err = CHDERR_REQUIRES_PARENT);
}
/* make sure we have a valid parent */ /* make sure we have a valid parent */
if (parent != NULL) if (parent != NULL)
@ -1561,6 +1570,12 @@ CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent,
chd_error err; chd_error err;
core_file *file = NULL; core_file *file = NULL;
if (filename == NULL)
{
err = CHDERR_INVALID_PARAMETER;
goto cleanup;
}
/* choose the proper mode */ /* choose the proper mode */
switch(mode) switch(mode)
{ {
@ -1677,6 +1692,9 @@ CHD_EXPORT void chd_close(chd_file *chd)
if (chd->file_cache) if (chd->file_cache)
free(chd->file_cache); free(chd->file_cache);
if (chd->parent)
chd_close(chd->parent);
/* free our memory */ /* free our memory */
free(chd); free(chd);
} }
@ -1750,6 +1768,41 @@ CHD_EXPORT const chd_header *chd_get_header(chd_file *chd)
return &chd->header; return &chd->header;
} }
/*-------------------------------------------------
chd_read_header - read CHD header data
from file into the pointed struct
-------------------------------------------------*/
CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header)
{
chd_error err = CHDERR_NONE;
chd_file chd;
/* punt if NULL */
if (filename == NULL || header == NULL)
EARLY_EXIT(err = CHDERR_INVALID_PARAMETER);
/* open the file */
chd.file = core_fopen(filename);
if (chd.file == NULL)
EARLY_EXIT(err = CHDERR_FILE_NOT_FOUND);
/* attempt to read the header */
err = header_read(&chd, header);
if (err != CHDERR_NONE)
EARLY_EXIT(err);
/* validate the header */
err = header_validate(header);
if (err != CHDERR_NONE)
EARLY_EXIT(err);
cleanup:
if (chd.file != NULL)
core_fclose(chd.file);
return err;
}
/*************************************************************************** /***************************************************************************
CORE DATA READ/WRITE CORE DATA READ/WRITE
***************************************************************************/ ***************************************************************************/
@ -2344,13 +2397,33 @@ static chd_error hunk_read_into_memory(chd_file *chd, UINT32 hunknum, UINT8 *des
return hunk_read_into_memory(chd, blockoffs, dest); return hunk_read_into_memory(chd, blockoffs, dest);
case COMPRESSION_PARENT: case COMPRESSION_PARENT:
#if 0 if (chd->parent == NULL)
/* TODO */
if (m_parent_missing)
return CHDERR_REQUIRES_PARENT; return CHDERR_REQUIRES_PARENT;
return m_parent->read_bytes(uint64_t(blockoffs) * uint64_t(m_parent->unit_bytes()), dest, m_hunkbytes); UINT8 units_in_hunk = chd->header.hunkbytes / chd->header.unitbytes;
#endif
return CHDERR_DECOMPRESSION_ERROR; /* blockoffs is aligned to units_in_hunk */
if (blockoffs % units_in_hunk == 0) {
return hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, dest);
/* blockoffs is not aligned to units_in_hunk */
} else {
UINT32 unit_in_hunk = blockoffs % units_in_hunk;
UINT8 *buf = malloc(chd->header.hunkbytes);
/* Read first half of hunk which contains blockoffs */
err = hunk_read_into_memory(chd->parent, blockoffs / units_in_hunk, buf);
if (err != CHDERR_NONE) {
free(buf);
return err;
}
memcpy(dest, buf + unit_in_hunk * chd->header.unitbytes, (units_in_hunk - unit_in_hunk) * chd->header.unitbytes);
/* Read second half of hunk which contains blockoffs */
err = hunk_read_into_memory(chd->parent, (blockoffs / units_in_hunk) + 1, buf);
if (err != CHDERR_NONE) {
free(buf);
return err;
}
memcpy(dest + (units_in_hunk - unit_in_hunk) * chd->header.unitbytes, buf, unit_in_hunk * chd->header.unitbytes);
free(buf);
}
} }
return CHDERR_NONE; return CHDERR_NONE;
} }
@ -2375,7 +2448,7 @@ static chd_error map_read(chd_file *chd)
UINT8 cookie[MAP_ENTRY_SIZE]; UINT8 cookie[MAP_ENTRY_SIZE];
UINT32 count; UINT32 count;
chd_error err; chd_error err;
int i; UINT32 i;
/* first allocate memory */ /* first allocate memory */
chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks); chd->map = (map_entry *)malloc(sizeof(chd->map[0]) * chd->header.totalhunks);
@ -2545,8 +2618,6 @@ static void zlib_codec_free(void *codec)
/* deinit the streams */ /* deinit the streams */
if (data != NULL) if (data != NULL)
{ {
int i;
inflateEnd(&data->inflater); inflateEnd(&data->inflater);
/* free our fast memory */ /* free our fast memory */

View file

@ -8,40 +8,37 @@
***************************************************************************/ ***************************************************************************/
#include <assert.h>
#include <string.h> #include <string.h>
#include <libchdr/flac.h> #include <libchdr/flac.h>
#define DR_FLAC_IMPLEMENTATION
#define DR_FLAC_NO_STDIO
#include <dr_libs/dr_flac.h>
/*************************************************************************** /***************************************************************************
* FLAC DECODER * FLAC DECODER
*************************************************************************** ***************************************************************************
*/ */
static 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);
FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte 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_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata);
static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes);
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);
/* getters (valid after reset) */ /* getters (valid after reset) */
static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; } 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 channels(flac_decoder *decoder) { return decoder->channels; }
static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; } static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
static uint32_t total_samples(flac_decoder *decoder) { return FLAC__stream_decoder_get_total_samples(decoder->decoder); }
static FLAC__StreamDecoderState state(flac_decoder *decoder) { return FLAC__stream_decoder_get_state(decoder->decoder); }
static const char *state_string(flac_decoder *decoder) { return FLAC__stream_decoder_get_resolved_state_string(decoder->decoder); }
/*------------------------------------------------- /*-------------------------------------------------
* flac_decoder - constructor * 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->sample_rate = 0;
decoder->channels = 0; decoder->channels = 0;
decoder->bits_per_sample = 0; decoder->bits_per_sample = 0;
@ -53,6 +50,7 @@ void flac_decoder_init(flac_decoder *decoder)
decoder->uncompressed_offset = 0; decoder->uncompressed_offset = 0;
decoder->uncompressed_length = 0; decoder->uncompressed_length = 0;
decoder->uncompressed_swap = 0; decoder->uncompressed_swap = 0;
return 0;
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -63,7 +61,8 @@ void flac_decoder_init(flac_decoder *decoder)
void flac_decoder_free(flac_decoder* decoder) void flac_decoder_free(flac_decoder* decoder)
{ {
if ((decoder != NULL) && (decoder->decoder != NULL)) if ((decoder != NULL) && (decoder->decoder != NULL))
FLAC__stream_decoder_delete(decoder->decoder); drflac_close(decoder->decoder);
decoder->decoder = NULL;
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -75,17 +74,11 @@ void flac_decoder_free(flac_decoder* decoder)
static int flac_decoder_internal_reset(flac_decoder* decoder) static int flac_decoder_internal_reset(flac_decoder* decoder)
{ {
decoder->compressed_offset = 0; decoder->compressed_offset = 0;
if (FLAC__stream_decoder_init_stream(decoder->decoder, flac_decoder_free(decoder);
&flac_decoder_read_callback_static, decoder->decoder = drflac_open_with_metadata(
NULL, flac_decoder_read_callback, flac_decoder_seek_callback,
&flac_decoder_tell_callback_static, flac_decoder_metadata_callback, decoder, NULL);
NULL, return (decoder->decoder != 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);
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -114,16 +107,16 @@ int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_
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)); 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[0x08] = decoder->custom_header[0x0a] = (block_size*num_channels) >> 8;
decoder->custom_header[0x09] = decoder->custom_header[0x0b] = block_size & 0xff; decoder->custom_header[0x09] = decoder->custom_header[0x0b] = (block_size*num_channels) & 0xff;
decoder->custom_header[0x12] = sample_rate >> 12; decoder->custom_header[0x12] = sample_rate >> 12;
decoder->custom_header[0x13] = sample_rate >> 4; decoder->custom_header[0x13] = sample_rate >> 4;
decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1); decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
/* configure the header ahead of the provided buffer */ /* 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->compressed_length = sizeof(decoder->custom_header);
decoder->compressed2_start = (const FLAC__byte *)(buffer); decoder->compressed2_start = (const uint8_t *)(buffer);
decoder->compressed2_length = length; decoder->compressed2_length = length;
return flac_decoder_internal_reset(decoder); return flac_decoder_internal_reset(decoder);
} }
@ -143,43 +136,20 @@ int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uin
decoder->uncompressed_length = num_samples; decoder->uncompressed_length = num_samples;
decoder->uncompressed_swap = swap_endian; decoder->uncompressed_swap = swap_endian;
#define BUFFER 2352 /* bytes per CD audio sector */
int16_t buffer[BUFFER];
uint32_t buf_samples = BUFFER / channels(decoder);
/* loop until we get everything we want */ /* loop until we get everything we want */
while (decoder->uncompressed_offset < decoder->uncompressed_length) while (decoder->uncompressed_offset < decoder->uncompressed_length) {
if (!FLAC__stream_decoder_process_single(decoder->decoder)) uint32_t frames = (num_samples < buf_samples ? num_samples : buf_samples);
if (!drflac_read_pcm_frames_s16(decoder->decoder, frames, buffer))
return 0; return 0;
flac_decoder_write_callback(decoder, buffer, frames*sizeof(*buffer)*channels(decoder));
num_samples -= frames;
}
return 1; 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 * finish - finish up the decode
*------------------------------------------------- *-------------------------------------------------
@ -188,15 +158,21 @@ bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_end
uint32_t flac_decoder_finish(flac_decoder* decoder) uint32_t flac_decoder_finish(flac_decoder* decoder)
{ {
/* get the final decoding position and move forward */ /* get the final decoding position and move forward */
FLAC__uint64 position = 0; drflac *flac = decoder->decoder;
FLAC__stream_decoder_get_decode_position(decoder->decoder, &position); uint64_t position = decoder->compressed_offset;
FLAC__stream_decoder_finish(decoder->decoder);
/* 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 */ /* adjust position if we provided the header */
if (position == 0) if (position == 0)
return 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; position -= decoder->compressed_length;
flac_decoder_free(decoder);
return position; return position;
} }
@ -208,39 +184,31 @@ uint32_t flac_decoder_finish(flac_decoder* decoder)
#define MIN(x, y) ((x) < (y) ? (x) : (y)) #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_decoder* decoder = (flac_decoder*)userdata;
} uint8_t *dst = buffer;
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;
/* copy from primary buffer first */ /* copy from primary buffer first */
uint32_t outputpos = 0; 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); 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); memcpy(&dst[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
outputpos += bytes_to_copy; outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy; decoder->compressed_offset += bytes_to_copy;
} }
/* once we're out of that, copy from the secondary buffer */ /* 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)); 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); memcpy(&dst[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
outputpos += bytes_to_copy; outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy; decoder->compressed_offset += bytes_to_copy;
} }
*bytes = outputpos;
/* return based on whether we ran out of data */ return outputpos;
return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -248,30 +216,18 @@ FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC
*------------------------------------------------- *-------------------------------------------------
*/ */
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 */ /* ignore all but STREAMINFO metadata */
if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO) if (metadata->type != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO)
return; return;
/* parse out the data we care about */ /* parse out the data we care about */
fldecoder = (flac_decoder *)(client_data); decoder->sample_rate = metadata->data.streaminfo.sampleRate;
fldecoder->sample_rate = metadata->data.stream_info.sample_rate; decoder->bits_per_sample = metadata->data.streaminfo.bitsPerSample;
fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample; decoder->channels = metadata->data.streaminfo.channels;
fldecoder->channels = metadata->data.stream_info.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;
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -280,53 +236,67 @@ FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__Stre
*------------------------------------------------- *-------------------------------------------------
*/ */
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes)
{
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[])
{ {
int sampnum, chan; int sampnum, chan;
int shift, blocksize; int shift, blocksize;
flac_decoder * decoder = (flac_decoder *)client_data; flac_decoder * decoder = (flac_decoder *)userdata;
int16_t *sampbuf = (int16_t *)buffer;
assert(frame->header.channels == channels(decoder)); int sampch = channels(decoder);
uint32_t offset = decoder->uncompressed_offset;
uint16_t usample;
/* interleaved case */ /* interleaved case */
shift = decoder->uncompressed_swap ? 8 : 0; shift = decoder->uncompressed_swap ? 8 : 0;
blocksize = frame->header.blocksize; blocksize = bytes / (sampch * sizeof(sampbuf[0]));
if (decoder->uncompressed_start[1] == NULL) if (decoder->uncompressed_start[1] == NULL)
{ {
int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels; int16_t *dest = decoder->uncompressed_start[0] + offset * sampch;
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++) for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < frame->header.channels; chan++) for (chan = 0; chan < sampch; chan++) {
*dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift)); usample = (uint16_t)*sampbuf++;
*dest++ = (int16_t)((usample << shift) | (usample >> shift));
}
} }
/* non-interleaved case */ /* non-interleaved case */
else else
{ {
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++) for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < frame->header.channels; chan++) for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
if (decoder->uncompressed_start[chan] != NULL) 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) /*-------------------------------------------------
* * seek_callback - handle seeks on the output
* @brief ------------------------------------------------- * stream
* 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.
*/ */
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

@ -97,7 +97,6 @@
***************************************************************************/ ***************************************************************************/
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -181,7 +180,8 @@ 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 huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{ {
int numbits, curnode; int numbits;
uint32_t curnode;
enum huffman_error error; enum huffman_error error;
/* bits per entry depends on the maxbits */ /* bits per entry depends on the maxbits */
@ -247,7 +247,7 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
int last = 0; int last = 0;
int count = 0; int count = 0;
int index; int index;
int curcode; uint32_t curcode;
uint8_t rlefullbits = 0; uint8_t rlefullbits = 0;
uint32_t temp; uint32_t temp;
enum huffman_error error; enum huffman_error error;
@ -317,7 +317,7 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder) enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
{ {
int i; uint32_t i;
uint32_t lowerweight; uint32_t lowerweight;
uint32_t upperweight; uint32_t upperweight;
/* compute the number of data items in the histogram */ /* compute the number of data items in the histogram */
@ -381,7 +381,7 @@ 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 huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
{ {
int curcode; uint32_t curcode;
int nextalloc; int nextalloc;
int listitems = 0; int listitems = 0;
int maxbits = 0; int maxbits = 0;
@ -478,7 +478,8 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder) enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
{ {
int curcode, codelen; uint32_t curcode;
int codelen;
uint32_t curstart = 0; uint32_t curstart = 0;
/* build up a histogram of bit lengths */ /* build up a histogram of bit lengths */
uint32_t bithisto[33] = { 0 }; uint32_t bithisto[33] = { 0 };
@ -519,7 +520,7 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
void huffman_build_lookup_table(struct huffman_decoder* decoder) void huffman_build_lookup_table(struct huffman_decoder* decoder)
{ {
int curcode; uint32_t curcode;
/* iterate over all codes */ /* iterate over all codes */
for (curcode = 0; curcode < decoder->numcodes; curcode++) for (curcode = 0; curcode < decoder->numcodes; curcode++)
{ {