Add FLAC.

This commit is contained in:
2021-10-20 00:44:34 +01:00
parent 81b9fe7704
commit a6fce35a2c
9 changed files with 244 additions and 4 deletions

3
.gitmodules vendored
View File

@@ -7,3 +7,6 @@
[submodule "3rdparty/lzfse"]
path = 3rdparty/lzfse
url = https://github.com/lzfse/lzfse
[submodule "3rdparty/flac"]
path = 3rdparty/flac
url = https://github.com/xiph/flac

View File

@@ -15,4 +15,15 @@ set(ZSTD_MULTITHREAD_SUPPORT OFF) # Not really sure if it works properly
set(ZSTD_LEGACY_SUPPORT ON) # Unsure if may ever be needed, just in case
add_subdirectory(zstd-1.5.0/build/cmake)
include(lzma.cmake)
include(lzma.cmake)
cmake_policy(SET CMP0077 NEW)
set(BUILD_CXXLIBS OFF)
set(BUILD_PROGRAMS OFF)
set(BUILD_EXAMPLES OFF)
set(BUILD_DOCS OFF)
set(INSTALL_MANPAGES OFF)
set(INSTALL_PKGCONFIG_MODULES OFF)
set(INSTALL_CMAKE_CONFIG_MODULE OFF)
set(WITH_OGG OFF)
add_subdirectory(flac)

1
3rdparty/flac vendored Submodule

Submodule 3rdparty/flac added at b358381a10

View File

@@ -36,6 +36,8 @@ message("Detected compiler: ${CMAKE_C_COMPILER_ID}")
message("Detected build type: ${CMAKE_BUILD_TYPE}")
message("Detected platform: ${CMAKE_C_PLATFORM_ID}")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if("${CMAKE_BUILD_TYPE}" MATCHES "Release")
if("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC")
add_compile_options("/O2" "/fp:fast")
@@ -73,7 +75,7 @@ endif()
add_subdirectory(3rdparty)
add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h adc.c adc.h lzip.c lzip.h)
add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h adc.c adc.h lzip.c lzip.h flac.c flac.h)
MACRO(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target)
if("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC")
@@ -94,6 +96,6 @@ MACRO(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target)
ENDIF()
ENDMACRO()
TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE("Aaru.Compression.Native" bz2_static lzlib lzfse libzstd_static lzma)
TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE("Aaru.Compression.Native" bz2_static lzlib lzfse libzstd_static lzma FLAC)
add_subdirectory(tests)

117
flac.c Normal file
View File

@@ -0,0 +1,117 @@
//
// Created by claunia on 20/10/21.
//
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "library.h"
#include "FLAC/stream_decoder.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 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));
FLAC__bool ok = true;
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
ok = 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 bufffer[],
void* client_data)
{
aaru_flac_ctx* ctx = (aaru_flac_ctx*)client_data;
size_t i;
for(i = 0; i < frame->header.blocksize && ctx->dst_pos < ctx->dst_len; i++)
{
// Left channel
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)bufffer[0][i];
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)bufffer[0][i] >> 8;
// Right channel
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)bufffer[1][i];
ctx->dst_buffer[ctx->dst_pos++] = (FLAC__uint16)(FLAC__int16)bufffer[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;
}

24
flac.h Normal file
View File

@@ -0,0 +1,24 @@
//
// Created by claunia on 20/10/21.
//
#ifndef AARU_COMPRESSION_NATIVE__FLAC_H_
#define AARU_COMPRESSION_NATIVE__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;
AARU_EXPORT size_t AARU_CALL flac_decode_redbook_buffer(uint8_t* dst_buffer,
size_t dst_size,
const uint8_t* src_buffer,
size_t src_size);
#endif // AARU_COMPRESSION_NATIVE__FLAC_H_

View File

@@ -30,7 +30,10 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/zstd.zst
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lzma.bin
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/flac.flac
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 apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp)
add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp)
target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native")

BIN
tests/data/flac.flac Normal file

Binary file not shown.

79
tests/flac.cpp Normal file
View File

@@ -0,0 +1,79 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2021 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 <cstdint>
#include <cstddef>
#include "../library.h"
#include "../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 = 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);
}