Organic: update artwork, add harmonic knobs to control harmonic of each oscillator
@@ -545,24 +545,29 @@ AudioFileProcessorView knob {
|
||||
}
|
||||
|
||||
organicInstrumentView knob {
|
||||
color: rgb(205, 16, 216);
|
||||
qproperty-outerColor: rgb(23, 9, 24);
|
||||
/*qproperty-outerColor: rgb(64, 21, 67);*/
|
||||
color: rgb(124, 207, 98);
|
||||
qproperty-outerColor: rgb(13, 42, 4);
|
||||
qproperty-innerRadius: 2;
|
||||
qproperty-outerRadius: 8.7;
|
||||
qproperty-outerRadius: 7.5;
|
||||
qproperty-centerPointX: 10.5;
|
||||
qproperty-centerPointY: 10.5;
|
||||
qproperty-lineWidth: 2;
|
||||
qproperty-lineWidth: 1.5;
|
||||
}
|
||||
|
||||
organicInstrumentView knob#harmKnob {
|
||||
color: rgb(205, 98, 216);
|
||||
qproperty-outerColor: rgb(18, 4, 18);
|
||||
}
|
||||
|
||||
organicInstrumentView knob#fx1Knob,
|
||||
organicInstrumentView knob#volKnob {
|
||||
color: rgb(157, 157, 157);
|
||||
qproperty-outerColor: rgb(37, 37, 37);
|
||||
qproperty-innerRadius: 4;
|
||||
qproperty-outerRadius: 11.2;
|
||||
qproperty-outerRadius: 10.0;
|
||||
qproperty-centerPointX: 18.5;
|
||||
qproperty-centerPointY: 13.8;
|
||||
qproperty-lineWidth: 3;
|
||||
qproperty-lineWidth: 2;
|
||||
}
|
||||
|
||||
sf2InstrumentView knob {
|
||||
|
||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -42,6 +42,8 @@
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
@@ -62,7 +64,7 @@ Plugin::Descriptor PLUGIN_EXPORT organic_plugin_descriptor =
|
||||
}
|
||||
|
||||
QPixmap * organicInstrumentView::s_artwork = NULL;
|
||||
|
||||
float * organicInstrument::s_harmonics = NULL;
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
@@ -90,6 +92,8 @@ organicInstrument::organicInstrument( InstrumentTrack * _instrument_track ) :
|
||||
// Connect events
|
||||
connect( &m_osc[i]->m_oscModel, SIGNAL( dataChanged() ),
|
||||
m_osc[i], SLOT ( oscButtonChanged() ) );
|
||||
connect( &m_osc[i]->m_harmModel, SIGNAL( dataChanged() ),
|
||||
m_osc[i], SLOT( updateDetuning() ) );
|
||||
connect( &m_osc[i]->m_volModel, SIGNAL( dataChanged() ),
|
||||
m_osc[i], SLOT( updateVolume() ) );
|
||||
connect( &m_osc[i]->m_panModel, SIGNAL( dataChanged() ),
|
||||
@@ -101,14 +105,37 @@ organicInstrument::organicInstrument( InstrumentTrack * _instrument_track ) :
|
||||
|
||||
}
|
||||
|
||||
m_osc[0]->m_harmonic = log2f( 0.5f ); // one octave below
|
||||
/* m_osc[0]->m_harmonic = log2f( 0.5f ); // one octave below
|
||||
m_osc[1]->m_harmonic = log2f( 0.75f ); // a fifth below
|
||||
m_osc[2]->m_harmonic = log2f( 1.0f ); // base freq
|
||||
m_osc[3]->m_harmonic = log2f( 2.0f ); // first overtone
|
||||
m_osc[4]->m_harmonic = log2f( 3.0f ); // second overtone
|
||||
m_osc[5]->m_harmonic = log2f( 4.0f ); // .
|
||||
m_osc[6]->m_harmonic = log2f( 5.0f ); // .
|
||||
m_osc[7]->m_harmonic = log2f( 6.0f ); // .
|
||||
m_osc[7]->m_harmonic = log2f( 6.0f ); // .*/
|
||||
|
||||
if( s_harmonics == NULL )
|
||||
{
|
||||
s_harmonics = new float[ NUM_HARMONICS ];
|
||||
s_harmonics[0] = log2f( 0.5f );
|
||||
s_harmonics[1] = log2f( 0.75f );
|
||||
s_harmonics[2] = log2f( 1.0f );
|
||||
s_harmonics[3] = log2f( 2.0f );
|
||||
s_harmonics[4] = log2f( 3.0f );
|
||||
s_harmonics[5] = log2f( 4.0f );
|
||||
s_harmonics[6] = log2f( 5.0f );
|
||||
s_harmonics[7] = log2f( 6.0f );
|
||||
s_harmonics[8] = log2f( 7.0f );
|
||||
s_harmonics[9] = log2f( 8.0f );
|
||||
s_harmonics[10] = log2f( 9.0f );
|
||||
s_harmonics[11] = log2f( 10.0f );
|
||||
s_harmonics[12] = log2f( 11.0f );
|
||||
s_harmonics[13] = log2f( 12.0f );
|
||||
s_harmonics[14] = log2f( 13.0f );
|
||||
s_harmonics[15] = log2f( 14.0f );
|
||||
s_harmonics[16] = log2f( 15.0f );
|
||||
s_harmonics[17] = log2f( 16.0f );
|
||||
}
|
||||
|
||||
for (int i=0; i < m_numOscillators; i++) {
|
||||
m_osc[i]->updateVolume();
|
||||
@@ -142,8 +169,8 @@ void organicInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
QString is = QString::number( i );
|
||||
m_osc[i]->m_volModel.saveSettings( _doc, _this, "vol" + is );
|
||||
m_osc[i]->m_panModel.saveSettings( _doc, _this, "pan" + is );
|
||||
_this.setAttribute( "harmonic" + is, QString::number(
|
||||
powf( 2.0f, m_osc[i]->m_harmonic ) ) );
|
||||
m_osc[i]->m_harmModel.saveSettings( _doc, _this, "newharmonic" + is );
|
||||
|
||||
m_osc[i]->m_detuneModel.saveSettings( _doc, _this, "detune"
|
||||
+ is );
|
||||
m_osc[i]->m_oscModel.saveSettings( _doc, _this, "wavetype"
|
||||
@@ -166,6 +193,15 @@ void organicInstrument::loadSettings( const QDomElement & _this )
|
||||
m_osc[i]->m_detuneModel.loadSettings( _this, "detune" + is );
|
||||
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 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_osc[i]->m_harmModel.setValue( static_cast<float>( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
m_volModel.loadSettings( _this, "vol" );
|
||||
@@ -429,26 +465,40 @@ organicInstrumentView::~organicInstrumentView()
|
||||
void organicInstrumentView::modelChanged()
|
||||
{
|
||||
organicInstrument * oi = castModel<organicInstrument>();
|
||||
const float y=91.3;
|
||||
const float rowHeight = 26.52f;
|
||||
const float x=53.4;
|
||||
const float colWidth = 23.829f; // 54.4 77.2 220.2
|
||||
|
||||
const float y=91.0f;
|
||||
const float rowHeight = 26.0f;
|
||||
const float x=53.0f;
|
||||
const float colWidth = 24.0f;
|
||||
|
||||
m_numOscillators = oi->m_numOscillators;
|
||||
|
||||
m_fx1Knob->setModel( &oi->m_fx1Model );
|
||||
m_volKnob->setModel( &oi->m_volModel );
|
||||
|
||||
// TODO: Delete existing oscKnobs if they exist
|
||||
if( m_oscKnobs != NULL )
|
||||
{
|
||||
delete[] m_oscKnobs;
|
||||
}
|
||||
|
||||
m_oscKnobs = new OscillatorKnobs[ m_numOscillators ];
|
||||
|
||||
// Create knobs, now that we know how many to make
|
||||
for( int i = 0; i < m_numOscillators; ++i )
|
||||
{
|
||||
// setup harmonic knob
|
||||
knob * harmKnob = new organicKnob( this );
|
||||
harmKnob->move( x + i * colWidth, y - rowHeight );
|
||||
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 );
|
||||
connect( &oi->m_osc[i]->m_oscModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateKnobHint() ) );
|
||||
|
||||
oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ) + " ", QString() );
|
||||
|
||||
// setup volume-knob
|
||||
@@ -473,17 +523,31 @@ void organicInstrumentView::modelChanged()
|
||||
+ " ", " " +
|
||||
tr( "cents" ) );
|
||||
|
||||
m_oscKnobs[i] = OscillatorKnobs( volKnob, oscKnob, panKnob, detuneKnob );
|
||||
m_oscKnobs[i] = OscillatorKnobs( harmKnob, volKnob, oscKnob, panKnob, detuneKnob );
|
||||
|
||||
// Attach to models
|
||||
m_oscKnobs[i].m_volKnob->setModel(
|
||||
&oi->m_osc[i]->m_volModel );
|
||||
m_oscKnobs[i].m_oscKnob->setModel(
|
||||
&oi->m_osc[i]->m_oscModel );
|
||||
m_oscKnobs[i].m_panKnob->setModel(
|
||||
&oi->m_osc[i]->m_panModel );
|
||||
m_oscKnobs[i].m_detuneKnob->setModel(
|
||||
&oi->m_osc[i]->m_detuneModel );
|
||||
m_oscKnobs[i].m_harmKnob->setModel( &oi->m_osc[i]->m_harmModel );
|
||||
m_oscKnobs[i].m_volKnob->setModel( &oi->m_osc[i]->m_volModel );
|
||||
m_oscKnobs[i].m_oscKnob->setModel( &oi->m_osc[i]->m_oscModel );
|
||||
m_oscKnobs[i].m_panKnob->setModel( &oi->m_osc[i]->m_panModel );
|
||||
m_oscKnobs[i].m_detuneKnob->setModel( &oi->m_osc[i]->m_detuneModel );
|
||||
}
|
||||
updateKnobHint();
|
||||
}
|
||||
|
||||
|
||||
void organicInstrumentView::updateKnobHint()
|
||||
{
|
||||
organicInstrument * oi = castModel<organicInstrument>();
|
||||
for( int i = 0; i < m_numOscillators; ++i )
|
||||
{
|
||||
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:" ) + " ", " (" +
|
||||
HARMONIC_NAMES[ static_cast<int>( harm ) ] + ")" );
|
||||
m_oscKnobs[i].m_oscKnob->setHintText( tr( "Osc %1 waveform:" ) + " ", " (" +
|
||||
WAVEFORM_NAMES[ static_cast<int>( wave ) ] + ")" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +559,8 @@ OscillatorObject::OscillatorObject( Model * _parent, int _index ) :
|
||||
m_waveShape( Oscillator::SineWave, 0, Oscillator::NumWaveShapes-1, this ),
|
||||
m_oscModel( 0.0f, 0.0f, 5.0f, 1.0f,
|
||||
this, tr( "Osc %1 waveform" ).arg( _index + 1 ) ),
|
||||
m_harmModel( static_cast<float>( _index ), 0.0f, 17.0f, 1.0f,
|
||||
this, tr( "Osc %1 harmonic" ).arg( _index + 1 ) ),
|
||||
m_volModel( 100.0f, 0.0f, 100.0f, 1.0f,
|
||||
this, tr( "Osc %1 volume" ).arg( _index + 1 ) ),
|
||||
m_panModel( DefaultPanning, PanningLeft, PanningRight, 1.0f,
|
||||
@@ -547,10 +613,10 @@ void OscillatorObject::updateVolume()
|
||||
|
||||
void OscillatorObject::updateDetuning()
|
||||
{
|
||||
m_detuningLeft = powf( 2.0f, m_harmonic
|
||||
m_detuningLeft = powf( 2.0f, organicInstrument::s_harmonics[ static_cast<int>( m_harmModel.value() ) ]
|
||||
+ (float)m_detuneModel.value() / 100.0f ) /
|
||||
engine::mixer()->processingSampleRate();
|
||||
m_detuningRight = powf( 2.0f, m_harmonic
|
||||
m_detuningRight = powf( 2.0f, organicInstrument::s_harmonics[ static_cast<int>( m_harmModel.value() ) ]
|
||||
- (float)m_detuneModel.value() / 100.0f ) /
|
||||
engine::mixer()->processingSampleRate();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* organic.h - additive synthesizer for organ-like sounds
|
||||
*
|
||||
* Copyright (c) 2006-2008 Andreas Brandmaier <andy/at/brandmaier/dot/de>
|
||||
*
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -23,8 +23,10 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ORGANIC_H
|
||||
#define _ORGANIC_H
|
||||
#ifndef ORGANIC_H
|
||||
#define ORGANIC_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentView.h"
|
||||
@@ -37,6 +39,36 @@ class knob;
|
||||
class NotePlayHandle;
|
||||
class pixmapButton;
|
||||
|
||||
const int NUM_HARMONICS = 18;
|
||||
const QString HARMONIC_NAMES[NUM_HARMONICS] = {
|
||||
"Octave below",
|
||||
"Fifth below",
|
||||
"Fundamental",
|
||||
"2nd harmonic",
|
||||
"3rd harmonic",
|
||||
"4th harmonic",
|
||||
"5th harmonic",
|
||||
"6th harmonic",
|
||||
"7th harmonic",
|
||||
"8th harmonic",
|
||||
"9th harmonic",
|
||||
"10th harmonic",
|
||||
"11th harmonic",
|
||||
"12th harmonic",
|
||||
"13th harmonic",
|
||||
"14th harmonic",
|
||||
"15th harmonic",
|
||||
"16th harmonic"
|
||||
};
|
||||
|
||||
const QString WAVEFORM_NAMES[6] = {
|
||||
"Sine wave",
|
||||
"Triangle wave",
|
||||
"Saw wave",
|
||||
"Square wave",
|
||||
"Moog saw wave",
|
||||
"Exponential wave"
|
||||
};
|
||||
|
||||
class OscillatorObject : public Model
|
||||
{
|
||||
@@ -45,11 +77,11 @@ private:
|
||||
int m_numOscillators;
|
||||
IntModel m_waveShape;
|
||||
FloatModel m_oscModel;
|
||||
FloatModel m_harmModel;
|
||||
FloatModel m_volModel;
|
||||
FloatModel m_panModel;
|
||||
FloatModel m_detuneModel;
|
||||
|
||||
float m_harmonic;
|
||||
float m_volumeLeft;
|
||||
float m_volumeRight;
|
||||
// normalized detuning -> x/sampleRate
|
||||
@@ -90,9 +122,10 @@ public:
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
|
||||
virtual QString nodeName() const;
|
||||
|
||||
|
||||
int intRand( int min, int max );
|
||||
|
||||
static float * s_harmonics;
|
||||
|
||||
public slots:
|
||||
void randomiseSettings();
|
||||
@@ -101,17 +134,17 @@ public slots:
|
||||
private:
|
||||
float inline waveshape(float in, float amount);
|
||||
|
||||
|
||||
|
||||
// fast atan, fast rather than accurate
|
||||
inline float fastatan( float x )
|
||||
{
|
||||
return (x / (1.0 + 0.28 * (x * x)));
|
||||
}
|
||||
|
||||
|
||||
int m_numOscillators;
|
||||
|
||||
|
||||
OscillatorObject ** m_osc;
|
||||
|
||||
|
||||
struct oscPtr
|
||||
{
|
||||
Oscillator * oscLeft;
|
||||
@@ -125,6 +158,8 @@ private:
|
||||
|
||||
virtual PluginView * instantiateView( QWidget * _parent );
|
||||
|
||||
float m_harmonics [18];
|
||||
|
||||
private slots:
|
||||
void updateAllDetuning();
|
||||
|
||||
@@ -144,10 +179,13 @@ private:
|
||||
|
||||
struct OscillatorKnobs
|
||||
{
|
||||
OscillatorKnobs( knob * v,
|
||||
OscillatorKnobs(
|
||||
knob * h,
|
||||
knob * v,
|
||||
knob * o,
|
||||
knob * p,
|
||||
knob * dt ) :
|
||||
m_harmKnob( h ),
|
||||
m_volKnob( v ),
|
||||
m_oscKnob( o ),
|
||||
m_panKnob( p ),
|
||||
@@ -157,7 +195,8 @@ private:
|
||||
OscillatorKnobs()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
knob * m_harmKnob;
|
||||
knob * m_volKnob;
|
||||
knob * m_oscKnob;
|
||||
knob * m_panKnob;
|
||||
@@ -171,8 +210,11 @@ private:
|
||||
pixmapButton * m_randBtn;
|
||||
|
||||
int m_numOscillators;
|
||||
|
||||
|
||||
static QPixmap * s_artwork;
|
||||
|
||||
protected slots:
|
||||
void updateKnobHint();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.6 KiB |