diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2025-05-16 23:27:59 +0200 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2025-05-16 23:48:26 +0200 |
commit | c5ae2cec2c8308f96867e1620f0ec3a5c41395e4 (patch) | |
tree | 8291351078e27ece783f9495241cdf667cfd4e0b /src | |
parent | 2a143471b0898dd8b6257ca69309a6f2b1c20bf3 (diff) | |
download | atracdenc-c5ae2cec2c8308f96867e1620f0ec3a5c41395e4.tar.gz |
[AT3P] Add advanced option for GHA debug
There are 3 flags:
GHA_PASS_INPUT - allows to pass source signal in to the filter
GHA_WRITE_TONAL - allows to write result of GHA into the bitstream
GHA_WRITE_RESIUDAL - allows to process signal after the filter
If all 3 flags set it denotes normal processing.
If we want to see only result of sinusoid extraction (tonal component) we can set only
GHA_WRITE_TONAL flag. If we want to see signal after extraction we need
to set GHA_PASS_INPUT and GHA_WRITE_RESIUDAL.
Diffstat (limited to 'src')
-rw-r--r-- | src/atrac/at3p/at3p.cpp | 107 | ||||
-rw-r--r-- | src/atrac3p.h | 18 | ||||
-rw-r--r-- | src/main.cpp | 17 |
3 files changed, 130 insertions, 12 deletions
diff --git a/src/atrac/at3p/at3p.cpp b/src/atrac/at3p/at3p.cpp index 278d362..ceee283 100644 --- a/src/atrac/at3p/at3p.cpp +++ b/src/atrac/at3p/at3p.cpp @@ -28,6 +28,7 @@ #include <cassert> #include <vector> +#include <unordered_map> using std::vector; @@ -35,10 +36,11 @@ namespace NAtracDEnc { class TAt3PEnc::TImpl { public: - TImpl(ICompressedOutput* out, int channels) + TImpl(ICompressedOutput* out, int channels, TSettings settings) : BitStream(out, 2048) , ChannelCtx(channels) , GhaProcessor(MakeGhaProcessor0(channels == 2)) + , Settings(settings) { delay.NumToneBands = 0; } @@ -72,6 +74,7 @@ private: vector<TChannelCtx> ChannelCtx; std::unique_ptr<IGhaProcessor> GhaProcessor; TAt3PGhaData delay; + const TSettings Settings; }; TPCMEngine::EProcessResult TAt3PEnc::TImpl:: @@ -121,8 +124,14 @@ EncodeFrame(const float* data, int channels) TAt3pMDCT::TPcmBandsData p; float tmp[2048]; //TODO: scale window - for (size_t i = 0; i < 2048; i++) { - tmp[i] = x[i] / 32768.0; + if (Settings.UseGha & TSettings::GHA_WRITE_RESIUDAL) { + for (size_t i = 0; i < 2048; i++) { + tmp[i] = x[i] / 32768.0; + } + } else { + for (size_t i = 0; i < 2048; i++) { + tmp[i] = 0.0; + } } for (size_t b = 0; b < 16; b++) { p[b] = tmp + b * 128; @@ -136,10 +145,14 @@ EncodeFrame(const float* data, int channels) BitStream.WriteFrame(channels, p, scaledBlocks); for (int ch = 0; ch < channels; ch++) { - memcpy(ChannelCtx[ch].PrevBuf, ChannelCtx[ch].CurBuf, sizeof(float) * TAt3PEnc::NumSamples); + if (Settings.UseGha & TSettings::GHA_PASS_INPUT) { + memcpy(ChannelCtx[ch].PrevBuf, ChannelCtx[ch].CurBuf, sizeof(float) * TAt3PEnc::NumSamples); + } else { + memset(ChannelCtx[ch].PrevBuf, 0, sizeof(float) * TAt3PEnc::NumSamples); + } std::swap(ChannelCtx[ch].NextBuf, ChannelCtx[ch].CurBuf); } - if (tonalBlock) { + if (tonalBlock && (Settings.UseGha & TSettings::GHA_WRITE_TONAL)) { delay = *tonalBlock; } else { delay.NumToneBands = 0; @@ -148,18 +161,96 @@ EncodeFrame(const float* data, int channels) return TPCMEngine::EProcessResult::PROCESSED; } -TAt3PEnc::TAt3PEnc(TCompressedOutputPtr&& out, int channels) +TAt3PEnc::TAt3PEnc(TCompressedOutputPtr&& out, int channels, TSettings settings) : Out(std::move(out)) , Channels(channels) + , Impl(new TImpl(Out.get(), Channels, settings)) { } TPCMEngine::TProcessLambda TAt3PEnc::GetLambda() { - Impl.reset(new TImpl(Out.get(), Channels)); - return [this](float* data, const TPCMEngine::ProcessMeta&) { return Impl->EncodeFrame(data, Channels); }; } +static void SetGha(const std::string& str, TAt3PEnc::TSettings& settings) { + int mask = std::stoi(str); + if (mask > 7 || mask < 0) { + throw std::runtime_error("invalud value of GHA processing mask"); + } + + if (mask & TAt3PEnc::TSettings::GHA_PASS_INPUT) + std::cerr << "GHA_PASS_INPUT" << std::endl; + if (mask & TAt3PEnc::TSettings::GHA_WRITE_RESIUDAL) + std::cerr << "GHA_WRITE_RESIUDAL" << std::endl; + if (mask & TAt3PEnc::TSettings::GHA_WRITE_TONAL) + std::cerr << "GHA_WRITE_TONAL" << std::endl; + + settings.UseGha = mask; +} + + + +void TAt3PEnc::ParseAdvancedOpt(const char* opt, TSettings& settings) { + typedef void (*processFn)(const std::string& str, TSettings& settings); + static std::unordered_map<std::string, processFn> keys { + {"ghadbg", &SetGha} + }; + + if (opt == nullptr) + return; + + const char* start = opt; + bool vState = false; //false - key state, true - value state + processFn handler = nullptr; + + while (opt) { + if (!vState) { + if (*opt == ',') { + throw std::runtime_error("unexpected \",\" just after key."); +// if (opt - start > 0) { +// } +// opt++; +// start = opt; + } else if (*opt == '=') { + auto it = keys.find(std::string(start, opt - start)); + if (it == keys.end()) { + throw std::runtime_error(std::string("unexpected advanced option \"") + + std::string(start, opt - start)); + } + handler = it->second; + vState = true; + opt++; + start = opt; + } else if (!*opt) { + throw std::runtime_error("unexpected end of key token"); +// if (opt - start > 0) { +// } +// opt = nullptr; + } else { + opt++; + } + } else { + if (*opt == ',') { + if (opt - start > 0) { + handler(std::string(start, opt - start), settings); + } + opt++; + start = opt; + vState = false; + } else if (*opt == '=') { + throw std::runtime_error("unexpected \"=\" inside value token."); + } else if (!*opt) { + if (opt - start > 0) { + handler(std::string(start, opt - start), settings); + } + opt = nullptr; + } else { + opt++; + } + } + } +} + } diff --git a/src/atrac3p.h b/src/atrac3p.h index 258a6f1..779929d 100644 --- a/src/atrac3p.h +++ b/src/atrac3p.h @@ -26,9 +26,25 @@ namespace NAtracDEnc { class TAt3PEnc : public IProcessor { public: - TAt3PEnc(TCompressedOutputPtr&& out, int channels); + struct TSettings { + enum GhaProcessingFlags : uint8_t { + GHA_PASS_INPUT = 1, + GHA_WRITE_TONAL = 1 << 1, + GHA_WRITE_RESIUDAL = 1 << 2, + + GHA_ENABLED = GHA_PASS_INPUT | GHA_WRITE_TONAL | GHA_WRITE_RESIUDAL + }; + uint8_t UseGha; + + TSettings() + : UseGha(GHA_ENABLED) + {} + }; + TAt3PEnc(TCompressedOutputPtr&& out, int channels, TSettings settings); TPCMEngine::TProcessLambda GetLambda() override; static constexpr int NumSamples = 2048; + static void ParseAdvancedOpt(const char* opt, TSettings& settings); + private: TCompressedOutputPtr Out; int Channels; diff --git a/src/main.cpp b/src/main.cpp index 8dbf700..861495f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,6 +110,7 @@ enum EOptions O_NOSTDOUT = '4', O_NOTONAL = 5, O_NOGAINCONTROL = 6, + O_ADVANCED_OPT = 7, }; static void CheckInputFormat(const TWav* p) @@ -258,7 +259,8 @@ static void PrepareAtrac3PEncoder(const string& inFile, uint64_t* totalSamples, const TWavPtr& wavIO, TPcmEnginePtr* pcmEngine, - TAtracProcessorPtr* atracProcessor) + TAtracProcessorPtr* atracProcessor, + const char* advancedOpt) { *totalSamples = wavIO->GetTotalSamples(); const uint64_t numFrames = (*totalSamples) / 2048; @@ -300,13 +302,18 @@ static void PrepareAtrac3PEncoder(const string& inFile, pcmEngine->reset(new TPCMEngine(4096, numChannels, TPCMEngine::TReaderPtr(wavIO->GetPCMReader()))); - atracProcessor->reset(new TAt3PEnc(std::move(omaIO), numChannels)); + TAt3PEnc::TSettings settings; + if (advancedOpt) { + TAt3PEnc::ParseAdvancedOpt(advancedOpt, settings); + } + atracProcessor->reset(new TAt3PEnc(std::move(omaIO), numChannels, settings)); } int main_(int argc, char* const* argv) { const char* myName = argv[0]; + const char* advancedOpt = nullptr; static struct option longopts[] = { { "encode", optional_argument, NULL, O_ENCODE }, { "decode", no_argument, NULL, O_DECODE }, @@ -317,6 +324,7 @@ int main_(int argc, char* const* argv) { "notransient", optional_argument, NULL, O_NOTRANSIENT}, { "nostdout", no_argument, NULL, O_NOSTDOUT}, { "nogaincontrol", no_argument, NULL, O_NOGAINCONTROL}, + { "advanced", required_argument, NULL, O_ADVANCED_OPT}, { NULL, 0, NULL, 0} }; @@ -399,6 +407,9 @@ int main_(int argc, char* const* argv) case O_NOGAINCONTROL: noGainControl = true; break; + case O_ADVANCED_OPT: + advancedOpt = optarg; + break; default: printUsage(myName); return 1; @@ -466,7 +477,7 @@ int main_(int argc, char* const* argv) { wavIO = OpenWavFile(inFile); PrepareAtrac3PEncoder(inFile, outFile, noStdOut, wavIO->GetChannelNum(), - &totalSamples, wavIO, &pcmEngine, &atracProcessor); + &totalSamples, wavIO, &pcmEngine, &atracProcessor, advancedOpt); pcmFrameSz = 2048; } break; |