aboutsummaryrefslogtreecommitdiffstats
path: root/src/atrac1denc.cpp
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2024-12-24 22:59:03 +0100
committerDaniil Cherednik <dan.cherednik@gmail.com>2024-12-24 22:59:03 +0100
commitbddbeb98b3db8d435de6b2d10269640121475538 (patch)
tree1a791f5dd49b94ead503b9b77c6b9277f2701a89 /src/atrac1denc.cpp
parentc73a0e24a0d5c510a65efbe5c2fbc7fd39a3c003 (diff)
parent74d6e04c21bddd435bd74c34dbe027b883772a76 (diff)
downloadatracdenc-bddbeb98b3db8d435de6b2d10269640121475538.tar.gz
Merge branch 'master' into at3plus-dev
Diffstat (limited to 'src/atrac1denc.cpp')
-rw-r--r--src/atrac1denc.cpp125
1 files changed, 81 insertions, 44 deletions
diff --git a/src/atrac1denc.cpp b/src/atrac1denc.cpp
index 48f1864..27940bd 100644
--- a/src/atrac1denc.cpp
+++ b/src/atrac1denc.cpp
@@ -24,6 +24,7 @@
#include "atrac/atrac1_dequantiser.h"
#include "atrac/atrac1_qmf.h"
#include "atrac/atrac1_bitalloc.h"
+#include "atrac/atrac_psy_common.h"
#include "util.h"
namespace NAtracDEnc {
@@ -35,6 +36,7 @@ using std::vector;
TAtrac1Encoder::TAtrac1Encoder(TCompressedOutputPtr&& aea, TAtrac1EncodeSettings&& settings)
: Aea(std::move(aea))
, Settings(std::move(settings))
+ , LoudnessCurve(CreateLoudnessCurve(TAtrac1Data::NumSamples))
{
}
@@ -43,8 +45,8 @@ TAtrac1Decoder::TAtrac1Decoder(TCompressedInputPtr&& aea)
{
}
-static void vector_fmul_window(TFloat *dst, const TFloat *src0,
- const TFloat *src1, const TFloat *win, int len)
+static void vector_fmul_window(float *dst, const float *src0,
+ const float *src1, const float *win, int len)
{
int i, j;
@@ -53,36 +55,36 @@ static void vector_fmul_window(TFloat *dst, const TFloat *src0,
src0 += len;
for (i = -len, j = len - 1; i < 0; i++, j--) {
- TFloat s0 = src0[i];
- TFloat s1 = src1[j];
- TFloat wi = win[i];
- TFloat wj = win[j];
+ float s0 = src0[i];
+ float s1 = src1[j];
+ float wi = win[i];
+ float wj = win[j];
dst[i] = s0 * wj - s1 * wi;
dst[j] = s0 * wi + s1 * wj;
}
}
-void TAtrac1MDCT::Mdct(TFloat Specs[512], TFloat* low, TFloat* mid, TFloat* hi, const TBlockSize& blockSize) {
+void TAtrac1MDCT::Mdct(float Specs[512], float* low, float* mid, float* hi, const TBlockSize& blockSize) {
uint32_t pos = 0;
- for (uint32_t band = 0; band < NumQMF; band++) {
+ for (uint32_t band = 0; band < TAtrac1Data::NumQMF; band++) {
const uint32_t numMdctBlocks = 1 << blockSize.LogCount[band];
- TFloat* srcBuf = (band == 0) ? low : (band == 1) ? mid : hi;
- uint32_t bufSz = (band == 2) ? 256 : 128;
+ float* srcBuf = (band == 0) ? low : (band == 1) ? mid : hi;
+ uint32_t bufSz = (band == 2) ? 256 : 128;
const uint32_t blockSz = (numMdctBlocks == 1) ? bufSz : 32;
uint32_t winStart = (numMdctBlocks == 1) ? ((band == 2) ? 112 : 48) : 0;
//compensate level for 3rd band in case of short window
- const TFloat multiple = (numMdctBlocks != 1 && band == 2) ? 2.0 : 1.0;
- vector<TFloat> tmp(512);
+ const float multiple = (numMdctBlocks != 1 && band == 2) ? 2.0 : 1.0;
+ vector<float> tmp(512);
uint32_t blockPos = 0;
for (size_t k = 0; k < numMdctBlocks; ++k) {
- memcpy(&tmp[winStart], &srcBuf[bufSz], 32 * sizeof(TFloat));
+ memcpy(&tmp[winStart], &srcBuf[bufSz], 32 * sizeof(float));
for (size_t i = 0; i < 32; i++) {
srcBuf[bufSz + i] = TAtrac1Data::SineWindow[i] * srcBuf[blockPos + blockSz - 32 + i];
srcBuf[blockPos + blockSz - 32 + i] = TAtrac1Data::SineWindow[31 - i] * srcBuf[blockPos + blockSz - 32 + i];
}
- memcpy(&tmp[winStart+32], &srcBuf[blockPos], blockSz * sizeof(TFloat));
- const vector<TFloat>& sp = (numMdctBlocks == 1) ? ((band == 2) ? Mdct512(&tmp[0]) : Mdct256(&tmp[0])) : Mdct64(&tmp[0]);
+ memcpy(&tmp[winStart+32], &srcBuf[blockPos], blockSz * sizeof(float));
+ const vector<float>& sp = (numMdctBlocks == 1) ? ((band == 2) ? Mdct512(&tmp[0]) : Mdct256(&tmp[0])) : Mdct64(&tmp[0]);
for (size_t i = 0; i < sp.size(); i++) {
Specs[blockPos + pos + i] = sp[i] * multiple;
}
@@ -93,25 +95,25 @@ void TAtrac1MDCT::Mdct(TFloat Specs[512], TFloat* low, TFloat* mid, TFloat* hi,
blockPos += 32;
}
pos += bufSz;
- }
+ }
}
-void TAtrac1MDCT::IMdct(TFloat Specs[512], const TBlockSize& mode, TFloat* low, TFloat* mid, TFloat* hi) {
+void TAtrac1MDCT::IMdct(float Specs[512], const TBlockSize& mode, float* low, float* mid, float* hi) {
uint32_t pos = 0;
- for (size_t band = 0; band < NumQMF; band++) {
+ for (size_t band = 0; band < TAtrac1Data::NumQMF; band++) {
const uint32_t numMdctBlocks = 1 << mode.LogCount[band];
const uint32_t bufSz = (band == 2) ? 256 : 128;
const uint32_t blockSz = (numMdctBlocks == 1) ? bufSz : 32;
uint32_t start = 0;
- TFloat* dstBuf = (band == 0) ? low : (band == 1) ? mid : hi;
+ float* dstBuf = (band == 0) ? low : (band == 1) ? mid : hi;
- vector<TFloat> invBuf(512);
- TFloat* prevBuf = &dstBuf[bufSz * 2 - 16];
+ vector<float> invBuf(512);
+ float* prevBuf = &dstBuf[bufSz * 2 - 16];
for (uint32_t block = 0; block < numMdctBlocks; block++) {
if (band) {
SwapArray(&Specs[pos], blockSz);
}
- vector<TFloat> inv = (numMdctBlocks != 1) ? Midct64(&Specs[pos]) : (bufSz == 128) ? Midct256(&Specs[pos]) : Midct512(&Specs[pos]);
+ vector<float> inv = (numMdctBlocks != 1) ? Midct64(&Specs[pos]) : (bufSz == 128) ? Midct256(&Specs[pos]) : Midct512(&Specs[pos]);
for (size_t i = 0; i < (inv.size()/2); i++) {
invBuf[start+i] = inv[i + inv.size()/4];
}
@@ -123,7 +125,7 @@ void TAtrac1MDCT::IMdct(TFloat Specs[512], const TBlockSize& mode, TFloat* low,
pos += blockSz;
}
if (numMdctBlocks == 1)
- memcpy(dstBuf + 32, &invBuf[16], ((band == 2) ? 240 : 112) * sizeof(TFloat));
+ memcpy(dstBuf + 32, &invBuf[16], ((band == 2) ? 240 : 112) * sizeof(float));
for (size_t j = 0; j < 16; j++) {
dstBuf[bufSz*2 - 16 + j] = invBuf[bufSz - 16 + j];
@@ -131,9 +133,9 @@ void TAtrac1MDCT::IMdct(TFloat Specs[512], const TBlockSize& mode, TFloat* low,
}
}
-TPCMEngine<TFloat>::TProcessLambda TAtrac1Decoder::GetLambda() {
- return [this](TFloat* data, const TPCMEngine<TFloat>::ProcessMeta& /*meta*/) {
- TFloat sum[512];
+TPCMEngine::TProcessLambda TAtrac1Decoder::GetLambda() {
+ return [this](float* data, const TPCMEngine::ProcessMeta& /*meta*/) {
+ float sum[512];
const uint32_t srcChannels = Aea->GetChannelNum();
for (uint32_t channel = 0; channel < srcChannels; channel++) {
std::unique_ptr<ICompressedIO::TFrame> frame(Aea->ReadFrame());
@@ -142,13 +144,13 @@ TPCMEngine<TFloat>::TProcessLambda TAtrac1Decoder::GetLambda() {
TBlockSize mode(&bitstream);
TAtrac1Dequantiser dequantiser;
- vector<TFloat> specs;
+ vector<float> specs;
specs.resize(512);;
dequantiser.Dequant(&bitstream, mode, &specs[0]);
IMdct(&specs[0], mode, &PcmBufLow[channel][0], &PcmBufMid[channel][0], &PcmBufHi[channel][0]);
SynthesisFilterBank[channel].Synthesis(&sum[0], &PcmBufLow[channel][0], &PcmBufMid[channel][0], &PcmBufHi[channel][0]);
- for (size_t i = 0; i < NumSamples; ++i) {
+ for (size_t i = 0; i < TAtrac1Data::NumSamples; ++i) {
if (sum[i] > PcmValueMax)
sum[i] = PcmValueMax;
if (sum[i] < PcmValueMin)
@@ -157,36 +159,52 @@ TPCMEngine<TFloat>::TProcessLambda TAtrac1Decoder::GetLambda() {
data[i * srcChannels + channel] = sum[i];
}
}
- return TPCMEngine<TFloat>::EProcessResult::PROCESSED;
+ return TPCMEngine::EProcessResult::PROCESSED;
};
}
-TPCMEngine<TFloat>::TProcessLambda TAtrac1Encoder::GetLambda() {
+TPCMEngine::TProcessLambda TAtrac1Encoder::GetLambda() {
const uint32_t srcChannels = Aea->GetChannelNum();
- vector<IAtrac1BitAlloc*> bitAlloc;
- for (size_t i = 0; i < srcChannels; i++) {
- bitAlloc.push_back(new TAtrac1SimpleBitAlloc(Aea.get(), Settings.GetBfuIdxConst(), Settings.GetFastBfuNumSearch()));
+ vector<IAtrac1BitAlloc*> bitAlloc(srcChannels);
+
+ for (auto& x : bitAlloc) {
+ x = new TAtrac1SimpleBitAlloc(Aea.get(), Settings.GetBfuIdxConst(), Settings.GetFastBfuNumSearch());
}
- return [this, srcChannels, bitAlloc](TFloat* data, const TPCMEngine<TFloat>::ProcessMeta& /*meta*/) {
+ struct TChannelData {
+ TChannelData()
+ : Specs(TAtrac1Data::NumSamples)
+ , Loudness(0.0)
+ {}
+
+ vector<float> Specs;
+ float Loudness;
+ };
+
+ using TData = vector<TChannelData>;
+ auto buf = std::make_shared<TData>(srcChannels);
+
+ return [this, srcChannels, bitAlloc, buf](float* data, const TPCMEngine::ProcessMeta& /*meta*/) {
+ TBlockSize blockSz[2];
+
+ uint32_t windowMasks[2] = {0};
for (uint32_t channel = 0; channel < srcChannels; channel++) {
- TFloat src[NumSamples];
- vector<TFloat> specs(512);
- for (size_t i = 0; i < NumSamples; ++i) {
+ float src[TAtrac1Data::NumSamples];
+ for (size_t i = 0; i < TAtrac1Data::NumSamples; ++i) {
src[i] = data[i * srcChannels + channel];
}
AnalysisFilterBank[channel].Analysis(&src[0], &PcmBufLow[channel][0], &PcmBufMid[channel][0], &PcmBufHi[channel][0]);
- uint32_t windowMask = 0;
+ uint32_t& windowMask = windowMasks[channel];
if (Settings.GetWindowMode() == TAtrac1EncodeSettings::EWindowMode::EWM_AUTO) {
windowMask |= (uint32_t)TransientDetectors.GetDetector(channel, 0).Detect(&PcmBufLow[channel][0]);
- const vector<TFloat>& invMid = InvertSpectr<128>(&PcmBufMid[channel][0]);
+ const vector<float>& invMid = InvertSpectr<128>(&PcmBufMid[channel][0]);
windowMask |= (uint32_t)TransientDetectors.GetDetector(channel, 1).Detect(&invMid[0]) << 1;
- const vector<TFloat>& invHi = InvertSpectr<256>(&PcmBufHi[channel][0]);
+ const vector<float>& invHi = InvertSpectr<256>(&PcmBufHi[channel][0]);
windowMask |= (uint32_t)TransientDetectors.GetDetector(channel, 2).Detect(&invHi[0]) << 2;
//std::cout << "trans: " << windowMask << std::endl;
@@ -194,13 +212,32 @@ TPCMEngine<TFloat>::TProcessLambda TAtrac1Encoder::GetLambda() {
//no transient detection, use given mask
windowMask = Settings.GetWindowMask();
}
- const TBlockSize blockSize(windowMask & 0x1, windowMask & 0x2, windowMask & 0x4); //low, mid, hi
- Mdct(&specs[0], &PcmBufLow[channel][0], &PcmBufMid[channel][0], &PcmBufHi[channel][0], blockSize);
- bitAlloc[channel]->Write(Scaler.ScaleFrame(specs, blockSize), blockSize);
+ blockSz[channel] = TBlockSize(windowMask & 0x1, windowMask & 0x2, windowMask & 0x4); //low, mid, hi
+
+ auto& specs = (*buf)[channel].Specs;
+
+ Mdct(&specs[0], &PcmBufLow[channel][0], &PcmBufMid[channel][0], &PcmBufHi[channel][0], blockSz[channel]);
+
+ float l = 0.0;
+ for (size_t i = 0; i < specs.size(); i++) {
+ float e = specs[i] * specs[i];
+ l += e * LoudnessCurve[i];
+ }
+ (*buf)[channel].Loudness = l;
+ }
+
+ if (srcChannels == 2 && windowMasks[0] == 0 && windowMasks[1] == 0) {
+ Loudness = TrackLoudness(Loudness, (*buf)[0].Loudness, (*buf)[1].Loudness);
+ } else if (windowMasks[0] == 0) {
+ Loudness = TrackLoudness(Loudness, (*buf)[0].Loudness);
+ }
+
+ for (uint32_t channel = 0; channel < srcChannels; channel++) {
+ bitAlloc[channel]->Write(Scaler.ScaleFrame((*buf)[channel].Specs, blockSz[channel]), blockSz[channel], Loudness / LoudFactor);
}
- return TPCMEngine<TFloat>::EProcessResult::PROCESSED;
+ return TPCMEngine::EProcessResult::PROCESSED;
};
}