aboutsummaryrefslogtreecommitdiffstats
path: root/src/atrac/atrac3_bitstream.cpp
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2020-07-08 00:08:50 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2020-07-08 00:08:50 +0300
commit40d971c988fd9ccfb82cc6aaacc57ca1ad477d52 (patch)
tree66c4a8d87450e0318be6621d9315b90ec5229978 /src/atrac/atrac3_bitstream.cpp
parent240ca54145159a7aefc74ca8b23ed273e0ce2cbf (diff)
downloadatracdenc-40d971c988fd9ccfb82cc6aaacc57ca1ad477d52.tar.gz
[atrac3] Simple adaptive MS bitrate shift
Diffstat (limited to 'src/atrac/atrac3_bitstream.cpp')
-rw-r--r--src/atrac/atrac3_bitstream.cpp47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/atrac/atrac3_bitstream.cpp b/src/atrac/atrac3_bitstream.cpp
index 04209c2..df0130c 100644
--- a/src/atrac/atrac3_bitstream.cpp
+++ b/src/atrac/atrac3_bitstream.cpp
@@ -150,9 +150,10 @@ std::pair<uint8_t, uint32_t> TAtrac3BitStreamWriter::CalcSpecsBitsConsumption(co
//true - should reencode
//false - not need to
-static inline bool CheckBfus(uint8_t* numBfu, const vector<uint32_t>& precisionPerEachBlocks)
+static inline bool CheckBfus(uint16_t* numBfu, const vector<uint32_t>& precisionPerEachBlocks)
{
- uint8_t curLastBfu = *numBfu - 1;
+ assert(*numBfu);
+ uint16_t curLastBfu = *numBfu - 1;
//assert(curLastBfu < precisionPerEachBlocks.size());
assert(*numBfu == precisionPerEachBlocks.size());
if (precisionPerEachBlocks[curLastBfu] == 0) {
@@ -174,7 +175,17 @@ std::pair<uint8_t, vector<uint32_t>> TAtrac3BitStreamWriter::CreateAllocation(co
TFloat spread = AnalizeScaleFactorSpread(scaledBlocks);
- uint8_t numBfu = BfuIdxConst ? BfuIdxConst : 32;
+ uint16_t numBfu = BfuIdxConst ? BfuIdxConst : 32;
+
+ // Limit number of BFU if target bitrate is not enough
+ // 3 bits to write each bfu without data
+ // 5 bits we need for tonal header
+ // 32 * 3 + 5 = 101
+ if (targetBits < 101) {
+ uint16_t lim = (targetBits - 5) / 3;
+ numBfu = std::min(numBfu, lim);
+ }
+
vector<uint32_t> precisionPerEachBlocks(numBfu);
uint8_t mode;
bool cont = true;
@@ -188,14 +199,18 @@ std::pair<uint8_t, vector<uint32_t>> TAtrac3BitStreamWriter::CreateAllocation(co
auto consumption = CalcSpecsBitsConsumption(sce, tmpAlloc, mt);
auto bitsUsedByTonal = EncodeTonalComponents(sce, tmpAlloc, nullptr);
- //std::cerr << consumption.second << " |tonal: " << bitsUsedByTonal << std::endl;
+ //std::cerr << consumption.second << " |tonal: " << bitsUsedByTonal << " target: " << targetBits << " shift " << shift << " max | min " << maxShift << " " << minShift << std::endl;
consumption.second += bitsUsedByTonal;
if (consumption.second < targetBits) {
if (maxShift - minShift < 0.1) {
precisionPerEachBlocks = tmpAlloc;
mode = consumption.first;
- cont = !BfuIdxConst && CheckBfus(&numBfu, precisionPerEachBlocks);
+ if (numBfu > 1) {
+ cont = !BfuIdxConst && CheckBfus(&numBfu, precisionPerEachBlocks);
+ } else {
+ cont = false;
+ }
break;
}
maxShift = shift - 0.01;
@@ -467,19 +482,33 @@ void WriteJsParams(NBitStream::TBitStream* bs)
}
}
-static int32_t CalcMsBytesShift(uint32_t frameSz,
+// 0.5 - M only (mono)
+// 0.0 - Uncorrelated
+// -0.5 - S only
+static TFloat CalcMSRatio(TFloat mEnergy, TFloat sEnergy) {
+ TFloat total = sEnergy + mEnergy;
+ if (total > 0)
+ return mEnergy / total - 0.5;
+
+ // No signal - nothing to shift
+ return 0;
+}
+
+static int32_t CalcMSBytesShift(uint32_t frameSz,
const vector<TAtrac3BitStreamWriter::TSingleChannelElement>& elements,
const int32_t b[2])
{
const int32_t totalUsedBits = 0 - b[0] - b[1];
assert(totalUsedBits > 0);
- const uint32_t maxAllowedShift = frameSz / 2 - Div8Ceil(totalUsedBits);
+ const int32_t maxAllowedShift = (frameSz / 2 - Div8Ceil(totalUsedBits));
if (elements[1].ScaledBlocks.empty()) {
return maxAllowedShift;
} else {
- return std::min(frameSz / 3, maxAllowedShift);
+ TFloat ratio = CalcMSRatio(elements[0].Energy, elements[1].Energy);
+ //std::cerr << ratio << std::endl;
+ return std::max(std::min(ToInt(frameSz * ratio), maxAllowedShift), -maxAllowedShift);
}
}
@@ -533,7 +562,7 @@ void TAtrac3BitStreamWriter::WriteSoundUnit(const vector<TSingleChannelElement>&
int mt[2][MaxSpecs];
std::pair<uint8_t, vector<uint32_t>> allocations[2];
- const int32_t msBytesShift = Params.Js ? CalcMsBytesShift(Params.FrameSz, singleChannelElements, bitsToAlloc) : 0; // positive - gain to m, negative to s. Must be zero if no joint stereo mode
+ const int32_t msBytesShift = Params.Js ? CalcMSBytesShift(Params.FrameSz, singleChannelElements, bitsToAlloc) : 0; // positive - gain to m, negative to s. Must be zero if no joint stereo mode
bitsToAlloc[0] += 8 * (halfFrameSz + msBytesShift);
bitsToAlloc[1] += 8 * (halfFrameSz - msBytesShift);