aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2025-01-25 22:04:33 +0000
committerDaniil Cherednik <dan.cherednik@gmail.com>2025-01-25 22:04:33 +0000
commit7733e7f22330dacb315c0df003446fbe9c22d6ba (patch)
treeafb0d60b4b46b3e85c40cd6d14a73c1ca97e80bb /src
parent01dfec3a4c5916a819d80743bab201a4a7ec12f3 (diff)
downloadatracdenc-7733e7f22330dacb315c0df003446fbe9c22d6ba.tar.gz
[AT3P] MDCT code
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/atrac/at3p/at3p_mdct.cpp104
-rw-r--r--src/atrac/at3p/at3p_mdct.h50
-rw-r--r--src/atrac/at3p/at3p_mdct_ut.cpp106
4 files changed, 261 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d40f6e6..ac02187 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -96,6 +96,7 @@ set(SOURCE_ATRACDENC_IMPL
atrac/at3p/at3p.cpp
atrac/at3p/at3p_bitstream.cpp
atrac/at3p/at3p_gha.cpp
+ atrac/at3p/at3p_mdct.cpp
atrac/at3p/at3p_tables.cpp
lib/mdct/mdct.cpp
)
diff --git a/src/atrac/at3p/at3p_mdct.cpp b/src/atrac/at3p/at3p_mdct.cpp
new file mode 100644
index 0000000..b92e87b
--- /dev/null
+++ b/src/atrac/at3p/at3p_mdct.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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
+ */
+
+#include "at3p_mdct.h"
+#include "util.h"
+
+#include <array>
+
+#include <iostream>
+#include <vector>
+
+using std::vector;
+
+namespace NAtracDEnc {
+
+static std::array<float, 128> SineWin;
+
+static void InitSineWin() {
+ if (SineWin[SineWin.size() - 1] == 0.0) {
+ for (size_t i = 0; i < SineWin.size(); i++) {
+ SineWin[i] = 2.0 * sinf((i + 0.5) * (M_PI / (2.0 * SineWin.size())));
+ }
+ }
+}
+
+TAt3pMDCT::TAt3pMDCT()
+{
+ InitSineWin();
+}
+
+void TAt3pMDCT::Do(float specs[2048], const TPcmBandsData& bands, THistBuf& work)
+{
+ for (size_t b = 0; b < 16; b++) {
+ const float* srcBuff = bands[b];
+ float* const curSpec = &specs[b*128];
+
+ std::array<float, 256>& tmp = work[b];
+
+ for (size_t i = 0; i < 128; i++) {
+ tmp[128 + i] = SineWin[127 - i] * srcBuff[i];
+ }
+
+ const vector<float>& sp = Mdct(tmp.data());
+
+ memcpy(curSpec, sp.data(), 128 * sizeof(float));
+
+ if (b & 1) {
+ SwapArray(curSpec, 128);
+ }
+
+ for (size_t i = 0; i < 128; i++) {
+ tmp[i] = SineWin[i] * srcBuff[i];
+ }
+ }
+}
+
+TAt3pMIDCT::TAt3pMIDCT()
+{
+ InitSineWin();
+}
+
+void TAt3pMIDCT::Do(float specs[2048], TPcmBandsData& bands, THistBuf& work)
+{
+ for (size_t b = 0; b < 16; b++) {
+ float* dstBuff = bands[b];
+ float* const curSpec = &specs[b*128];
+
+ std::array<float, 128>& tmp = work[b];
+
+ if (b & 1) {
+ SwapArray(curSpec, 128);
+ }
+
+ vector<float> inv = Midct(curSpec);
+
+ for (int j = 0; j < 128; ++j) {
+ inv[j] *= SineWin[j];
+ inv[255 - j] *= SineWin[j];
+ }
+
+ for (uint32_t j = 0; j < 128; ++j) {
+ dstBuff[j] = inv[j] + tmp[j];
+ }
+
+ memcpy(tmp.data(), &inv[128], sizeof(float)*128);
+ }
+}
+
+};
diff --git a/src/atrac/at3p/at3p_mdct.h b/src/atrac/at3p/at3p_mdct.h
new file mode 100644
index 0000000..de67245
--- /dev/null
+++ b/src/atrac/at3p/at3p_mdct.h
@@ -0,0 +1,50 @@
+/*
+ * 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 <array>
+#include <config.h>
+
+#include "lib/mdct/mdct.h"
+
+namespace NAtracDEnc {
+
+class TAt3pMDCT {
+public:
+ TAt3pMDCT();
+ using THistBuf = std::array<std::array<float, 256>, 16>;
+ using TPcmBandsData = std::array<const float*, 16>;
+
+ void Do(float specs[2048], const TPcmBandsData& bands, THistBuf& work);
+private:
+ NMDCT::TMDCT<256> Mdct;
+};
+
+class TAt3pMIDCT {
+public:
+ TAt3pMIDCT();
+ using THistBuf = std::array<std::array<float, 128>, 16>;
+ using TPcmBandsData = std::array<float*, 16>;
+
+ void Do(float specs[2048], TPcmBandsData& bands, THistBuf& work);
+private:
+ NMDCT::TMIDCT<256> Midct;
+};
+
+}
diff --git a/src/atrac/at3p/at3p_mdct_ut.cpp b/src/atrac/at3p/at3p_mdct_ut.cpp
new file mode 100644
index 0000000..c74eb47
--- /dev/null
+++ b/src/atrac/at3p/at3p_mdct_ut.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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
+ */
+
+#include "at3p_mdct.h"
+#include <gtest/gtest.h>
+
+#include <vector>
+#include <cmath>
+
+using namespace NAtracDEnc;
+
+TEST(TAtpMDCT, ZeroOneBlock) {
+ std::array<float, 2048> specs;
+ static std::array<float, 2048> zero;
+
+ {
+ TAt3pMDCT mdct;
+
+ static TAt3pMDCT::THistBuf buff;
+
+ TAt3pMDCT::TPcmBandsData pcm;
+ for (size_t i = 0; i < pcm.size(); i++) {
+ pcm[i] = &zero[i * 128];
+ }
+
+ mdct.Do(specs.data(), pcm, buff);
+
+ for(auto s: specs)
+ EXPECT_NEAR(s, 0.0, 0.0000000001);
+ }
+
+ {
+ TAt3pMIDCT midct;
+
+ TAt3pMIDCT::TPcmBandsData pcm;
+ static TAt3pMIDCT::THistBuf buff;
+ for (size_t i = 0; i < pcm.size(); i++) {
+ pcm[i] = &zero[i * 128];
+ }
+
+ midct.Do(specs.data(), pcm, buff);
+
+ for(size_t i = 0; i < zero.size(); ++i)
+ EXPECT_NEAR(zero[i], 0.0, 0.0000000001);
+ }
+}
+
+
+TEST(TAtpMDCT, DC) {
+ std::array<float, 4096> specs;
+ std::array<float, 2048> dc;
+
+ for (size_t i = 0; i < dc.size(); i++) {
+ dc[i] = 1.0;
+ }
+
+ {
+ TAt3pMDCT mdct;
+
+ static TAt3pMDCT::THistBuf buff;
+
+ TAt3pMDCT::TPcmBandsData pcm;
+ for (size_t i = 0; i < pcm.size(); i++) {
+ pcm[i] = &dc[i * 128];
+ }
+
+ mdct.Do(specs.data(), pcm, buff);
+ mdct.Do(specs.data() + 2048, pcm, buff);
+ }
+
+ {
+ TAt3pMIDCT midct;
+
+ std::array<float, 2048> result;
+
+ TAt3pMIDCT::TPcmBandsData pcm;
+
+ static TAt3pMIDCT::THistBuf buff;
+
+ for (size_t i = 0; i < pcm.size(); i++) {
+ pcm[i] = &result[i * 128];
+ }
+
+ midct.Do(specs.data(), pcm, buff);
+ midct.Do(specs.data() + 2048, pcm, buff);
+
+ for(size_t i = 0; i < result.size(); ++i) {
+ EXPECT_NEAR(result[i], dc[i], 0.000001);
+ }
+ }
+}