Merge pull request #659 from diizy/organic

Organic: update artwork, add harmonic knobs to control harmonic of each ...
This commit is contained in:
Tobias Doerffel
2014-04-29 23:56:01 +02:00
7 changed files with 177 additions and 50 deletions

View File

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

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -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,9 +169,9 @@ 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_detuneModel.saveSettings( _doc, _this, "detune"
m_osc[i]->m_harmModel.saveSettings( _doc, _this, "newharmonic" + is );
m_osc[i]->m_detuneModel.saveSettings( _doc, _this, "newdetune"
+ is );
m_osc[i]->m_oscModel.saveSettings( _doc, _this, "wavetype"
+ is );
@@ -163,9 +190,25 @@ void organicInstrument::loadSettings( const QDomElement & _this )
{
QString is = QString::number( i );
m_osc[i]->m_volModel.loadSettings( _this, "vol" + is );
m_osc[i]->m_detuneModel.loadSettings( _this, "detune" + is );
if( _this.hasAttribute( "detune" + is ) )
{
m_osc[i]->m_detuneModel.setValue( _this.attribute( "detune" ).toInt() * 12 );
}
else
{
m_osc[i]->m_detuneModel.loadSettings( _this, "newdetune" + 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" );
@@ -374,7 +417,8 @@ public:
organicInstrumentView::organicInstrumentView( Instrument * _instrument,
QWidget * _parent ) :
InstrumentView( _instrument, _parent )
InstrumentView( _instrument, _parent ),
m_oscKnobs( NULL )
{
organicInstrument * oi = castModel<organicInstrument>();
@@ -390,6 +434,7 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument,
m_fx1Knob->setFixedSize( 37, 47 );
m_fx1Knob->setHintText( tr( "Distortion:" ) + " ", QString() );
m_fx1Knob->setObjectName( "fx1Knob" );
m_fx1Knob->setWhatsThis( tr( "The distortion knob adds distortion to the output of the instrument. " ) );
// setup volume-knob
m_volKnob = new organicKnob( this );
@@ -398,6 +443,8 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument,
m_volKnob->setFixedSize( 37, 47 );
m_volKnob->setHintText( tr( "Volume:" ) + " ", "%" );
m_volKnob->setObjectName( "volKnob" );
m_volKnob->setWhatsThis( tr( "The volume knob controls the volume of the output of the instrument. "
"It is cumulative with the instrument window's volume control. " ) );
// randomise
m_randBtn = new pixmapButton( this, tr( "Randomise" ) );
@@ -406,7 +453,9 @@ organicInstrumentView::organicInstrumentView( Instrument * _instrument,
"randomise_pressed" ) );
m_randBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
"randomise" ) );
m_randBtn->setWhatsThis( tr( "The randomize button randomizes all knobs except the harmonics,"
"main volume and distortion knobs. ") );
connect( m_randBtn, SIGNAL ( clicked() ),
oi, SLOT( randomiseSettings() ) );
@@ -429,26 +478,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
@@ -465,25 +528,38 @@ void organicInstrumentView::modelChanged()
panKnob->setHintText( tr("Osc %1 panning:").arg(
i + 1 ) + " ", "" );
// setup knob for left fine-detuning
// setup knob for fine-detuning
knob * detuneKnob = new organicKnob( this );
detuneKnob->move( x + i * colWidth, y + rowHeight*3 );
detuneKnob->setHintText( tr( "Osc %1 fine detuning "
"left:" ).arg( i + 1 )
detuneKnob->setHintText( tr( "Osc %1 stereo detuning" ).arg( i + 1 )
+ " ", " " +
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,11 +571,13 @@ 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,
this, tr( "Osc %1 panning" ).arg( _index + 1 ) ),
m_detuneModel( 0.0f, -100.0f, 100.0f, 1.0f,
m_detuneModel( 0.0f, -1200.0f, 1200.0f, 1.0f,
this, tr( "Osc %1 fine detuning left" ).arg( _index + 1 ) )
{
}
@@ -547,11 +625,11 @@ void OscillatorObject::updateVolume()
void OscillatorObject::updateDetuning()
{
m_detuningLeft = powf( 2.0f, m_harmonic
+ (float)m_detuneModel.value() / 100.0f ) /
m_detuningLeft = powf( 2.0f, organicInstrument::s_harmonics[ static_cast<int>( m_harmModel.value() ) ]
+ (float)m_detuneModel.value() * CENT ) /
engine::mixer()->processingSampleRate();
m_detuningRight = powf( 2.0f, m_harmonic
- (float)m_detuneModel.value() / 100.0f ) /
m_detuningRight = powf( 2.0f, organicInstrument::s_harmonics[ static_cast<int>( m_harmModel.value() ) ]
- (float)m_detuneModel.value() * CENT ) /
engine::mixer()->processingSampleRate();
}

View File

@@ -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,38 @@ 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"
};
const float CENT = 1.0f / 1200.0f;
class OscillatorObject : public Model
{
@@ -45,11 +79,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 +124,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 +136,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 +160,8 @@ private:
virtual PluginView * instantiateView( QWidget * _parent );
float m_harmonics [18];
private slots:
void updateAllDetuning();
@@ -144,10 +181,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 +197,8 @@ private:
OscillatorKnobs()
{
}
knob * m_harmKnob;
knob * m_volKnob;
knob * m_oscKnob;
knob * m_panKnob;
@@ -171,8 +212,11 @@ private:
pixmapButton * m_randBtn;
int m_numOscillators;
static QPixmap * s_artwork;
protected slots:
void updateKnobHint();
};

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB