Log scales finalized

This commit is contained in:
Vesa
2014-06-20 22:46:10 +03:00
parent 737839164a
commit 14909bdf1b
9 changed files with 121 additions and 65 deletions

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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() ) );

View File

@@ -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 );
}

View File

@@ -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;
}
}
}