diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2016-03-13 09:49:33 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2016-09-02 21:21:28 +0300 |
commit | cfaa2cd39b7256a868a4f5cd83aac207df6bd1b3 (patch) | |
tree | 75efff26584e046566d17cd308d45b6b0fd5abfc /src/main.cpp | |
parent | b4df8a7c2dd12eea27c8cc52bd52a1bb8c00943f (diff) | |
download | atracdenc-cfaa2cd39b7256a868a4f5cd83aac207df6bd1b3.tar.gz |
Dirty implementation of atrac3 encoder:
- no JS mode
- constant quantiser for tonal components
- gain controll implemented but produces some artifacts with real signals.
- etc...
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 274 |
1 files changed, 211 insertions, 63 deletions
diff --git a/src/main.cpp b/src/main.cpp index f74b253..9550ce4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,20 +6,23 @@ #include "pcmengin.h" #include "wav.h" #include "aea.h" -#include "atracdenc.h" +#include "config.h" +#include "atrac1denc.h" +#include "atrac3denc.h" using std::cout; using std::cerr; using std::endl; using std::string; -using std::unique_ptr; -using std::move; using std::stoi; using namespace NAtracDEnc; +typedef std::unique_ptr<TPCMEngine<TFloat>> TPcmEnginePtr; +typedef std::unique_ptr<IProcessor<TFloat>> TAtracProcessorPtr; -static void printUsage(const char* myName) { +static void printUsage(const char* myName) +{ cout << "\tusage: " << myName << " <-e|-d> <-i input> <-o output>\n" << endl; cout << "-e encode mode (PCM -> ATRAC), -i wav file, -o aea file" << endl; cout << "-d decode mode (ATRAC -> PCM), -i aea file, -o wav file" << endl; @@ -27,7 +30,8 @@ static void printUsage(const char* myName) { } -static void printProgress(int percent) { +static void printProgress(int percent) +{ static uint32_t counter; counter++; const char symbols[4] = {'-', '\\', '|', '/'}; @@ -35,26 +39,143 @@ static void printProgress(int percent) { fflush(stdout); } -static string GetHelp() { +static string GetHelp() +{ return "\n--encode -i \t - encode mode" "\n--decode -d \t - decode mode" "\n -i input file" "\n -o output file" - "\nAdvanced options:\n --bfuidxconst\t Set constant amount of used BFU. WARNING: It is not a lowpass filter! Do not use it to cut off hi frequency." - "\n --bfuidxfast\t enable fast search of BFU amount" - "\n --notransient[=mask] disable transient detection and use optional mask to set bands with short MDCT window"; + "\n --bitrate (only if supported by codec)" + "\nAdvanced options:\n --bfuidxconst\t Set constant amount of used BFU (ATRAC1). " + "WARNING: It is not a lowpass filter! Do not use it to cut off hi frequency." + "\n --bfuidxfast\t enable fast search of BFU amount (ATRAC1)" + "\n --notransient[=mask] disable transient detection and use optional mask to set bands with short MDCT window " + "(ATRAC1)" + /*"\n --nogaincontrol disable gain control (ATRAC3)"*/ + "\n --notonal disable tonal components (ATRAC3)"; } -int main(int argc, char* const* argv) { +static int checkedStoi(const char* data, int min, int max, int def) +{ + int tmp = 0; + try { + tmp = stoi(data); + if (tmp < min || tmp > max) + throw std::invalid_argument(data); + return tmp; + } catch (std::invalid_argument&) { + cerr << "Wrong arg: " << data << " " << def << " will be used" << endl; + return def; + } +} + +enum EOptions +{ + O_ENCODE = 'e', + O_DECODE = 'd', + O_HELP = 'h', + O_BITRATE = 'b', + O_BFUIDXCONST = 1, + O_BFUIDXFAST = 2, + O_NOTRANSIENT = 3, + O_MONO = 'm', + O_NOSTDOUT = '4', + O_NOTONAL = 5, + O_NOGAINCONTROL = 6, +}; + +static void PrepareAtrac1Encoder(const string& inFile, + const string& outFile, + const bool noStdOut, + NAtrac1::TAtrac1EncodeSettings&& encoderSettings, + uint64_t* totalSamples, + TWavPtr* wavIO, + TPcmEnginePtr* pcmEngine, + TAtracProcessorPtr* atracProcessor) +{ + using NAtrac1::TAtrac1Data; + + wavIO->reset(new TWav(inFile)); + const int numChannels = (*wavIO)->GetChannelNum(); + *totalSamples = (*wavIO)->GetTotalSamples(); + //TODO: recheck it + const uint32_t numFrames = numChannels * (*totalSamples) / TAtrac1Data::NumSamples; + TCompressedIOPtr aeaIO = TCompressedIOPtr(new TAea(outFile, "test", numChannels, numFrames)); + pcmEngine->reset(new TPCMEngine<TFloat>(4096, + numChannels, + TPCMEngine<TFloat>::TReaderPtr((*wavIO)->GetPCMReader<TFloat>()))); + if (!noStdOut) + cout << "Input file: " << inFile + << "\n Channels: " << numChannels + << "\n SampleRate: " << (*wavIO)->GetSampleRate() + << "\n TotalSamples: " << totalSamples + << endl; + atracProcessor->reset(new TAtrac1Processor(std::move(aeaIO), std::move(encoderSettings))); +} + +static void PrepareAtrac1Decoder(const string& inFile, + const string& outFile, + const bool noStdOut, + uint64_t* totalSamples, + TWavPtr* wavIO, + TPcmEnginePtr* pcmEngine, + TAtracProcessorPtr* atracProcessor) +{ + TCompressedIOPtr aeaIO = TCompressedIOPtr(new TAea(inFile)); + *totalSamples = aeaIO->GetLengthInSamples(); + uint32_t length = aeaIO->GetLengthInSamples(); + if (!noStdOut) + cout << "Name: " << aeaIO->GetName() + << "\n Channels: " << aeaIO->GetChannelNum() + << "\n Length: " << length + << endl; + wavIO->reset(new TWav(outFile, aeaIO->GetChannelNum(), 44100)); + pcmEngine->reset(new TPCMEngine<TFloat>(4096, + aeaIO->GetChannelNum(), + TPCMEngine<TFloat>::TWriterPtr((*wavIO)->GetPCMWriter<TFloat>()))); + atracProcessor->reset(new TAtrac1Processor(std::move(aeaIO), NAtrac1::TAtrac1EncodeSettings())); +} + +static void PrepareAtrac3Encoder(const string& inFile, + const string& outFile, + const bool noStdOut, + NAtrac3::TAtrac3EncoderSettings&& encoderSettings, + uint64_t* totalSamples, + TWavPtr* wavIO, + TPcmEnginePtr* pcmEngine, + TAtracProcessorPtr* atracProcessor) +{ + std::cout << "WARNING: ATRAC3 is uncompleted, result will be not good )))" << std::endl; + if (!noStdOut) + std::cout << "bitrate " << encoderSettings.ConteinerParams->Bitrate << std::endl; + wavIO->reset(new TWav(inFile)); + const int numChannels = (*wavIO)->GetChannelNum(); + *totalSamples = (*wavIO)->GetTotalSamples(); + TCompressedIOPtr omaIO = TCompressedIOPtr(new TOma(outFile, + "test", + numChannels, + numChannels * (*totalSamples) / 512, OMAC_ID_ATRAC3, + encoderSettings.ConteinerParams->FrameSz)); + pcmEngine->reset(new TPCMEngine<TFloat>(4096, + numChannels, + TPCMEngine<TFloat>::TReaderPtr((*wavIO)->GetPCMReader<TFloat>()))); + atracProcessor->reset(new TAtrac3Processor(std::move(omaIO), std::move(encoderSettings))); +} + +int main(int argc, char* const* argv) +{ const char* myName = argv[0]; static struct option longopts[] = { - { "encode", no_argument, NULL, 'e' }, - { "decode", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - { "bfuidxconst", required_argument, NULL, 1}, - { "bfuidxfast", no_argument, NULL, 2}, - { "notransient", optional_argument, NULL, 3}, - { "nostdout", no_argument, NULL, 4}, + { "encode", optional_argument, NULL, O_ENCODE }, + { "decode", no_argument, NULL, O_DECODE }, + { "help", no_argument, NULL, O_HELP }, + { "bitrate", required_argument, NULL, O_BITRATE}, + { "bfuidxconst", required_argument, NULL, O_BFUIDXCONST}, + { "bfuidxfast", no_argument, NULL, O_BFUIDXFAST}, + { "notransient", optional_argument, NULL, O_NOTRANSIENT}, + { "nostdout", no_argument, NULL, O_NOSTDOUT}, + { "notonal", no_argument, NULL, O_NOTONAL}, + { "nogaincontrol", no_argument, NULL, O_NOGAINCONTROL}, { NULL, 0, NULL, 0} }; @@ -64,15 +185,23 @@ int main(int argc, char* const* argv) { uint32_t mode = 0; uint32_t bfuIdxConst = 0; //0 - auto, no const bool fastBfuNumSearch = false; - bool nostdout = false; - TAtrac1EncodeSettings::EWindowMode windowMode = TAtrac1EncodeSettings::EWindowMode::EWM_AUTO; - uint32_t winMask = 0; //all is long + bool noStdOut = false; + bool noGainControl = false; + bool noTonalComponents = false; + NAtrac1::TAtrac1EncodeSettings::EWindowMode windowMode = NAtrac1::TAtrac1EncodeSettings::EWindowMode::EWM_AUTO; + uint32_t winMask = 0; //0 - all is long + uint32_t bitrate = 0; //0 - use default for codec while ((ch = getopt_long(argc, argv, "edhi:o:m", longopts, NULL)) != -1) { switch (ch) { - case 'e': + case O_ENCODE: mode |= E_ENCODE; + if (optarg) { + if (strcmp(optarg, "atrac3") == 0) { + mode |= E_ATRAC3; + } + } break; - case 'd': + case O_DECODE: mode |= E_DECODE; break; case 'i': @@ -81,25 +210,24 @@ int main(int argc, char* const* argv) { case 'o': outFile = optarg; if (outFile == "-") - nostdout = true; + noStdOut = true; break; case 'h': cout << GetHelp() << endl; return 0; break; - case 1: - try { - bfuIdxConst = stoi(optarg); - } catch (std::invalid_argument&) { - cerr << "Wrong arg: " << optarg << " should be (0, 8]" << endl; - return -1; - } + case O_BITRATE: + bitrate = checkedStoi(optarg, 32, 384, 0); + std::cout << "BITRATE" << bitrate << std::endl; + break; + case O_BFUIDXCONST: + bfuIdxConst = checkedStoi(optarg, 1, 8, 0); break; - case 2: + case O_BFUIDXFAST: fastBfuNumSearch = true; break; - case 3: - windowMode = TAtrac1EncodeSettings::EWindowMode::EWM_NOTRANSIENT; + case O_NOTRANSIENT: + windowMode = NAtrac1::TAtrac1EncodeSettings::EWindowMode::EWM_NOTRANSIENT; if (optarg) { winMask = stoi(optarg); } @@ -108,8 +236,14 @@ int main(int argc, char* const* argv) { ((winMask & 2) ? "short": "long") << ", hi - " << ((winMask & 4) ? "short": "long") << endl; break; - case 4: - nostdout = true; + case O_NOSTDOUT: + noStdOut = true; + break; + case O_NOTONAL: + noTonalComponents = true; + break; + case O_NOGAINCONTROL: + noGainControl = true; break; default: printUsage(myName); @@ -128,36 +262,50 @@ int main(int argc, char* const* argv) { return 1; } if (bfuIdxConst > 8) { - cerr << "Wrong bfuidxconst value ("<< bfuIdxConst << "). This is advanced options, use --help to get more information" << endl; + cerr << "Wrong bfuidxconst value ("<< bfuIdxConst << "). " + << "This is advanced options, use --help to get more information" + << endl; return 1; } - TPCMEngine<double>* pcmEngine = nullptr; - IProcessor<double>* atracProcessor; + + TPcmEnginePtr pcmEngine; + TAtracProcessorPtr atracProcessor; uint64_t totalSamples = 0; TWavPtr wavIO; - if (mode == E_ENCODE) { - wavIO = TWavPtr(new TWav(inFile)); - const int numChannels = wavIO->GetChannelNum(); - totalSamples = wavIO->GetTotalSamples(); - //TODO: recheck it - TAeaPtr aeaIO = TAeaPtr(new TAea(outFile, "test", numChannels, numChannels * totalSamples / 512)); - pcmEngine = new TPCMEngine<double>(4096, numChannels, TPCMEngine<double>::TReaderPtr(wavIO->GetPCMReader<double>())); - if (!nostdout) - cout << "Input file: " << inFile << "\n Channels: " << numChannels << "\n SampleRate: " << wavIO->GetSampleRate() << "\n TotalSamples: " << totalSamples << endl; - atracProcessor = new TAtrac1Processor(move(aeaIO), TAtrac1EncodeSettings(bfuIdxConst, fastBfuNumSearch, windowMode, winMask)); - } else if (mode == E_DECODE) { - TAeaPtr aeaIO = TAeaPtr(new TAea(inFile)); - totalSamples = aeaIO->GetLengthInSamples(); - uint32_t length = aeaIO->GetLengthInSamples(); - if (!nostdout) - cout << "Name: " << aeaIO->GetName() << "\n Channels: " << aeaIO->GetChannelNum() << "\n Length: " << length << endl; - wavIO = TWavPtr(new TWav(outFile, aeaIO->GetChannelNum(), 44100)); - pcmEngine = new TPCMEngine<double>(4096, aeaIO->GetChannelNum(), TPCMEngine<double>::TWriterPtr(wavIO->GetPCMWriter<double>())); - atracProcessor = new TAtrac1Processor(move(aeaIO), TAtrac1EncodeSettings(bfuIdxConst, fastBfuNumSearch, windowMode, winMask)); - } else { - cerr << "Processing mode was not specified" << endl; - return 1; + uint32_t pcmFrameSz = 0; //size of one pcm frame to process + switch (mode) { + case E_ENCODE: + { + using NAtrac1::TAtrac1Data; + NAtrac1::TAtrac1EncodeSettings encoderSettings(bfuIdxConst, fastBfuNumSearch, windowMode, winMask); + PrepareAtrac1Encoder(inFile, outFile, noStdOut, std::move(encoderSettings), + &totalSamples, &wavIO, &pcmEngine, &atracProcessor); + pcmFrameSz = TAtrac1Data::NumSamples; + } + break; + case E_DECODE: + { + using NAtrac1::TAtrac1Data; + PrepareAtrac1Decoder(inFile, outFile, noStdOut, + &totalSamples, &wavIO, &pcmEngine, &atracProcessor); + pcmFrameSz = TAtrac1Data::NumSamples; + } + break; + case (E_ENCODE | E_ATRAC3): + { + using NAtrac3::TAtrac3Data; + NAtrac3::TAtrac3EncoderSettings encoderSettings(bitrate * 1024, noGainControl, noTonalComponents); + PrepareAtrac3Encoder(inFile, outFile, noStdOut, std::move(encoderSettings), + &totalSamples, &wavIO, &pcmEngine, &atracProcessor); + pcmFrameSz = TAtrac3Data::NumSamples;; + } + break; + default: + { + cerr << "Processing mode was not specified" << endl; + return 1; + } } auto atracLambda = (mode == E_DECODE) ? atracProcessor->GetDecodeLambda() : @@ -165,12 +313,12 @@ int main(int argc, char* const* argv) { uint64_t processed = 0; try { - while (totalSamples > (processed = pcmEngine->ApplyProcess(512, atracLambda))) + while (totalSamples > (processed = pcmEngine->ApplyProcess(pcmFrameSz, atracLambda))) { - if (!nostdout) + if (!noStdOut) printProgress(processed*100/totalSamples); } - if (!nostdout) + if (!noStdOut) cout << "\nDone" << endl; } catch (TAeaIOError err) { |