aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2024-08-17 00:14:52 +0200
committerDaniil Cherednik <dan.cherednik@gmail.com>2024-08-17 00:14:52 +0200
commitb223290c08204ac0d3e4a826cd586de7aec106cc (patch)
treeef0cb3040ff8b7fd8114e8bd88bfc6ddfa62174c
parentbb0f0779a6f253a8544a73f8471f4ce3988a61c7 (diff)
downloadatracdenc-b223290c08204ac0d3e4a826cd586de7aec106cc.tar.gz
[AT3P] Some GHA related improvements:
* subband can share tone infos with other channel if all tones in this band matched by frequency, channel marked as leader and folower * add tool to dump test generated signals into OMA container (example GHA_UT_DUMP_DIR=/tmp/ ./test/at3plus_gha_ut) * fix code to produce correct bitstream * add code to apply PQF to the input frame and pass subbands to GHA
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/atrac/at3p/at3p.cpp42
-rw-r--r--src/atrac/at3p/at3p_bitstream.cpp56
-rw-r--r--src/atrac/at3p/at3p_gha.cpp59
-rw-r--r--src/atrac/at3p/at3p_gha.h4
-rw-r--r--src/atrac/at3p/at3p_gha_ut.cpp159
-rw-r--r--src/atrac3p.h1
7 files changed, 248 insertions, 74 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2ac6049..c82b5dc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -101,6 +101,7 @@ set(SOURCE_ATRACDENC_IMPL
atrac3denc.cpp
atrac/atrac3.cpp
atrac/atrac3_bitstream.cpp
+ atrac/atrac3plus_pqf/atrac3plus_pqf.c
atrac/at3p/at3p.cpp
atrac/at3p/at3p_bitstream.cpp
atrac/at3p/at3p_gha.cpp
diff --git a/src/atrac/at3p/at3p.cpp b/src/atrac/at3p/at3p.cpp
index 327ed9e..5069354 100644
--- a/src/atrac/at3p/at3p.cpp
+++ b/src/atrac/at3p/at3p.cpp
@@ -18,24 +18,60 @@
#include <atrac3p.h>
+#include <atrac/atrac3plus_pqf/atrac3plus_pqf.h>
+
#include "at3p_bitstream.h"
+#include "at3p_gha.h"
+
+#include <vector>
+
+using std::vector;
namespace NAtracDEnc {
class TAt3PEnc::TImpl {
public:
- TImpl(ICompressedOutput* out)
+ TImpl(ICompressedOutput* out, int channels)
: BitStream(out, 2048)
+ , ChannelCtx(channels)
+ , GhaProcessor(MakeGhaProcessor0(ChannelCtx[0].SubbandsBuf, channels == 2 ? ChannelCtx[1].SubbandsBuf : nullptr))
{}
+
void EncodeFrame(const TFloat* data, int channels);
private:
+ struct TChannelCtx {
+ TChannelCtx()
+ : PqfCtx(at3plus_pqf_create_a_ctx())
+ {}
+
+ ~TChannelCtx() {
+ at3plus_pqf_free_a_ctx(PqfCtx);
+ }
+
+ at3plus_pqf_a_ctx_t PqfCtx;
+ TFloat SubbandsBuf[TAt3PEnc::NumSamples];
+ };
+
TAt3PBitStream BitStream;
+ vector<TChannelCtx> ChannelCtx;
+ std::unique_ptr<IGhaProcessor> GhaProcessor;
};
void TAt3PEnc::TImpl::
EncodeFrame(const TFloat* data, int channels)
{
- BitStream.WriteFrame(channels, nullptr);
+
+ for (int ch = 0; ch < channels; ch++) {
+ float src[TAt3PEnc::NumSamples];
+ for (size_t i = 0; i < NumSamples; ++i) {
+ src[i] = data[i * channels + ch];
+ }
+
+ at3plus_pqf_do_analyse(ChannelCtx[ch].PqfCtx, src, ChannelCtx[ch].SubbandsBuf);
+ }
+
+ auto tonalBlock = GhaProcessor->DoAnalize();
+ BitStream.WriteFrame(channels, tonalBlock);
}
TAt3PEnc::TAt3PEnc(TCompressedOutputPtr&& out, int channels)
@@ -45,7 +81,7 @@ TAt3PEnc::TAt3PEnc(TCompressedOutputPtr&& out, int channels)
}
TPCMEngine<TFloat>::TProcessLambda TAt3PEnc::GetLambda() {
- Impl.reset(new TImpl(Out.get()));
+ Impl.reset(new TImpl(Out.get(), Channels));
return [this](TFloat* data, const TPCMEngine<TFloat>::ProcessMeta&) {
Impl->EncodeFrame(data, Channels);
diff --git a/src/atrac/at3p/at3p_bitstream.cpp b/src/atrac/at3p/at3p_bitstream.cpp
index 96dee74..df960c2 100644
--- a/src/atrac/at3p/at3p_bitstream.cpp
+++ b/src/atrac/at3p/at3p_bitstream.cpp
@@ -95,6 +95,28 @@ TAt3PBitStream::TAt3PBitStream(ICompressedOutput* container, uint16_t frameSz)
NEnv::SetRoundFloat();
}
+static void WriteSubbandFlags(NBitStream::TBitStream& bs, const bool* flags, int numFlags)
+{
+
+ int sum = 0;
+ for (int i = 0; i < numFlags; i++) {
+ sum += (uint32_t)flags[i];
+ }
+
+ if (sum == 0) {
+ bs.Write(0, 1);
+ } else if (sum == numFlags) {
+ bs.Write(1, 1);
+ bs.Write(0, 1);
+ } else {
+ bs.Write(1, 1);
+ bs.Write(1, 1);
+ for (int i = 0; i < numFlags; i++) {
+ bs.Write(flags[i], 1);
+ }
+ }
+}
+
static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3PGhaData* tonalBlock)
{
//GHA amplidude mode 1
@@ -105,8 +127,8 @@ static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3
bs.Write(tbHuff.Code, tbHuff.Len);
if (channels == 2) {
- bs.Write(0, 1);
- bs.Write(0, 1);
+ WriteSubbandFlags(bs, tonalBlock->ToneSharing, tonalBlock->NumToneBands);
+ WriteSubbandFlags(bs, &tonalBlock->SecondIsLeader, 1);
bs.Write(0, 1);
}
@@ -117,7 +139,7 @@ static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3
}
// Envelope data
for (int i = 0; i < tonalBlock->NumToneBands; i++) {
- if (ch && !tonalBlock->SecondChBands[i]) {
+ if (ch && tonalBlock->ToneSharing[i]) {
continue;
}
@@ -132,7 +154,7 @@ static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3
int mode = 0; //TODO: Calc mode
bs.Write(mode, ch + 1);
for (int i = 0; i < tonalBlock->NumToneBands; i++) {
- if (ch && !tonalBlock->SecondChBands[i]) {
+ if (ch && tonalBlock->ToneSharing[i]) {
continue;
}
bs.Write(tonalBlock->GetNumWaves(ch, i), 4);
@@ -145,7 +167,7 @@ static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3
}
for (int i = 0; i < tonalBlock->NumToneBands; i++) {
- if (ch && !tonalBlock->SecondChBands[i]) {
+ if (ch && tonalBlock->ToneSharing[i]) {
continue;
}
@@ -171,7 +193,7 @@ static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3
bs.Write(mode, ch + 1);
for (int i = 0; i < tonalBlock->NumToneBands; i++) {
- if (ch && !tonalBlock->SecondChBands[i]) {
+ if (ch && tonalBlock->ToneSharing[i]) {
continue;
}
@@ -180,13 +202,15 @@ static void WriteTonalBlock(NBitStream::TBitStream& bs, int channels, const TAt3
continue;
}
- for (size_t j = 0; j < numWaves; j++)
- bs.Write(0, 6);
+ const auto w = tonalBlock->GetWaves(ch, i);
+ for (size_t j = 0; j < numWaves; j++) {
+ bs.Write(w.first[j].AmpSf, 6);
+ }
}
// Phase
for (int i = 0; i < tonalBlock->NumToneBands; i++) {
- if (ch && !tonalBlock->SecondChBands[i]) {
+ if (ch && tonalBlock->ToneSharing[i]) {
continue;
}
@@ -214,10 +238,20 @@ void TAt3PBitStream::WriteFrame(int channels, const TAt3PGhaData* tonalBlock)
// 2 - Nobody know
bitStream.Write(channels - 1, 2);
+ int num_quant_units = 14;
+ bitStream.Write(num_quant_units - 1, 5);
+
+ for (int ch = 0; ch < channels; ch++) {
+ bitStream.Write(0, 2); // channel wordlen mode
+ for (int j = 0; j < num_quant_units; j++) {
+ bitStream.Write(0, 3); // wordlen
+ }
+ }
+
// Skip some bits to produce correct zero bitstream
- bitStream.Write(0, 10);
+
if (channels == 2) {
- bitStream.Write(0, 12);
+ bitStream.Write(0, 7);
} else {
bitStream.Write(0, 3);
}
diff --git a/src/atrac/at3p/at3p_gha.cpp b/src/atrac/at3p/at3p_gha.cpp
index 79b3c5b..79c2e8a 100644
--- a/src/atrac/at3p/at3p_gha.cpp
+++ b/src/atrac/at3p/at3p_gha.cpp
@@ -111,7 +111,7 @@ private:
return AmpSfTab;
}
- uint32_t FillFolowerRes(const TGhaInfoMap& fGhaInfos, TGhaInfoMap::const_iterator& it, uint32_t leaderSb);
+ uint32_t FillFolowerRes(const TGhaInfoMap& lGha, const TGhaInfoMap& fGha, TGhaInfoMap::const_iterator& it, uint32_t leaderSb);
uint32_t AmplitudeToSf(float amp);
@@ -358,7 +358,8 @@ void TGhaProcessor::FillResultBuf(const vector<TChannelData>& data)
{
uint32_t usedContiguousSb[2] = {0, 0};
uint32_t numTones[2] = {0, 0};
- //TODO: Calc used SB just during DoRound routine
+
+ // TODO: This can be improved. Bitstream allows to set leader/folower flag for each band.
for (size_t ch = 0; ch < data.size(); ch++) {
int cur = -1;
for (const auto& info : data[ch].GhaInfos) {
@@ -374,13 +375,14 @@ void TGhaProcessor::FillResultBuf(const vector<TChannelData>& data)
break;
}
}
- //std::cerr << "ch: " << ch << " usedSb: " << usedContiguousSb[ch] << " numTones: " << numTones[ch] << std::endl;
}
bool leader = usedContiguousSb[1] > usedContiguousSb[0];
+ ResultBuf.SecondIsLeader = leader;
ResultBuf.NumToneBands = usedContiguousSb[leader];
+ TGhaInfoMap::const_iterator leaderStartIt;
TGhaInfoMap::const_iterator folowerIt;
if (data.size() == 2) {
TWavesChannel& fWaves = ResultBuf.Waves[1];
@@ -389,10 +391,7 @@ void TGhaProcessor::FillResultBuf(const vector<TChannelData>& data)
// Yes, see bitstream code
fWaves.WaveSbInfos.resize(usedContiguousSb[leader]);
folowerIt = data[!leader].GhaInfos.begin();
-
- for (size_t i = 0; i < usedContiguousSb[leader]; i++) {
- ResultBuf.SecondChBands[i] = false;
- }
+ leaderStartIt = data[leader].GhaInfos.begin();
}
const auto& ghaInfos = data[leader].GhaInfos;
@@ -423,7 +422,8 @@ void TGhaProcessor::FillResultBuf(const vector<TChannelData>& data)
// process folower if present
if (data.size() == 2) {
- nextFolowerSb = FillFolowerRes(data[!leader].GhaInfos, folowerIt, nextSb);
+ nextFolowerSb = FillFolowerRes(data[leader].GhaInfos, data[!leader].GhaInfos, folowerIt, nextSb);
+ leaderStartIt = it;
}
nextSb = sb;
@@ -434,36 +434,53 @@ void TGhaProcessor::FillResultBuf(const vector<TChannelData>& data)
}
if (data.size() == 2 && nextFolowerSb <= usedContiguousSb[leader]) {
- FillFolowerRes(data[!leader].GhaInfos, folowerIt, nextSb);
+ FillFolowerRes(data[leader].GhaInfos, data[!leader].GhaInfos, folowerIt, nextSb);
}
}
-uint32_t TGhaProcessor::FillFolowerRes(const TGhaInfoMap& fGhaInfos, TGhaInfoMap::const_iterator& it, const uint32_t leaderSb)
+uint32_t TGhaProcessor::FillFolowerRes(const TGhaInfoMap& lGhaInfos, const TGhaInfoMap& fGhaInfos, TGhaInfoMap::const_iterator& it, const uint32_t curSb)
{
TWavesChannel& waves = ResultBuf.Waves[1];
- uint32_t fSb;
- if (it != fGhaInfos.end()) {
- fSb = ((it->first) >> 10);
- ResultBuf.SecondChBands[fSb] = true;
- waves.WaveSbInfos[fSb].WaveIndex = waves.WaveParams.size();
- }
+
+ uint32_t folowerSbMode = 0; // 0 - no tones, 1 - sharing band, 2 - own tones set
+ uint32_t nextSb = 0;
+ uint32_t added = 0;
while (it != fGhaInfos.end()) {
- fSb = ((it->first) >> 10);
- if (fSb > leaderSb) {
- return fSb;
+ uint32_t sb = ((it->first) >> 10);
+ if (sb > curSb) {
+ nextSb = sb;
+ break;
}
+ // search same indedx in the leader and set coresponding bit
+ folowerSbMode |= uint8_t(lGhaInfos.find(it->first) == lGhaInfos.end()) + 1u;
+
const auto freqIndex = it->first & 1023;
const auto phaseIndex = GhaPhaseToIndex(it->second.phase);
const auto ampSf = AmplitudeToSf(it->second.magnitude);
- waves.WaveSbInfos[fSb].WaveNums++;
waves.WaveParams.push_back(TAt3PGhaData::TWaveParam{freqIndex, ampSf, 1, phaseIndex});
it++;
+ added++;
+ }
+
+ switch (folowerSbMode) {
+ case 0:
+ ResultBuf.ToneSharing[curSb] = false;
+ waves.WaveSbInfos[curSb].WaveNums = 0;
+ break;
+ case 1:
+ ResultBuf.ToneSharing[curSb] = true;
+ waves.WaveParams.resize(waves.WaveParams.size() - added);
+ break;
+ default:
+ ResultBuf.ToneSharing[curSb] = false;
+ waves.WaveSbInfos[curSb].WaveIndex = waves.WaveParams.size() - added;
+ waves.WaveSbInfos[curSb].WaveNums = added;
}
- return 0;
+ return nextSb;
}
uint32_t TGhaProcessor::AmplitudeToSf(float amp)
diff --git a/src/atrac/at3p/at3p_gha.h b/src/atrac/at3p/at3p_gha.h
index 0daded1..35785a6 100644
--- a/src/atrac/at3p/at3p_gha.h
+++ b/src/atrac/at3p/at3p_gha.h
@@ -44,7 +44,9 @@ struct TAt3PGhaData {
std::array<TWavesChannel, 2> Waves;
uint8_t NumToneBands;
- bool SecondChBands[16];
+
+ bool ToneSharing[16];
+ bool SecondIsLeader;
size_t GetNumWaves(size_t ch, size_t sb) const {
return Waves[ch].WaveSbInfos.at(sb).WaveNums;
diff --git a/src/atrac/at3p/at3p_gha_ut.cpp b/src/atrac/at3p/at3p_gha_ut.cpp
index 718bb04..6554a41 100644
--- a/src/atrac/at3p/at3p_gha_ut.cpp
+++ b/src/atrac/at3p/at3p_gha_ut.cpp
@@ -1,7 +1,10 @@
+#include "at3p_bitstream.h"
#include "at3p_gha.h"
+#include "oma.h"
#include <gtest/gtest.h>
#include <cmath>
#include <vector>
+#include <cstdlib>
using std::vector;
@@ -48,6 +51,39 @@ static const TAt3PGhaData __attribute__ ((noinline)) GenAndRunGha(vector<TTestPa
return *(processor->DoAnalize());
}
+static class TDumper {
+public:
+ TDumper()
+ : PathPrefix(std::getenv("GHA_UT_DUMP_DIR"))
+ {}
+
+ void Dump(const TAt3PGhaData* gha, size_t channels, size_t len) {
+ if (!PathPrefix) {
+ return;
+ }
+
+ std::string path = PathPrefix;
+ path += "/";
+ path += ::testing::UnitTest::GetInstance()->current_test_info()->name();
+ path += ".oma";
+
+ std::unique_ptr<TOma> out(new TOma(path,
+ "test",
+ channels,
+ 1, OMAC_ID_ATRAC3PLUS,
+ 2048,
+ false));
+
+ TAt3PBitStream bs(out.get(), 2048);
+
+ for (size_t i = 0; i < len; i++) {
+ bs.WriteFrame(channels, gha + i);
+ }
+ }
+private:
+ const char* PathPrefix;
+} Dumper;
+
// Single channel simple cases
TEST(AT3PGHA, 689hz0625__full_frame_mono) {
@@ -59,6 +95,7 @@ TEST(AT3PGHA, 689hz0625__full_frame_mono) {
EXPECT_EQ(res.GetWaves(0, 0).second, 1);
EXPECT_EQ(res.GetWaves(0, 0).first->FreqIndex, 512);
EXPECT_EQ(res.GetWaves(0, 0).first->AmpSf, 63);
+ Dumper.Dump(&res, 1, 1);
}
@@ -81,6 +118,7 @@ TEST(AT3PGHA, 689hz0625_900hz__full_frame_mono) {
EXPECT_EQ(res.GetWaves(0, 0).second, 2);
EXPECT_EQ(res.GetWaves(0, 0).first[0].FreqIndex, 512);
EXPECT_EQ(res.GetWaves(0, 0).first[1].FreqIndex, 669);
+ Dumper.Dump(&res, 1, 1);
}
TEST(AT3PGHA, 400hz_800hz__full_frame_mono) {
@@ -92,10 +130,11 @@ TEST(AT3PGHA, 400hz_800hz__full_frame_mono) {
EXPECT_EQ(res.GetWaves(0, 0).second, 2);
EXPECT_EQ(res.GetWaves(0, 0).first[0].FreqIndex, 297);
EXPECT_EQ(res.GetWaves(0, 0).first[1].FreqIndex, 594);
+ Dumper.Dump(&res, 1, 1);
}
TEST(AT3PGHA, 689hz0625_2067hz1875__full_frame_mono) {
- auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}, {689.0625f, 16384, 128, 256}}, {});
+ auto res = GenAndRunGha({{689.0625f, 16384, 0, 128}, {689.0625f, 16384, 128, 256}}, {});
EXPECT_EQ(res.NumToneBands, 2);
EXPECT_EQ(res.Waves[0].WaveParams.size(), 2);
EXPECT_EQ(res.Waves[0].WaveSbInfos.size(), 2);
@@ -103,8 +142,11 @@ TEST(AT3PGHA, 689hz0625_2067hz1875__full_frame_mono) {
EXPECT_EQ(res.GetNumWaves(0, 1), 1);
EXPECT_EQ(res.GetWaves(0, 0).second, 1);
EXPECT_EQ(res.GetWaves(0, 0).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.GetWaves(0, 0).first->AmpSf, 59);
EXPECT_EQ(res.GetWaves(0, 1).second, 1);
EXPECT_EQ(res.GetWaves(0, 1).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.GetWaves(0, 1).first->AmpSf, 59);
+ Dumper.Dump(&res, 1, 1);
}
TEST(AT3PGHA, 689hz0625_4823hz4375__full_frame_mono) {
@@ -115,11 +157,12 @@ TEST(AT3PGHA, 689hz0625_4823hz4375__full_frame_mono) {
EXPECT_EQ(res.GetNumWaves(0, 0), 1);
EXPECT_EQ(res.GetWaves(0, 0).second, 1);
EXPECT_EQ(res.GetWaves(0, 0).first->FreqIndex, 512);
+ Dumper.Dump(&res, 1, 1);
}
// Two channels simple cases
-TEST(AT3PGHA, 689hz0625__full_frame_stereo) {
+TEST(AT3PGHA, 689hz0625__full_frame_stereo_shared) {
auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}}, {{689.0625f, 32768, 0, 128}});
EXPECT_EQ(res.NumToneBands, 1);
EXPECT_EQ(res.Waves[0].WaveParams.size(), 1);
@@ -128,11 +171,29 @@ TEST(AT3PGHA, 689hz0625__full_frame_stereo) {
EXPECT_EQ(res.GetWaves(0, 0).second, 1);
EXPECT_EQ(res.GetWaves(0, 0).first->FreqIndex, 512);
+ EXPECT_EQ(res.ToneSharing[0], true);
+ EXPECT_EQ(res.Waves[1].WaveParams.size(), 0);
+ Dumper.Dump(&res, 2, 1);
+}
+
+TEST(AT3PGHA, 689hz0625__full_frame_stereo_own) {
+ auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}}, {{1000.0625f, 32768, 0, 128}});
+ EXPECT_EQ(res.NumToneBands, 1);
+ EXPECT_EQ(res.Waves[0].WaveParams.size(), 1);
+ EXPECT_EQ(res.Waves[0].WaveSbInfos.size(), 1);
+ EXPECT_EQ(res.GetNumWaves(0, 0), 1);
+ EXPECT_EQ(res.GetWaves(0, 0).second, 1);
+ EXPECT_EQ(res.GetWaves(0, 0).first->FreqIndex, 512);
+
+ EXPECT_EQ(res.ToneSharing[0], false);
+
EXPECT_EQ(res.Waves[1].WaveParams.size(), 1);
EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 1);
EXPECT_EQ(res.GetNumWaves(1, 0), 1);
EXPECT_EQ(res.GetWaves(1, 0).second, 1);
- EXPECT_EQ(res.GetWaves(1, 0).first->FreqIndex, 512);
+ EXPECT_EQ(res.GetWaves(1, 0).first->FreqIndex, 743);
+
+ Dumper.Dump(&res, 2, 1);
}
TEST(AT3PGHA, 689hz0625__full_frame_stereo_multiple_second) {
@@ -144,12 +205,36 @@ TEST(AT3PGHA, 689hz0625__full_frame_stereo_multiple_second) {
EXPECT_EQ(res.GetWaves(0, 0).second, 1);
EXPECT_EQ(res.GetWaves(0, 0).first->FreqIndex, 512);
+ EXPECT_EQ(res.ToneSharing[0], false);
EXPECT_EQ(res.Waves[1].WaveParams.size(), 2);
EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 1);
EXPECT_EQ(res.GetNumWaves(1, 0), 2);
EXPECT_EQ(res.GetWaves(1, 0).second, 2);
EXPECT_EQ(res.GetWaves(1, 0).first[0].FreqIndex, 512);
EXPECT_EQ(res.GetWaves(1, 0).first[1].FreqIndex, 669);
+ Dumper.Dump(&res, 2, 1);
+}
+
+TEST(AT3PGHA, 689hz0625_2067hz1875__full_frame_stereo_first_is_leader) {
+ auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}, {689.0625f, 16384, 128, 256}},
+ {{689.0625f, 32768, 0, 128}});
+ EXPECT_EQ(res.NumToneBands, 2);
+ EXPECT_EQ(res.Waves[0].WaveParams.size(), 2);
+ EXPECT_EQ(res.Waves[0].WaveSbInfos.size(), 2);
+ EXPECT_EQ(res.GetNumWaves(0, 0), 1);
+ EXPECT_EQ(res.GetNumWaves(0, 1), 1);
+ EXPECT_EQ(res.GetWaves(0, 0).second, 1);
+ EXPECT_EQ(res.GetWaves(0, 0).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.GetWaves(0, 1).second, 1);
+ EXPECT_EQ(res.GetWaves(0, 1).first[0].FreqIndex, 512);
+
+ EXPECT_EQ(res.ToneSharing[0], true);
+ EXPECT_EQ(res.ToneSharing[1], false);
+
+ EXPECT_EQ(res.Waves[1].WaveParams.size(), 0); // sb0 sharing, sb1 zerro
+ EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 2);
+ EXPECT_EQ(res.GetNumWaves(1, 1), 0);
+ Dumper.Dump(&res, 2, 1);
}
TEST(AT3PGHA, 689hz0625_2067hz1875__full_frame_stereo_second_is_leader) {
@@ -165,14 +250,17 @@ TEST(AT3PGHA, 689hz0625_2067hz1875__full_frame_stereo_second_is_leader) {
EXPECT_EQ(res.GetWaves(0, 1).second, 1);
EXPECT_EQ(res.GetWaves(0, 1).first[0].FreqIndex, 512);
- EXPECT_EQ(res.Waves[1].WaveParams.size(), 1);
+ EXPECT_EQ(res.ToneSharing[0], true);
+ EXPECT_EQ(res.ToneSharing[1], false);
+
+ EXPECT_EQ(res.Waves[1].WaveParams.size(), 0);
EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 2);
- EXPECT_EQ(res.GetNumWaves(0, 0), 1);
- EXPECT_EQ(res.GetWaves(1, 0).second, 1);
- EXPECT_EQ(res.GetWaves(1, 0).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.GetNumWaves(1, 1), 0);
+
+ Dumper.Dump(&res, 2, 1);
}
-TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_has_0_2) {
+TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_sharing_0_2) {
auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}, {689.0625f, 32768, 128, 256}, {689.0625f, 16384, 256, 384}},
{{689.0625f, 32768, 0, 128}, {689.0625f, 16384, 256, 384}});
EXPECT_EQ(res.NumToneBands, 3);
@@ -188,20 +276,15 @@ TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_has_0_2
EXPECT_EQ(res.GetWaves(0, 2).second, 1);
EXPECT_EQ(res.GetWaves(0, 2).first[0].FreqIndex, 512);
- EXPECT_EQ(res.SecondChBands[0], true);
- EXPECT_EQ(res.SecondChBands[1], false);
- EXPECT_EQ(res.SecondChBands[2], true);
- EXPECT_EQ(res.Waves[1].WaveParams.size(), 2);
- EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 3);
- EXPECT_EQ(res.GetNumWaves(1, 0), 1);
- EXPECT_EQ(res.GetNumWaves(1, 2), 1);
- EXPECT_EQ(res.GetWaves(1, 0).second, 1);
- EXPECT_EQ(res.GetWaves(1, 0).first[0].FreqIndex, 512);
- EXPECT_EQ(res.GetWaves(1, 2).second, 1);
- EXPECT_EQ(res.GetWaves(1, 2).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.ToneSharing[0], true);
+ EXPECT_EQ(res.ToneSharing[1], false);
+ EXPECT_EQ(res.ToneSharing[2], true);
+ EXPECT_EQ(res.Waves[1].WaveParams.size(), 0);
+ EXPECT_EQ(res.GetNumWaves(1, 1), 0);
+ Dumper.Dump(&res, 2, 1);
}
-TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_has_2) {
+TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_sharing_2) {
auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}, {689.0625f, 32768, 128, 256}, {689.0625f, 16384, 256, 384}},
{{689.0625f, 16384, 256, 384}});
EXPECT_EQ(res.NumToneBands, 3);
@@ -217,17 +300,16 @@ TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_has_2)
EXPECT_EQ(res.GetWaves(0, 2).second, 1);
EXPECT_EQ(res.GetWaves(0, 2).first[0].FreqIndex, 512);
- EXPECT_EQ(res.SecondChBands[0], false);
- EXPECT_EQ(res.SecondChBands[1], false);
- EXPECT_EQ(res.SecondChBands[2], true);
- EXPECT_EQ(res.Waves[1].WaveParams.size(), 1);
- EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 3);
- EXPECT_EQ(res.GetNumWaves(1, 2), 1);
- EXPECT_EQ(res.GetWaves(1, 2).second, 1);
- EXPECT_EQ(res.GetWaves(1, 2).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.ToneSharing[0], false);
+ EXPECT_EQ(res.ToneSharing[1], false);
+ EXPECT_EQ(res.ToneSharing[2], true);
+ EXPECT_EQ(res.Waves[1].WaveParams.size(), 0);
+ EXPECT_EQ(res.GetNumWaves(1, 0), 0);
+ EXPECT_EQ(res.GetNumWaves(1, 1), 0);
+ Dumper.Dump(&res, 2, 1);
}
-TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_has_1) {
+TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_sharing_1) {
auto res = GenAndRunGha({{689.0625f, 32768, 0, 128}, {689.0625f, 32768, 128, 256}, {689.0625f, 16384, 256, 384}},
{{689.0625f, 16384, 128, 256}});
EXPECT_EQ(res.NumToneBands, 3);
@@ -243,16 +325,16 @@ TEST(AT3PGHA, 689hz0625_2067hz1875_3445hz3125__full_frame_stereo_folower_has_1)
EXPECT_EQ(res.GetWaves(0, 2).second, 1);
EXPECT_EQ(res.GetWaves(0, 2).first[0].FreqIndex, 512);
- EXPECT_EQ(res.SecondChBands[0], false);
- EXPECT_EQ(res.SecondChBands[1], true);
- EXPECT_EQ(res.SecondChBands[2], false);
- EXPECT_EQ(res.Waves[1].WaveParams.size(), 1);
- EXPECT_EQ(res.Waves[1].WaveSbInfos.size(), 3);
- EXPECT_EQ(res.GetNumWaves(1, 1), 1);
- EXPECT_EQ(res.GetWaves(1, 1).second, 1);
- EXPECT_EQ(res.GetWaves(1, 1).first[0].FreqIndex, 512);
+ EXPECT_EQ(res.ToneSharing[0], false);
+ EXPECT_EQ(res.ToneSharing[1], true);
+ EXPECT_EQ(res.ToneSharing[2], false);
+ EXPECT_EQ(res.Waves[1].WaveParams.size(), 0);
+ EXPECT_EQ(res.GetNumWaves(1, 0), 0);
+ EXPECT_EQ(res.GetNumWaves(1, 2), 0);
+ Dumper.Dump(&res, 2, 1);
}
+/*
TEST(AT3PGHA, max_tones_multiple_bands_full_frame_stereo) {
auto res = GenAndRunGha({
{60.0f, 8192, 0, 128}, {120.0f, 8192, 0, 128}, {180.0f, 4096, 0, 128}, {240.0f, 2048, 0, 128},
@@ -354,6 +436,7 @@ TEST(AT3PGHA, max_tones_multiple_bands_full_frame_stereo) {
EXPECT_EQ(res.GetWaves(1, 6).first[0].FreqIndex, 45);
EXPECT_EQ(res.GetWaves(1, 6).first[1].FreqIndex, 89);
EXPECT_EQ(res.GetWaves(1, 6).first[2].FreqIndex, 134);
+ Dumper.Dump(&res, 2, 1);
}
-
+*/
diff --git a/src/atrac3p.h b/src/atrac3p.h
index 31371d1..82f8718 100644
--- a/src/atrac3p.h
+++ b/src/atrac3p.h
@@ -28,6 +28,7 @@ class TAt3PEnc : public IProcessor<TFloat> {
public:
TAt3PEnc(TCompressedOutputPtr&& out, int channels);
TPCMEngine<TFloat>::TProcessLambda GetLambda() override;
+ static constexpr int NumSamples = 2048;
private:
TCompressedOutputPtr Out;
int Channels;