Merge branch 'master' into cmake_dist
# Conflicts: # include/Plugin.h # src/core/Plugin.cpp
This commit is contained in:
@@ -83,18 +83,45 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
if( m_bbControls.m_gainModel.isValueChanged() ) { changeGain(); }
|
||||
if( m_bbControls.m_ratioModel.isValueChanged() ) { changeRatio(); }
|
||||
|
||||
float gain = m_bbControls.m_gainModel.value();
|
||||
ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer();
|
||||
int gainInc = gainBuffer ? 1 : 0;
|
||||
float *gainPtr = gainBuffer ? &( gainBuffer->values()[ 0 ] ) : &gain;
|
||||
|
||||
double outSum = 0.0;
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
if( gainBuffer )
|
||||
{
|
||||
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
|
||||
//process period using sample exact data
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
{
|
||||
m_bbFX.leftFX().setGain( *gainPtr );
|
||||
m_bbFX.rightFX().setGain( *gainPtr );
|
||||
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
|
||||
|
||||
sample_t s[2] = { buf[f][0], buf[f][1] };
|
||||
m_bbFX.nextSample( s[0], s[1] );
|
||||
sample_t s[2] = { buf[f][0], buf[f][1] };
|
||||
m_bbFX.nextSample( s[0], s[1] );
|
||||
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
gainPtr += gainInc;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//process period without sample exact data
|
||||
m_bbFX.leftFX().setGain( *gainPtr );
|
||||
m_bbFX.rightFX().setGain( *gainPtr );
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
{
|
||||
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
|
||||
|
||||
sample_t s[2] = { buf[f][0], buf[f][1] };
|
||||
m_bbFX.nextSample( s[0], s[1] );
|
||||
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
}
|
||||
}
|
||||
|
||||
checkGate( outSum / frames );
|
||||
|
||||
@@ -10,7 +10,7 @@ ADD_SUBDIRECTORY(carlabase)
|
||||
ADD_SUBDIRECTORY(carlapatchbay)
|
||||
ADD_SUBDIRECTORY(carlarack)
|
||||
ADD_SUBDIRECTORY(CrossoverEQ)
|
||||
ADD_SUBDIRECTORY(delay)
|
||||
ADD_SUBDIRECTORY(Delay)
|
||||
ADD_SUBDIRECTORY(DualFilter)
|
||||
ADD_SUBDIRECTORY(dynamics_processor)
|
||||
ADD_SUBDIRECTORY(Eq)
|
||||
@@ -23,6 +23,7 @@ ADD_SUBDIRECTORY(LadspaEffect)
|
||||
ADD_SUBDIRECTORY(lb302)
|
||||
#ADD_SUBDIRECTORY(lb303)
|
||||
ADD_SUBDIRECTORY(MidiImport)
|
||||
ADD_SUBDIRECTORY(MidiExport)
|
||||
ADD_SUBDIRECTORY(MultitapEcho)
|
||||
ADD_SUBDIRECTORY(monstro)
|
||||
ADD_SUBDIRECTORY(nes)
|
||||
|
||||
3
plugins/Delay/CMakeLists.txt
Normal file
3
plugins/Delay/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
BUILD_PLUGIN(delay DelayEffect.cpp DelayControls.cpp DelayControlsDialog.cpp Lfo.cpp StereoDelay.cpp MOCFILES DelayControls.h DelayControlsDialog.h ../Eq/EqFader.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
#include <QtXml/QDomElement>
|
||||
|
||||
#include "delaycontrols.h"
|
||||
#include "delayeffect.h"
|
||||
#include "DelayControls.h"
|
||||
#include "DelayEffect.h"
|
||||
#include "Engine.h"
|
||||
#include "Song.h"
|
||||
|
||||
@@ -35,9 +35,12 @@ DelayControls::DelayControls( DelayEffect* effect ):
|
||||
m_delayTimeModel( 0.5, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Delay Samples" )) ,
|
||||
m_feedbackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ),
|
||||
m_lfoTimeModel(2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Lfo Frequency" ) ),
|
||||
m_lfoAmountModel(0.0, 0.0, 2.0, 0.0001, 2000.0, this, tr ( "Lfo Amount" ) )
|
||||
m_lfoAmountModel(0.0, 0.0, 2.0, 0.0001, 2000.0, this, tr ( "Lfo Amount" ) ),
|
||||
m_outGainModel( 0.0, -60.0, 20.0, 0.01, this, tr( "Output gain" ) )
|
||||
{
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changeSampleRate() ) );
|
||||
m_outPeakL = 0.0;
|
||||
m_outPeakR = 0.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +52,7 @@ void DelayControls::loadSettings( const QDomElement &_this )
|
||||
m_feedbackModel.loadSettings( _this, "FeebackAmount" );
|
||||
m_lfoTimeModel.loadSettings( _this , "LfoFrequency");
|
||||
m_lfoAmountModel.loadSettings( _this, "LfoAmount");
|
||||
m_outGainModel.loadSettings( _this, "OutGain" );
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +64,7 @@ void DelayControls::saveSettings( QDomDocument& doc, QDomElement& _this )
|
||||
m_feedbackModel.saveSettings( doc, _this ,"FeebackAmount" );
|
||||
m_lfoTimeModel.saveSettings( doc, _this, "LfoFrequency" );
|
||||
m_lfoAmountModel.saveSettings( doc, _this ,"LfoAmount" );
|
||||
m_outGainModel.saveSettings( doc, _this, "OutGain" );
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "EffectControls.h"
|
||||
#include "Knob.h"
|
||||
#include "delaycontrolsdialog.h"
|
||||
#include "DelayControlsDialog.h"
|
||||
|
||||
|
||||
|
||||
@@ -48,13 +48,17 @@ public:
|
||||
return "Delay";
|
||||
}
|
||||
virtual int controlCount(){
|
||||
return 4;
|
||||
return 5;
|
||||
}
|
||||
virtual EffectControlDialog* createView()
|
||||
{
|
||||
return new DelayControlsDialog( this );
|
||||
}
|
||||
|
||||
float m_outPeakL;
|
||||
float m_outPeakR;
|
||||
|
||||
|
||||
private slots:
|
||||
void changeSampleRate();
|
||||
|
||||
@@ -64,6 +68,7 @@ private:
|
||||
FloatModel m_feedbackModel;
|
||||
TempoSyncKnobModel m_lfoTimeModel;
|
||||
TempoSyncKnobModel m_lfoAmountModel;
|
||||
FloatModel m_outGainModel;
|
||||
|
||||
friend class DelayControlsDialog;
|
||||
friend class DelayEffect;
|
||||
@@ -22,10 +22,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "delaycontrolsdialog.h"
|
||||
#include "delaycontrols.h"
|
||||
#include "DelayControlsDialog.h"
|
||||
#include "DelayControls.h"
|
||||
#include "embed.h"
|
||||
#include "TempoSyncKnob.h"
|
||||
#include "../Eq/EqFader.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
|
||||
|
||||
@@ -37,37 +40,112 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) :
|
||||
QPalette pal;
|
||||
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
|
||||
setPalette( pal );
|
||||
setFixedSize( 200, 75 );
|
||||
setFixedSize( 300, 200 );
|
||||
|
||||
TempoSyncKnob* sampleDelayKnob = new TempoSyncKnob( knobBright_26, this );
|
||||
sampleDelayKnob->move( 20,10 );
|
||||
sampleDelayKnob->move( 13,10 );
|
||||
sampleDelayKnob->setVolumeKnob( false );
|
||||
sampleDelayKnob->setModel( &controls->m_delayTimeModel );
|
||||
sampleDelayKnob->setLabel( tr( "Delay" ) );
|
||||
sampleDelayKnob->setHintText( tr( "Delay Time" ) + " ", " s" );
|
||||
|
||||
Knob * feedbackKnob = new Knob( knobBright_26, this );
|
||||
feedbackKnob->move( 63,10 );
|
||||
feedbackKnob->move( 13, 55 );
|
||||
feedbackKnob->setVolumeKnob( true) ;
|
||||
feedbackKnob->setModel( &controls->m_feedbackModel);
|
||||
feedbackKnob->setLabel( tr( "Regen" ) );
|
||||
feedbackKnob->setHintText( tr ( "Feedback Amount" ) + " " , "" );
|
||||
|
||||
TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this );
|
||||
lfoFreqKnob->move( 106,10 );
|
||||
lfoFreqKnob->move( 13, 100 );
|
||||
lfoFreqKnob->setVolumeKnob( false );
|
||||
lfoFreqKnob->setModel( &controls->m_lfoTimeModel );
|
||||
lfoFreqKnob->setLabel( tr( "Rate" ) );
|
||||
lfoFreqKnob->setHintText( tr ( "Lfo") + " ", " s" );
|
||||
|
||||
TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this );
|
||||
lfoAmtKnob->move( 150,10 );
|
||||
lfoAmtKnob->move( 13, 145 );
|
||||
lfoAmtKnob->setVolumeKnob( false );
|
||||
lfoAmtKnob->setModel( &controls->m_lfoAmountModel );
|
||||
lfoAmtKnob->setLabel( tr( "Lfo" ) );
|
||||
lfoAmtKnob->setHintText( tr ( "Lfo Amt" ) + " " , " s" );
|
||||
|
||||
EqFader * outFader = new EqFader( &controls->m_outGainModel,tr( "Out Gain" ),
|
||||
this, &controls->m_outPeakL, &controls->m_outPeakR );
|
||||
outFader->setMaximumHeight( 196 );
|
||||
outFader->move( 263, 42 );
|
||||
outFader->setDisplayConversion( false );
|
||||
outFader->setHintText( tr( "Gain" ), "dBv" );
|
||||
|
||||
XyPad * pad = new XyPad( this, &controls->m_feedbackModel, &controls->m_delayTimeModel );
|
||||
pad->resize( 196, 196 );
|
||||
pad->move( 50, 2 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
XyPad::XyPad(QWidget *parent, FloatModel *xModel, FloatModel *yModel) :
|
||||
QWidget( parent ),
|
||||
m_xModel( xModel ),
|
||||
m_yModel( yModel ),
|
||||
m_acceptInput( false )
|
||||
{
|
||||
connect( m_xModel, SIGNAL( dataChanged() ) , this, SLOT( update() ) );
|
||||
connect( m_yModel, SIGNAL( dataChanged() ) , this, SLOT( update() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void XyPad::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter( this );
|
||||
//Draw Frequecy maker lines
|
||||
painter.setPen( QPen( QColor( 200, 200, 200, 200 ), 8, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
|
||||
float xRange = m_xModel->maxValue() - m_xModel->minValue();
|
||||
float xInc = xRange / width();
|
||||
int xPos = ( m_xModel->value() - m_xModel->minValue() ) / xInc;
|
||||
|
||||
float yRange = m_yModel->maxValue() - m_yModel->minValue();
|
||||
float yInc = yRange / height();
|
||||
int yPos = ( m_yModel->value() - m_yModel->minValue() ) / yInc;
|
||||
|
||||
painter.drawPoint( xPos, yPos );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void XyPad::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
m_acceptInput = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void XyPad::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
m_acceptInput = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void XyPad::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if( m_acceptInput && (event->x() >= 0) && ( event->x() < width() )
|
||||
&& ( event->y() >= 0) && ( event->y() < height() ) )
|
||||
{
|
||||
//set xmodel
|
||||
float xRange = m_xModel->maxValue() - m_xModel->minValue();
|
||||
float xInc = xRange / width();
|
||||
m_xModel->setValue( m_xModel->minValue() + ( event->x() * xInc ) );
|
||||
|
||||
//set ymodel
|
||||
float yRange = m_yModel->maxValue() - m_yModel->minValue();
|
||||
float yInc = yRange / height();
|
||||
m_yModel->setValue( m_yModel->minValue() + ( event->y() * yInc ) );
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
#define DELAYCONTROLSDIALOG_H
|
||||
|
||||
#include "EffectControlDialog.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
class DelayControls;
|
||||
|
||||
@@ -38,4 +39,23 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class XyPad : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
XyPad( QWidget *parent = 0, FloatModel *xModel = 0, FloatModel *yModel = 0 );
|
||||
~XyPad() {}
|
||||
|
||||
protected:
|
||||
virtual void paintEvent ( QPaintEvent * event );
|
||||
virtual void mousePressEvent(QMouseEvent * event );
|
||||
virtual void mouseReleaseEvent(QMouseEvent * event);
|
||||
virtual void mouseMoveEvent(QMouseEvent * event);
|
||||
|
||||
private:
|
||||
FloatModel *m_xModel;
|
||||
FloatModel *m_yModel;
|
||||
bool m_acceptInput;
|
||||
};
|
||||
|
||||
#endif // DELAYCONTROLSDIALOG_H
|
||||
@@ -22,9 +22,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "delayeffect.h"
|
||||
#include "DelayEffect.h"
|
||||
#include "Engine.h"
|
||||
#include "embed.cpp"
|
||||
#include "interpolation.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
@@ -53,6 +54,7 @@ DelayEffect::DelayEffect( Model* parent, const Plugin::Descriptor::SubPluginFeat
|
||||
m_delay = 0;
|
||||
m_delay = new StereoDelay( 20, Engine::mixer()->processingSampleRate() );
|
||||
m_lfo = new Lfo( Engine::mixer()->processingSampleRate() );
|
||||
m_outGain = 1.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,25 +82,65 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
return( false );
|
||||
}
|
||||
double outSum = 0.0;
|
||||
const float sr = Engine::mixer()->processingSampleRate();
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
const float length = m_delayControls.m_delayTimeModel.value() * Engine::mixer()->processingSampleRate();
|
||||
const float amplitude = m_delayControls.m_lfoAmountModel.value() * Engine::mixer()->processingSampleRate();
|
||||
m_lfo->setFrequency( 1.0 / m_delayControls.m_lfoTimeModel.value() );
|
||||
m_delay->setFeedback( m_delayControls.m_feedbackModel.value() );
|
||||
sample_t dryS[2];
|
||||
float lPeak = 0.0;
|
||||
float rPeak = 0.0;
|
||||
float length = m_delayControls.m_delayTimeModel.value();
|
||||
float amplitude = m_delayControls.m_lfoAmountModel.value() * sr;
|
||||
float lfoTime = 1.0 / m_delayControls.m_lfoTimeModel.value();
|
||||
float feedback = m_delayControls.m_feedbackModel.value();
|
||||
ValueBuffer *lengthBuffer = m_delayControls.m_delayTimeModel.valueBuffer();
|
||||
ValueBuffer *feedbackBuffer = m_delayControls.m_feedbackModel.valueBuffer();
|
||||
ValueBuffer *lfoTimeBuffer = m_delayControls.m_lfoTimeModel.valueBuffer();
|
||||
ValueBuffer *lfoAmountBuffer = m_delayControls.m_lfoAmountModel.valueBuffer();
|
||||
int lengthInc = lengthBuffer ? 1 : 0;
|
||||
int amplitudeInc = lfoAmountBuffer ? 1 : 0;
|
||||
int lfoTimeInc = lfoTimeBuffer ? 1 : 0;
|
||||
int feedbackInc = feedbackBuffer ? 1 : 0;
|
||||
float *lengthPtr = lengthBuffer ? &( lengthBuffer->values()[ 0 ] ) : &length;
|
||||
float *amplitudePtr = lfoAmountBuffer ? &( lfoAmountBuffer->values()[ 0 ] ) : &litude;
|
||||
float *lfoTimePtr = lfoTimeBuffer ? &( lfoTimeBuffer->values()[ 0 ] ) : &lfoTime;
|
||||
float *feedbackPtr = feedbackBuffer ? &( feedbackBuffer->values()[ 0 ] ) : &feedback;
|
||||
|
||||
if( m_delayControls.m_outGainModel.isValueChanged() )
|
||||
{
|
||||
m_outGain = dbvToAmp( m_delayControls.m_outGainModel.value() );
|
||||
}
|
||||
int sampleLength;
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
{
|
||||
dryS[0] = buf[f][0];
|
||||
dryS[1] = buf[f][1];
|
||||
m_delay->setLength( ( float )length + ( amplitude * ( float )m_lfo->tick() ) );
|
||||
|
||||
m_delay->setFeedback( *feedbackPtr );
|
||||
m_lfo->setFrequency( *lfoTimePtr );
|
||||
sampleLength = *lengthPtr * Engine::mixer()->processingSampleRate();
|
||||
m_currentLength = linearInterpolate( sampleLength, m_currentLength, 0.9999 );
|
||||
m_delay->setLength( m_currentLength + ( *amplitudePtr * ( float )m_lfo->tick() ) );
|
||||
m_delay->tick( buf[f] );
|
||||
|
||||
buf[f][0] *= m_outGain;
|
||||
buf[f][1] *= m_outGain;
|
||||
|
||||
lPeak = buf[f][0] > lPeak ? buf[f][0] : lPeak;
|
||||
rPeak = buf[f][1] > rPeak ? buf[f][1] : rPeak;
|
||||
|
||||
buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
|
||||
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
|
||||
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
|
||||
|
||||
lengthPtr += lengthInc;
|
||||
amplitudePtr += amplitudeInc;
|
||||
lfoTimePtr += lfoTimeInc;
|
||||
feedbackPtr += feedbackInc;
|
||||
}
|
||||
checkGate( outSum / frames );
|
||||
m_delayControls.m_outPeakL = lPeak;
|
||||
m_delayControls.m_outPeakR = rPeak;
|
||||
|
||||
return isRunning();
|
||||
}
|
||||
|
||||
@@ -26,9 +26,10 @@
|
||||
#define DELAYEFFECT_H
|
||||
|
||||
#include "Effect.h"
|
||||
#include "delaycontrols.h"
|
||||
#include "lfo.h"
|
||||
#include "stereodelay.h"
|
||||
#include "DelayControls.h"
|
||||
#include "Lfo.h"
|
||||
#include "StereoDelay.h"
|
||||
#include "ValueBuffer.h"
|
||||
|
||||
class DelayEffect : public Effect
|
||||
{
|
||||
@@ -46,6 +47,8 @@ private:
|
||||
DelayControls m_delayControls;
|
||||
StereoDelay* m_delay;
|
||||
Lfo* m_lfo;
|
||||
float m_outGain;
|
||||
float m_currentLength;
|
||||
};
|
||||
|
||||
#endif // DELAYEFFECT_H
|
||||
@@ -22,7 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lfo.h"
|
||||
#include "Lfo.h"
|
||||
#include "lmms_math.h"
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stereodelay.h"
|
||||
#include "StereoDelay.h"
|
||||
#include <cstdlib>
|
||||
#include "lmms_basics.h"
|
||||
#include "interpolation.h"
|
||||
@@ -74,7 +74,7 @@ void StereoDelay::tick( sampleFrame frame )
|
||||
m_buffer[m_index][0] += frame[0] * m_feedback;
|
||||
m_buffer[m_index][1] += frame[1] * m_feedback;
|
||||
|
||||
m_index = ( m_index + 1) % m_maxLength;
|
||||
m_index = ( m_index + 1) % (int) m_maxLength;
|
||||
}
|
||||
|
||||
|
||||
BIN
plugins/Delay/artwork.png
Normal file
BIN
plugins/Delay/artwork.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -95,33 +95,52 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
m_filter2changed = true;
|
||||
}
|
||||
|
||||
float cut1 = m_dfControls.m_cut1Model.value();
|
||||
float res1 = m_dfControls.m_res1Model.value();
|
||||
float gain1 = m_dfControls.m_gain1Model.value();
|
||||
float cut2 = m_dfControls.m_cut2Model.value();
|
||||
float res2 = m_dfControls.m_res2Model.value();
|
||||
float gain2 = m_dfControls.m_gain2Model.value();
|
||||
float mix = m_dfControls.m_mixModel.value();
|
||||
|
||||
ValueBuffer *cut1Buffer = m_dfControls.m_cut1Model.valueBuffer();
|
||||
ValueBuffer *res1Buffer = m_dfControls.m_res1Model.valueBuffer();
|
||||
ValueBuffer *gain1Buffer = m_dfControls.m_gain1Model.valueBuffer();
|
||||
ValueBuffer *cut2Buffer = m_dfControls.m_cut2Model.valueBuffer();
|
||||
ValueBuffer *res2Buffer = m_dfControls.m_res2Model.valueBuffer();
|
||||
ValueBuffer *gain2Buffer = m_dfControls.m_gain2Model.valueBuffer();
|
||||
ValueBuffer *mixBuffer = m_dfControls.m_mixModel.valueBuffer();
|
||||
|
||||
int cut1Inc = cut1Buffer ? 1 : 0;
|
||||
int res1Inc = res1Buffer ? 1 : 0;
|
||||
int gain1Inc = gain1Buffer ? 1 : 0;
|
||||
int cut2Inc = cut2Buffer ? 1 : 0;
|
||||
int res2Inc = res2Buffer ? 1 : 0;
|
||||
int gain2Inc = gain2Buffer ? 1 : 0;
|
||||
int mixInc = mixBuffer ? 1 : 0;
|
||||
|
||||
float *cut1Ptr = cut1Buffer ? &( cut1Buffer->values()[ 0 ] ) : &cut1;
|
||||
float *res1Ptr = res1Buffer ? &( res1Buffer->values()[ 0 ] ) : &res1;
|
||||
float *gain1Ptr = gain1Buffer ? &( gain1Buffer->values()[ 0 ] ) : &gain1;
|
||||
float *cut2Ptr = cut2Buffer ? &( cut2Buffer->values()[ 0 ] ) : &cut2;
|
||||
float *res2Ptr = res2Buffer ? &( res2Buffer->values()[ 0 ] ) : &res2;
|
||||
float *gain2Ptr = gain2Buffer ? &( gain2Buffer->values()[ 0 ] ) : &gain2;
|
||||
float *mixPtr = mixBuffer ? &( mixBuffer->values()[ 0 ] ) : &mix;
|
||||
|
||||
const bool enabled1 = m_dfControls.m_enabled1Model.value();
|
||||
const bool enabled2 = m_dfControls.m_enabled2Model.value();
|
||||
|
||||
// recalculate only when necessary: either cut/res is changed, or the changed-flag is set (filter type or samplerate changed)
|
||||
if( ( enabled1 && ( m_dfControls.m_cut1Model.isValueChanged() ||
|
||||
m_dfControls.m_res1Model.isValueChanged() ) ) || m_filter1changed )
|
||||
{
|
||||
m_filter1->calcFilterCoeffs( m_dfControls.m_cut1Model.value(), m_dfControls.m_res1Model.value() );
|
||||
m_filter1changed = false;
|
||||
}
|
||||
if( ( enabled2 && ( m_dfControls.m_cut2Model.isValueChanged() ||
|
||||
m_dfControls.m_res2Model.isValueChanged() ) ) || m_filter2changed )
|
||||
{
|
||||
m_filter2->calcFilterCoeffs( m_dfControls.m_cut2Model.value(), m_dfControls.m_res2Model.value() );
|
||||
m_filter2changed = false;
|
||||
}
|
||||
|
||||
// get mix amounts for wet signals of both filters
|
||||
const float mix2 = ( ( m_dfControls.m_mixModel.value() + 1.0f ) * 0.5f );
|
||||
const float mix1 = 1.0f - mix2;
|
||||
|
||||
const float gain1 = m_dfControls.m_gain1Model.value() * 0.01f;
|
||||
const float gain2 = m_dfControls.m_gain2Model.value() * 0.01f;
|
||||
|
||||
// buffer processing loop
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
{
|
||||
// get mix amounts for wet signals of both filters
|
||||
const float mix2 = ( ( *mixPtr + 1.0f ) * 0.5f );
|
||||
const float mix1 = 1.0f - mix2;
|
||||
const float gain1 = *gain1Ptr * 0.01f;
|
||||
const float gain2 = *gain2Ptr * 0.01f;
|
||||
sample_t s[2] = { 0.0f, 0.0f }; // mix
|
||||
sample_t s1[2] = { buf[f][0], buf[f][1] }; // filter 1
|
||||
sample_t s2[2] = { buf[f][0], buf[f][1] }; // filter 2
|
||||
@@ -129,6 +148,16 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
// update filter 1
|
||||
if( enabled1 )
|
||||
{
|
||||
//update filter 1 params here
|
||||
// recalculate only when necessary: either cut/res is changed, or the changed-flag is set (filter type or samplerate changed)
|
||||
if( ( ( *cut1Ptr != m_currentCut1 ||
|
||||
*res1Ptr != m_currentRes1 ) ) || m_filter1changed )
|
||||
{
|
||||
m_filter1->calcFilterCoeffs( *cut1Ptr, *res2Ptr );
|
||||
m_filter1changed = false;
|
||||
m_currentCut1 = *cut1Ptr;
|
||||
m_currentRes1 = *res1Ptr;
|
||||
}
|
||||
s1[0] = m_filter1->update( s1[0], 0 );
|
||||
s1[1] = m_filter1->update( s1[1], 1 );
|
||||
|
||||
@@ -144,6 +173,15 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
// update filter 2
|
||||
if( enabled2 )
|
||||
{
|
||||
//update filter 2 params here
|
||||
if( ( ( *cut2Ptr != m_currentCut2 ||
|
||||
*res2Ptr != m_currentRes2 ) ) || m_filter2changed )
|
||||
{
|
||||
m_filter2->calcFilterCoeffs( *cut2Ptr, *res2Ptr );
|
||||
m_filter2changed = false;
|
||||
m_currentCut2 = *cut2Ptr;
|
||||
m_currentRes2 = *res2Ptr;
|
||||
}
|
||||
s2[0] = m_filter2->update( s2[0], 0 );
|
||||
s2[1] = m_filter2->update( s2[1], 1 );
|
||||
|
||||
@@ -160,6 +198,15 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
// do another mix with dry signal
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
|
||||
//increment pointers
|
||||
cut1Ptr += cut1Inc;
|
||||
res1Ptr += res1Inc;
|
||||
gain1Ptr += gain1Inc;
|
||||
cut2Ptr += cut2Inc;
|
||||
res2Ptr += res2Inc;
|
||||
gain2Ptr += gain2Inc;
|
||||
mixPtr += mixInc;
|
||||
}
|
||||
|
||||
checkGate( outSum / frames );
|
||||
|
||||
@@ -53,6 +53,11 @@ private:
|
||||
bool m_filter1changed;
|
||||
bool m_filter2changed;
|
||||
|
||||
float m_currentCut1;
|
||||
float m_currentRes1;
|
||||
float m_currentCut2;
|
||||
float m_currentRes2;
|
||||
|
||||
friend class DualFilterControls;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -71,6 +71,101 @@ EqEffect::~EqEffect()
|
||||
|
||||
bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
|
||||
{
|
||||
// setup sample exact controls
|
||||
float hpRes = m_eqControls.m_hpResModel.value();
|
||||
float lowShelfRes = m_eqControls.m_lowShelfResModel.value();
|
||||
float para1Bw = m_eqControls.m_para1BwModel.value();
|
||||
float para2Bw = m_eqControls.m_para2BwModel.value();
|
||||
float para3Bw = m_eqControls.m_para3BwModel.value();
|
||||
float para4Bw = m_eqControls.m_para4BwModel.value();
|
||||
float highShelfRes = m_eqControls.m_highShelfResModel.value();
|
||||
float lpRes = m_eqControls.m_lpResModel.value();
|
||||
|
||||
float hpFreq = m_eqControls.m_hpFeqModel.value();
|
||||
float lowShelfFreq = m_eqControls.m_lowShelfFreqModel.value();
|
||||
float para1Freq = m_eqControls.m_para1FreqModel.value();
|
||||
float para2Freq = m_eqControls.m_para2FreqModel.value();
|
||||
float para3Freq = m_eqControls.m_para3FreqModel.value();
|
||||
float para4Freq = m_eqControls.m_para4FreqModel.value();
|
||||
float highShelfFreq = m_eqControls.m_highShelfFreqModel.value();
|
||||
float lpFreq = m_eqControls.m_lpFreqModel.value();
|
||||
|
||||
ValueBuffer *hpResBuffer = m_eqControls.m_hpResModel.valueBuffer();
|
||||
ValueBuffer *lowShelfResBuffer = m_eqControls.m_lowShelfResModel.valueBuffer();
|
||||
ValueBuffer *para1BwBuffer = m_eqControls.m_para1BwModel.valueBuffer();
|
||||
ValueBuffer *para2BwBuffer = m_eqControls.m_para2BwModel.valueBuffer();
|
||||
ValueBuffer *para3BwBuffer = m_eqControls.m_para3BwModel.valueBuffer();
|
||||
ValueBuffer *para4BwBuffer = m_eqControls.m_para4BwModel.valueBuffer();
|
||||
ValueBuffer *highShelfResBuffer = m_eqControls.m_highShelfResModel.valueBuffer();
|
||||
ValueBuffer *lpResBuffer = m_eqControls.m_lpResModel.valueBuffer();
|
||||
|
||||
ValueBuffer *hpFreqBuffer = m_eqControls.m_hpFeqModel.valueBuffer();
|
||||
ValueBuffer *lowShelfFreqBuffer = m_eqControls.m_lowShelfFreqModel.valueBuffer();
|
||||
ValueBuffer *para1FreqBuffer = m_eqControls.m_para1FreqModel.valueBuffer();
|
||||
ValueBuffer *para2FreqBuffer = m_eqControls.m_para2FreqModel.valueBuffer();
|
||||
ValueBuffer *para3FreqBuffer = m_eqControls.m_para3FreqModel.valueBuffer();
|
||||
ValueBuffer *para4FreqBuffer = m_eqControls.m_para4FreqModel.valueBuffer();
|
||||
ValueBuffer *highShelfFreqBuffer = m_eqControls.m_highShelfFreqModel.valueBuffer();
|
||||
ValueBuffer *lpFreqBuffer = m_eqControls.m_lpFreqModel.valueBuffer();
|
||||
|
||||
int hpResInc = hpResBuffer ? 1 : 0;
|
||||
int lowShelfResInc = lowShelfResBuffer ? 1 : 0;
|
||||
int para1BwInc = para1BwBuffer ? 1 : 0;
|
||||
int para2BwInc = para2BwBuffer ? 1 : 0;
|
||||
int para3BwInc = para3BwBuffer ? 1 : 0;
|
||||
int para4BwInc = para4BwBuffer ? 1 : 0;
|
||||
int highShelfResInc = highShelfResBuffer ? 1 : 0;
|
||||
int lpResInc = lpResBuffer ? 1 : 0;
|
||||
|
||||
int hpFreqInc = hpFreqBuffer ? 1 : 0;
|
||||
int lowShelfFreqInc = lowShelfFreqBuffer ? 1 : 0;
|
||||
int para1FreqInc = para1FreqBuffer ? 1 : 0;
|
||||
int para2FreqInc = para2FreqBuffer ? 1 : 0;
|
||||
int para3FreqInc = para3FreqBuffer ? 1 : 0;
|
||||
int para4FreqInc = para4FreqBuffer ? 1 : 0;
|
||||
int highShelfFreqInc = highShelfFreqBuffer ? 1 : 0;
|
||||
int lpFreqInc = lpFreqBuffer ? 1 : 0;
|
||||
|
||||
float *hpResPtr = hpResBuffer ? &( hpResBuffer->values()[ 0 ] ) : &hpRes;
|
||||
float *lowShelfResPtr = lowShelfResBuffer ? &( lowShelfResBuffer->values()[ 0 ] ) : &lowShelfRes;
|
||||
float *para1BwPtr = para1BwBuffer ? &( para1BwBuffer->values()[ 0 ] ) : ¶1Bw;
|
||||
float *para2BwPtr = para2BwBuffer ? &( para2BwBuffer->values()[ 0 ] ) : ¶2Bw;
|
||||
float *para3BwPtr = para3BwBuffer ? &( para3BwBuffer->values()[ 0 ] ) : ¶3Bw;
|
||||
float *para4BwPtr = para4BwBuffer ? &( para4BwBuffer->values()[ 0 ] ) : ¶4Bw;
|
||||
float *highShelfResPtr = highShelfResBuffer ? &( highShelfResBuffer->values()[ 0 ] ) : &highShelfRes;
|
||||
float *lpResPtr = lpResBuffer ? &( lpResBuffer->values()[ 0 ] ) : &lpRes;
|
||||
|
||||
float *hpFreqPtr = hpFreqBuffer ? &( hpFreqBuffer->values()[ 0 ] ) : &hpFreq;
|
||||
float *lowShelfFreqPtr = lowShelfFreqBuffer ? &( lowShelfFreqBuffer->values()[ 0 ] ) : &lowShelfFreq;
|
||||
float *para1FreqPtr = para1FreqBuffer ? &(para1FreqBuffer->values()[ 0 ] ) : ¶1Freq;
|
||||
float *para2FreqPtr = para2FreqBuffer ? &(para2FreqBuffer->values()[ 0 ] ) : ¶2Freq;
|
||||
float *para3FreqPtr = para3FreqBuffer ? &(para3FreqBuffer->values()[ 0 ] ) : ¶3Freq;
|
||||
float *para4FreqPtr = para4FreqBuffer ? &(para4FreqBuffer->values()[ 0 ] ) : ¶4Freq;
|
||||
float *hightShelfFreqPtr = highShelfFreqBuffer ? &(highShelfFreqBuffer->values()[ 0 ] ) : &highShelfFreq;
|
||||
float *lpFreqPtr = lpFreqBuffer ? &(lpFreqBuffer ->values()[ 0 ] ) : &lpFreq;
|
||||
|
||||
bool hpActive = m_eqControls.m_hpActiveModel.value();
|
||||
bool hp24Active = m_eqControls.m_hp24Model.value();
|
||||
bool hp48Active = m_eqControls.m_hp48Model.value();
|
||||
bool lowShelfActive = m_eqControls.m_lowShelfActiveModel.value();
|
||||
bool para1Active = m_eqControls.m_para1ActiveModel.value();
|
||||
bool para2Active = m_eqControls.m_para2ActiveModel.value();
|
||||
bool para3Active = m_eqControls.m_para3ActiveModel.value();
|
||||
bool para4Active = m_eqControls.m_para4ActiveModel.value();
|
||||
bool highShelfActive = m_eqControls.m_highShelfActiveModel.value();
|
||||
bool lpActive = m_eqControls.m_lpActiveModel.value();
|
||||
bool lp24Active = m_eqControls.m_lp24Model.value();
|
||||
bool lp48Active = m_eqControls.m_lp48Model.value();
|
||||
|
||||
float lowShelfGain = m_eqControls.m_lowShelfGainModel.value();
|
||||
float para1Gain = m_eqControls.m_para1GainModel.value();
|
||||
float para2Gain = m_eqControls.m_para2GainModel.value();
|
||||
float para3Gain = m_eqControls.m_para3GainModel.value();
|
||||
float para4Gain = m_eqControls.m_para4GainModel.value();
|
||||
float highShelfGain = m_eqControls.m_highShelfGainModel.value();
|
||||
|
||||
|
||||
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
return( false );
|
||||
@@ -105,83 +200,126 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
|
||||
m_eqControls.m_inPeakL = m_eqControls.m_inPeakL < m_inPeak[0] ? m_inPeak[0] : m_eqControls.m_inPeakL;
|
||||
m_eqControls.m_inPeakR = m_eqControls.m_inPeakR < m_inPeak[1] ? m_inPeak[1] : m_eqControls.m_inPeakR;
|
||||
|
||||
if(m_eqControls.m_hpActiveModel.value() ){
|
||||
for( fpp_t f = 0; f < frames; f++)
|
||||
{
|
||||
if( hpActive ){
|
||||
|
||||
m_hp12.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
|
||||
m_hp12.processBuffer( buf, frames );
|
||||
m_hp12.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 );
|
||||
buf[f][0] = m_hp12.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_hp12.update( buf[f][1], 1 );
|
||||
|
||||
if( m_eqControls.m_hp24Model.value() || m_eqControls.m_hp48Model.value() )
|
||||
{
|
||||
m_hp24.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
|
||||
m_hp24.processBuffer( buf, frames );
|
||||
if( hp24Active || hp48Active )
|
||||
{
|
||||
m_hp24.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 );
|
||||
buf[f][0] = m_hp24.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_hp24.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( hp48Active )
|
||||
{
|
||||
m_hp480.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 );
|
||||
buf[f][0] = m_hp480.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_hp480.update( buf[f][1], 1 );
|
||||
|
||||
m_hp481.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 );
|
||||
buf[f][0] = m_hp481.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_hp481.update( buf[f][1], 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_eqControls.m_hp48Model.value() )
|
||||
if( lowShelfActive )
|
||||
{
|
||||
m_hp480.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
|
||||
m_hp480.processBuffer( buf, frames );
|
||||
|
||||
m_hp481.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 );
|
||||
m_hp481.processBuffer( buf, frames );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_eqControls.m_lowShelfActiveModel.value() )
|
||||
{
|
||||
m_lowShelf.setParameters( sampleRate, m_eqControls.m_lowShelfFreqModel.value(), m_eqControls.m_lowShelfResModel .value(), m_eqControls.m_lowShelfGainModel.value() );
|
||||
m_lowShelf.processBuffer( buf, frames );
|
||||
}
|
||||
|
||||
if( m_eqControls.m_para1ActiveModel.value() )
|
||||
{
|
||||
m_para1.setParameters( sampleRate, m_eqControls.m_para1FreqModel.value(), m_eqControls.m_para1BwModel.value(), m_eqControls.m_para1GainModel.value() );
|
||||
m_para1.processBuffer( buf, frames );
|
||||
}
|
||||
|
||||
if( m_eqControls.m_para2ActiveModel.value() )
|
||||
{
|
||||
m_para2.setParameters( sampleRate, m_eqControls.m_para2FreqModel.value(), m_eqControls.m_para2BwModel.value(), m_eqControls.m_para2GainModel.value() );
|
||||
m_para2.processBuffer( buf, frames );
|
||||
}
|
||||
|
||||
if( m_eqControls.m_para3ActiveModel.value() )
|
||||
{
|
||||
m_para3.setParameters( sampleRate, m_eqControls.m_para3FreqModel.value(), m_eqControls.m_para3BwModel.value(), m_eqControls.m_para3GainModel.value() );
|
||||
m_para3.processBuffer( buf, frames );
|
||||
}
|
||||
|
||||
if( m_eqControls.m_para4ActiveModel.value() )
|
||||
{
|
||||
m_para4.setParameters( sampleRate, m_eqControls.m_para4FreqModel.value(), m_eqControls.m_para4BwModel.value(), m_eqControls.m_para4GainModel.value() );
|
||||
m_para4.processBuffer( buf, frames );
|
||||
}
|
||||
|
||||
if( m_eqControls.m_highShelfActiveModel.value() )
|
||||
{
|
||||
m_highShelf.setParameters( sampleRate, m_eqControls.m_highShelfFreqModel.value(), m_eqControls.m_highShelfResModel.value(), m_eqControls.m_highShelfGainModel.value());
|
||||
m_highShelf.processBuffer( buf, frames );
|
||||
}
|
||||
|
||||
if(m_eqControls.m_lpActiveModel.value() ){
|
||||
m_lp12.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
|
||||
m_lp12.processBuffer( buf, frames );
|
||||
|
||||
if( m_eqControls.m_lp24Model.value() || m_eqControls.m_lp48Model.value() )
|
||||
{
|
||||
m_lp24.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
|
||||
m_lp24.processBuffer( buf, frames );
|
||||
m_lowShelf.setParameters( sampleRate, *lowShelfFreqPtr, *lowShelfResPtr, lowShelfGain );
|
||||
buf[f][0] = m_lowShelf.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_lowShelf.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( m_eqControls.m_lp48Model.value() )
|
||||
if( para1Active )
|
||||
{
|
||||
m_lp480.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
|
||||
m_lp480.processBuffer( buf, frames );
|
||||
|
||||
m_lp481.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 );
|
||||
m_lp481.processBuffer( buf, frames );
|
||||
m_para1.setParameters( sampleRate, *para1FreqPtr, *para1BwPtr, para1Gain );
|
||||
buf[f][0] = m_para1.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_para1.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( para2Active )
|
||||
{
|
||||
m_para2.setParameters( sampleRate, *para2FreqPtr, *para2BwPtr, para2Gain );
|
||||
buf[f][0] = m_para2.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_para2.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( para3Active )
|
||||
{
|
||||
m_para3.setParameters( sampleRate, *para3FreqPtr, *para3BwPtr, para3Gain );
|
||||
buf[f][0] = m_para3.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_para3.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( para4Active )
|
||||
{
|
||||
m_para4.setParameters( sampleRate, *para4FreqPtr, *para4BwPtr, para4Gain );
|
||||
buf[f][0] = m_para4.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_para4.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( highShelfActive )
|
||||
{
|
||||
m_highShelf.setParameters( sampleRate, *hightShelfFreqPtr, *highShelfResPtr, highShelfGain );
|
||||
buf[f][0] = m_highShelf.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_highShelf.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( lpActive ){
|
||||
m_lp12.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 );
|
||||
buf[f][0] = m_lp12.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_lp12.update( buf[f][1], 1 );
|
||||
|
||||
if( lp24Active || lp48Active )
|
||||
{
|
||||
m_lp24.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 );
|
||||
buf[f][0] = m_lp24.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_lp24.update( buf[f][1], 1 );
|
||||
}
|
||||
|
||||
if( lp48Active )
|
||||
{
|
||||
m_lp480.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 );
|
||||
buf[f][0] = m_lp480.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_lp480.update( buf[f][1], 1 );
|
||||
|
||||
m_lp481.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 );
|
||||
buf[f][0] = m_lp481.update( buf[f][0], 0 );
|
||||
buf[f][1] = m_lp481.update( buf[f][1], 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//increment pointers if needed
|
||||
hpResPtr += hpResInc;
|
||||
lowShelfResPtr += lowShelfResInc;
|
||||
para1BwPtr += para1BwInc;
|
||||
para2BwPtr += para2BwInc;
|
||||
para3BwPtr += para3BwInc;
|
||||
para4BwPtr += para4BwInc;
|
||||
highShelfResPtr += highShelfResInc;
|
||||
lpResPtr += lpResInc;
|
||||
|
||||
hpFreqPtr += hpFreqInc;
|
||||
lowShelfFreqPtr += lowShelfFreqInc;
|
||||
para1FreqPtr += para1FreqInc;
|
||||
para2FreqPtr += para2FreqInc;
|
||||
para3FreqPtr += para3FreqInc;
|
||||
para4FreqPtr += para4FreqInc;
|
||||
hightShelfFreqPtr += highShelfFreqInc;
|
||||
lpFreqPtr += lpFreqInc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sampleFrame outPeak = { 0, 0 };
|
||||
gain( buf, frames, outGain, &outPeak );
|
||||
m_eqControls.m_outPeakL = m_eqControls.m_outPeakL < outPeak[0] ? outPeak[0] : m_eqControls.m_outPeakL;
|
||||
|
||||
@@ -122,19 +122,6 @@ public:
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief processBuffer
|
||||
/// \param buf Audio Buffer
|
||||
/// \param frames Count of sampleFrames in Audio Buffer
|
||||
///
|
||||
virtual void processBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
for ( fpp_t f = 0 ; f < frames ; ++f)
|
||||
{
|
||||
buf[f][0] = update( buf[f][0] , 0);
|
||||
buf[f][1] = update( buf[f][1] , 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
|
||||
@@ -24,9 +24,9 @@ FOREACH(_item ${PLUGIN_SOURCES})
|
||||
ELSE(LMMS_BUILD_APPLE)
|
||||
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm")
|
||||
ENDIF(LMMS_BUILD_APPLE)
|
||||
IF(LMMS_BUILD_LINUX)
|
||||
IF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU)
|
||||
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -nostartfiles")
|
||||
ENDIF(LMMS_BUILD_LINUX)
|
||||
ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU)
|
||||
ENDFOREACH(_item ${PLUGIN_SOURCES})
|
||||
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ FOREACH(_item ${PLUGIN_SOURCES})
|
||||
ELSE(LMMS_BUILD_APPLE)
|
||||
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm")
|
||||
ENDIF(LMMS_BUILD_APPLE)
|
||||
IF(LMMS_BUILD_LINUX)
|
||||
IF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU)
|
||||
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -nostartfiles")
|
||||
ENDIF(LMMS_BUILD_LINUX)
|
||||
ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU)
|
||||
ENDFOREACH(_item ${PLUGIN_SOURCES})
|
||||
|
||||
|
||||
4
plugins/MidiExport/CMakeLists.txt
Normal file
4
plugins/MidiExport/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
BUILD_PLUGIN(midiexport MidiExport.cpp MidiExport.h MidiFile.hpp
|
||||
MOCFILES MidiExport.h)
|
||||
183
plugins/MidiExport/MidiExport.cpp
Normal file
183
plugins/MidiExport/MidiExport.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* MidiExport.cpp - support for importing MIDI files
|
||||
*
|
||||
* Author: Mohamed Abdel Maksoud <mohamed at amaksoud.com>
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDir>
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
|
||||
#include "MidiExport.h"
|
||||
#include "Engine.h"
|
||||
#include "TrackContainer.h"
|
||||
#include "InstrumentTrack.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
Plugin::Descriptor PLUGIN_EXPORT midiexport_plugin_descriptor =
|
||||
{
|
||||
STRINGIFY( PLUGIN_NAME ),
|
||||
"MIDI Export",
|
||||
QT_TRANSLATE_NOOP( "pluginBrowser",
|
||||
"Filter for exporting MIDI-files from LMMS" ),
|
||||
"Mohamed Abdel Maksoud <mohamed at amaksoud.com>",
|
||||
0x0100,
|
||||
Plugin::ExportFilter,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
MidiExport::MidiExport() : ExportFilter( &midiexport_plugin_descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
MidiExport::~MidiExport()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MidiExport::tryExport( const TrackContainer::TrackList &tracks, int tempo, const QString &filename )
|
||||
{
|
||||
QFile f(filename);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
QDataStream midiout(&f);
|
||||
|
||||
InstrumentTrack* instTrack;
|
||||
QDomElement element;
|
||||
|
||||
|
||||
int nTracks = 0;
|
||||
const int BUFFER_SIZE = 50*1024;
|
||||
uint8_t buffer[BUFFER_SIZE];
|
||||
uint32_t size;
|
||||
|
||||
foreach( Track* track, tracks ) if( track->type() == Track::InstrumentTrack ) nTracks++;
|
||||
|
||||
// midi header
|
||||
MidiFile::MIDIHeader header(nTracks);
|
||||
size = header.writeToBuffer(buffer);
|
||||
midiout.writeRawData((char *)buffer, size);
|
||||
|
||||
// midi tracks
|
||||
foreach( Track* track, tracks )
|
||||
{
|
||||
DataFile dataFile( DataFile::SongProject );
|
||||
MidiFile::MIDITrack<BUFFER_SIZE> mtrack;
|
||||
|
||||
if( track->type() != Track::InstrumentTrack ) continue;
|
||||
|
||||
//qDebug() << "exporting " << track->name();
|
||||
|
||||
|
||||
mtrack.addName(track->name().toStdString(), 0);
|
||||
//mtrack.addProgramChange(0, 0);
|
||||
mtrack.addTempo(tempo, 0);
|
||||
|
||||
instTrack = dynamic_cast<InstrumentTrack *>( track );
|
||||
element = instTrack->saveState( dataFile, dataFile.content() );
|
||||
|
||||
// instrumentTrack
|
||||
// - instrumentTrack
|
||||
// - pattern
|
||||
int base_pitch = 0;
|
||||
double base_volume = 1.0;
|
||||
int base_time = 0;
|
||||
|
||||
|
||||
for(QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling())
|
||||
{
|
||||
//QDomText txt = n.toText();
|
||||
//qDebug() << ">> child node " << n.nodeName();
|
||||
|
||||
if (n.nodeName() == "instrumenttrack")
|
||||
{
|
||||
// TODO interpret pan="0" fxch="0" usemasterpitch="1" pitchrange="1" pitch="0" basenote="57"
|
||||
QDomElement it = n.toElement();
|
||||
base_pitch = it.attribute("pitch", "0").toInt();
|
||||
base_volume = it.attribute("volume", "100").toDouble()/100.0;
|
||||
}
|
||||
|
||||
if (n.nodeName() == "pattern")
|
||||
{
|
||||
base_time = n.toElement().attribute("pos", "0").toInt();
|
||||
// TODO interpret steps="12" muted="0" type="1" name="Piano1" len="2592"
|
||||
for(QDomNode nn = n.firstChild(); !nn.isNull(); nn = nn.nextSibling())
|
||||
{
|
||||
QDomElement note = nn.toElement();
|
||||
if (note.attribute("len", "0") == "0" || note.attribute("vol", "0") == "0") continue;
|
||||
#if 0
|
||||
qDebug() << ">>>> key " << note.attribute( "key", "0" )
|
||||
<< " " << note.attribute("len", "0") << " @"
|
||||
<< note.attribute("pos", "0");
|
||||
#endif
|
||||
mtrack.addNote(
|
||||
note.attribute("key", "0").toInt()+base_pitch
|
||||
, 100 * base_volume * (note.attribute("vol", "100").toDouble()/100)
|
||||
, (base_time+note.attribute("pos", "0").toDouble())/48
|
||||
, (note.attribute("len", "0")).toDouble()/48);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
size = mtrack.writeToBuffer(buffer);
|
||||
midiout.writeRawData((char *)buffer, size);
|
||||
} // for each track
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MidiExport::error()
|
||||
{
|
||||
//qDebug() << "MidiExport error: " << m_error ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// necessary for getting instance out of shared lib
|
||||
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data )
|
||||
{
|
||||
return new MidiExport();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
58
plugins/MidiExport/MidiExport.h
Normal file
58
plugins/MidiExport/MidiExport.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* MidiExport.h - support for Exporting MIDI-files
|
||||
*
|
||||
* Author: Mohamed Abdel Maksoud <mohamed at amaksoud.com>
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* 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 _MIDI_EXPORT_H
|
||||
#define _MIDI_EXPORT_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "ExportFilter.h"
|
||||
#include "MidiFile.hpp"
|
||||
|
||||
|
||||
|
||||
class MidiExport: public ExportFilter
|
||||
{
|
||||
// Q_OBJECT
|
||||
public:
|
||||
MidiExport( );
|
||||
~MidiExport();
|
||||
|
||||
virtual PluginView * instantiateView( QWidget * )
|
||||
{
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
virtual bool tryExport( const TrackContainer::TrackList &tracks, int tempo, const QString &filename );
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void error( void );
|
||||
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
308
plugins/MidiExport/MidiFile.hpp
Normal file
308
plugins/MidiExport/MidiFile.hpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#ifndef MIDIFILE_HPP
|
||||
#define MIDIFILE_HPP
|
||||
|
||||
/**
|
||||
* Name: MidiFile.hpp
|
||||
* Purpose: C++ re-write of the python module MidiFile.py
|
||||
* Author: Mohamed Abdel Maksoud <mohamed at amaksoud.com>
|
||||
*-----------------------------------------------------------------------------
|
||||
* Name: MidiFile.py
|
||||
* Purpose: MIDI file manipulation utilities
|
||||
*
|
||||
* Author: Mark Conway Wirt <emergentmusics) at (gmail . com>
|
||||
*
|
||||
* Created: 2008/04/17
|
||||
* Copyright: (c) 2009 Mark Conway Wirt
|
||||
* License: Please see License.txt for the terms under which this
|
||||
* software is distributed.
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
|
||||
namespace MidiFile
|
||||
{
|
||||
|
||||
const int TICKSPERBEAT = 128;
|
||||
|
||||
|
||||
int writeVarLength(uint32_t val, uint8_t *buffer)
|
||||
{
|
||||
/*
|
||||
Accept an input, and write a MIDI-compatible variable length stream
|
||||
|
||||
The MIDI format is a little strange, and makes use of so-called variable
|
||||
length quantities. These quantities are a stream of bytes. If the most
|
||||
significant bit is 1, then more bytes follow. If it is zero, then the
|
||||
byte in question is the last in the stream
|
||||
*/
|
||||
int size = 0;
|
||||
uint8_t result, little_endian[4];
|
||||
result = val & 0x7F;
|
||||
little_endian[size++] = result;
|
||||
val = val >> 7;
|
||||
while (val > 0)
|
||||
{
|
||||
result = val & 0x7F;
|
||||
result = result | 0x80;
|
||||
little_endian[size++] = result;
|
||||
val = val >> 7;
|
||||
}
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
buffer[i] = little_endian[size-i-1];
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int writeBigEndian4(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = val >> 24;
|
||||
buf[1] = val >> 16 & 0xff;
|
||||
buf[2] = val >> 8 & 0xff;
|
||||
buf[3] = val & 0xff;
|
||||
return 4;
|
||||
}
|
||||
|
||||
int writeBigEndian2(uint16_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = val >> 8 & 0xff;
|
||||
buf[1] = val & 0xff;
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
class MIDIHeader
|
||||
{
|
||||
// Class to encapsulate the MIDI header structure.
|
||||
uint16_t numTracks;
|
||||
uint16_t ticksPerBeat;
|
||||
|
||||
public:
|
||||
|
||||
MIDIHeader(uint16_t nTracks, uint16_t ticksPB=TICKSPERBEAT): numTracks(nTracks), ticksPerBeat(ticksPB) {}
|
||||
|
||||
inline int writeToBuffer(uint8_t *buffer, int start=0) const
|
||||
{
|
||||
// chunk ID
|
||||
buffer[start++] = 'M'; buffer[start++] = 'T'; buffer[start++] = 'h'; buffer[start++] = 'd';
|
||||
// chunk size (6 bytes always)
|
||||
buffer[start++] = 0; buffer[start++] = 0; buffer[start++] = 0; buffer[start++] = 0x06;
|
||||
// format: 1 (multitrack)
|
||||
buffer[start++] = 0; buffer[start++] = 0x01;
|
||||
|
||||
start += writeBigEndian2(numTracks, buffer+start);
|
||||
|
||||
start += writeBigEndian2(ticksPerBeat, buffer+start);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct Event
|
||||
{
|
||||
uint32_t time;
|
||||
uint32_t tempo;
|
||||
string trackName;
|
||||
enum {NOTE_ON, NOTE_OFF, TEMPO, PROG_CHANGE, TRACK_NAME} type;
|
||||
// TODO make a union to save up space
|
||||
uint8_t pitch;
|
||||
uint8_t programNumber;
|
||||
uint8_t duration;
|
||||
uint8_t volume;
|
||||
uint8_t channel;
|
||||
|
||||
Event() {time=tempo=pitch=programNumber=duration=volume=channel=0; trackName="";}
|
||||
|
||||
inline int writeToBuffer(uint8_t *buffer) const
|
||||
{
|
||||
uint8_t code, fourbytes[4];
|
||||
int size=0;
|
||||
switch (type)
|
||||
{
|
||||
case NOTE_ON:
|
||||
code = 0x9 << 4 | channel;
|
||||
size += writeVarLength(time, buffer+size);
|
||||
buffer[size++] = code;
|
||||
buffer[size++] = pitch;
|
||||
buffer[size++] = volume;
|
||||
break;
|
||||
case NOTE_OFF:
|
||||
code = 0x8 << 4 | channel;
|
||||
size += writeVarLength(time, buffer+size);
|
||||
buffer[size++] = code;
|
||||
buffer[size++] = pitch;
|
||||
buffer[size++] = volume;
|
||||
break;
|
||||
case TEMPO:
|
||||
code = 0xFF;
|
||||
size += writeVarLength(time, buffer+size);
|
||||
buffer[size++] = code;
|
||||
buffer[size++] = 0x51;
|
||||
buffer[size++] = 0x03;
|
||||
writeBigEndian4(int(60000000.0 / tempo), fourbytes);
|
||||
|
||||
//printf("tempo of %x translates to ", tempo);
|
||||
for (int i=0; i<3; i++) printf("%02x ", fourbytes[i+1]);
|
||||
printf("\n");
|
||||
buffer[size++] = fourbytes[1];
|
||||
buffer[size++] = fourbytes[2];
|
||||
buffer[size++] = fourbytes[3];
|
||||
break;
|
||||
case PROG_CHANGE:
|
||||
code = 0xC << 4 | channel;
|
||||
size += writeVarLength(time, buffer+size);
|
||||
buffer[size++] = code;
|
||||
buffer[size++] = programNumber;
|
||||
break;
|
||||
case TRACK_NAME:
|
||||
size += writeVarLength(time, buffer+size);
|
||||
buffer[size++] = 0xFF;
|
||||
buffer[size++] = 0x03;
|
||||
size += writeVarLength(trackName.size(), buffer+size);
|
||||
trackName.copy((char *)(&buffer[size]), trackName.size());
|
||||
size += trackName.size();
|
||||
// buffer[size++] = '\0';
|
||||
// buffer[size++] = '\0';
|
||||
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
} // writeEventsToBuffer
|
||||
|
||||
|
||||
// events are sorted by their time
|
||||
inline bool operator < (const Event& b) const {
|
||||
return this->time < b.time;
|
||||
}
|
||||
};
|
||||
|
||||
template<const int MAX_TRACK_SIZE>
|
||||
class MIDITrack
|
||||
{
|
||||
// A class that encapsulates a MIDI track
|
||||
// Nested class definitions.
|
||||
vector<Event> events;
|
||||
|
||||
public:
|
||||
uint8_t channel;
|
||||
|
||||
MIDITrack(): channel(0) {}
|
||||
|
||||
inline void addEvent(const Event &e)
|
||||
{
|
||||
Event E = e;
|
||||
events.push_back(E);
|
||||
}
|
||||
|
||||
inline void addNote(uint8_t pitch, uint8_t volume, double time, double duration)
|
||||
{
|
||||
Event event; event.channel = channel;
|
||||
event.volume = volume;
|
||||
|
||||
event.type = Event::NOTE_ON; event.pitch = pitch; event.time= (uint32_t) (time * TICKSPERBEAT);
|
||||
addEvent(event);
|
||||
|
||||
event.type = Event::NOTE_OFF; event.pitch = pitch; event.time=(uint32_t) ((time+duration) * TICKSPERBEAT);
|
||||
addEvent(event);
|
||||
|
||||
//printf("note: %d-%d\n", (uint32_t) time * TICKSPERBEAT, (uint32_t)((time+duration) * TICKSPERBEAT));
|
||||
}
|
||||
|
||||
inline void addName(const string &name, uint32_t time)
|
||||
{
|
||||
Event event; event.channel = channel;
|
||||
event.type = Event::TRACK_NAME; event.time=time; event.trackName = name;
|
||||
addEvent(event);
|
||||
}
|
||||
|
||||
inline void addProgramChange(uint8_t prog, uint32_t time)
|
||||
{
|
||||
Event event; event.channel = channel;
|
||||
event.type = Event::PROG_CHANGE; event.time=time; event.programNumber = prog;
|
||||
addEvent(event);
|
||||
}
|
||||
|
||||
inline void addTempo(uint8_t tempo, uint32_t time)
|
||||
{
|
||||
Event event; event.channel = channel;
|
||||
event.type = Event::TEMPO; event.time=time; event.tempo = tempo;
|
||||
addEvent(event);
|
||||
}
|
||||
|
||||
inline int writeMIDIToBuffer(uint8_t *buffer, int start=0) const
|
||||
{
|
||||
// Write the meta data and note data to the packed MIDI stream.
|
||||
// Process the events in the eventList
|
||||
|
||||
start += writeEventsToBuffer(buffer, start);
|
||||
|
||||
// Write MIDI close event.
|
||||
buffer[start++] = 0x00;
|
||||
buffer[start++] = 0xFF;
|
||||
buffer[start++] = 0x2F;
|
||||
buffer[start++] = 0x00;
|
||||
|
||||
// return the entire length of the data and write to the header
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
inline int writeEventsToBuffer(uint8_t *buffer, int start=0) const
|
||||
{
|
||||
// Write the events in MIDIEvents to the MIDI stream.
|
||||
vector<Event> _events = events;
|
||||
std::sort(_events.begin(), _events.end());
|
||||
vector<Event>::const_iterator it;
|
||||
uint32_t time_last = 0, tmp;
|
||||
for (it = _events.begin(); it!=_events.end(); ++it)
|
||||
{
|
||||
Event e = *it;
|
||||
if (e.time < time_last){
|
||||
printf("error: e.time=%d time_last=%d\n", e.time, time_last);
|
||||
assert(false);
|
||||
}
|
||||
tmp = e.time;
|
||||
e.time -= time_last;
|
||||
time_last = tmp;
|
||||
start += e.writeToBuffer(buffer+start);
|
||||
if (start >= MAX_TRACK_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
inline int writeToBuffer(uint8_t *buffer, int start=0) const
|
||||
{
|
||||
uint8_t eventsBuffer[MAX_TRACK_SIZE];
|
||||
uint32_t events_size = writeMIDIToBuffer(eventsBuffer);
|
||||
//printf(">> track %lu events took 0x%x bytes\n", events.size(), events_size);
|
||||
|
||||
// chunk ID
|
||||
buffer[start++] = 'M'; buffer[start++] = 'T'; buffer[start++] = 'r'; buffer[start++] = 'k';
|
||||
// chunk size
|
||||
start += writeBigEndian4(events_size, buffer+start);
|
||||
// copy events data
|
||||
memmove(buffer+start, eventsBuffer, events_size);
|
||||
start += events_size;
|
||||
return start;
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
||||
@@ -497,6 +497,15 @@ bool MidiImport::readSMF( TrackContainer* tc )
|
||||
}
|
||||
}
|
||||
|
||||
// Set channel 10 to drums as per General MIDI's orders
|
||||
if( chs[9].hasNotes && chs[9].it_inst && chs[9].isSF2 )
|
||||
{
|
||||
// AFAIK, 128 should be the standard bank for drums in SF2.
|
||||
// If not, this has to be made configurable.
|
||||
chs[9].it_inst->childModel( "bank" )->setValue( 128 );
|
||||
chs[9].it_inst->childModel( "patch" )->setValue( 0 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
BUILD_PLUGIN(delay delayeffect.cpp delaycontrols.cpp delaycontrolsdialog.cpp lfo.cpp stereodelay.cpp MOCFILES delaycontrols.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
@@ -458,10 +458,6 @@ void lb302Synth::recalcFilter()
|
||||
vcf_envpos = ENVINC; // Trigger filter update in process()
|
||||
}
|
||||
|
||||
inline int MIN(int a, int b) {
|
||||
return (a<b)?a:b;
|
||||
}
|
||||
|
||||
inline float GET_INC(float freq) {
|
||||
return freq/Engine::mixer()->processingSampleRate(); // TODO: Use actual sampling rate.
|
||||
}
|
||||
|
||||
@@ -581,7 +581,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument,
|
||||
ck->setWhatsThis(
|
||||
tr( "With this knob you can set the coarse detuning of "
|
||||
"oscillator %1. You can detune the oscillator "
|
||||
"12 semitones (1 octave) up and down. This is "
|
||||
"24 semitones (2 octaves) up and down. This is "
|
||||
"useful for creating sounds with a chord." ).
|
||||
arg( i + 1 ) );
|
||||
|
||||
|
||||
@@ -82,18 +82,27 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
double out_sum = 0.0;
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
const float input = m_wsControls.m_inputModel.value();
|
||||
const float output = m_wsControls.m_outputModel.value();
|
||||
float input = m_wsControls.m_inputModel.value();
|
||||
float output = m_wsControls.m_outputModel.value();
|
||||
const float * samples = m_wsControls.m_wavegraphModel.samples();
|
||||
const bool clip = m_wsControls.m_clipModel.value();
|
||||
|
||||
ValueBuffer *inputBuffer = m_wsControls.m_inputModel.valueBuffer();
|
||||
ValueBuffer *outputBufer = m_wsControls.m_outputModel.valueBuffer();
|
||||
|
||||
int inputInc = inputBuffer ? 1 : 0;
|
||||
int outputInc = outputBufer ? 1 : 0;
|
||||
|
||||
float *inputPtr = inputBuffer ? &( inputBuffer->values()[ 0 ] ) : &input;
|
||||
float *outputPtr = outputBufer ? &( outputBufer->values()[ 0 ] ) : &output;
|
||||
|
||||
for( fpp_t f = 0; f < _frames; ++f )
|
||||
{
|
||||
float s[2] = { _buf[f][0], _buf[f][1] };
|
||||
|
||||
// apply input gain
|
||||
s[0] *= input;
|
||||
s[1] *= input;
|
||||
s[0] *= *inputPtr;
|
||||
s[1] *= *inputPtr;
|
||||
|
||||
// clip if clip enabled
|
||||
if( clip )
|
||||
@@ -127,13 +136,16 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
}
|
||||
|
||||
// apply output gain
|
||||
s[0] *= output;
|
||||
s[1] *= output;
|
||||
s[0] *= *outputPtr;
|
||||
s[1] *= *outputPtr;
|
||||
|
||||
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
|
||||
// mix wet/dry signals
|
||||
_buf[f][0] = d * _buf[f][0] + w * s[0];
|
||||
_buf[f][1] = d * _buf[f][1] + w * s[1];
|
||||
|
||||
outputPtr += outputInc;
|
||||
inputPtr += inputInc;
|
||||
}
|
||||
|
||||
checkGate( out_sum / _frames );
|
||||
|
||||
@@ -32,7 +32,11 @@ IF(MINGW_PREFIX)
|
||||
SET(FLTK_SKIP_FLUID TRUE)
|
||||
ENDIF()
|
||||
|
||||
FIND_PACKAGE(FLTK REQUIRED)
|
||||
FIND_PACKAGE(FLTK)
|
||||
|
||||
IF(NOT FLTK_FOUND)
|
||||
RETURN()
|
||||
ENDIF()
|
||||
|
||||
IF(MINGW_PREFIX)
|
||||
SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid")
|
||||
|
||||
Reference in New Issue
Block a user