You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dr_libs/tests/flac/dr_flac_decoding.c

826 lines
28 KiB
C

/*#define DR_FLAC_NO_CRC*/
/*#define DR_FLAC_NO_SIMD*/
/*#define DR_FLAC_BUFFER_SIZE 4096*/
#include "dr_flac_common.c"
#define FILE_NAME_WIDTH 40
#define NUMBER_WIDTH 10
#define TABLE_MARGIN 2
#define DEFAULT_SOURCE_DIR "testvectors/flac/testbench"
drflac_result decode_test__read_and_compare_pcm_frames_s32(libflac* pLibFlac, drflac* pFlac, drflac_uint64 pcmFrameCount, drflac_int32* pPCMFrames_libflac, drflac_int32* pPCMFrames_drflac)
{
drflac_uint64 pcmFrameCount_libflac;
drflac_uint64 pcmFrameCount_drflac;
drflac_uint64 iPCMFrame;
/* To test decoding we just read a number of PCM frames from each decoder and compare. */
pcmFrameCount_libflac = libflac_read_pcm_frames_s32(pLibFlac, pcmFrameCount, pPCMFrames_libflac);
pcmFrameCount_drflac = drflac_read_pcm_frames_s32(pFlac, pcmFrameCount, pPCMFrames_drflac);
/* The total number of frames we decoded need to match. */
if (pcmFrameCount_libflac != pcmFrameCount_drflac) {
printf(" Decoded frame counts differ: pcmFrameCount=%d, libFLAC=%d, dr_flac=%d", (int)pcmFrameCount, (int)pcmFrameCount_libflac, (int)pcmFrameCount_drflac);
return DRFLAC_ERROR;
}
/* Each of the decoded PCM frames need to match. */
DRFLAC_ASSERT(pcmFrameCount_libflac == pcmFrameCount_drflac);
for (iPCMFrame = 0; iPCMFrame < pcmFrameCount_libflac; iPCMFrame += 1) {
drflac_int32* pPCMFrame_libflac = pPCMFrames_libflac + (iPCMFrame * pLibFlac->channels);
drflac_int32* pPCMFrame_drflac = pPCMFrames_drflac + (iPCMFrame * pLibFlac->channels);
drflac_uint32 iChannel;
drflac_bool32 hasError = DRFLAC_FALSE;
for (iChannel = 0; iChannel < pLibFlac->channels; iChannel += 1) {
if (pPCMFrame_libflac[iChannel] != pPCMFrame_drflac[iChannel]) {
printf(" PCM Frame @ %d[%d] does not match: pcmFrameCount=%d\n", (int)iPCMFrame, iChannel, (int)pcmFrameCount);
hasError = DRFLAC_TRUE;
break;
}
}
if (hasError) {
return DRFLAC_ERROR; /* Decoded frames do not match. */
}
}
/* Done. */
return DRFLAC_SUCCESS;
}
drflac_result decode_test__read_and_compare_pcm_frame_chunks_s32(libflac* pLibFlac, drflac* pFlac, drflac_uint64 pcmFrameChunkSize)
{
drflac_result result = DRFLAC_SUCCESS;
drflac_uint64 iPCMFrame;
drflac_int32* pPCMFrames_libflac;
drflac_int32* pPCMFrames_drflac;
/* Make sure the decoder's are seeked back to the start first. */
drflac_seek_to_pcm_frame(pFlac, 0);
libflac_seek_to_pcm_frame(pLibFlac, 0);
pPCMFrames_libflac = (drflac_int32*)malloc((size_t)(pcmFrameChunkSize * pLibFlac->channels * sizeof(drflac_int32)));
if (pPCMFrames_libflac == NULL) {
printf(" [libFLAC] Out of memory");
return DRFLAC_ERROR;
}
pPCMFrames_drflac = (drflac_int32*)malloc((size_t)(pcmFrameChunkSize * pLibFlac->channels * sizeof(drflac_int32)));
if (pPCMFrames_drflac == NULL) {
free(pPCMFrames_libflac);
printf(" [dr_flac] Out of memory");
return DRFLAC_ERROR;
}
for (iPCMFrame = 0; iPCMFrame < pLibFlac->pcmFrameCount; iPCMFrame += pcmFrameChunkSize) {
result = decode_test__read_and_compare_pcm_frames_s32(pLibFlac, pFlac, pcmFrameChunkSize, pPCMFrames_libflac, pPCMFrames_drflac);
if (result != DRFLAC_SUCCESS) {
break;
}
}
free(pPCMFrames_libflac);
free(pPCMFrames_drflac);
return result;
}
drflac_result decode_test__read_and_compare_pcm_frames_f32(libflac* pLibFlac, drflac* pFlac, drflac_uint64 pcmFrameCount, float* pPCMFrames_libflac, float* pPCMFrames_drflac)
{
drflac_uint64 pcmFrameCount_libflac;
drflac_uint64 pcmFrameCount_drflac;
drflac_uint64 iPCMFrame;
/* To test decoding we just read a number of PCM frames from each decoder and compare. */
pcmFrameCount_libflac = libflac_read_pcm_frames_f32(pLibFlac, pcmFrameCount, pPCMFrames_libflac);
pcmFrameCount_drflac = drflac_read_pcm_frames_f32(pFlac, pcmFrameCount, pPCMFrames_drflac);
/* The total number of frames we decoded need to match. */
if (pcmFrameCount_libflac != pcmFrameCount_drflac) {
printf(" Decoded frame counts differ: pcmFrameCount=%d, libFLAC=%d, dr_flac=%d", (int)pcmFrameCount, (int)pLibFlac->currentPCMFrame, (int)pFlac->currentPCMFrame);
return DRFLAC_ERROR;
}
/* Each of the decoded PCM frames need to match. */
DRFLAC_ASSERT(pcmFrameCount_libflac == pcmFrameCount_drflac);
for (iPCMFrame = 0; iPCMFrame < pcmFrameCount_libflac; iPCMFrame += 1) {
float* pPCMFrame_libflac = pPCMFrames_libflac + (iPCMFrame * pLibFlac->channels);
float* pPCMFrame_drflac = pPCMFrames_drflac + (iPCMFrame * pLibFlac->channels);
drflac_uint32 iChannel;
drflac_bool32 hasError = DRFLAC_FALSE;
for (iChannel = 0; iChannel < pLibFlac->channels; iChannel += 1) {
if (pPCMFrame_libflac[iChannel] != pPCMFrame_drflac[iChannel]) {
printf(" PCM Frame @ %d[%d] does not match: pcmFrameCount=%d", (int)iPCMFrame, iChannel, (int)pcmFrameCount);
hasError = DRFLAC_TRUE;
break;
}
}
if (hasError) {
return DRFLAC_ERROR; /* Decoded frames do not match. */
}
}
/* Done. */
return DRFLAC_SUCCESS;
}
drflac_result decode_test__read_and_compare_pcm_frame_chunks_f32(libflac* pLibFlac, drflac* pFlac, drflac_uint64 pcmFrameChunkSize)
{
drflac_result result = DRFLAC_SUCCESS;
drflac_uint64 iPCMFrame;
float* pPCMFrames_libflac;
float* pPCMFrames_drflac;
/* Make sure the decoder's are seeked back to the start first. */
drflac_seek_to_pcm_frame(pFlac, 0);
libflac_seek_to_pcm_frame(pLibFlac, 0);
pPCMFrames_libflac = (float*)malloc((size_t)(pcmFrameChunkSize * pLibFlac->channels * sizeof(float)));
if (pPCMFrames_libflac == NULL) {
printf(" [libFLAC] Out of memory");
return DRFLAC_ERROR;
}
pPCMFrames_drflac = (float*)malloc((size_t)(pcmFrameChunkSize * pLibFlac->channels * sizeof(float)));
if (pPCMFrames_drflac == NULL) {
free(pPCMFrames_libflac);
printf(" [dr_flac] Out of memory");
return DRFLAC_ERROR;
}
for (iPCMFrame = 0; iPCMFrame < pLibFlac->pcmFrameCount; iPCMFrame += pcmFrameChunkSize) {
result = decode_test__read_and_compare_pcm_frames_f32(pLibFlac, pFlac, pcmFrameChunkSize, pPCMFrames_libflac, pPCMFrames_drflac);
if (result != DRFLAC_SUCCESS) {
break;
}
}
free(pPCMFrames_libflac);
free(pPCMFrames_drflac);
return result;
}
drflac_result decode_test__read_and_compare_pcm_frames_s16(libflac* pLibFlac, drflac* pFlac, drflac_uint64 pcmFrameCount, drflac_int16* pPCMFrames_libflac, drflac_int16* pPCMFrames_drflac)
{
drflac_uint64 pcmFrameCount_libflac;
drflac_uint64 pcmFrameCount_drflac;
drflac_uint64 iPCMFrame;
/* To test decoding we just read a number of PCM frames from each decoder and compare. */
pcmFrameCount_libflac = libflac_read_pcm_frames_s16(pLibFlac, pcmFrameCount, pPCMFrames_libflac);
pcmFrameCount_drflac = drflac_read_pcm_frames_s16(pFlac, pcmFrameCount, pPCMFrames_drflac);
/* The total number of frames we decoded need to match. */
if (pcmFrameCount_libflac != pcmFrameCount_drflac) {
printf(" Decoded frame counts differ: pcmFrameCount=%d, libFLAC=%d, dr_flac=%d", (int)pcmFrameCount, (int)pLibFlac->currentPCMFrame, (int)pFlac->currentPCMFrame);
return DRFLAC_ERROR;
}
/* Each of the decoded PCM frames need to match. */
DRFLAC_ASSERT(pcmFrameCount_libflac == pcmFrameCount_drflac);
for (iPCMFrame = 0; iPCMFrame < pcmFrameCount_libflac; iPCMFrame += 1) {
drflac_int16* pPCMFrame_libflac = pPCMFrames_libflac + (iPCMFrame * pLibFlac->channels);
drflac_int16* pPCMFrame_drflac = pPCMFrames_drflac + (iPCMFrame * pLibFlac->channels);
drflac_uint32 iChannel;
drflac_bool32 hasError = DRFLAC_FALSE;
for (iChannel = 0; iChannel < pLibFlac->channels; iChannel += 1) {
if (pPCMFrame_libflac[iChannel] != pPCMFrame_drflac[iChannel]) {
printf(" PCM Frame @ %d[%d] does not match: pcmFrameCount=%d", (int)iPCMFrame, iChannel, (int)pcmFrameCount);
hasError = DRFLAC_TRUE;
break;
}
}
if (hasError) {
return DRFLAC_ERROR; /* Decoded frames do not match. */
}
}
/* Done. */
return DRFLAC_SUCCESS;
}
drflac_result decode_test__read_and_compare_pcm_frame_chunks_s16(libflac* pLibFlac, drflac* pFlac, drflac_uint64 pcmFrameChunkSize)
{
drflac_result result = DRFLAC_SUCCESS;
drflac_uint64 iPCMFrame;
drflac_int16* pPCMFrames_libflac;
drflac_int16* pPCMFrames_drflac;
/* Make sure the decoder's are seeked back to the start first. */
drflac_seek_to_pcm_frame(pFlac, 0);
libflac_seek_to_pcm_frame(pLibFlac, 0);
pPCMFrames_libflac = (drflac_int16*)malloc((size_t)(pcmFrameChunkSize * pLibFlac->channels * sizeof(drflac_int16)));
if (pPCMFrames_libflac == NULL) {
printf(" [libFLAC] Out of memory");
return DRFLAC_ERROR;
}
pPCMFrames_drflac = (drflac_int16*)malloc((size_t)(pcmFrameChunkSize * pLibFlac->channels * sizeof(drflac_int16)));
if (pPCMFrames_drflac == NULL) {
free(pPCMFrames_libflac);
printf(" [dr_flac] Out of memory");
return DRFLAC_ERROR;
}
for (iPCMFrame = 0; iPCMFrame < pLibFlac->pcmFrameCount; iPCMFrame += pcmFrameChunkSize) {
result = decode_test__read_and_compare_pcm_frames_s16(pLibFlac, pFlac, pcmFrameChunkSize, pPCMFrames_libflac, pPCMFrames_drflac);
if (result != DRFLAC_SUCCESS) {
break;
}
}
free(pPCMFrames_libflac);
free(pPCMFrames_drflac);
return result;
}
drflac_result decode_test_file_s32(libflac* pLibFlac, drflac* pFlac)
{
drflac_result result = DRFLAC_SUCCESS;
/* Start with reading the entire file in one go. */
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_s32(pLibFlac, pFlac, pLibFlac->pcmFrameCount);
}
/* Now try with reading one PCM frame at a time.*/
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_s32(pLibFlac, pFlac, 1);
}
/* Now test FLAC frame boundaries. */
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_s32(pLibFlac, pFlac, (pFlac->maxBlockSizeInPCMFrames > 0) ? pFlac->maxBlockSizeInPCMFrames : 4096);
}
return result;
}
drflac_result decode_test_file_f32(libflac* pLibFlac, drflac* pFlac)
{
drflac_result result = DRFLAC_SUCCESS;
/* Start with reading the entire file in one go. */
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_f32(pLibFlac, pFlac, pLibFlac->pcmFrameCount);
}
/* Now try with reading one PCM frame at a time.*/
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_f32(pLibFlac, pFlac, 1);
}
/* Now test FLAC frame boundaries. */
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_f32(pLibFlac, pFlac, (pFlac->maxBlockSizeInPCMFrames > 0) ? pFlac->maxBlockSizeInPCMFrames : 4096);
}
return result;
}
drflac_result decode_test_file_s16(libflac* pLibFlac, drflac* pFlac)
{
drflac_result result = DRFLAC_SUCCESS;
/* Start with reading the entire file in one go. */
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_s16(pLibFlac, pFlac, pLibFlac->pcmFrameCount);
}
/* Now try with reading one PCM frame at a time.*/
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_s16(pLibFlac, pFlac, 1);
}
/* Now test FLAC frame boundaries. */
if (result == DRFLAC_SUCCESS) {
result = decode_test__read_and_compare_pcm_frame_chunks_s16(pLibFlac, pFlac, (pFlac->maxBlockSizeInPCMFrames > 0) ? pFlac->maxBlockSizeInPCMFrames : 4096);
}
return result;
}
static void on_meta(void* pUserData, drflac_metadata* pMetadata)
{
(void)pUserData;
switch (pMetadata->type)
{
case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET:
{
/*
This section is here just to make it easy to test cuesheets. It's not designed to integrate cleanly with the output of this program
so I'm just selectively enabling and disabling this section as required.
*/
#if 0
drflac_cuesheet_track_iterator i;
drflac_cuesheet_track track;
printf("Cuesheet Found. Track Count = %d\n", (int)pMetadata->data.cuesheet.trackCount);
drflac_init_cuesheet_track_iterator(&i, pMetadata->data.cuesheet.trackCount, pMetadata->data.cuesheet.pTrackData);
while (drflac_next_cuesheet_track(&i, &track)) {
drflac_uint32 iTrackIndex;
printf("Cuesheet Track %d. Index Count = %d:\n", track.trackNumber, track.indexCount);
for (iTrackIndex = 0; iTrackIndex < track.indexCount; iTrackIndex += 1) {
printf(" Index %d - Offset %llu\n", iTrackIndex, track.pIndexPoints[iTrackIndex].offset);
}
}
#endif
} break;
}
}
drflac_result decode_test_file(const char* pFilePath)
{
/* To test seeking we just seek to our target PCM frame and then decode whatever is remaining and compare it against libFLAC. */
drflac_result result;
libflac libflac;
drflac* pFlac;
dr_printf_fixed_with_margin(FILE_NAME_WIDTH, TABLE_MARGIN, "%s", dr_path_file_name(pFilePath));
/* First load the decoder from libFLAC. */
result = libflac_init_file(pFilePath, &libflac);
if (result != DRFLAC_SUCCESS) {
printf(" Failed to open via libFLAC.");
return result;
}
/* Now load from dr_flac. */
pFlac = drflac_open_file_with_metadata(pFilePath, on_meta, NULL, NULL);
if (pFlac == NULL) {
printf(" Failed to open via dr_flac.");
libflac_uninit(&libflac);
return DRFLAC_ERROR; /* Failed to load dr_flac decoder. */
}
/* At this point we should have both libFLAC and dr_flac decoders open. We can now perform identical operations on each of them and compare. */
result = decode_test_file_s32(&libflac, pFlac);
if (result != DRFLAC_SUCCESS) {
drflac_close(pFlac);
libflac_uninit(&libflac);
return result;
}
result = decode_test_file_f32(&libflac, pFlac);
if (result != DRFLAC_SUCCESS) {
drflac_close(pFlac);
libflac_uninit(&libflac);
return result;
}
result = decode_test_file_s16(&libflac, pFlac);
if (result != DRFLAC_SUCCESS) {
drflac_close(pFlac);
libflac_uninit(&libflac);
return result;
}
/* We're done with our decoders. */
drflac_close(pFlac);
libflac_uninit(&libflac);
if (result == DRFLAC_SUCCESS) {
printf(" Passed");
}
return result;
}
drflac_result decode_test_directory(const char* pDirectoryPath)
{
dr_file_iterator iteratorState;
dr_file_iterator* pFile;
dr_printf_fixed(FILE_NAME_WIDTH, "%s", pDirectoryPath);
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "RESULT");
printf("\n");
pFile = dr_file_iterator_begin(pDirectoryPath, &iteratorState);
while (pFile != NULL) {
drflac_result result;
/* Skip directories for now, but we may want to look at doing recursive file iteration. */
if (!pFile->isDirectory) {
result = decode_test_file(pFile->absolutePath);
(void)result;
printf("\n");
}
pFile = dr_file_iterator_next(pFile);
}
return DRFLAC_SUCCESS;
}
drflac_result decode_test()
{
drflac_result result = DRFLAC_SUCCESS;
/* Directories. */
{
result = decode_test_directory(DEFAULT_SOURCE_DIR);
(void)result;
}
return result;
}
drflac_result open_and_read_test_file_s32(libflac* pLibFlac, const char* pFilePath)
{
drflac_int32* pPCMFrames;
drflac_uint64 pcmFrameCount;
drflac_uint32 channels;
drflac_uint32 sampleRate;
drflac_uint64 iPCMFrame;
pPCMFrames = drflac_open_file_and_read_pcm_frames_s32(pFilePath, &channels, &sampleRate, &pcmFrameCount, NULL);
if (pPCMFrames == NULL) {
printf(" drflac_open_and_read failed.");
return DRFLAC_ERROR; /* Error decoding */
}
if (pcmFrameCount != pLibFlac->pcmFrameCount) {
printf(" Decoded frame counts differ: pcmFrameCount=%d, libFLAC=%d, dr_flac=%d", (int)pcmFrameCount, (int)pLibFlac->currentPCMFrame, (int)pcmFrameCount);
drflac_free(pPCMFrames, NULL);
return DRFLAC_ERROR;
}
for (iPCMFrame = 0; iPCMFrame < pLibFlac->pcmFrameCount; iPCMFrame += 1) {
drflac_int32* pPCMFrame_libflac = pLibFlac->pPCMFrames + (iPCMFrame * pLibFlac->channels);
drflac_int32* pPCMFrame_drflac = pPCMFrames + (iPCMFrame * pLibFlac->channels);
drflac_uint32 iChannel;
drflac_bool32 hasError = DRFLAC_FALSE;
for (iChannel = 0; iChannel < pLibFlac->channels; iChannel += 1) {
if (pPCMFrame_libflac[iChannel] != pPCMFrame_drflac[iChannel]) {
printf(" PCM Frame @ %d[%d] does not match: pcmFrameCount=%d", (int)iPCMFrame, iChannel, (int)pcmFrameCount);
hasError = DRFLAC_TRUE;
break;
}
}
if (hasError) {
drflac_free(pPCMFrames, NULL);
return DRFLAC_ERROR; /* Decoded frames do not match. */
}
}
drflac_free(pPCMFrames, NULL);
return DRFLAC_SUCCESS;
}
drflac_result open_and_read_test_file_f32(libflac* pLibFlac, const char* pFilePath)
{
float* pPCMFrames;
drflac_uint64 pcmFrameCount;
drflac_uint32 channels;
drflac_uint32 sampleRate;
drflac_uint64 iPCMFrame;
pPCMFrames = drflac_open_file_and_read_pcm_frames_f32(pFilePath, &channels, &sampleRate, &pcmFrameCount, NULL);
if (pPCMFrames == NULL) {
printf(" drflac_open_and_read failed.");
return DRFLAC_ERROR; /* Error decoding */
}
if (pcmFrameCount != pLibFlac->pcmFrameCount) {
printf(" Decoded frame counts differ: pcmFrameCount=%d, libFLAC=%d, dr_flac=%d", (int)pcmFrameCount, (int)pLibFlac->currentPCMFrame, (int)pcmFrameCount);
drflac_free(pPCMFrames, NULL);
return DRFLAC_ERROR;
}
for (iPCMFrame = 0; iPCMFrame < pLibFlac->pcmFrameCount; iPCMFrame += 1) {
drflac_int32* pPCMFrame_libflac = pLibFlac->pPCMFrames + (iPCMFrame * pLibFlac->channels);
float* pPCMFrame_drflac = pPCMFrames + (iPCMFrame * pLibFlac->channels);
drflac_uint32 iChannel;
drflac_bool32 hasError = DRFLAC_FALSE;
for (iChannel = 0; iChannel < pLibFlac->channels; iChannel += 1) {
if ((pPCMFrame_libflac[iChannel] / 2147483648.0) != pPCMFrame_drflac[iChannel]) {
printf(" PCM Frame @ %d[%d] does not match: pcmFrameCount=%d", (int)iPCMFrame, iChannel, (int)pcmFrameCount);
hasError = DRFLAC_TRUE;
break;
}
}
if (hasError) {
drflac_free(pPCMFrames, NULL);
return DRFLAC_ERROR; /* Decoded frames do not match. */
}
}
drflac_free(pPCMFrames, NULL);
return DRFLAC_SUCCESS;
}
drflac_result open_and_read_test_file_s16(libflac* pLibFlac, const char* pFilePath)
{
drflac_int16* pPCMFrames;
drflac_uint64 pcmFrameCount;
drflac_uint32 channels;
drflac_uint32 sampleRate;
drflac_uint64 iPCMFrame;
pPCMFrames = drflac_open_file_and_read_pcm_frames_s16(pFilePath, &channels, &sampleRate, &pcmFrameCount, NULL);
if (pPCMFrames == NULL) {
printf(" drflac_open_and_read failed.");
return DRFLAC_ERROR; /* Error decoding */
}
if (pcmFrameCount != pLibFlac->pcmFrameCount) {
printf(" Decoded frame counts differ: pcmFrameCount=%d, libFLAC=%d, dr_flac=%d", (int)pcmFrameCount, (int)pLibFlac->currentPCMFrame, (int)pcmFrameCount);
drflac_free(pPCMFrames, NULL);
return DRFLAC_ERROR;
}
for (iPCMFrame = 0; iPCMFrame < pLibFlac->pcmFrameCount; iPCMFrame += 1) {
drflac_int32* pPCMFrame_libflac = pLibFlac->pPCMFrames + (iPCMFrame * pLibFlac->channels);
drflac_int16* pPCMFrame_drflac = pPCMFrames + (iPCMFrame * pLibFlac->channels);
drflac_uint32 iChannel;
drflac_bool32 hasError = DRFLAC_FALSE;
for (iChannel = 0; iChannel < pLibFlac->channels; iChannel += 1) {
if ((pPCMFrame_libflac[iChannel] >> 16) != pPCMFrame_drflac[iChannel]) {
printf(" PCM Frame @ %d[%d] does not match: pcmFrameCount=%d", (int)iPCMFrame, iChannel, (int)pcmFrameCount);
hasError = DRFLAC_TRUE;
break;
}
}
if (hasError) {
drflac_free(pPCMFrames, NULL);
return DRFLAC_ERROR; /* Decoded frames do not match. */
}
}
drflac_free(pPCMFrames, NULL);
return DRFLAC_SUCCESS;
}
drflac_result open_and_read_test_file(const char* pFilePath)
{
drflac_result result;
libflac libflac;
dr_printf_fixed_with_margin(FILE_NAME_WIDTH, TABLE_MARGIN, "%s", dr_path_file_name(pFilePath));
/* First load the decoder from libFLAC. */
result = libflac_init_file(pFilePath, &libflac);
if (result != DRFLAC_SUCCESS) {
printf(" Failed to open via libFLAC.");
return result;
}
result = open_and_read_test_file_s32(&libflac, pFilePath);
if (result != DRFLAC_SUCCESS) {
return result;
}
open_and_read_test_file_f32(&libflac, pFilePath);
if (result != DRFLAC_SUCCESS) {
return result;
}
open_and_read_test_file_s16(&libflac, pFilePath);
if (result != DRFLAC_SUCCESS) {
return result;
}
libflac_uninit(&libflac);
if (result == DRFLAC_SUCCESS) {
printf(" Passed");
}
return result;
}
drflac_result open_and_read_test_directory(const char* pDirectoryPath)
{
dr_file_iterator iteratorState;
dr_file_iterator* pFile;
dr_printf_fixed(FILE_NAME_WIDTH, "%s", pDirectoryPath);
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "RESULT");
printf("\n");
pFile = dr_file_iterator_begin(pDirectoryPath, &iteratorState);
while (pFile != NULL) {
drflac_result result;
/* Skip directories for now, but we may want to look at doing recursive file iteration. */
if (!pFile->isDirectory) {
result = open_and_read_test_file(pFile->absolutePath);
(void)result;
printf("\n");
}
pFile = dr_file_iterator_next(pFile);
}
return DRFLAC_SUCCESS;
}
drflac_result open_and_read_test()
{
drflac_result result = DRFLAC_SUCCESS;
/* Directories. */
{
result = open_and_read_test_directory(DEFAULT_SOURCE_DIR);
(void)result;
}
return result;
}
drflac_result decode_profiling_file(const char* pFilePath)
{
drflac_result result;
libflac libflac;
drflac* pFlac;
drflac_int32* pTempBuffer;
double decodeTimeBeg;
double decodeTimeEnd;
double drflacDecodeTimeInSeconds;
void* pFileData;
size_t fileSizeInBytes;
dr_printf_fixed_with_margin(FILE_NAME_WIDTH, 2, "%s", dr_path_file_name(pFilePath));
/* libFLAC */
result = libflac_init_file(pFilePath, &libflac);
if (result != DRFLAC_SUCCESS) {
printf(" [libFLAC] Failed to load file");
return result;
}
/* dr_flac */
pFileData = dr_open_and_read_file(pFilePath, &fileSizeInBytes);
if (pFileData == NULL) {
printf(" Failed to load file");
return DRFLAC_ERROR; /* Failed to open the file. */
}
pFlac = drflac_open_memory(pFileData, fileSizeInBytes, NULL);
if (pFlac == NULL) {
free(pFileData);
printf(" [dr_flac] Failed to load file.");
return DRFLAC_ERROR;
}
/* libFLAC decode time. */
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "%.2fms", libflac.decodeTimeInSeconds*1000);
/* dr_flac decode time. */
pTempBuffer = (drflac_int32*)malloc((size_t)(libflac.pcmFrameCount * libflac.channels * sizeof(drflac_int32)));
if (pTempBuffer == NULL) {
libflac_uninit(&libflac);
drflac_close(pFlac);
free(pFileData);
printf(" Out of memory.");
return DRFLAC_ERROR; /* Out of memory. */
}
DRFLAC_ZERO_MEMORY(pTempBuffer, (size_t)(libflac.pcmFrameCount * libflac.channels * sizeof(drflac_int32)));
decodeTimeBeg = dr_timer_now();
drflac_read_pcm_frames_s32(pFlac, libflac.pcmFrameCount, pTempBuffer);
decodeTimeEnd = dr_timer_now();
free(pTempBuffer);
free(pFileData);
drflacDecodeTimeInSeconds = decodeTimeEnd - decodeTimeBeg;
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "%.2fms", drflacDecodeTimeInSeconds*1000);
/* Difference. */
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "%d%%", (int)(drflacDecodeTimeInSeconds/libflac.decodeTimeInSeconds * 100));
libflac_uninit(&libflac);
drflac_close(pFlac);
return DRFLAC_SUCCESS;
}
drflac_result decode_profiling_directory(const char* pDirectoryPath)
{
dr_file_iterator iteratorState;
dr_file_iterator* pFile;
drflac_bool32 foundError = DRFLAC_FALSE;
dr_printf_fixed(FILE_NAME_WIDTH, "%s", pDirectoryPath);
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "libFLAC");
dr_printf_fixed_with_margin(NUMBER_WIDTH, TABLE_MARGIN, "dr_flac");
printf("\n");
pFile = dr_file_iterator_begin(pDirectoryPath, &iteratorState);
while (pFile != NULL) {
drflac_result result;
/* Skip directories for now, but we may want to look at doing recursive file iteration. */
if (!pFile->isDirectory) {
result = decode_profiling_file(pFile->absolutePath);
if (result != DRFLAC_SUCCESS) {
foundError = DRFLAC_TRUE;
}
printf("\n");
}
pFile = dr_file_iterator_next(pFile);
}
return (foundError) ? DRFLAC_ERROR : DRFLAC_SUCCESS;
}
drflac_result decode_profiling()
{
drflac_result result = DRFLAC_SUCCESS;
/* Directories. */
{
result = decode_profiling_directory(DEFAULT_SOURCE_DIR);
}
return result;
}
int main(int argc, char** argv)
{
drflac_result result = DRFLAC_SUCCESS;
drflac_bool32 doTesting = DRFLAC_TRUE;
drflac_bool32 doProfiling = DRFLAC_TRUE;
/* This program has two main parts. The first is just a normal functionality test. The second is a profiling of the different seeking methods. */
if (dr_argv_is_set(argc, argv, "--onlyprofile")) {
doTesting = DRFLAC_FALSE;
}
print_cpu_caps();
/* Exhaustive seek test. */
if (doTesting) {
printf("=======================================================================\n");
printf("DECODE TESTING\n");
printf("=======================================================================\n");
result = decode_test();
if (result != DRFLAC_SUCCESS) {
return (int)result; /* Don't continue if an error occurs during testing. */
}
printf("\n");
printf("=======================================================================\n");
printf("OPEN-AND-READ TESTING - drflac_open_*_and_read_pcm_frames_*()\n");
printf("=======================================================================\n");
result = open_and_read_test();
if (result != DRFLAC_SUCCESS) {
return (int)result; /* Don't continue if an error occurs during testing. */
}
printf("\n");
} else {
printf("=======================================================================\n");
printf("WARNING: Correctness Tests Disabled\n");
printf("=======================================================================\n");
}
/* Profiling. */
if (doProfiling) {
printf("=======================================================================\n");
printf("DECODE PROFILING (LOWER IS BETTER)\n");
printf("=======================================================================\n");
result = decode_profiling();
printf("\n");
}
/*getchar();*/
return (int)result;
}