Merge branch 'master' into cmake_dist

# Conflicts:
#	include/Plugin.h
#	src/core/Plugin.cpp
This commit is contained in:
Lukas W
2015-03-21 11:53:00 +01:00
105 changed files with 3436 additions and 1823 deletions

View File

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

View File

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

View 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")

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 ] ) : &amplitude;
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();
}

View File

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

View File

@@ -22,7 +22,7 @@
*
*/
#include "lfo.h"
#include "Lfo.h"
#include "lmms_math.h"

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

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

View File

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

View File

@@ -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 ] ) : &para1Bw;
float *para2BwPtr = para2BwBuffer ? &( para2BwBuffer->values()[ 0 ] ) : &para2Bw;
float *para3BwPtr = para3BwBuffer ? &( para3BwBuffer->values()[ 0 ] ) : &para3Bw;
float *para4BwPtr = para4BwBuffer ? &( para4BwBuffer->values()[ 0 ] ) : &para4Bw;
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 ] ) : &para1Freq;
float *para2FreqPtr = para2FreqBuffer ? &(para2FreqBuffer->values()[ 0 ] ) : &para2Freq;
float *para3FreqPtr = para3FreqBuffer ? &(para3FreqBuffer->values()[ 0 ] ) : &para3Freq;
float *para4FreqPtr = para4FreqBuffer ? &(para4FreqBuffer->values()[ 0 ] ) : &para4Freq;
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;

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,4 @@
INCLUDE(BuildPlugin)
BUILD_PLUGIN(midiexport MidiExport.cpp MidiExport.h MidiFile.hpp
MOCFILES MidiExport.h)

View 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();
}
}

View 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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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