Merge branch 'master' into dynamic-effect-dialog

This commit is contained in:
Michael Gregorius
2023-07-06 13:12:04 +02:00
455 changed files with 3340 additions and 2448 deletions

View File

@@ -74,7 +74,7 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const ValueBuffer * volBuf = m_ampControls.m_volumeModel.valueBuffer();
const ValueBuffer * panBuf = m_ampControls.m_panModel.valueBuffer();
const ValueBuffer * leftBuf = m_ampControls.m_leftModel.valueBuffer();
@@ -83,8 +83,8 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
for( fpp_t f = 0; f < frames; ++f )
{
// qDebug( "offset %d, value %f", f, m_ampControls.m_volumeModel.value( f ) );
sample_t s[2] = { buf[f][0], buf[f][1] };
auto s = std::array{buf[f][0], buf[f][1]};
// vol knob
if( volBuf )
@@ -99,8 +99,8 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
}
// convert pan values to left/right values
const float pan = panBuf
? panBuf->value( f )
const float pan = panBuf
? panBuf->value( f )
: m_ampControls.m_panModel.value();
const float left1 = pan <= 0
? 1.0
@@ -111,12 +111,12 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
// second stage amplification
const float left2 = leftBuf
? leftBuf->value( f )
? leftBuf->value( f )
: m_ampControls.m_leftModel.value();
const float right2 = rightBuf
? rightBuf->value( f )
? rightBuf->value( f )
: m_ampControls.m_rightModel.value();
s[0] *= left1 * left2 * 0.01;
s[1] *= right1 * right2 * 0.01;

View File

@@ -550,7 +550,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument,
connect( castModel<AudioFileProcessor>(), SIGNAL( isPlaying( lmms::f_cnt_t ) ),
m_waveView, SLOT( isPlaying( lmms::f_cnt_t ) ) );
qRegisterMetaType<f_cnt_t>( "f_cnt_t" );
qRegisterMetaType<lmms::f_cnt_t>( "lmms::f_cnt_t" );
setAcceptDrops( true );
}
@@ -1287,4 +1287,4 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main(Model * model, void *)
}
} // namespace lmms
} // namespace lmms

View File

@@ -102,7 +102,7 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
m_bbFX.leftFX().setGain( gain );
m_bbFX.rightFX().setGain( gain);
sample_t s[2] = { buf[f][0], buf[f][1] };
auto s = std::array{buf[f][0], buf[f][1]};
m_bbFX.nextSample( s[0], s[1] );
buf[f][0] = d * buf[f][0] + w * s[0];

View File

@@ -35,8 +35,8 @@ const int OS_RATE = 5;
const float OS_RATIO = 1.0f / OS_RATE;
const float CUTOFF_RATIO = 0.353553391f;
const int SILENCEFRAMES = 10;
const float OS_RESAMPLE [5] = { 0.0001490062883964112, 0.1645978376763992, 0.6705063120704088,
0.1645978376763992, 0.0001490062883964112 };
const auto OS_RESAMPLE = std::array{0.0001490062883964112f, 0.1645978376763992f, 0.6705063120704088f,
0.1645978376763992f, 0.0001490062883964112f };
extern "C"
{
@@ -65,13 +65,13 @@ BitcrushEffect::BitcrushEffect( Model * parent, const Descriptor::SubPluginFeatu
m_buffer = MM_ALLOC<sampleFrame>( Engine::audioEngine()->framesPerPeriod() * OS_RATE );
m_filter.setLowpass( m_sampleRate * ( CUTOFF_RATIO * OS_RATIO ) );
m_needsUpdate = true;
m_bitCounterL = 0.0f;
m_bitCounterR = 0.0f;
m_left = 0.0f;
m_right = 0.0f;
m_silenceCounter = 0;
}
@@ -125,7 +125,7 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
m_rateCoeffL = ( m_sampleRate * OS_RATE ) / ( rate - diff );
m_rateCoeffR = ( m_sampleRate * OS_RATE ) / ( rate + diff );
m_bitCounterL = 0.0f;
m_bitCounterR = 0.0f;
}
@@ -147,9 +147,9 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
m_outClip = dbfsToAmp( m_controls.m_outClip.value() );
}
m_needsUpdate = false;
const float noiseAmt = m_controls.m_inNoise.value() * 0.01f;
// read input buffer and write it to oversampled buffer
if( m_rateEnabled ) // rate crushing enabled so do that
{
@@ -164,15 +164,15 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
if( m_bitCounterL > m_rateCoeffL )
{
m_bitCounterL -= m_rateCoeffL;
m_left = m_depthEnabled
? depthCrush( buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ) )
m_left = m_depthEnabled
? depthCrush( buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ) )
: buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt );
}
if( m_bitCounterR > m_rateCoeffR )
{
m_bitCounterR -= m_rateCoeffR;
m_right = m_depthEnabled
? depthCrush( buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ) )
m_right = m_depthEnabled
? depthCrush( buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ) )
: buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt );
}
}
@@ -185,17 +185,17 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
for( int o = 0; o < OS_RATE; ++o )
{
m_buffer[f * OS_RATE + o][0] = m_depthEnabled
? depthCrush( buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ) )
? depthCrush( buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt ) )
: buf[f][0] * m_inGain + noise( buf[f][0] * noiseAmt );
m_buffer[f * OS_RATE + o][1] = m_depthEnabled
? depthCrush( buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ) )
? depthCrush( buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt ) )
: buf[f][1] * m_inGain + noise( buf[f][1] * noiseAmt );
}
}
}
// the oversampled buffer is now written, so filter it to reduce aliasing
for( int f = 0; f < frames * OS_RATE; ++f )
{
if( qMax( qAbs( m_buffer[f][0] ), qAbs( m_buffer[f][1] ) ) >= 1.0e-10f )
@@ -218,10 +218,10 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
}
}
}
// now downsample and write it back to main buffer
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
@@ -238,7 +238,7 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
buf[f][1] = d * buf[f][1] + w * qBound( -m_outClip, rsum, m_outClip ) * m_outGain;
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );
return isRunning();

View File

@@ -15,14 +15,13 @@ if(LMMS_HAVE_WEAKCARLA)
${CMAKE_CURRENT_SOURCE_DIR}/carla/source/backend
)
# force "lib" prefix
IF(LMMS_BUILD_WIN32)
# use carla.dll
SET(CMAKE_SHARED_LIBRARY_PREFIX "")
SET(CARLA_NATIVE_LIB carla)
ELSE()
# use libcarla_native-plugin
SET(CARLA_NATIVE_LIB carla_native-plugin)
SET(CMAKE_SHARED_LIBRARY_PREFIX "lib")
ENDIF()
SET(CARLA_NATIVE_LIB carla_native-plugin)
ADD_LIBRARY(${CARLA_NATIVE_LIB} SHARED DummyCarla.cpp)
TARGET_INCLUDE_DIRECTORIES(${CARLA_NATIVE_LIB} PUBLIC ${CARLA_INCLUDE_DIRS})
INSTALL(TARGETS ${CARLA_NATIVE_LIB}

View File

@@ -276,7 +276,7 @@ bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
float rOutPeak = 0.0;
float lInPeak = 0.0;
float rInPeak = 0.0;
const bool midside = m_compressorControls.m_midsideModel.value();
const bool peakmode = m_compressorControls.m_peakmodeModel.value();
const float inBalance = m_compressorControls.m_inBalanceModel.value();
@@ -292,8 +292,8 @@ bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
for(fpp_t f = 0; f < frames; ++f)
{
sample_t drySignal[2] = {buf[f][0], buf[f][1]};
sample_t s[2] = {drySignal[0] * m_inGainVal, drySignal[1] * m_inGainVal};
auto drySignal = std::array{buf[f][0], buf[f][1]};
auto s = std::array{drySignal[0] * m_inGainVal, drySignal[1] * m_inGainVal};
// Calculate tilt filters, to bias the sidechain to the low or high frequencies
if (m_tiltVal)
@@ -512,7 +512,7 @@ bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
m_inputBufLoc = 0;
}
const float temp[2] = {drySignal[0], drySignal[1]};
const auto temp = std::array{drySignal[0], drySignal[1]};
s[0] = m_inputBuf[0][m_inputBufLoc];
s[1] = m_inputBuf[1][m_inputBufLoc];
@@ -525,8 +525,8 @@ bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
s[1] = drySignal[1];
}
float delayedDrySignal[2] = {s[0], s[1]};
auto delayedDrySignal = std::array{s[0], s[1]};
if (midside)// Convert left/right to mid/side
{
const float temp = s[0];

View File

@@ -206,7 +206,7 @@ CompressorControlDialog::CompressorControlDialog(CompressorControls* controls) :
peakButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("peak_sel"));
peakButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("peak_unsel"));
peakButton->setToolTip(tr("Use absolute value of the input"));
rmsPeakGroup = new automatableButtonGroup(this);
rmsPeakGroup->addButton(rmsButton);
rmsPeakGroup->addButton(peakButton);
@@ -221,7 +221,7 @@ CompressorControlDialog::CompressorControlDialog(CompressorControls* controls) :
midSideButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("midside_sel"));
midSideButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("midside_unsel"));
midSideButton->setToolTip(tr("Compress mid and side audio"));
leftRightMidSideGroup = new automatableButtonGroup(this);
leftRightMidSideGroup->addButton(leftRightButton);
leftRightMidSideGroup->addButton(midSideButton);
@@ -514,8 +514,8 @@ void CompressorControlDialog::redrawKnee()
{
m_p.setPen(QPen(m_kneeColor2, 3));
float prevPoint[2] = {kneePoint1, kneePoint1};
float newPoint[2] = {0, 0};
auto prevPoint = std::array{kneePoint1, kneePoint1};
auto newPoint = std::array{0.f, 0.f};
// Draw knee curve using many straight lines.
for (int i = 0; i < COMP_KNEE_LINES; ++i)
@@ -542,7 +542,7 @@ void CompressorControlDialog::redrawKnee()
m_p.end();
m_p.begin(&m_kneePixmap2);
m_p.setCompositionMode(QPainter::CompositionMode_Source);
m_p.fillRect(0, 0, m_windowSizeX, m_kneeWindowSizeY, QColor("transparent"));
m_p.setCompositionMode(QPainter::CompositionMode_SourceOver);

View File

@@ -91,7 +91,7 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
const float sr = Engine::audioEngine()->processingSampleRate();
const float d = dryLevel();
const float w = wetLevel();
sample_t dryS[2];
auto dryS = std::array<sample_t, 2>{};
float lPeak = 0.0;
float rPeak = 0.0;
float length = m_delayControls.m_delayTimeModel.value();

View File

@@ -0,0 +1,3 @@
INCLUDE(BuildPlugin)
BUILD_PLUGIN(dispersion Dispersion.cpp DispersionControls.cpp DispersionControlDialog.cpp MOCFILES DispersionControls.h DispersionControlDialog.h EMBEDDED_RESOURCES *.png)

View File

@@ -0,0 +1,162 @@
/*
* Dispersion.cpp
*
* Copyright (c) 2023 Lost Robot <r94231/at/gmail/dot/com>
*
* This file is part of LMMS - https://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 "Dispersion.h"
#include "embed.h"
#include "plugin_export.h"
namespace lmms
{
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT dispersion_plugin_descriptor =
{
LMMS_STRINGIFY(PLUGIN_NAME),
"Dispersion",
QT_TRANSLATE_NOOP("PluginBrowser", "An all-pass filter allowing for extremely high orders."),
"Lost Robot <r94231/at/gmail/dot/com>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader("logo"),
nullptr,
nullptr
};
}
DispersionEffect::DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key) :
Effect(&dispersion_plugin_descriptor, parent, key),
m_dispersionControls(this),
m_sampleRate(Engine::audioEngine()->processingSampleRate()),
m_amountVal(0)
{
}
bool DispersionEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning())
{
return false;
}
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const int amount = m_dispersionControls.m_amountModel.value();
const float freq = m_dispersionControls.m_freqModel.value();
const float reso = m_dispersionControls.m_resoModel.value();
float feedback = m_dispersionControls.m_feedbackModel.value();
const bool dc = m_dispersionControls.m_dcModel.value();
// All-pass coefficient calculation
const float w0 = (F_2PI / m_sampleRate) * freq;
const float a0 = 1 + (std::sin(w0) / (reso * 2.f));
float apCoeff1 = (1 - (a0 - 1)) / a0;
float apCoeff2 = (-2 * std::cos(w0)) / a0;
float dcCoeff = 0.001 * (44100.f / m_sampleRate);
if (amount != m_amountVal)
{
if (amount < m_amountVal)
{
// Flush filter buffers when they're no longer in use
for (int i = amount * 2; i < m_amountVal * 2; ++i)
{
m_state.x0[i] = m_state.x1[i] = m_state.y0[i] = m_state.y1[i] = 0;
}
}
m_amountVal = amount;
}
if (amount == 0)
{
feedback = 0;
m_feedbackVal[0] = m_feedbackVal[1] = 0;
}
for (fpp_t f = 0; f < frames; ++f)
{
std::array<sample_t, 2> s = { buf[f][0] + m_feedbackVal[0], buf[f][1] + m_feedbackVal[1] };
runDispersionAP(m_amountVal, apCoeff1, apCoeff2, s);
m_feedbackVal[0] = s[0] * feedback;
m_feedbackVal[1] = s[1] * feedback;
if (dc)
{
// DC offset removal
for (int i = 0; i < 2; ++i)
{
m_integrator[i] = m_integrator[i] * (1.f - dcCoeff) + s[i] * dcCoeff;
s[i] -= m_integrator[i];
}
}
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
}
checkGate(outSum / frames);
return isRunning();
}
void DispersionEffect::runDispersionAP(const int filtNum, const float apCoeff1, const float apCoeff2, std::array<sample_t, 2> &put)
{
for (int i = 0; i < filtNum * 2; ++i)
{
const int channel = i % 2;
const sample_t currentInput = put[channel];
const sample_t filterOutput = apCoeff1 * (currentInput - m_state.y1[i])
+ apCoeff2 * (m_state.x0[i] - m_state.y0[i]) + m_state.x1[i];
m_state.x1[i] = m_state.x0[i];
m_state.x0[i] = currentInput;
m_state.y1[i] = m_state.y0[i];
m_state.y0[i] = filterOutput;
put[channel] = filterOutput;
}
}
extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main(Model* parent, void* data)
{
return new DispersionEffect(parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>(data));
}
}
} // namespace lmms

View File

@@ -0,0 +1,78 @@
/*
* Dispersion.h
*
* Copyright (c) 2023 Lost Robot <r94231/at/gmail/dot/com>
*
* This file is part of LMMS - https://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 LMMS_DISPERSION_H
#define LMMS_DISPERSION_H
#include "DispersionControls.h"
#include "Effect.h"
#include "lmms_math.h"
namespace lmms
{
constexpr inline int MAX_DISPERSION_FILTERS = 999;
class DispersionEffect : public Effect
{
public:
DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
~DispersionEffect() override = default;
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
EffectControls* controls() override
{
return &m_dispersionControls;
}
void runDispersionAP(const int filtNum, const float apCoeff1, const float apCoeff2, std::array<sample_t, 2> &put);
private:
DispersionControls m_dispersionControls;
float m_sampleRate;
int m_amountVal;
using Filter = std::array<sample_t, MAX_DISPERSION_FILTERS * 2>;
struct FilterState {
Filter x0{};
Filter x1{};
Filter y0{};
Filter y1{};
};
FilterState m_state = {};
std::array<float, 2> m_feedbackVal{};
std::array<float, 2> m_integrator{};
friend class DispersionControls;
};
} // namespace lmms
#endif // LMMS_DISPERSION_H

View File

@@ -0,0 +1,82 @@
/*
* DispersionControlDialog.cpp
*
* Copyright (c) 2023 Lost Robot <r94231/at/gmail/dot/com>
*
* This file is part of LMMS - https://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 "DispersionControlDialog.h"
#include "DispersionControls.h"
#include "embed.h"
#include "Knob.h"
#include "LcdSpinBox.h"
#include "PixmapButton.h"
namespace lmms::gui
{
DispersionControlDialog::DispersionControlDialog(DispersionControls* controls) :
EffectControlDialog(controls)
{
setAutoFillBackground(true);
QPalette pal;
pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
setPalette(pal);
setFixedSize(207, 50);
LcdSpinBox * m_amountBox = new LcdSpinBox(3, this, "Amount");
m_amountBox->setModel(&controls->m_amountModel);
m_amountBox->move(5, 10);
m_amountBox->setLabel(tr("AMOUNT"));
m_amountBox->setToolTip(tr("Number of all-pass filters"));
Knob * freqKnob = new Knob(knobBright_26, this);
freqKnob->move(59, 8);
freqKnob->setModel(&controls->m_freqModel);
freqKnob->setLabel(tr("FREQ"));
freqKnob->setHintText(tr("Frequency:") , " Hz");
Knob * resoKnob = new Knob(knobBright_26, this);
resoKnob->move(99, 8);
resoKnob->setModel(&controls->m_resoModel);
resoKnob->setLabel(tr("RESO"));
resoKnob->setHintText(tr("Resonance:") , " octaves");
Knob * feedbackKnob = new Knob(knobBright_26, this);
feedbackKnob->move(139, 8);
feedbackKnob->setModel(&controls->m_feedbackModel);
feedbackKnob->setLabel(tr("FEED"));
feedbackKnob->setHintText(tr("Feedback:") , "");
PixmapButton * dcButton = new PixmapButton(this, tr("DC Offset Removal"));
dcButton->move(176, 16);
dcButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("dc_active"));
dcButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("dc_inactive"));
dcButton->setCheckable(true);
dcButton->setModel(&controls->m_dcModel);
dcButton->setToolTip(tr("Remove DC Offset"));
}
} // namespace lmms::gui

View File

@@ -0,0 +1,52 @@
/*
* DispersionControlDialog.h
*
* Copyright (c) 2023 Lost Robot <r94231/at/gmail/dot/com>
*
* This file is part of LMMS - https://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 LMMS_GUI_DISPERSION_CONTROL_DIALOG_H
#define LMMS_GUI_DISPERSION_CONTROL_DIALOG_H
#include "EffectControlDialog.h"
namespace lmms
{
class DispersionControls;
namespace gui
{
class DispersionControlDialog : public EffectControlDialog
{
Q_OBJECT
public:
DispersionControlDialog(DispersionControls* controls);
~DispersionControlDialog() override = default;
};
} // namespace gui
} // namespace lmms
#endif // LMMS_GUI_DISPERSION_CONTROL_DIALOG_H

View File

@@ -0,0 +1,73 @@
/*
* DispersionControls.cpp
*
* Copyright (c) 2023 Lost Robot <r94231/at/gmail/dot/com>
*
* This file is part of LMMS - https://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 "DispersionControls.h"
#include "Dispersion.h"
#include <QDomElement>
namespace lmms
{
DispersionControls::DispersionControls(DispersionEffect* effect) :
EffectControls(effect),
m_effect(effect),
m_amountModel(0, 0, MAX_DISPERSION_FILTERS, this, tr("Amount")),
m_freqModel(200, 20, 20000, 0.001, this, tr("Frequency")),
m_resoModel(0.707, 0.01, 8, 0.0001, this, tr("Resonance")),
m_feedbackModel(0.f, -1.f, 1.f, 0.0001, this, tr("Feedback")),
m_dcModel(false, this, tr("DC Offset Removal"))
{
m_freqModel.setScaleLogarithmic(true);
m_resoModel.setScaleLogarithmic(true);
}
void DispersionControls::loadSettings(const QDomElement& parent)
{
m_amountModel.loadSettings(parent, "amount");
m_freqModel.loadSettings(parent, "freq");
m_resoModel.loadSettings(parent, "reso");
m_feedbackModel.loadSettings(parent, "feedback");
m_dcModel.loadSettings(parent, "dc");
}
void DispersionControls::saveSettings(QDomDocument& doc, QDomElement& parent)
{
m_amountModel.saveSettings(doc, parent, "amount");
m_freqModel.saveSettings(doc, parent, "freq");
m_resoModel.saveSettings(doc, parent, "reso");
m_feedbackModel.saveSettings(doc, parent, "feedback");
m_dcModel.saveSettings(doc, parent, "dc");
}
} // namespace lmms

View File

@@ -0,0 +1,81 @@
/*
* DispersionControls.h
*
* Copyright (c) 2023 Lost Robot <r94231/at/gmail/dot/com>
*
* This file is part of LMMS - https://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 LMMS_DISPERSION_CONTROLS_H
#define LMMS_DISPERSION_CONTROLS_H
#include "DispersionControlDialog.h"
#include "EffectControls.h"
namespace lmms
{
class DispersionEffect;
namespace gui
{
class DispersionControlDialog;
}
class DispersionControls : public EffectControls
{
Q_OBJECT
public:
DispersionControls(DispersionEffect* effect);
~DispersionControls() override = default;
void saveSettings(QDomDocument & doc, QDomElement & parent) override;
void loadSettings(const QDomElement & parent) override;
inline QString nodeName() const override
{
return "DispersionControls";
}
int controlCount() override
{
return 5;
}
gui::EffectControlDialog* createView() override
{
return new gui::DispersionControlDialog(this);
}
private:
DispersionEffect* m_effect;
IntModel m_amountModel;
FloatModel m_freqModel;
FloatModel m_resoModel;
FloatModel m_feedbackModel;
BoolModel m_dcModel;
friend class gui::DispersionControlDialog;
friend class DispersionEffect;
};
} // namespace lmms
#endif // LMMS_DISPERSION_CONTROLS_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
plugins/Dispersion/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

View File

@@ -134,8 +134,8 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
const bool enabled1 = m_dfControls.m_enabled1Model.value();
const bool enabled2 = m_dfControls.m_enabled2Model.value();
// buffer processing loop
for( fpp_t f = 0; f < frames; ++f )
@@ -145,9 +145,9 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
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
auto s = std::array{0.0f, 0.0f}; // mix
auto s1 = std::array{buf[f][0], buf[f][1]}; // filter 1
auto s2 = std::array{buf[f][0], buf[f][1]}; // filter 2
// update filter 1
if( enabled1 )

View File

@@ -105,17 +105,17 @@ bool DynProcEffect::processAudioBuffer( sampleFrame * _buf,
// variables for effect
int i = 0;
float sm_peak[2] = { 0.0f, 0.0f };
auto sm_peak = std::array{0.0f, 0.0f};
float gain;
double out_sum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const int stereoMode = m_dpControls.m_stereomodeModel.value();
const float inputGain = m_dpControls.m_inputModel.value();
const float outputGain = m_dpControls.m_outputModel.value();
const float * samples = m_dpControls.m_wavegraphModel.samples();
// debug code
@@ -143,7 +143,7 @@ bool DynProcEffect::processAudioBuffer( sampleFrame * _buf,
for( fpp_t f = 0; f < _frames; ++f )
{
double s[2] = { _buf[f][0], _buf[f][1] };
auto s = std::array{_buf[f][0], _buf[f][1]};
// apply input gain
s[0] *= inputGain;
@@ -211,7 +211,7 @@ bool DynProcEffect::processAudioBuffer( sampleFrame * _buf,
gain = samples[199];
};
s[i] *= gain;
s[i] *= gain;
s[i] /= sm_peak[i];
}
}

View File

@@ -116,7 +116,7 @@ void DynProcControls::saveSettings( QDomDocument & _doc,
void DynProcControls::setDefaultShape()
{
float shp [200] = { };
auto shp = std::array<float, 200>{};
for ( int i = 0; i<200; i++)
{
shp[i] = ((float)i + 1.0f) / 200.0f;

View File

@@ -46,12 +46,12 @@ EqControls::EqControls( EqEffect *effect ) :
m_para4GainModel( 0.0 , -18, 18, 0.001, this, tr( "Peak 4 gain" ) ),
m_highShelfGainModel( 0.0 , -18, 18, 0.001, this, tr( "High-shelf gain" ) ),
m_hpResModel( 0.707,0.003, 10.0 , 0.001, this, tr( "HP res" ) ),
m_lowShelfResModel( 1.4,0.55, 10.0 , 0.001, this , tr( "Low-shelf res" ) ),
m_lowShelfResModel( 0.707, 0.55, 10.0 , 0.001, this , tr( "Low-shelf res" ) ),
m_para1BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 1 BW" ) ),
m_para2BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 2 BW" ) ),
m_para3BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 3 BW" ) ),
m_para4BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 4 BW" ) ),
m_highShelfResModel( 1.4, 0.55, 10.0 , 0.001, this , tr( "High-shelf res" ) ),
m_highShelfResModel( 0.707, 0.55, 10.0 , 0.001, this , tr( "High-shelf res" ) ),
m_lpResModel( 0.707,0.003, 10.0 , 0.001, this , tr( "LP res" ) ),
m_hpFeqModel( 31.0, 20.0, 20000, 0.001, this , tr( "HP freq" ) ),
m_lowShelfFreqModel( 80.0, 20.0, 20000, 0.001, this , tr( "Low-shelf freq" ) ),

View File

@@ -316,8 +316,7 @@ float EqHandle::getLowCutCurve( float x )
double c = cosf( w0 );
double s = sinf( w0 );
double resonance = getResonance();
double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20);
double alpha = s / 2 * sqrt ( ( A +1/A ) * ( 1 / resonance -1 ) +2 );
double alpha = s / (2 * resonance);
double a0, a1, a2, b0, b1, b2; // coeffs to calculate
b0 = ( 1 + c ) * 0.5;
@@ -360,8 +359,7 @@ float EqHandle::getHighCutCurve( float x )
double c = cosf( w0 );
double s = sinf( w0 );
double resonance = getResonance();
double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20 );
double alpha = s / 2 * sqrt ( ( A + 1 / A ) * ( 1 / resonance -1 ) +2 );
double alpha = s / (2 * resonance);
double a0, a1, a2, b0, b1, b2; // coeffs to calculate
b0 = ( 1 - c ) * 0.5;

View File

@@ -71,7 +71,7 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
//wet/dry controls
const float dry = dryLevel();
const float wet = wetLevel();
sample_t dryS[2];
auto dryS = std::array<sample_t, 2>{};
// setup sample exact controls
float hpRes = m_eqControls.m_hpResModel.value();
float lowShelfRes = m_eqControls.m_lowShelfResModel.value();

View File

@@ -24,6 +24,9 @@
#include "FlangerEffect.h"
#include "Engine.h"
#include "MonoDelay.h"
#include "Noise.h"
#include "QuadratureLfo.h"
#include "embed.h"
#include "plugin_export.h"
@@ -104,7 +107,7 @@ bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
m_lfo->setOffset( m_flangerControls.m_lfoPhaseModel.value() / 180 * D_PI );
m_lDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
m_rDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
sample_t dryS[2];
auto dryS = std::array<sample_t, 2>{};
float leftLfo;
float rightLfo;
for( fpp_t f = 0; f < frames; ++f )

View File

@@ -28,17 +28,14 @@
#include "Effect.h"
#include "FlangerControls.h"
#include "MonoDelay.h"
#include "Noise.h"
#include "QuadratureLfo.h"
namespace lmms
{
class MonoDelay;
class Noise;
class QuadratureLfo;
namespace lmms
{
class FlangerEffect : public Effect
{

View File

@@ -4,8 +4,8 @@ INCLUDE_DIRECTORIES(game-music-emu/gme)
BUILD_PLUGIN(freeboy
FreeBoy.cpp
FreeBoy.h
Gb_Apu_Buffer.cpp
Gb_Apu_Buffer.h
GbApuWrapper.cpp
GbApuWrapper.h
game-music-emu/gme/Gb_Apu.cpp
game-music-emu/gme/Gb_Apu.h
game-music-emu/gme/Gb_Oscs.cpp

View File

@@ -2,7 +2,7 @@
* FreeBoy.cpp - GameBoy papu based instrument
*
* Copyright (c) 2008 Attila Herman <attila589/at/gmail.com>
* Csaba Hruska <csaba.hruska/at/gmail.com>
* Csaba Hruska <csaba.hruska/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
@@ -23,11 +23,12 @@
*
*/
#include <cmath>
#include <QDomElement>
#include "FreeBoy.h"
#include "Gb_Apu_Buffer.h"
#include <cmath>
#include <QDomElement>
#include "GbApuWrapper.h"
#include "base64.h"
#include "InstrumentTrack.h"
#include "Knob.h"
@@ -45,8 +46,11 @@ namespace lmms
{
const blip_time_t FRAME_LENGTH = 70224;
const long CLOCK_RATE = 4194304;
namespace
{
constexpr blip_time_t FRAME_LENGTH = 70224;
constexpr long CLOCK_RATE = 4194304;
}
extern "C"
{
@@ -118,9 +122,7 @@ FreeBoyInstrument::FreeBoyInstrument( InstrumentTrack * _instrument_track ) :
m_trebleModel( -20.0f, -100.0f, 200.0f, 1.0f, this, tr( "Treble" ) ),
m_bassModel( 461.0f, -1.0f, 600.0f, 1.0f, this, tr( "Bass" ) ),
m_graphModel( 0, 15, 32, this, false, 1 ),
m_time(0)
m_graphModel( 0, 15, 32, this, false, 1 )
{
}
@@ -238,189 +240,193 @@ f_cnt_t FreeBoyInstrument::desiredReleaseFrames() const
void FreeBoyInstrument::playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer )
void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer)
{
const f_cnt_t tfp = _n->totalFramesPlayed();
const f_cnt_t tfp = nph->totalFramesPlayed();
const int samplerate = Engine::audioEngine()->processingSampleRate();
const fpp_t frames = _n->framesLeftForCurrentPeriod();
const f_cnt_t offset = _n->noteOffset();
const fpp_t frames = nph->framesLeftForCurrentPeriod();
const f_cnt_t offset = nph->noteOffset();
int data = 0;
int freq = _n->frequency();
int freq = nph->frequency();
if ( tfp == 0 )
{
auto papu = new Gb_Apu_Buffer();
papu->set_sample_rate( samplerate, CLOCK_RATE );
auto papu = new GbApuWrapper{};
papu->setSampleRate(samplerate, CLOCK_RATE);
// Master sound circuitry power control
papu->write_register( fakeClock(), 0xff26, 0x80 );
papu->writeRegister(0xff26, 0x80);
data = m_ch1VolumeModel.value();
data = data<<1;
data = data << 1;
data += m_ch1VolSweepDirModel.value();
data = data<<3;
data = data << 3;
data += m_ch1SweepStepLengthModel.value();
papu->write_register( fakeClock(), 0xff12, data );
papu->writeRegister(0xff12, data);
data = m_ch2VolumeModel.value();
data = data<<1;
data = data << 1;
data += m_ch2VolSweepDirModel.value();
data = data<<3;
data = data << 3;
data += m_ch2SweepStepLengthModel.value();
papu->write_register( fakeClock(), 0xff17, data );
papu->writeRegister(0xff17, data);
//channel 4 - noise
data = m_ch4VolumeModel.value();
data = data<<1;
data = data << 1;
data += m_ch4VolSweepDirModel.value();
data = data<<3;
data = data << 3;
data += m_ch4SweepStepLengthModel.value();
papu->write_register( fakeClock(), 0xff21, data );
papu->writeRegister(0xff21, data);
_n->m_pluginData = papu;
nph->m_pluginData = papu;
}
auto papu = static_cast<Gb_Apu_Buffer*>(_n->m_pluginData);
auto papu = static_cast<GbApuWrapper*>(nph->m_pluginData);
papu->treble_eq( m_trebleModel.value() );
papu->bass_freq( m_bassModel.value() );
papu->trebleEq(m_trebleModel.value());
papu->bassFreq(m_bassModel.value());
//channel 1 - square
data = m_ch1SweepTimeModel.value();
data = data<<1;
data = data << 1;
data += m_ch1SweepDirModel.value();
data = data << 3;
data += m_ch1SweepRtShiftModel.value();
papu->write_register( fakeClock(), 0xff10, data );
papu->writeRegister(0xff10, data);
data = m_ch1WavePatternDutyModel.value();
data = data<<6;
papu->write_register( fakeClock(), 0xff11, data );
data = data << 6;
papu->writeRegister(0xff11, data);
//channel 2 - square
data = m_ch2WavePatternDutyModel.value();
data = data<<6;
papu->write_register( fakeClock(), 0xff16, data );
data = data << 6;
papu->writeRegister(0xff16, data);
//channel 3 - wave
//data = m_ch3OnModel.value()?128:0;
//data = m_ch3OnModel.value() ? 128 : 0;
data = 128;
papu->write_register( fakeClock(), 0xff1a, data );
papu->writeRegister(0xff1a, data);
int ch3voldata[4] = { 0, 3, 2, 1 };
auto ch3voldata = std::array{0, 3, 2, 1};
data = ch3voldata[(int)m_ch3VolumeModel.value()];
data = data<<5;
papu->write_register( fakeClock(), 0xff1c, data );
data = data << 5;
papu->writeRegister(0xff1c, data);
//controls
data = m_so1VolumeModel.value();
data = data<<4;
data = data << 4;
data += m_so2VolumeModel.value();
papu->write_register( fakeClock(), 0xff24, data );
papu->writeRegister(0xff24, data);
data = m_ch4So2Model.value()?128:0;
data += m_ch3So2Model.value()?64:0;
data += m_ch2So2Model.value()?32:0;
data += m_ch1So2Model.value()?16:0;
data += m_ch4So1Model.value()?8:0;
data += m_ch3So1Model.value()?4:0;
data += m_ch2So1Model.value()?2:0;
data += m_ch1So1Model.value()?1:0;
papu->write_register( fakeClock(), 0xff25, data );
data = m_ch4So2Model.value() ? 128 : 0;
data += m_ch3So2Model.value() ? 64 : 0;
data += m_ch2So2Model.value() ? 32 : 0;
data += m_ch1So2Model.value() ? 16 : 0;
data += m_ch4So1Model.value() ? 8 : 0;
data += m_ch3So1Model.value() ? 4 : 0;
data += m_ch2So1Model.value() ? 2 : 0;
data += m_ch1So1Model.value() ? 1 : 0;
papu->writeRegister(0xff25, data);
const float * wpm = m_graphModel.samples();
const float* wpm = m_graphModel.samples();
for( char i=0; i<16; i++ )
for (char i = 0; i < 16; ++i)
{
data = (int)floor(wpm[i*2]) << 4;
data += (int)floor(wpm[i*2+1]);
papu->write_register( fakeClock(), 0xff30 + i, data );
data = static_cast<int>(std::floor(wpm[i * 2])) << 4;
data += static_cast<int>(std::floor(wpm[(i * 2) + 1]));
papu->writeRegister(0xff30 + i, data);
}
if( ( freq >= 65 ) && ( freq <=4000 ) )
if ((freq >= 65) && (freq <= 4000))
{
int initflag = (tfp==0)?128:0;
// Hz = 4194304 / ( ( 2048 - ( 11-bit-freq ) ) << 5 )
data = 2048 - ( ( 4194304 / freq )>>5 );
if( tfp==0 )
int initFlag = (tfp == 0) ? 128 : 0;
// Hz = 4194304 / ((2048 - (11-bit-freq)) << 5)
data = 2048 - ((4194304 / freq) >> 5);
if (tfp == 0)
{
papu->write_register( fakeClock(), 0xff13, data & 0xff );
papu->write_register( fakeClock(), 0xff14, (data>>8) | initflag );
papu->writeRegister(0xff13, data & 0xff);
papu->writeRegister(0xff14, (data >> 8) | initFlag);
}
papu->write_register( fakeClock(), 0xff18, data & 0xff );
papu->write_register( fakeClock(), 0xff19, (data>>8) | initflag );
papu->write_register( fakeClock(), 0xff1d, data & 0xff );
papu->write_register( fakeClock(), 0xff1e, (data>>8) | initflag );
papu->writeRegister(0xff18, data & 0xff);
papu->writeRegister(0xff19, (data >> 8) | initFlag);
papu->writeRegister(0xff1d, data & 0xff);
papu->writeRegister(0xff1e, (data >> 8) | initFlag);
}
if( tfp == 0 )
if (tfp == 0)
{
//PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1)
char sopt=0;
char ropt=1;
float fopt = 524288.0 / ( ropt * pow( 2.0, sopt + 1.0 ) );
float f;
for ( char s=0; s<16; s++ )
for ( char r=0; r<8; r++ ) {
f = 524288.0 / ( r * pow( 2.0, s + 1.0 ) );
if( fabs( freq-fopt ) > fabs( freq-f ) ) {
fopt = f;
ropt = r;
sopt = s;
// Initialize noise channel...
// PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1)
// When div_ratio = 0 the ratio should be 0.5. Since s = 0 is the only case where r = 0 gives
// a unique frequency, we can start by guessing s = r = 0 here and then skip r = 0 in the loop.
char clock_freq = 0;
char div_ratio = 0;
float closest_freq = 524288.0 / (0.5 * std::pow(2.0, clock_freq + 1.0));
// This nested for loop iterates over all possible combinations of clock frequency and dividing
// ratio and chooses the combination whose resulting frequency is closest to the note frequency
for (char s = 0; s < 16; ++s)
{
for (char r = 1; r < 8; ++r)
{
float f = 524288.0 / (r * std::pow(2.0, s + 1.0));
if (std::fabs(freq - closest_freq) > std::fabs(freq - f))
{
closest_freq = f;
div_ratio = r;
clock_freq = s;
}
}
}
data = sopt;
data = clock_freq;
data = data << 1;
data += m_ch4ShiftRegWidthModel.value();
data = data << 3;
data += ropt;
papu->write_register( fakeClock(), 0xff22, data );
data += div_ratio;
papu->writeRegister(0xff22, data);
//channel 4 init
papu->write_register( fakeClock(), 0xff23, 128 );
papu->writeRegister(0xff23, 128);
}
int const buf_size = 2048;
int framesleft = frames;
int datalen = 0;
blip_sample_t buf [buf_size*2];
while( framesleft > 0 )
constexpr int bufSize = 2048;
int framesLeft = frames;
int dataLen = 0;
auto buf = std::array<blip_sample_t, bufSize * 2>{};
while (framesLeft > 0)
{
int avail = papu->samples_avail();
if( avail <= 0 )
int avail = papu->samplesAvail();
if (avail <= 0)
{
m_time = 0;
papu->end_frame(FRAME_LENGTH);
avail = papu->samples_avail();
papu->endFrame(FRAME_LENGTH);
avail = papu->samplesAvail();
}
datalen = framesleft>avail?avail:framesleft;
datalen = datalen>buf_size?buf_size:datalen;
dataLen = framesLeft > avail ? avail : framesLeft;
dataLen = dataLen > bufSize ? bufSize : dataLen;
long count = papu->read_samples( buf, datalen*2)/2;
long count = papu->readSamples(buf.data(), dataLen * 2) / 2;
for( fpp_t frame = 0; frame < count; ++frame )
for (fpp_t frame = 0; frame < count; ++frame)
{
for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch )
for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch)
{
sample_t s = float(buf[frame*2+ch])/32768.0;
_working_buffer[frames-framesleft+frame+offset][ch] = s;
sample_t s = static_cast<float>(buf[(frame * 2) + ch]) / 32768.0f;
workingBuffer[frames - framesLeft + frame + offset][ch] = s;
}
}
framesleft -= count;
framesLeft -= count;
}
instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
instrumentTrack()->processAudioBuffer(workingBuffer, frames + offset, nph);
}
void FreeBoyInstrument::deleteNotePluginData( NotePlayHandle * _n )
void FreeBoyInstrument::deleteNotePluginData(NotePlayHandle* nph)
{
delete static_cast<Gb_Apu_Buffer *>( _n->m_pluginData );
delete static_cast<GbApuWrapper*>(nph->m_pluginData);
}
@@ -736,4 +742,4 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
}
} // namespace lmms
} // namespace lmms

View File

@@ -1,8 +1,8 @@
/*
* FreeBoyInstrument.h - GameBoy papu based instrument
* FreeBoy.h - GameBoy papu based instrument
*
* Copyright (c) 2008 <Attila Herman <attila589/at/gmail.com>
* Csaba Hruska <csaba.hruska/at/gmail.com>
* Copyright (c) 2008 Attila Herman <attila589/at/gmail.com>
* Csaba Hruska <csaba.hruska/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
@@ -23,8 +23,8 @@
*
*/
#ifndef FREEBOY_H
#define FREEBOY_H
#ifndef LMMS_FREEBOY_H
#define LMMS_FREEBOY_H
#include "AutomatableModel.h"
#include "Blip_Buffer.h"
@@ -54,10 +54,8 @@ public:
FreeBoyInstrument( InstrumentTrack * _instrument_track );
~FreeBoyInstrument() override = default;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;
void playNote(NotePlayHandle* nph, sampleFrame* workingBuffer) override;
void deleteNotePluginData(NotePlayHandle* nph) override;
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
@@ -112,12 +110,8 @@ private:
graphModel m_graphModel;
// Fake CPU timing
blip_time_t m_time;
blip_time_t fakeClock() { return m_time += 4; }
friend class gui::FreeBoyInstrumentView;
} ;
};
namespace gui
@@ -172,11 +166,11 @@ private:
/*protected slots:
void updateKnobHint();
void updateKnobToolTip();*/
} ;
};
} // namespace gui
} // namespace lmms
#endif
#endif // LMMS_FREEBOY_H

View File

@@ -1,7 +1,7 @@
/*
* Gb_Apu_Buffer.cpp - Gb_Apu subclass which allows direct buffer access
* GbApuWrapper.cpp - Gb_Apu subclass which allows direct buffer access
* Copyright (c) 2017 Tres Finocchiaro <tres.finocchiaro/at/gmail.com>
*
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
@@ -20,37 +20,45 @@
* Boston, MA 02110-1301 USA.
*
*/
#include "Gb_Apu_Buffer.h"
#include "GbApuWrapper.h"
namespace lmms
{
void Gb_Apu_Buffer::end_frame(blip_time_t end_time) {
Gb_Apu::end_frame(end_time);
m_buf.end_frame(end_time);
// Sets specified sample rate and clock rate in Stereo_Buffer
blargg_err_t GbApuWrapper::setSampleRate(long sampleRate, long clockRate)
{
Gb_Apu::output(m_buf.center(), m_buf.left(), m_buf.right());
m_buf.clock_rate(clockRate);
return m_buf.set_sample_rate(sampleRate);
}
// Sets specified sample rate and clock rate in Multi_Buffer
blargg_err_t Gb_Apu_Buffer::set_sample_rate(long sample_rate, long clock_rate) {
Gb_Apu_Buffer::output(m_buf.center(), m_buf.left(), m_buf.right());
m_buf.clock_rate(clock_rate);
return m_buf.set_sample_rate(sample_rate);
}
// Wrap Multi_Buffer::samples_avail()
long Gb_Apu_Buffer::samples_avail() const {
// Wrap Stereo_Buffer::samples_avail()
long GbApuWrapper::samplesAvail() const
{
return m_buf.samples_avail();
}
// Wrap Multi_Buffer::read_samples(...)
long Gb_Apu_Buffer::read_samples(sample_t* out, long count) {
// Wrap Stereo_Buffer::read_samples(...)
long GbApuWrapper::readSamples(blip_sample_t* out, long count)
{
return m_buf.read_samples(out, count);
}
void Gb_Apu_Buffer::bass_freq(int freq) {
// Wrap Stereo_Buffer::bass_freq(...)
void GbApuWrapper::bassFreq(int freq)
{
m_buf.bass_freq(freq);
}
void GbApuWrapper::endFrame(blip_time_t endTime)
{
m_time = 0;
Gb_Apu::end_frame(endTime);
m_buf.end_frame(endTime);
}
} // namespace lmms

View File

@@ -1,7 +1,7 @@
/*
* Gb_Apu_Buffer.cpp - Gb_Apu subclass which allows direct buffer access
* GbApuWrapper.h - Gb_Apu subclass which allows direct buffer access
* Copyright (c) 2017 Tres Finocchiaro <tres.finocchiaro/at/gmail.com>
*
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
@@ -20,8 +20,9 @@
* Boston, MA 02110-1301 USA.
*
*/
#ifndef GB_APU_BUFFER_H
#define GB_APU_BUFFER_H
#ifndef LMMS_GB_APU_WRAPPER_H
#define LMMS_GB_APU_WRAPPER_H
#include "Gb_Apu.h"
#include "Multi_Buffer.h"
@@ -31,25 +32,30 @@ namespace lmms
{
class Gb_Apu_Buffer : public Gb_Apu {
class GbApuWrapper : private Gb_Apu
{
MM_OPERATORS
public:
Gb_Apu_Buffer() = default;
~Gb_Apu_Buffer() = default;
GbApuWrapper() = default;
~GbApuWrapper() = default;
void end_frame(blip_time_t);
blargg_err_t setSampleRate(long sampleRate, long clockRate);
void writeRegister(unsigned addr, int data) { Gb_Apu::write_register(fakeClock(), addr, data); }
long samplesAvail() const;
long readSamples(blip_sample_t* out, long count);
void trebleEq(const blip_eq_t& eq) { Gb_Apu::treble_eq(eq); }
void bassFreq(int freq);
void endFrame(blip_time_t endTime);
blargg_err_t set_sample_rate(long sample_rate, long clock_rate);
long samples_avail() const;
using sample_t = blip_sample_t;
long read_samples(sample_t* out, long count);
void bass_freq(int freq);
private:
Stereo_Buffer m_buf;
// Fake CPU timing
blip_time_t fakeClock() { return m_time += 4; }
blip_time_t m_time = 0;
};
} // namespace lmms
#endif
#endif // LMMS_GB_APU_WRAPPER_H

View File

@@ -98,7 +98,7 @@ LadspaBrowserView::LadspaBrowserView( ToolPlugin * _tool ) :
{
auto hlayout = new QHBoxLayout(this);
hlayout->setSpacing( 0 );
hlayout->setMargin( 0 );
hlayout->setContentsMargins(0, 0, 0, 0);
m_tabBar = new TabBar( this, QBoxLayout::TopToBottom );
m_tabBar->setExclusive( true );
@@ -166,7 +166,7 @@ QWidget * LadspaBrowserView::createTab( QWidget * _parent, const QString & _txt,
tab->setFixedSize( 500, 400 );
auto layout = new QVBoxLayout(tab);
layout->setSpacing( 0 );
layout->setMargin( 0 );
layout->setContentsMargins(0, 0, 0, 0);
const QString type = "<b>" + tr( "Type:" ) + "</b> ";
auto title = new QLabel(type + _txt, tab);

View File

@@ -94,7 +94,7 @@ LadspaDescription::LadspaDescription( QWidget * _parent,
auto descriptionBox = new QGroupBox(tr("Description"), this);
auto descriptionLayout = new QVBoxLayout(descriptionBox);
descriptionLayout->setSpacing( 0 );
descriptionLayout->setMargin( 0 );
descriptionLayout->setContentsMargins(0, 0, 0, 0);
m_scrollArea = new QScrollArea( descriptionBox );
descriptionLayout->addWidget( m_scrollArea );
@@ -130,7 +130,7 @@ void LadspaDescription::update( const ladspa_key_t & _key )
auto maker = new QWidget(description);
auto makerLayout = new QHBoxLayout(maker);
makerLayout->setMargin( 0 );
makerLayout->setContentsMargins(0, 0, 0, 0);
makerLayout->setSpacing( 0 );
layout->addWidget( maker );
@@ -145,7 +145,7 @@ void LadspaDescription::update( const ladspa_key_t & _key )
auto copyright = new QWidget(description);
auto copyrightLayout = new QHBoxLayout(copyright);
copyrightLayout->setMargin( 0 );
copyrightLayout->setContentsMargins(0, 0, 0, 0);
copyrightLayout->setSpacing( 0 );
layout->addWidget( copyright );

View File

@@ -47,7 +47,7 @@ LadspaPortDialog::LadspaPortDialog( const ladspa_key_t & _key )
auto vlayout = new QVBoxLayout(this);
vlayout->setSpacing( 0 );
vlayout->setMargin( 0 );
vlayout->setContentsMargins(0, 0, 0, 0);
int pc = manager->getPortCount( _key );

View File

@@ -130,7 +130,7 @@ void LadspaEffect::changeSampleRate()
bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
const fpp_t _frames )
{
m_pluginMutex.lock();
@@ -154,7 +154,7 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
}
// Copy the LMMS audio buffer to the LADSPA input buffer and initialize
// the control ports.
// the control ports.
ch_cnt_t channel = 0;
for( ch_cnt_t proc = 0; proc < processorCount(); ++proc )
{
@@ -164,10 +164,10 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
switch( pp->rate )
{
case CHANNEL_IN:
for( fpp_t frame = 0;
for( fpp_t frame = 0;
frame < frames; ++frame )
{
pp->buffer[frame] =
pp->buffer[frame] =
_buf[frame][channel];
}
++channel;
@@ -181,15 +181,15 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
}
else
{
pp->value = static_cast<LADSPA_Data>(
pp->value = static_cast<LADSPA_Data>(
pp->control->value() / pp->scale );
// This only supports control rate ports, so the audio rates are
// treated as though they were control rate by setting the
// port buffer to all the same value.
for( fpp_t frame = 0;
for( fpp_t frame = 0;
frame < frames; ++frame )
{
pp->buffer[frame] =
pp->buffer[frame] =
pp->value;
}
}
@@ -200,9 +200,9 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
{
break;
}
pp->value = static_cast<LADSPA_Data>(
pp->value = static_cast<LADSPA_Data>(
pp->control->value() / pp->scale );
pp->buffer[0] =
pp->buffer[0] =
pp->value;
break;
case CHANNEL_OUT:
@@ -239,7 +239,7 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
case CONTROL_RATE_INPUT:
break;
case CHANNEL_OUT:
for( fpp_t frame = 0;
for( fpp_t frame = 0;
frame < frames; ++frame )
{
_buf[frame][channel] = d * _buf[frame][channel] + w * pp->buffer[frame];
@@ -303,7 +303,7 @@ void LadspaEffect::pluginInstantiation()
int inputch = 0;
int outputch = 0;
LADSPA_Data * inbuf [2];
std::array<LADSPA_Data*, 2> inbuf;
inbuf[0] = nullptr;
inbuf[1] = nullptr;
for( ch_cnt_t proc = 0; proc < processorCount(); proc++ )
@@ -463,9 +463,9 @@ void LadspaEffect::pluginInstantiation()
ports.append( p );
// For convenience, keep a separate list of the ports that are used
// For convenience, keep a separate list of the ports that are used
// to control the processors.
if( p->rate == AUDIO_RATE_INPUT ||
if( p->rate == AUDIO_RATE_INPUT ||
p->rate == CONTROL_RATE_INPUT )
{
p->control_id = m_portControls.count();
@@ -479,7 +479,7 @@ void LadspaEffect::pluginInstantiation()
m_descriptor = manager->getDescriptor( m_key );
if( m_descriptor == nullptr )
{
QMessageBox::warning( 0, "Effect",
QMessageBox::warning( 0, "Effect",
"Can't get LADSPA descriptor function: " + m_key.second,
QMessageBox::Ok, QMessageBox::NoButton );
setOkay( false );
@@ -518,8 +518,8 @@ void LadspaEffect::pluginInstantiation()
port,
pp->buffer ) )
{
QMessageBox::warning( 0, "Effect",
"Failed to connect port: " + m_key.second,
QMessageBox::warning( 0, "Effect",
"Failed to connect port: " + m_key.second,
QMessageBox::Ok, QMessageBox::NoButton );
setDontRun( true );
return;

View File

@@ -71,7 +71,7 @@ void LadspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent,
auto maker = new QWidget(_parent);
auto l = new QHBoxLayout(maker);
l->setMargin( 0 );
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing( 0 );
auto maker_label = new QLabel(maker);
@@ -85,7 +85,7 @@ void LadspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent,
auto copyright = new QWidget(_parent);
l = new QHBoxLayout( copyright );
l->setMargin( 0 );
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing( 0 );
copyright->setMinimumWidth( _parent->minimumWidth() );

View File

@@ -1,7 +1,7 @@
/*
* Lv2Effect.cpp - implementation of LV2 effect
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*

View File

@@ -1,7 +1,7 @@
/*
* Lv2Effect.h - implementation of LV2 effect
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*

View File

@@ -1,7 +1,7 @@
/*
* Lv2FxControlDialog.cpp - Lv2FxControlDialog implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
@@ -38,7 +38,7 @@ Lv2FxControlDialog::Lv2FxControlDialog(Lv2FxControls *controls) :
{
if (m_reloadPluginButton) {
connect(m_reloadPluginButton, &QPushButton::clicked,
this, [this](){ lv2Controls()->reloadPlugin(); });
this, [this](){ lv2Controls()->reload(); });
}
if (m_toggleUIButton) {
connect(m_toggleUIButton, &QPushButton::toggled,
@@ -67,7 +67,9 @@ Lv2FxControls *Lv2FxControlDialog::lv2Controls()
void Lv2FxControlDialog::modelChanged()
{
Lv2ViewBase::modelChanged(lv2Controls());
connect(lv2Controls(), &Lv2FxControls::modelChanged,
this, [this](){ this->modelChanged();} );
}
} // namespace lmms::gui
} // namespace lmms::gui

View File

@@ -1,7 +1,7 @@
/*
* Lv2FxControlDialog.h - Lv2FxControlDialog implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
@@ -45,7 +45,7 @@ public:
private:
Lv2FxControls *lv2Controls();
void modelChanged() override;
void modelChanged() final;
};

View File

@@ -1,7 +1,7 @@
/*
* Lv2FxControls.cpp - Lv2FxControls implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
@@ -41,13 +41,33 @@ Lv2FxControls::Lv2FxControls(class Lv2Effect *effect, const QString& uri) :
if (isValid())
{
connect(Engine::audioEngine(), &AudioEngine::sampleRateChanged,
this, [this](){Lv2ControlBase::reloadPlugin();});
this, [this](){onSampleRateChanged();});
}
}
void Lv2FxControls::reload()
{
Lv2ControlBase::reload();
emit modelChanged();
}
void Lv2FxControls::onSampleRateChanged()
{
// TODO: once lv2 options are implemented,
// plugins that support it might allow changing their samplerate
// through it instead of reloading
reload();
}
void Lv2FxControls::saveSettings(QDomDocument &doc, QDomElement &that)
{
Lv2ControlBase::saveSettings(doc, that);
@@ -86,20 +106,4 @@ void Lv2FxControls::changeControl() // TODO: what is that?
}
DataFile::Types Lv2FxControls::settingsType()
{
return DataFile::EffectSettings;
}
void Lv2FxControls::setNameFromFile(const QString &name)
{
effect()->setDisplayName(name);
}
} // namespace lmms

View File

@@ -1,7 +1,7 @@
/*
* Lv2FxControls.h - Lv2FxControls implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
@@ -43,8 +43,11 @@ class Lv2FxControlDialog;
class Lv2FxControls : public EffectControls, public Lv2ControlBase
{
Q_OBJECT
signals:
void modelChanged();
public:
Lv2FxControls(Lv2Effect *effect, const QString &uri);
void reload();
void saveSettings(QDomDocument &_doc, QDomElement &_parent) override;
void loadSettings(const QDomElement &that) override;
@@ -60,8 +63,7 @@ private slots:
void changeControl();
private:
DataFile::Types settingsType() override;
void setNameFromFile(const QString &name) override;
void onSampleRateChanged();
friend class gui::Lv2FxControlDialog;
friend class Lv2Effect;

View File

@@ -1,7 +1,7 @@
/*
* Lv2Instrument.cpp - implementation of LV2 instrument
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
@@ -78,10 +78,12 @@ Lv2Instrument::Lv2Instrument(InstrumentTrack *instrumentTrackArg,
{
if (Lv2ControlBase::isValid())
{
clearRunningNotes();
connect(instrumentTrack()->pitchRangeModel(), SIGNAL(dataChanged()),
this, SLOT(updatePitchRange()), Qt::DirectConnection);
connect(Engine::audioEngine(), &AudioEngine::sampleRateChanged,
this, [this](){Lv2ControlBase::reloadPlugin();});
this, [this](){onSampleRateChanged();});
// now we need a play-handle which cares for calling play()
auto iph = new InstrumentPlayHandle(this, instrumentTrackArg);
@@ -101,6 +103,37 @@ Lv2Instrument::~Lv2Instrument()
void Lv2Instrument::reload()
{
Lv2ControlBase::reload();
clearRunningNotes();
emit modelChanged();
}
void Lv2Instrument::clearRunningNotes()
{
#ifdef LV2_INSTRUMENT_USE_MIDI
for (int i = 0; i < NumKeys; ++i) { m_runningNotes[i] = 0; }
#endif
}
void Lv2Instrument::onSampleRateChanged()
{
// TODO: once lv2 options are implemented,
// plugins that support it might allow changing their samplerate
// through it instead of reloading
reload();
}
bool Lv2Instrument::isValid() const { return Lv2ControlBase::isValid(); }
@@ -196,25 +229,9 @@ QString Lv2Instrument::nodeName() const
DataFile::Types Lv2Instrument::settingsType()
{
return DataFile::InstrumentTrackSettings;
}
void Lv2Instrument::setNameFromFile(const QString &name)
{
instrumentTrack()->setName(name);
}
namespace gui
{
/*
Lv2InsView
*/
@@ -227,7 +244,7 @@ Lv2InsView::Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent) :
setAutoFillBackground(true);
if (m_reloadPluginButton) {
connect(m_reloadPluginButton, &QPushButton::clicked,
this, [this](){ this->castModel<Lv2Instrument>()->reloadPlugin();} );
this, [this](){ this->castModel<Lv2Instrument>()->reload();} );
}
if (m_toggleUIButton) {
connect(m_toggleUIButton, &QPushButton::toggled,
@@ -283,6 +300,8 @@ void Lv2InsView::dropEvent(QDropEvent *_de)
void Lv2InsView::modelChanged()
{
Lv2ViewBase::modelChanged(castModel<Lv2Instrument>());
connect(castModel<Lv2Instrument>(), &Lv2Instrument::modelChanged,
this, [this](){ this->modelChanged();} );
}

View File

@@ -1,7 +1,7 @@
/*
* Lv2Instrument.h - implementation of LV2 instrument
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
@@ -50,6 +50,8 @@ class Lv2InsView;
class Lv2Instrument : public Instrument, public Lv2ControlBase
{
Q_OBJECT
signals:
void modelChanged();
public:
/*
initialization
@@ -57,6 +59,8 @@ public:
Lv2Instrument(InstrumentTrack *instrumentTrackArg,
Descriptor::SubPluginFeatures::Key* key);
~Lv2Instrument() override;
void reload();
void onSampleRateChanged();
//! Must be checked after ctor or reload
bool isValid() const;
@@ -97,12 +101,11 @@ private slots:
private:
QString nodeName() const override;
DataFile::Types settingsType() override;
void setNameFromFile(const QString &name) override;
#ifdef LV2_INSTRUMENT_USE_MIDI
std::array<int, NumKeys> m_runningNotes = {};
#endif
void clearRunningNotes();
friend class gui::Lv2InsView;
};

View File

@@ -5,7 +5,7 @@
* Copyright (c) 2017 Hyunjin Song <tteu.ingog/at/gmail.com>
*
* This file is part of LMMS - https://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
@@ -81,7 +81,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks,
int nTracks = 0;
uint8_t buffer[BUFFER_SIZE];
auto buffer = std::array<uint8_t, BUFFER_SIZE>{};
uint32_t size;
for (const Track* track : tracks) if (track->type() == Track::InstrumentTrack) nTracks++;
@@ -89,8 +89,8 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks,
// midi header
MidiFile::MIDIHeader header(nTracks);
size = header.writeToBuffer(buffer);
midiout.writeRawData((char *)buffer, size);
size = header.writeToBuffer(buffer.data());
midiout.writeRawData((char *)buffer.data(), size);
std::vector<std::vector<std::pair<int,int>>> plists;
@@ -139,8 +139,8 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks,
}
processPatternNotes(midiClip, INT_MAX);
writeMidiClipToTrack(mtrack, midiClip);
size = mtrack.writeToBuffer(buffer);
midiout.writeRawData((char *)buffer, size);
size = mtrack.writeToBuffer(buffer.data());
midiout.writeRawData((char *)buffer.data(), size);
}
if (track->type() == Track::PatternTrack)
@@ -254,8 +254,8 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks,
++itr;
}
}
size = mtrack.writeToBuffer(buffer);
midiout.writeRawData((char *)buffer, size);
size = mtrack.writeToBuffer(buffer.data());
midiout.writeRawData((char *)buffer.data(), size);
}
return true;

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - https://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
@@ -152,17 +152,17 @@ public:
ap( nullptr ),
lastPos( 0 )
{ }
AutomationTrack * at;
AutomationClip * ap;
TimePos lastPos;
smfMidiCC & create( TrackContainer* tc, QString tn )
{
if( !at )
{
// Keep LMMS responsive, for now the import runs
// in the main thread. This should probably be
// Keep LMMS responsive, for now the import runs
// in the main thread. This should probably be
// removed if that ever changes.
qApp->processEvents();
at = dynamic_cast<AutomationTrack *>( Track::create( Track::AutomationTrack, tc ) );
@@ -195,7 +195,7 @@ public:
lastPos = time;
time = time - ap->startPosition();
ap->putValue( time, value, false );
ap->changeLength( TimePos( time.getBar() + 1, 0 ) );
ap->changeLength( TimePos( time.getBar() + 1, 0 ) );
return *this;
}
@@ -214,14 +214,14 @@ public:
isSF2( false ),
hasNotes( false )
{ }
InstrumentTrack * it;
MidiClip* p;
Instrument * it_inst;
bool isSF2;
bool isSF2;
bool hasNotes;
QString trackName;
smfMidiChannel * create( TrackContainer* tc, QString tn )
{
if( !it ) {
@@ -231,7 +231,7 @@ public:
#ifdef LMMS_HAVE_FLUIDSYNTH
it_inst = it->loadInstrument( "sf2player" );
if( it_inst )
{
isSF2 = true;
@@ -242,7 +242,7 @@ public:
else
{
it_inst = it->loadInstrument( "patman" );
}
}
#else
it_inst = it->loadInstrument( "patman" );
#endif
@@ -315,9 +315,9 @@ bool MidiImport::readSMF( TrackContainer* tc )
pd.setMaximum( seq->tracks() + preTrackSteps );
pd.setValue( 1 );
// 128 CC + Pitch Bend
smfMidiCC ccs[MIDI_CC_COUNT];
auto ccs = std::array<smfMidiCC, MIDI_CC_COUNT>{};
// channel to CC object for program changes
std::unordered_map<long, smfMidiCC> pcs;
@@ -338,9 +338,9 @@ bool MidiImport::readSMF( TrackContainer* tc )
auto timeSigDenominatorPat = new AutomationClip(dt);
timeSigDenominatorPat->setDisplayName(tr("Denominator"));
timeSigDenominatorPat->addObject(&timeSigMM.denominatorModel());
// TODO: adjust these to Time.Sig changes
double beatsPerBar = 4;
double beatsPerBar = 4;
double ticksPerBeat = DefaultTicksPerBar / beatsPerBar;
// Time-sig changes
@@ -358,7 +358,11 @@ bool MidiImport::readSMF( TrackContainer* tc )
pd.setValue( 2 );
// Tempo stuff
AutomationClip * tap = tc->tempoAutomationClip();
auto tt = dynamic_cast<AutomationTrack*>(Track::create(Track::AutomationTrack, Engine::getSong()));
tt->setName(tr("Tempo"));
auto tap = new AutomationClip(tt);
tap->setDisplayName(tr("Tempo"));
tap->addObject(&Engine::getSong()->tempoModel());
if( tap )
{
tap->clear();
@@ -389,7 +393,7 @@ bool MidiImport::readSMF( TrackContainer* tc )
if( evt->is_update() )
{
printf("Unhandled SONG update: %d %f %s\n",
printf("Unhandled SONG update: %d %f %s\n",
evt->get_type_code(), evt->time, evt->get_attribute() );
}
}
@@ -451,9 +455,9 @@ bool MidiImport::readSMF( TrackContainer* tc )
noteEvt->get_identifier(),
noteEvt->get_loud() * (200.f / 127.f)); // Map from MIDI velocity to LMMS volume
ch->addNote( n );
}
else if( evt->is_update() )
{
smfMidiChannel * ch = chs[evt->chan].create( tc, trackName );
@@ -499,7 +503,7 @@ bool MidiImport::readSMF( TrackContainer* tc )
double cc = evt->get_real_value();
AutomatableModel * objModel = nullptr;
switch( ccid )
switch( ccid )
{
case 0:
if( ch->isSF2 && ch->it_inst )
@@ -540,7 +544,7 @@ bool MidiImport::readSMF( TrackContainer* tc )
if( ccs[ccid].at == nullptr ) {
ccs[ccid].create( tc, trackName + " > " + (
objModel != nullptr ?
objModel->displayName() :
objModel->displayName() :
QString("CC %1").arg(ccid) ) );
}
ccs[ccid].putValue( time, objModel, cc );
@@ -549,7 +553,7 @@ bool MidiImport::readSMF( TrackContainer* tc )
}
}
else {
printf("Unhandled update: %d %d %f %s\n", (int) evt->chan,
printf("Unhandled update: %d %d %f %s\n", (int) evt->chan,
evt->get_type_code(), evt->time, evt->get_attribute() );
}
}
@@ -557,8 +561,8 @@ bool MidiImport::readSMF( TrackContainer* tc )
}
delete seq;
for( auto& c: chs )
{
if (c.second.hasNotes)

View File

@@ -49,6 +49,7 @@
#ifndef ALLEGRO_H
#define ALLEGRO_H
#include <assert.h>
#include <cstdint>
#include <cstring>
#include <istream>
#include <ostream>

View File

@@ -653,8 +653,8 @@ inline void MonstroSynth::updateModulators( float * env1, float * env2, float *
// frames played before
const f_cnt_t tfp = m_nph->totalFramesPlayed();
float * lfo [2];
float * env [2];
auto lfo = std::array<float*, 2>{};
auto env = std::array<float*, 2>{};
lfo[0] = lfo1;
lfo[1] = lfo2;
env[0] = env1;
@@ -1694,8 +1694,8 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent )
m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, ComboBox::DEFAULT_HEIGHT );
m_lfo2WaveBox->setFont( pointSize<8>( m_lfo2WaveBox->font() ) );
maketsknob(m_lfo2AttKnob, LFOCOL4, LFOROW, tr("Attack"), " ms", "lfoKnob")
maketsknob(m_lfo2RateKnob, LFOCOL5, LFOROW, tr("Rate"), " ms", "lfoKnob")
maketsknob(m_lfo2AttKnob, LFOCOL4, LFOROW, tr("Attack"), " ms", "lfoKnob")
maketsknob(m_lfo2RateKnob, LFOCOL5, LFOROW, tr("Rate"), " ms", "lfoKnob")
makeknob(m_lfo2PhsKnob, LFOCOL6, LFOROW, tr("Phase"), tr(" deg"), "lfoKnob")
maketsknob(m_env1PreKnob, KNOBCOL1, E1ROW, tr("Pre-delay"), " ms", "envKnob")

View File

@@ -92,7 +92,7 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
QMutex OpulenzInstrument::emulatorMutex;
// Weird ordering of voice parameters
const unsigned int adlib_opadd[OPL2_VOICES] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12};
const auto adlib_opadd = std::array<unsigned int, OPL2_VOICES>{0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12};
OpulenzInstrument::OpulenzInstrument( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, &opulenz_plugin_descriptor ),
@@ -371,7 +371,7 @@ bool OpulenzInstrument::handleMidiEvent( const MidiEvent& event, const TimePos&
}
break;
default:
#ifdef LMMS_DEBUG
#ifdef LMMS_DEBUG
printf("Midi CC %02x %02x\n", event.controllerNumber(), event.controllerValue() );
#endif
break;
@@ -534,7 +534,7 @@ void OpulenzInstrument::loadGMPatch() {
// Update patch from the models to the chip emulation
void OpulenzInstrument::updatePatch() {
unsigned char inst[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
auto inst = std::array<unsigned char, 14>{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
inst[0] = ( op1_trem_mdl.value() ? 128 : 0 ) +
( op1_vib_mdl.value() ? 64 : 0 ) +
( op1_perc_mdl.value() ? 0 : 32 ) + // NB. This envelope mode is "perc", not "sus"
@@ -583,7 +583,7 @@ void OpulenzInstrument::updatePatch() {
#endif
loadPatch(inst);
loadPatch(inst.data());
}
// Load an SBI file into the knob models
@@ -763,7 +763,7 @@ OpulenzInstrumentView::OpulenzInstrumentView( Instrument * _instrument,
setPalette( pal );
}
OpulenzInstrumentView::~OpulenzInstrumentView() {
// Knobs are QWidgets and our children, so they're
// Knobs are QWidgets and our children, so they're
// destroyed automagically
}
@@ -782,20 +782,20 @@ void OpulenzInstrumentView::updateKnobHints()
{
// Envelope times in ms: t[0] = 0, t[n] = ( 1<<n ) * X, X = 0.11597 for A, 0.6311 for D/R
// Here some rounding has been applied.
const float attack_times[16] = {
0.0, 0.2, 0.4, 0.9, 1.8, 3.7, 7.4,
const auto attack_times = std::array<float, 16>{
0.0, 0.2, 0.4, 0.9, 1.8, 3.7, 7.4,
15.0, 30.0, 60.0, 120.0, 240.0, 480.0,
950.0, 1900.0, 3800.0
950.0, 1900.0, 3800.0
};
const float dr_times[16] = {
0.0, 1.2, 2.5, 5.0, 10.0, 20.0, 40.0,
80.0, 160.0, 320.0, 640.0, 1300.0, 2600.0,
5200.0, 10000.0, 20000.0
const auto dr_times = std::array<float, 16>{
0.0, 1.2, 2.5, 5.0, 10.0, 20.0, 40.0,
80.0, 160.0, 320.0, 640.0, 1300.0, 2600.0,
5200.0, 10000.0, 20000.0
};
const int fmultipliers[16] = {
-12, 0, 12, 19, 24, 28, 31, 34, 36, 38, 40, 40, 43, 43, 47, 47
const auto fmultipliers = std::array<int, 16>{
-12, 0, 12, 19, 24, 28, 31, 34, 36, 38, 40, 40, 43, 43, 47, 47
};
auto m = castModel<OpulenzInstrument>();
@@ -863,11 +863,11 @@ void OpulenzInstrumentView::modelChanged()
connect( &m->op1_d_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op2_d_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op1_r_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op2_r_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op1_r_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op2_r_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op1_mul_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op2_mul_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op1_mul_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
connect( &m->op2_mul_mdl, SIGNAL( dataChanged() ), this, SLOT( updateKnobHints() ) );
updateKnobHints();

View File

@@ -2,7 +2,7 @@
* Organic.cpp - additive synthesizer for organ-like sounds
*
* Copyright (c) 2006-2008 Andreas Brandmaier <andy/at/brandmaier/dot/de>
*
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
@@ -71,7 +71,7 @@ float * OrganicInstrument::s_harmonics = nullptr;
*
* class OrganicInstrument
*
* lmms - plugin
* lmms - plugin
*
***********************************************************************/
@@ -90,7 +90,7 @@ OrganicInstrument::OrganicInstrument( InstrumentTrack * _instrument_track ) :
m_osc[i] = new OscillatorObject( this, i );
m_osc[i]->m_numOscillators = m_numOscillators;
// Connect events
// Connect events
connect( &m_osc[i]->m_oscModel, SIGNAL( dataChanged() ),
m_osc[i], SLOT ( oscButtonChanged() ) );
connect( &m_osc[i]->m_harmModel, SIGNAL( dataChanged() ),
@@ -114,7 +114,7 @@ OrganicInstrument::OrganicInstrument( InstrumentTrack * _instrument_track ) :
m_osc[5]->m_harmonic = log2f( 4.0f ); // .
m_osc[6]->m_harmonic = log2f( 5.0f ); // .
m_osc[7]->m_harmonic = log2f( 6.0f ); // .*/
if( s_harmonics == nullptr )
{
s_harmonics = new float[ NUM_HARMONICS ];
@@ -142,10 +142,10 @@ OrganicInstrument::OrganicInstrument( InstrumentTrack * _instrument_track ) :
m_osc[i]->updateVolume();
m_osc[i]->updateDetuning();
}
connect( Engine::audioEngine(), SIGNAL( sampleRateChanged() ),
this, SLOT( updateAllDetuning() ) );
this, SLOT( updateAllDetuning() ) );
}
@@ -193,7 +193,7 @@ void OrganicInstrument::loadSettings( const QDomElement & _this )
m_osc[i]->m_volModel.loadSettings( _this, "vol" + is );
if( _this.hasAttribute( "detune" + is ) )
{
m_osc[i]->m_detuneModel.setValue( _this.attribute( "detune" ).toInt() * 12 );
m_osc[i]->m_detuneModel.setValue( _this.attribute( "detune" ).toInt() * 12 );
}
else
{
@@ -201,7 +201,7 @@ void OrganicInstrument::loadSettings( const QDomElement & _this )
}
m_osc[i]->m_panModel.loadSettings( _this, "pan" + is );
m_osc[i]->m_oscModel.loadSettings( _this, "wavetype" + is );
if( _this.hasAttribute( "newharmonic" + is ) )
{
m_osc[i]->m_harmModel.loadSettings( _this, "newharmonic" + is );
@@ -211,7 +211,7 @@ void OrganicInstrument::loadSettings( const QDomElement & _this )
m_osc[i]->m_harmModel.setValue( static_cast<float>( i ) );
}
}
m_volModel.loadSettings( _this, "vol" );
m_fx1Model.loadSettings( _this, "foldback" );
}
@@ -230,23 +230,23 @@ void OrganicInstrument::playNote( NotePlayHandle * _n,
{
const fpp_t frames = _n->framesLeftForCurrentPeriod();
const f_cnt_t offset = _n->noteOffset();
if( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr )
{
Oscillator * oscs_l[NUM_OSCILLATORS];
Oscillator * oscs_r[NUM_OSCILLATORS];
auto oscs_l = std::array<Oscillator*, NUM_OSCILLATORS>{};
auto oscs_r = std::array<Oscillator*, NUM_OSCILLATORS>{};
_n->m_pluginData = new oscPtr;
for( int i = m_numOscillators - 1; i >= 0; --i )
{
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetLeft[i]
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetLeft[i]
= rand() / ( RAND_MAX + 1.0f );
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetRight[i]
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetRight[i]
= rand() / ( RAND_MAX + 1.0f );
// initialise ocillators
if( i == m_numOscillators - 1 )
{
// create left oscillator
@@ -287,8 +287,8 @@ void OrganicInstrument::playNote( NotePlayHandle * _n,
m_osc[i]->m_volumeRight,
oscs_r[i + 1] );
}
}
static_cast<oscPtr *>( _n->m_pluginData )->oscLeft = oscs_l[0];
@@ -303,10 +303,10 @@ void OrganicInstrument::playNote( NotePlayHandle * _n,
// -- fx section --
// fxKnob is [0;1]
float t = m_fx1Model.value();
for (int i=0 ; i < frames + offset ; i++)
{
_working_buffer[i][0] = waveshape( _working_buffer[i][0], t ) *
@@ -314,7 +314,7 @@ void OrganicInstrument::playNote( NotePlayHandle * _n,
_working_buffer[i][1] = waveshape( _working_buffer[i][1], t ) *
m_volModel.value() / 100.0f;
}
// -- --
instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
@@ -329,7 +329,7 @@ void OrganicInstrument::deleteNotePluginData( NotePlayHandle * _n )
_n->m_pluginData )->oscLeft );
delete static_cast<Oscillator *>( static_cast<oscPtr *>(
_n->m_pluginData )->oscRight );
delete static_cast<oscPtr *>( _n->m_pluginData );
}
@@ -388,7 +388,7 @@ void OrganicInstrument::updateAllDetuning()
int OrganicInstrument::intRand( int min, int max )
{
// int randn = min+int((max-min)*rand()/(RAND_MAX + 1.0));
// int randn = min+int((max-min)*rand()/(RAND_MAX + 1.0));
// cout << randn << endl;
int randn = ( rand() % (max - min) ) + min;
return( randn );
@@ -452,7 +452,7 @@ OrganicInstrumentView::OrganicInstrumentView( Instrument * _instrument,
"randomise_pressed" ) );
m_randBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"randomise" ) );
connect( m_randBtn, SIGNAL ( clicked() ),
oi, SLOT( randomiseSettings() ) );
@@ -479,10 +479,10 @@ void OrganicInstrumentView::modelChanged()
const float y=91.0f;
const float rowHeight = 26.0f;
const float x=53.0f;
const float colWidth = 24.0f;
const float colWidth = 24.0f;
m_numOscillators = oi->m_numOscillators;
m_fx1Knob->setModel( &oi->m_fx1Model );
m_volKnob->setModel( &oi->m_volModel );
@@ -490,7 +490,7 @@ void OrganicInstrumentView::modelChanged()
{
delete[] m_oscKnobs;
}
m_oscKnobs = new OscillatorKnobs[ m_numOscillators ];
// Create knobs, now that we know how many to make
@@ -502,7 +502,7 @@ void OrganicInstrumentView::modelChanged()
harmKnob->setObjectName( "harmKnob" );
connect( &oi->m_osc[i]->m_harmModel, SIGNAL( dataChanged() ),
this, SLOT( updateKnobHint() ) );
// setup waveform-knob
Knob * oscKnob = new OrganicKnob( this );
oscKnob->move( x + i * colWidth, y );
@@ -510,7 +510,7 @@ void OrganicInstrumentView::modelChanged()
this, SLOT( updateKnobHint() ) );
oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), QString() );
// setup volume-knob
auto volKnob = new Knob(knobStyled, this);
volKnob->setVolumeKnob( true );
@@ -518,13 +518,13 @@ void OrganicInstrumentView::modelChanged()
volKnob->setFixedSize( 21, 21 );
volKnob->setHintText( tr( "Osc %1 volume:" ).arg(
i + 1 ), "%" );
// setup panning-knob
Knob * panKnob = new OrganicKnob( this );
panKnob->move( x + i * colWidth, y + rowHeight*2 );
panKnob->setHintText( tr("Osc %1 panning:").arg(
i + 1 ), "" );
// setup knob for fine-detuning
Knob * detuneKnob = new OrganicKnob( this );
detuneKnob->move( x + i * colWidth, y + rowHeight*3 );
@@ -552,7 +552,7 @@ void OrganicInstrumentView::updateKnobHint()
{
const float harm = oi->m_osc[i]->m_harmModel.value();
const float wave = oi->m_osc[i]->m_oscModel.value();
m_oscKnobs[i].m_harmKnob->setHintText( tr( "Osc %1 harmonic:" ).arg( i + 1 ), " (" +
HARMONIC_NAMES[ static_cast<int>( harm ) ] + ")" );
m_oscKnobs[i].m_oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), " (" +
@@ -575,7 +575,7 @@ OscillatorObject::OscillatorObject( Model * _parent, int _index ) :
this, tr( "Osc %1 volume" ).arg( _index + 1 ) ),
m_panModel( DefaultPanning, PanningLeft, PanningRight, 1.0f,
this, tr( "Osc %1 panning" ).arg( _index + 1 ) ),
m_detuneModel( 0.0f, -1200.0f, 1200.0f, 1.0f,
m_detuneModel( 0.0f, -1200.0f, 1200.0f, 1.0f,
this, tr( "Osc %1 fine detuning left" ).arg( _index + 1 ) )
{
}
@@ -586,7 +586,7 @@ OscillatorObject::OscillatorObject( Model * _parent, int _index ) :
void OscillatorObject::oscButtonChanged()
{
static Oscillator::WaveShapes shapes[] =
static auto shapes = std::array
{
Oscillator::SineWave,
Oscillator::SawWave,
@@ -639,12 +639,12 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
/*
* some notes & ideas for the future of this plugin:
*
*
* - 32.692 Hz in the bass to 5919.85 Hz of treble in a Hammond organ
* => implement harmonic foldback
*
*
m_osc[i].m_oscModel->setInitValue( 0.0f );
* - randomize preset
* - randomize preset
*/

View File

@@ -225,11 +225,11 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch(
return( LoadOpen );
}
unsigned char header[239];
auto header = std::array<unsigned char, 239>{};
if( fread( header, 1, 239, fd ) != 239 ||
( memcmp( header, "GF1PATCH110\0ID#000002", 22 )
&& memcmp( header, "GF1PATCH100\0ID#000002", 22 ) ) )
if (fread(header.data(), 1, 239, fd ) != 239 ||
(memcmp(header.data(), "GF1PATCH110\0ID#000002", 22)
&& memcmp(header.data(), "GF1PATCH100\0ID#000002", 22)))
{
fclose( fd );
return( LoadNotGUS );

View File

@@ -62,7 +62,7 @@ ReverbSCEffect::ReverbSCEffect( Model* parent, const Descriptor::SubPluginFeatur
sp_dcblock_create(&dcblk[0]);
sp_dcblock_create(&dcblk[1]);
sp_dcblock_init(sp, dcblk[0], Engine::audioEngine()->currentQualitySettings().sampleRateMultiplier() );
sp_dcblock_init(sp, dcblk[1], Engine::audioEngine()->currentQualitySettings().sampleRateMultiplier() );
}
@@ -88,7 +88,7 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
SPFLOAT tmpL, tmpR;
SPFLOAT dcblkL, dcblkR;
ValueBuffer * inGainBuf = m_reverbSCControls.m_inputGainModel.valueBuffer();
ValueBuffer * sizeBuf = m_reverbSCControls.m_sizeModel.valueBuffer();
ValueBuffer * colorBuf = m_reverbSCControls.m_colorModel.valueBuffer();
@@ -96,7 +96,7 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
for( fpp_t f = 0; f < frames; ++f )
{
sample_t s[2] = { buf[f][0], buf[f][1] };
auto s = std::array{buf[f][0], buf[f][1]};
const auto inGain
= (SPFLOAT)DB2LIN((inGainBuf ? inGainBuf->values()[f] : m_reverbSCControls.m_inputGainModel.value()));
@@ -105,12 +105,12 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
s[0] *= inGain;
s[1] *= inGain;
revsc->feedback = (SPFLOAT)(sizeBuf ?
sizeBuf->values()[f]
revsc->feedback = (SPFLOAT)(sizeBuf ?
sizeBuf->values()[f]
: m_reverbSCControls.m_sizeModel.value());
revsc->lpfreq = (SPFLOAT)(colorBuf ?
colorBuf->values()[f]
revsc->lpfreq = (SPFLOAT)(colorBuf ?
colorBuf->values()[f]
: m_reverbSCControls.m_colorModel.value());
@@ -128,7 +128,7 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
return isRunning();
}
void ReverbSCEffect::changeSampleRate()
{
// Change sr variable in Soundpipe. does not need to be destroyed
@@ -144,7 +144,7 @@ void ReverbSCEffect::changeSampleRate()
sp_dcblock_create(&dcblk[0]);
sp_dcblock_create(&dcblk[1]);
sp_dcblock_init(sp, dcblk[0], Engine::audioEngine()->currentQualitySettings().sampleRateMultiplier() );
sp_dcblock_init(sp, dcblk[1], Engine::audioEngine()->currentQualitySettings().sampleRateMultiplier() );
mutex.unlock();
@@ -156,9 +156,9 @@ extern "C"
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data )
{
return new ReverbSCEffect(
parent,
static_cast<const Plugin::Descriptor::SubPluginFeatures::Key*>(data)
return new ReverbSCEffect(
parent,
static_cast<const Plugin::Descriptor::SubPluginFeatures::Key*>(data)
);
}

View File

@@ -154,7 +154,7 @@ void PatchesDialog::setup ( fluid_synth_t * pSynth, int iChan,
fluid_preset_t preset;
fluid_preset_t *pCurPreset = &preset;
#else
fluid_preset_t *pCurPreset;
fluid_preset_t *pCurPreset = nullptr;
#endif
while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) {
int iBank = fluid_preset_get_banknum(pCurPreset);

View File

@@ -181,6 +181,15 @@ Sf2Instrument::Sf2Instrument( InstrumentTrack * _instrument_track ) :
connect( &m_chorusLevel, SIGNAL( dataChanged() ), this, SLOT( updateChorus() ) );
connect( &m_chorusSpeed, SIGNAL( dataChanged() ), this, SLOT( updateChorus() ) );
connect( &m_chorusDepth, SIGNAL( dataChanged() ), this, SLOT( updateChorus() ) );
// Microtuning
connect(Engine::getSong(), &Song::scaleListChanged, this, &Sf2Instrument::updateTuning);
connect(Engine::getSong(), &Song::keymapListChanged, this, &Sf2Instrument::updateTuning);
connect(instrumentTrack()->microtuner()->enabledModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection);
connect(instrumentTrack()->microtuner()->scaleModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection);
connect(instrumentTrack()->microtuner()->keymapModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection);
connect(instrumentTrack()->microtuner()->keyRangeImportModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection);
connect(instrumentTrack()->baseNoteModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection);
auto iph = new InstrumentPlayHandle(this, _instrument_track);
Engine::audioEngine()->addPlayHandle( iph );
@@ -537,6 +546,38 @@ void Sf2Instrument::updateChorus()
void Sf2Instrument::updateTuning()
{
if (instrumentTrack()->microtuner()->enabledModel()->value())
{
auto centArray = std::array<double, 128>{};
double lowestHz = pow(2., -69. / 12.) * 440.;// Frequency of MIDI note 0, which is approximately 8.175798916 Hz
for (int i = 0; i < 128; ++i)
{
// Get desired Hz of note
double noteHz = instrumentTrack()->microtuner()->keyToFreq(i, DefaultBaseKey);
// Convert Hz to cents
centArray[i] = noteHz == 0. ? 0. : 1200. * log2(noteHz / lowestHz);
}
fluid_synth_activate_key_tuning(m_synth, 0, 0, "", centArray.data(), true);
for (int chan = 0; chan < 16; chan++)
{
fluid_synth_activate_tuning(m_synth, chan, 0, 0, true);
}
}
else
{
fluid_synth_activate_key_tuning(m_synth, 0, 0, "", nullptr, true);
for (int chan = 0; chan < 16; chan++)
{
fluid_synth_activate_tuning(m_synth, chan, 0, 0, true);
}
}
}
void Sf2Instrument::reloadSynth()
{
double tempRate;
@@ -604,6 +645,7 @@ void Sf2Instrument::reloadSynth()
updateReverbOn();
updateChorusOn();
updateGain();
updateTuning();
// Reset last MIDI pitch properties, which will be set to the correct values
// upon playing the next note
@@ -622,18 +664,19 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * )
}
const f_cnt_t tfp = _n->totalFramesPlayed();
int masterPitch = instrumentTrack()->useMasterPitchModel()->value() ? Engine::getSong()->masterPitch() : 0;
int baseNote = instrumentTrack()->baseNoteModel()->value();
int midiNote = _n->midiKey() - baseNote + DefaultBaseKey + masterPitch;
if( tfp == 0 )
// out of range?
if (midiNote < 0 || midiNote >= 128)
{
const float LOG440 = 2.643452676f;
return;
}
int midiNote = (int)floor( 12.0 * ( log2( _n->unpitchedFrequency() ) - LOG440 ) - 4.0 );
// out of range?
if( midiNote <= 0 || midiNote >= 128 )
{
return;
}
if (tfp == 0)
{
const int baseVelocity = instrumentTrack()->midiPort()->baseVelocity();
auto pluginData = new Sf2PluginData;

View File

@@ -111,7 +111,7 @@ public slots:
void updateChorusOn();
void updateChorus();
void updateGain();
void updateTuning();
private:
static QMutex s_fontsMutex;

View File

@@ -3,7 +3,7 @@
*
* Copyright (c) 2008 Csaba Hruska <csaba.hruska/at/gmail.com>
* Attila Herman <attila589/at/gmail.com>
*
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
@@ -52,22 +52,22 @@ namespace lmms
#define SIDWRITEDELAY 9 // lda $xxxx,x 4 cycles, sta $d400,x 5 cycles
#define SIDWAVEDELAY 4 // and $xxxx,x 4 cycles extra
unsigned char sidorder[] =
auto sidorder = std::array<unsigned char, 25>
{0x15,0x16,0x18,0x17,
0x05,0x06,0x02,0x03,0x00,0x01,0x04,
0x0c,0x0d,0x09,0x0a,0x07,0x08,0x0b,
0x13,0x14,0x10,0x11,0x0e,0x0f,0x12};
static const char *attackTime[16] = { "2 ms", "8 ms", "16 ms", "24 ms",
static auto attackTime = std::array<const char*, 16>{ "2 ms", "8 ms", "16 ms", "24 ms",
"38 ms", "56 ms", "68 ms", "80 ms",
"100 ms", "250 ms", "500 ms", "800 ms",
"1 s", "3 s", "5 s", "8 s" };
static const char *decRelTime[16] = { "6 ms", "24 ms", "48 ms", "72 ms",
static auto decRelTime = std::array<const char*, 16>{ "6 ms", "24 ms", "48 ms", "72 ms",
"114 ms", "168 ms", "204 ms", "240 ms",
"300 ms", "750 ms", "1.5 s", "2.4 s",
"3 s", "9 s", "15 s", "24 s" };
// release time time in ms
static const int relTime[16] = { 6, 24, 48, 72, 114, 168, 204, 240, 300, 750,
static const auto relTime = std::array{ 6, 24, 48, 72, 114, 168, 204, 240, 300, 750,
1500, 2400, 3000, 9000, 15000, 24000 };
@@ -118,11 +118,11 @@ VoiceObject::VoiceObject( Model * _parent, int _idx ) :
SidInstrument::SidInstrument( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, &sid_plugin_descriptor ),
// filter
// filter
m_filterFCModel( 1024.0f, 0.0f, 2047.0f, 1.0f, this, tr( "Cutoff frequency" ) ),
m_filterResonanceModel( 8.0f, 0.0f, 15.0f, 1.0f, this, tr( "Resonance" ) ),
m_filterModeModel( LowPass, 0, NumFilterTypes-1, this, tr( "Filter type" )),
// misc
m_voice3OffModel( false, this, tr( "Voice 3 off" ) ),
m_volumeModel( 15.0f, 0.0f, 15.0f, 1.0f, this, tr( "Volume" ) ),
@@ -167,11 +167,11 @@ void SidInstrument::saveSettings( QDomDocument & _doc,
_doc, _this, "test" + is );
}
// filter
// filter
m_filterFCModel.saveSettings( _doc, _this, "filterFC" );
m_filterResonanceModel.saveSettings( _doc, _this, "filterResonance" );
m_filterModeModel.saveSettings( _doc, _this, "filterMode" );
// misc
m_voice3OffModel.saveSettings( _doc, _this, "voice3Off" );
m_volumeModel.saveSettings( _doc, _this, "volume" );
@@ -200,12 +200,12 @@ void SidInstrument::loadSettings( const QDomElement & _this )
m_voice[i]->m_filteredModel.loadSettings( _this, "filtered" + is );
m_voice[i]->m_testModel.loadSettings( _this, "test" + is );
}
// filter
// filter
m_filterFCModel.loadSettings( _this, "filterFC" );
m_filterResonanceModel.loadSettings( _this, "filterResonance" );
m_filterModeModel.loadSettings( _this, "filterMode" );
// misc
m_voice3OffModel.loadSettings( _this, "voice3Off" );
m_volumeModel.loadSettings( _this, "volume" );
@@ -318,7 +318,7 @@ void SidInstrument::playNote( NotePlayHandle * _n,
int delta_t = clockrate * frames / samplerate + 4;
// avoid variable length array for msvc compat
auto buf = reinterpret_cast<short*>(_working_buffer + offset);
unsigned char sidreg[NUMSIDREGS];
auto sidreg = std::array<unsigned char, NUMSIDREGS>{};
for (auto& reg : sidreg)
{
@@ -354,7 +354,7 @@ void SidInstrument::playNote( NotePlayHandle * _n,
sidreg[base+1] = (data16>>8)&0x00FF;
// pw
data16 = (int)m_voice[i]->m_pulseWidthModel.value();
sidreg[base+2] = data16&0x00FF;
sidreg[base+3] = (data16>>8)&0x000F;
// control: wave form, (test), ringmod, sync, gate
@@ -363,7 +363,7 @@ void SidInstrument::playNote( NotePlayHandle * _n,
data8 += m_voice[i]->m_ringModModel.value()?4:0;
data8 += m_voice[i]->m_testModel.value()?8:0;
switch( m_voice[i]->m_waveFormModel.value() )
{
{
default: break;
case VoiceObject::NoiseWave: data8 += 128; break;
case VoiceObject::SquareWave: data8 += 64; break;
@@ -394,7 +394,7 @@ void SidInstrument::playNote( NotePlayHandle * _n,
data16 = (int)m_filterFCModel.value();
sidreg[21] = data16&0x0007;
sidreg[22] = (data16>>3)&0x00FF;
// res, filt ex,3,2,1
data16 = (int)m_filterResonanceModel.value();
data8 = (data16&0x000F)<<4;
@@ -409,7 +409,7 @@ void SidInstrument::playNote( NotePlayHandle * _n,
data8 += m_voice3OffModel.value()?128:0;
switch( m_filterModeModel.value() )
{
{
default: break;
case LowPass: data8 += 16; break;
case BandPass: data8 += 32; break;
@@ -417,8 +417,8 @@ void SidInstrument::playNote( NotePlayHandle * _n,
}
sidreg[24] = data8&0x00FF;
int num = sid_fillbuffer(sidreg, sid,delta_t,buf, frames);
int num = sid_fillbuffer(sidreg.data(), sid, delta_t, buf, frames);
if(num!=frames)
printf("!!!Not enough samples\n");
@@ -544,7 +544,7 @@ SidInstrumentView::SidInstrumentView( Instrument * _instrument,
m_sidTypeBtnGrp->addButton( mos6581_btn );
m_sidTypeBtnGrp->addButton( mos8580_btn );
for( int i = 0; i < 3; i++ )
for( int i = 0; i < 3; i++ )
{
Knob *ak = new sidKnob( this );
ak->setHintText( tr("Attack:"), "" );
@@ -674,7 +674,7 @@ void SidInstrumentView::updateKnobHint()
m_releaseModel.value()] ) + ")" );
m_voiceKnobs[i].m_relKnob->setToolTip(
decRelTime[(int)k->m_voice[i]->m_releaseModel.value()]);
m_voiceKnobs[i].m_pwKnob->setHintText( tr( "Pulse width:" )+ " ", " (" +
QString::number( (double)k->m_voice[i]->
m_pulseWidthModel.value() / 40.95 ) + "%)" );
@@ -758,7 +758,7 @@ void SidInstrumentView::modelChanged()
connect(&voice->m_sustainModel, SIGNAL(dataChanged()), this, SLOT(updateKnobToolTip()));
connect(&voice->m_coarseModel, SIGNAL(dataChanged()), this, SLOT(updateKnobToolTip()));
}
connect( &k->m_volumeModel, SIGNAL( dataChanged() ),
this, SLOT( updateKnobToolTip() ) );
connect( &k->m_filterResonanceModel, SIGNAL( dataChanged() ),

BIN
plugins/Sid/filter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -240,7 +240,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
envelopeResolutionKnob->setModel(&controls->m_envelopeResolutionModel);
envelopeResolutionKnob->setLabel(tr("Envelope res."));
envelopeResolutionKnob->setToolTip(tr("Increase envelope resolution for better details, decrease for better GUI performance."));
envelopeResolutionKnob->setHintText(tr("Draw at most"), tr(" envelope points per pixel"));
envelopeResolutionKnob->setHintText(tr("Maximum number of envelope points drawn per pixel:"), "");
advanced_layout->addWidget(envelopeResolutionKnob, 0, 0, 1, 1, Qt::AlignCenter);
// Spectrum graph resolution
@@ -248,7 +248,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
spectrumResolutionKnob->setModel(&controls->m_spectrumResolutionModel);
spectrumResolutionKnob->setLabel(tr("Spectrum res."));
spectrumResolutionKnob->setToolTip(tr("Increase spectrum resolution for better details, decrease for better GUI performance."));
spectrumResolutionKnob->setHintText(tr("Draw at most"), tr(" spectrum points per pixel"));
spectrumResolutionKnob->setHintText(tr("Maximum number of spectrum points drawn per pixel:"), "");
advanced_layout->addWidget(spectrumResolutionKnob, 1, 0, 1, 1, Qt::AlignCenter);
// Peak falloff speed
@@ -272,7 +272,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
waterfallHeightKnob->setModel(&controls->m_waterfallHeightModel);
waterfallHeightKnob->setLabel(tr("Waterfall height"));
waterfallHeightKnob->setToolTip(tr("Increase to get slower scrolling, decrease to see fast transitions better. Warning: medium CPU usage."));
waterfallHeightKnob->setHintText(tr("Keep"), tr(" lines"));
waterfallHeightKnob->setHintText(tr("Number of lines to keep:"), "");
advanced_layout->addWidget(waterfallHeightKnob, 0, 2, 1, 1, Qt::AlignCenter);
processor->reallocateBuffers();
connect(&controls->m_waterfallHeightModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();});
@@ -290,7 +290,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
windowOverlapKnob->setModel(&controls->m_windowOverlapModel);
windowOverlapKnob->setLabel(tr("Window overlap"));
windowOverlapKnob->setToolTip(tr("Increase to prevent missing fast transitions arriving near FFT window edges. Warning: high CPU usage."));
windowOverlapKnob->setHintText(tr("Each sample processed"), tr(" times"));
windowOverlapKnob->setHintText(tr("Number of times each sample is processed:"), "");
advanced_layout->addWidget(windowOverlapKnob, 0, 3, 1, 1, Qt::AlignCenter);
// FFT zero padding
@@ -365,4 +365,4 @@ QSize SaControlsDialog::sizeHint() const
}
} // namespace lmms::gui
} // namespace lmms::gui

View File

@@ -648,8 +648,8 @@ std::vector<std::pair<int, std::string>> SaSpectrumView::makeLogFreqTics(int low
{
std::vector<std::pair<int, std::string>> result;
int i, j;
int a[] = {10, 20, 50}; // sparse series multipliers
int b[] = {14, 30, 70}; // additional (denser) series
auto a = std::array{10, 20, 50}; // sparse series multipliers
auto b = std::array{14, 30, 70}; // additional (denser) series
// generate main steps (powers of 10); use the series to specify smaller steps
for (i = 1; i <= high; i *= 10)

View File

@@ -85,15 +85,15 @@ StereoEnhancerEffect::~StereoEnhancerEffect()
bool StereoEnhancerEffect::processAudioBuffer( sampleFrame * _buf,
const fpp_t _frames )
{
// This appears to be used for determining whether or not to continue processing
// audio with this effect
// audio with this effect
double out_sum = 0.0;
float width;
int frameIndex = 0;
if( !isEnabled() || !isRunning() )
{
return( false );
@@ -104,7 +104,7 @@ bool StereoEnhancerEffect::processAudioBuffer( sampleFrame * _buf,
for( fpp_t f = 0; f < _frames; ++f )
{
// copy samples into the delay buffer
m_delayBuffer[m_currFrame][0] = _buf[f][0];
m_delayBuffer[m_currFrame][1] = _buf[f][1];
@@ -122,7 +122,7 @@ bool StereoEnhancerEffect::processAudioBuffer( sampleFrame * _buf,
}
//sample_t s[2] = { _buf[f][0], _buf[f][1] }; //Vanilla
sample_t s[2] = { _buf[f][0], m_delayBuffer[frameIndex][1] }; //Chocolate
auto s = std::array{_buf[f][0], m_delayBuffer[frameIndex][1]}; //Chocolate
m_seFX.nextSample( s[0], s[1] );

View File

@@ -21,7 +21,7 @@
* Boston, MA 02110-1301 USA.
*
*/
#include <QDomElement>
@@ -81,10 +81,10 @@ OscillatorObject::OscillatorObject( Model * _parent, int _idx ) :
m_fineRightModel( 0.0f, -100.0f, 100.0f, 1.0f, this,
tr( "Osc %1 fine detuning right" ).arg( _idx + 1 ) ),
m_phaseOffsetModel( 0.0f, 0.0f, 360.0f, 1.0f, this,
tr( "Osc %1 phase-offset" ).arg( _idx+1 ) ),
tr( "Osc %1 phase-offset" ).arg( _idx+1 ) ),
m_stereoPhaseDetuningModel( 0.0f, 0.0f, 360.0f, 1.0f, this,
tr( "Osc %1 stereo phase-detuning" ).arg( _idx+1 ) ),
m_waveShapeModel( Oscillator::SineWave, 0,
m_waveShapeModel( Oscillator::SineWave, 0,
Oscillator::NumWaveShapes-1, this,
tr( "Osc %1 wave shape" ).arg( _idx+1 ) ),
m_modulationAlgoModel( Oscillator::SignalMix, 0,
@@ -220,7 +220,7 @@ void OscillatorObject::updateUseWaveTable()
}
TripleOscillator::TripleOscillator( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, &tripleoscillator_plugin_descriptor )
@@ -310,8 +310,8 @@ void TripleOscillator::playNote( NotePlayHandle * _n,
{
if( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr )
{
Oscillator * oscs_l[NUM_OF_OSCILLATORS];
Oscillator * oscs_r[NUM_OF_OSCILLATORS];
auto oscs_l = std::array<Oscillator*, NUM_OF_OSCILLATORS>{};
auto oscs_r = std::array<Oscillator*, NUM_OF_OSCILLATORS>{};
for( int i = NUM_OF_OSCILLATORS - 1; i >= 0; --i )
{

View File

@@ -221,16 +221,16 @@ void VestigeInstrument::loadSettings( const QDomElement & _this )
const QMap<QString, QString> & dump = m_plugin->parameterDump();
paramCount = dump.size();
char paramStr[35];
auto paramStr = std::array<char, 35>{};
knobFModel = new FloatModel *[ paramCount ];
QStringList s_dumpValues;
for( int i = 0; i < paramCount; i++ )
{
sprintf( paramStr, "param%d", i );
s_dumpValues = dump[ paramStr ].split( ":" );
sprintf(paramStr.data(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
knobFModel[i] = new FloatModel( 0.0f, 0.0f, 1.0f, 0.01f, this, QString::number(i) );
knobFModel[i]->loadSettings( _this, paramStr );
knobFModel[i]->loadSettings(_this, paramStr.data());
if( !( knobFModel[ i ]->isAutomated() || knobFModel[ i ]->controllerConnection() ) )
{
@@ -286,12 +286,12 @@ void VestigeInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this )
if (knobFModel != nullptr) {
const QMap<QString, QString> & dump = m_plugin->parameterDump();
paramCount = dump.size();
char paramStr[35];
auto paramStr = std::array<char, 35>{};
for( int i = 0; i < paramCount; i++ )
{
if (knobFModel[i]->isAutomated() || knobFModel[i]->controllerConnection()) {
sprintf( paramStr, "param%d", i);
knobFModel[i]->saveSettings( _doc, _this, paramStr );
sprintf(paramStr.data(), "param%d", i);
knobFModel[i]->saveSettings(_doc, _this, paramStr.data());
}
/* QDomElement me = _doc.createElement( paramStr );
@@ -938,7 +938,7 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume
using ::operator|;
#endif
m_vi = m_vi2;
m_vi->m_scrollArea = new QScrollArea( this );
widget = new QWidget(this);
@@ -996,13 +996,13 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume
hasKnobModel = false;
}
char paramStr[35];
auto paramStr = std::array<char, 35>{};
QStringList s_dumpValues;
for( int i = 0; i < m_vi->paramCount; i++ )
{
sprintf( paramStr, "param%d", i);
s_dumpValues = dump[ paramStr ].split( ":" );
sprintf(paramStr.data(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
vstKnobs[ i ] = new CustomTextKnob( knobBright_26, this, s_dumpValues.at( 1 ) );
vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" );
@@ -1010,9 +1010,9 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume
if( !hasKnobModel )
{
sprintf( paramStr, "%d", i);
m_vi->knobFModel[ i ] = new FloatModel( LocaleHelper::toFloat(s_dumpValues.at(2)),
0.0f, 1.0f, 0.01f, castModel<VestigeInstrument>(), paramStr );
sprintf(paramStr.data(), "%d", i);
m_vi->knobFModel[i] = new FloatModel(LocaleHelper::toFloat(s_dumpValues.at(2)),
0.0f, 1.0f, 0.01f, castModel<VestigeInstrument>(), paramStr.data());
}
FloatModel * model = m_vi->knobFModel[i];
@@ -1063,7 +1063,7 @@ void ManageVestigeInstrumentView::closeWindow()
void ManageVestigeInstrumentView::syncPlugin( void )
{
char paramStr[35];
auto paramStr = std::array<char, 35>{};
QStringList s_dumpValues;
const QMap<QString, QString> & dump = m_vi->m_plugin->parameterDump();
float f_value;
@@ -1074,8 +1074,8 @@ void ManageVestigeInstrumentView::syncPlugin( void )
// those auto-setted values are not jurnaled, tracked for undo / redo
if( !( m_vi->knobFModel[ i ]->isAutomated() || m_vi->knobFModel[ i ]->controllerConnection() ) )
{
sprintf( paramStr, "param%d", i );
s_dumpValues = dump[ paramStr ].split( ":" );
sprintf(paramStr.data(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
f_value = LocaleHelper::toFloat(s_dumpValues.at(2));
m_vi->knobFModel[ i ]->setAutomatedValue( f_value );
m_vi->knobFModel[ i ]->setInitValue( f_value );

View File

@@ -51,7 +51,7 @@ ELSEIF(LMMS_BUILD_LINUX)
INCLUDE(CheckWineGcc)
CheckWineGcc(32 "${WINEGCC}" WINEGCC_WORKING)
IF(NOT WINEGCC_WORKING)
MESSAGE(WARNING "winegcc fails to complie 32-bit binaries, please make sure you have 32-bit GCC libraries")
MESSAGE(WARNING "winegcc fails to compile 32-bit binaries, please make sure you have 32-bit GCC libraries")
RETURN()
ENDIF()
ExternalProject_Add(RemoteVstPlugin32

View File

@@ -504,20 +504,14 @@ QWidget *VstPlugin::editor()
void VstPlugin::openPreset()
{
gui::FileDialog ofd( nullptr, tr( "Open Preset" ), "",
tr( "Vst Plugin Preset (*.fxp *.fxb)" ) );
ofd.setFileMode( gui::FileDialog::ExistingFiles );
if( ofd.exec () == QDialog::Accepted &&
!ofd.selectedFiles().isEmpty() )
gui::FileDialog ofd(nullptr, tr("Open Preset"), "", tr("VST Plugin Preset (*.fxp *.fxb)"));
ofd.setFileMode(gui::FileDialog::ExistingFiles);
if (ofd.exec() == QDialog::Accepted && !ofd.selectedFiles().isEmpty())
{
lock();
sendMessage( message( IdLoadPresetFile ).
addString(
QSTR_TO_STDSTR(
QDir::toNativeSeparators( ofd.selectedFiles()[0] ) ) )
);
waitForMessage( IdLoadPresetFile, true );
sendMessage(message(IdLoadPresetFile).addString(QSTR_TO_STDSTR(
QDir::toNativeSeparators(ofd.selectedFiles()[0]))));
waitForMessage(IdLoadPresetFile, true);
unlock();
}
}
@@ -585,32 +579,32 @@ void VstPlugin::savePreset()
QString presName = currentProgramName().isEmpty() ? tr(": default") : currentProgramName();
presName.replace("\"", "'"); // QFileDialog unable to handle double quotes properly
gui::FileDialog sfd( nullptr, tr( "Save Preset" ), presName.section(": ", 1, 1) + tr(".fxp"),
tr( "Vst Plugin Preset (*.fxp *.fxb)" ) );
gui::FileDialog sfd(nullptr, tr("Save Preset"), presName.section(": ", 1, 1) + tr(".fxp"),
tr("VST Plugin Preset (*.fxp *.fxb)"));
if( p_name != "" ) // remember last directory
if (p_name != "") // remember last directory
{
sfd.setDirectory( QFileInfo( p_name ).absolutePath() );
sfd.setDirectory(QFileInfo(p_name).absolutePath());
}
sfd.setAcceptMode( gui::FileDialog::AcceptSave );
sfd.setFileMode( gui::FileDialog::AnyFile );
if( sfd.exec () == QDialog::Accepted &&
!sfd.selectedFiles().isEmpty() && sfd.selectedFiles()[0] != "" )
sfd.setAcceptMode(gui::FileDialog::AcceptSave);
sfd.setFileMode(gui::FileDialog::AnyFile);
if (sfd.exec() == QDialog::Accepted && !sfd.selectedFiles().isEmpty() && sfd.selectedFiles()[0] != "")
{
QString fns = sfd.selectedFiles()[0];
p_name = fns;
if ((fns.toUpper().indexOf(tr(".FXP")) == -1) && (fns.toUpper().indexOf(tr(".FXB")) == -1))
{
fns = fns + tr(".fxb");
else fns = fns.left(fns.length() - 4) + (fns.right( 4 )).toLower();
}
else
{
fns = fns.left(fns.length() - 4) + (fns.right(4)).toLower();
}
lock();
sendMessage( message( IdSavePresetFile ).
addString(
QSTR_TO_STDSTR(
QDir::toNativeSeparators( fns ) ) )
);
waitForMessage( IdSavePresetFile, true );
sendMessage(message(IdSavePresetFile).addString(QSTR_TO_STDSTR(QDir::toNativeSeparators(fns))));
waitForMessage(IdSavePresetFile, true);
unlock();
}
}
@@ -757,7 +751,7 @@ void VstPlugin::createUI( QWidget * parent )
QHBoxLayout * l = new QHBoxLayout( helper );
QWidget * target = new QWidget( helper );
l->setSpacing( 0 );
l->setMargin( 0 );
l->setContentsMargins(0, 0, 0, 0);
l->addWidget( target );
// we've to call that for making sure, Qt created the windows
@@ -825,4 +819,4 @@ QString VstPlugin::embedMethod() const
}
} // namespace lmms
} // namespace lmms

View File

@@ -83,16 +83,16 @@ void VstEffectControls::loadSettings( const QDomElement & _this )
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
paramCount = dump.size();
char paramStr[35];
auto paramStr = std::array<char, 35>{};
knobFModel = new FloatModel *[ paramCount ];
QStringList s_dumpValues;
for( int i = 0; i < paramCount; i++ )
{
sprintf( paramStr, "param%d", i );
s_dumpValues = dump[ paramStr ].split( ":" );
sprintf(paramStr.data(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
knobFModel[i] = new FloatModel( 0.0f, 0.0f, 1.0f, 0.01f, this, QString::number(i) );
knobFModel[i]->loadSettings( _this, paramStr );
knobFModel[i]->loadSettings(_this, paramStr.data());
if( !( knobFModel[ i ]->isAutomated() ||
knobFModel[ i ]->controllerConnection() ) )
@@ -134,12 +134,12 @@ void VstEffectControls::saveSettings( QDomDocument & _doc, QDomElement & _this )
if (knobFModel != nullptr) {
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
paramCount = dump.size();
char paramStr[35];
auto paramStr = std::array<char, 35>{};
for( int i = 0; i < paramCount; i++ )
{
if (knobFModel[i]->isAutomated() || knobFModel[i]->controllerConnection()) {
sprintf( paramStr, "param%d", i);
knobFModel[i]->saveSettings( _doc, _this, paramStr );
sprintf(paramStr.data(), "param%d", i);
knobFModel[i]->saveSettings(_doc, _this, paramStr.data());
}
}
}
@@ -173,7 +173,7 @@ void VstEffectControls::managePlugin()
auto tt = new gui::ManageVSTEffectView(m_effect, this);
ctrHandle = (QObject *)tt;
} else if (m_subWindow != nullptr) {
if (m_subWindow->widget()->isVisible() == false ) {
if (m_subWindow->widget()->isVisible() == false ) {
m_scrollArea->show();
m_subWindow->show();
} else {
@@ -371,13 +371,13 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls *
hasKnobModel = false;
}
char paramStr[35];
auto paramStr = std::array<char, 35>{};
QStringList s_dumpValues;
for( int i = 0; i < m_vi->paramCount; i++ )
{
sprintf( paramStr, "param%d", i);
s_dumpValues = dump[ paramStr ].split( ":" );
sprintf(paramStr.data(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
vstKnobs[ i ] = new CustomTextKnob( knobBright_26, widget, s_dumpValues.at( 1 ) );
vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" );
@@ -385,9 +385,9 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls *
if( !hasKnobModel )
{
sprintf( paramStr, "%d", i);
m_vi->knobFModel[ i ] = new FloatModel( LocaleHelper::toFloat(s_dumpValues.at(2)),
0.0f, 1.0f, 0.01f, _eff, paramStr );
sprintf(paramStr.data(), "%d", i);
m_vi->knobFModel[i] = new FloatModel(LocaleHelper::toFloat(s_dumpValues.at(2)),
0.0f, 1.0f, 0.01f, _eff, paramStr.data());
}
FloatModel * model = m_vi->knobFModel[i];
@@ -439,7 +439,7 @@ void ManageVSTEffectView::closeWindow()
void ManageVSTEffectView::syncPlugin()
{
char paramStr[35];
auto paramStr = std::array<char, 35>{};
QStringList s_dumpValues;
const QMap<QString, QString> & dump = m_effect->m_plugin->parameterDump();
float f_value;
@@ -451,8 +451,8 @@ void ManageVSTEffectView::syncPlugin()
if( !( m_vi2->knobFModel[ i ]->isAutomated() ||
m_vi2->knobFModel[ i ]->controllerConnection() ) )
{
sprintf( paramStr, "param%d", i );
s_dumpValues = dump[ paramStr ].split( ":" );
sprintf(paramStr.data(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
f_value = LocaleHelper::toFloat(s_dumpValues.at(2));
m_vi2->knobFModel[ i ]->setAutomatedValue( f_value );
m_vi2->knobFModel[ i ]->setInitValue( f_value );
@@ -477,7 +477,7 @@ void ManageVSTEffectView::displayAutomatedOnly()
{
vstKnobs[ i ]->hide();
m_displayAutomatedOnly->setText( "All" );
} else {
} else {
vstKnobs[ i ]->show();
m_displayAutomatedOnly->setText( "Automated" );
}
@@ -534,7 +534,7 @@ void ManageVSTEffectView::syncParameterText()
ManageVSTEffectView::~ManageVSTEffectView()
{
if( m_vi2->knobFModel != nullptr )
{
{
for( int i = 0; i < m_vi2->paramCount; i++ )
{
delete m_vi2->knobFModel[ i ];
@@ -553,18 +553,18 @@ ManageVSTEffectView::~ManageVSTEffectView()
delete [] m_vi2->knobFModel;
m_vi2->knobFModel = nullptr;
}
if( m_vi2->m_scrollArea != nullptr )
{
delete m_vi2->m_scrollArea;
m_vi2->m_scrollArea = nullptr;
}
if( m_vi2->m_subWindow != nullptr )
{
m_vi2->m_subWindow->setAttribute( Qt::WA_DeleteOnClose );
m_vi2->m_subWindow->close();
if( m_vi2->m_subWindow != nullptr )
{
delete m_vi2->m_subWindow;

View File

@@ -96,7 +96,7 @@ bool WaveShaperEffect::processAudioBuffer( sampleFrame * _buf,
for( fpp_t f = 0; f < _frames; ++f )
{
float s[2] = { _buf[f][0], _buf[f][1] };
auto s = std::array{_buf[f][0], _buf[f][1]};
// apply input gain
s[0] *= *inputPtr;
@@ -114,7 +114,7 @@ bool WaveShaperEffect::processAudioBuffer( sampleFrame * _buf,
for( i=0; i <= 1; ++i )
{
const int lookup = static_cast<int>( qAbs( s[i] ) * 200.0f );
const float frac = fraction( qAbs( s[i] ) * 200.0f );
const float frac = fraction( qAbs( s[i] ) * 200.0f );
const float posneg = s[i] < 0 ? -1.0f : 1.0f;
if( lookup < 1 )
@@ -122,8 +122,8 @@ bool WaveShaperEffect::processAudioBuffer( sampleFrame * _buf,
s[i] = frac * samples[0] * posneg;
}
else if( lookup < 200 )
{
s[i] = linearInterpolate( samples[ lookup - 1 ],
{
s[i] = linearInterpolate( samples[ lookup - 1 ],
samples[ lookup ], frac )
* posneg;
}

View File

@@ -69,7 +69,7 @@ void WaveShaperControls::loadSettings( const QDomElement & _this )
//load input, output knobs
m_inputModel.loadSettings( _this, "inputGain" );
m_outputModel.loadSettings( _this, "outputGain" );
m_clipModel.loadSettings( _this, "clipInput" );
//load waveshape
@@ -105,7 +105,7 @@ void WaveShaperControls::saveSettings( QDomDocument & _doc,
void WaveShaperControls::setDefaultShape()
{
float shp [200] = { };
auto shp = std::array<float, 200>{};
for ( int i = 0; i<200; i++)
{
shp[i] = ((float)i + 1.0f) / 200.0f;

View File

@@ -214,7 +214,7 @@ struct WaveValueFunctionInterpolate : public exprtk::ifunction<T>
const T *m_vec;
const std::size_t m_size;
};
static const unsigned int random_data[257]={
static const auto random_data = std::array<unsigned int, 257>{
0xd76a33ec, 0x4a767724, 0xb34ebd08 ,0xf4024196,
0x17b426e2, 0x8dc6389a, 0x1b5dcb93 ,0xa771bd3f,
0x078d502e, 0x8980988a, 0x1f64f846 ,0xb5b48ed7,
@@ -526,14 +526,14 @@ ExprFront::ExprFront(const char * expr, int last_func_samples)
try
{
m_data = new ExprFrontData(last_func_samples);
m_data->m_expression_string = expr;
m_data->m_symbol_table.add_pi();
m_data->m_symbol_table.add_constant("e", F_E);
m_data->m_symbol_table.add_constant("seed", SimpleRandom::generator() & max_float_integer_mask);
m_data->m_symbol_table.add_function("sinew", sin_wave_func);
m_data->m_symbol_table.add_function("squarew", square_wave_func);
m_data->m_symbol_table.add_function("trianglew", triangle_wave_func);
@@ -577,7 +577,7 @@ bool ExprFront::compile()
sstore.disable_all_assignment_ops();
sstore.disable_all_control_structures();
parser_t parser(sstore);
m_valid=parser.compile(m_data->m_expression_string, m_data->m_expression);
}
catch(...)
@@ -600,7 +600,7 @@ float ExprFront::evaluate()
WARN_EXPRTK;
}
return 0;
}
bool ExprFront::add_variable(const char* name, float& ref)
{
@@ -757,7 +757,7 @@ void ExprSynth::renderOutput(fpp_t frames, sampleFrame *buf)
const float new_freq = m_nph->frequency();
const float freq_inc = (new_freq - m_frequency) / frames;
const bool is_released = m_nph->isReleased();
expression_t *o1_rawExpr = &(m_exprO1->getData()->m_expression);
expression_t *o2_rawExpr = &(m_exprO2->getData()->m_expression);
LastSampleFunction<float> * last_func1 = &m_exprO1->getData()->m_last_func;
@@ -791,7 +791,7 @@ void ExprSynth::renderOutput(fpp_t frames, sampleFrame *buf)
}
else
{
if (o2_valid)
{
o1_rawExpr = o2_rawExpr;

View File

@@ -1,5 +1,12 @@
if(NOT FLTK_FOUND)
return()
endif()
INCLUDE(BuildPlugin)
find_package(Threads REQUIRED)
find_package(ZLIB REQUIRED)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# definitions for ZynAddSubFX
@@ -11,40 +18,20 @@ ELSE()
ADD_DEFINITIONS(-DOS_WINDOWS)
ENDIF()
# do not conflict with LMMS' Controller class
ADD_DEFINITIONS(-DController=ZynController)
# use asm optimizations when on x86 or x86_64
IF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
if(NOT MSVC AND (LMMS_HOST_X86 OR LMMS_HOST_X86_64))
ADD_DEFINITIONS(-DASM_F2I_YES)
ENDIF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
endif()
# build ZynAddSubFX with full optimizations
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive")
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive")
endif()
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "6.0.0")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-misleading-indentation")
ENDIF()
IF(LMMS_BUILD_WIN32)
# link system-libraries
ADD_DEFINITIONS(-DPTW32_STATIC_LIB)
# fix X11 headers errors caused by bug with mingw + c++11 (enable -std=gnu++0x)
SET(CMAKE_CXX_EXTENSIONS ON)
ENDIF(LMMS_BUILD_WIN32)
SET(FLTK_SKIP_OPENGL TRUE)
SET(FLTK_SKIP_FORMS TRUE)
SET(FLTK_SKIP_IMAGES TRUE)
SET(FLTK_SKIP_MATH TRUE)
IF(MINGW_PREFIX)
SET(FLTK_SKIP_FLUID TRUE)
ENDIF()
IF(NOT FLTK_FOUND)
RETURN()
ENDIF()
IF(MINGW_PREFIX)
SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid")
ENDIF()
@@ -57,13 +44,15 @@ IF(NOT EXISTS ${FLTK_FLUID_EXECUTABLE})
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES("${FLTK_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
${FFTW3F_INCLUDE_DIRS}
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}")
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI)
include_directories(
"${FLTK_INCLUDE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
${FFTW3F_INCLUDE_DIRS}
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}"
"${CMAKE_SOURCE_DIR}/src/3rdparty/mingw-std-threads"
"${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI"
)
ADD_DEFINITIONS(-DPLUGINVERSION) # removes exit confirmation dialogs etc. in MasterUI.fl
add_subdirectory(zynaddsubfx/src/Nio)
@@ -116,24 +105,23 @@ SET(zynaddsubfx_core_SRCS
zynaddsubfx/src/Synth/PADnote.cpp
zynaddsubfx/src/Synth/Resonance.cpp
zynaddsubfx/src/Synth/SUBnote.cpp
)
)
add_library(ZynAddSubFxCoreObjs OBJECT LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
add_library(ZynAddSubFxCore INTERFACE)
target_sources(ZynAddSubFxCore INTERFACE
$<TARGET_OBJECTS:ZynAddSubFxCoreObjs>
$<TARGET_OBJECTS:zynaddsubfx_nio>
)
IF(LMMS_BUILD_LINUX)
ADD_LIBRARY(ZynAddSubFxCore MODULE LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
ELSE()
ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS})
ENDIF()
TARGET_LINK_LIBRARIES(ZynAddSubFxCore zynaddsubfx_nio ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread)
TARGET_LINK_LIBRARIES(ZynAddSubFxCore Qt5::Widgets Qt5::Xml)
IF(LMMS_BUILD_WIN32)
TARGET_LINK_LIBRARIES(ZynAddSubFxCore -lws2_32)
INSTALL(TARGETS ZynAddSubFxCore RUNTIME DESTINATION "${PLUGIN_DIR}")
ELSE(LMMS_BUILD_WIN32)
INSTALL(TARGETS ZynAddSubFxCore LIBRARY DESTINATION "${PLUGIN_DIR}")
ENDIF(LMMS_BUILD_WIN32)
target_link_libraries(ZynAddSubFxCore INTERFACE
${FFTW3F_LIBRARIES}
${QT_LIBRARIES}
Qt5::Widgets
Qt5::Xml
Threads::Threads
ZLIB::ZLIB
)
LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/..")
IF(LMMS_BUILD_LINUX)
@@ -144,10 +132,11 @@ ELSE()
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
ENDIF()
BUILD_PLUGIN(zynaddsubfx ZynAddSubFx.cpp ZynAddSubFx.h MOCFILES ZynAddSubFx.h EMBEDDED_RESOURCES artwork.png logo.png)
TARGET_LINK_LIBRARIES(zynaddsubfx -lZynAddSubFxCore)
ADD_DEPENDENCIES(zynaddsubfx ZynAddSubFxCore)
target_link_libraries(zynaddsubfx ZynAddSubFxCore)
IF(WIN32)
if(MSVC)
set(WINRC "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc")
elseif(WIN32)
SET(WINRC "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj")
ADD_CUSTOM_COMMAND(OUTPUT "${WINRC}"
COMMAND "${CMAKE_RC_COMPILER}"
@@ -155,14 +144,19 @@ IF(WIN32)
"-o\"${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj\""
"-i\"${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc\""
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc")
ENDIF(WIN32)
endif()
# Use libraries in non-standard directories (e.g., another version of Qt)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ADD_SUBDIRECTORY("${LMMS_SOURCE_DIR}/src/common" common)
ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${LMMS_COMMON_SRCS} "${WINRC}")
add_executable(RemoteZynAddSubFx
RemoteZynAddSubFx.cpp
${LMMS_COMMON_SRCS}
"${WINRC}"
$<TARGET_OBJECTS:zynaddsubfx_gui>
)
INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}")
# Needed to deploy dependencies of RemoteZynAddSubFx
SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "RemoteZynAddSubFx")
@@ -182,8 +176,7 @@ IF(FLTK_CONFIG AND NOT (LMMS_BUILD_APPLE OR LMMS_BUILD_WIN32))
STRING(REPLACE " " ";" FLTK_FILTERED_LDFLAGS ${FLTK_FILTERED_LDFLAGS})
LIST(REMOVE_ITEM FLTK_FILTERED_LDFLAGS -lX11)
ENDIF()
TARGET_LINK_LIBRARIES(RemoteZynAddSubFx zynaddsubfx_gui -lZynAddSubFxCore ${FLTK_FILTERED_LDFLAGS} -lpthread )
ADD_DEPENDENCIES(RemoteZynAddSubFx ZynAddSubFxCore)
target_link_libraries(RemoteZynAddSubFx ZynAddSubFxCore ${FLTK_FILTERED_LDFLAGS})
if(LMMS_HAVE_LIBRT)
target_link_libraries(RemoteZynAddSubFx rt)
@@ -199,13 +192,6 @@ ENDIF(LMMS_BUILD_WIN32)
IF(LMMS_BUILD_WIN32)
add_custom_command(
TARGET ZynAddSubFxCore
POST_BUILD
COMMAND "${STRIP_COMMAND}" "$<TARGET_FILE:ZynAddSubFxCore>"
VERBATIM
COMMAND_EXPAND_LISTS
)
add_custom_command(
TARGET RemoteZynAddSubFx
POST_BUILD

View File

@@ -22,19 +22,25 @@
*
*/
#include <lmmsconfig.h>
#include "LocalZynAddSubFx.h"
#include "zynaddsubfx/src/Misc/Util.h"
#include <unistd.h>
#include <ctime>
#include "LocalZynAddSubFx.h"
#include "lmmsconfig.h"
#ifdef LMMS_BUILD_WIN32
# include <wchar.h>
# include "IoHelper.h"
#else
# include <unistd.h>
#endif
#include "MidiEvent.h"
#include "zynaddsubfx/src/Nio/NulEngine.h"
#include "zynaddsubfx/src/Misc/Master.h"
#include "zynaddsubfx/src/Misc/Part.h"
#include "zynaddsubfx/src/Misc/Util.h"
// Global variable in zynaddsubfx/src/globals.h
SYNTH_T* synth = nullptr;
@@ -53,14 +59,6 @@ LocalZynAddSubFx::LocalZynAddSubFx() :
{
if( s_instanceCount == 0 )
{
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION
// (non-portable) initialization of statically linked pthread library
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif // LMMS_BUILD_WIN32
initConfig();
synth = new SYNTH_T;
@@ -143,14 +141,20 @@ void LocalZynAddSubFx::loadXML( const std::string & _filename )
{
char * f = strdup( _filename.c_str() );
pthread_mutex_lock( &m_master->mutex );
m_master->defaults();
m_master->loadXML( f );
pthread_mutex_unlock( &m_master->mutex );
{
const auto lock = std::lock_guard{m_master->mutex};
m_master->defaults();
m_master->loadXML( f );
}
m_master->applyparameters();
#ifdef LMMS_BUILD_WIN32
_wunlink(toWString(_filename).c_str());
#else
unlink( f );
#endif
free( f );
}
@@ -161,10 +165,11 @@ void LocalZynAddSubFx::loadPreset( const std::string & _filename, int _part )
{
char * f = strdup( _filename.c_str() );
pthread_mutex_lock( &m_master->mutex );
m_master->part[_part]->defaultsinstrument();
m_master->part[_part]->loadXMLinstrument( f );
pthread_mutex_unlock( &m_master->mutex );
{
const auto lock = std::lock_guard{m_master->mutex};
m_master->part[_part]->defaultsinstrument();
m_master->part[_part]->loadXMLinstrument( f );
}
m_master->applyparameters();
@@ -262,8 +267,13 @@ void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event )
void LocalZynAddSubFx::processAudio( sampleFrame * _out )
{
#ifdef _MSC_VER
const auto outputl = static_cast<float*>(_alloca(synth->buffersize * sizeof(float)));
const auto outputr = static_cast<float*>(_alloca(synth->buffersize * sizeof(float)));
#else
float outputl[synth->buffersize];
float outputr[synth->buffersize];
#endif
m_master->GetAudioOutSamples( synth->buffersize, synth->samplerate, outputl, outputr );

View File

@@ -22,17 +22,19 @@
*
*/
#include "RemoteZynAddSubFx.h"
#include <lmmsconfig.h>
#ifdef LMMS_BUILD_WIN32
#include <winsock2.h>
#endif
#include <queue>
#include "ThreadShims.h"
#undef CursorShape // is, by mistake, not undefed in FL
#include "RemotePluginClient.h"
#include "RemoteZynAddSubFx.h"
#include "LocalZynAddSubFx.h"
#include "zynaddsubfx/src/Nio/Nio.h"
@@ -60,12 +62,12 @@ public:
sendMessage( IdInitDone );
waitForMessage( IdInitDone );
pthread_mutex_init( &m_guiMutex, nullptr );
pthread_create( &m_messageThreadHandle, nullptr, messageLoop, this );
m_messageThread = std::thread{&RemoteZynAddSubFx::messageLoop, this};
}
~RemoteZynAddSubFx() override
{
m_messageThread.join();
Nio::stop();
}
@@ -84,9 +86,8 @@ public:
message m;
while( ( m = receiveMessage() ).id != IdQuit )
{
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
processMessage( m );
pthread_mutex_unlock( &m_master->mutex );
}
m_guiExit = true;
}
@@ -102,9 +103,10 @@ public:
case IdHideUI:
case IdLoadSettingsFromFile:
case IdLoadPresetFile:
pthread_mutex_lock( &m_guiMutex );
m_guiMessages.push( _m );
pthread_mutex_unlock( &m_guiMutex );
{
const auto lock = std::lock_guard{m_guiMutex};
m_guiMessages.push( _m );
}
break;
case IdSaveSettingsToFile:
@@ -144,22 +146,13 @@ public:
LocalZynAddSubFx::processAudio( _out );
}
static void * messageLoop( void * _arg )
{
auto _this = static_cast<RemoteZynAddSubFx*>(_arg);
_this->messageLoop();
return nullptr;
}
void guiLoop();
private:
const int m_guiSleepTime;
pthread_t m_messageThreadHandle;
pthread_mutex_t m_guiMutex;
std::thread m_messageThread;
std::mutex m_guiMutex;
std::queue<RemotePluginClient::message> m_guiMessages;
bool m_guiExit;
@@ -189,12 +182,11 @@ void RemoteZynAddSubFx::guiLoop()
}
if( exitProgram == 1 )
{
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
sendMessage( IdHideUI );
exitProgram = 0;
pthread_mutex_unlock( &m_master->mutex );
}
pthread_mutex_lock( &m_guiMutex );
const auto lock = std::lock_guard{m_guiMutex};
while( m_guiMessages.size() )
{
RemotePluginClient::message m = m_guiMessages.front();
@@ -219,9 +211,8 @@ void RemoteZynAddSubFx::guiLoop()
{
ui->refresh_master_ui();
}
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
sendMessage( IdLoadSettingsFromFile );
pthread_mutex_unlock( &m_master->mutex );
break;
}
@@ -235,9 +226,8 @@ void RemoteZynAddSubFx::guiLoop()
ui->updatepanel();
ui->refresh_master_ui();
}
pthread_mutex_lock( &m_master->mutex );
const auto lock = std::lock_guard{m_master->mutex};
sendMessage( IdLoadPresetFile );
pthread_mutex_unlock( &m_master->mutex );
break;
}
@@ -245,7 +235,6 @@ void RemoteZynAddSubFx::guiLoop()
break;
}
}
pthread_mutex_unlock( &m_guiMutex );
}
Fl::flush();
@@ -271,15 +260,6 @@ int main( int _argc, char * * _argv )
const auto pollParentThread = PollParentThread{};
#endif
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION
// (non-portable) initialization of statically linked pthread library
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif // LMMS_BUILD_WIN32
#ifdef SYNC_WITH_SHM_FIFO
RemoteZynAddSubFx * remoteZASF =
new RemoteZynAddSubFx( _argv[1], _argv[2] );
@@ -291,14 +271,6 @@ int main( int _argc, char * * _argv )
delete remoteZASF;
#ifdef LMMS_BUILD_WIN32
#ifndef __WINPTHREADS_VERSION
pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();
#endif
#endif // LMMS_BUILD_WIN32
return 0;
}

View File

@@ -0,0 +1,9 @@
#include <condition_variable>
#include <mutex>
#include <thread>
#if defined(__MINGW32__) && !defined(_GLIBCXX_HAS_GTHREADS)
# include <mingw.condition_variable.h>
# include <mingw.mutex.h>
# include <mingw.thread.h>
#endif