encoding settings

This commit is contained in:
Blue 2023-10-13 16:10:08 -03:00
parent 03e7f29d84
commit 5c3a4a592e
Signed by: blue
GPG Key ID: 9B203B252A63EE38
8 changed files with 148 additions and 22 deletions

View File

@ -1,7 +1,8 @@
# Changelog
## MLC 1.3.3 (UNRELEASED)
## MLC 1.3.3 (October 13, 2023)
- Regex to specify non-music files to copy
- Encoding settings (VBR/CBR, encoding quality, output quality)
## MLC 1.3.2 (October 10, 2023)
- A release purely for CI

View File

@ -51,3 +51,48 @@
# Allowed value are: [all, none] or regex without any additional syntax,
# for example: filesToCopy cover\.jpe?g
#filesToCopy all
# Encoding quality
# Sets up encoding quality (NOT OUTPUT QUALITY)
# The higher quality the slower the encoding process
# 0 is the highest quality and slowest process
# 9 is the lowest quality and the fastest process fastest
# Allowed values are: [0, 1, 2, ... 9]
#encodingQuality 0
# Output quality
# Sets up output quality
# The higher quality the less information is lonst in compression
# 0 is the highest possible quality for selected mode and type and results in the biggest file
# 9 is the lowest quality but results in the smalest file
# Allowed values are [0, 1, 2, ... 9]
# For the constant bitrate modes (CBR) the following table is valid
# Quality | MP3 |
# --------+-----+--
# 0 | 320 |
# --------+-----+--
# 1 | 288 |
# --------+-----+--
# 2 | 256 |
# --------+-----+--
# 3 | 224 |
# --------+-----+--
# 4 | 192 |
# --------+-----+--
# 5 | 160 |
# --------+-----+--
# 6 | 128 |
# --------+-----+--
# 7 | 96 |
# --------+-----+--
# 8 | 64 |
# --------+-----+--
# 9 | 32 |
#outputQuality 0
# Variable bitrate
# Switches on or off variable bitrate
# VBR files are usually smaller, but not supped to be worse
# in terms of quality. VBR files might be a bit more tricky for the player
# Allowedvalues are: [true, false]
#vbr true

View File

@ -12,6 +12,18 @@ constexpr std::string_view jpeg ("image/jpeg");
const std::map<std::string, std::string> textIdentificationReplacements({
{"PUBLISHER", "TPUB"}
});
constexpr std::array<int, 10> bitrates({
320,
288,
256,
224,
192,
160,
128,
96,
64,
32
});
FLACtoMP3::FLACtoMP3(Logger::Severity severity, uint8_t size) :
logger(severity),
@ -46,7 +58,7 @@ bool FLACtoMP3::run() {
if (pcmCounter > 0)
flush();
int nwrite = lame_encode_flush(encoder, outputBuffer, pcmSize * 2);
int nwrite = lame_encode_flush(encoder, outputBuffer, outputBufferSize);
fwrite((char*)outputBuffer, nwrite, 1, output);
@ -98,9 +110,21 @@ void FLACtoMP3::setOutputFile(const std::string& path) {
outPath = path;
lame_set_VBR(encoder, vbr_default);
lame_set_VBR_quality(encoder, 0);
lame_set_quality(encoder, 0);
}
void FLACtoMP3::setParameters(unsigned char encodingQuality, unsigned char outputQuality, bool vbr) {
if (vbr) {
logger.info("Encoding to VBR with quality " + std::to_string(outputQuality));
lame_set_VBR(encoder, vbr_default);
lame_set_VBR_quality(encoder, outputQuality);
} else {
int bitrate = bitrates[outputQuality];
logger.info("Encoding to CBR " + std::to_string(bitrate));
lame_set_VBR(encoder, vbr_off);
lame_set_brate(encoder, bitrate);
}
lame_set_quality(encoder, encodingQuality);
}
bool FLACtoMP3::initializeOutput() {
@ -306,7 +330,7 @@ bool FLACtoMP3::flush() {
nwrite = lame_encode_buffer_interleaved(
encoder,
pcm,
pcmCounter,
pcmCounter / 2,
outputBuffer,
outputBufferSize
);

View File

@ -8,6 +8,7 @@
#include <string>
#include <string_view>
#include <map>
#include <array>
#include <stdio.h>
#include "logger/accumulator.h"
@ -19,6 +20,7 @@ public:
void setInputFile(const std::string& path);
void setOutputFile(const std::string& path);
void setParameters(unsigned char encodingQuality, unsigned char outputQuality, bool vbr);
bool run();
std::list<Logger::Message> getHistory() const;

View File

@ -17,6 +17,9 @@ enum class Option {
destination,
parallel,
filesToCopy,
encodingQuality,
outputQuality,
vbr,
_optionsSize
};
@ -38,13 +41,19 @@ constexpr std::array<std::string_view, static_cast<int>(Option::_optionsSize)> o
"source",
"destination",
"parallel",
"filesToCopy"
"filesToCopy",
"encodingQuality",
"outputQuality",
"vbr"
});
constexpr std::array<std::string_view, Settings::_typesSize> types({
"mp3"
});
constexpr unsigned int maxQuality = 9;
constexpr unsigned int minQuality = 0;
bool is_space(char ch){
return std::isspace(static_cast<unsigned char>(ch));
}
@ -77,7 +86,10 @@ Settings::Settings(int argc, char ** argv):
logLevel(std::nullopt),
configPath(std::nullopt),
threads(std::nullopt),
nonMusic(std::nullopt)
nonMusic(std::nullopt),
encodingQuality(std::nullopt),
outputQuality(std::nullopt),
vbr(std::nullopt)
{
for (int i = 1; i < argc; ++i)
arguments.push_back(argv[i]);
@ -187,6 +199,27 @@ unsigned int Settings::getThreads() const {
return 0;
}
unsigned char Settings::getOutputQuality() const {
if (outputQuality.has_value())
return outputQuality.value();
else
return minQuality; //actually, it means max possible quality
}
unsigned char Settings::getEncodingQuality() const {
if (encodingQuality.has_value())
return encodingQuality.value();
else
return minQuality; //actually, it means max possible quality
}
bool Settings::getVBR() const {
if (vbr.has_value())
return vbr.value();
else
return true;
}
void Settings::strip(std::string& line) {
line.erase(line.begin(), std::find_if(line.begin(), line.end(), std::not_fn(is_space)));
line.erase(std::find_if(line.rbegin(), line.rend(), std::not_fn(is_space)).base(), line.end());
@ -280,6 +313,21 @@ void Settings::readConfigLine(const std::string& line) {
nonMusic = regex;
}
} break;
case Option::outputQuality: {
unsigned int value;
if (!outputQuality.has_value() && stream >> value)
outputQuality = std::clamp(value, minQuality, maxQuality);
} break;
case Option::encodingQuality: {
unsigned int value;
if (!encodingQuality.has_value() && stream >> value)
encodingQuality = std::clamp(value, minQuality, maxQuality);
} break;
case Option::vbr: {
bool value;
if (!vbr.has_value() && stream >> std::boolalpha >> value)
vbr = value;
} break;
default:
break;
}

View File

@ -40,6 +40,9 @@ public:
Action getAction() const;
unsigned int getThreads() const;
bool matchNonMusic(const std::string& fileName) const;
unsigned char getEncodingQuality() const;
unsigned char getOutputQuality() const;
bool getVBR() const;
bool readConfigFile();
void readConfigLine(const std::string& line);
@ -66,4 +69,7 @@ private:
std::optional<std::string> configPath;
std::optional<unsigned int> threads;
std::optional<std::regex> nonMusic;
std::optional<unsigned char> encodingQuality;
std::optional<unsigned char> outputQuality;
std::optional<bool> vbr;
};

View File

@ -119,14 +119,15 @@ unsigned int TaskManager::getCompleteTasks() const {
return completeTasks;
}
TaskManager::JobResult TaskManager::execute(const Job& job) {
TaskManager::JobResult TaskManager::execute(Job& job) {
switch (job.type) {
case Job::copy:
return copyJob(job, settings->getLogLevel());
return copyJob(job, settings);
case Job::convert:
switch (settings->getType()) {
case Settings::mp3:
return mp3Job(job, settings->getLogLevel());
job.destination.replace_extension("mp3");
return mp3Job(job, settings);
default:
break;
}
@ -162,19 +163,18 @@ void TaskManager::printResilt(const TaskManager::Job& job, const TaskManager::Jo
);
}
TaskManager::JobResult TaskManager::mp3Job(
const TaskManager::Job& job,
Logger::Severity logLevel)
{
FLACtoMP3 convertor(logLevel);
TaskManager::JobResult TaskManager::mp3Job(const TaskManager::Job& job, const std::shared_ptr<Settings>& settings) {
FLACtoMP3 convertor(settings->getLogLevel());
convertor.setInputFile(job.source);
convertor.setOutputFile(job.destination.string() + ".mp3");
convertor.setOutputFile(job.destination);
convertor.setParameters(settings->getEncodingQuality(), settings->getOutputQuality(), settings->getVBR());
bool result = convertor.run();
return {result, convertor.getHistory()};
}
TaskManager::JobResult TaskManager::copyJob(const TaskManager::Job& job, Logger::Severity logLevel) {
(void)(logLevel);
TaskManager::JobResult TaskManager::copyJob(const TaskManager::Job& job, const std::shared_ptr<Settings>& settings) {
(void)(settings);
bool success = std::filesystem::copy_file(
job.source,
job.destination,

View File

@ -35,10 +35,10 @@ public:
private:
void loop();
JobResult execute(const Job& job);
JobResult execute(Job& job);
void printResilt(const Job& job, const JobResult& result);
static JobResult mp3Job(const Job& job, Logger::Severity logLevel);
static JobResult copyJob(const Job& job, Logger::Severity logLevel);
static JobResult mp3Job(const Job& job, const std::shared_ptr<Settings>& settings);
static JobResult copyJob(const Job& job, const std::shared_ptr<Settings>& settings);
private:
std::shared_ptr<Settings> settings;