diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2025-01-25 22:04:33 +0000 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2025-01-25 22:04:33 +0000 |
commit | 7733e7f22330dacb315c0df003446fbe9c22d6ba (patch) | |
tree | afb0d60b4b46b3e85c40cd6d14a73c1ca97e80bb /src | |
parent | 01dfec3a4c5916a819d80743bab201a4a7ec12f3 (diff) | |
download | atracdenc-7733e7f22330dacb315c0df003446fbe9c22d6ba.tar.gz |
[AT3P] MDCT code
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_mdct.cpp | 104 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_mdct.h | 50 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_mdct_ut.cpp | 106 |
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); + } + } +} |