diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2024-12-24 22:59:03 +0100 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2024-12-24 22:59:03 +0100 |
commit | bddbeb98b3db8d435de6b2d10269640121475538 (patch) | |
tree | 1a791f5dd49b94ead503b9b77c6b9277f2701a89 /src/atrac3denc.cpp | |
parent | c73a0e24a0d5c510a65efbe5c2fbc7fd39a3c003 (diff) | |
parent | 74d6e04c21bddd435bd74c34dbe027b883772a76 (diff) | |
download | atracdenc-bddbeb98b3db8d435de6b2d10269640121475538.tar.gz |
Merge branch 'master' into at3plus-dev
Diffstat (limited to 'src/atrac3denc.cpp')
-rw-r--r-- | src/atrac3denc.cpp | 130 |
1 files changed, 79 insertions, 51 deletions
diff --git a/src/atrac3denc.cpp b/src/atrac3denc.cpp index b1f81d1..56e6517 100644 --- a/src/atrac3denc.cpp +++ b/src/atrac3denc.cpp @@ -18,6 +18,7 @@ #include "atrac3denc.h" #include "transient_detector.h" +#include "atrac/atrac_psy_common.h" #include <assert.h> #include <algorithm> #include <iostream> @@ -28,26 +29,26 @@ using namespace NMDCT; using namespace NAtrac3; using std::vector; -void TAtrac3MDCT::Mdct(TFloat specs[1024], TFloat* bands[4], TFloat maxLevels[4], TGainModulatorArray gainModulators) +void TAtrac3MDCT::Mdct(float specs[1024], float* bands[4], float maxLevels[4], TGainModulatorArray gainModulators) { for (int band = 0; band < 4; ++band) { - TFloat* srcBuff = bands[band]; - TFloat* const curSpec = &specs[band*256]; + float* srcBuff = bands[band]; + float* const curSpec = &specs[band*256]; TGainModulator modFn = gainModulators[band]; - TFloat tmp[512]; - memcpy(&tmp[0], srcBuff, 256 * sizeof(TFloat)); + float tmp[512]; + memcpy(&tmp[0], srcBuff, 256 * sizeof(float)); if (modFn) { modFn(&tmp[0], &srcBuff[256]); } - TFloat max = 0.0; + float max = 0.0; for (int i = 0; i < 256; i++) { max = std::max(max, std::abs(srcBuff[256+i])); srcBuff[i] = TAtrac3Data::EncodeWindow[i] * srcBuff[256+i]; tmp[256+i] = TAtrac3Data::EncodeWindow[255-i] * srcBuff[256+i]; } - const vector<TFloat>& sp = Mdct512(&tmp[0]); + const vector<float>& sp = Mdct512(&tmp[0]); assert(sp.size() == 256); - memcpy(curSpec, sp.data(), 256 * sizeof(TFloat)); + memcpy(curSpec, sp.data(), 256 * sizeof(float)); if (band & 1) { SwapArray(curSpec, 256); } @@ -55,27 +56,27 @@ void TAtrac3MDCT::Mdct(TFloat specs[1024], TFloat* bands[4], TFloat maxLevels[4] } } -void TAtrac3MDCT::Mdct(TFloat specs[1024], TFloat* bands[4], TGainModulatorArray gainModulators) +void TAtrac3MDCT::Mdct(float specs[1024], float* bands[4], TGainModulatorArray gainModulators) { - static TFloat dummy[4]; + static float dummy[4]; Mdct(specs, bands, dummy, gainModulators); } -void TAtrac3MDCT::Midct(TFloat specs[1024], TFloat* bands[4], TGainDemodulatorArray gainDemodulators) +void TAtrac3MDCT::Midct(float specs[1024], float* bands[4], TGainDemodulatorArray gainDemodulators) { for (int band = 0; band < 4; ++band) { - TFloat* dstBuff = bands[band]; - TFloat* curSpec = &specs[band*256]; - TFloat* prevBuff = dstBuff + 256; + float* dstBuff = bands[band]; + float* curSpec = &specs[band*256]; + float* prevBuff = dstBuff + 256; TAtrac3GainProcessor::TGainDemodulator demodFn = gainDemodulators[band]; if (band & 1) { SwapArray(curSpec, 256); } - vector<TFloat> inv = Midct512(curSpec); + vector<float> inv = Midct512(curSpec); assert(inv.size()/2 == 256); for (int j = 0; j < 256; ++j) { - inv[j] *= /*2 */ DecodeWindow[j]; - inv[511 - j] *= /*2*/ DecodeWindow[j]; + inv[j] *= /*2 */ TAtrac3Data::DecodeWindow[j]; + inv[511 - j] *= /*2*/ TAtrac3Data::DecodeWindow[j]; } if (demodFn) { demodFn(dstBuff, inv.data(), prevBuff); @@ -84,13 +85,14 @@ void TAtrac3MDCT::Midct(TFloat specs[1024], TFloat* bands[4], TGainDemodulatorAr dstBuff[j] = inv[j] + prevBuff[j]; } } - memcpy(prevBuff, &inv[256], sizeof(TFloat)*256); + memcpy(prevBuff, &inv[256], sizeof(float)*256); } } TAtrac3Encoder::TAtrac3Encoder(TCompressedOutputPtr&& oma, TAtrac3EncoderSettings&& encoderSettings) : Oma(std::move(oma)) , Params(std::move(encoderSettings)) + , LoudnessCurve(CreateLoudnessCurve(TAtrac3Data::NumSamples)) , SingleChannelElements(Params.SourceChannels) , TransientParamsHistory(Params.SourceChannels, std::vector<TTransientParam>(4)) {} @@ -128,9 +130,9 @@ TAtrac3MDCT::TGainModulatorArray TAtrac3MDCT::MakeGainModulatorArray(const TAtra } } -TFloat TAtrac3Encoder::LimitRel(TFloat x) +float TAtrac3Encoder::LimitRel(float x) { - return std::min(std::max((double)x, GainLevel[15]), GainLevel[0]); + return std::min(std::max(x, TAtrac3Data::GainLevel[15]), TAtrac3Data::GainLevel[0]); } void TAtrac3Encoder::ResetTransientParamsHistory(int channel, int band) @@ -148,18 +150,18 @@ const TAtrac3Encoder::TTransientParam& TAtrac3Encoder::GetTransientParamsHistory return TransientParamsHistory[channel][band]; } -TAtrac3Encoder::TTransientParam TAtrac3Encoder::CalcTransientParam(const std::vector<TFloat>& gain, const TFloat lastMax) +TAtrac3Encoder::TTransientParam TAtrac3Encoder::CalcTransientParam(const std::vector<float>& gain, const float lastMax) { int32_t attack0Location = -1; // position where gain is risen up, -1 - no attack - TFloat attack0Relation = 1; + float attack0Relation = 1; - const TFloat attackThreshold = 2; + const float attackThreshold = 2; { // pre-echo searching // relative to previous half frame for (uint32_t i = 0; i < gain.size(); i++) { - const TFloat tmp = gain[i] / lastMax; + const float tmp = gain[i] / lastMax; if (tmp > attackThreshold) { attack0Relation = tmp; attack0Location = i; @@ -169,13 +171,13 @@ TAtrac3Encoder::TTransientParam TAtrac3Encoder::CalcTransientParam(const std::ve } int32_t attack1Location = -1; - TFloat attack1Relation = 1; + float attack1Relation = 1; { // pre-echo searching // relative to previous subsamples block - TFloat q = gain[0]; + float q = gain[0]; for (uint32_t i = 1; i < gain.size(); i++) { - const TFloat tmp = gain[i] / q; + const float tmp = gain[i] / q; if (tmp > attackThreshold) { attack1Relation = tmp; attack1Location = i; @@ -185,15 +187,15 @@ TAtrac3Encoder::TTransientParam TAtrac3Encoder::CalcTransientParam(const std::ve } int32_t releaseLocation = -1; // position where gain is fallen down, -1 - no release - TFloat releaseRelation = 1; + float releaseRelation = 1; - const TFloat releaseTreshold = 2; + const float releaseTreshold = 2; { // post-echo searching // relative to current frame - TFloat q = gain.back(); + float q = gain.back(); for (uint32_t i = gain.size() - 2; i > 0; --i) { - const TFloat tmp = gain[i] / q; + const float tmp = gain[i] / q; if (tmp > releaseTreshold) { releaseRelation = tmp; releaseLocation = i; @@ -206,24 +208,24 @@ TAtrac3Encoder::TTransientParam TAtrac3Encoder::CalcTransientParam(const std::ve return {attack0Location, attack0Relation, attack1Location, attack1Relation, releaseLocation, releaseRelation}; } -void TAtrac3Encoder::CreateSubbandInfo(TFloat* in[4], +void TAtrac3Encoder::CreateSubbandInfo(float* in[4], uint32_t channel, TAtrac3Data::SubbandInfo* subbandInfo) { - auto relToIdx = [](TFloat rel) { + auto relToIdx = [](float rel) { rel = 1.0/rel; return (uint32_t)(RelationToIdx(rel)); }; for (int band = 0; band < 4; ++band) { - const TFloat* srcBuff = in[band]; + const float* srcBuff = in[band]; - const TFloat* const lastMax = &PrevPeak[channel][band]; + const float* const lastMax = &PrevPeak[channel][band]; std::vector<TAtrac3Data::SubbandInfo::TGainPoint> curve; - const std::vector<TFloat> gain = AnalyzeGain(srcBuff, 256, 32, false); + const std::vector<float> gain = AnalyzeGain(srcBuff, 256, 32, false); auto transientParam = CalcTransientParam(gain, *lastMax); bool hasTransient = false; @@ -275,8 +277,8 @@ void TAtrac3Encoder::CreateSubbandInfo(TFloat* in[4], void TAtrac3Encoder::Matrixing() { for (uint32_t subband = 0; subband < 4; subband++) { - TFloat* pair[2] = {PcmBuffer.GetSecond(subband * 2), PcmBuffer.GetSecond(subband * 2 + 1)}; - TFloat tmp[2]; + float* pair[2] = {PcmBuffer.GetSecond(subband * 2), PcmBuffer.GetSecond(subband * 2 + 1)}; + float tmp[2]; for (uint32_t sample = 0; sample < 256; sample++) { tmp[0] = pair[0][sample]; tmp[1] = pair[1][sample]; @@ -286,21 +288,33 @@ void TAtrac3Encoder::Matrixing() } } -TPCMEngine<TFloat>::TProcessLambda TAtrac3Encoder::GetLambda() +TPCMEngine::TProcessLambda TAtrac3Encoder::GetLambda() { std::shared_ptr<TAtrac3BitStreamWriter> bitStreamWriter(new TAtrac3BitStreamWriter(Oma.get(), *Params.ConteinerParams, Params.BfuIdxConst)); - return [this, bitStreamWriter](TFloat* data, const TPCMEngine<TFloat>::ProcessMeta& meta) { + + struct TChannelData { + TChannelData() + : Specs(TAtrac3Data::NumSamples) + {} + + vector<float> Specs; + }; + + using TData = vector<TChannelData>; + auto buf = std::make_shared<TData>(2); + + return [this, bitStreamWriter, buf](float* data, const TPCMEngine::ProcessMeta& meta) { using TSce = TAtrac3BitStreamWriter::TSingleChannelElement; for (uint32_t channel = 0; channel < meta.Channels; channel++) { - TFloat src[NumSamples]; + float src[TAtrac3Data::NumSamples]; - for (size_t i = 0; i < NumSamples; ++i) { + for (size_t i = 0; i < TAtrac3Data::NumSamples; ++i) { src[i] = data[i * meta.Channels + channel] / 4.0; } { - TFloat* p[4] = {PcmBuffer.GetSecond(channel), PcmBuffer.GetSecond(channel+2), PcmBuffer.GetSecond(channel+4), PcmBuffer.GetSecond(channel+6)}; + float* p[4] = {PcmBuffer.GetSecond(channel), PcmBuffer.GetSecond(channel+2), PcmBuffer.GetSecond(channel+4), PcmBuffer.GetSecond(channel+6)}; AnalysisFilterBank[channel].Analysis(&src[0], p); } } @@ -310,27 +324,42 @@ TPCMEngine<TFloat>::TProcessLambda TAtrac3Encoder::GetLambda() } for (uint32_t channel = 0; channel < meta.Channels; channel++) { - vector<TFloat> specs(1024); + auto& specs = (*buf)[channel].Specs; TSce* sce = &SingleChannelElements[channel]; sce->SubbandInfo.Reset(); if (!Params.NoGainControll) { - TFloat* p[4] = {PcmBuffer.GetSecond(channel), PcmBuffer.GetSecond(channel+2), PcmBuffer.GetSecond(channel+4), PcmBuffer.GetSecond(channel+6)}; + float* p[4] = {PcmBuffer.GetSecond(channel), PcmBuffer.GetSecond(channel+2), PcmBuffer.GetSecond(channel+4), PcmBuffer.GetSecond(channel+6)}; CreateSubbandInfo(p, channel, &sce->SubbandInfo); //4 detectors per band } - TFloat* maxOverlapLevels = PrevPeak[channel]; + float* maxOverlapLevels = PrevPeak[channel]; { - TFloat* p[4] = {PcmBuffer.GetFirst(channel), PcmBuffer.GetFirst(channel+2), PcmBuffer.GetFirst(channel+4), PcmBuffer.GetFirst(channel+6)}; + float* p[4] = {PcmBuffer.GetFirst(channel), PcmBuffer.GetFirst(channel+2), PcmBuffer.GetFirst(channel+4), PcmBuffer.GetFirst(channel+6)}; Mdct(specs.data(), p, maxOverlapLevels, MakeGainModulatorArray(sce->SubbandInfo)); } - sce->Energy = CalcEnergy(specs); + float l = 0; + for (size_t i = 0; i < specs.size(); i++) { + float e = specs[i] * specs[i]; + l += e * LoudnessCurve[i]; + } + + sce->Loudness = l; //TBlockSize for ATRAC3 - 4 subband, all are long (no short window) sce->ScaledBlocks = Scaler.ScaleFrame(specs, TBlockSize()); + } + if (meta.Channels == 2 && !Params.ConteinerParams->Js) { + const TSce& sce0 = SingleChannelElements[0]; + const TSce& sce1 = SingleChannelElements[1]; + Loudness = TrackLoudness(Loudness, sce0.Loudness, sce1.Loudness); + } else { + // 1 channel or Js. In case of Js we do not use side channel to adjust loudness + const TSce& sce0 = SingleChannelElements[0]; + Loudness = TrackLoudness(Loudness, sce0.Loudness); } if (Params.ConteinerParams->Js && meta.Channels == 1) { @@ -341,9 +370,8 @@ TPCMEngine<TFloat>::TProcessLambda TAtrac3Encoder::GetLambda() SingleChannelElements[1].SubbandInfo.Info.resize(1); } - bitStreamWriter->WriteSoundUnit(SingleChannelElements); - - return TPCMEngine<TFloat>::EProcessResult::PROCESSED; + bitStreamWriter->WriteSoundUnit(SingleChannelElements, Loudness); + return TPCMEngine::EProcessResult::PROCESSED; }; } |