Skip to content

Commit cfaa2cd

Browse files
committed
Dirty implementation of atrac3 encoder:
- no JS mode - constant quantiser for tonal components - gain controll implemented but produces some artifacts with real signals. - etc...
1 parent b4df8a7 commit cfaa2cd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3070
-406
lines changed

CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ endmacro(use_cxx11)
1212

1313
use_cxx11()
1414

15+
macro(use_c11)
16+
if (CMAKE_VERSION VERSION_LESS "3.1")
17+
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
18+
set (CMAKE_C_FLAGS "--std=gnu11 ${CMAKE_C_FLAGS}")
19+
endif ()
20+
else ()
21+
set (CMAKE_C_STANDARD 11)
22+
endif ()
23+
endmacro(use_c11)
24+
25+
use_c11()
26+
1527
add_subdirectory(3rd/gtest-1.7.0)
1628
add_subdirectory(src)
1729
add_subdirectory(test)

src/CMakeLists.txt

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
22

3+
#add_definitions( "-Wall -O2 -g -Rpass-analysis=loop-vectorize" )
4+
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -fno-omit-frame-pointer")
5+
36
add_definitions( "-Wall -O2 -g" )
47

58
project(atracdenc)
@@ -8,11 +11,30 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
811
INCLUDE(FindLibSndFile)
912

1013
include_directories(${LIBSNDFILE_INCLUDE_DIR})
14+
include_directories("oma/liboma/include")
1115

12-
set(SOURCE_LIB mdct/vorbis_impl/mdct.c)
13-
set(SOURCE_EXE main.cpp wav.cpp aea.cpp transient_detector.cpp atracdenc.cpp bitstream/bitstream.cpp atrac/atrac1.cpp atrac/atrac1_dequantiser.cpp atrac/atrac_scale.cpp atrac/atrac1_bitalloc.cpp)
16+
set(SOURCE_MDCT_LIB mdct/vorbis_impl/mdct.c)
17+
set(SOURCE_OMA_LIB oma/liboma/src/liboma.c)
18+
set(SOURCE_EXE
19+
main.cpp
20+
wav.cpp
21+
aea.cpp
22+
transient_detector.cpp
23+
atrac1denc.cpp
24+
bitstream/bitstream.cpp
25+
atrac/atrac1.cpp
26+
atrac/atrac1_dequantiser.cpp
27+
atrac/atrac_scale.cpp
28+
atrac/atrac_psy_common.cpp
29+
atrac/atrac1_bitalloc.cpp
30+
oma.cpp
31+
atrac3denc.cpp
32+
atrac/atrac3.cpp
33+
atrac/atrac3_bitstream.cpp
34+
)
1435

15-
add_library(mdct_impl STATIC ${SOURCE_LIB})
36+
add_library(mdct_impl STATIC ${SOURCE_MDCT_LIB})
37+
add_library(oma STATIC ${SOURCE_OMA_LIB})
1638
add_executable(atracdenc ${SOURCE_EXE})
17-
target_link_libraries(atracdenc mdct_impl ${SNDFILE_LIBRARIES})
39+
target_link_libraries(atracdenc mdct_impl oma ${SNDFILE_LIBRARIES})
1840

src/aea.h

-1
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,4 @@ class TAea : public IAtrac1IO {
4848
long long GetLengthInSamples() const override;
4949
};
5050

51-
typedef std::unique_ptr<IAtrac1IO> TAeaPtr;
5251

src/atrac/atrac1.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
#include "atrac1.h"
22

3-
constexpr uint32_t TAtrac1Data::BlocksPerBand[QMF_BANDS + 1];
4-
constexpr uint32_t TAtrac1Data::SpecsPerBlock[MAX_BFUS];
5-
constexpr uint32_t TAtrac1Data::SpecsStartLong[MAX_BFUS];
6-
constexpr uint32_t TAtrac1Data::SpecsStartShort[MAX_BFUS];
3+
namespace NAtracDEnc {
4+
namespace NAtrac1 {
5+
6+
constexpr uint32_t TAtrac1Data::BlocksPerBand[NumQMF + 1];
7+
constexpr uint32_t TAtrac1Data::SpecsPerBlock[MaxBfus];
8+
constexpr uint32_t TAtrac1Data::SpecsStartLong[MaxBfus];
9+
constexpr uint32_t TAtrac1Data::SpecsStartShort[MaxBfus];
710
constexpr uint32_t TAtrac1Data::BfuAmountTab[8];
811
double TAtrac1Data::ScaleTable[64] = {0};
912
double TAtrac1Data::SineWindow[32] = {0};
1013

14+
} //namespace NAtrac1
15+
} //namespace NAtracDEnc

src/atrac/atrac1.h

+38-35
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,52 @@
44
#include <map>
55
#include <math.h>
66
#include "../bitstream/bitstream.h"
7-
const int QMF_BANDS = 3;
8-
const int MAX_BFUS = 52;
7+
namespace NAtracDEnc {
8+
namespace NAtrac1 {
9+
10+
class TAtrac1EncodeSettings {
11+
public:
12+
enum class EWindowMode {
13+
EWM_NOTRANSIENT,
14+
EWM_AUTO
15+
};
16+
private:
17+
const uint32_t BfuIdxConst = 0;
18+
const bool FastBfuNumSearch = false;
19+
EWindowMode WindowMode = EWindowMode::EWM_AUTO;
20+
const uint32_t WindowMask = 0;
21+
public:
22+
TAtrac1EncodeSettings()
23+
{}
24+
TAtrac1EncodeSettings(uint32_t bfuIdxConst, bool fastBfuNumSearch, EWindowMode windowMode, uint32_t windowMask)
25+
: BfuIdxConst(bfuIdxConst)
26+
, FastBfuNumSearch(fastBfuNumSearch)
27+
, WindowMode(windowMode)
28+
, WindowMask(windowMask)
29+
{}
30+
uint32_t GetBfuIdxConst() const { return BfuIdxConst; }
31+
bool GetFastBfuNumSearch() const { return FastBfuNumSearch; }
32+
EWindowMode GetWindowMode() const {return WindowMode; }
33+
uint32_t GetWindowMask() const {return WindowMask; }
34+
};
935

1036
class TAtrac1Data {
37+
public:
38+
static constexpr uint8_t MaxBfus = 52;
39+
static constexpr uint8_t NumQMF = 3;
1140
protected:
12-
static constexpr uint32_t SpecsPerBlock[MAX_BFUS] = {
41+
static constexpr uint32_t SpecsPerBlock[MaxBfus] = {
1342
8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, // low band
1443
6, 6, 6, 6, 7, 7, 7, 7, 9, 9, 9, 9, 10, 10, 10, 10, // middle band
1544
12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20, 20, 20, 20 // high band
1645
};
17-
static constexpr uint32_t BlocksPerBand[QMF_BANDS + 1] = {0, 20, 36, 52};
18-
static constexpr uint32_t SpecsStartLong[MAX_BFUS] = {
46+
static constexpr uint32_t BlocksPerBand[NumQMF + 1] = {0, 20, 36, 52};
47+
static constexpr uint32_t SpecsStartLong[MaxBfus] = {
1948
0, 8, 16, 24, 32, 36, 40, 44, 48, 56, 64, 72, 80, 86, 92, 98, 104, 110, 116, 122,
2049
128, 134, 140, 146, 152, 159, 166, 173, 180, 189, 198, 207, 216, 226, 236, 246,
2150
256, 268, 280, 292, 304, 316, 328, 340, 352, 372, 392, 412, 432, 452, 472, 492,
2251
};
23-
static constexpr uint32_t SpecsStartShort[MAX_BFUS] = {
52+
static constexpr uint32_t SpecsStartShort[MaxBfus] = {
2453
0, 32, 64, 96, 8, 40, 72, 104, 12, 44, 76, 108, 20, 52, 84, 116, 26, 58, 90, 122,
2554
128, 160, 192, 224, 134, 166, 198, 230, 141, 173, 205, 237, 150, 182, 214, 246,
2655
256, 288, 320, 352, 384, 416, 448, 480, 268, 300, 332, 364, 396, 428, 460, 492
@@ -30,8 +59,6 @@ class TAtrac1Data {
3059
static const uint32_t BitsPerBfuAmountTabIdx = 3;
3160
static const uint32_t BitsPerIDWL = 4;
3261
static const uint32_t BitsPerIDSF = 6;
33-
static const uint32_t NumSamples = 512;
34-
static const uint8_t NumQMF = QMF_BANDS;
3562

3663
static double ScaleTable[64];
3764
static double SineWindow[32];
@@ -43,6 +70,7 @@ class TAtrac1Data {
4370
return 2;
4471
}
4572
public:
73+
static const uint32_t NumSamples = 512;
4674
TAtrac1Data() {
4775
if (ScaleTable[0] == 0) {
4876
for (uint32_t i = 0; i < 64; i++) {
@@ -57,30 +85,5 @@ class TAtrac1Data {
5785
}
5886
};
5987

60-
class TBlockSize {
61-
static std::array<int, QMF_BANDS> Parse(NBitStream::TBitStream* stream) {
62-
std::array<int,QMF_BANDS> tmp;
63-
tmp[0] = 2 - stream->Read(2);
64-
tmp[1] = 2 - stream->Read(2);
65-
tmp[2] = 3 - stream->Read(2);
66-
stream->Read(2); //skip unused 2 bits
67-
return tmp;
68-
}
69-
static std::array<int,QMF_BANDS> Create(bool lowShort, bool midShort, bool hiShort) {
70-
std::array<int,QMF_BANDS> tmp;
71-
tmp[0] = lowShort ? 2 : 0;
72-
tmp[1] = midShort ? 2 : 0;
73-
tmp[2] = hiShort ? 3 : 0;
74-
return tmp;
75-
}
76-
public:
77-
TBlockSize(NBitStream::TBitStream* stream)
78-
: LogCount(Parse(stream))
79-
{}
80-
TBlockSize(bool lowShort, bool midShort, bool hiShort)
81-
: LogCount(Create(lowShort, midShort, hiShort))
82-
{}
83-
const std::array<int,QMF_BANDS> LogCount;
84-
};
85-
86-
88+
} //namespace NAtrac1
89+
} //namespace NAtracDEnc

src/atrac/atrac1_bitalloc.cpp

+32-43
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,39 @@
11
#include "atrac1_bitalloc.h"
2+
#include "atrac_psy_common.h"
23
#include "atrac_scale.h"
34
#include "atrac1.h"
45
#include <math.h>
56
#include <cassert>
67
#include "../bitstream/bitstream.h"
8+
9+
namespace NAtracDEnc {
710
namespace NAtrac1 {
811

912
using std::vector;
1013
using std::cerr;
1114
using std::endl;
1215
using std::pair;
1316

14-
static const uint32_t FixedBitAllocTableLong[MAX_BFUS] = {
17+
static const uint32_t FixedBitAllocTableLong[TAtrac1BitStreamWriter::MaxBfus] = {
1518
7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6,
1619
6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4,
1720
4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 0, 0, 0
1821
};
1922

20-
static const uint32_t FixedBitAllocTableShort[MAX_BFUS] = {
23+
static const uint32_t FixedBitAllocTableShort[TAtrac1BitStreamWriter::MaxBfus] = {
2124
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2225
6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2326
4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0
2427
};
2528

26-
static const uint32_t BitBoostMask[MAX_BFUS] = {
29+
static const uint32_t BitBoostMask[TAtrac1BitStreamWriter::MaxBfus] = {
2730
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
2831
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
2932
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3033
};
3134

32-
//returns 1 for tone-like, 0 - noise-like
33-
static double AnalizeSpread(const std::vector<TScaledBlock>& scaledBlocks) {
34-
double s = 0.0;
35-
for (size_t i = 0; i < scaledBlocks.size(); ++i) {
36-
s += scaledBlocks[i].ScaleFactorIndex;
37-
}
38-
s /= scaledBlocks.size();
39-
double sigma = 0.0;
40-
double xxx = 0.0;
41-
for (size_t i = 0; i < scaledBlocks.size(); ++i) {
42-
xxx = (scaledBlocks[i].ScaleFactorIndex - s);
43-
xxx *= xxx;
44-
sigma += xxx;
45-
}
46-
sigma /= scaledBlocks.size();
47-
sigma = sqrt(sigma);
48-
if (sigma > 14.0)
49-
sigma = 14.0;
50-
return sigma/14.0;
51-
}
52-
5335
TBitsBooster::TBitsBooster() {
54-
for (uint32_t i = 0; i < MAX_BFUS; ++i) {
36+
for (uint32_t i = 0; i < MaxBfus; ++i) {
5537
if (BitBoostMask[i] == 0)
5638
continue;
5739
const uint32_t nBits = SpecsPerBlock[i];
@@ -68,15 +50,13 @@ uint32_t TBitsBooster::ApplyBoost(std::vector<uint32_t>* bitsPerEachBlock, uint3
6850
//the key too low
6951
if (maxIt == BitsBoostMap.begin())
7052
return surplus;
71-
//std::cout << "key: " << key << " min key: " << MinKey << " it pos: " << maxIt->first << endl;
7253

7354
while (surplus >= MinKey) {
7455
bool done = true;
7556
for (std::multimap<uint32_t, uint32_t>::iterator it = BitsBoostMap.begin(); it != maxIt; ++it) {
7657
const uint32_t curBits = it->first;
7758
const uint32_t curPos = it->second;
7859

79-
//std::cout << "key: " << key << " curBits: " << curBits << endl;
8060
assert(key >= curBits);
8161
if (curPos >= bitsPerEachBlock->size())
8262
break;
@@ -90,23 +70,25 @@ uint32_t TBitsBooster::ApplyBoost(std::vector<uint32_t>* bitsPerEachBlock, uint3
9070
(*bitsPerEachBlock)[curPos] += nBitsPerSpec;
9171
surplus -= curBits * nBitsPerSpec;
9272

93-
//std::cout << "added: " << curPos << " " << nBitsPerSpec << " got: " << (*bitsPerEachBlock)[curPos] << endl;
9473
done = false;
9574
}
9675
if (done)
9776
break;
9877
}
9978

100-
//std::cout << "boost: " << surplus << " was " << target - cur << endl;
10179
return surplus;
10280
}
10381

10482

105-
vector<uint32_t> TAtrac1SimpleBitAlloc::CalcBitsAllocation(const std::vector<TScaledBlock>& scaledBlocks, const uint32_t bfuNum, const double spread, const double shift, const TBlockSize& blockSize) {
83+
vector<uint32_t> TAtrac1SimpleBitAlloc::CalcBitsAllocation(const std::vector<TScaledBlock>& scaledBlocks,
84+
const uint32_t bfuNum,
85+
const TFloat spread,
86+
const TFloat shift,
87+
const TBlockSize& blockSize) {
10688
vector<uint32_t> bitsPerEachBlock(bfuNum);
10789
for (size_t i = 0; i < bitsPerEachBlock.size(); ++i) {
10890
const uint32_t fix = blockSize.LogCount[BfuToBand(i)] ? FixedBitAllocTableShort[i] : FixedBitAllocTableLong[i];
109-
int tmp = spread * ( (double)scaledBlocks[i].ScaleFactorIndex/3.2) + (1.0 - spread) * fix - shift;
91+
int tmp = spread * ( (TFloat)scaledBlocks[i].ScaleFactorIndex/3.2) + (1.0 - spread) * fix - shift;
11092
if (tmp > 16) {
11193
bitsPerEachBlock[i] = 16;
11294
} else if (tmp < 2) {
@@ -143,40 +125,43 @@ uint32_t TAtrac1SimpleBitAlloc::GetMaxUsedBfuId(const vector<uint32_t>& bitsPerE
143125
return idx;
144126
}
145127

146-
uint32_t TAtrac1SimpleBitAlloc::CheckBfuUsage(bool* changed, uint32_t curBfuId, const vector<uint32_t>& bitsPerEachBlock) {
128+
uint32_t TAtrac1SimpleBitAlloc::CheckBfuUsage(bool* changed,
129+
uint32_t curBfuId, const vector<uint32_t>& bitsPerEachBlock) {
147130
uint32_t usedBfuId = GetMaxUsedBfuId(bitsPerEachBlock);
148131
if (usedBfuId < curBfuId) {
149132
*changed = true;
150133
curBfuId = FastBfuNumSearch ? usedBfuId : (curBfuId - 1);
151134
}
152135
return curBfuId;
153136
}
137+
154138
uint32_t TAtrac1SimpleBitAlloc::Write(const std::vector<TScaledBlock>& scaledBlocks, const TBlockSize& blockSize) {
155139
uint32_t bfuIdx = BfuIdxConst ? BfuIdxConst - 1 : 7;
156140
bool autoBfu = !BfuIdxConst;
157-
double spread = AnalizeSpread(scaledBlocks);
141+
TFloat spread = AnalizeScaleFactorSpread(scaledBlocks);
158142

159143
vector<uint32_t> bitsPerEachBlock(BfuAmountTab[bfuIdx]);
160144
uint32_t targetBitsPerBfus;
161145
uint32_t curBitsPerBfus;
162146
for (;;) {
163147
bitsPerEachBlock.resize(BfuAmountTab[bfuIdx]);
164-
const uint32_t bitsAvaliablePerBfus = SoundUnitSize * 8 - BitsPerBfuAmountTabIdx - 32 - 2 - 3 - bitsPerEachBlock.size() * (BitsPerIDWL + BitsPerIDSF);
165-
double maxShift = 15;
166-
double minShift = -3;
167-
double shift = 3.0;
148+
const uint32_t bitsAvaliablePerBfus = SoundUnitSize * 8 - BitsPerBfuAmountTabIdx - 32 - 2 - 3 -
149+
bitsPerEachBlock.size() * (BitsPerIDWL + BitsPerIDSF);
150+
TFloat maxShift = 15;
151+
TFloat minShift = -3;
152+
TFloat shift = 3.0;
168153
const uint32_t maxBits = bitsAvaliablePerBfus;
169154
const uint32_t minBits = bitsAvaliablePerBfus - 110;
170155

171156
bool bfuNumChanged = false;
172157
for (;;) {
173-
const vector<uint32_t>& tmpAlloc = CalcBitsAllocation(scaledBlocks, BfuAmountTab[bfuIdx], spread, shift, blockSize);
158+
const vector<uint32_t>& tmpAlloc = CalcBitsAllocation(scaledBlocks, BfuAmountTab[bfuIdx],
159+
spread, shift, blockSize);
174160
uint32_t bitsUsed = 0;
175161
for (size_t i = 0; i < tmpAlloc.size(); i++) {
176162
bitsUsed += SpecsPerBlock[i] * tmpAlloc[i];
177163
}
178164

179-
//std::cout << spread << " bitsUsed: " << bitsUsed << " min " << minBits << " max " << maxBits << " " << maxShift << " " << minShift << " " << endl;
180165
if (bitsUsed < minBits) {
181166
if (maxShift - minShift < 0.1) {
182167
if (autoBfu) {
@@ -214,7 +199,10 @@ uint32_t TAtrac1SimpleBitAlloc::Write(const std::vector<TScaledBlock>& scaledBlo
214199
return BfuAmountTab[bfuIdx];
215200
}
216201

217-
void TAtrac1BitStreamWriter::WriteBitStream(const vector<uint32_t>& bitsPerEachBlock, const std::vector<TScaledBlock>& scaledBlocks, uint32_t bfuAmountIdx, const TBlockSize& blockSize) {
202+
void TAtrac1BitStreamWriter::WriteBitStream(const vector<uint32_t>& bitsPerEachBlock,
203+
const std::vector<TScaledBlock>& scaledBlocks,
204+
uint32_t bfuAmountIdx,
205+
const TBlockSize& blockSize) {
218206
NBitStream::TBitStream bitStream;
219207
size_t bitUsed = 0;
220208
if (bfuAmountIdx >= (1 << BitsPerBfuAmountTabIdx)) {
@@ -252,8 +240,8 @@ void TAtrac1BitStreamWriter::WriteBitStream(const vector<uint32_t>& bitsPerEachB
252240
if (wordLength == 0 || wordLength == 1)
253241
continue;
254242

255-
const double multiple = ((1 << (wordLength - 1)) - 1);
256-
for (const double val : scaledBlocks[i].Values) {
243+
const TFloat multiple = ((1 << (wordLength - 1)) - 1);
244+
for (const TFloat val : scaledBlocks[i].Values) {
257245
const int tmp = round(val * multiple);
258246
const uint32_t testwl = bitsPerEachBlock[i] ? (bitsPerEachBlock[i] - 1) : 0;
259247
const uint32_t a = !!testwl + testwl;
@@ -280,4 +268,5 @@ void TAtrac1BitStreamWriter::WriteBitStream(const vector<uint32_t>& bitsPerEachB
280268
Container->WriteFrame(bitStream.GetBytes());
281269
}
282270

283-
}
271+
} //namespace NAtrac1
272+
} //namespace NAtracDEnc

0 commit comments

Comments
 (0)