Skip to content

Commit

Permalink
Initial implementation of sample-exact models and controllers
Browse files Browse the repository at this point in the history
Also featuring a very efficient buffer-based system for transporting sample-exact control data
Also interpolation for automations
The native Amplifier is a reference implementation for taking advantage of sample-exact data and is currently
the only one that does so, it can be used to test things out, and as documentation/example for implementing the
same elsewhere
  • Loading branch information
diizy committed May 30, 2014
1 parent 3a833d2 commit 44f1d3d
Show file tree
Hide file tree
Showing 16 changed files with 484 additions and 126 deletions.
34 changes: 31 additions & 3 deletions include/AutomatableModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "JournallingObject.h"
#include "Model.h"
#include "MidiTime.h"
#include "ValueBuffer.h"


// simple way to map a property of a view to a model
Expand Down Expand Up @@ -98,6 +99,13 @@ class EXPORT AutomatableModel : public Model, public JournallingObject
}

bool isAutomated() const;
bool isAutomatedOrControlled() const
{
return isAutomated() || m_controllerConnection != NULL;
}

bool hasSampleExactData() const;


ControllerConnection* controllerConnection() const
{
Expand Down Expand Up @@ -134,6 +142,12 @@ class EXPORT AutomatableModel : public Model, public JournallingObject

float controllerValue( int frameOffset ) const;

// returns sample-exact data as a ValueBuffer
// should only be called when sample-exact data exists
// in other cases (eg. for automation), the receiving end should interpolate
// the values themselves
ValueBuffer * valueBuffer();

template<class T>
T initValue() const
{
Expand Down Expand Up @@ -241,6 +255,16 @@ class EXPORT AutomatableModel : public Model, public JournallingObject
}

float globalAutomationValueAt( const MidiTime& time );

bool strictStepSize() const
{
return m_strictStepSize;
}

void setStrictStepSize( const bool b )
{
m_strictStepSize = b;
}

public slots:
virtual void reset();
Expand All @@ -254,7 +278,7 @@ public slots:
//! max() and aligned according to the step size (step size 0.05 -> value
//! 0.12345 becomes 0.10 etc.). You should always call it at the end after
//! doing your own calculations.
float fittedValue( float value ) const;
float fittedValue( float value, bool forceStep = false ) const;


private:
Expand Down Expand Up @@ -290,10 +314,13 @@ public slots:
float m_range;
float m_centerValue;

// most objects will need this temporarily (until sampleExact is
// standard)
// currently unused?
float m_oldValue;
int m_setValueDepth;

// used to determine if step size should be applied strictly (ie. always)
// or only when value set from gui (default)
bool m_strictStepSize;

AutoModelVector m_linkedModels;
bool m_hasLinkedModels;
Expand All @@ -305,6 +332,7 @@ public slots:

static float s_copiedValue;

ValueBuffer m_valueBuffer;

signals:
void initValueChanged( float val );
Expand Down
18 changes: 17 additions & 1 deletion include/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "Mixer.h"
#include "Model.h"
#include "JournallingObject.h"
#include "ValueBuffer.h"

class ControllerDialog;
class Controller;
Expand Down Expand Up @@ -62,6 +63,8 @@ class Controller : public Model, public JournallingObject
virtual ~Controller();

virtual float currentValue( int _offset );
// The per-controller get-value-in-buffers function
virtual ValueBuffer * valueBuffer();

inline bool isSampleExact() const
{
Expand Down Expand Up @@ -111,6 +114,10 @@ class Controller : public Model, public JournallingObject
return tLimit<float>( _val, 0.0f, 1.0f );
}

static unsigned int runningPeriods()
{
return s_periods;
}
static unsigned int runningFrames();
static float runningTime();

Expand Down Expand Up @@ -138,6 +145,15 @@ public slots:
// The internal per-controller get-value function
virtual float value( int _offset );

virtual void updateValueBuffer();

// buffer for storing sample-exact values in case there
// are more than one model wanting it, so we don't have to create it
// again every time
ValueBuffer m_valueBuffer;
// when we last updated the valuebuffer - so we know if we have to update it
unsigned int m_bufferLastUpdated;

float m_currentValue;
bool m_sampleExact;
int m_connectionCount;
Expand All @@ -147,7 +163,7 @@ public slots:

static ControllerVector s_controllers;

static unsigned int s_frames;
static unsigned int s_periods;


signals:
Expand Down
10 changes: 8 additions & 2 deletions include/ControllerConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@
*/


#ifndef _CONTROLLER_CONNECTION_H
#define _CONTROLLER_CONNECTION_H
#ifndef CONTROLLER_CONNECTION_H
#define CONTROLLER_CONNECTION_H

#include <QtCore/QObject>
#include <QtCore/QVector>

#include "Controller.h"
#include "JournallingObject.h"
#include "ValueBuffer.h"

class ControllerConnection;

Expand Down Expand Up @@ -64,6 +65,11 @@ class EXPORT ControllerConnection : public QObject, public JournallingObject
{
return m_controller->currentValue( _offset );
}

ValueBuffer * valueBuffer()
{
return m_controller->valueBuffer();
}

inline void setTargetName( const QString & _name );

Expand Down
18 changes: 10 additions & 8 deletions include/LfoController.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
*
*/

#ifndef _LFO_CONTROLLER_H
#define _LFO_CONTROLLER_H
#ifndef LFO_CONTROLLER_H
#define LFO_CONTROLLER_H

#include <QtGui/QWidget>

Expand Down Expand Up @@ -59,8 +59,8 @@ public slots:


protected:
// The internal per-controller get-value function
virtual float value( int _offset );
// The internal per-controller value updating function
virtual void updateValueBuffer();

FloatModel m_baseModel;
TempoSyncKnobModel m_speedModel;
Expand All @@ -69,17 +69,19 @@ public slots:
IntModel m_waveModel;
IntModel m_multiplierModel;

int m_duration;
int m_phaseCorrection;
int m_phaseOffset;
float m_duration;
float m_phaseOffset;
float m_currentPhase;

sample_t (*m_sampleFunction)( const float );

private:
SampleBuffer * m_userDefSampleBuffer;

protected slots:
void updatePhase();
void updateSampleFunction();
void updateDuration();

friend class LfoControllerDialog;

Expand Down
7 changes: 4 additions & 3 deletions include/MidiController.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
*
*/

#ifndef _MIDI_CONTROLLER_H
#define _MIDI_CONTROLLER_H
#ifndef MIDI_CONTROLLER_H
#define MIDI_CONTROLLER_H

#include <QtGui/QWidget>

Expand Down Expand Up @@ -67,13 +67,14 @@ public slots:

protected:
// The internal per-controller get-value function
virtual float value( int _offset );
virtual void updateValueBuffer();


MidiPort m_midiPort;


float m_lastValue;
float m_previousValue;

friend class ControllerConnectionDialog;
friend class AutoDetectMidiController;
Expand Down
6 changes: 3 additions & 3 deletions include/PeakController.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
*
*/

#ifndef _PEAK_CONTROLLER_H
#define _PEAK_CONTROLLER_H
#ifndef PEAK_CONTROLLER_H
#define PEAK_CONTROLLER_H

#include <QtGui/QWidget>

Expand Down Expand Up @@ -65,7 +65,7 @@ public slots:

protected:
// The internal per-controller get-value function
virtual float value( int _offset );
virtual void updateValueBuffer();

PeakControllerEffect * m_peakEffect;

Expand Down
137 changes: 137 additions & 0 deletions include/ValueBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* ValueBuffer.h - a container class for passing buffers of model values around
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#ifndef VALUE_BUFFER_H
#define VALUE_BUFFER_H

#include "interpolation.h"
#include <string.h>

class ValueBuffer
{
public:
ValueBuffer()
{
m_values = NULL;
m_length = 0;
}

ValueBuffer( int length )
{
m_values = new float[length];
m_length = length;
}

ValueBuffer( float * values, int length )
{
m_values = new float[length];
m_length = length;
memcpy( m_values, values, sizeof(float) * length );
}

ValueBuffer( float value, int length )
{
m_values = new float[length];
m_length = length;
for( int i = 0; i < length; i++ )
{
m_values[i] = value;
}
}

virtual ~ValueBuffer()
{
delete[] m_values;
}

void clear()
{
delete[] m_values;
m_values = NULL;
m_length = 0;
}

void fill( float value )
{
for( int i = 0; i < m_length; i++ )
{
m_values[i] = value;
}
}

float value( int offset ) const
{
return m_values[ offset % m_length ];
}

void setValue( int offset, float value )
{
m_values[ offset % m_length ] = value;
}

float * values() const
{
return m_values;
}

void setValues( float * values )
{
m_values = values;
}

int length() const
{
return m_length;
}

void setLength( const int length )
{
m_length = length;
}

void interpolate( float start, float end )
{
float f = 0.0f;
const float fstep = 1.0f / static_cast<float>( m_length );
for( int i = 0; i < m_length; i++ )
{
f += fstep;
m_values[i] = linearInterpolate( start, end, f );
}
}

static ValueBuffer interpolatedBuffer( float start, float end, int length )
{
ValueBuffer vb = ValueBuffer( length );
vb.interpolate( start, end );
return vb;
}

private:
float * m_values;
int m_length;
};

#endif
Loading

0 comments on commit 44f1d3d

Please sign in to comment.