Log scales finalized
This commit is contained in:
@@ -162,7 +162,11 @@ public:
|
||||
{
|
||||
return castValue<T>( m_step );
|
||||
}
|
||||
|
||||
|
||||
//! @brief Returns value scaled with the scale type and min/max values of this model
|
||||
float scaledValue( float value ) const;
|
||||
//! @brief Returns value applied with the inverse of this model's scale type
|
||||
float inverseScaledValue( float value ) const;
|
||||
|
||||
void setInitValue( const float value );
|
||||
|
||||
@@ -187,6 +191,10 @@ public:
|
||||
{
|
||||
setScaleType( setToTrue ? Logarithmic : Linear );
|
||||
}
|
||||
bool isScaleLogarithmic() const
|
||||
{
|
||||
return m_scaleType == Logarithmic;
|
||||
}
|
||||
|
||||
void setStep( const float step );
|
||||
|
||||
@@ -224,16 +232,7 @@ public:
|
||||
return "automatablemodel";
|
||||
}
|
||||
|
||||
QString displayValue( const float val ) const
|
||||
{
|
||||
switch( m_dataType )
|
||||
{
|
||||
case Float: return QString::number( castValue<float>( val ) );
|
||||
case Integer: return QString::number( castValue<int>( val ) );
|
||||
case Bool: return QString::number( castValue<bool>( val ) );
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
QString displayValue( const float val ) const;
|
||||
|
||||
bool hasLinkedModels() const
|
||||
{
|
||||
|
||||
@@ -22,10 +22,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LMMS_CONSTANTS_H
|
||||
#define _LMMS_CONSTANTS_H
|
||||
#ifndef LMMS_CONSTANTS_H
|
||||
#define LMMS_CONSTANTS_H
|
||||
|
||||
const float F_PI = 3.1415926535f;
|
||||
const float F_E = 2.718281828459045f;
|
||||
const float F_2PI = 2*F_PI;
|
||||
const float F_PI_2 = F_PI*0.5;
|
||||
|
||||
|
||||
@@ -128,5 +128,42 @@ static inline double sinc( double _x )
|
||||
}
|
||||
|
||||
|
||||
//! @brief Returns logarithm of value, while accounting for zeros or negative values
|
||||
static inline float saneLog( float value )
|
||||
{
|
||||
if( value == 0.0f )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return value < 0.0f
|
||||
? logf( -value ) * -1.0f
|
||||
: logf( value );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @brief Scales @value from linear to logarithmic.
|
||||
//! Value should be within [0,1]
|
||||
static inline float logToLinearScale( float min, float max, float value )
|
||||
{
|
||||
if( min < 0 )
|
||||
{
|
||||
return powf( value * ( 1.0f - min / max ) + min / max, F_E ) * ( max - min ) + min;
|
||||
}
|
||||
return powf( value, F_E ) * ( max - min ) + min;
|
||||
}
|
||||
|
||||
|
||||
//! @brief Scales value from logarithmic to linear. Value should be in min-max range.
|
||||
static inline float linearToLogScale( float min, float max, float value )
|
||||
{
|
||||
static const float EXP = 1.0f / F_E;
|
||||
const float val = ( value - min ) / ( max - min );
|
||||
if( min < 0 )
|
||||
{
|
||||
return powf( val * ( 1.0f - min / max ) + min / max, EXP ) * ( max - min ) + min;
|
||||
}
|
||||
return powf( val, EXP ) * ( max - min ) + min;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LADSPA_CONTROL_DIALOG_H
|
||||
#define _LADSPA_CONTROL_DIALOG_H
|
||||
#ifndef LADSPA_CONTROL_DIALOG_H
|
||||
#define LADSPA_CONTROL_DIALOG_H
|
||||
|
||||
#include "EffectControlDialog.h"
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LADSPA_CONTROLS_H
|
||||
#define _LADSPA_CONTROLS_H
|
||||
#ifndef LADSPA_CONTROLS_H
|
||||
#define LADSPA_CONTROLS_H
|
||||
|
||||
#include "EffectControls.h"
|
||||
#include "LadspaControl.h"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "AutomatableModel.h"
|
||||
#include "AutomationPattern.h"
|
||||
#include "ControllerConnection.h"
|
||||
|
||||
#include "lmms_math.h"
|
||||
|
||||
float AutomatableModel::s_copiedValue = 0;
|
||||
|
||||
@@ -246,25 +246,42 @@ void AutomatableModel::setValue( const float value )
|
||||
|
||||
|
||||
|
||||
//! @brief Scales @value from linear to logarithmic.
|
||||
//! Value should be within [0,1]
|
||||
//! @todo This should be moved into a maths header
|
||||
template<class T> T logToLinearScale(T min, T max, T value)
|
||||
template<class T> T AutomatableModel::logToLinearScale( T value ) const
|
||||
{
|
||||
return exp( ( log(max) - log(min) ) * value + log(min) );
|
||||
return castValue<T>( ::logToLinearScale( minValue<float>(), maxValue<float>(), static_cast<float>( value ) ) );
|
||||
}
|
||||
|
||||
|
||||
float AutomatableModel::scaledValue( float value ) const
|
||||
{
|
||||
return m_scaleType == Linear
|
||||
? value
|
||||
: logToLinearScale<float>( ( value - minValue<float>() ) / m_range );
|
||||
}
|
||||
|
||||
|
||||
float AutomatableModel::inverseScaledValue( float value ) const
|
||||
{
|
||||
return m_scaleType == Linear
|
||||
? value
|
||||
: ::linearToLogScale( minValue<float>(), maxValue<float>(), value );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class T> T AutomatableModel::logToLinearScale(T value) const
|
||||
QString AutomatableModel::displayValue( const float val ) const
|
||||
{
|
||||
return ::logToLinearScale( minValue<float>(), maxValue<float>(), value );
|
||||
switch( m_dataType )
|
||||
{
|
||||
case Float: return QString::number( castValue<float>( scaledValue( val ) ) );
|
||||
case Integer: return QString::number( castValue<int>( scaledValue( val ) ) );
|
||||
case Bool: return QString::number( castValue<bool>( scaledValue( val ) ) );
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! @todo: this should be moved into a maths header
|
||||
template<class T>
|
||||
void roundAt( T& value, const T& where, const T& step_size )
|
||||
@@ -293,13 +310,7 @@ void AutomatableModel::setAutomatedValue( const float value )
|
||||
++m_setValueDepth;
|
||||
const float oldValue = m_value;
|
||||
|
||||
const float scaled_value =
|
||||
( m_scaleType == Linear )
|
||||
? value
|
||||
: logToLinearScale(
|
||||
// fits value into [0,1]:
|
||||
(value - minValue<float>()) / maxValue<float>()
|
||||
);
|
||||
const float scaled_value = scaledValue( value );
|
||||
|
||||
m_value = fittedValue( scaled_value );
|
||||
|
||||
@@ -313,9 +324,7 @@ void AutomatableModel::setAutomatedValue( const float value )
|
||||
!(*it)->fittedValue( m_value ) !=
|
||||
(*it)->m_value )
|
||||
{
|
||||
// @TOBY: don't take m_value, but better: value,
|
||||
// otherwise, we convert to log twice?
|
||||
(*it)->setAutomatedValue( m_value );
|
||||
(*it)->setAutomatedValue( value );
|
||||
}
|
||||
}
|
||||
emit dataChanged();
|
||||
@@ -604,13 +613,7 @@ float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
{
|
||||
// scale/fit the value appropriately and return it
|
||||
const float value = latestPattern->valueAt( time - latestPattern->startPosition() );
|
||||
const float scaled_value =
|
||||
( m_scaleType == Linear )
|
||||
? value
|
||||
: logToLinearScale(
|
||||
// fits value into [0,1]:
|
||||
(value - minValue<float>()) / maxValue<float>()
|
||||
);
|
||||
const float scaled_value = scaledValue( value );
|
||||
return fittedValue( scaled_value );
|
||||
}
|
||||
// if we still find no pattern, the value at that time is undefined so
|
||||
|
||||
@@ -76,7 +76,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port,
|
||||
( m_port->max - m_port->min )
|
||||
/ ( m_port->name.toUpper() == "GAIN"
|
||||
&& m_port->max == 10.0f ? 4000.0f :
|
||||
400.0f ) );
|
||||
( m_port->suggests_logscale ? 8000.0f : 800.0f ) ) );
|
||||
m_knobModel.setInitValue( m_port->def );
|
||||
connect( &m_knobModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( knobChanged() ) );
|
||||
@@ -87,7 +87,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port,
|
||||
case TIME:
|
||||
m_tempoSyncKnobModel.setRange( m_port->min, m_port->max,
|
||||
( m_port->max -
|
||||
m_port->min ) / 400.0f );
|
||||
m_port->min ) / 800.0f );
|
||||
m_tempoSyncKnobModel.setInitValue( m_port->def );
|
||||
connect( &m_tempoSyncKnobModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( tempoKnobChanged() ) );
|
||||
|
||||
@@ -1359,7 +1359,8 @@ inline void AutomationEditor::drawCross( QPainter & _p )
|
||||
QPoint tt_pos = QCursor::pos();
|
||||
tt_pos.ry() -= 64;
|
||||
tt_pos.rx() += 32;
|
||||
QToolTip::showText( tt_pos,QString::number( level ),this);
|
||||
float scaledLevel = m_pattern->firstObject()->scaledValue( level );
|
||||
QToolTip::showText( tt_pos, QString::number( scaledLevel ), this );
|
||||
}
|
||||
|
||||
|
||||
@@ -1896,17 +1897,10 @@ float AutomationEditor::getLevel( int _y )
|
||||
// pressed level
|
||||
float level = roundf( ( m_bottomLevel + ( m_y_auto ?
|
||||
( m_maxLevel - m_minLevel ) * ( level_line_y - _y )
|
||||
/ (float)( level_line_y - TOP_MARGIN ) :
|
||||
/ (float)( level_line_y - ( TOP_MARGIN + 2 ) ) :
|
||||
( level_line_y - _y ) / (float)m_y_delta ) ) / m_step ) * m_step;
|
||||
// some range-checking-stuff
|
||||
if( level < m_bottomLevel )
|
||||
{
|
||||
level = m_bottomLevel;
|
||||
}
|
||||
else if( level > m_topLevel )
|
||||
{
|
||||
level = m_topLevel;
|
||||
}
|
||||
level = qBound( m_bottomLevel, level, m_topLevel );
|
||||
|
||||
return( level );
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#ifndef __USE_XOPEN
|
||||
#define __USE_XOPEN
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#include "lmms_math.h"
|
||||
#include "knob.h"
|
||||
#include "caption_menu.h"
|
||||
#include "config_mgr.h"
|
||||
@@ -320,7 +320,7 @@ bool knob::updateAngle()
|
||||
int angle = 0;
|
||||
if( model() && model()->maxValue() != model()->minValue() )
|
||||
{
|
||||
angle = angleFromValue( model()->value(), model()->minValue(), model()->maxValue(), m_totalAngle );
|
||||
angle = angleFromValue( model()->inverseScaledValue( model()->value() ), model()->minValue(), model()->maxValue(), m_totalAngle );
|
||||
}
|
||||
if( qAbs( angle - m_angle ) > 3 )
|
||||
{
|
||||
@@ -388,7 +388,7 @@ void knob::drawKnob( QPainter * _p )
|
||||
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
const int centerAngle = angleFromValue( model()->centerValue(), model()->minValue(), model()->maxValue(), m_totalAngle );
|
||||
const int centerAngle = angleFromValue( model()->inverseScaledValue( model()->centerValue() ), model()->minValue(), model()->maxValue(), m_totalAngle );
|
||||
|
||||
const int arcLineWidth = 2;
|
||||
const int arcRectSize = m_knobPixmap->width() - arcLineWidth;
|
||||
@@ -669,15 +669,37 @@ void knob::setPosition( const QPoint & _p )
|
||||
{
|
||||
const float value = getValue( _p ) + m_leftOver;
|
||||
const float step = model()->step<float>();
|
||||
|
||||
if( qAbs( value ) >= step )
|
||||
const float oldValue = model()->value();
|
||||
|
||||
|
||||
if( model()->isScaleLogarithmic() ) // logarithmic code
|
||||
{
|
||||
model()->setValue( model()->value() - value );
|
||||
m_leftOver = 0.0f;
|
||||
const float pos = ( oldValue - model()->minValue() ) / model()->range();
|
||||
const float ratio = 0.1f + pos * 15.f;
|
||||
float newValue = value * ratio;
|
||||
if( qAbs( newValue ) >= step )
|
||||
{
|
||||
model()->setValue( oldValue - newValue );
|
||||
m_leftOver = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_leftOver = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
else // linear code
|
||||
{
|
||||
m_leftOver = value;
|
||||
if( qAbs( value ) >= step )
|
||||
{
|
||||
model()->setValue( oldValue - value );
|
||||
m_leftOver = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_leftOver = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user