mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2025-12-16 11:14:39 +00:00
Add FLAC.
This commit is contained in:
172
3rdparty/flac.cmake
vendored
Normal file
172
3rdparty/flac.cmake
vendored
Normal 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}")
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
33
include/aaruformat/flac.h
Normal 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
279
src/flac.c
Normal 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;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
53
tests/crc32.c
Normal 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
31
tests/crc32.h
Normal 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
BIN
tests/data/audio.bin
Normal file
Binary file not shown.
BIN
tests/data/flac.flac
Normal file
BIN
tests/data/flac.flac
Normal file
Binary file not shown.
145
tests/flac.cpp
Normal file
145
tests/flac.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user