Skip to content

Commit de25dae

Browse files
committed
refactoring & replaced map with function based sampling rate finder.
Signed-off-by: Stavros Avramidis <stavros9899@gmail.com>
1 parent 11d5f7a commit de25dae

4 files changed

Lines changed: 61 additions & 66 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ project(MQA_identifier)
44
set(CMAKE_CXX_STANDARD 17)
55

66
if (NOT (MSVC))
7-
set(CMAKE_CXX_FLAGS "-O3 -Wall -static -ffast-math")
8-
7+
set(CMAKE_CXX_FLAGS "-O3 -march=native -Wall -static -static-libstdc++ -ffast-math")
98
else (NOT (MSVC))
109
set(CMAKE_CXX_FLAGS "/O2")
1110
STRING(REPLACE "/O2" "/Od" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
1211
endif ()
1312

14-
set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG")
15-
1613
find_library(FLAC++_LIBRARIES NAMES FLAC++ FLAC)
1714
find_library(OGG NAMES OGG)
1815

gui/CMakeLists.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
88
set(QT_USE_QTMAIN TRUE)
99

1010
if (NOT (MSVC))
11-
set(CMAKE_CXX_FLAGS "-O2 -Wall -static -ffast-math")
11+
set(CMAKE_CXX_FLAGS "-O2 -Wall -static -static-libstdc++ -static-libgcc")
1212

1313
else (NOT (MSVC))
1414
set(CMAKE_CXX_FLAGS "/O2")
@@ -24,9 +24,8 @@ elseif (APPLE)
2424
endif ()
2525

2626
find_package(Qt5Core REQUIRED)
27-
find_package(Qt5Gui REQUIRED)
2827
find_package(Qt5Widgets REQUIRED)
2928

3029

3130
add_executable(${PROJECT_NAME} ${GUI_TYPE} ${CMAKE_PARENT_LIST_FILE}/../main.cpp ${CMAKE_PARENT_LIST_FILE}/../mainwindow.cpp ${CMAKE_PARENT_LIST_FILE}/../mainwindow.ui)
32-
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
31+
target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::Core)

gui/mqa_id_gui.pro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
2323
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
2424

2525
CONFIG += c++11
26-
#CONFIG += static
26+
CONFIG += static
27+
CONFIG += static-runtime
2728

2829

2930
SOURCES += \

mqa_identifier.h

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,25 @@
1818

1919
#include <FLAC++/decoder.h>
2020

21-
const std::map<unsigned char, uint32_t> OriginalSampleRateTable = {
22-
/* MQA 's encoded value - sample rate in Hz */
23-
24-
/* 1x Sample Rate */
25-
{0b0000, 44100},
26-
{0b0001, 48000},
27-
/* 2x Sample Rate */
28-
{0b1000, 88200},
29-
{0b1001, 96000},
30-
/* 4x Sample Rate */
31-
{0b0100, 176400},
32-
{0b0101, 192000},
33-
/* 8x Sample Rate */
34-
{0b1100, 352800},
35-
{0b1101, 384000} /* ? */
36-
37-
/* ?? 16x Sample Rate ?? */
38-
/* 2 bits left - probably 705.6K and 786K
39-
* No recordings on those values so no worries
21+
22+
/**
23+
* Returns original Sample rate (in Hz) from waveform bytecode.
24+
* @param c 4bit bytecode
25+
* @return
26+
*/
27+
uint32_t OriginalSampleRateDecoder(unsigned c) {
28+
if (c > 0b1111u) throw std::logic_error("Invalid bytecode");
29+
/*
30+
* If LSB is 0 then base is 44100 else 48000
31+
* 3 MSB need to be rotated and raised to the power of 2 (so 1, 2, 4, 8, ...)
32+
* output is base * multiplier
4033
*/
41-
};
34+
const uint32_t base = (c & 1u) ? 48000 : 44100;
35+
36+
const uint32_t multiplier = 1u << (((c >> 3u) & 1u) | (((c >> 2u) & 1u) << 1u) | (((c >> 1u) & 1u) << 2u));
37+
38+
return base * multiplier;
39+
}
4240

4341

4442
class MQA_identifier {
@@ -50,9 +48,10 @@ class MQA_identifier {
5048
uint32_t bps = 0;
5149
FLAC__uint64 decoded_samples = 0;
5250
std::vector<std::array<const FLAC__int32, 2>> samples;
53-
std::string mqa_endoder;
51+
std::string mqa_encoder;
5452
uint32_t original_sample_rate = 0;
5553

54+
5655
explicit MyDecoder(std::string file) : FLAC::Decoder::File(), file_(std::move(file)) {};
5756

5857
::FLAC__StreamDecoderInitStatus decode();
@@ -78,6 +77,7 @@ class MQA_identifier {
7877
public:
7978
explicit MQA_identifier(std::string file) : file_(std::move(file)), decoder(file_), isMQA_(false) {}
8079

80+
8181
bool detect();
8282

8383
[[nodiscard]] std::string getMQA_encoder() const noexcept;
@@ -118,23 +118,19 @@ void MQA_identifier::MyDecoder::metadata_callback(const ::FLAC__StreamMetadata *
118118
const auto comment = reinterpret_cast<char *>(metadata->data.vorbis_comment.comments[i].entry);
119119

120120
if (std::strncmp("MQAENCODER", comment, 10) == 0)
121-
this->mqa_endoder =
121+
this->mqa_encoder =
122122
std::string(comment + 10, comment + metadata->data.vorbis_comment.comments[i].length);
123-
124-
else if (std::strncmp("ORIGINALSAMPLERATE", comment, 18) == 0)
125-
this->original_sample_rate = std::stoul(comment + 19);
126-
127-
else if (std::strncmp("MQASAMPLERATE", comment, 13) == 0)
128-
this->original_sample_rate = std::stoul(comment + 14);
129123
}
130124
}
131125

132126
}
133127

128+
134129
void MQA_identifier::MyDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status) {
135130
std::cerr << "Got error callback: " << FLAC__StreamDecoderErrorStatusString[status] << "\n";
136131
}
137132

133+
138134
::FLAC__StreamDecoderInitStatus MQA_identifier::MyDecoder::decode() {
139135
bool ok = true;
140136

@@ -155,6 +151,7 @@ ::FLAC__StreamDecoderInitStatus MQA_identifier::MyDecoder::decode() {
155151
while (this->decoded_samples < this->sample_rate * 3 /* read only 3 first seconds */ )
156152
ok = this->process_single();
157153

154+
158155
if (!ok) {
159156
std::cerr << "decoding FAILED\n";
160157
std::cerr << this->get_state().resolved_as_cstring(*this);
@@ -166,51 +163,52 @@ ::FLAC__StreamDecoderInitStatus MQA_identifier::MyDecoder::decode() {
166163
bool MQA_identifier::detect() {
167164
this->decoder.decode();
168165

169-
for (auto p = 0u; p < this->decoder.bps; p++) {
170-
uint64_t buffer = 0;
171-
for (const auto &s: this->decoder.samples) {
172-
buffer |=
173-
((static_cast<uint32_t>(s[0]) ^ static_cast<uint32_t>(s[1])) >> p) & 1u; //static_cast for clang-tidy
174-
if (buffer == 0xbe0498c88) { // MQA magic word
175-
this->isMQA_ = true;
176-
177-
// Get Original Sample Rate
178-
unsigned char orsf = 0;
179-
for (auto m = 3u; m < 7; m++) { // Skip 2 bits nd get next 4
180-
auto cur = *(&s + m);
181-
auto j = ((static_cast<uint32_t>(cur[0]) ^ static_cast<uint32_t>(cur[1])) >> p) & 1u;
182-
orsf |= j << (6u - m);
183-
}
184-
try {
185-
if (decoder.original_sample_rate != 0
186-
&& decoder.original_sample_rate != OriginalSampleRateTable.at(orsf))
187-
std::cerr << decoder.original_sample_rate << "\n";
188-
this->decoder.original_sample_rate = OriginalSampleRateTable.at(orsf);
189-
} catch (std::exception &e) {
190-
std::cerr << e.what() << "\n";
191-
}
192-
193-
// We are done return true
194-
return true;
195-
} else
196-
buffer = (buffer << 1u) & 0xFFFFFFFFFu;
197-
}
166+
uint64_t buffer = 0;
167+
const auto pos = (this->decoder.bps - 16u); // aim for 16th bit
168+
for (const auto &s: this->decoder.samples) {
169+
buffer |= ((static_cast<uint32_t>(s[0]) ^ static_cast<uint32_t>(s[1])) >> pos) & 1u; //cast for clang-tidy
170+
171+
if (buffer == 0xbe0498c88) { // MQA magic word
172+
this->isMQA_ = true;
173+
174+
// Get Original Sample Rate
175+
unsigned char orsf = 0;
176+
for (auto m = 3u; m < 7; m++) { // Skip 2 bits nd get next 4
177+
auto cur = *(&s + m);
178+
auto j =
179+
((static_cast<uint32_t>(cur[0]) ^ static_cast<uint32_t>(cur[1])) >> pos) & 1u;
180+
orsf |= j << (6u - m);
181+
}
182+
try {
183+
this->decoder.original_sample_rate = OriginalSampleRateDecoder(orsf);
184+
}
185+
catch (std::exception &e) { std::cerr << e.what() << "\n"; }
186+
// We are done return true
187+
return true;
188+
189+
} else
190+
buffer = (buffer << 1u) & 0xFFFFFFFFFu;
198191
}
192+
199193
return false;
200194
}
201195

196+
202197
std::string MQA_identifier::getMQA_encoder() const noexcept {
203-
return this->decoder.mqa_endoder;
198+
return this->decoder.mqa_encoder;
204199
}
205200

201+
206202
uint32_t MQA_identifier::originalSampleRate() const noexcept {
207203
return this->decoder.original_sample_rate;
208204
}
209205

206+
210207
bool MQA_identifier::isMQA() const noexcept {
211208
return this->isMQA_;
212209
}
213210

211+
214212
std::string MQA_identifier::filename() const noexcept {
215213
return this->file_;
216214
}

0 commit comments

Comments
 (0)