File: DynamicRangeProcessorUtils.cpp

package info (click to toggle)
audacity 3.7.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 134,800 kB
  • sloc: cpp: 366,277; ansic: 198,323; lisp: 7,761; sh: 3,414; python: 1,501; xml: 1,385; perl: 854; makefile: 125
file content (125 lines) | stat: -rw-r--r-- 3,947 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*  SPDX-License-Identifier: GPL-2.0-or-later */
/*!********************************************************************

  Audacity: A Digital Audio Editor

  DynamicRangeProcessorUtils.cpp

  Matthieu Hodgkinson

**********************************************************************/
#include "DynamicRangeProcessorUtils.h"
#include <optional>
#include <regex>
#include <stdexcept>
#include <unordered_map>

namespace DynamicRangeProcessorUtils
{
namespace
{

template <typename Struct> struct SettingDescription
{
   double Struct::*const mem {};
   const char* const key {};
};

static const std::vector<SettingDescription<CompressorSettings>>
   compressorSettingDescriptions {
      { &CompressorSettings::thresholdDb, "thresholdDb" },
      { &CompressorSettings::makeupGainDb, "makeupGainDb" },
      { &CompressorSettings::kneeWidthDb, "kneeWidthDb" },
      { &CompressorSettings::compressionRatio, "compressionRatio" },
      { &CompressorSettings::lookaheadMs, "lookaheadMs" },
      { &CompressorSettings::attackMs, "attackMs" },
      { &CompressorSettings::releaseMs, "releaseMs" },
      { &CompressorSettings::showInput, "showInput" },
      { &CompressorSettings::showOutput, "showOutput" },
      { &CompressorSettings::showActual, "showActual" },
      { &CompressorSettings::showTarget, "showTarget" },
   };

const std::vector<SettingDescription<LimiterSettings>>
   limiterSettingDescriptions {
      { &LimiterSettings::thresholdDb, "thresholdDb" },
      { &LimiterSettings::makeupTargetDb, "makeupTargetDb" },
      { &LimiterSettings::kneeWidthDb, "kneeWidthDb" },
      { &LimiterSettings::lookaheadMs, "lookaheadMs" },
      { &LimiterSettings::releaseMs, "releaseMs" },
      { &LimiterSettings::showInput, "showInput" },
      { &LimiterSettings::showOutput, "showOutput" },
      { &LimiterSettings::showActual, "showActual" },
      { &LimiterSettings::showTarget, "showTarget" },
   };

template <typename Struct>
std::optional<Struct> Deserialize(
   const std::string& str,
   const std::vector<SettingDescription<Struct>>& settings)
{
   Struct settingStruct;

   const std::regex pattern(R"((\w+)=\"(-?\d+\.?\d*)\")");

   // Create an unordered_map to store the key-value pairs
   std::unordered_map<std::string, std::string> values;

   const auto begin = std::sregex_iterator(str.begin(), str.end(), pattern);
   const auto end = std::sregex_iterator();

   for (auto it = begin; it != end; ++it)
   {
      const std::smatch match = *it;
      values[match[1].str()] = match[2].str();
   }

   if (std::any_of(
          settings.begin(), settings.end(), [&values](const auto& setting) {
             return values.find(setting.key) == values.end();
          }))
      return {};

   for (const auto& setting : settings)
      try
      {
         settingStruct.*(setting.mem) = std::stod(values.at(setting.key));
      }
      catch (...)
      {
         return {};
      }

   return settingStruct;
}

template <typename Struct>
std::vector<Preset<Struct>> GetPresets(
   const std::vector<SettingDescription<Struct>>& settingDescriptions,
   const std::vector<Detail::SerializedPreset>& serializedPresets)
{
   std::vector<Preset<Struct>> presets;
   for (const auto& serialized : serializedPresets)
      if (
         const auto preset =
            Deserialize<Struct>(serialized.settings, settingDescriptions))
         presets.push_back({ serialized.name, *preset });

   return presets;
}
} // namespace
} // namespace DynamicRangeProcessorUtils

std::vector<DynamicRangeProcessorUtils::CompressorPreset>
DynamicRangeProcessorUtils::GetCompressorPresets()
{
   return GetPresets<CompressorSettings>(
      compressorSettingDescriptions, Detail::serializedCompressorPresets);
}

std::vector<DynamicRangeProcessorUtils::LimiterPreset>
DynamicRangeProcessorUtils::GetLimiterPresets()
{
   return GetPresets<LimiterSettings>(
      limiterSettingDescriptions, Detail::serializedLimiterPresets);
}