aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2016-03-13 13:20:27 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2016-07-17 20:26:30 +0300
commit23d9f7d44612fc51064f9449e36e5a9c103d867c (patch)
treee44c21313c6d69ae69c234a7efc48cf4687f3a05
parent59818683fe2930ea4a7f898f43f47db94f437cc9 (diff)
downloadatracdenc-23d9f7d44612fc51064f9449e36e5a9c103d867c.tar.gz
auto choice CLC/VLC mode.
-rw-r--r--src/atrac/atrac3.h1
-rw-r--r--src/atrac/atrac3_bitstream.cpp71
-rw-r--r--src/atrac/atrac3_bitstream.h6
3 files changed, 57 insertions, 21 deletions
diff --git a/src/atrac/atrac3.h b/src/atrac/atrac3.h
index 01c8ae0..476d0f0 100644
--- a/src/atrac/atrac3.h
+++ b/src/atrac/atrac3.h
@@ -52,6 +52,7 @@ protected:
static constexpr uint32_t const * const SpecsStartLong = &BlockSizeTab[0];
static constexpr uint32_t ClcLengthTab[8] = { 0, 4, 3, 3, 4, 4, 5, 6 };
static const int NumQMF = 4;
+ static const uint32_t MAX_SPECS = 1024;
static constexpr uint32_t BlocksPerBand[NumQMF + 1] = {0, 18, 26, 30, 32};
static constexpr uint32_t SpecsPerBlock[33] = {
diff --git a/src/atrac/atrac3_bitstream.cpp b/src/atrac/atrac3_bitstream.cpp
index 3612afb..395bb1c 100644
--- a/src/atrac/atrac3_bitstream.cpp
+++ b/src/atrac/atrac3_bitstream.cpp
@@ -9,8 +9,11 @@
using NAtracDEnc::TScaledBlock;
using std::vector;
-void TAtrac3BitStreamWriter::CLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream) {
- uint32_t numBits = ClcLengthTab[selector];
+uint32_t TAtrac3BitStreamWriter::CLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream) {
+ const uint32_t numBits = ClcLengthTab[selector];
+ const uint32_t bitsUsed = (selector > 1) ? numBits * blockSize : numBits * blockSize / 2;
+ if (!bitStream)
+ return bitsUsed;
if (selector > 1) {
for (uint32_t i = 0; i < blockSize; ++i) {
bitStream->Write(NBitStream::MakeSign(mantissas[i], numBits), numBits);
@@ -23,11 +26,13 @@ void TAtrac3BitStreamWriter::CLCEnc(const uint32_t selector, const int mantissas
bitStream->Write(code, numBits);
}
}
+ return bitsUsed;
}
-void TAtrac3BitStreamWriter::VLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream) {
+uint32_t TAtrac3BitStreamWriter::VLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream) {
const THuffEntry* huffTable = HuffTables[selector - 1].Table;
const uint8_t tableSz = HuffTables[selector - 1].Sz;
+ uint32_t bitsUsed = 0;
if (selector > 1) {
for (uint32_t i = 0; i < blockSize; ++i) {
int m = mantissas[i];
@@ -36,8 +41,9 @@ void TAtrac3BitStreamWriter::VLCEnc(const uint32_t selector, const int mantissas
huffS -= 1;
assert(huffS < 256);
assert(huffS < tableSz);
- std::cout << "m: " << m << "huff: " << huffS << std::endl;
- bitStream->Write(huffTable[huffS].Code, huffTable[huffS].Bits);
+ bitsUsed += huffTable[huffS].Bits;
+ if (bitStream)
+ bitStream->Write(huffTable[huffS].Code, huffTable[huffS].Bits);
}
} else {
assert(tableSz == 9);
@@ -45,18 +51,52 @@ void TAtrac3BitStreamWriter::VLCEnc(const uint32_t selector, const int mantissas
const int ma = mantissas[i * 2];
const int mb = mantissas[i * 2 + 1];
const uint32_t huffS = MantissasToVlcIndex(ma, mb);
- bitStream->Write(huffTable[huffS].Code, huffTable[huffS].Bits);
+ bitsUsed += huffTable[huffS].Bits;
+ if (bitStream)
+ bitStream->Write(huffTable[huffS].Code, huffTable[huffS].Bits);
}
}
+ return bitsUsed;
+}
+std::pair<uint8_t, uint32_t> TAtrac3BitStreamWriter::CalcSpecsBitsConsumption(const vector<TScaledBlock>& scaledBlocks, const vector<uint32_t>& precisionPerEachBlocks, int* mantisas) {
+ uint32_t bitsUsed = 5 + 1; //numBlocks + codingMode
+ const uint32_t numBlocks = precisionPerEachBlocks.size();
+ bitsUsed += numBlocks * 3; //used VLC or CLC table (precision)
+
+ auto lambda = [=](bool clcMode, bool calcMant) {
+ uint32_t bits = 0;
+ for (uint32_t i = 0; i < numBlocks; ++i) {
+ if (precisionPerEachBlocks[i] == 0)
+ continue;
+ bits += 6; //sfi
+ const uint32_t first = BlockSizeTab[i];
+ const uint32_t last = BlockSizeTab[i+1];
+ const uint32_t blockSize = last - first;
+ const double mul = MaxQuant[std::min(precisionPerEachBlocks[i], (uint32_t)7)];
+ if (calcMant) {
+ for (uint32_t j = 0, f = first; f < last; f++, j++) {
+ mantisas[f] = round(scaledBlocks[i].Values[j] * mul);
+ }
+ }
+ bits += clcMode ? CLCEnc(precisionPerEachBlocks[i], mantisas + first, blockSize, nullptr) :
+ VLCEnc(precisionPerEachBlocks[i], mantisas + first, blockSize, nullptr);
+ }
+ return bits;
+ };
+ const uint32_t clcBits = lambda(true, true);
+ const uint32_t vlcBits = lambda(false, false);
+ bool mode = clcBits <= vlcBits;
+ //std::cout << "mode: " << mode << " " << clcBits << " " <<vlcBits << std::endl;
+ return std::make_pair(mode, bitsUsed + (mode ? clcBits : vlcBits));
}
void TAtrac3BitStreamWriter::EncodeSpecs(const vector<TScaledBlock>& scaledBlocks, const vector<uint32_t>& precisionPerEachBlocks, NBitStream::TBitStream* bitStream) {
const uint32_t numBlocks = precisionPerEachBlocks.size(); //number of blocks to save
- const uint32_t codingMode = 0;//1; //0 - VLC, 1 - CLC
- int mantisas[MAXSPECPERBLOCK];
+ int mt[MAX_SPECS];
+ const auto consumption = CalcSpecsBitsConsumption(scaledBlocks, precisionPerEachBlocks, mt);
+ const uint32_t codingMode = consumption.first;//0 - VLC, 1 - CLC
assert(numBlocks <= 32);
bitStream->Write(numBlocks-1, 5);
bitStream->Write(codingMode, 1);
-
for (uint32_t i = 0; i < numBlocks; ++i) {
uint32_t val = precisionPerEachBlocks[i]; //coding table used (VLC) or number of bits used (CLC)
bitStream->Write(val, 3);
@@ -70,23 +110,16 @@ void TAtrac3BitStreamWriter::EncodeSpecs(const vector<TScaledBlock>& scaledBlock
if (precisionPerEachBlocks[i] == 0)
continue;
- uint32_t first = BlockSizeTab[i];
+ const uint32_t first = BlockSizeTab[i];
const uint32_t last = BlockSizeTab[i+1];
const uint32_t blockSize = last - first;
- const double mul = MaxQuant[std::min(precisionPerEachBlocks[i], (uint32_t)7)];
-
- for (uint32_t j = 0; first < last; first++, j++) {
- mantisas[j] = round(scaledBlocks[i].Values[j] * mul);
- }
if (codingMode == 1) {
- CLCEnc(precisionPerEachBlocks[i], mantisas, blockSize, bitStream);
+ CLCEnc(precisionPerEachBlocks[i], mt + first, blockSize, bitStream);
} else {
- VLCEnc(precisionPerEachBlocks[i], mantisas, blockSize, bitStream);
+ VLCEnc(precisionPerEachBlocks[i], mt + first, blockSize, bitStream);
}
}
-
-
}
void TAtrac3BitStreamWriter::WriteSoundUnit(const TAtrac3SubbandInfo& subbandInfo, const vector<TScaledBlock>& scaledBlocks) {
diff --git a/src/atrac/atrac3_bitstream.h b/src/atrac/atrac3_bitstream.h
index 8a63d01..af9763c 100644
--- a/src/atrac/atrac3_bitstream.h
+++ b/src/atrac/atrac3_bitstream.h
@@ -6,6 +6,7 @@
#include "../atrac/atrac1.h"
#include "atrac_scale.h"
#include <vector>
+#include <utility>
static const uint32_t MAXSPECPERBLOCK = 128;
@@ -13,8 +14,9 @@ class TAtrac3BitStreamWriter : public virtual TAtrac3Data {
TOma* Container;
const TContainerParams Params;
std::vector<char> OutBuffer;
- void CLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream);
- void VLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream);
+ uint32_t CLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream);
+ uint32_t VLCEnc(const uint32_t selector, const int mantissas[MAXSPECPERBLOCK], const uint32_t blockSize, NBitStream::TBitStream* bitStream);
+ std::pair<uint8_t, uint32_t> CalcSpecsBitsConsumption(const std::vector<NAtracDEnc::TScaledBlock>& scaledBlocks, const std::vector<uint32_t>& precisionPerEachBlocks, int* mantisas);
void EncodeSpecs(const std::vector<NAtracDEnc::TScaledBlock>& scaledBlocks, const std::vector<uint32_t>& bitsPerEachBlock, NBitStream::TBitStream* bitStream);
public:
TAtrac3BitStreamWriter(TOma* container, const TContainerParams& params) //no mono mode for atrac3