File: m_vcenv2.cpp

package info (click to toggle)
ams 1.8.7-5
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,880 kB
  • ctags: 2,171
  • sloc: cpp: 17,793; makefile: 433; sh: 101
file content (168 lines) | stat: -rw-r--r-- 5,624 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <qwidget.h>
#include <qstring.h>
#include <qslider.h>   
#include <qcheckbox.h>  
#include <qlabel.h>
#include <qvbox.h>
#include <qhbox.h>
#include <qspinbox.h>
#include <qradiobutton.h>
#include <qpushbutton.h>
#include <qdialog.h>
#include <qpainter.h>
#include <alsa/asoundlib.h>
#include "synthdata.h"
#include "m_vcenv2.h"
#include "port.h"

M_vcenv2::M_vcenv2(QWidget* parent, const char *name, SynthData *p_synthdata) 
              : Module(1, parent, name, p_synthdata) {

  QString qs;
  int l1;

  M_type = M_type_vcenv2;
  setGeometry(MODULE_NEW_X, MODULE_NEW_Y, MODULE_VCENV2_WIDTH, MODULE_VCENV2_HEIGHT);
  port_M_gate = new Port("Gate", PORT_IN, 0, this, synthdata); 
  port_M_gate->move(0, 35);
  port_M_gate->outTypeAcceptList.append(outType_audio);
  portList.append(port_M_gate);
  port_M_retrigger = new Port("Retrigger", PORT_IN, 1, this, synthdata); 
  port_M_retrigger->move(0, 55);
  port_M_retrigger->outTypeAcceptList.append(outType_audio);
  portList.append(port_M_retrigger);
  port_M_attack = new Port("Attack", PORT_IN, 2, this, synthdata); 
  port_M_attack->move(0, 75);
  port_M_attack->outTypeAcceptList.append(outType_audio);
  portList.append(port_M_attack);
  port_M_decay = new Port("Decay", PORT_IN, 3, this, synthdata); 
  port_M_decay->move(0, 95);
  port_M_decay->outTypeAcceptList.append(outType_audio);
  portList.append(port_M_decay);
  port_M_sustain = new Port("Sustain", PORT_IN, 4, this, synthdata); 
  port_M_sustain->move(0, 115);
  port_M_sustain->outTypeAcceptList.append(outType_audio);
  portList.append(port_M_sustain);
  port_M_release = new Port("Release", PORT_IN, 5, this, synthdata); 
  port_M_release->move(0, 135);
  port_M_release->outTypeAcceptList.append(outType_audio);
  portList.append(port_M_release);
  port_out = new Port("Out", PORT_OUT, 0, this, synthdata);          
  port_out->move(width() - port_out->width(), 155);
  port_out->outType = outType_audio;
  portList.append(port_out);
  qs.sprintf("VC Envelope II ID %d", moduleID);
  a0 = 0.0;
  d0 = 0.0;
  s0 = 0.7;
  r0 = 0.0;
  aGain = 1.0;
  dGain = 1.0;
  sGain = 1.0;
  rGain = 1.0;
  for (l1 = 0; l1 < synthdata->poly; l1++) {
    gate[l1] = false;
    retrigger[l1] = false;
    state[l1] = 0;
    noteActive[l1] = false;
    e[l1] = 0;
  }
  configDialog->addSlider(-8, 8, a0, "Attack Offset", &a0);
  configDialog->addSlider(-8, 8, d0, "Decay Offset", &d0);
  configDialog->addSlider(0, 1, s0, "Sustain Offset", &s0);
  configDialog->addSlider(-8, 8, r0, "Release Offset", &r0);
  configDialog->addSlider(-8, 8, aGain, "Attack Gain", &aGain);
  configDialog->addSlider(-8, 8, dGain, "Decay Gain", &dGain);
  configDialog->addSlider(0, 1, sGain, "Sustain Gain", &sGain);
  configDialog->addSlider(-8, 8, rGain, "Release Gain", &rGain);
  configDialog->setCaption(qs);
}

M_vcenv2::~M_vcenv2() {
}

void M_vcenv2::generateCycle() {

  int l1, l2;
  double ts, tsr, tsn, tmp, c, n, log2;

  if (!cycleReady) {
    cycleProcessing = true;

    gateData = port_M_gate->getinputdata ();
    retriggerData = port_M_retrigger->getinputdata ();
    attackData = port_M_attack->getinputdata ();
    decayData = port_M_decay->getinputdata ();
    sustainData = port_M_sustain->getinputdata ();
    releaseData = port_M_release->getinputdata ();

    ts = 1.0;
    tsr = ts / (double)synthdata->rate;
    tsn = ts * (double)synthdata->rate;
    log2 = log(2.0);
    for (l1 = 0; l1 < synthdata->poly; l1++) {
//      fprintf(stderr, "gate:%d retrigger:%d noteActive:%d state: %d\n", gate[l1], retrigger[l1], noteActive[l1], state[l1]);
      for (l2 = 0; l2 < synthdata->cyclesize; l2++) {
        if (!gate[l1] && gateData[l1][l2] > 0.5) {
          gate[l1] = true;
          noteActive[l1] = true;
          state[l1] = 1;
        }
        if (gate[l1] && gateData[l1][l2] < 0.5) {
          gate[l1] = false;
          state[l1] = 4;
        }
        if (!retrigger[l1] && retriggerData[l1][l2] > 0.5) {
          retrigger[l1] = true; 
          if (gate[l1]) {
            state[l1] = 1;
          }
        }
        if (retrigger[l1] && retriggerData[l1][l2] < 0.5) {
          retrigger[l1] = false;
        }
        switch (state[l1]) {
          case 0: e[l1] = 0;
                  break;
          case 1: e[l1] += ((tmp = synthdata->exp_table(log2 * (a0 + aGain * attackData[l1][l2]))) > 0.001) ? tsr / tmp : tsr / 0.001;
                  if (e[l1] >= 1.0) {
                    state[l1] = 2;
                    e[l1] = 1.0;
                  }
                  break;
          case 2: n = tsn * (synthdata->exp_table(log2 * (d0 + dGain * decayData[l1][l2])));
                  if (n < 1) n = 1;
                  c = 2.3 / n; 
                  e[l1] *= exp(-c);            
                  if (e[l1] <= s0 + sGain * sustainData[l1][l2] + 1e-20) {
                    state[l1] = 3;
                  } else {
                    break;
                  }
          case 3: e[l1] = s0 + sGain * sustainData[l1][l2];
                  break;
          case 4: n = tsn * (synthdata->exp_table(log2 * (r0 + rGain * releaseData[l1][l2])));
                  if (n < 1) n = 1;
                  c = 2.3 / n; 
                  e[l1] *= exp(-c);      
                  if (e[l1] <= 1e-20) {
                    e[l1] = 0;
                    noteActive[l1] = false;
                  }
                  break;
          default: e[l1] = 0;
        }
        data[0][l1][l2] = e[l1];
      }
    }
  }
  cycleProcessing = false;
  cycleReady = true;
}

void M_vcenv2::showConfigDialog() {
}