LMMS
Loading...
Searching...
No Matches
EnvelopeFreeEdit.cpp
Go to the documentation of this file.
1/*
2 ZynAddSubFX - a software synthesizer
3
4 EnvelopeFreeEdit.cpp - Envelope Edit View
5 Copyright (C) 2016 Mark McCurry
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11*/
12#include "EnvelopeFreeEdit.h"
13#include "../Misc/Util.h"
14#include <FL/Fl.H>
15#include <FL/fl_draw.H>
16#include <cstdlib>
17#include <cassert>
18#include <rtosc/rtosc.h>
19
20using namespace zyncarla;
21
22EnvelopeFreeEdit::EnvelopeFreeEdit(int x,int y, int w, int h, const char *label)
23:Fl_Box(x,y,w,h,label), Fl_Osc_Widget(this)
24{
25 pair=NULL;
26 currentpoint=-1;
27 cpx=0;
28 lastpoint=-1;
29}
30
32{
33 oscRegister("Penvpoints");
34 oscRegister("Penvdt");
35 oscRegister("Penvval");
36 oscRegister("Penvsustain");
37
38 //register for non-bulk types
39 for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) {
40 osc->createLink(loc+string("Penvdt") + to_s(i), this);
41 osc->createLink(loc+string("Penvval") + to_s(i), this);
42 }
43}
44
46{
47 const char *args = rtosc_argument_string(msg);
48 if(strstr(msg,"Penvpoints") && !strcmp(args, "i")) {
50 } else if(strstr(msg,"Penvdt") && !strcmp(args, "b")) {
54 } else if(strstr(msg,"Penvval") && !strcmp(args, "b")) {
58 } else if(strstr(msg, "Penvval") && !strcmp(args, "c")) {
59 const char *str = strstr(msg, "Penvval");
60 int id = atoi(str+7);
61 assert(0 <= id && id < MAX_ENVELOPE_POINTS);
62 Penvval[id] = rtosc_argument(msg, 0).i;
63 } else if(strstr(msg, "Penvdt") && !strcmp(args, "c")) {
64 const char *str = strstr(msg, "Penvdt");
65 int id = atoi(str+6);
66 assert(0 <= id && id < MAX_ENVELOPE_POINTS);
67 Penvdt[id] = rtosc_argument(msg, 0).i;
68 } else if(strstr(msg,"Penvsustain") && !strcmp(args, "i")) {
70 }
71 redraw();
72 do_callback();
73}
74
75void EnvelopeFreeEdit::setpair(Fl_Box *pair_)
76{
77 pair=pair_;
78}
79
81{
82 const int lx=w()-10;
83 int npoints=Penvpoints;
84
85 float sum=0;
86 for(int i=1; i<npoints; ++i)
87 sum+=getdt(i)+1;
88
89 float sumbefore=0;//the sum of all points before the computed point
90 for(int i=1; i<=n; ++i)
91 sumbefore+=getdt(i)+1;
92
93 return (int) (sumbefore/(float) sum*lx);
94}
95
97{
98 const int ly=h()-10;
99
100 return (1.0-Penvval[n]/127.0)*ly;
101}
102
103static inline int distance_fn(int dx, int dy) {
104 return dx*dx+dy*dy;
105}
106
108{
109 x-=5;y-=5;
110
111 int nearestpoint=0;
112 int nearest_distance_sq=distance_fn(x-getpointx(0), y-getpointy(0));
113 for(int i=1; i<Penvpoints; ++i){
114 int distance_sq=distance_fn(x-getpointx(i), y-getpointy(i));
115 if (distance_sq<nearest_distance_sq) {
116 nearestpoint=i;
117 nearest_distance_sq=distance_sq;
118 }
119 }
120
121 return nearestpoint;
122}
123
124static float dt(char val)
125{
126 return (powf(2.0f, val / 127.0f * 12.0f) - 1.0f) * 10.0f; //miliseconds
127}
128
130{
131 return dt(Penvdt[i]);
132}
133
134static bool ctrldown, altdown;
135
137{
138 int ox=x(),oy=y(),lx=w(),ly=h();
139 //if (env->Pfreemode==0)
140 // env->converttofree();
141 const int npoints=Penvpoints;
142
143 if (active_r()) fl_color(FL_BLACK);
144 else fl_color(90,90,90);
145 if (!active_r()) currentpoint=-1;
146
147 fl_rectf(ox,oy,lx,ly);
148
149 //Margins
150 ox+=5;oy+=5;lx-=10;ly-=10;
151
152 //draw the lines
153 fl_color(FL_GRAY);
154
155 const int midline = oy+ly*(1-64.0/127);
156 fl_line_style(FL_SOLID);
157 fl_line(ox+2,midline,ox+lx-2,midline);
158
159 //draws the evelope points and lines
160 Fl_Color alb=FL_WHITE;
161 if (!active_r()) alb=fl_rgb_color(180,180,180);
162 fl_color(alb);
163 int oldxx=0,xx=0,oldyy=0,yy=getpointy(0);
164 fl_rectf(ox-3,oy+yy-3,6,6);
165 for (int i=1; i<npoints; ++i){
166 oldxx=xx;oldyy=yy;
167 xx=getpointx(i);yy=getpointy(i);
168 if (i==currentpoint || (ctrldown && i==lastpoint))
169 fl_color(FL_RED);
170 else
171 fl_color(alb);
172 fl_line(ox+oldxx,oy+oldyy,ox+xx,oy+yy);
173 fl_rectf(ox+xx-3,oy+yy-3,6,6);
174 }
175
176 //draw the last moved point point (if exists)
177 if (lastpoint>=0){
178 fl_color(FL_CYAN);
179 fl_rectf(ox+getpointx(lastpoint)-5,oy+getpointy(lastpoint)-5,10,10);
180 }
181
182 //draw the sustain position
183 if(Penvsustain>0){
184 fl_color(FL_YELLOW);
186 fl_line(ox+xx,oy+0,ox+xx,oy+ly);
187 }
188
189 //Show the envelope duration and the current line duration
190 fl_font(FL_HELVETICA|FL_BOLD,10);
191 float time=0.0;
192 if (currentpoint<=0 && (!ctrldown||lastpoint <= 0)){
193 fl_color(alb);
194 for(int i=1; i<npoints; ++i)
195 time+=getdt(i);
196 } else {
197 fl_color(FL_RED);
199 }
200 char tmpstr[20];
201 if (!altdown || ctrldown) {
202 if (time<1000.0)
203 snprintf((char *)&tmpstr,20,"%.1fms",time);
204 else
205 snprintf((char *)&tmpstr,20,"%.2fs",time/1000.0);
206 fl_draw(tmpstr,ox+lx-20,oy+ly-10,20,10,FL_ALIGN_RIGHT,NULL,0);
207 }
208 if (!altdown || !ctrldown) {
209 if (lastpoint>=0){
210 snprintf((char *)&tmpstr,20,"%d", Penvval[lastpoint]);
211 fl_draw(tmpstr,ox+lx-20,oy+ly-23,20,10,FL_ALIGN_RIGHT,NULL,0);
212 }
213 }
214}
215
217{
218 const int x_=Fl::event_x()-x();
219 const int y_=Fl::event_y()-y();
220 static Fl_Widget *old_focus;
221 int key, old_mod_state;
222
223 switch(event) {
224 case FL_ENTER:
225 old_focus=Fl::focus();
226 Fl::focus(this);
227 // Otherwise the underlying window seems to regrab focus,
228 // and I can't see the KEYDOWN action.
229 return 1;
230 case FL_LEAVE:
231 Fl::focus(old_focus);
232 break;
233 case FL_KEYDOWN:
234 case FL_KEYUP:
235 key = Fl::event_key();
236 if (key==FL_Alt_L || key==FL_Alt_R) {
237 altdown = (event==FL_KEYDOWN);
238 redraw();
239 if (pair!=NULL) pair->redraw();
240 }
241 if (key==FL_Control_L || key==FL_Control_R){
242 ctrldown = (event==FL_KEYDOWN);
243 redraw();
244 if (pair!=NULL) pair->redraw();
245 }
246 break;
247 case FL_PUSH:
249 cpx=x_;
250 cpy=y_;
254 redraw();
255 if (pair)
256 pair->redraw();
257 return 1;
258 case FL_RELEASE:
259 currentpoint=-1;
260 redraw();
261 if (pair)
262 pair->redraw();
263 return 1;
264 case FL_MOUSEWHEEL:
265 if (Fl::event_buttons())
266 return 1;
267 if (lastpoint>=0) {
268 int delta = Fl::event_dy() * (Fl::event_shift() ? 4 : 1);
269 if (!ctrldown) {
270 int ny = Penvval[lastpoint] - delta;
271 ny = ny < 0 ? 0 : ny > 127 ? 127 : ny;
272 Penvval[lastpoint] = ny;
273 oscWrite(to_s("Penvval")+to_s(lastpoint), "c", ny);
274 oscWrite("Penvval","");
275 } else if (lastpoint > 0) {
276 int newdt = Penvdt[lastpoint] - delta;
277 newdt = newdt < 0 ? 0 : newdt > 127 ? 127 : newdt;
278 Penvdt[lastpoint] = newdt;
279 oscWrite(to_s("Penvdt")+to_s(lastpoint), "c", newdt);
280 oscWrite("Penvdt","");
281 }
282 redraw();
283 if (pair!=NULL) pair->redraw();
284 return 1;
285 }
286 case FL_DRAG:
287 if (currentpoint>=0){
288 old_mod_state = mod_state;
289 mod_state = ctrldown << 1 | altdown;
290 if (old_mod_state != mod_state) {
291 cpx=x_;
292 cpy=y_;
295 old_mod_state = mod_state;
296 }
297
298 if (!altdown || !ctrldown) {
299 const int dy=(int)((cpy-y_)/3.0);
300 const int newval=limit(cpval+dy, 0, 127);
301
302 Penvval[currentpoint]=newval;
303 oscWrite(to_s("Penvval")+to_s(currentpoint), "c", newval);
304 oscWrite("Penvval","");
305 }
306
307 if (!altdown || ctrldown) {
308 const int dx=(int)((x_-cpx)*0.1);
309 const int newdt=limit(cpdt+dx,0,127);
310
311 if(currentpoint!=0)
312 Penvdt[currentpoint]=newdt;
313 else
315 oscWrite(to_s("Penvdt")+to_s(currentpoint), "c", newdt);
316 oscWrite("Penvdt","");
317 }
318
319 redraw();
320
321 if(pair)
322 pair->redraw();
323 return 1;
324 }
325 }
326 // Needed to propagate undo/redo keys.
327 return 0;
328}
329
331{
332 oscWrite("Penvpoints");
333 oscWrite("Penvdt");
334 oscWrite("Penvval");
335 oscWrite("Penvsustain");
336}
337
338void EnvelopeFreeEdit::rebase(std::string new_base)
339{
340 osc->renameLink(loc+"Penvpoints", new_base+"Penvpoints", this);
341 osc->renameLink(loc+"Penvdt", new_base+"Penvdt", this);
342 osc->renameLink(loc+"Penvval", new_base+"Penvval", this);
343 osc->renameLink(loc+"Penvsustain", new_base+"Penvsustain", this);
344 for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) {
345 string dt = string("Penvdt") + to_s(i);
346 string val = string("Penvval") + to_s(i);
347 osc->renameLink(loc+dt, new_base+dt, this);
348 osc->renameLink(loc+val, new_base+val, this);
349 }
350 loc = new_base;
351 update();
352}
#define MAX_ENVELOPE_POINTS
Definition globals.h:191
#define NULL
Definition CarlaBridgeFormat.cpp:30
static bool ctrldown
Definition EnvelopeFreeEdit.cpp:134
static float dt(char val)
Definition EnvelopeFreeEdit.cpp:124
static int distance_fn(int dx, int dy)
Definition EnvelopeFreeEdit.cpp:103
static bool altdown
Definition EnvelopeFreeEdit.cpp:134
assert(0)
int getpointy(int n) const
Definition EnvelopeFreeEdit.cpp:96
float getdt(int i) const
Definition EnvelopeFreeEdit.cpp:129
void setpair(Fl_Box *pair_)
Definition EnvelopeFreeEdit.cpp:75
int cpx
Definition EnvelopeFreeEdit.h:54
void OSC_raw(const char *msg) override
Definition EnvelopeFreeEdit.cpp:45
char Penvdt[MAX_ENVELOPE_POINTS]
Definition EnvelopeFreeEdit.h:57
Fl_Box * pair
Definition EnvelopeFreeEdit.h:51
char Penvval[MAX_ENVELOPE_POINTS]
Definition EnvelopeFreeEdit.h:58
int getnearest(int x, int y) const
Definition EnvelopeFreeEdit.cpp:107
int cpval
Definition EnvelopeFreeEdit.h:54
void rebase(std::string new_base) override
Definition EnvelopeFreeEdit.cpp:338
int handle(int event) override
Definition EnvelopeFreeEdit.cpp:216
int cpy
Definition EnvelopeFreeEdit.h:54
char Penvsustain
Definition EnvelopeFreeEdit.h:60
int cpdt
Definition EnvelopeFreeEdit.h:54
int lastpoint
Definition EnvelopeFreeEdit.h:41
char Penvpoints
Definition EnvelopeFreeEdit.h:44
EnvelopeFreeEdit(int x, int y, int w, int h, const char *label=0)
Definition EnvelopeFreeEdit.cpp:22
void init(void)
Definition EnvelopeFreeEdit.cpp:31
void draw(void) override
Definition EnvelopeFreeEdit.cpp:136
int getpointx(int n) const
Definition EnvelopeFreeEdit.cpp:80
void update(void) override
Definition EnvelopeFreeEdit.cpp:330
int currentpoint
Definition EnvelopeFreeEdit.h:54
int mod_state
Definition EnvelopeFreeEdit.h:62
Fl_Osc_Interface * osc
Definition Fl_Osc_Widget.H:65
Fl_Osc_Widget(void)
Definition Fl_Osc_Widget.cpp:16
std::string loc
Definition Fl_Osc_Widget.H:62
void oscRegister(const char *path)
Definition Fl_Osc_Widget.cpp:91
void oscWrite(std::string path, const char *args,...)
Definition Fl_Osc_Widget.cpp:60
UINT_D64 w
Definition inflate.c:942
int y
Definition inflate.c:1588
int lx[BMAX+1]
Definition inflate.c:1578
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
int val
Definition jpeglib.h:956
const char * msg
Definition missing_descriptor.c:20
Definition zynaddsubfx-src.cpp:569
T limit(T val, T min, T max)
Definition Util.h:85
const AbsTime * time
Definition PADnoteParameters.h:189
std::string to_s(T x)
Definition Util.h:67
const char * rtosc_argument_string(const char *msg)
Definition rtosc.c:11
rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
Definition rtosc.c:732
Definition rtosc.h:41
int32_t i
Definition rtosc.h:47
rtosc_blob_t b
Definition rtosc.h:55
int n
Definition crypt.c:458
memcpy(hh, h, RAND_HEAD_LEN)
ZCONST char * key
Definition crypt.c:587
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
b
Definition crypt.c:628
typedef int(UZ_EXP MsgFn)()
dy
Definition zipinfo.c:2288