diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2020-03-31 17:07:38 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2020-03-31 17:07:38 +0200 |
commit | ec75b9e317baf249d67295300bc5308b7c33f4ac (patch) | |
tree | 6f43693530b463fc913f7c7153a3f54a43ebd04b /src/utils.cpp | |
parent | a1eb6cf861d3c1cbd4e6c016be3cbd2a1e3d797d (diff) | |
download | ODR-AudioEnc-ec75b9e317baf249d67295300bc5308b7c33f4ac.tar.gz ODR-AudioEnc-ec75b9e317baf249d67295300bc5308b7c33f4ac.tar.bz2 ODR-AudioEnc-ec75b9e317baf249d67295300bc5308b7c33f4ac.zip |
Fix GStreamer input, rework ICY-Text write
Diffstat (limited to 'src/utils.cpp')
-rw-r--r-- | src/utils.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..525f05e --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,96 @@ +#include <cmath> +#include <cstdint> +#include <cstddef> +#include <sstream> + +#include "utils.h" +#include <unistd.h> + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/* Taken from sox */ +const char* level(int channel, int peak) +{ + static char const * const text[][2] = { + /* White: 2dB steps */ + {"", ""}, {"-", "-"}, {"=", "="}, {"-=", "=-"}, + {"==", "=="}, {"-==", "==-"}, {"===", "==="}, {"-===", "===-"}, + {"====", "===="}, {"-====", "====-"}, {"=====", "====="}, + {"-=====", "=====-"}, {"======", "======"}, + /* Red: 1dB steps */ + {"!=====", "=====!"}, + }; + int const red = 1, white = NUMOF(text) - red; + + double linear = ((double)peak) / INT16_MAX; + + int vu_dB = linear ? floor(2 * white + red + linear_to_dB(linear)) : 0; + + int index = vu_dB < 2 * white ? + MAX(vu_dB / 2, 0) : + MIN(vu_dB - white, red + white - 1); + + return text[index][channel]; +} + +size_t strlen_utf8(const char *s) { + size_t result = 0; + + // ignore continuation bytes - only count single/leading bytes + while (*s) + if ((*s++ & 0xC0) != 0x80) + result++; + + return result; +} + +static const std::string ICY_TEXT_SEPARATOR = " - "; + +bool write_icy_to_file(const ICY_TEXT_t text, const std::string& filename, bool dl_plus) +{ + FILE* fd = fopen(filename.c_str(), "wb"); + if (fd) { + bool ret = true; + bool artist_title_used = !text.artist.empty() and !text.title.empty(); + + // if desired, prepend DL Plus information + if (dl_plus) { + std::stringstream ss; + ss << "##### parameters { #####\n"; + ss << "DL_PLUS=1\n"; + + // if non-empty text, add tag + if (artist_title_used) { + size_t artist_len = strlen_utf8(text.artist.c_str()); + size_t title_start = artist_len + strlen_utf8(ICY_TEXT_SEPARATOR.c_str()); + + // ITEM.ARTIST + ss << "DL_PLUS_TAG=4 0 " << (artist_len - 1) << "\n"; // -1 ! + + // ITEM.TITLE + ss << "DL_PLUS_TAG=1 " << title_start << " " << (strlen_utf8(text.title.c_str()) - 1) << "\n"; // -1 ! + } else if (!text.now_playing.empty()) { + // PROGRAMME.NOW + ss << "DL_PLUS_TAG=33 0 " << (strlen_utf8(text.now_playing.c_str()) - 1) << "\n"; // -1 ! + } + + ss << "##### parameters } #####\n"; + ret &= fputs(ss.str().c_str(), fd) >= 0; + } + + if (artist_title_used) { + ret &= fputs(text.artist.c_str(), fd) >= 0; + ret &= fputs(ICY_TEXT_SEPARATOR.c_str(), fd) >= 0; + ret &= fputs(text.title.c_str(), fd) >= 0; + } + else { + ret &= fputs(text.now_playing.c_str(), fd) >= 0; + } + fclose(fd); + + return ret; + } + + return false; +} |