~ubuntu-branches/ubuntu/utopic/lmms/utopic

« back to all changes in this revision

Viewing changes to plugins/watsyn/Watsyn.cpp

  • Committer: Package Import Robot
  • Author(s): Israel Dahl
  • Date: 2014-04-30 18:49:37 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20140430184937-hozuuxonlbshciya
Tags: 1.0.1-src-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Watsyn.cpp - a 4-oscillator modulating wavetable synth
3
 
 *
4
 
 * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
5
 
 *
6
 
 * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
7
 
 *
8
 
 * This program is free software; you can redistribute it and/or
9
 
 * modify it under the terms of the GNU General Public
10
 
 * License as published by the Free Software Foundation; either
11
 
 * version 2 of the License, or (at your option) any later version.
12
 
 *
13
 
 * This program is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 
 * General Public License for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU General Public
19
 
 * License along with this program (see COPYING); if not, write to the
20
 
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
 
 * Boston, MA 02110-1301 USA.
22
 
 *
23
 
 */
24
 
 
25
 
#include <QtXml/QDomElement>
26
 
 
27
 
#include "Watsyn.h"
28
 
#include "engine.h"
29
 
#include "InstrumentTrack.h"
30
 
#include "templates.h"
31
 
#include "tooltip.h"
32
 
#include "song.h"
33
 
#include "lmms_math.h"
34
 
 
35
 
#include "embed.cpp"
36
 
 
37
 
extern "C"
38
 
{
39
 
 
40
 
Plugin::Descriptor PLUGIN_EXPORT watsyn_plugin_descriptor =
41
 
{
42
 
        STRINGIFY( PLUGIN_NAME ),
43
 
        "Watsyn",
44
 
        QT_TRANSLATE_NOOP( "pluginBrowser",
45
 
                                "4-oscillator modulatable wavetable synth" ),
46
 
        "Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
47
 
        0x0100,
48
 
        Plugin::Instrument,
49
 
        new PluginPixmapLoader( "logo" ),
50
 
        NULL,
51
 
        NULL
52
 
} ;
53
 
 
54
 
}
55
 
 
56
 
 
57
 
 
58
 
 
59
 
WatsynObject::WatsynObject( float * _A1wave, float * _A2wave,
60
 
                                        float * _B1wave, float * _B2wave,
61
 
                                        int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames,
62
 
                                        WatsynInstrument * _w ) :
63
 
                                m_amod( _amod ),
64
 
                                m_bmod( _bmod ),
65
 
                                m_samplerate( _samplerate ),
66
 
                                m_nph( _nph ),
67
 
                                m_fpp( _frames ),
68
 
                                m_parent( _w )
69
 
{
70
 
        m_abuf = new sampleFrame[_frames];
71
 
        m_bbuf = new sampleFrame[_frames];
72
 
 
73
 
        m_lphase[A1_OSC] = 0.0f;
74
 
        m_lphase[A2_OSC] = 0.0f;
75
 
        m_lphase[B1_OSC] = 0.0f;
76
 
        m_lphase[B2_OSC] = 0.0f;
77
 
 
78
 
        m_rphase[A1_OSC] = 0.0f;
79
 
        m_rphase[A2_OSC] = 0.0f;
80
 
        m_rphase[B1_OSC] = 0.0f;
81
 
        m_rphase[B2_OSC] = 0.0f;
82
 
 
83
 
        // copy wavegraphs to the synth object to prevent race conditions
84
 
 
85
 
        memcpy( &m_A1wave, _A1wave, sizeof( m_A1wave ) );
86
 
        memcpy( &m_A2wave, _A2wave, sizeof( m_A2wave ) );
87
 
        memcpy( &m_B1wave, _B1wave, sizeof( m_B1wave ) );
88
 
        memcpy( &m_B2wave, _B2wave, sizeof( m_B2wave ) );
89
 
}
90
 
 
91
 
 
92
 
 
93
 
WatsynObject::~WatsynObject()
94
 
{
95
 
        delete[] m_abuf;
96
 
        delete[] m_bbuf;
97
 
}
98
 
 
99
 
 
100
 
void WatsynObject::renderOutput( fpp_t _frames )
101
 
{
102
 
        if( m_abuf == NULL )
103
 
                m_abuf = new sampleFrame[m_fpp];
104
 
        if( m_bbuf == NULL )
105
 
                m_bbuf = new sampleFrame[m_fpp];
106
 
 
107
 
        for( fpp_t frame = 0; frame < _frames; frame++ )
108
 
        {
109
 
                // put phases of 1-series oscs into variables because phase modulation might happen
110
 
                float A1_lphase = m_lphase[A1_OSC];
111
 
                float A1_rphase = m_rphase[A1_OSC];
112
 
                float B1_lphase = m_lphase[B1_OSC];
113
 
                float B1_rphase = m_rphase[B1_OSC];
114
 
 
115
 
                /////////////   A-series   /////////////////
116
 
 
117
 
                // A2
118
 
                sample_t A2_L = m_A2wave[ static_cast<int>( m_lphase[A2_OSC] ) ] * m_parent->m_lvol[A2_OSC];
119
 
                                                        /*interpolate( m_A2wave[ static_cast<int>( m_lphase[A2_OSC] ) % WAVELEN ],
120
 
                                                        m_A2wave[ static_cast<int>( m_lphase[A2_OSC] + 1 ) % WAVELEN ],
121
 
                                                        fraction( m_lphase[A2_OSC] ) ) * m_parent->m_lvol[A2_OSC];*/
122
 
                sample_t A2_R = m_A2wave[ static_cast<int>( m_rphase[A2_OSC] ) ] * m_parent->m_rvol[A2_OSC];
123
 
                /*interpolate( m_A2wave[ static_cast<int>( m_rphase[A2_OSC] ) % WAVELEN ],
124
 
                                                        m_A2wave[ static_cast<int>( m_rphase[A2_OSC] + 1 ) % WAVELEN ],
125
 
                                                        fraction( m_rphase[A2_OSC] ) ) * m_parent->m_rvol[A2_OSC];*/
126
 
                // if phase mod, add to phases
127
 
                if( m_amod == MOD_PM )
128
 
                {
129
 
                        A1_lphase = fmodf( A1_lphase + A2_L * PMOD_AMT, WAVELEN );
130
 
                        if( A1_lphase < 0 ) A1_lphase += WAVELEN;
131
 
                        A1_rphase = fmodf( A1_rphase + A2_R * PMOD_AMT, WAVELEN );
132
 
                        if( A1_rphase < 0 ) A1_rphase += WAVELEN;
133
 
                }
134
 
                // A1
135
 
                sample_t A1_L = interpolate( m_A1wave[ static_cast<int>( A1_lphase ) ],
136
 
                                                        m_A1wave[ static_cast<int>( A1_lphase + 1 ) % WAVELEN ],
137
 
                                                        fraction( A1_lphase ) ) * m_parent->m_lvol[A1_OSC];
138
 
                sample_t A1_R = interpolate( m_A1wave[ static_cast<int>( A1_rphase ) ],
139
 
                                                        m_A1wave[ static_cast<int>( A1_rphase + 1 ) % WAVELEN ],
140
 
                                                        fraction( A1_rphase ) ) * m_parent->m_rvol[A1_OSC];
141
 
 
142
 
                /////////////   B-series   /////////////////
143
 
 
144
 
                // B2
145
 
                sample_t B2_L = m_B2wave[ static_cast<int>( m_lphase[B2_OSC] ) ] * m_parent->m_lvol[B2_OSC];
146
 
                                                /*interpolate( m_B2wave[ static_cast<int>( m_lphase[B2_OSC] ) % WAVELEN ],
147
 
                                                m_B2wave[ static_cast<int>( m_lphase[B2_OSC] + 1 ) % WAVELEN ],
148
 
                                                fraction( m_lphase[B2_OSC] ) ) * m_parent->m_lvol[B2_OSC];*/
149
 
                sample_t B2_R = m_B2wave[ static_cast<int>( m_rphase[B2_OSC] ) ] * m_parent->m_rvol[B2_OSC];
150
 
                                                /*interpolate( m_B2wave[ static_cast<int>( m_rphase[B2_OSC] ) % WAVELEN ],
151
 
                                                m_B2wave[ static_cast<int>( m_rphase[B2_OSC] + 1 ) % WAVELEN ],
152
 
                                                fraction( m_rphase[B2_OSC] ) ) * m_parent->m_rvol[B2_OSC];*/
153
 
 
154
 
                // if crosstalk active, add a1
155
 
                const float xt = m_parent->m_xtalk.value();
156
 
                if( xt > 0.0 )
157
 
                {
158
 
                        B2_L += ( A1_L * xt ) / 100.0f;
159
 
                        B2_R += ( A1_R * xt ) / 100.0f;
160
 
                }
161
 
 
162
 
                // if phase mod, add to phases
163
 
                if( m_bmod == MOD_PM )
164
 
                {
165
 
                        B1_lphase = fmodf( B1_lphase + B2_L * PMOD_AMT, WAVELEN );
166
 
                        if( B1_lphase < 0 ) B1_lphase += WAVELEN;
167
 
                        B1_rphase = fmodf( B1_rphase + B2_R * PMOD_AMT, WAVELEN );
168
 
                        if( B1_rphase < 0 ) B1_rphase += WAVELEN;
169
 
                }
170
 
                // B1
171
 
                sample_t B1_L = interpolate( m_B1wave[ static_cast<int>( B1_lphase ) % WAVELEN ],
172
 
                                                        m_B1wave[ static_cast<int>( B1_lphase + 1 ) % WAVELEN ],
173
 
                                                        fraction( B1_lphase ) ) * m_parent->m_lvol[B1_OSC];
174
 
                sample_t B1_R = interpolate( m_B1wave[ static_cast<int>( B1_rphase ) % WAVELEN ],
175
 
                                                        m_B1wave[ static_cast<int>( B1_rphase + 1 ) % WAVELEN ],
176
 
                                                        fraction( B1_rphase ) ) * m_parent->m_rvol[B1_OSC];
177
 
 
178
 
 
179
 
                // A-series modulation)
180
 
                switch( m_amod )
181
 
                {
182
 
                        case MOD_MIX:
183
 
                                A1_L = ( A1_L + A2_L ) / 2.0;
184
 
                                A1_R = ( A1_R + A2_R ) / 2.0;
185
 
                                break;
186
 
                        case MOD_AM:
187
 
                                A1_L *= qMax( 0.0f, A2_L + 1.0f );
188
 
                                A1_R *= qMax( 0.0f, A2_R + 1.0f );
189
 
                                break;
190
 
                        case MOD_RM:
191
 
                                A1_L *= A2_L;
192
 
                                A1_R *= A2_R;
193
 
                                break;
194
 
                }
195
 
                m_abuf[frame][0] = A1_L;
196
 
                m_abuf[frame][1] = A1_R;
197
 
 
198
 
                // B-series modulation (other than phase mod)
199
 
                switch( m_bmod )
200
 
                {
201
 
                        case MOD_MIX:
202
 
                                B1_L = ( B1_L + B2_L ) / 2.0;
203
 
                                B1_R = ( B1_R + B2_R ) / 2.0;
204
 
                                break;
205
 
                        case MOD_AM:
206
 
                                B1_L *= qMax( 0.0f, B2_L + 1.0f );
207
 
                                B1_R *= qMax( 0.0f, B2_R + 1.0f );
208
 
                                break;
209
 
                        case MOD_RM:
210
 
                                B1_L *= B2_L;
211
 
                                B1_R *= B2_R;
212
 
                                break;
213
 
                }
214
 
                m_bbuf[frame][0] = B1_L;
215
 
                m_bbuf[frame][1] = B1_R;
216
 
 
217
 
                // update phases
218
 
                for( int i = 0; i < NUM_OSCS; i++ )
219
 
                {
220
 
                        m_lphase[i] += ( static_cast<float>( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_lfreq[i] ) ) );
221
 
                        m_lphase[i] = fmodf( m_lphase[i], WAVELEN );
222
 
                        m_rphase[i] += ( static_cast<float>( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_rfreq[i] ) ) );
223
 
                        m_rphase[i] = fmodf( m_rphase[i], WAVELEN );
224
 
                }
225
 
        }
226
 
 
227
 
}
228
 
 
229
 
 
230
 
 
231
 
WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) :
232
 
                Instrument( _instrument_track, &watsyn_plugin_descriptor ),
233
 
 
234
 
                a1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A1" ) ),
235
 
                a2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A2" ) ),
236
 
                b1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume B1" ) ),
237
 
                b2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume B2" ) ),
238
 
 
239
 
                a1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning A1" ) ),
240
 
                a2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning A2" ) ),
241
 
                b1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B1" ) ),
242
 
                b2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B2" ) ),
243
 
 
244
 
                a1_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier A1" ) ),
245
 
                a2_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier A2" ) ),
246
 
                b1_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier B1" ) ),
247
 
                b2_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier B2" ) ),
248
 
 
249
 
                a1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A1" ) ),
250
 
                a2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A2" ) ),
251
 
                b1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune B1" ) ),
252
 
                b2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune B2" ) ),
253
 
 
254
 
                a1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune A1" ) ),
255
 
                a2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune A2" ) ),
256
 
                b1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B1" ) ),
257
 
                b2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B2" ) ),
258
 
 
259
 
                a1_graph( -1.0f, 1.0f, GRAPHLEN, this ),
260
 
                a2_graph( -1.0f, 1.0f, GRAPHLEN, this ),
261
 
                b1_graph( -1.0f, 1.0f, GRAPHLEN, this ),
262
 
                b2_graph( -1.0f, 1.0f, GRAPHLEN, this ),
263
 
 
264
 
                m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ),
265
 
                m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ),
266
 
 
267
 
                m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope attack" ) ),
268
 
                m_envHold( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope hold" ) ),
269
 
                m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope decay" ) ),
270
 
 
271
 
                m_xtalk( 0.0f, 0.0f, 100.0f, 0.1f, this, tr( "A1-B2 Crosstalk" ) ),
272
 
 
273
 
                m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ),
274
 
                m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ),
275
 
 
276
 
                m_selectedGraph( 0, 0, 3, this, tr( "Selected graph" ) )
277
 
{
278
 
        connect( &a1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
279
 
        connect( &a2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
280
 
        connect( &b1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
281
 
        connect( &b2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
282
 
 
283
 
        connect( &a1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
284
 
        connect( &a2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
285
 
        connect( &b1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
286
 
        connect( &b2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
287
 
 
288
 
        connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
289
 
        connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
290
 
        connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
291
 
        connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
292
 
 
293
 
        connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
294
 
        connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
295
 
        connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
296
 
        connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
297
 
 
298
 
        connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
299
 
        connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
300
 
        connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
301
 
        connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) );
302
 
        
303
 
        connect( &a1_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) );
304
 
        connect( &a2_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) );
305
 
        connect( &b1_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) );
306
 
        connect( &b2_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) );
307
 
 
308
 
        a1_graph.setWaveToSine();
309
 
        a2_graph.setWaveToSine();
310
 
        b1_graph.setWaveToSine();
311
 
        b2_graph.setWaveToSine();
312
 
 
313
 
        updateVolumes();
314
 
        updateFreq();
315
 
        updateWaves();
316
 
}
317
 
 
318
 
 
319
 
WatsynInstrument::~WatsynInstrument()
320
 
{
321
 
}
322
 
 
323
 
 
324
 
void WatsynInstrument::playNote( NotePlayHandle * _n,
325
 
                                                sampleFrame * _working_buffer )
326
 
{
327
 
        if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL )
328
 
        {
329
 
                WatsynObject * w = new WatsynObject(
330
 
                                &A1_wave[0],
331
 
                                &A2_wave[0],
332
 
                                &B1_wave[0],
333
 
                                &B2_wave[0],
334
 
                                m_amod.value(), m_bmod.value(),
335
 
                                engine::mixer()->processingSampleRate(), _n,
336
 
                                engine::mixer()->framesPerPeriod(), this );
337
 
 
338
 
                _n->m_pluginData = w;
339
 
        }
340
 
 
341
 
        const fpp_t frames = _n->framesLeftForCurrentPeriod();
342
 
 
343
 
        WatsynObject * w = static_cast<WatsynObject *>( _n->m_pluginData );
344
 
 
345
 
        sampleFrame * abuf = w->abuf();
346
 
        sampleFrame * bbuf = w->bbuf();
347
 
 
348
 
        w-> renderOutput( frames );
349
 
 
350
 
        // envelope parameters
351
 
        const float envAmt = m_envAmt.value();
352
 
        const float envAtt = ( m_envAtt.value() * w->samplerate() ) / 1000.0f;
353
 
        const float envHold = ( m_envHold.value() * w->samplerate() ) / 1000.0f;
354
 
        const float envDec = ( m_envDec.value() * w->samplerate() ) / 1000.0f;
355
 
        const float envLen = envAtt + envDec + envHold;
356
 
        const float tfp_ = static_cast<float>( _n->totalFramesPlayed() );
357
 
 
358
 
        // if sample-exact is enabled, use sample-exact calculations...
359
 
        if( engine::mixer()->currentQualitySettings().sampleExactControllers )
360
 
        {
361
 
                for( fpp_t f=0; f < frames; f++ )
362
 
                {
363
 
                        const float tfp = tfp_ + f;
364
 
                        // handle mixing envelope
365
 
                        float mixvalue = m_abmix.value( f );
366
 
                        if( envAmt != 0.0f && tfp < envLen )
367
 
                        {
368
 
                                if( tfp < envAtt )
369
 
                                {
370
 
                                        mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f );
371
 
                                }
372
 
                                else if ( tfp >= envAtt && tfp < envAtt + envHold )
373
 
                                {
374
 
                                        mixvalue = qBound( -100.0f, mixvalue + envAmt, 100.0f );
375
 
                                }
376
 
                                else
377
 
                                {
378
 
                                        mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - ( envAtt + envHold ) ) / envDec * envAmt ), 100.0f );
379
 
                                }
380
 
                        }
381
 
                        // get knob values in sample-exact way
382
 
                        const float bmix = ( ( mixvalue + 100.0 ) / 200.0 );
383
 
                        const float amix = 1.0 - bmix;
384
 
 
385
 
                        // mix a/b streams according to mixing knob
386
 
                        _working_buffer[f][0] = ( abuf[f][0] * amix ) +
387
 
                                                                        ( bbuf[f][0] * bmix );
388
 
                        _working_buffer[f][1] = ( abuf[f][1] * amix ) +
389
 
                                                                        ( bbuf[f][1] * bmix );
390
 
                }
391
 
        }
392
 
 
393
 
        // if sample-exact is not enabled, use simpler calculations:
394
 
        // if mix envelope is active, and we haven't gone past the envelope end, use envelope-aware calculation...
395
 
        else if( envAmt != 0.0f && tfp_ < envLen )
396
 
        {
397
 
                const float mixvalue_ = m_abmix.value();
398
 
                for( fpp_t f=0; f < frames; f++ )
399
 
                {
400
 
                        float mixvalue = mixvalue_;
401
 
                        const float tfp = tfp_ + f;
402
 
                        // handle mixing envelope
403
 
                        if( tfp < envAtt )
404
 
                        {
405
 
                                mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f );
406
 
                        }
407
 
                        else if ( tfp >= envAtt && tfp < envAtt + envHold )
408
 
                        {
409
 
                                mixvalue = qBound( -100.0f, mixvalue + envAmt, 100.0f );
410
 
                        }
411
 
                        else
412
 
                        {
413
 
                                mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - ( envAtt + envHold ) ) / envDec * envAmt ), 100.0f );
414
 
                        }
415
 
 
416
 
                        // get knob values
417
 
                        const float bmix = ( ( mixvalue + 100.0 ) / 200.0 );
418
 
                        const float amix = 1.0 - bmix;
419
 
 
420
 
                        // mix a/b streams according to mixing knob
421
 
                        _working_buffer[f][0] = ( abuf[f][0] * amix ) +
422
 
                                                                        ( bbuf[f][0] * bmix );
423
 
                        _working_buffer[f][1] = ( abuf[f][1] * amix ) +
424
 
                                                                        ( bbuf[f][1] * bmix );
425
 
                }
426
 
        }
427
 
 
428
 
        // ... mix envelope is inactive or we've past the end of envelope, so use a faster calculation to save cpu
429
 
        else
430
 
        {
431
 
                // get knob values
432
 
                const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 );
433
 
                const float amix = 1.0 - bmix;
434
 
                for( fpp_t f=0; f < frames; f++ )
435
 
                {
436
 
                        // mix a/b streams according to mixing knob
437
 
                        _working_buffer[f][0] = ( abuf[f][0] * amix ) +
438
 
                                                                        ( bbuf[f][0] * bmix );
439
 
                        _working_buffer[f][1] = ( abuf[f][1] * amix ) +
440
 
                                                                        ( bbuf[f][1] * bmix );
441
 
                }
442
 
        }
443
 
 
444
 
        applyRelease( _working_buffer, _n );
445
 
 
446
 
        instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n );
447
 
}
448
 
 
449
 
 
450
 
void WatsynInstrument::deleteNotePluginData( NotePlayHandle * _n )
451
 
{
452
 
        delete static_cast<WatsynObject *>( _n->m_pluginData );
453
 
}
454
 
 
455
 
 
456
 
void WatsynInstrument::saveSettings( QDomDocument & _doc,
457
 
                                                        QDomElement & _this )
458
 
{
459
 
        a1_vol.saveSettings( _doc, _this, "a1_vol" );
460
 
        a2_vol.saveSettings( _doc, _this, "a2_vol" );
461
 
        b1_vol.saveSettings( _doc, _this, "b1_vol" );
462
 
        b2_vol.saveSettings( _doc, _this, "b2_vol" );
463
 
 
464
 
        a1_pan.saveSettings( _doc, _this, "a1_pan" );
465
 
        a2_pan.saveSettings( _doc, _this, "a2_pan" );
466
 
        b1_pan.saveSettings( _doc, _this, "b1_pan" );
467
 
        b2_pan.saveSettings( _doc, _this, "b2_pan" );
468
 
 
469
 
        a1_mult.saveSettings( _doc, _this, "a1_mult" );
470
 
        a2_mult.saveSettings( _doc, _this, "a2_mult" );
471
 
        b1_mult.saveSettings( _doc, _this, "b1_mult" );
472
 
        b2_mult.saveSettings( _doc, _this, "b2_mult" );
473
 
 
474
 
        a1_ltune.saveSettings( _doc, _this, "a1_ltune" );
475
 
        a2_ltune.saveSettings( _doc, _this, "a2_ltune" );
476
 
        b1_ltune.saveSettings( _doc, _this, "b1_ltune" );
477
 
        b2_ltune.saveSettings( _doc, _this, "b2_ltune" );
478
 
 
479
 
        a1_rtune.saveSettings( _doc, _this, "a1_rtune" );
480
 
        a2_rtune.saveSettings( _doc, _this, "a2_rtune" );
481
 
        b1_rtune.saveSettings( _doc, _this, "b1_rtune" );
482
 
        b2_rtune.saveSettings( _doc, _this, "b2_rtune" );
483
 
 
484
 
        // save graphs
485
 
        QString sampleString;
486
 
 
487
 
        base64::encode( (const char *)a1_graph.samples(), a1_graph.length() * sizeof(float), sampleString );
488
 
        _this.setAttribute( "a1_wave", sampleString );
489
 
        base64::encode( (const char *)a2_graph.samples(), a2_graph.length() * sizeof(float), sampleString );
490
 
        _this.setAttribute( "a2_wave", sampleString );
491
 
        base64::encode( (const char *)b1_graph.samples(), b1_graph.length() * sizeof(float), sampleString );
492
 
        _this.setAttribute( "b1_wave", sampleString );
493
 
        base64::encode( (const char *)b2_graph.samples(), b2_graph.length() * sizeof(float), sampleString );
494
 
        _this.setAttribute( "b2_wave", sampleString );
495
 
 
496
 
        m_abmix.saveSettings( _doc, _this, "abmix" );
497
 
        m_envAmt.saveSettings( _doc, _this, "envAmt" );
498
 
        m_envAtt.saveSettings( _doc, _this, "envAtt" );
499
 
        m_envHold.saveSettings( _doc, _this, "envHold" );
500
 
        m_envDec.saveSettings( _doc, _this, "envDec" );
501
 
 
502
 
        m_xtalk.saveSettings( _doc, _this, "xtalk" );
503
 
 
504
 
        m_amod.saveSettings( _doc, _this, "amod" );
505
 
        m_bmod.saveSettings( _doc, _this, "bmod" );
506
 
/*      m_selectedGraph.saveSettings( _doc, _this, "selgraph" );*/
507
 
}
508
 
 
509
 
 
510
 
void WatsynInstrument::loadSettings( const QDomElement & _this )
511
 
{
512
 
        a1_vol.loadSettings( _this, "a1_vol" );
513
 
        a2_vol.loadSettings( _this, "a2_vol" );
514
 
        b1_vol.loadSettings( _this, "b1_vol" );
515
 
        b2_vol.loadSettings( _this, "b2_vol" );
516
 
 
517
 
        a1_pan.loadSettings( _this, "a1_pan" );
518
 
        a2_pan.loadSettings( _this, "a2_pan" );
519
 
        b1_pan.loadSettings( _this, "b1_pan" );
520
 
        b2_pan.loadSettings( _this, "b2_pan" );
521
 
 
522
 
        a1_mult.loadSettings( _this, "a1_mult" );
523
 
        a2_mult.loadSettings( _this, "a2_mult" );
524
 
        b1_mult.loadSettings( _this, "b1_mult" );
525
 
        b2_mult.loadSettings( _this, "b2_mult" );
526
 
 
527
 
        a1_ltune.loadSettings( _this, "a1_ltune" );
528
 
        a2_ltune.loadSettings( _this, "a2_ltune" );
529
 
        b1_ltune.loadSettings( _this, "b1_ltune" );
530
 
        b2_ltune.loadSettings( _this, "b2_ltune" );
531
 
 
532
 
        a1_rtune.loadSettings( _this, "a1_rtune" );
533
 
        a2_rtune.loadSettings( _this, "a2_rtune" );
534
 
        b1_rtune.loadSettings( _this, "b1_rtune" );
535
 
        b2_rtune.loadSettings( _this, "b2_rtune" );
536
 
 
537
 
        // load graphs
538
 
        int size = 0;
539
 
        char * dst = 0;
540
 
 
541
 
        base64::decode( _this.attribute( "a1_wave"), &dst, &size );
542
 
        a1_graph.setSamples( (float*) dst );
543
 
        base64::decode( _this.attribute( "a2_wave"), &dst, &size );
544
 
        a2_graph.setSamples( (float*) dst );
545
 
        base64::decode( _this.attribute( "b1_wave"), &dst, &size );
546
 
        b1_graph.setSamples( (float*) dst );
547
 
        base64::decode( _this.attribute( "b2_wave"), &dst, &size );
548
 
        b2_graph.setSamples( (float*) dst );
549
 
 
550
 
        delete[] dst;
551
 
 
552
 
        m_abmix.loadSettings( _this, "abmix" );
553
 
 
554
 
        m_envAmt.loadSettings( _this, "envAmt" );
555
 
        m_envAtt.loadSettings( _this, "envAtt" );
556
 
        m_envHold.loadSettings( _this, "envHold" );
557
 
        m_envDec.loadSettings( _this, "envDec" );
558
 
 
559
 
        m_xtalk.loadSettings( _this, "xtalk" );
560
 
 
561
 
        m_amod.loadSettings( _this, "amod" );
562
 
        m_bmod.loadSettings( _this, "bmod" );
563
 
/*      m_selectedGraph.loadSettings( _this, "selgraph" );*/
564
 
}
565
 
 
566
 
 
567
 
QString WatsynInstrument::nodeName() const
568
 
{
569
 
        return( watsyn_plugin_descriptor.name );
570
 
}
571
 
 
572
 
 
573
 
PluginView * WatsynInstrument::instantiateView( QWidget * _parent )
574
 
{
575
 
        return( new WatsynView( this, _parent ) );
576
 
}
577
 
 
578
 
 
579
 
void WatsynInstrument::updateVolumes()
580
 
{
581
 
        m_lvol[A1_OSC] = leftCh( a1_vol.value(), a1_pan.value() );
582
 
        m_rvol[A1_OSC] = rightCh( a1_vol.value(), a1_pan.value() );
583
 
 
584
 
        m_lvol[A2_OSC] = leftCh( a2_vol.value(), a2_pan.value() );
585
 
        m_rvol[A2_OSC] = rightCh( a2_vol.value(), a2_pan.value() );
586
 
 
587
 
        m_lvol[B1_OSC] = leftCh( b1_vol.value(), b1_pan.value() );
588
 
        m_rvol[B1_OSC] = rightCh( b1_vol.value(), b1_pan.value() );
589
 
 
590
 
        m_lvol[B2_OSC] = leftCh( b2_vol.value(), b2_pan.value() );
591
 
        m_rvol[B2_OSC] = rightCh( b2_vol.value(), b2_pan.value() );
592
 
}
593
 
 
594
 
void WatsynInstrument::updateFreq()
595
 
{
596
 
        // calculate frequencies
597
 
        m_lfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_ltune.value() / 1200 );
598
 
        m_rfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_rtune.value() / 1200 );
599
 
        
600
 
        m_lfreq[A2_OSC] = ( a2_mult.value() / 8 ) * powf( 2, a2_ltune.value() / 1200 );
601
 
        m_rfreq[A2_OSC] = ( a2_mult.value() / 8 ) * powf( 2, a2_rtune.value() / 1200 );
602
 
 
603
 
        m_lfreq[B1_OSC] = ( b1_mult.value() / 8 ) * powf( 2, b1_ltune.value() / 1200 );
604
 
        m_rfreq[B1_OSC] = ( b1_mult.value() / 8 ) * powf( 2, b1_rtune.value() / 1200 );
605
 
 
606
 
        m_lfreq[B2_OSC] = ( b2_mult.value() / 8 ) * powf( 2, b2_ltune.value() / 1200 );
607
 
        m_rfreq[B2_OSC] = ( b2_mult.value() / 8 ) * powf( 2, b2_rtune.value() / 1200 ); 
608
 
}
609
 
 
610
 
 
611
 
void WatsynInstrument::updateWaves()
612
 
{
613
 
        // do cip+oversampling on the wavetables to improve quality
614
 
        cipcpy( &A1_wave[0], const_cast<float*>( a1_graph.samples() ) );
615
 
        cipcpy( &A2_wave[0], const_cast<float*>( a2_graph.samples() ) );
616
 
        cipcpy( &B1_wave[0], const_cast<float*>( b1_graph.samples() ) );
617
 
        cipcpy( &B2_wave[0], const_cast<float*>( b2_graph.samples() ) );
618
 
}
619
 
 
620
 
 
621
 
WatsynView::WatsynView( Instrument * _instrument,
622
 
                                        QWidget * _parent ) :
623
 
        InstrumentView( _instrument, _parent )
624
 
{
625
 
        setAutoFillBackground( true );
626
 
        QPalette pal;
627
 
 
628
 
        pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(     "artwork" ) );
629
 
        setPalette( pal );
630
 
 
631
 
// knobs... lots of em
632
 
 
633
 
        makeknob( a1_volKnob, 130, A1ROW, "Volume", "%", "aKnob" )
634
 
        makeknob( a2_volKnob, 130, A2ROW, "Volume", "%", "aKnob" )
635
 
        makeknob( b1_volKnob, 130, B1ROW, "Volume", "%", "bKnob" )
636
 
        makeknob( b2_volKnob, 130, B2ROW, "Volume", "%", "bKnob"  )
637
 
 
638
 
        makeknob( a1_panKnob, 154, A1ROW, "Panning", "", "aKnob" )
639
 
        makeknob( a2_panKnob, 154, A2ROW, "Panning", "", "aKnob" )
640
 
        makeknob( b1_panKnob, 154, B1ROW, "Panning", "", "bKnob"  )
641
 
        makeknob( b2_panKnob, 154, B2ROW, "Panning", "", "bKnob"  )
642
 
 
643
 
        makeknob( a1_multKnob, 178, A1ROW, "Freq. multiplier", "/8", "aKnob" )
644
 
        makeknob( a2_multKnob, 178, A2ROW, "Freq. multiplier", "/8", "aKnob" )
645
 
        makeknob( b1_multKnob, 178, B1ROW, "Freq. multiplier", "/8", "bKnob"  )
646
 
        makeknob( b2_multKnob, 178, B2ROW, "Freq. multiplier", "/8", "bKnob"  )
647
 
 
648
 
        makeknob( a1_ltuneKnob, 202, A1ROW, "Left detune", " cents", "aKnob" )
649
 
        makeknob( a2_ltuneKnob, 202, A2ROW, "Left detune", " cents", "aKnob" )
650
 
        makeknob( b1_ltuneKnob, 202, B1ROW, "Left detune", " cents", "bKnob"  )
651
 
        makeknob( b2_ltuneKnob, 202, B2ROW, "Left detune", " cents", "bKnob"  )
652
 
 
653
 
        makeknob( a1_rtuneKnob, 226, A1ROW, "Right detune", " cents", "aKnob" )
654
 
        makeknob( a2_rtuneKnob, 226, A2ROW, "Right detune", " cents", "aKnob" )
655
 
        makeknob( b1_rtuneKnob, 226, B1ROW, "Right detune", " cents", "bKnob"  )
656
 
        makeknob( b2_rtuneKnob, 226, B2ROW, "Right detune", " cents", "bKnob"  )
657
 
 
658
 
        makeknob( m_abmixKnob, 4, 3, "A-B Mix", "", "mixKnob" )
659
 
 
660
 
        makeknob( m_envAmtKnob, 88, 3, "Mix envelope amount", "", "mixenvKnob" )
661
 
 
662
 
        maketsknob( m_envAttKnob, 88, A1ROW, "Mix envelope attack", " ms", "mixenvKnob" )
663
 
        maketsknob( m_envHoldKnob, 88, A2ROW, "Mix envelope hold", " ms", "mixenvKnob" )
664
 
        maketsknob( m_envDecKnob, 88, B1ROW, "Mix envelope decay", " ms", "mixenvKnob" )
665
 
 
666
 
        makeknob( m_xtalkKnob, 88, B2ROW, "Crosstalk", "", "xtalkKnob" )
667
 
 
668
 
// let's set volume knobs
669
 
        a1_volKnob -> setVolumeKnob( true );
670
 
        a2_volKnob -> setVolumeKnob( true );
671
 
        b1_volKnob -> setVolumeKnob( true );
672
 
        b2_volKnob -> setVolumeKnob( true );
673
 
 
674
 
        m_abmixKnob -> setFixedSize( 31, 31 );
675
 
 
676
 
 
677
 
// button groups next.
678
 
// graph select buttons
679
 
        pixmapButton * a1_selectButton = new pixmapButton( this, NULL );
680
 
        a1_selectButton -> move( 4, 121 );
681
 
        a1_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "a1_active" ) );
682
 
        a1_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "a1_inactive" ) );
683
 
        toolTip::add( a1_selectButton, tr( "Select oscillator A1") );
684
 
 
685
 
        pixmapButton * a2_selectButton = new pixmapButton( this, NULL );
686
 
        a2_selectButton -> move( 44, 121 );
687
 
        a2_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "a2_active" ) );
688
 
        a2_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "a2_inactive" ) );
689
 
        toolTip::add( a2_selectButton, tr( "Select oscillator A2") );
690
 
 
691
 
        pixmapButton * b1_selectButton = new pixmapButton( this, NULL );
692
 
        b1_selectButton -> move( 84, 121 );
693
 
        b1_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "b1_active" ) );
694
 
        b1_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "b1_inactive" ) );
695
 
        toolTip::add( b1_selectButton, tr( "Select oscillator B1") );
696
 
 
697
 
        pixmapButton * b2_selectButton = new pixmapButton( this, NULL );
698
 
        b2_selectButton -> move( 124, 121 );
699
 
        b2_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "b2_active" ) );
700
 
        b2_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "b2_inactive" ) );
701
 
        toolTip::add( b2_selectButton, tr( "Select oscillator B2") );
702
 
 
703
 
        m_selectedGraphGroup = new automatableButtonGroup( this );
704
 
        m_selectedGraphGroup -> addButton( a1_selectButton );
705
 
        m_selectedGraphGroup -> addButton( a2_selectButton );
706
 
        m_selectedGraphGroup -> addButton( b1_selectButton );
707
 
        m_selectedGraphGroup -> addButton( b2_selectButton );
708
 
 
709
 
// A-modulation button group
710
 
        pixmapButton * amod_mixButton = new pixmapButton( this, NULL );
711
 
        amod_mixButton -> move( 4, 50 );
712
 
        amod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "amix_active" ) );
713
 
        amod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "amix_inactive" ) );
714
 
        toolTip::add( amod_mixButton, tr( "Mix output of A2 to A1" ) );
715
 
 
716
 
        pixmapButton * amod_amButton = new pixmapButton( this, NULL );
717
 
        amod_amButton -> move( 4, 66 );
718
 
        amod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "aam_active" ) );
719
 
        amod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "aam_inactive" ) );
720
 
        toolTip::add( amod_amButton, tr( "Modulate amplitude of A1 with output of A2" ) );
721
 
 
722
 
        pixmapButton * amod_rmButton = new pixmapButton( this, NULL );
723
 
        amod_rmButton -> move( 4, 82 );
724
 
        amod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "arm_active" ) );
725
 
        amod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "arm_inactive" ) );
726
 
        toolTip::add( amod_rmButton, tr( "Ring-modulate A1 and A2" ) );
727
 
 
728
 
        pixmapButton * amod_pmButton = new pixmapButton( this, NULL );
729
 
        amod_pmButton -> move( 4, 98 );
730
 
        amod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "apm_active" ) );
731
 
        amod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "apm_inactive" ) );
732
 
        toolTip::add( amod_pmButton, tr( "Modulate phase of A1 with output of A2" ) );
733
 
 
734
 
        m_aModGroup = new automatableButtonGroup( this );
735
 
        m_aModGroup -> addButton( amod_mixButton );
736
 
        m_aModGroup -> addButton( amod_amButton );
737
 
        m_aModGroup -> addButton( amod_rmButton );
738
 
        m_aModGroup -> addButton( amod_pmButton );
739
 
 
740
 
// B-modulation button group
741
 
        pixmapButton * bmod_mixButton = new pixmapButton( this, NULL );
742
 
        bmod_mixButton -> move( 44, 50 );
743
 
        bmod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bmix_active" ) );
744
 
        bmod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bmix_inactive" ) );
745
 
        toolTip::add( bmod_mixButton, tr( "Mix output of B2 to B1" ) );
746
 
 
747
 
        pixmapButton * bmod_amButton = new pixmapButton( this, NULL );
748
 
        bmod_amButton -> move( 44, 66 );
749
 
        bmod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bam_active" ) );
750
 
        bmod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bam_inactive" ) );
751
 
        toolTip::add( bmod_amButton, tr( "Modulate amplitude of B1 with output of B2" ) );
752
 
 
753
 
        pixmapButton * bmod_rmButton = new pixmapButton( this, NULL );
754
 
        bmod_rmButton -> move( 44, 82 );
755
 
        bmod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "brm_active" ) );
756
 
        bmod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "brm_inactive" ) );
757
 
        toolTip::add( bmod_rmButton, tr( "Ring-modulate B1 and B2" ) );
758
 
 
759
 
        pixmapButton * bmod_pmButton = new pixmapButton( this, NULL );
760
 
        bmod_pmButton -> move( 44, 98 );
761
 
        bmod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bpm_active" ) );
762
 
        bmod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bpm_inactive" ) );
763
 
        toolTip::add( bmod_pmButton, tr( "Modulate phase of B1 with output of B2" ) );
764
 
 
765
 
        m_bModGroup = new automatableButtonGroup( this );
766
 
        m_bModGroup -> addButton( bmod_mixButton );
767
 
        m_bModGroup -> addButton( bmod_amButton );
768
 
        m_bModGroup -> addButton( bmod_rmButton );
769
 
        m_bModGroup -> addButton( bmod_pmButton );
770
 
 
771
 
 
772
 
// graph widgets
773
 
        pal = QPalette();
774
 
        pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap("wavegraph") );
775
 
// a1 graph
776
 
        a1_graph = new graph( this, graph::LinearStyle, 224, 105 );
777
 
        a1_graph->move( 4, 141 );
778
 
        a1_graph->setAutoFillBackground( true );
779
 
        a1_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) );
780
 
        toolTip::add( a1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
781
 
        a1_graph->setPalette( pal );
782
 
 
783
 
// a2 graph
784
 
        a2_graph = new graph( this, graph::LinearStyle, 224, 105 );
785
 
        a2_graph->move( 4, 141 );
786
 
        a2_graph->setAutoFillBackground( true );
787
 
        a2_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) );
788
 
        toolTip::add( a2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
789
 
        a2_graph->setPalette( pal );
790
 
 
791
 
// b1 graph
792
 
        b1_graph = new graph( this, graph::LinearStyle, 224, 105 );
793
 
        b1_graph->move( 4, 141 );
794
 
        b1_graph->setAutoFillBackground( true );
795
 
        b1_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) );
796
 
        toolTip::add( b1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
797
 
        b1_graph->setPalette( pal );
798
 
 
799
 
// b2 graph
800
 
        b2_graph = new graph( this, graph::LinearStyle, 224, 105 );
801
 
        b2_graph->move( 4, 141 );
802
 
        b2_graph->setAutoFillBackground( true );
803
 
        b2_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) );
804
 
        toolTip::add( b2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
805
 
        b2_graph->setPalette( pal );
806
 
 
807
 
 
808
 
// misc pushbuttons
809
 
// waveform modifications
810
 
 
811
 
        m_loadButton = new pixmapButton( this, tr( "Load waveform" ) );
812
 
        m_loadButton -> move ( 173, 121 );
813
 
        m_loadButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "load_active" ) );
814
 
        m_loadButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "load_inactive" ) );
815
 
        toolTip::add( m_loadButton, tr( "Click to load a waveform from a sample file" ) );
816
 
 
817
 
        m_phaseLeftButton = new pixmapButton( this, tr( "Phase left" ) );
818
 
        m_phaseLeftButton -> move ( 193, 121 );
819
 
        m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) );
820
 
        m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) );
821
 
        toolTip::add( m_phaseLeftButton, tr( "Click to shift phase by -15 degrees" ) );
822
 
 
823
 
        m_phaseRightButton = new pixmapButton( this, tr( "Phase right" ) );
824
 
        m_phaseRightButton -> move ( 210, 121 );
825
 
        m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) );
826
 
        m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) );
827
 
        toolTip::add( m_phaseRightButton, tr( "Click to shift phase by +15 degrees" ) );
828
 
 
829
 
        m_normalizeButton = new pixmapButton( this, tr( "Normalize" ) );
830
 
        m_normalizeButton -> move ( 230, 121 );
831
 
        m_normalizeButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_active" ) );
832
 
        m_normalizeButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_inactive" ) );
833
 
        toolTip::add( m_normalizeButton, tr( "Click to normalize" ) );
834
 
 
835
 
 
836
 
        m_invertButton = new pixmapButton( this, tr( "Invert" ) );
837
 
        m_invertButton -> move ( 230, 138 );
838
 
        m_invertButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_active" ) );
839
 
        m_invertButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_inactive" ) );
840
 
        toolTip::add( m_invertButton, tr( "Click to invert" ) );
841
 
 
842
 
        m_smoothButton = new pixmapButton( this, tr( "Smooth" ) );
843
 
        m_smoothButton -> move ( 230, 155 );
844
 
        m_smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) );
845
 
        m_smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) );
846
 
        toolTip::add( m_smoothButton, tr( "Click to smooth" ) );
847
 
 
848
 
// waveforms
849
 
 
850
 
        m_sinWaveButton = new pixmapButton( this, tr( "Sine wave" ) );
851
 
        m_sinWaveButton -> move ( 230, 176 );
852
 
        m_sinWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_active" ) );
853
 
        m_sinWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_inactive" ) );
854
 
        toolTip::add( m_sinWaveButton, tr( "Click for sine wave" ) );
855
 
 
856
 
        m_triWaveButton = new pixmapButton( this, tr( "Triangle wave" ) );
857
 
        m_triWaveButton -> move ( 230, 194 );
858
 
        m_triWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_active" ) );
859
 
        m_triWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_inactive" ) );
860
 
        toolTip::add( m_triWaveButton, tr( "Click for triangle wave" ) );
861
 
 
862
 
        m_sawWaveButton = new pixmapButton( this, tr( "Triangle wave" ) );
863
 
        m_sawWaveButton -> move ( 230, 212 );
864
 
        m_sawWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_active" ) );
865
 
        m_sawWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_inactive" ) );
866
 
        toolTip::add( m_sawWaveButton, tr( "Click for saw wave" ) );
867
 
 
868
 
        m_sqrWaveButton = new pixmapButton( this, tr( "Square wave" ) );
869
 
        m_sqrWaveButton -> move ( 230, 230 );
870
 
        m_sqrWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_active" ) );
871
 
        m_sqrWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_inactive" ) );
872
 
        toolTip::add( m_sqrWaveButton, tr( "Click for square wave" ) );
873
 
 
874
 
 
875
 
 
876
 
        connect( m_sinWaveButton, SIGNAL( clicked() ), this, SLOT( sinWaveClicked() ) );
877
 
        connect( m_triWaveButton, SIGNAL( clicked() ), this, SLOT( triWaveClicked() ) );
878
 
        connect( m_sawWaveButton, SIGNAL( clicked() ), this, SLOT( sawWaveClicked() ) );
879
 
        connect( m_sqrWaveButton, SIGNAL( clicked() ), this, SLOT( sqrWaveClicked() ) );
880
 
        connect( m_normalizeButton, SIGNAL( clicked() ), this, SLOT( normalizeClicked() ) );
881
 
        connect( m_invertButton, SIGNAL( clicked() ), this, SLOT( invertClicked() ) );
882
 
        connect( m_smoothButton, SIGNAL( clicked() ), this, SLOT( smoothClicked() ) );
883
 
        connect( m_phaseLeftButton, SIGNAL( clicked() ), this, SLOT( phaseLeftClicked() ) );
884
 
        connect( m_phaseRightButton, SIGNAL( clicked() ), this, SLOT( phaseRightClicked() ) );
885
 
        connect( m_loadButton, SIGNAL( clicked() ), this, SLOT( loadClicked() ) );
886
 
 
887
 
        connect( a1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
888
 
        connect( a2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
889
 
        connect( b1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
890
 
        connect( b2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
891
 
 
892
 
        updateLayout();
893
 
}
894
 
 
895
 
 
896
 
WatsynView::~WatsynView()
897
 
{
898
 
}
899
 
 
900
 
 
901
 
 
902
 
void WatsynView::updateLayout()
903
 
{
904
 
        switch( m_selectedGraphGroup->model()->value() )
905
 
        {
906
 
                case A1_OSC:
907
 
                        a1_graph->show();
908
 
                        a2_graph->hide();
909
 
                        b1_graph->hide();
910
 
                        b2_graph->hide();
911
 
                        break;
912
 
                case A2_OSC:
913
 
                        a1_graph->hide();
914
 
                        a2_graph->show();
915
 
                        b1_graph->hide();
916
 
                        b2_graph->hide();
917
 
                        break;
918
 
                case B1_OSC:
919
 
                        a1_graph->hide();
920
 
                        a2_graph->hide();
921
 
                        b1_graph->show();
922
 
                        b2_graph->hide();
923
 
                        break;
924
 
                case B2_OSC:
925
 
                        a1_graph->hide();
926
 
                        a2_graph->hide();
927
 
                        b1_graph->hide();
928
 
                        b2_graph->show();
929
 
                        break;
930
 
        }
931
 
}
932
 
 
933
 
 
934
 
 
935
 
void WatsynView::sinWaveClicked()
936
 
{
937
 
        switch( m_selectedGraphGroup->model()->value() )
938
 
        {
939
 
                case A1_OSC:
940
 
                        a1_graph->model()->setWaveToSine();
941
 
                        engine::getSong()->setModified();
942
 
                        break;
943
 
                case A2_OSC:
944
 
                        a2_graph->model()->setWaveToSine();
945
 
                        engine::getSong()->setModified();
946
 
                        break;
947
 
                case B1_OSC:
948
 
                        b1_graph->model()->setWaveToSine();
949
 
                        engine::getSong()->setModified();
950
 
                        break;
951
 
                case B2_OSC:
952
 
                        b2_graph->model()->setWaveToSine();
953
 
                        engine::getSong()->setModified();
954
 
                        break;
955
 
        }
956
 
}
957
 
 
958
 
 
959
 
void WatsynView::triWaveClicked()
960
 
{
961
 
        switch( m_selectedGraphGroup->model()->value() )
962
 
        {
963
 
                case A1_OSC:
964
 
                        a1_graph->model()->setWaveToTriangle();
965
 
                        engine::getSong()->setModified();
966
 
                        break;
967
 
                case A2_OSC:
968
 
                        a2_graph->model()->setWaveToTriangle();
969
 
                        engine::getSong()->setModified();
970
 
                        break;
971
 
                case B1_OSC:
972
 
                        b1_graph->model()->setWaveToTriangle();
973
 
                        engine::getSong()->setModified();
974
 
                        break;
975
 
                case B2_OSC:
976
 
                        b2_graph->model()->setWaveToTriangle();
977
 
                        engine::getSong()->setModified();
978
 
                        break;
979
 
        }
980
 
}
981
 
 
982
 
 
983
 
void WatsynView::sawWaveClicked()
984
 
{
985
 
        switch( m_selectedGraphGroup->model()->value() )
986
 
        {
987
 
                case A1_OSC:
988
 
                        a1_graph->model()->setWaveToSaw();
989
 
                        engine::getSong()->setModified();
990
 
                        break;
991
 
                case A2_OSC:
992
 
                        a2_graph->model()->setWaveToSaw();
993
 
                        engine::getSong()->setModified();
994
 
                        break;
995
 
                case B1_OSC:
996
 
                        b1_graph->model()->setWaveToSaw();
997
 
                        engine::getSong()->setModified();
998
 
                        break;
999
 
                case B2_OSC:
1000
 
                        b2_graph->model()->setWaveToSaw();
1001
 
                        engine::getSong()->setModified();
1002
 
                        break;
1003
 
        }
1004
 
}
1005
 
 
1006
 
 
1007
 
void WatsynView::sqrWaveClicked()
1008
 
{
1009
 
        switch( m_selectedGraphGroup->model()->value() )
1010
 
        {
1011
 
                case A1_OSC:
1012
 
                        a1_graph->model()->setWaveToSquare();
1013
 
                        engine::getSong()->setModified();
1014
 
                        break;
1015
 
                case A2_OSC:
1016
 
                        a2_graph->model()->setWaveToSquare();
1017
 
                        engine::getSong()->setModified();
1018
 
                        break;
1019
 
                case B1_OSC:
1020
 
                        b1_graph->model()->setWaveToSquare();
1021
 
                        engine::getSong()->setModified();
1022
 
                        break;
1023
 
                case B2_OSC:
1024
 
                        b2_graph->model()->setWaveToSquare();
1025
 
                        engine::getSong()->setModified();
1026
 
                        break;
1027
 
        }
1028
 
}
1029
 
 
1030
 
 
1031
 
void WatsynView::normalizeClicked()
1032
 
{
1033
 
        switch( m_selectedGraphGroup->model()->value() )
1034
 
        {
1035
 
                case A1_OSC:
1036
 
                        a1_graph->model()->normalize();
1037
 
                        engine::getSong()->setModified();
1038
 
                        break;
1039
 
                case A2_OSC:
1040
 
                        a2_graph->model()->normalize();
1041
 
                        engine::getSong()->setModified();
1042
 
                        break;
1043
 
                case B1_OSC:
1044
 
                        b1_graph->model()->normalize();
1045
 
                        engine::getSong()->setModified();
1046
 
                        break;
1047
 
                case B2_OSC:
1048
 
                        b2_graph->model()->normalize();
1049
 
                        engine::getSong()->setModified();
1050
 
                        break;
1051
 
        }
1052
 
}
1053
 
 
1054
 
 
1055
 
void WatsynView::invertClicked()
1056
 
{
1057
 
        switch( m_selectedGraphGroup->model()->value() )
1058
 
        {
1059
 
                case A1_OSC:
1060
 
                        a1_graph->model()->invert();
1061
 
                        engine::getSong()->setModified();
1062
 
                        break;
1063
 
                case A2_OSC:
1064
 
                        a2_graph->model()->invert();
1065
 
                        engine::getSong()->setModified();
1066
 
                        break;
1067
 
                case B1_OSC:
1068
 
                        b1_graph->model()->invert();
1069
 
                        engine::getSong()->setModified();
1070
 
                        break;
1071
 
                case B2_OSC:
1072
 
                        b2_graph->model()->invert();
1073
 
                        engine::getSong()->setModified();
1074
 
                        break;
1075
 
        }
1076
 
}
1077
 
 
1078
 
 
1079
 
void WatsynView::smoothClicked()
1080
 
{
1081
 
        switch( m_selectedGraphGroup->model()->value() )
1082
 
        {
1083
 
                case A1_OSC:
1084
 
                        a1_graph->model()->smooth();
1085
 
                        engine::getSong()->setModified();
1086
 
                        break;
1087
 
                case A2_OSC:
1088
 
                        a2_graph->model()->smooth();
1089
 
                        engine::getSong()->setModified();
1090
 
                        break;
1091
 
                case B1_OSC:
1092
 
                        b1_graph->model()->smooth();
1093
 
                        engine::getSong()->setModified();
1094
 
                        break;
1095
 
                case B2_OSC:
1096
 
                        b2_graph->model()->smooth();
1097
 
                        engine::getSong()->setModified();
1098
 
                        break;
1099
 
        }
1100
 
}
1101
 
 
1102
 
 
1103
 
void WatsynView::phaseLeftClicked()
1104
 
{
1105
 
        switch( m_selectedGraphGroup->model()->value() )
1106
 
        {
1107
 
                case A1_OSC:
1108
 
                        a1_graph->model()->shiftPhase( -15 );
1109
 
                        engine::getSong()->setModified();
1110
 
                        break;
1111
 
                case A2_OSC:
1112
 
                        a2_graph->model()->shiftPhase( -15 );
1113
 
                        engine::getSong()->setModified();
1114
 
                        break;
1115
 
                case B1_OSC:
1116
 
                        b1_graph->model()->shiftPhase( -15 );
1117
 
                        engine::getSong()->setModified();
1118
 
                        break;
1119
 
                case B2_OSC:
1120
 
                        b2_graph->model()->shiftPhase( -15 );
1121
 
                        engine::getSong()->setModified();
1122
 
                        break;
1123
 
        }
1124
 
}
1125
 
 
1126
 
 
1127
 
void WatsynView::phaseRightClicked()
1128
 
{
1129
 
        switch( m_selectedGraphGroup->model()->value() )
1130
 
        {
1131
 
                case A1_OSC:
1132
 
                        a1_graph->model()->shiftPhase( 15 );
1133
 
                        engine::getSong()->setModified();
1134
 
                        break;
1135
 
                case A2_OSC:
1136
 
                        a2_graph->model()->shiftPhase( 15 );
1137
 
                        engine::getSong()->setModified();
1138
 
                        break;
1139
 
                case B1_OSC:
1140
 
                        b1_graph->model()->shiftPhase( 15 );
1141
 
                        engine::getSong()->setModified();
1142
 
                        break;
1143
 
                case B2_OSC:
1144
 
                        b2_graph->model()->shiftPhase( 15 );
1145
 
                        engine::getSong()->setModified();
1146
 
                        break;
1147
 
        }
1148
 
}
1149
 
 
1150
 
 
1151
 
void WatsynView::loadClicked()
1152
 
{
1153
 
        QString fileName;
1154
 
        switch( m_selectedGraphGroup->model()->value() )
1155
 
        {
1156
 
                case A1_OSC:
1157
 
                        a1_graph->model()->setWaveToUser();
1158
 
                        engine::getSong()->setModified();
1159
 
                        break;
1160
 
                case A2_OSC:
1161
 
                        a2_graph->model()->setWaveToUser();
1162
 
                        engine::getSong()->setModified();
1163
 
                        break;
1164
 
                case B1_OSC:
1165
 
                        b1_graph->model()->setWaveToUser();
1166
 
                        engine::getSong()->setModified();
1167
 
                        break;
1168
 
                case B2_OSC:
1169
 
                        b2_graph->model()->setWaveToUser();
1170
 
                        engine::getSong()->setModified();
1171
 
                        break;
1172
 
        }
1173
 
}
1174
 
 
1175
 
 
1176
 
void WatsynView::modelChanged()
1177
 
{
1178
 
        WatsynInstrument * w = castModel<WatsynInstrument>();
1179
 
 
1180
 
        a1_volKnob -> setModel( &w -> a1_vol );
1181
 
        a2_volKnob -> setModel( &w -> a2_vol );
1182
 
        b1_volKnob -> setModel( &w -> b1_vol );
1183
 
        b2_volKnob -> setModel( &w -> b2_vol );
1184
 
 
1185
 
        a1_panKnob -> setModel( &w -> a1_pan );
1186
 
        a2_panKnob -> setModel( &w -> a2_pan );
1187
 
        b1_panKnob -> setModel( &w -> b1_pan );
1188
 
        b2_panKnob -> setModel( &w -> b2_pan );
1189
 
 
1190
 
        a1_multKnob -> setModel( &w -> a1_mult );
1191
 
        a2_multKnob -> setModel( &w -> a2_mult );
1192
 
        b1_multKnob -> setModel( &w -> b1_mult );
1193
 
        b2_multKnob -> setModel( &w -> b2_mult );
1194
 
 
1195
 
        a1_ltuneKnob -> setModel( &w -> a1_ltune );
1196
 
        a2_ltuneKnob -> setModel( &w -> a2_ltune );
1197
 
        b1_ltuneKnob -> setModel( &w -> b1_ltune );
1198
 
        b2_ltuneKnob -> setModel( &w -> b2_ltune );
1199
 
 
1200
 
        a1_rtuneKnob -> setModel( &w -> a1_rtune );
1201
 
        a2_rtuneKnob -> setModel( &w -> a2_rtune );
1202
 
        b1_rtuneKnob -> setModel( &w -> b1_rtune );
1203
 
        b2_rtuneKnob -> setModel( &w -> b2_rtune );
1204
 
 
1205
 
        m_abmixKnob -> setModel( &w -> m_abmix );
1206
 
 
1207
 
        m_selectedGraphGroup -> setModel( &w -> m_selectedGraph );
1208
 
 
1209
 
        m_aModGroup -> setModel( &w -> m_amod );
1210
 
        m_bModGroup -> setModel( &w -> m_bmod );
1211
 
 
1212
 
        a1_graph -> setModel( &w -> a1_graph );
1213
 
        a2_graph -> setModel( &w -> a2_graph );
1214
 
        b1_graph -> setModel( &w -> b1_graph );
1215
 
        b2_graph -> setModel( &w -> b2_graph );
1216
 
 
1217
 
        m_envAmtKnob -> setModel( &w -> m_envAmt );
1218
 
        m_envAttKnob -> setModel( &w -> m_envAtt );
1219
 
        m_envHoldKnob -> setModel( &w -> m_envHold );
1220
 
        m_envDecKnob -> setModel( &w -> m_envDec );
1221
 
 
1222
 
        m_xtalkKnob -> setModel( &w -> m_xtalk );
1223
 
}
1224
 
 
1225
 
 
1226
 
 
1227
 
 
1228
 
 
1229
 
extern "C"
1230
 
{
1231
 
 
1232
 
// necessary for getting instance out of shared lib
1233
 
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data )
1234
 
{
1235
 
        return( new WatsynInstrument( static_cast<InstrumentTrack *>( _data ) ) );
1236
 
}
1237
 
 
1238
 
 
1239
 
}
1240
 
 
1241
 
 
1242
 
#include "moc_Watsyn.cxx"