diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 5ce60a9..9c55d72 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -20,9 +20,10 @@ The Windows version uses C++23, and the Unix versions use either C++20 or C++23 ### fmt library -The features that rsgain uses from the fmt library have been integrated into the C++20 and C++23 standards, specifically the `` and `` headers. Currently, neither GCC nor Clang have full support those features, so the fmt libary is required. When they gain support, the fmt dependency will be dropped in favor of the C++ standard library. - -The features have been incorporated into Microsoft's C++ standard library implementation, so the fmt library is no longer required for the Windows version. +The features that rsgain uses from the fmt library have been integrated into the C++20 and C++23 standards, specifically the `` and `` headers. The standard library implementations are planned to completely replace rsgain's fmt dependency in the future. To support the transition, rsgain can use either the fmt library or standard library, depending on platform: +- MSVC has full support in the standard library since version 19.37. The fmt library has been dropped from the Windows version in favor of the standard library implementation +- GCC (libstdc++) has full support in the standard library since version 14. Pass `-DUSE_STD_FORMAT=ON` to `cmake` to use the standard library instead of the fmt library +- Clang (libc++) has full support in the standard library since version 18. Enable it using the configuration switch described above for GCC ## Unix diff --git a/src/easymode.cpp b/src/easymode.cpp index 6567616..6573d46 100644 --- a/src/easymode.cpp +++ b/src/easymode.cpp @@ -27,7 +27,7 @@ #include "scan.hpp" #define MAX_THREAD_SLEEP 30 -#define HELP_STATS(title, format, ...) print(COLOR_YELLOW "{:<18} " COLOR_OFF format "\n", title ":" __VA_OPT__(,) __VA_ARGS__) +#define HELP_STATS(title, format, ...) rsgain::print(COLOR_YELLOW "{:<18} " COLOR_OFF format "\n", title ":" __VA_OPT__(,) __VA_ARGS__) extern "C" { int format_handler(void *user, const char *section, const char *name, const char *value); @@ -776,7 +776,7 @@ void scan_easy(const std::filesystem::path &path, const std::filesystem::path &p break; cv.wait_for(lock, std::chrono::milliseconds(200)); } - print("\33[2K\n"); + rsgain::print("\33[2K\n"); } // Single threaded scanning @@ -787,22 +787,22 @@ void scan_easy(const std::filesystem::path &path, const std::filesystem::path &p job->update_data(data); jobs.pop(); } - print("\n"); + rsgain::print("\n"); } // Output statistics at the end auto duration = std::chrono::floor(std::chrono::system_clock::now() - start_time); if (!data.files) { if (data.skipped) - print("Skipped {:L} file{} with existing ReplayGain information\n", + rsgain::print("Skipped {:L} file{} with existing ReplayGain information\n", data.skipped, data.skipped > 1 ? "s" : "" ); - print("No files were scanned\n"); + rsgain::print("No files were scanned\n"); return; } - print(COLOR_GREEN "Scanning Complete" COLOR_OFF "\n"); + rsgain::print(COLOR_GREEN "Scanning Complete" COLOR_OFF "\n"); HELP_STATS("Time Elapsed", "{:%H:%M:%S}", duration); HELP_STATS("Files Scanned", "{:L}", data.files); if (data.skipped) @@ -810,46 +810,46 @@ void scan_easy(const std::filesystem::path &path, const std::filesystem::path &p HELP_STATS("Clip Adjustments", "{:L} ({:.1f}% of files)", data.clipping_adjustments, 100.f * (float) data.clipping_adjustments / (float) data.files); HELP_STATS("Average Gain", "{:.2f} dB", data.total_gain / (double) data.files); double average_peak = data.total_peak / (double) data.files; - HELP_STATS("Average Peak", "{:.6f}{}", average_peak, average_peak != 0.0 ? format(" ({:.2f} dB)", 20.0 * log10(average_peak)) : ""); + HELP_STATS("Average Peak", "{:.6f}{}", average_peak, average_peak != 0.0 ? rsgain::format(" ({:.2f} dB)", 20.0 * log10(average_peak)) : ""); HELP_STATS("Negative Gains", "{:L} ({:.1f}% of files)", data.total_negative, 100.f * (float) data.total_negative / (float) data.files); HELP_STATS("Positive Gains", "{:L} ({:.1f}% of files)", data.total_positive, 100.f * (float) data.total_positive / (float) data.files); - print("\n"); + rsgain::print("\n"); // Inform user of errors if (!data.error_directories.empty()) { - print(COLOR_RED "There were errors while scanning the following directories:" COLOR_OFF "\n"); + rsgain::print(COLOR_RED "There were errors while scanning the following directories:" COLOR_OFF "\n"); for (const std::string &s : data.error_directories) - print("{}\n", s); - print("\n"); + rsgain::print("{}\n", s); + rsgain::print("\n"); } } static inline void help_easy() { - print(COLOR_RED "Usage: " COLOR_OFF "{}{}{} easy [OPTIONS] DIRECTORY\n", COLOR_GREEN, EXECUTABLE_TITLE, COLOR_OFF); + rsgain::print(COLOR_RED "Usage: " COLOR_OFF "{}{}{} easy [OPTIONS] DIRECTORY\n", COLOR_GREEN, EXECUTABLE_TITLE, COLOR_OFF); - print(" Easy Mode recursively scans a directory using the recommended settings for each\n"); - print(" file type. Easy Mode assumes that you have your music library organized with each album\n"); - print(" in its own folder.\n"); + rsgain::print(" Easy Mode recursively scans a directory using the recommended settings for each\n"); + rsgain::print(" file type. Easy Mode assumes that you have your music library organized with each album\n"); + rsgain::print(" in its own folder.\n"); - print("\n"); - print(COLOR_RED "Options:\n" COLOR_OFF); + rsgain::print("\n"); + rsgain::print(COLOR_RED "Options:\n" COLOR_OFF); CMD_HELP("--help", "-h", "Show this help"); CMD_HELP("--quiet", "-q", "Don't print scanning status messages"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--skip-existing", "-S", "Don't scan files with existing ReplayGain information"); CMD_HELP("--multithread=n", "-m n", "Scan files with n parallel threads"); CMD_HELP("--preset=s", "-p s", "Load scan preset s"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--output", "-O", "Output tab-delimited scan data to CSV file per directory"); CMD_HELP("--output=s", "-O s", "Output with sep header (needed for Microsoft Excel compatibility)"); CMD_HELP("--output=a", "-O a", "Output with files sorted in alphanumeric order"); - print("\n"); + rsgain::print("\n"); - print("Please report any issues to " PROJECT_URL "/issues\n"); - print("\n"); + rsgain::print("Please report any issues to " PROJECT_URL "/issues\n"); + rsgain::print("\n"); } diff --git a/src/output.cpp b/src/output.cpp index 4f9c28c..2740bbf 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -91,7 +91,7 @@ void ProgressBar::update(int pos) // Only output if we've actually made progress since last the call, or the console width changed if (c != c_prev || w != w_prev) { - print(" {:3.0f}% [", percent * 100.f); + rsgain::print(" {:3.0f}% [", percent * 100.f); memset(buffer, '=', (size_t) c); memset(buffer + c, ' ', (size_t) (w - c)); buffer[w] = ']'; @@ -117,7 +117,7 @@ void ProgressBar::complete() delete buffer; buffer = nullptr; - print("\n"); + rsgain::print("\n"); } inline int ProgressBar::get_console_width() @@ -144,7 +144,7 @@ void MTProgress::update(const std::string &path) if (w_path + w_message >= w_console) w_path = w_console - w_message; - print("\33[2K " COLOR_GREEN "{:5.1f}%" COLOR_OFF MT_MESSAGE "{:.{}}\r", + rsgain::print("\33[2K " COLOR_GREEN "{:5.1f}%" COLOR_OFF MT_MESSAGE "{:.{}}\r", 100.f * ((float) (cur) / (float) (total)), path, w_path < 0 ? 0 : w_path diff --git a/src/output.hpp b/src/output.hpp index 18fa842..2f0a7c3 100644 --- a/src/output.hpp +++ b/src/output.hpp @@ -53,13 +53,25 @@ #ifdef USE_STD_FORMAT #include #include -#define format std::format -#define print std::print +namespace rsgain { +template +constexpr auto format(std::format_string fmt, Args&&... args) { return std::format(fmt, std::forward(args)...); } +template +constexpr auto print(std::format_string fmt, Args&&... args) { std::print(fmt, std::forward(args)...); } +template +constexpr auto print(std::FILE* stream, std::format_string fmt, Args&&... args) { std::print(stream, fmt, std::forward(args)...); } +} #else #include #include -#define format fmt::format -#define print fmt::print +namespace rsgain { +template +constexpr auto format(fmt::format_string fmt, Args&&... args) { return fmt::format(fmt, std::forward(args)...); } +template +constexpr auto print(fmt::format_string fmt, Args&&... args) { fmt::print(fmt, std::forward(args)...); } +template +constexpr auto print(std::FILE* stream, fmt::format_string fmt, Args&&... args) { fmt::print(stream, fmt, std::forward(args)...); } +} #endif #define COLOR_GREEN "" @@ -87,10 +99,10 @@ #define FAIL_PREFIX "[" COLOR_RED FAIL_CHAR COLOR_OFF "] " extern int quiet; -#define output_ok(format, ...) if (!quiet) print(OK_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) -#define output_warn(format, ...) if (!quiet) print(WARN_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) -#define output_error(format, ...) print(stderr, ERROR_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) -#define output_fail(format, ...) print(stderr, FAIL_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) +#define output_ok(format, ...) if (!quiet) rsgain::print(OK_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) +#define output_warn(format, ...) if (!quiet) rsgain::print(WARN_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) +#define output_error(format, ...) rsgain::print(stderr, ERROR_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) +#define output_fail(format, ...) rsgain::print(stderr, FAIL_PREFIX format "\n" __VA_OPT__(,) __VA_ARGS__) class ProgressBar { private: diff --git a/src/rsgain.cpp b/src/rsgain.cpp index 86d03ea..e61edff 100644 --- a/src/rsgain.cpp +++ b/src/rsgain.cpp @@ -58,10 +58,10 @@ extern "C" { #include "output.hpp" #include "easymode.hpp" -#define PRINT_LIB(lib, version) print(" " COLOR_YELLOW " {:<14}" COLOR_OFF " {}\n", lib, version) +#define PRINT_LIB(lib, version) rsgain::print(" " COLOR_YELLOW " {:<14}" COLOR_OFF " {}\n", lib, version) #define PRINT_LIB_FFMPEG(name, fn) \ ffver = fn(); \ - PRINT_LIB(name, format("{}.{}.{}", AV_VERSION_MAJOR(ffver), AV_VERSION_MINOR(ffver), AV_VERSION_MICRO(ffver))) + PRINT_LIB(name, rsgain::format("{}.{}.{}", AV_VERSION_MAJOR(ffver), AV_VERSION_MINOR(ffver), AV_VERSION_MICRO(ffver))) #ifdef _WIN32 #include @@ -386,53 +386,53 @@ int main(int argc, char *argv[]) { } static void help_main() { - print(COLOR_RED "Usage: " COLOR_OFF "{}{}{} [OPTIONS] ...\n", COLOR_GREEN, EXECUTABLE_TITLE, COLOR_OFF); + rsgain::print(COLOR_RED "Usage: " COLOR_OFF "{}{}{} [OPTIONS] ...\n", COLOR_GREEN, EXECUTABLE_TITLE, COLOR_OFF); - print("{} {} supports writing tags to the following file types:\n", PROJECT_NAME, PROJECT_VERSION); - print(" FLAC (.flac), Ogg (.ogg, .oga, .spx), Opus (.opus), MP2 (.mp2),\n"); - print(" MP3 (.mp3), MP4 (.m4a), WMA (.wma), WavPack (.wv), APE (.ape),\n"); - print(" WAV (.wav), AIFF (.aiff, .aif, .snd), and TAK (.tak).\n"); + rsgain::print("{} {} supports writing tags to the following file types:\n", PROJECT_NAME, PROJECT_VERSION); + rsgain::print(" FLAC (.flac), Ogg (.ogg, .oga, .spx), Opus (.opus), MP2 (.mp2),\n"); + rsgain::print(" MP3 (.mp3), MP4 (.m4a), WMA (.wma), WavPack (.wv), APE (.ape),\n"); + rsgain::print(" WAV (.wav), AIFF (.aiff, .aif, .snd), and TAK (.tak).\n"); - print("\n"); - print(COLOR_RED "Options:\n" COLOR_OFF); + rsgain::print("\n"); + rsgain::print(COLOR_RED "Options:\n" COLOR_OFF); CMD_HELP("--help", "-h", "Show this help"); CMD_HELP("--version", "-v", "Show version number"); - print("\n"); - print(COLOR_RED "Commands:\n" COLOR_OFF); + rsgain::print("\n"); + rsgain::print(COLOR_RED "Commands:\n" COLOR_OFF); CMD_CMD("easy", "Easy Mode: Recursively scan a directory with recommended settings"); CMD_CMD("custom", "Custom Mode: Scan individual files with custom settings"); - print("\n"); - print("Run '{} easy --help' or '{} custom --help' for more information.", EXECUTABLE_TITLE, EXECUTABLE_TITLE); + rsgain::print("\n"); + rsgain::print("Run '{} easy --help' or '{} custom --help' for more information.", EXECUTABLE_TITLE, EXECUTABLE_TITLE); - print("\n\n"); - print("Please report any issues to " PROJECT_URL "/issues\n\n"); + rsgain::print("\n\n"); + rsgain::print("Please report any issues to " PROJECT_URL "/issues\n\n"); } static inline void help_custom() { - print(COLOR_RED "Usage: " COLOR_OFF "{}{}{} custom [OPTIONS] FILES...\n", COLOR_GREEN, EXECUTABLE_TITLE, COLOR_OFF); + rsgain::print(COLOR_RED "Usage: " COLOR_OFF "{}{}{} custom [OPTIONS] FILES...\n", COLOR_GREEN, EXECUTABLE_TITLE, COLOR_OFF); - print(" Custom Mode allows the user to specify the options to scan the files with. The\n"); - print(" list of files to scan must be listed explicitly after the options.\n"); - print("\n"); + rsgain::print(" Custom Mode allows the user to specify the options to scan the files with. The\n"); + rsgain::print(" list of files to scan must be listed explicitly after the options.\n"); + rsgain::print("\n"); - print(COLOR_RED "Options:\n" COLOR_OFF); + rsgain::print(COLOR_RED "Options:\n" COLOR_OFF); CMD_HELP("--help", "-h", "Show this help"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--album", "-a", "Calculate album gain and peak"); CMD_HELP("--skip-existing", "-S", "Don't scan files with existing ReplayGain information"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--tagmode=s", "-s s", "Scan files but don't write ReplayGain tags (default)"); CMD_HELP("--tagmode=d", "-s d", "Delete ReplayGain tags from files"); CMD_HELP("--tagmode=i", "-s i", "Scan and write ReplayGain 2.0 tags to files"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--loudness=n", "-l n", "Use n LUFS as target loudness (" STR(MIN_TARGET_LOUDNESS) " ≤ n ≤ " STR(MAX_TARGET_LOUDNESS) ")"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--clip-mode=n", "-c n", "No clipping protection (default)"); CMD_HELP("--clip-mode=p", "-c p", "Clipping protection enabled for positive gain values only"); @@ -440,7 +440,7 @@ static inline void help_custom() { CMD_HELP("--max-peak=n", "-m n", "Use max peak level n dB for clipping protection"); CMD_HELP("--true-peak", "-t", "Use true peak for peak calculations"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--lowercase", "-L", "Write lowercase tags (MP2/MP3/MP4/WMA/WAV/AIFF)"); CMD_CONT("This is non-standard but sometimes needed"); @@ -448,7 +448,7 @@ static inline void help_custom() { CMD_HELP("--id3v2-version=3", "-I 3", "Write ID3v2.3 tags to MP2/MP3/WAV/AIFF"); CMD_HELP("--id3v2-version=4", "-I 4", "Write ID3v2.4 tags to MP2/MP3/WAV/AIFF"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--opus-mode=d", "-o d", "Write standard ReplayGain tags, clear header output gain (default)"); CMD_HELP("--opus-mode=r", "-o r", "Write R128_*_GAIN tags, clear header output gain"); @@ -456,7 +456,7 @@ static inline void help_custom() { CMD_HELP("--opus-mode=t", "-o t", "Write track gain to header output gain"); CMD_HELP("--opus-mode=a", "-o a", "Write album gain to header output gain"); - print("\n"); + rsgain::print("\n"); CMD_HELP("--output", "-O", "Output tab-delimited scan data to stdout"); CMD_HELP("--output=s", "-O s", "Output with sep header (needed for Microsoft Excel compatibility)"); @@ -465,10 +465,10 @@ static inline void help_custom() { CMD_HELP("--preserve-mtimes", "-p", "Preserve file mtimes"); CMD_HELP("--quiet", "-q", "Don't print scanning status messages"); - print("\n"); + rsgain::print("\n"); - print("Please report any issues to " PROJECT_URL "/issues\n"); - print("\n"); + rsgain::print("Please report any issues to " PROJECT_URL "/issues\n"); + rsgain::print("\n"); } static void version() { @@ -476,7 +476,7 @@ static void version() { int ebur128_v_major = 0; int ebur128_v_minor = 0; int ebur128_v_patch = 0; - print(COLOR_GREEN PROJECT_NAME COLOR_OFF " " PROJECT_VERSION + rsgain::print(COLOR_GREEN PROJECT_NAME COLOR_OFF " " PROJECT_VERSION #if defined COMMITS_SINCE_TAG && defined COMMIT_HASH "-r" COMMITS_SINCE_TAG "-" COMMIT_HASH #endif @@ -485,27 +485,27 @@ static void version() { // Library versions ebur128_get_version(&ebur128_v_major, &ebur128_v_minor, &ebur128_v_patch); - PRINT_LIB("libebur128", format("{}.{}.{}", ebur128_v_major, ebur128_v_minor, ebur128_v_patch)); + PRINT_LIB("libebur128", rsgain::format("{}.{}.{}", ebur128_v_major, ebur128_v_minor, ebur128_v_patch)); PRINT_LIB_FFMPEG("libavformat", avformat_version); PRINT_LIB_FFMPEG("libavcodec", avcodec_version); PRINT_LIB_FFMPEG("libavutil", avutil_version); PRINT_LIB_FFMPEG("libswresample", swresample_version); #if HAS_TAGLIB2 TagLib::VersionNumber tver = TagLib::runtimeVersion(); - PRINT_LIB("TagLib", format("{}.{}{}", tver.majorVersion(), tver.minorVersion(), tver.patchVersion() ? format(".{}", tver.patchVersion()) : "")); + PRINT_LIB("TagLib", rsgain::format("{}.{}{}", tver.majorVersion(), tver.minorVersion(), tver.patchVersion() ? rsgain::format(".{}", tver.patchVersion()) : "")); #else - print("\n"); - print("Built with:\n"); - PRINT_LIB("TagLib", format("{}.{}{}", TAGLIB_MAJOR_VERSION, TAGLIB_MINOR_VERSION, TAGLIB_PATCH_VERSION ? format(".{}", TAGLIB_PATCH_VERSION) : "")); + rsgain::print("\n"); + rsgain::print("Built with:\n"); + PRINT_LIB("TagLib", rsgain::format("{}.{}{}", TAGLIB_MAJOR_VERSION, TAGLIB_MINOR_VERSION, TAGLIB_PATCH_VERSION ? rsgain::format(".{}", TAGLIB_PATCH_VERSION) : "")); #endif - print("\n"); + rsgain::print("\n"); #if defined(__GNUC__) && !defined(__clang__) - print(COLOR_YELLOW "{:<17}" COLOR_OFF " GCC {}.{}\n", "Compiler:", __GNUC__, __GNUC_MINOR__); + rsgain::print(COLOR_YELLOW "{:<17}" COLOR_OFF " GCC {}.{}\n", "Compiler:", __GNUC__, __GNUC_MINOR__); #endif #ifdef __clang__ - print(COLOR_YELLOW "{:<17}" COLOR_OFF " " + rsgain::print(COLOR_YELLOW "{:<17}" COLOR_OFF " " #ifdef __apple_build_version__ "Apple " #endif @@ -513,8 +513,8 @@ static void version() { #endif #ifdef _MSC_VER - print(COLOR_YELLOW "{:<17}" COLOR_OFF " Microsoft C/C++ {:.2f}\n", "Compiler:", (float) _MSC_VER / 100.0f); + rsgain::print(COLOR_YELLOW "{:<17}" COLOR_OFF " Microsoft C/C++ {:.2f}\n", "Compiler:", (float) _MSC_VER / 100.0f); #endif - print(COLOR_YELLOW "{:<17}" COLOR_OFF " " BUILD_DATE "\n", "Build Date:"); + rsgain::print(COLOR_YELLOW "{:<17}" COLOR_OFF " " BUILD_DATE "\n", "Build Date:"); } diff --git a/src/rsgain.hpp b/src/rsgain.hpp index 2df751e..40d2558 100644 --- a/src/rsgain.hpp +++ b/src/rsgain.hpp @@ -1,8 +1,8 @@ #pragma once -#define CMD_HELP(CMDL, CMDS, MSG) print(" {}{:<8} {:<20}{} {}.\n", COLOR_YELLOW, CMDS ",", CMDL, COLOR_OFF, MSG); -#define CMD_CMD(CMD, MSG) print(" {}{:<22}{} {}.\n", COLOR_YELLOW, CMD, COLOR_OFF, MSG); -#define CMD_CONT(MSG) print(" {}{:<8} {:<20}{} {}.\n", COLOR_YELLOW, "", "", COLOR_OFF, MSG); +#define CMD_HELP(CMDL, CMDS, MSG) rsgain::print(" {}{:<8} {:<20}{} {}.\n", COLOR_YELLOW, CMDS ",", CMDL, COLOR_OFF, MSG); +#define CMD_CMD(CMD, MSG) rsgain::print(" {}{:<22}{} {}.\n", COLOR_YELLOW, CMD, COLOR_OFF, MSG); +#define CMD_CONT(MSG) rsgain::print(" {}{:<8} {:<20}{} {}.\n", COLOR_YELLOW, "", "", COLOR_OFF, MSG); #define MATCH(x,y) !strcmp(x,y) #define STR_CAT(a) #a #define STR(a) STR_CAT(a) diff --git a/src/scan.cpp b/src/scan.cpp index 6284cfa..1b807f2 100644 --- a/src/scan.cpp +++ b/src/scan.cpp @@ -220,7 +220,7 @@ bool ScanJob::Track::scan(const Config &config, std::mutex *m) if (lk) lk->lock(); - rc = avformat_open_input(&format_ctx, format("file:{}", path.string()).c_str(), nullptr, nullptr); + rc = avformat_open_input(&format_ctx, rsgain::format("file:{}", path.string()).c_str(), nullptr, nullptr); if (rc < 0) { output_fferror(rc, "Could not open input"); goto end; @@ -290,7 +290,7 @@ bool ScanJob::Track::scan(const Config &config, std::mutex *m) output_ok("Stream #{}: {}, {}{:L} Hz, {} ch", stream_id, codec->long_name, - codec_ctx->bits_per_raw_sample > 0 ? format("{} bit, ", codec_ctx->bits_per_raw_sample) : "", + codec_ctx->bits_per_raw_sample > 0 ? rsgain::format("{} bit, ", codec_ctx->bits_per_raw_sample) : "", codec_ctx->sample_rate, nb_channels ); @@ -525,52 +525,52 @@ void ScanJob::tag_tracks() if (tab_output) { // Filename;Loudness;Gain (dB);Peak;Peak (dB);Peak Type;Clipping Adjustment; - print(stream, "{}\t", track.path.filename().string()); - track.result.track_loudness == -HUGE_VAL ? print(stream, "-∞\t") : print(stream, "{:.2f}\t", track.result.track_loudness); - print(stream, "{:.2f}\t", track.result.track_gain); - print(stream, "{:.6f}\t", track.result.track_peak); - track.result.track_peak == 0.0 ? print(stream, "-∞\t") : print(stream, "{:.2f}\t", 20.0 * log10(track.result.track_peak)); - print(stream, "{}\t", config.true_peak ? "True" : "Sample"); - print(stream, "{}\n", track.tclip ? "Y" : "N"); + rsgain::print(stream, "{}\t", track.path.filename().string()); + track.result.track_loudness == -HUGE_VAL ? rsgain::print(stream, "-∞\t") : rsgain::print(stream, "{:.2f}\t", track.result.track_loudness); + rsgain::print(stream, "{:.2f}\t", track.result.track_gain); + rsgain::print(stream, "{:.6f}\t", track.result.track_peak); + track.result.track_peak == 0.0 ? rsgain::print(stream, "-∞\t") : rsgain::print(stream, "{:.2f}\t", 20.0 * log10(track.result.track_peak)); + rsgain::print(stream, "{}\t", config.true_peak ? "True" : "Sample"); + rsgain::print(stream, "{}\n", track.tclip ? "Y" : "N"); if (config.do_album && ((size_t) (&track - &tracks[0]) == (nb_files - 1))) { - print(stream, "{}\t", "Album"); - track.result.album_loudness == -HUGE_VAL ? print(stream, "-∞\t") : print(stream, "{:.2f}\t", track.result.album_loudness); - print(stream, "{:.2f}\t", track.result.album_gain); - print(stream, "{:.6f}\t", track.result.album_peak); - track.result.album_peak == 0.0 ? print(stream, "-∞\t") : print(stream, "{:.2f}\t", 20.0 * log10(track.result.album_peak)); - print(stream, "{}\t", config.true_peak ? "True" : "Sample"); - print(stream, "{}\n", track.aclip ? "Y" : "N"); + rsgain::print(stream, "{}\t", "Album"); + track.result.album_loudness == -HUGE_VAL ? rsgain::print(stream, "-∞\t") : rsgain::print(stream, "{:.2f}\t", track.result.album_loudness); + rsgain::print(stream, "{:.2f}\t", track.result.album_gain); + rsgain::print(stream, "{:.6f}\t", track.result.album_peak); + track.result.album_peak == 0.0 ? rsgain::print(stream, "-∞\t") : rsgain::print(stream, "{:.2f}\t", 20.0 * log10(track.result.album_peak)); + rsgain::print(stream, "{}\t", config.true_peak ? "True" : "Sample"); + rsgain::print(stream, "{}\n", track.aclip ? "Y" : "N"); } } // Human-readable output if (human_output) { - print("\nTrack: {}\n", track.path.string()); - print(" Loudness: {} LUFS\n", track.result.track_loudness == -HUGE_VAL ? " -∞" : format("{:8.2f}", track.result.track_loudness)); - print(" Peak: {:8.6f} ({} dB)\n", + rsgain::print("\nTrack: {}\n", track.path.string()); + rsgain::print(" Loudness: {} LUFS\n", track.result.track_loudness == -HUGE_VAL ? " -∞" : rsgain::format("{:8.2f}", track.result.track_loudness)); + rsgain::print(" Peak: {:8.6f} ({} dB)\n", track.result.track_peak, - track.result.track_peak == 0.0 ? "-∞" : format("{:.2f}", 20.0 * log10(track.result.track_peak)) + track.result.track_peak == 0.0 ? "-∞" : rsgain::format("{:.2f}", 20.0 * log10(track.result.track_peak)) ); - print(" Gain: {:8.2f} dB {}{}\n", + rsgain::print(" Gain: {:8.2f} dB {}{}\n", track.result.track_gain, - track.type == FileType::OPUS && (config.opus_mode == 'r' || config.opus_mode == 's') ? format("({})", GAIN_TO_Q78(track.result.track_gain)) : "", + track.type == FileType::OPUS && (config.opus_mode == 'r' || config.opus_mode == 's') ? rsgain::format("({})", GAIN_TO_Q78(track.result.track_gain)) : "", track.tclip ? " (adjusted to prevent clipping)" : "" ); if (config.do_album && ((size_t) (&track - &tracks[0]) == (nb_files - 1))) { - print("\nAlbum:\n"); - print(" Loudness: {} LUFS\n", track.result.album_loudness == -HUGE_VAL ? " -∞" : format("{:8.2f}", track.result.album_loudness)); - print(" Peak: {:8.6f} ({} dB)\n", + rsgain::print("\nAlbum:\n"); + rsgain::print(" Loudness: {} LUFS\n", track.result.album_loudness == -HUGE_VAL ? " -∞" : rsgain::format("{:8.2f}", track.result.album_loudness)); + rsgain::print(" Peak: {:8.6f} ({} dB)\n", track.result.album_peak, - track.result.album_peak == 0.0 ? "-∞" : format("{:.2f}", 20.0 * log10(track.result.album_peak)) + track.result.album_peak == 0.0 ? "-∞" : rsgain::format("{:.2f}", 20.0 * log10(track.result.album_peak)) ); - print(" Gain: {:8.2f} dB {}{}\n", + rsgain::print(" Gain: {:8.2f} dB {}{}\n", track.result.album_gain, - type == FileType::OPUS && (config.opus_mode == 'r' || config.opus_mode == 's') ? format("({})", GAIN_TO_Q78(track.result.album_gain)) : "", + type == FileType::OPUS && (config.opus_mode == 'r' || config.opus_mode == 's') ? rsgain::format("({})", GAIN_TO_Q78(track.result.album_gain)) : "", track.aclip ? " (adjusted to prevent clipping)" : "" ); } - print("\n"); + rsgain::print("\n"); } } if (config.tab_output == OutputType::FILE && stream != nullptr) diff --git a/src/tag.cpp b/src/tag.cpp index 7d84b9a..138c385 100644 --- a/src/tag.cpp +++ b/src/tag.cpp @@ -65,8 +65,8 @@ #include "output.hpp" #define TAGLIB_VERSION (TAGLIB_MAJOR_VERSION * 10000 + TAGLIB_MINOR_VERSION * 100 + TAGLIB_PATCH_VERSION) -#define FORMAT_GAIN(gain) format("{:.2f} dB", gain) -#define FORMAT_PEAK(peak) format("{:.6f}", peak) +#define FORMAT_GAIN(gain) rsgain::format("{:.2f} dB", gain) +#define FORMAT_PEAK(peak) rsgain::format("{:.6f}", peak) #define OPUS_HEADER_SIZE 47 #define OGG_ROW_SIZE 4 #define OPUS_HEAD_OFFSET 7 * OGG_ROW_SIZE @@ -636,12 +636,12 @@ static void tag_write(TagLib::Ogg::XiphComment *tag, const ScanResult &result, c // Opus RFC 7845 tag if (std::is_same_v && (config.opus_mode == 'r' || config.opus_mode == 's')) { tag->addField(R128_STRING[static_cast(R128Tag::TRACK_GAIN)], - format("{}", GAIN_TO_Q78(result.track_gain)) + rsgain::format("{}", GAIN_TO_Q78(result.track_gain)) ); if (config.do_album) { tag->addField(R128_STRING[static_cast(R128Tag::ALBUM_GAIN)], - format("{}", GAIN_TO_Q78(result.album_gain)) + rsgain::format("{}", GAIN_TO_Q78(result.album_gain)) ); } }