aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2024-07-08 21:42:48 +0000
committerDaniil Cherednik <dan.cherednik@gmail.com>2024-07-09 23:07:40 +0200
commitc4b19af8391640f143aaf446658354dcf01432d1 (patch)
tree68ebb11f38eaec53e16879e59ce776bd249d8491
parentf8eabde1e1a2fa6bdb2b09dcdee5cecb750beb30 (diff)
downloadatracdenc-c4b19af8391640f143aaf446658354dcf01432d1.tar.gz
Allow to configure atracdenc to use float instead of double
The default is double for hystorical reason. Actually no any reason to use double precision float point calculation for all processing. AT3P encoding will use float except places were we really need double precision. So this default will be changed to float in near future and this option will be removed.
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/atrac/atrac1.cpp4
-rw-r--r--src/atrac/atrac1.h4
-rw-r--r--src/atrac/atrac3plus_pqf/ut/ipqf_ut.cpp4
-rw-r--r--src/atrac/atrac_psy_common.h2
-rw-r--r--src/atrac3denc.cpp2
-rw-r--r--src/atracdenc_ut.cpp20
-rw-r--r--src/config.h11
-rw-r--r--src/lib/mdct/mdct_ut.cpp37
-rw-r--r--src/lib/mdct/mdct_ut_common.h28
-rw-r--r--src/transient_detector.cpp10
-rw-r--r--test/CMakeLists.txt4
13 files changed, 107 insertions, 34 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81d7999..0332f19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
project(atracdenc)
include_directories(src)
+
+option(ATDE_USE_FLOAT "use float32 precision for dsp" OFF)
+
if (UNIX)
find_package(GTest)
if (GTest_FOUND)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dfa923e..b3680d5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -32,6 +32,10 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
enable_cxx_compiler_flag_if_supported("-Wall")
enable_cxx_compiler_flag_if_supported("-Wextra")
+if (ATDE_USE_FLOAT)
+ add_compile_definitions(ATDE_USE_FLOAT)
+endif()
+
if (WIN32)
add_compile_definitions(PLATFORM_WINDOWS)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
@@ -62,7 +66,13 @@ include_directories(
)
set(SOURCE_FFT_LIB lib/fft/kissfft_impl/kiss_fft.c)
-set_source_files_properties(lib/fft/kissfft_impl/kiss_fft.c PROPERTIES COMPILE_FLAGS -Dkiss_fft_scalar=double)
+
+if (ATDE_USE_FLOAT)
+ set_source_files_properties(lib/fft/kissfft_impl/kiss_fft.c PROPERTIES COMPILE_FLAGS -Dkiss_fft_scalar=float)
+else()
+ set_source_files_properties(lib/fft/kissfft_impl/kiss_fft.c PROPERTIES COMPILE_FLAGS -Dkiss_fft_scalar=double)
+endif()
+
set(SOURCE_OMA_LIB lib/liboma/src/liboma.c)
set(SOURCE_BITSTREAM_LIB lib/bitstream/bitstream.cpp)
set(SOURCE_ATRACDENC_IMPL
diff --git a/src/atrac/atrac1.cpp b/src/atrac/atrac1.cpp
index f7e6c61..e128609 100644
--- a/src/atrac/atrac1.cpp
+++ b/src/atrac/atrac1.cpp
@@ -26,8 +26,8 @@ constexpr uint32_t TAtrac1Data::SpecsPerBlock[MaxBfus];
constexpr uint32_t TAtrac1Data::SpecsStartLong[MaxBfus];
constexpr uint32_t TAtrac1Data::SpecsStartShort[MaxBfus];
constexpr uint32_t TAtrac1Data::BfuAmountTab[8];
-double TAtrac1Data::ScaleTable[64] = {0};
-double TAtrac1Data::SineWindow[32] = {0};
+TFloat TAtrac1Data::ScaleTable[64] = {0};
+TFloat TAtrac1Data::SineWindow[32] = {0};
} //namespace NAtrac1
} //namespace NAtracDEnc
diff --git a/src/atrac/atrac1.h b/src/atrac/atrac1.h
index e0d8161..67c869f 100644
--- a/src/atrac/atrac1.h
+++ b/src/atrac/atrac1.h
@@ -78,8 +78,8 @@ protected:
static const uint32_t BitsPerIDWL = 4;
static const uint32_t BitsPerIDSF = 6;
- static double ScaleTable[64];
- static double SineWindow[32];
+ static TFloat ScaleTable[64];
+ static TFloat SineWindow[32];
uint32_t BfuToBand(uint32_t i) {
if (i < 20)
return 0;
diff --git a/src/atrac/atrac3plus_pqf/ut/ipqf_ut.cpp b/src/atrac/atrac3plus_pqf/ut/ipqf_ut.cpp
index ee2d75d..4492cb9 100644
--- a/src/atrac/atrac3plus_pqf/ut/ipqf_ut.cpp
+++ b/src/atrac/atrac3plus_pqf/ut/ipqf_ut.cpp
@@ -233,7 +233,7 @@ TEST(pqf, Chirp_Short) {
ff_atrac3p_ipqf(&sctx, &subbands[0], &tmp[0]);
- const static float err = 1.0 / (float)(1<<22);
+ const static float err = 1.0 / (float)(1<<21);
for (int i = 368; i < 2048; i++) {
EXPECT_NEAR(tmp[i], x[i - 368], err);
@@ -260,7 +260,7 @@ TEST(pqf, Chirp_Long) {
ff_atrac3p_ipqf(&sctx, &subbands[0], &tmp[0]);
ff_atrac3p_ipqf(&sctx, &subbands[2048], &tmp[2048]);
- const static float err = 4096.0 / (float)(1<<22);
+ const static float err = 1.0 / (float)(1<<21);
for (int i = 368; i < 4096; i++) {
EXPECT_NEAR(tmp[i], x[i-368], err);
}
diff --git a/src/atrac/atrac_psy_common.h b/src/atrac/atrac_psy_common.h
index dc1e65e..1a83e74 100644
--- a/src/atrac/atrac_psy_common.h
+++ b/src/atrac/atrac_psy_common.h
@@ -21,6 +21,6 @@
namespace NAtracDEnc {
-double AnalizeScaleFactorSpread(const std::vector<TScaledBlock>& scaledBlocks);
+TFloat AnalizeScaleFactorSpread(const std::vector<TScaledBlock>& scaledBlocks);
} //namespace NAtracDEnc
diff --git a/src/atrac3denc.cpp b/src/atrac3denc.cpp
index e5a0da9..a07c11e 100644
--- a/src/atrac3denc.cpp
+++ b/src/atrac3denc.cpp
@@ -130,7 +130,7 @@ TAtrac3MDCT::TGainModulatorArray TAtrac3MDCT::MakeGainModulatorArray(const TAtra
TFloat TAtrac3Encoder::LimitRel(TFloat x)
{
- return std::min(std::max(x, GainLevel[15]), GainLevel[0]);
+ return std::min(std::max((double)x, GainLevel[15]), GainLevel[0]);
}
void TAtrac3Encoder::ResetTransientParamsHistory(int channel, int band)
diff --git a/src/atracdenc_ut.cpp b/src/atracdenc_ut.cpp
index 9b7b331..efcd3df 100644
--- a/src/atracdenc_ut.cpp
+++ b/src/atracdenc_ut.cpp
@@ -17,6 +17,7 @@
*/
#include "atrac1denc.h"
+#include <lib/mdct/mdct_ut_common.h>
#include <gtest/gtest.h>
#include <vector>
@@ -24,13 +25,28 @@ using std::vector;
using namespace NAtracDEnc;
void CheckResult128(const vector<TFloat>& a, const vector<TFloat>& b) {
+ float m = 0.0;
+ for (int i = 0; i < a.size(); i++) {
+ m = fmax(m, (float)a[i]);
+ }
+
+ auto eps = CalcEps(m);
+
for (int i = 0; i < 96; ++i ) {
- EXPECT_NEAR(a[i], 4 * b[i+32], 0.0000001);
+ EXPECT_NEAR(a[i], 4 * b[i+32], eps);
}
}
+
void CheckResult256(const vector<TFloat>& a, const vector<TFloat>& b) {
+ float m = 0.0;
+ for (int i = 0; i < a.size(); i++) {
+ m = fmax(m, (float)a[i]);
+ }
+
+ auto eps = CalcEps(m);
+
for (int i = 0; i < 192; ++i ) {
- EXPECT_NEAR(a[i], 2 * b[i+32], 0.0000001);
+ EXPECT_NEAR(a[i], 2 * b[i+32], eps);
}
}
diff --git a/src/config.h b/src/config.h
index ed5a149..d3635df 100644
--- a/src/config.h
+++ b/src/config.h
@@ -18,21 +18,18 @@
#pragma once
-#define CONFIG_DOUBLE
-
#ifndef NOMINMAX
#define NOMINMAX
#endif
-#ifdef CONFIG_DOUBLE
-# define kiss_fft_scalar double
-typedef double TFloat;
-#else
+#ifdef ATDE_USE_FLOAT
# define kiss_fft_scalar float
typedef float TFloat;
+#else
+# define kiss_fft_scalar double
+typedef double TFloat;
#endif
-
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
diff --git a/src/lib/mdct/mdct_ut.cpp b/src/lib/mdct/mdct_ut.cpp
index 31f6f81..6f49b59 100644
--- a/src/lib/mdct/mdct_ut.cpp
+++ b/src/lib/mdct/mdct_ut.cpp
@@ -17,6 +17,7 @@
*/
#include "mdct.h"
+#include "mdct_ut_common.h"
#include <gtest/gtest.h>
#include <vector>
@@ -35,7 +36,7 @@ static vector<TFloat> mdct(TFloat* x, int N) {
res.push_back(sum);
}
return res;
-}
+}
static vector<TFloat> midct(TFloat* x, int N) {
vector<TFloat> res;
@@ -59,8 +60,9 @@ TEST(TMdctTest, MDCT32) {
const vector<TFloat> res1 = mdct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N);
for (int i = 0; i < res1.size(); i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -74,8 +76,9 @@ TEST(TMdctTest, MDCT64) {
const vector<TFloat> res1 = mdct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N);
for (int i = 0; i < res1.size(); i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -89,8 +92,9 @@ TEST(TMdctTest, MDCT128) {
const vector<TFloat> res1 = mdct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N * 4);
for (int i = 0; i < res1.size(); i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -104,8 +108,9 @@ TEST(TMdctTest, MDCT256) {
const vector<TFloat> res1 = mdct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N * 4);
for (int i = 0; i < res1.size(); i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.00000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -113,14 +118,17 @@ TEST(TMdctTest, MDCT256_RAND) {
const int N = 256;
TMDCT<N> transform(N);
vector<TFloat> src(N);
+ TFloat m = 0.0;
for (int i = 0; i < N; i++) {
src[i] = rand();
+ m = std::max(m, src[i]);
}
const vector<TFloat> res1 = mdct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(m * 8);
for (int i = 0; i < res1.size(); i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.01);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -134,8 +142,9 @@ TEST(TMdctTest, MIDCT32) {
const vector<TFloat> res1 = midct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N);
for (int i = 0; i < N; i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -149,8 +158,9 @@ TEST(TMdctTest, MIDCT64) {
const vector<TFloat> res1 = midct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N);
for (int i = 0; i < N; i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -164,8 +174,9 @@ TEST(TMdctTest, MIDCT128) {
const vector<TFloat> res1 = midct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N);
for (int i = 0; i < N; i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.0000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -179,8 +190,9 @@ TEST(TMdctTest, MIDCT256) {
const vector<TFloat> res1 = midct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(N * 2);
for (int i = 0; i < N; i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.000000001);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
@@ -188,13 +200,16 @@ TEST(TMdctTest, MIDCT256_RAND) {
const int N = 256;
TMIDCT<N> transform(N);
vector<TFloat> src(N);
+ TFloat m = 0.0;
for (int i = 0; i < N/2; i++) {
src[i] = rand();
+ m = std::max(m, src[i]);
}
const vector<TFloat> res1 = midct(&src[0], N/2);
const vector<TFloat> res2 = transform(&src[0]);
EXPECT_EQ(res1.size(), res2.size());
+ auto eps = CalcEps(m * 4);
for (int i = 0; i < N; i++) {
- EXPECT_NEAR(res1[i], res2[i], 0.01);
+ EXPECT_NEAR(res1[i], res2[i], eps);
}
}
diff --git a/src/lib/mdct/mdct_ut_common.h b/src/lib/mdct/mdct_ut_common.h
new file mode 100644
index 0000000..5c1096c
--- /dev/null
+++ b/src/lib/mdct/mdct_ut_common.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of AtracDEnc.
+ *
+ * AtracDEnc 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.
+ *
+ * AtracDEnc 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 AtracDEnc; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "mdct.h"
+
+// Calculate value of error for given magnitude
+inline TFloat CalcEps(TFloat magn) {
+ const float snr = (sizeof(TFloat) == 4) ? -114.0 : -240.0;
+ return magn * pow(10, (snr / 20.0));
+}
+
diff --git a/src/transient_detector.cpp b/src/transient_detector.cpp
index 8e4c072..ca96cd4 100644
--- a/src/transient_detector.cpp
+++ b/src/transient_detector.cpp
@@ -51,18 +51,18 @@ void TTransientDetector::HPFilter(const TFloat* in, TFloat* out) {
-3.36639e-17 * 2.0, -0.0438162 * 2.0, -1.54175e-17 * 2.0, 0.0931738 * 2.0,
-5.52212e-17 * 2.0, -0.313819 * 2.0
};
- memcpy(HPFBuffer.data() + PrevBufSz, in, BlockSz * sizeof(double));
- const double* inBuf = HPFBuffer.data();
+ memcpy(HPFBuffer.data() + PrevBufSz, in, BlockSz * sizeof(TFloat));
+ const TFloat* inBuf = HPFBuffer.data();
for (size_t i = 0; i < BlockSz; ++i) {
- double s = inBuf[i + 10];
- double s2 = 0;
+ TFloat s = inBuf[i + 10];
+ TFloat s2 = 0;
for (size_t j = 0; j < ((FIRLen - 1) / 2) - 1 ; j += 2) {
s += fircoef[j] * (inBuf[i + j] + inBuf[i + FIRLen - j]);
s2 += fircoef[j + 1] * (inBuf[i + j + 1] + inBuf[i + FIRLen - j - 1]);
}
out[i] = (s + s2)/2;
}
- memcpy(HPFBuffer.data(), in + (BlockSz - PrevBufSz), PrevBufSz * sizeof(double));
+ memcpy(HPFBuffer.data(), in + (BlockSz - PrevBufSz), PrevBufSz * sizeof(TFloat));
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index c75445e..3818b28 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -3,6 +3,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_C_STANDARD 11)
+if (ATDE_USE_FLOAT)
+ add_compile_definitions(ATDE_USE_FLOAT)
+endif()
+
set(atracdenc_ut
${CMAKE_SOURCE_DIR}/src/lib/mdct/mdct_ut.cpp
${CMAKE_SOURCE_DIR}/src/lib/bitstream/bitstream_ut.cpp