2021-08-27 16:18:11 +02:00
/*
2022-05-11 21:37:55 +02:00
* Copyright ( c ) 2021 - 2022 , kleines Filmröllchen < filmroellchen @ serenityos . org >
2021-08-27 16:18:11 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
2022-11-14 18:20:59 +00:00
# include <AK/Concepts.h>
2022-12-04 18:02:33 +00:00
# include <AK/DeprecatedString.h>
2021-08-27 16:18:11 +02:00
# include <AK/FixedPoint.h>
# include <AK/Format.h>
2021-09-28 17:50:12 +02:00
# include <AK/Forward.h>
2022-05-11 21:37:55 +02:00
# include <AK/Function.h>
2021-08-27 16:18:11 +02:00
# include <AK/Types.h>
2021-09-28 17:50:12 +02:00
# include <LibDSP/Music.h>
2021-08-27 16:18:11 +02:00
2022-07-17 11:35:31 +02:00
namespace DSP {
2021-08-27 16:18:11 +02:00
using ParameterFixedPoint = FixedPoint < 8 , i64 > ;
2021-09-28 18:01:39 +02:00
// Identifies the different kinds of parameters.
// Note that achieving parameter type identification is NOT possible with typeid().
enum class ParameterType : u8 {
Invalid = 0 ,
Range ,
Enum ,
Boolean ,
} ;
2021-10-12 01:15:12 +02:00
enum class Logarithmic : bool {
No ,
Yes
} ;
2021-08-27 16:18:11 +02:00
// Processors have modifiable parameters that should be presented to the UI in a uniform way without requiring the processor itself to implement custom interfaces.
class ProcessorParameter {
public :
2022-12-04 18:02:33 +00:00
ProcessorParameter ( DeprecatedString name , ParameterType type )
2021-08-27 16:18:11 +02:00
: m_name ( move ( name ) )
2021-09-28 18:01:39 +02:00
, m_type ( type )
2021-08-27 16:18:11 +02:00
{
}
2022-12-04 18:02:33 +00:00
DeprecatedString const & name ( ) const { return m_name ; }
2021-09-28 18:01:39 +02:00
ParameterType type ( ) const { return m_type ; }
2021-08-27 16:18:11 +02:00
private :
2022-12-04 18:02:33 +00:00
DeprecatedString const m_name ;
2021-09-28 18:01:39 +02:00
ParameterType const m_type ;
2021-08-27 16:18:11 +02:00
} ;
namespace Detail {
struct ProcessorParameterSetValueTag {
explicit ProcessorParameterSetValueTag ( ) = default ;
} ;
template < typename ParameterT >
class ProcessorParameterSingleValue : public ProcessorParameter {
public :
2022-12-04 18:02:33 +00:00
ProcessorParameterSingleValue ( DeprecatedString name , ParameterType type , ParameterT initial_value )
2021-09-28 18:01:39 +02:00
: ProcessorParameter ( move ( name ) , type )
2021-08-27 16:18:11 +02:00
, m_value ( move ( initial_value ) )
{
}
operator ParameterT ( ) const
{
return value ( ) ;
}
2022-10-17 00:06:11 +02:00
operator double ( ) const
requires ( IsSame < ParameterT , ParameterFixedPoint > )
2021-08-27 16:18:11 +02:00
{
return static_cast < double > ( value ( ) ) ;
}
ParameterT value ( ) const { return m_value ; } ;
void set_value ( ParameterT value )
{
2022-07-17 11:35:31 +02:00
set_value_sneaky ( value , DSP : : Detail : : ProcessorParameterSetValueTag { } ) ;
2022-07-13 12:44:19 +02:00
for ( auto const & did_change_value : m_change_value_listeners )
2021-08-27 16:18:11 +02:00
did_change_value ( value ) ;
}
// Use of this function is discouraged. It doesn't notify the value listener.
void set_value_sneaky ( ParameterT value , [ [ maybe_unused ] ] Detail : : ProcessorParameterSetValueTag )
{
if ( value ! = m_value )
m_value = value ;
}
2022-07-13 12:44:19 +02:00
// FIXME: Devise a good API for unregistering listeners.
void register_change_listener ( Function < void ( ParameterT const & ) > listener )
{
m_change_value_listeners . append ( move ( listener ) ) ;
}
2021-08-27 16:18:11 +02:00
protected :
ParameterT m_value ;
2022-07-13 12:44:19 +02:00
Vector < Function < void ( ParameterT const & ) > > m_change_value_listeners ;
2021-08-27 16:18:11 +02:00
} ;
}
class ProcessorBooleanParameter final : public Detail : : ProcessorParameterSingleValue < bool > {
public :
2022-12-04 18:02:33 +00:00
ProcessorBooleanParameter ( DeprecatedString name , bool initial_value )
2021-09-28 18:01:39 +02:00
: Detail : : ProcessorParameterSingleValue < bool > ( move ( name ) , ParameterType : : Boolean , move ( initial_value ) )
2021-08-27 16:18:11 +02:00
{
}
} ;
class ProcessorRangeParameter final : public Detail : : ProcessorParameterSingleValue < ParameterFixedPoint > {
public :
2022-12-04 18:02:33 +00:00
ProcessorRangeParameter ( DeprecatedString name , ParameterFixedPoint min_value , ParameterFixedPoint max_value , ParameterFixedPoint initial_value , Logarithmic logarithmic )
2021-09-28 18:01:39 +02:00
: Detail : : ProcessorParameterSingleValue < ParameterFixedPoint > ( move ( name ) , ParameterType : : Range , move ( initial_value ) )
2021-08-27 16:18:11 +02:00
, m_min_value ( move ( min_value ) )
, m_max_value ( move ( max_value ) )
, m_default_value ( move ( initial_value ) )
2021-10-12 01:15:12 +02:00
, m_logarithmic ( logarithmic )
2021-08-27 16:18:11 +02:00
{
VERIFY ( initial_value < = max_value & & initial_value > = min_value ) ;
}
ProcessorRangeParameter ( ProcessorRangeParameter const & to_copy )
2021-10-12 01:15:12 +02:00
: ProcessorRangeParameter ( to_copy . name ( ) , to_copy . min_value ( ) , to_copy . max_value ( ) , to_copy . value ( ) , to_copy . is_logarithmic ( ) )
2021-08-27 16:18:11 +02:00
{
}
ParameterFixedPoint min_value ( ) const { return m_min_value ; }
ParameterFixedPoint max_value ( ) const { return m_max_value ; }
2021-10-12 01:15:12 +02:00
ParameterFixedPoint range ( ) const { return m_max_value - m_min_value ; }
constexpr Logarithmic is_logarithmic ( ) const { return m_logarithmic ; }
2021-08-27 16:18:11 +02:00
ParameterFixedPoint default_value ( ) const { return m_default_value ; }
void set_value ( ParameterFixedPoint value )
{
VERIFY ( value < = m_max_value & & value > = m_min_value ) ;
Detail : : ProcessorParameterSingleValue < ParameterFixedPoint > : : set_value ( value ) ;
}
private :
double const m_min_value ;
double const m_max_value ;
double const m_default_value ;
2021-10-12 01:15:12 +02:00
Logarithmic const m_logarithmic ;
2021-08-27 16:18:11 +02:00
} ;
2022-11-14 18:20:59 +00:00
template < Enum EnumT >
class ProcessorEnumParameter final : public Detail : : ProcessorParameterSingleValue < EnumT > {
2021-10-31 14:09:43 +01:00
public :
2022-12-04 18:02:33 +00:00
ProcessorEnumParameter ( DeprecatedString name , EnumT initial_value )
2021-09-28 18:01:39 +02:00
: Detail : : ProcessorParameterSingleValue < EnumT > ( move ( name ) , ParameterType : : Enum , initial_value )
2021-10-31 14:09:43 +01:00
{
}
} ;
2021-08-27 16:18:11 +02:00
}
template < >
2022-07-17 11:35:31 +02:00
struct AK : : Formatter < DSP : : ProcessorRangeParameter > : AK : : StandardFormatter {
2021-08-27 16:18:11 +02:00
Formatter ( ) = default ;
explicit Formatter ( StandardFormatter formatter )
: StandardFormatter ( formatter )
{
}
2022-07-17 11:35:31 +02:00
ErrorOr < void > format ( FormatBuilder & builder , DSP : : ProcessorRangeParameter value )
2021-08-27 16:18:11 +02:00
{
if ( m_mode = = Mode : : Pointer ) {
Formatter < FlatPtr > formatter { * this } ;
2021-11-16 01:15:21 +01:00
return formatter . format ( builder , reinterpret_cast < FlatPtr > ( & value ) ) ;
2021-08-27 16:18:11 +02:00
}
if ( m_sign_mode ! = FormatBuilder : : SignMode : : Default )
VERIFY_NOT_REACHED ( ) ;
if ( m_alternative_form )
VERIFY_NOT_REACHED ( ) ;
if ( m_zero_pad )
VERIFY_NOT_REACHED ( ) ;
if ( m_mode ! = Mode : : Default )
VERIFY_NOT_REACHED ( ) ;
if ( m_width . has_value ( ) & & m_precision . has_value ( ) )
VERIFY_NOT_REACHED ( ) ;
m_width = m_width . value_or ( 0 ) ;
m_precision = m_precision . value_or ( NumericLimits < size_t > : : max ( ) ) ;
2022-12-04 18:02:33 +00:00
TRY ( builder . put_literal ( DeprecatedString : : formatted ( " [{} - {}]: {} " , value . min_value ( ) , value . max_value ( ) , value . value ( ) ) ) ) ;
2021-11-16 01:15:21 +01:00
return { } ;
2021-08-27 16:18:11 +02:00
}
} ;