diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2016-03-13 13:20:27 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2016-03-13 13:20:27 +0300 |
commit | 3d296a72ef26b6dc48224428a661168faeff2c05 (patch) | |
tree | d6ebdf3a89d71c7b052bc0048ea4e3f4e75e8b79 | |
parent | ae7ffde2740b9f7108e521be050d690360099f7e (diff) | |
download | atracdenc-3d296a72ef26b6dc48224428a661168faeff2c05.tar.gz |
auto choice CLC/VLC mode.
-rw-r--r-- | src/atrac/atrac3.h | 1 | ||||
-rw-r--r-- | src/atrac/atrac3_bitstream.cpp | 71 | ||||
-rw-r--r-- | src/atrac/atrac3_bitstream.h | 6 |
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 |