ProcessorParameter.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Copyright (c) 2021-2022, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Concepts.h>
  8. #include <AK/FixedPoint.h>
  9. #include <AK/Format.h>
  10. #include <AK/Forward.h>
  11. #include <AK/Function.h>
  12. #include <AK/String.h>
  13. #include <AK/Types.h>
  14. #include <LibDSP/Music.h>
  15. namespace DSP {
  16. using ParameterFixedPoint = FixedPoint<8, i64>;
  17. // Identifies the different kinds of parameters.
  18. // Note that achieving parameter type identification is NOT possible with typeid().
  19. enum class ParameterType : u8 {
  20. Invalid = 0,
  21. Range,
  22. Enum,
  23. Boolean,
  24. };
  25. enum class Logarithmic : bool {
  26. No,
  27. Yes
  28. };
  29. // Processors have modifiable parameters that should be presented to the UI in a uniform way without requiring the processor itself to implement custom interfaces.
  30. class ProcessorParameter {
  31. public:
  32. ProcessorParameter(ErrorOr<String> name, ParameterType type)
  33. : m_type(type)
  34. {
  35. if (!name.is_error())
  36. m_name = name.release_value();
  37. }
  38. String const& name() const { return m_name; }
  39. ParameterType type() const { return m_type; }
  40. private:
  41. String m_name {};
  42. ParameterType const m_type;
  43. };
  44. namespace Detail {
  45. struct ProcessorParameterSetValueTag {
  46. explicit ProcessorParameterSetValueTag() = default;
  47. };
  48. template<typename ParameterT>
  49. class ProcessorParameterSingleValue : public ProcessorParameter {
  50. public:
  51. ProcessorParameterSingleValue(ErrorOr<String> name, ParameterType type, ParameterT initial_value)
  52. : ProcessorParameter(move(name), type)
  53. , m_value(move(initial_value))
  54. {
  55. }
  56. operator ParameterT() const
  57. {
  58. return value();
  59. }
  60. operator double() const
  61. requires(IsSame<ParameterT, ParameterFixedPoint>)
  62. {
  63. return static_cast<double>(value());
  64. }
  65. ParameterT value() const { return m_value; }
  66. void set_value(ParameterT value)
  67. {
  68. set_value_sneaky(value, DSP::Detail::ProcessorParameterSetValueTag {});
  69. for (auto const& did_change_value : m_change_value_listeners)
  70. did_change_value(value);
  71. }
  72. // Use of this function is discouraged. It doesn't notify the value listener.
  73. void set_value_sneaky(ParameterT value, [[maybe_unused]] Detail::ProcessorParameterSetValueTag)
  74. {
  75. if (value != m_value)
  76. m_value = value;
  77. }
  78. // FIXME: Devise a good API for unregistering listeners.
  79. void register_change_listener(Function<void(ParameterT const&)> listener)
  80. {
  81. m_change_value_listeners.append(move(listener));
  82. }
  83. protected:
  84. ParameterT m_value;
  85. Vector<Function<void(ParameterT const&)>> m_change_value_listeners;
  86. };
  87. }
  88. class ProcessorBooleanParameter final : public Detail::ProcessorParameterSingleValue<bool> {
  89. public:
  90. ProcessorBooleanParameter(String name, bool initial_value)
  91. : Detail::ProcessorParameterSingleValue<bool>(move(name), ParameterType::Boolean, move(initial_value))
  92. {
  93. }
  94. };
  95. class ProcessorRangeParameter final : public Detail::ProcessorParameterSingleValue<ParameterFixedPoint> {
  96. public:
  97. ProcessorRangeParameter(ErrorOr<String> name, ParameterFixedPoint min_value, ParameterFixedPoint max_value, ParameterFixedPoint initial_value, Logarithmic logarithmic)
  98. : Detail::ProcessorParameterSingleValue<ParameterFixedPoint>(move(name), ParameterType::Range, move(initial_value))
  99. , m_min_value(move(min_value))
  100. , m_max_value(move(max_value))
  101. , m_default_value(move(initial_value))
  102. , m_logarithmic(logarithmic)
  103. {
  104. VERIFY(initial_value <= max_value && initial_value >= min_value);
  105. }
  106. ProcessorRangeParameter(ProcessorRangeParameter const& to_copy)
  107. : ProcessorRangeParameter(to_copy.name(), to_copy.min_value(), to_copy.max_value(), to_copy.value(), to_copy.is_logarithmic())
  108. {
  109. }
  110. ParameterFixedPoint min_value() const { return m_min_value; }
  111. ParameterFixedPoint max_value() const { return m_max_value; }
  112. ParameterFixedPoint range() const { return m_max_value - m_min_value; }
  113. constexpr Logarithmic is_logarithmic() const { return m_logarithmic; }
  114. ParameterFixedPoint default_value() const { return m_default_value; }
  115. void set_value(ParameterFixedPoint value)
  116. {
  117. Detail::ProcessorParameterSingleValue<ParameterFixedPoint>::set_value(value.clamp(min_value(), max_value()));
  118. }
  119. private:
  120. double const m_min_value;
  121. double const m_max_value;
  122. double const m_default_value;
  123. Logarithmic const m_logarithmic;
  124. };
  125. template<Enum EnumT>
  126. class ProcessorEnumParameter final : public Detail::ProcessorParameterSingleValue<EnumT> {
  127. public:
  128. ProcessorEnumParameter(ErrorOr<String> name, EnumT initial_value)
  129. : Detail::ProcessorParameterSingleValue<EnumT>(move(name), ParameterType::Enum, initial_value)
  130. {
  131. }
  132. };
  133. }
  134. template<>
  135. struct AK::Formatter<DSP::ProcessorRangeParameter> : AK::StandardFormatter {
  136. Formatter() = default;
  137. explicit Formatter(StandardFormatter formatter)
  138. : StandardFormatter(formatter)
  139. {
  140. }
  141. ErrorOr<void> format(FormatBuilder& builder, DSP::ProcessorRangeParameter value)
  142. {
  143. if (m_mode == Mode::Pointer) {
  144. Formatter<FlatPtr> formatter { *this };
  145. return formatter.format(builder, reinterpret_cast<FlatPtr>(&value));
  146. }
  147. if (m_sign_mode != FormatBuilder::SignMode::Default)
  148. VERIFY_NOT_REACHED();
  149. if (m_alternative_form)
  150. VERIFY_NOT_REACHED();
  151. if (m_zero_pad)
  152. VERIFY_NOT_REACHED();
  153. if (m_mode != Mode::Default)
  154. VERIFY_NOT_REACHED();
  155. if (m_width.has_value() && m_precision.has_value())
  156. VERIFY_NOT_REACHED();
  157. m_width = m_width.value_or(0);
  158. m_precision = m_precision.value_or(NumericLimits<size_t>::max());
  159. TRY(builder.put_literal(TRY(String::formatted("[{} - {}]: {}", value.min_value(), value.max_value(), value.value())).bytes_as_string_view()));
  160. return {};
  161. }
  162. };