123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- /*
- * Watsyn.h - a 4-oscillator modulating wavetable synth
- *
- * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
- *
- * 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 WATSYN_H
- #define WATSYN_H
- #include "Instrument.h"
- #include "InstrumentView.h"
- #include "Graph.h"
- #include "AutomatableModel.h"
- #include "AutomatableButton.h"
- #include "TempoSyncKnob.h"
- #include "NotePlayHandle.h"
- #include "PixmapButton.h"
- #include <samplerate.h>
- #include "MemoryManager.h"
- #define makeknob( name, x, y, hint, unit, oname ) \
- name = new Knob( knobStyled, this ); \
- name ->move( x, y ); \
- name ->setHintText( hint, unit ); \
- name ->setObjectName( oname ); \
- name ->setFixedSize( 19, 19 );
- #define maketsknob( name, x, y, hint, unit, oname ) \
- name = new TempoSyncKnob( knobStyled, this ); \
- name ->move( x, y ); \
- name ->setHintText( hint, unit ); \
- name ->setObjectName( oname ); \
- name ->setFixedSize( 19, 19 );
- #define A1ROW 26
- #define A2ROW 49
- #define B1ROW 72
- #define B2ROW 95
- const int GRAPHLEN = 220; // don't change - must be same as the size of the widget
- const int WAVERATIO = 32; // oversampling ratio
- const int WAVELEN = GRAPHLEN * WAVERATIO;
- const int PMOD_AMT = WAVELEN / 2;
- const int MOD_MIX = 0;
- const int MOD_AM = 1;
- const int MOD_RM = 2;
- const int MOD_PM = 3;
- const int NUM_MODS = 4;
- const int A1_OSC = 0;
- const int A2_OSC = 1;
- const int B1_OSC = 2;
- const int B2_OSC = 3;
- const int NUM_OSCS = 4;
- class WatsynInstrument;
- class WatsynObject
- {
- MM_OPERATORS
- public:
- WatsynObject( float * _A1wave, float * _A2wave,
- float * _B1wave, float * _B2wave,
- int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames,
- WatsynInstrument * _w );
- virtual ~WatsynObject();
- void renderOutput( fpp_t _frames );
- inline sampleFrame * abuf() const
- {
- return m_abuf;
- }
- inline sampleFrame * bbuf() const
- {
- return m_bbuf;
- }
- inline sample_rate_t samplerate() const
- {
- return m_samplerate;
- }
- private:
- int m_amod;
- int m_bmod;
- const sample_rate_t m_samplerate;
- NotePlayHandle * m_nph;
- fpp_t m_fpp;
- WatsynInstrument * m_parent;
- sampleFrame * m_abuf;
- sampleFrame * m_bbuf;
- float m_lphase [NUM_OSCS];
- float m_rphase [NUM_OSCS];
- float m_A1wave [WAVELEN];
- float m_A2wave [WAVELEN];
- float m_B1wave [WAVELEN];
- float m_B2wave [WAVELEN];
- };
- class WatsynInstrument : public Instrument
- {
- Q_OBJECT
- public:
- WatsynInstrument( InstrumentTrack * _instrument_track );
- virtual ~WatsynInstrument();
- virtual void playNote( NotePlayHandle * _n,
- sampleFrame * _working_buffer );
- virtual void deleteNotePluginData( NotePlayHandle * _n );
- virtual void saveSettings( QDomDocument & _doc,
- QDomElement & _this );
- virtual void loadSettings( const QDomElement & _this );
- virtual QString nodeName() const;
- virtual f_cnt_t desiredReleaseFrames() const
- {
- return( 64 );
- }
- virtual PluginView * instantiateView( QWidget * _parent );
- public slots:
- void updateVolumes();
- void updateFreqA1();
- void updateFreqA2();
- void updateFreqB1();
- void updateFreqB2();
- void updateWaveA1();
- void updateWaveA2();
- void updateWaveB1();
- void updateWaveB2();
- protected:
- float m_lvol [NUM_OSCS];
- float m_rvol [NUM_OSCS];
- float m_lfreq [NUM_OSCS];
- float m_rfreq [NUM_OSCS];
- private:
- inline float leftCh( float _vol, float _pan )
- {
- return ( _pan <= 0 ? 1.0 : 1.0 - ( _pan / 100.0 ) ) * _vol / 100.0;
- }
- inline float rightCh( float _vol, float _pan )
- {
- return ( _pan >= 0 ? 1.0 : 1.0 + ( _pan / 100.0 ) ) * _vol / 100.0;
- }
- // memcpy utilizing libsamplerate (src) for sinc interpolation
- inline void srccpy( float * _dst, float * _src )
- {
- int err;
- const int margin = 64;
-
- // copy to temp array
- float tmps [ GRAPHLEN + margin ]; // temp array in stack
- float * tmp = &tmps[0];
- memcpy( tmp, _src, sizeof( float ) * GRAPHLEN );
- memcpy( tmp + GRAPHLEN, _src, sizeof( float ) * margin );
- SRC_STATE * src_state = src_new( SRC_SINC_FASTEST, 1, &err );
- SRC_DATA src_data;
- src_data.data_in = tmp;
- src_data.input_frames = GRAPHLEN + margin;
- src_data.data_out = _dst;
- src_data.output_frames = WAVELEN;
- src_data.src_ratio = static_cast<double>( WAVERATIO );
- src_data.end_of_input = 0;
- err = src_process( src_state, &src_data );
- if( err ) { qDebug( "Watsyn SRC error: %s", src_strerror( err ) ); }
- src_delete( src_state );
- }
- // memcpy utilizing cubic interpolation
- /* inline void cipcpy( float * _dst, float * _src )
- {
- // calculate cyclic tangents
- float tang[GRAPHLEN];
- tang[0] = ( _src[1] - _src[ GRAPHLEN - 1] ) / 2;
- tang[ GRAPHLEN - 1 ] = ( _src[0] - _src[ GRAPHLEN - 2 ] ) / 2;
- for( int i = 1; i < GRAPHLEN-1; i++ )
- {
- tang[i] = ( _src[i+1] - _src[i-1] ) / 2;
- }
-
- // calculate cspline
- for( int i=0; i < WAVELEN; i++ )
- {
- const float s1 = _src[ i / WAVERATIO ];
- const float s2 = _src[ ( i / WAVERATIO + 1 ) % GRAPHLEN ];
- const float m1 = tang[ i / WAVERATIO ];
- const float m2 = tang[ ( i / WAVERATIO + 1 ) % GRAPHLEN ];
-
- const float x = static_cast<float>( i % WAVERATIO ) / WAVERATIO;
- const float x2 = x * x;
- const float x3 = x * x * x;
-
- _dst[i] = ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) +
- ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ) +
- ( ( x3 - x2 * 2 + x ) * m1 ) +
- ( ( x3 - x2 ) * m2 );
- }
- }*/
- FloatModel a1_vol;
- FloatModel a2_vol;
- FloatModel b1_vol;
- FloatModel b2_vol;
- FloatModel a1_pan;
- FloatModel a2_pan;
- FloatModel b1_pan;
- FloatModel b2_pan;
- FloatModel a1_mult;
- FloatModel a2_mult;
- FloatModel b1_mult;
- FloatModel b2_mult;
- FloatModel a1_ltune;
- FloatModel a2_ltune;
- FloatModel b1_ltune;
- FloatModel b2_ltune;
- FloatModel a1_rtune;
- FloatModel a2_rtune;
- FloatModel b1_rtune;
- FloatModel b2_rtune;
- graphModel a1_graph;
- graphModel a2_graph;
- graphModel b1_graph;
- graphModel b2_graph;
- FloatModel m_abmix;
- FloatModel m_envAmt;
- TempoSyncKnobModel m_envAtt;
- TempoSyncKnobModel m_envHold;
- TempoSyncKnobModel m_envDec;
- FloatModel m_xtalk;
- IntModel m_amod;
- IntModel m_bmod;
- IntModel m_selectedGraph;
-
- float A1_wave [WAVELEN];
- float A2_wave [WAVELEN];
- float B1_wave [WAVELEN];
- float B2_wave [WAVELEN];
- friend class WatsynObject;
- friend class WatsynView;
- };
- class WatsynView : public InstrumentViewFixedSize
- {
- Q_OBJECT
- public:
- WatsynView( Instrument * _instrument,
- QWidget * _parent );
- virtual ~WatsynView();
- protected slots:
- void updateLayout();
- void sinWaveClicked();
- void triWaveClicked();
- void sawWaveClicked();
- void sqrWaveClicked();
- void smoothClicked();
- void normalizeClicked();
- void invertClicked();
- void phaseLeftClicked();
- void phaseRightClicked();
- void loadClicked();
- private:
- virtual void modelChanged();
- // knobs
- Knob * a1_volKnob;
- Knob * a2_volKnob;
- Knob * b1_volKnob;
- Knob * b2_volKnob;
- Knob * a1_panKnob;
- Knob * a2_panKnob;
- Knob * b1_panKnob;
- Knob * b2_panKnob;
- Knob * a1_multKnob;
- Knob * a2_multKnob;
- Knob * b1_multKnob;
- Knob * b2_multKnob;
- Knob * a1_ltuneKnob;
- Knob * a2_ltuneKnob;
- Knob * b1_ltuneKnob;
- Knob * b2_ltuneKnob;
- Knob * a1_rtuneKnob;
- Knob * a2_rtuneKnob;
- Knob * b1_rtuneKnob;
- Knob * b2_rtuneKnob;
- Knob * m_abmixKnob;
- Knob * m_envAmtKnob;
- TempoSyncKnob * m_envAttKnob;
- TempoSyncKnob * m_envHoldKnob;
- TempoSyncKnob * m_envDecKnob;
- Knob * m_xtalkKnob;
- automatableButtonGroup * m_selectedGraphGroup;
- automatableButtonGroup * m_aModGroup;
- automatableButtonGroup * m_bModGroup;
- Graph * a1_graph;
- Graph * a2_graph;
- Graph * b1_graph;
- Graph * b2_graph;
- PixmapButton * m_sinWaveButton;
- PixmapButton * m_triWaveButton;
- PixmapButton * m_sawWaveButton;
- PixmapButton * m_sqrWaveButton;
- PixmapButton * m_normalizeButton;
- PixmapButton * m_invertButton;
- PixmapButton * m_smoothButton;
- PixmapButton * m_phaseLeftButton;
- PixmapButton * m_phaseRightButton;
- PixmapButton * m_loadButton;
- };
- #endif
|