diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2025-06-09 23:19:20 +0200 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2025-06-13 22:49:47 +0200 |
commit | 8b399993d5d6a9b7ef682027c8c15538ab88a156 (patch) | |
tree | aab3fccefd78a66953d96447f2fc8b19bb86e9cf | |
parent | 42aa1bfdd430ac39c8fdb76363d2868238d40853 (diff) | |
download | atracdenc-master.tar.gz |
And pass window shape in to the bitstream.
-rw-r--r-- | src/atrac/at3p/at3p.cpp | 11 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_bitstream.cpp | 25 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_bitstream.h | 10 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_bitstream_impl.h | 11 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_bitstream_ut.cpp | 6 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_mdct.cpp | 82 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_mdct.h | 50 | ||||
-rw-r--r-- | src/atrac/at3p/at3p_mdct_ut.cpp | 30 |
8 files changed, 178 insertions, 47 deletions
diff --git a/src/atrac/at3p/at3p.cpp b/src/atrac/at3p/at3p.cpp index c48c21c..0cdcdd3 100644 --- a/src/atrac/at3p/at3p.cpp +++ b/src/atrac/at3p/at3p.cpp @@ -117,7 +117,8 @@ EncodeFrame(const float* data, int channels) const TAt3PGhaData* tonalBlock = GhaProcessor->DoAnalize({b1Cur, b1Next}, {b2Cur, b2Next}, b1Prev, b2Prev); - std::vector<std::vector<TScaledBlock>> scaledBlocks; + std::vector<TAt3PBitStream::TSingleChannelElement> sces; + sces.resize(channels); for (int ch = 0; ch < channels; ch++) { float* x = (ch == 0) ? b1Prev : b2Prev; auto& c = ChannelCtx[ch]; @@ -137,13 +138,13 @@ EncodeFrame(const float* data, int channels) for (size_t b = 0; b < 16; b++) { p[b] = tmp + b * 128; } - Mdct.Do(c.Specs.data(), p, c.MdctBuf); - const auto& block = Scaler.ScaleFrame(c.Specs, NAt3p::TScaleTable::TBlockSizeMod()); - scaledBlocks.push_back(block); + Mdct.Do(c.Specs.data(), p, c.MdctBuf, sces[ch].SubbandInfo.Win); + + sces[ch].ScaledBlocks = Scaler.ScaleFrame(c.Specs, NAt3p::TScaleTable::TBlockSizeMod()); } - BitStream.WriteFrame(channels, p, scaledBlocks); + BitStream.WriteFrame(channels, p, sces); for (int ch = 0; ch < channels; ch++) { if (Settings.UseGha & TSettings::GHA_PASS_INPUT) { diff --git a/src/atrac/at3p/at3p_bitstream.cpp b/src/atrac/at3p/at3p_bitstream.cpp index 40e860f..2d48729 100644 --- a/src/atrac/at3p/at3p_bitstream.cpp +++ b/src/atrac/at3p/at3p_bitstream.cpp @@ -118,9 +118,9 @@ IBitStreamPartEncoder::EStatus TConfigure::Encode(void* frameData, TBitAllocHand frame->SfIdx.resize(frame->NumQuantUnits); for (size_t i = 0; i < frame->SfIdx.size(); i++) { - frame->SfIdx[i].first = frame->Chs[0].ScaledBlocks.at(i).ScaleFactorIndex; + frame->SfIdx[i].first = frame->Chs[0].Sce.ScaledBlocks.at(i).ScaleFactorIndex; if (frame->Chs.size() > 1) - frame->SfIdx[i].second = frame->Chs[1].ScaledBlocks.at(i).ScaleFactorIndex; + frame->SfIdx[i].second = frame->Chs[1].Sce.ScaledBlocks.at(i).ScaleFactorIndex; } frame->SpecTabIdx.resize(frame->NumQuantUnits); @@ -407,7 +407,7 @@ IBitStreamPartEncoder::EStatus TQuantUnitsEncoder::Encode(void* frameData, TBitA std::vector<std::pair<uint16_t, uint8_t>>> data; for (size_t ch = 0; ch < specFrame->Chs.size(); ch++) { auto& chData = specFrame->Chs.at(ch); - auto scaledBlocks = chData.ScaledBlocks; + auto scaledBlocks = chData.Sce.ScaledBlocks; for (size_t qu = 0; qu < specFrame->NumQuantUnits; qu++) { size_t len = (ch == 0) ? @@ -664,7 +664,20 @@ IBitStreamPartEncoder::EStatus TTonalComponentEncoder::Encode(void* frameData, T } for (size_t ch = 0; ch < chNum; ch++) { - Insert(0, 1); // window shape + TAt3pMDCTWin winType = specFrame->Chs[ch].Sce.SubbandInfo.Win; + uint8_t sbNum = atrac3p_qu_to_subband[specFrame->NumQuantUnits - 1] + 1; + if (winType.IsAllSine()) { + Insert(0, 1); + } else if (winType.IsAllSteep(sbNum)) { + Insert(1, 1); + Insert(0, 1); + } else { + Insert(1, 1); + Insert(1, 1); + for (size_t i = 0; i < sbNum; i++) { + Insert(winType.IsSbSteep(i), 1); + } + } } for (size_t ch = 0; ch < chNum; ch++) { @@ -687,7 +700,7 @@ IBitStreamPartEncoder::EStatus TTonalComponentEncoder::Encode(void* frameData, T return CheckFrameDone(specFrame, ba); } -void TAt3PBitStream::WriteFrame(int channels, const TAt3PGhaData* tonalBlock, const std::vector<std::vector<TScaledBlock>>& scaledBlocks) +void TAt3PBitStream::WriteFrame(int channels, const TAt3PGhaData* tonalBlock, const std::vector<TSingleChannelElement>& sces) { NBitStream::TBitStream bitStream; // First bit must be zero @@ -700,7 +713,7 @@ void TAt3PBitStream::WriteFrame(int channels, const TAt3PGhaData* tonalBlock, co const uint32_t initialNumQuantUnits = 32; - TSpecFrame frame(FrameSzToAllocBits, initialNumQuantUnits, channels, tonalBlock, scaledBlocks); + TSpecFrame frame(FrameSzToAllocBits, initialNumQuantUnits, channels, tonalBlock, sces); Encoder.Do(&frame, bitStream); diff --git a/src/atrac/at3p/at3p_bitstream.h b/src/atrac/at3p/at3p_bitstream.h index 25edd1e..5f3ae46 100644 --- a/src/atrac/at3p/at3p_bitstream.h +++ b/src/atrac/at3p/at3p_bitstream.h @@ -20,6 +20,7 @@ #include "compressed_io.h" #include "at3p_gha.h" +#include "at3p_mdct.h" #include <lib/bs_encode/encode.h> namespace NAtracDEnc { @@ -47,8 +48,15 @@ TTonePackResult CreateFreqBitPack(const TAt3PGhaData::TWaveParam* param, int len class TAt3PBitStream { public: + struct TSubbandInfos { + TAt3pMDCTWin Win; + }; + struct TSingleChannelElement { + TSubbandInfos SubbandInfo; + std::vector<TScaledBlock> ScaledBlocks; + }; TAt3PBitStream(ICompressedOutput* container, uint16_t frameSz); - void WriteFrame(int channels, const TAt3PGhaData* tonalData, const std::vector<std::vector<TScaledBlock>>& scaledBlocks); + void WriteFrame(int channels, const TAt3PGhaData* tonalData, const std::vector<TSingleChannelElement>& scaledBlocks); private: ICompressedOutput* Container; TBitStreamEncoder Encoder; diff --git a/src/atrac/at3p/at3p_bitstream_impl.h b/src/atrac/at3p/at3p_bitstream_impl.h index 32316f2..5e0fded 100644 --- a/src/atrac/at3p/at3p_bitstream_impl.h +++ b/src/atrac/at3p/at3p_bitstream_impl.h @@ -19,6 +19,7 @@ */ #include "atrac/at3p/at3p_gha.h" +#include "at3p_bitstream.h" #include <lib/bitstream/bitstream.h> #include <lib/bs_encode/encode.h> #include <atrac/atrac_scale.h> @@ -33,7 +34,7 @@ struct TVlcElement; struct TSpecFrame { TSpecFrame(uint32_t sz, uint32_t numQuantUnits, size_t channels, const TAt3PGhaData* tonalBlock, - const std::vector<std::vector<TScaledBlock>>& scaledBlocks) + const std::vector<TAt3PBitStream::TSingleChannelElement>& sces) : SizeBits(sz) , NumQuantUnits(numQuantUnits) , TonalBlock(tonalBlock) @@ -41,7 +42,7 @@ struct TSpecFrame { { Chs.reserve(channels); for (size_t i = 0; i < channels; i++) { - Chs.emplace_back(TChannel(scaledBlocks[i])); + Chs.emplace_back(TChannel(sces[i])); } } @@ -53,10 +54,10 @@ struct TSpecFrame { std::vector<std::pair<uint8_t, uint8_t>> SpecTabIdx; struct TChannel { - TChannel(const std::vector<TScaledBlock>& scaledBlock) - : ScaledBlocks(scaledBlock) + TChannel(const TAt3PBitStream::TSingleChannelElement& sce) + : Sce(sce) {} - const std::vector<TScaledBlock>& ScaledBlocks; + const TAt3PBitStream::TSingleChannelElement& Sce; }; std::vector<TChannel> Chs; diff --git a/src/atrac/at3p/at3p_bitstream_ut.cpp b/src/atrac/at3p/at3p_bitstream_ut.cpp index 92feb17..0b70297 100644 --- a/src/atrac/at3p/at3p_bitstream_ut.cpp +++ b/src/atrac/at3p/at3p_bitstream_ut.cpp @@ -125,10 +125,10 @@ TEST(AT3PBitstream, Wordlen) { NBitStream::TBitStream bs; TBitStreamEncoder encoder(std::move(encoders)); - std::vector<std::vector<TScaledBlock>> scaledBlocks; - scaledBlocks.resize(2); + std::vector<TAt3PBitStream::TSingleChannelElement> sce; + sce.resize(2); - TSpecFrame frame(444, 28, 2, nullptr, scaledBlocks); + TSpecFrame frame(444, 28, 2, nullptr, sce); FillFrameData(frame); diff --git a/src/atrac/at3p/at3p_mdct.cpp b/src/atrac/at3p/at3p_mdct.cpp index b92e87b..0836463 100644 --- a/src/atrac/at3p/at3p_mdct.cpp +++ b/src/atrac/at3p/at3p_mdct.cpp @@ -28,12 +28,18 @@ using std::vector; namespace NAtracDEnc { -static std::array<float, 128> SineWin; +static std::array<float, 128> SineWin128; +static std::array<float, 64> SineWin64; 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()))); + if (SineWin128[SineWin128.size() - 1] == 0.0) { + for (size_t i = 0; i < SineWin128.size(); i++) { + SineWin128[i] = 2.0 * sinf((i + 0.5) * (M_PI / (2.0 * SineWin128.size()))); + } + } + if (SineWin64[SineWin64.size() - 1] == 0.0) { + for (size_t i = 0; i < SineWin64.size(); i++) { + SineWin64[i] = 2.0 * sinf((i + 0.5) * (M_PI / (2.0 * SineWin64.size()))); } } } @@ -43,16 +49,26 @@ TAt3pMDCT::TAt3pMDCT() InitSineWin(); } -void TAt3pMDCT::Do(float specs[2048], const TPcmBandsData& bands, THistBuf& work) +void TAt3pMDCT::Do(float specs[2048], const TPcmBandsData& bands, THistBuf& work, TAt3pMDCTWin winType) { - for (size_t b = 0; b < 16; b++) { + for (size_t b = 0, flag = 1; b < 16; b++, flag <<= 1) { 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]; + if (winType.Flags & flag) { + for (size_t i = 0; i < 64; i++) { + tmp[128 + i] = srcBuff[i] * 2.0; + } + for (size_t i = 0; i < 64; i++) { + tmp[160 + i] = SineWin64[63 - i] * srcBuff[32 + i]; + } + memset(&tmp[224], 0, sizeof(float) * 32); + } else { + for (size_t i = 0; i < 128; i++) { + tmp[128 + i] = SineWin128[127 - i] * srcBuff[i]; + } } const vector<float>& sp = Mdct(tmp.data()); @@ -63,8 +79,18 @@ void TAt3pMDCT::Do(float specs[2048], const TPcmBandsData& bands, THistBuf& work SwapArray(curSpec, 128); } - for (size_t i = 0; i < 128; i++) { - tmp[i] = SineWin[i] * srcBuff[i]; + if (winType.Flags & flag) { + memset(&tmp[0], 0, sizeof(float) * 32); + for (size_t i = 0; i < 64; i++) { + tmp[i + 32] = SineWin64[i] * srcBuff[i + 32]; + } + for (size_t i = 0; i < 32; i++) { + tmp[i + 96] = srcBuff[i + 96] * 2.0; + } + } else { + for (size_t i = 0; i < 128; i++) { + tmp[i] = SineWin128[i] * srcBuff[i]; + } } } } @@ -74,13 +100,13 @@ TAt3pMIDCT::TAt3pMIDCT() InitSineWin(); } -void TAt3pMIDCT::Do(float specs[2048], TPcmBandsData& bands, THistBuf& work) +void TAt3pMIDCT::Do(float specs[2048], TPcmBandsData& bands, THistBuf& work, TAt3pMDCTWin winType) { - for (size_t b = 0; b < 16; b++) { + for (size_t b = 0, flag = 1; b < 16; b++, flag <<= 1) { float* dstBuff = bands[b]; float* const curSpec = &specs[b*128]; - std::array<float, 128>& tmp = work[b]; + std::array<float, 128>& tmp = work.Buf[b]; if (b & 1) { SwapArray(curSpec, 128); @@ -88,9 +114,32 @@ void TAt3pMIDCT::Do(float specs[2048], TPcmBandsData& bands, THistBuf& work) vector<float> inv = Midct(curSpec); - for (int j = 0; j < 128; ++j) { - inv[j] *= SineWin[j]; - inv[255 - j] *= SineWin[j]; + if (work.Win.Flags & flag) { + memset(&inv[0], 0, sizeof(float) * 32); + for (size_t j = 0; j < 64; ++j) { + inv[j + 32] *= SineWin64[j]; + } + for (size_t j = 96; j < 128; j++) { + inv[j] *= 2.0; + } + } else { + for (size_t j = 0; j < 128; ++j) { + inv[j] *= SineWin128[j]; + } + } + + if (winType.Flags & flag) { + for (size_t j = 128; j < 160; ++j) { + inv[j] *= 2.0; + } + for (size_t j = 0; j < 64; ++j) { + inv[223 - j] *= SineWin64[j]; + } + memset(&inv[224], 0, sizeof(float) * 32); + } else { + for (size_t j = 0; j < 128; ++j) { + inv[255 - j] *= SineWin128[j]; + } } for (uint32_t j = 0; j < 128; ++j) { @@ -99,6 +148,7 @@ void TAt3pMIDCT::Do(float specs[2048], TPcmBandsData& bands, THistBuf& work) memcpy(tmp.data(), &inv[128], sizeof(float)*128); } + work.Win = winType; } }; diff --git a/src/atrac/at3p/at3p_mdct.h b/src/atrac/at3p/at3p_mdct.h index de67245..c547fec 100644 --- a/src/atrac/at3p/at3p_mdct.h +++ b/src/atrac/at3p/at3p_mdct.h @@ -19,19 +19,60 @@ #pragma once #include <array> +#include <cstdint> #include <config.h> #include "lib/mdct/mdct.h" namespace NAtracDEnc { +class TAt3pMDCT; +class TAt3pMIDCT; + +class TAt3pMDCTWin { + friend class TAt3pMDCT; + friend class TAt3pMIDCT; +public: + enum EWinType { + SINE = 0, + STEEP = 1, + }; + + TAt3pMDCTWin() noexcept + : Flags(0) + {} + + TAt3pMDCTWin(EWinType win) noexcept + : Flags(win == STEEP ? (uint16_t)-1 : 0) + {} + + void SetSteepWin(size_t sb) noexcept { + Flags |= (1 << sb); + } + + bool IsAllSine() const noexcept { + return Flags == 0; + } + + bool IsAllSteep(uint8_t sbNum) const noexcept { + uint8_t mask = (1 << sbNum) - 1; + return (Flags & mask) == mask; + } + + bool IsSbSteep(uint8_t sb) const noexcept { + return Flags & (1 << sb); + } +private: + uint16_t Flags; +}; + 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); + void Do(float specs[2048], const TPcmBandsData& bands, THistBuf& work, TAt3pMDCTWin winType); private: NMDCT::TMDCT<256> Mdct; }; @@ -39,10 +80,13 @@ private: class TAt3pMIDCT { public: TAt3pMIDCT(); - using THistBuf = std::array<std::array<float, 128>, 16>; + struct THistBuf { + std::array<std::array<float, 128>, 16> Buf; + TAt3pMDCTWin Win; + }; using TPcmBandsData = std::array<float*, 16>; - void Do(float specs[2048], TPcmBandsData& bands, THistBuf& work); + void Do(float specs[2048], TPcmBandsData& bands, THistBuf& work, TAt3pMDCTWin winType); private: NMDCT::TMIDCT<256> Midct; }; diff --git a/src/atrac/at3p/at3p_mdct_ut.cpp b/src/atrac/at3p/at3p_mdct_ut.cpp index c74eb47..a405927 100644 --- a/src/atrac/at3p/at3p_mdct_ut.cpp +++ b/src/atrac/at3p/at3p_mdct_ut.cpp @@ -38,7 +38,7 @@ TEST(TAtpMDCT, ZeroOneBlock) { pcm[i] = &zero[i * 128]; } - mdct.Do(specs.data(), pcm, buff); + mdct.Do(specs.data(), pcm, buff, TAt3pMDCTWin::SINE); for(auto s: specs) EXPECT_NEAR(s, 0.0, 0.0000000001); @@ -53,15 +53,14 @@ TEST(TAtpMDCT, ZeroOneBlock) { pcm[i] = &zero[i * 128]; } - midct.Do(specs.data(), pcm, buff); + midct.Do(specs.data(), pcm, buff, TAt3pMDCTWin::SINE); for(size_t i = 0; i < zero.size(); ++i) EXPECT_NEAR(zero[i], 0.0, 0.0000000001); } } - -TEST(TAtpMDCT, DC) { +static void DoAt3pMDCTDcTest(TAt3pMDCTWin first, TAt3pMDCTWin second) { std::array<float, 4096> specs; std::array<float, 2048> dc; @@ -79,8 +78,8 @@ TEST(TAtpMDCT, DC) { pcm[i] = &dc[i * 128]; } - mdct.Do(specs.data(), pcm, buff); - mdct.Do(specs.data() + 2048, pcm, buff); + mdct.Do(specs.data(), pcm, buff, first); + mdct.Do(specs.data() + 2048, pcm, buff, second); } { @@ -96,11 +95,26 @@ TEST(TAtpMDCT, DC) { pcm[i] = &result[i * 128]; } - midct.Do(specs.data(), pcm, buff); - midct.Do(specs.data() + 2048, pcm, buff); + midct.Do(specs.data(), pcm, buff, first); + midct.Do(specs.data() + 2048, pcm, buff, second); for(size_t i = 0; i < result.size(); ++i) { EXPECT_NEAR(result[i], dc[i], 0.000001); } } } +TEST(TAtpMDCT, DCSineWin) { + DoAt3pMDCTDcTest(TAt3pMDCTWin::SINE, TAt3pMDCTWin::SINE); +} + +TEST(TAtpMDCT, DCSteepWin) { + DoAt3pMDCTDcTest(TAt3pMDCTWin::STEEP, TAt3pMDCTWin::STEEP); +} + +TEST(TAtpMDCT, DCSineSteepWin) { + DoAt3pMDCTDcTest(TAt3pMDCTWin::SINE, TAt3pMDCTWin::STEEP); +} + +TEST(TAtpMDCT, DCSteepSineWin) { + DoAt3pMDCTDcTest(TAt3pMDCTWin::STEEP, TAt3pMDCTWin::SINE); +} |