Merge pull request #799 from diizy/models3

S.ex. models: implement support for sample-exact controls in fx-mixer
This commit is contained in:
Tobias Doerffel
2014-06-01 14:31:21 +02:00
6 changed files with 106 additions and 23 deletions

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef _FX_MIXER_H
#define _FX_MIXER_H
#ifndef FX_MIXER_H
#define FX_MIXER_H
#include "Model.h"
#include "Mixer.h"

View File

@@ -22,11 +22,12 @@
*
*/
#ifndef _MIX_HELPERS_H
#define _MIX_HELPERS_H
#ifndef MIX_HELPERS_H
#define MIX_HELPERS_H
#include "lmms_basics.h"
class ValueBuffer;
namespace MixHelpers
{
@@ -39,6 +40,12 @@ void add( sampleFrame* dst, const sampleFrame* src, int frames );
/*! \brief Add samples from src multiplied by coeffSrc to dst */
void addMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst */
void addMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames );
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst */
void addMultipliedByBuffers( sampleFrame* dst, const sampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames );
/*! \brief Add samples from src multiplied by coeffSrcLeft/coeffSrcRight to dst */
void addMultipliedStereo( sampleFrame* dst, const sampleFrame* src, float coeffSrcLeft, float coeffSrcRight, int frames );

View File

@@ -26,6 +26,7 @@
#ifndef VALUE_BUFFER_H
#define VALUE_BUFFER_H
#include <QtGlobal>
#include "interpolation.h"
#include <string.h>
@@ -122,6 +123,29 @@ public:
}
}
void multiply( float f )
{
for( int i = 0; i < m_length; i++ )
{
m_values[i] *= f;
}
}
ValueBuffer & operator*=( const float & f )
{
multiply( f );
return *this;
}
ValueBuffer & operator+=( const ValueBuffer & v )
{
for( int i = 0; i < qMin( m_length, v.length() ); i++ )
{
m_values[i] += v.values()[i];
}
return *this;
}
static ValueBuffer interpolatedBuffer( float start, float end, int length )
{
ValueBuffer vb = ValueBuffer( length );

View File

@@ -115,10 +115,10 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
: m_ampControls.m_panModel.value();
const float left1 = pan <= 0
? 1.0
: 1.0 - m_ampControls.m_panModel.value( f ) * 0.01f;
: 1.0 - pan * 0.01f;
const float right1 = pan >= 0
? 1.0
: 1.0 + m_ampControls.m_panModel.value( ) * 0.01f;
: 1.0 + pan * 0.01f;
// second stage amplification
const float left2 = leftBuf

View File

@@ -32,7 +32,7 @@
#include "InstrumentTrack.h"
#include "bb_track_container.h"
#include "ValueBuffer.h"
FxChannel::FxChannel( int idx, Model * _parent ) :
m_fxChain( NULL ),
@@ -42,7 +42,7 @@ FxChannel::FxChannel( int idx, Model * _parent ) :
m_peakRight( 0.0f ),
m_buffer( new sampleFrame[engine::mixer()->framesPerPeriod()] ),
m_muteModel( false, _parent ),
m_volumeModel( 1.0, 0.0, 2.0, 0.01, _parent ),
m_volumeModel( 1.0, 0.0, 2.0, 0.001, _parent ),
m_name(),
m_lock(),
m_channelIndex( idx ),
@@ -79,10 +79,7 @@ void FxChannel::doProcessing( sampleFrame * _buf )
// SMF: OK, due to the fact, that the data from the audio-tracks has been
// written into our buffer already, all which needs to be done at this
// stage is to process inter-channel sends. I really don't like the idea
// of using threads for this -- it just doesn't make any sense and wastes
// cpu-cylces... so I just go through every child of this channel and
// call the acc. doProcessing() directly.
// stage is to process inter-channel sends.
if( m_muteModel.value() == false )
{
@@ -103,20 +100,39 @@ void FxChannel::doProcessing( sampleFrame * _buf )
if( sender->m_hasInput || sender->m_stillRunning )
{
// get the send level...
const float amt =
fxm->channelSendModel( senderIndex, m_channelIndex )->value();
// figure out if we're getting sample-exact input
ValueBuffer * sendBuf = fxm->channelSendModel( senderIndex, m_channelIndex )->hasSampleExactData()
? fxm->channelSendModel( senderIndex, m_channelIndex )->valueBuffer()
: NULL;
ValueBuffer * volBuf = sender->m_volumeModel.hasSampleExactData()
? sender->m_volumeModel.valueBuffer()
: NULL;
// mix it's output with this one's output
sampleFrame * ch_buf = sender->m_buffer;
const float v = sender->m_volumeModel.value() * amt;
for( f_cnt_t f = 0; f < fpp; ++f )
// use sample-exact mixing if sample-exact values are available
if( ! volBuf && ! sendBuf ) // neither volume nor send has sample-exact data...
{
_buf[f][0] += ch_buf[f][0] * v;
_buf[f][1] += ch_buf[f][1] * v;
const float v = sender->m_volumeModel.value() * fxm->channelSendModel( senderIndex, m_channelIndex )->value();
MixHelpers::addMultiplied( _buf, ch_buf, v, fpp );
}
else if( volBuf && sendBuf ) // both volume and send have sample-exact data
{
MixHelpers::addMultipliedByBuffers( _buf, ch_buf, volBuf, sendBuf, fpp );
}
else if( volBuf ) // volume has sample-exact data but send does not
{
const float v = fxm->channelSendModel( senderIndex, m_channelIndex )->value();
MixHelpers::addMultipliedByBuffer( _buf, ch_buf, v, volBuf, fpp );
}
else // vice versa
{
const float v = sender->m_volumeModel.value();
MixHelpers::addMultipliedByBuffer( _buf, ch_buf, v, sendBuf, fpp );
}
}
// if sender channel hasInput, then we hasInput too
if( sender->m_hasInput ) m_hasInput = true;
}
@@ -124,10 +140,10 @@ void FxChannel::doProcessing( sampleFrame * _buf )
const float v = m_volumeModel.value();
if( m_hasInput )
if( m_hasInput )
{
// only start fxchain when we have input...
m_fxChain.startRunning();
m_fxChain.startRunning();
}
if( m_hasInput || m_stillRunning )
{
@@ -488,7 +504,23 @@ void FxMixer::masterMix( sampleFrame * _buf )
}
//m_fxChannels[0]->doProcessing( NULL );
const float v = m_fxChannels[0]->m_volumeModel.value();
// handle sample-exact data in master volume fader
ValueBuffer * volBuf = m_fxChannels[0]->m_volumeModel.hasSampleExactData()
? m_fxChannels[0]->m_volumeModel.valueBuffer()
: NULL;
if( volBuf )
{
for( int f = 0; f < fpp; f++ )
{
m_fxChannels[0]->m_buffer[f][0] *= volBuf->values()[f];
m_fxChannels[0]->m_buffer[f][1] *= volBuf->values()[f];
}
}
const float v = volBuf
? 1.0f
: m_fxChannels[0]->m_volumeModel.value();
MixHelpers::addMultiplied( _buf, m_fxChannels[0]->m_buffer, v, fpp );
m_fxChannels[0]->m_peakLeft *= engine::mixer()->masterGain();

View File

@@ -25,6 +25,7 @@
#include <math.h>
#include "MixHelpers.h"
#include "ValueBuffer.h"
namespace MixHelpers
@@ -105,6 +106,25 @@ void addMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, in
}
void addMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames )
{
for( int f = 0; f < frames; ++f )
{
dst[f][0] += src[f][0] * coeffSrc * coeffSrcBuf->values()[f];
dst[f][1] += src[f][1] * coeffSrc * coeffSrcBuf->values()[f];
}
}
void addMultipliedByBuffers( sampleFrame* dst, const sampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames )
{
for( int f = 0; f < frames; ++f )
{
dst[f][0] += src[f][0] * coeffSrcBuf1->values()[f] * coeffSrcBuf2->values()[f];
dst[f][1] += src[f][1] * coeffSrcBuf1->values()[f] * coeffSrcBuf2->values()[f];
}
}
struct AddMultipliedStereoOp
{