Add FLAC.

This commit is contained in:
2022-05-28 13:38:09 +01:00
parent 0d6e731cf0
commit db5b14a56c
13 changed files with 766 additions and 22 deletions

172
3rdparty/flac.cmake vendored Normal file
View File

@@ -0,0 +1,172 @@
# 3.1 is OK for most parts. However:
# 3.3 is needed in src/libFLAC
# 3.5 is needed in src/libFLAC/ia32
# 3.9 is needed in 'doc' because of doxygen_add_docs()
#cmake_minimum_required(VERSION 3.5)
#if(NOT (CMAKE_BUILD_TYPE OR CMAKE_CONFIGURATION_TYPES OR DEFINED ENV{CFLAGS} OR DEFINED ENV{CXXFLAGS}))
# set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo")
#endif()
set(FLAC_VERSION 1.3.3) # HOMEPAGE_URL "https://www.xiph.org/flac/")
message(STATUS "FLAC VERSION: ${FLAC_VERSION}")
set(BUILD_SHARED_LIBS BOOL OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/flac/cmake")
set(VERSION ${FLAC_VERSION})
set(OLD_PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}")
set(PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/3rdparty/flac/")
#find_package(Iconv)
#set(HAVE_ICONV ${Iconv_FOUND})
#if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
# set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -funroll-loops")
#endif()
include(CMakePackageConfigHelpers)
include(CPack)
include(CTest)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckCSourceCompiles)
include(CheckCXXSourceCompiles)
include(UseSystemExtensions)
include(TestBigEndian)
check_include_file("byteswap.h" HAVE_BYTESWAP_H)
check_include_file("inttypes.h" HAVE_INTTYPES_H)
check_include_file("stdint.h" HAVE_STDINT_H)
if(MSVC)
check_include_file("intrin.h" FLAC__HAS_X86INTRIN)
else()
check_include_file("x86intrin.h" FLAC__HAS_X86INTRIN)
endif()
#check_function_exists(fseeko HAVE_FSEEKO)
check_c_source_compiles("int main() { return __builtin_bswap16 (0) ; }" HAVE_BSWAP16)
check_c_source_compiles("int main() { return __builtin_bswap32 (0) ; }" HAVE_BSWAP32)
if(NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW" OR (NOT ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm" AND NOT ${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64"))
test_big_endian(CPU_IS_BIG_ENDIAN)
endif()
check_c_compiler_flag(-mstackrealign HAVE_STACKREALIGN_FLAG)
include_directories("3rdparty/flac/include")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/3rdparty/flac")
add_definitions(-DHAVE_CONFIG_H)
if(MSVC)
add_definitions(
-D_CRT_SECURE_NO_WARNINGS
-D_USE_MATH_DEFINES)
endif()
option(WITH_ASM "Use any assembly optimization routines" ON)
check_include_file("cpuid.h" HAVE_CPUID_H)
check_include_file("sys/param.h" HAVE_SYS_PARAM_H)
set(CMAKE_REQUIRED_LIBRARIES m)
check_function_exists(lround HAVE_LROUND)
include(CheckCSourceCompiles)
include(CheckCPUArch)
check_cpu_arch_x64(FLAC__CPU_X86_64)
if(NOT FLAC__CPU_X86_64)
check_cpu_arch_x86(FLAC__CPU_IA32)
endif()
if(FLAC__CPU_X86_64 OR FLAC__CPU_IA32)
set(FLAC__ALIGN_MALLOC_DATA 1)
option(WITH_AVX "Enable AVX, AVX2 optimizations" ON)
endif()
include(CheckLanguage)
check_language(ASM_NASM)
if(CMAKE_ASM_NASM_COMPILER)
enable_language(ASM_NASM)
add_definitions(-DFLAC__HAS_NASM)
endif()
if(NOT WITH_ASM)
add_definitions(-DFLAC__NO_ASM)
endif()
if(FLAC__CPU_IA32)
if(WITH_ASM AND CMAKE_ASM_NASM_COMPILER)
add_subdirectory(ia32)
endif()
option(WITH_SSE "Enable SSE2 optimizations" ON)
check_c_compiler_flag(-msse2 HAVE_MSSE2_FLAG)
if(WITH_SSE)
add_compile_options(
$<$<BOOL:${HAVE_MSSE2_FLAG}>:-msse2>
$<$<BOOL:${MSVC}>:/arch:SSE2>)
endif()
endif()
include_directories("3rdparty/flac/src/libFLAC/include")
target_sources(aaruformat PRIVATE
3rdparty/flac/src/libFLAC/bitmath.c
3rdparty/flac/src/libFLAC/bitreader.c
3rdparty/flac/src/libFLAC/bitwriter.c
3rdparty/flac/src/libFLAC/cpu.c
3rdparty/flac/src/libFLAC/crc.c
3rdparty/flac/src/libFLAC/fixed.c
3rdparty/flac/src/libFLAC/fixed_intrin_sse2.c
3rdparty/flac/src/libFLAC/fixed_intrin_ssse3.c
3rdparty/flac/src/libFLAC/float.c
3rdparty/flac/src/libFLAC/format.c
3rdparty/flac/src/libFLAC/lpc.c
3rdparty/flac/src/libFLAC/lpc_intrin_sse.c
3rdparty/flac/src/libFLAC/lpc_intrin_sse2.c
3rdparty/flac/src/libFLAC/lpc_intrin_sse41.c
3rdparty/flac/src/libFLAC/lpc_intrin_avx2.c
3rdparty/flac/src/libFLAC/lpc_intrin_vsx.c
3rdparty/flac/src/libFLAC/md5.c
3rdparty/flac/src/libFLAC/memory.c
3rdparty/flac/src/libFLAC/metadata_iterators.c
3rdparty/flac/src/libFLAC/metadata_object.c
3rdparty/flac/src/libFLAC/stream_decoder.c
3rdparty/flac/src/libFLAC/stream_encoder.c
3rdparty/flac/src/libFLAC/stream_encoder_intrin_sse2.c
3rdparty/flac/src/libFLAC/stream_encoder_intrin_ssse3.c
3rdparty/flac/src/libFLAC/stream_encoder_intrin_avx2.c
3rdparty/flac/src/libFLAC/stream_encoder_framing.c
3rdparty/flac/src/libFLAC/window.c
$<$<BOOL:${WIN32}>:3rdparty/flac/include/share/windows_unicode_filenames.h>
$<$<BOOL:${WIN32}>:3rdparty/flac/src/libFLAC/windows_unicode_filenames.c>
$<$<BOOL:${OGG_FOUND}>:ogg_decoder_aspect.c>
$<$<BOOL:${OGG_FOUND}>:ogg_encoder_aspect.c>
$<$<BOOL:${OGG_FOUND}>:ogg_helper.c>
$<$<BOOL:${OGG_FOUND}>:ogg_mapping.c>)
target_compile_definitions(aaruformat PUBLIC FLAC__NO_DLL)
target_compile_definitions(aaruformat PUBLIC FLAC__NO_FILEIO)
# Disable fortify source when not-release or when cross-building with MingW for WoA
if(CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo OR "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW")
set(DODEFINE_FORTIFY_SOURCE 0)
endif()
set_property(TARGET aaruformat PROPERTY C_VISIBILITY_PRESET hidden)
if(ARCHITECTURE_IS_64BIT)
set(ENABLE_64_BIT_WORDS 1)
endif()
configure_file(3rdparty/flac/config.cmake.h.in 3rdparty/flac/config.h)
set(PROJECT_SOURCE_DIR "${OLD_PROJECT_SOURCE_DIR}")

View File

@@ -96,10 +96,12 @@ endif()
add_library(aaruformat SHARED include/aaruformat/consts.h include/aaruformat/enums.h include/aaru.h include/aaruformat.h
include/aaruformat/decls.h include/aaruformat/structs.h src/identify.c src/open.c include/aaruformat/context.h
src/close.c include/aaruformat/errors.h src/read.c include/aaruformat/crc64.h src/cst.c src/ecc_cd.c src/helpers.c
src/simd.c include/aaruformat/simd.h src/crc64/crc64.c src/crc64/crc64_clmul.c src/crc64/crc64_vmull.c src/crc64/arm_vmull.c src/crc64/arm_vmull.h src/spamsum.c include/aaruformat/spamsum.h)
src/simd.c include/aaruformat/simd.h src/crc64/crc64.c src/crc64/crc64_clmul.c src/crc64/crc64_vmull.c src/crc64/arm_vmull.c src/crc64/arm_vmull.h src/spamsum.c include/aaruformat/spamsum.h include/aaruformat/flac.h src/flac.c)
include_directories(include include/aaruformat)
include(3rdparty/flac.cmake)
MACRO(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target)
if("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC")
FOREACH(arg IN LISTS ARGN)

View File

@@ -16,7 +16,7 @@ Things still to be implemented that are already in the C# version:
- Writing
- Hashing while writing (requires MD5, SHA1 and SHA256)
- Deduplication (requires SHA256)
- Compression (requires FLAC and LZMA)
- Compression (requires LZMA)
Things to be implemented not in the C# version:
- Compile for Dreamcast (KallistiOS preferibly)

View File

@@ -142,6 +142,28 @@ AARU_LOCAL void roll_hash(spamsum_ctx* ctx, uint8_t c);
AARU_LOCAL void fuzzy_try_reduce_blockhash(spamsum_ctx* ctx);
AARU_LOCAL void fuzzy_try_fork_blockhash(spamsum_ctx* ctx);
AARU_EXPORT size_t AARU_CALL aaruf_flac_decode_redbook_buffer(uint8_t* dst_buffer,
size_t dst_size,
const uint8_t* src_buffer,
size_t src_size);
AARU_EXPORT size_t AARU_CALL aaruf_flac_encode_redbook_buffer(uint8_t* dst_buffer,
size_t dst_size,
const uint8_t* src_buffer,
size_t src_size,
uint32_t blocksize,
int32_t do_mid_side_stereo,
int32_t loose_mid_side_stereo,
const char* apodization,
uint32_t max_lpc_order,
uint32_t qlp_coeff_precision,
int32_t do_qlp_coeff_prec_search,
int32_t do_exhaustive_model_search,
uint32_t min_residual_partition_order,
uint32_t max_residual_partition_order,
const char* application_id,
uint32_t application_id_len);
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)

33
include/aaruformat/flac.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 Natalia Portillo.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBAARUFORMAT_FLAC_H
#define LIBAARUFORMAT_FLAC_H
typedef struct
{
const uint8_t* src_buffer;
size_t src_len;
size_t src_pos;
uint8_t* dst_buffer;
size_t dst_len;
size_t dst_pos;
uint8_t error;
} aaru_flac_ctx;
#endif // LIBAARUFORMAT_FLAC_H

279
src/flac.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 Natalia Portillo.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <aaruformat.h>
#include "../3rdparty/flac/include/FLAC/metadata.h"
#include "../3rdparty/flac/include/FLAC/stream_decoder.h"
#include "../3rdparty/flac/include/FLAC/stream_encoder.h"
#include "flac.h"
static FLAC__StreamDecoderReadStatus
read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder,
const FLAC__Frame* frame,
const FLAC__int32* const buffer[],
void* client_data);
static void
error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data);
AARU_EXPORT size_t AARU_CALL aaruf_flac_decode_redbook_buffer(uint8_t* dst_buffer,
size_t dst_size,
const uint8_t* src_buffer,
size_t src_size)
{
FLAC__StreamDecoder* decoder;
FLAC__StreamDecoderInitStatus init_status;
aaru_flac_ctx* ctx = (aaru_flac_ctx*)malloc(sizeof(aaru_flac_ctx));
size_t ret_size;
memset(ctx, 0, sizeof(aaru_flac_ctx));
ctx->src_buffer = src_buffer;
ctx->src_len = src_size;
ctx->src_pos = 0;
ctx->dst_buffer = dst_buffer;
ctx->dst_len = dst_size;
ctx->dst_pos = 0;
ctx->error = 0;
decoder = FLAC__stream_decoder_new();
if(!decoder)
{
free(ctx);
return -1;
}
FLAC__stream_decoder_set_md5_checking(decoder, false);
init_status = FLAC__stream_decoder_init_stream(
decoder, read_callback, NULL, NULL, NULL, NULL, write_callback, NULL, error_callback, ctx);
if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
{
free(ctx);
return -1;
}
// TODO: Return error somehow
FLAC__stream_decoder_process_until_end_of_stream(decoder);
FLAC__stream_decoder_delete(decoder);
ret_size = ctx->dst_pos;
free(ctx);
return ret_size;
}
static FLAC__StreamDecoderReadStatus
read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data)
{
aaru_flac_ctx* ctx = (aaru_flac_ctx*)client_data;
if(ctx->src_len - ctx->src_pos < *bytes) *bytes = ctx->src_len - ctx->src_pos;
if(*bytes == 0) return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
memcpy(buffer, ctx->src_buffer + ctx->src_pos, *bytes);
ctx->src_pos += *bytes;
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder,
const FLAC__Frame* frame,
const FLAC__int32* const buffer[],
void* client_data)
{
aaru_flac_ctx* ctx = (aaru_flac_ctx*)client_data;
size_t i;
uint16_t* buffer16 = (uint16_t*)(ctx->dst_buffer + ctx->dst_pos);
// Why FLAC does not interleave the channels as PCM do, oh the mistery, we could use memcpy instead of looping
for(i = 0; i < frame->header.blocksize && ctx->dst_pos < ctx->dst_len; i++)
{
// Left channel
*(buffer16++) = (FLAC__int16)buffer[0][i];
// Right channel
*(buffer16++) = (FLAC__int16)buffer[1][i];
ctx->dst_pos += 4;
/* TODO: Big-endian (use bswap?)
// Left channel
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)buffer[0][i];
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)buffer[0][i] >> 8;
// Right channel
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)buffer[1][i];
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)buffer[1][i] >> 8;
*/
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
static void error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data)
{
aaru_flac_ctx* ctx = (aaru_flac_ctx*)client_data;
fprintf(stderr, "Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
ctx->error = 1;
}
static FLAC__StreamEncoderWriteStatus encoder_write_callback(const FLAC__StreamEncoder* encoder,
const FLAC__byte buffer[],
size_t bytes,
uint32_t samples,
uint32_t current_frame,
void* client_data);
AARU_EXPORT size_t AARU_CALL aaruf_flac_encode_redbook_buffer(uint8_t* dst_buffer,
size_t dst_size,
const uint8_t* src_buffer,
size_t src_size,
uint32_t blocksize,
int32_t do_mid_side_stereo,
int32_t loose_mid_side_stereo,
const char* apodization,
uint32_t max_lpc_order,
uint32_t qlp_coeff_precision,
int32_t do_qlp_coeff_prec_search,
int32_t do_exhaustive_model_search,
uint32_t min_residual_partition_order,
uint32_t max_residual_partition_order,
const char* application_id,
uint32_t application_id_len)
{
FLAC__StreamEncoder* encoder;
aaru_flac_ctx* ctx = (aaru_flac_ctx*)malloc(sizeof(aaru_flac_ctx));
FLAC__StreamEncoderInitStatus init_status;
size_t ret_size;
FLAC__int32* pcm;
int i;
int16_t* buffer16 = (int16_t*)src_buffer;
FLAC__StreamMetadata* metadata[1];
memset(ctx, 0, sizeof(aaru_flac_ctx));
ctx->src_buffer = src_buffer;
ctx->src_len = src_size;
ctx->src_pos = 0;
ctx->dst_buffer = dst_buffer;
ctx->dst_len = dst_size;
ctx->dst_pos = 0;
ctx->error = 0;
encoder = FLAC__stream_encoder_new();
if(!encoder)
{
free(ctx);
return -1;
}
// TODO: Error detection here
FLAC__stream_encoder_set_verify(encoder, false);
FLAC__stream_encoder_set_streamable_subset(encoder, false);
FLAC__stream_encoder_set_channels(encoder, 2);
FLAC__stream_encoder_set_bits_per_sample(encoder, 16);
FLAC__stream_encoder_set_sample_rate(encoder, 44100);
FLAC__stream_encoder_set_blocksize(encoder, blocksize);
// true compresses more
FLAC__stream_encoder_set_do_mid_side_stereo(encoder, do_mid_side_stereo);
// false compresses more
FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, loose_mid_side_stereo);
// Apodization
FLAC__stream_encoder_set_apodization(encoder, apodization);
FLAC__stream_encoder_set_max_lpc_order(encoder, max_lpc_order);
FLAC__stream_encoder_set_qlp_coeff_precision(encoder, qlp_coeff_precision);
FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, do_qlp_coeff_prec_search);
FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, do_exhaustive_model_search);
FLAC__stream_encoder_set_min_residual_partition_order(encoder, min_residual_partition_order);
FLAC__stream_encoder_set_max_residual_partition_order(encoder, max_residual_partition_order);
FLAC__stream_encoder_set_total_samples_estimate(encoder, src_size / 4);
/* TODO: This is ignored by FLAC, need to replace it
if((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) != NULL)
{
memset(&vorbis_entry, 0, sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
vorbis_entry.entry = (unsigned char *)"Aaru.Compression.Native";
vorbis_entry.length = strlen("Aaru.Compression.Native");
FLAC__metadata_object_vorbiscomment_set_vendor_string(metadata[0], vorbis_entry, true);
}
*/
if(application_id_len > 0 && application_id != NULL)
if((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) != NULL)
FLAC__metadata_object_application_set_data(
metadata[0], (unsigned char*)application_id, application_id_len, true);
FLAC__stream_encoder_set_metadata(encoder, metadata, 1);
init_status = FLAC__stream_encoder_init_stream(encoder, encoder_write_callback, NULL, NULL, NULL, ctx);
if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
{
free(ctx);
return -1;
}
pcm = malloc((src_size / 2) * sizeof(FLAC__int32));
for(i = 0; i < src_size / 2; i++) pcm[i] = (FLAC__int32) * (buffer16++);
FLAC__stream_encoder_process_interleaved(encoder, pcm, src_size / 4);
FLAC__stream_encoder_finish(encoder);
FLAC__stream_encoder_delete(encoder);
ret_size = ctx->dst_pos;
free(ctx);
free(pcm);
FLAC__metadata_object_delete(metadata[0]);
return ret_size;
}
static FLAC__StreamEncoderWriteStatus encoder_write_callback(const FLAC__StreamEncoder* encoder,
const FLAC__byte buffer[],
size_t bytes,
uint32_t samples,
uint32_t current_frame,
void* client_data)
{
aaru_flac_ctx* ctx = (aaru_flac_ctx*)client_data;
if(bytes > ctx->dst_len - ctx->dst_pos) bytes = ctx->dst_len - ctx->dst_pos;
memcpy(ctx->dst_buffer + ctx->dst_pos, buffer, bytes);
ctx->dst_pos += bytes;
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}

View File

@@ -1,23 +1,23 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2021 Natalia Portillo.
* Copyright (C) 2002 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2006 ManTech International Corporation
* Copyright (C) 2013 Helmut Grohne <helmut@subdivi.de>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 Natalia Portillo.
* Copyright (C) 2002 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2006 ManTech International Corporation
* Copyright (C) 2013 Helmut Grohne <helmut@subdivi.de>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdint.h>
@@ -26,6 +26,7 @@
#include <string.h>
#include <aaruformat.h>
#include "spamsum.h"
static uint8_t b64[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,

View File

@@ -8,7 +8,13 @@ include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/random
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/flac.flac
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/audio.bin
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
# 'Google_Tests_run' is the target name
# 'test1.cpp tests2.cpp' are source files with tests
add_executable(tests_run crc64.cpp spamsum.cpp)
add_executable(tests_run crc64.cpp spamsum.cpp crc32.c crc32.h flac.cpp)
target_link_libraries(tests_run gtest gtest_main "aaruformat")

53
tests/crc32.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 Natalia Portillo.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#define CRC32_ISO_POLY 0xEDB88320
#define CRC32_ISO_SEED 0xFFFFFFFF
uint32_t crc32_data(const uint8_t* data, uint32_t len)
{
uint32_t localHashInt = CRC32_ISO_SEED;
uint32_t localTable[256];
int i, j;
for(i = 0; i < 256; i++)
{
uint32_t entry = (uint32_t)i;
for(j = 0; j < 8; j++)
if((entry & 1) == 1) entry = (entry >> 1) ^ CRC32_ISO_POLY;
else
entry >>= 1;
localTable[i] = entry;
}
for(i = 0; i < len; i++) localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)];
localHashInt ^= CRC32_ISO_SEED;
return localHashInt;
}
#ifdef __cplusplus
}
#endif

31
tests/crc32.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 Natalia Portillo.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBAARUFORMAT_TESTS_CRC32_H_
#define LIBAARUFORMAT_TESTS_CRC32_H_
#ifdef __cplusplus
extern "C"
{
#endif
uint32_t crc32_data(const uint8_t* data, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif // LIBAARUFORMAT_TESTS_CRC32_H_

BIN
tests/data/audio.bin Normal file

Binary file not shown.

BIN
tests/data/flac.flac Normal file

Binary file not shown.

145
tests/flac.cpp Normal file
View File

@@ -0,0 +1,145 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 Natalia Portillo.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <climits>
#include <cstddef>
#include <cstdint>
#include <aaruformat.h>
#include "../include/aaruformat/flac.h"
#include "crc32.h"
#include "gtest/gtest.h"
#define EXPECTED_CRC32 0xdfbc99bb
static const uint8_t* buffer;
class flacFixture : public ::testing::Test
{
public:
flacFixture()
{
// initialization;
// can also be done in SetUp()
}
protected:
void SetUp()
{
char path[PATH_MAX];
char filename[PATH_MAX];
getcwd(path, PATH_MAX);
snprintf(filename, PATH_MAX, "%s/data/flac.flac", path);
FILE* file = fopen(filename, "rb");
buffer = (const uint8_t*)malloc(6534197);
fread((void*)buffer, 1, 6534197, file);
fclose(file);
}
void TearDown() { free((void*)buffer); }
~flacFixture()
{
// resources cleanup, no exceptions allowed
}
// shared user data
};
TEST_F(flacFixture, flac)
{
auto* outBuf = (uint8_t*)malloc(9633792);
auto decoded = aaruf_flac_decode_redbook_buffer(outBuf, 9633792, buffer, 6534197);
EXPECT_EQ(decoded, 9633792);
auto crc = crc32_data(outBuf, 9633792);
free(outBuf);
EXPECT_EQ(crc, EXPECTED_CRC32);
}
TEST_F(flacFixture, flacCompress)
{
size_t original_len = 9633792;
uint cmp_len = original_len;
uint decmp_len = original_len;
char path[PATH_MAX];
char filename[PATH_MAX * 2];
FILE* file;
uint32_t original_crc, decmp_crc;
const uint8_t* original;
uint8_t* cmp_buffer;
uint8_t* decmp_buffer;
size_t newSize;
// Allocate buffers
original = (const uint8_t*)malloc(original_len);
cmp_buffer = (uint8_t*)malloc(cmp_len);
decmp_buffer = (uint8_t*)malloc(decmp_len);
// Read the file
getcwd(path, PATH_MAX);
snprintf(filename, PATH_MAX, "%s/data/audio.bin", path);
file = fopen(filename, "rb");
fread((void*)original, 1, original_len, file);
fclose(file);
// Calculate the CRC
original_crc = crc32_data(original, original_len);
// Compress
newSize = aaruf_flac_encode_redbook_buffer(cmp_buffer,
cmp_len,
original,
original_len,
4608,
1,
0,
"partial_tukey(0/1.0/1.0)",
12,
0,
1,
false,
0,
8,
"Aaru.Compression.Native.Tests",
strlen("Aaru.Compression.Native.Tests"));
cmp_len = newSize;
// Decompress
newSize = aaruf_flac_decode_redbook_buffer(decmp_buffer, decmp_len, cmp_buffer, cmp_len);
decmp_len = newSize;
EXPECT_EQ(decmp_len, original_len);
decmp_crc = crc32_data(decmp_buffer, decmp_len);
// Free buffers
free((void*)original);
free(cmp_buffer);
free(decmp_buffer);
EXPECT_EQ(decmp_crc, original_crc);
}