File: m_env.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 (185 lines) | stat: -rw-r--r-- 6,164 bytes parent folder | download | duplicates (3)
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#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_env.h"
#include "port.h"

M_env::M_env(QWidget* parent, const char *name, SynthData *p_synthdata) 
              : Module(2, parent, name, p_synthdata) {

  QString qs;
  int l1;

  M_type = M_type_env;
  setGeometry(MODULE_NEW_X, MODULE_NEW_Y, MODULE_ENV_WIDTH, MODULE_ENV_HEIGHT);
  delay = 0;
  attack = 0.05;
  hold = 0.02;
  decay = 0.1;
  sustain = 0.7;
  release = 0.05;
  timeScale = 1.0;
  port_gate = new Port("Gate", PORT_IN, 0, this, synthdata);
  port_gate->move(0, 35);
  port_gate->outTypeAcceptList.append(outType_audio);
  portList.append(port_gate);
  port_retrigger = new Port("Retrigger", PORT_IN, 1, this, synthdata);
  port_retrigger->move(0, 55);
  port_retrigger->outTypeAcceptList.append(outType_audio);
  portList.append(port_retrigger);
  port_gain_out = new Port("Out", PORT_OUT, 0, this, synthdata);          
  port_gain_out->move(width() - port_gain_out->width(), 75);
  port_gain_out->outType = outType_audio;
  portList.append(port_gain_out);
  port_inverse_out = new Port("Inverse Out", PORT_OUT, 1, this, synthdata);          
  port_inverse_out->move(width() - port_inverse_out->width(), 95);
  port_inverse_out->outType = outType_audio;
  portList.append(port_inverse_out);
  qs.sprintf("ENV ID %d", moduleID);
  configDialog->setCaption(qs);
  configDialog->addEnvelope(&delay, &attack, &hold, &decay, &sustain, &release);
  configDialog->initTabWidget();
  QVBox *adsrTab = new QVBox(configDialog->tabWidget);
  QVBox *delayTab = new QVBox(configDialog->tabWidget);
  configDialog->addSlider(0, 1, delay, "Delay", &delay, false, delayTab);
  configDialog->addSlider(0, 1, attack, "Attack", &attack, false, adsrTab);
  configDialog->addSlider(0, 1, hold, "Hold", &hold, false, delayTab);
  configDialog->addSlider(0, 1, decay, "Decay", &decay, false, adsrTab);
  configDialog->addSlider(0, 1, sustain, "Sustain", &sustain, false, adsrTab);
  configDialog->addSlider(0, 1, release, "Release", &release, false, adsrTab);
  configDialog->addSlider(0.1, 10, timeScale, "Time Scale", &timeScale, false, delayTab);
  configDialog->addTab(adsrTab, "ADSR");
  configDialog->addTab(delayTab, "Delay / Hold / Time Scale");
  for (l1 = 0; l1 < configDialog->midiSliderList.count(); l1++) {
    QObject::connect(configDialog->midiSliderList.at(l1), SIGNAL(valueChanged(int)), 
                     configDialog->envelopeList.at(0), SLOT(updateEnvelope(int)));
  }
  for (l1 = 0; l1 < synthdata->poly; l1++) {
    noteActive[l1] = false;
    gate[l1] = false;
    retrigger[l1] = false;
    noteOnOfs[l1] = 0;
    noteOffOfs[l1] = 0;
    e[l1] = 0;
    de[l1] = 0;
  }
}

M_env::~M_env() {

}

void M_env::generateCycle() {

  int l1, l2, status;
  float tscale, de_attack, de_decay, de_release;
  float a, dl, dc, h, dla, dlah, dlahdc;

  if (!cycleReady) {
    cycleProcessing = true;

    gateData = port_gate->getinputdata();
    retriggerData = port_retrigger->getinputdata();

    tscale = timeScale * (float)synthdata->rate;
    de_attack = (attack > 0) ? 1.0 / (attack * tscale) : 0;
    de_decay = (decay > 0) ? (1.0 - sustain) / (decay * tscale) : 0;
    a = tscale * attack;    
    dl = tscale * delay;    
    h = tscale * hold;         
    dc = tscale * decay;    
    dla = dl + a;    
    dlah = dla + h;    
    dlahdc = dlah + dc;    
    for (l1 = 0; l1 < synthdata->poly; l1++) {
      for (l2 = 0; l2 < synthdata->cyclesize; l2++) {
        if (!gate[l1] && (gateData[l1][l2] > 0.5)) {
          gate[l1] = true;
          noteActive[l1] = true;
          if (e[l1] > 0) {
            noteOnOfs[l1] = -ENVELOPE_RESPONSE;
            de[l1] = e[l1] / (float)ENVELOPE_RESPONSE;
          } else {
            noteOnOfs[l1] = 0;
          }
        }
        if (gate[l1] && (gateData[l1][l2] < 0.5)) {
          gate[l1] = false;
          noteOffOfs[l1] = 0;
          e_noteOff[l1] = e[l1];
        }
        if (!retrigger[l1] && (retriggerData[l1][l2] > 0.5)) { 
          retrigger[l1] = true;
          if (e[l1] > 0) {
            noteOnOfs[l1] = (de_attack > 0) ? e[l1] / de_attack : 0;
          } else {
            noteOnOfs[l1] = 0;
          }
        }
        if (retrigger[l1] && (retriggerData[l1][l2] < 0.5)) {
          retrigger[l1] = false;
        }
        if (gate[l1]) {
            status = 1;
            if (noteOnOfs[l1] < 0) status = 0;
            if (noteOnOfs[l1] >= int(dl)) status = 2; 
            if (noteOnOfs[l1] >= int(dla)) status = 3;
            if (noteOnOfs[l1] >= int(dlah)) status = 4;
            if (noteOnOfs[l1] >= int(dlahdc)) status = 5; 
            switch (status) {
              case 0: e[l1] -= de[l1];
                      break;
              case 1: e[l1] = 0;
                      break;
              case 2: e[l1] += de_attack;
                      break;
              case 3: e[l1] = 1.0;
                      break;
              case 4: e[l1] -= de_decay;
                      break;
              case 5: e[l1] = sustain;
                      break;
              default: e[l1] = 0;
                       break;
            }
            if (e[l1] < 0) e[l1] = 0;
            data[0][l1][l2] = e[l1];
            data[1][l1][l2] = -e[l1];
            noteOnOfs[l1]++;
        } else {                          // Release      
          de_release = (release > 0) ? e_noteOff[l1] / (release * tscale) : 0;
          e[l1] -= de_release;
          noteOffOfs[l1]++;
          if (noteOffOfs[l1] >= int(tscale * release)) {
            noteActive[l1] = false;
          }
          if ((release == 0) || (e[l1] < 0)) {
            e[l1] = 0;
          }
          data[0][l1][l2] = e[l1];
          data[1][l1][l2] = -e[l1];
        }
      }
    }
  }
  cycleProcessing = false;
  cycleReady = true;
}

void M_env::showConfigDialog() {
}