Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
5.2KB

  1. #include "EnvelopeFreeEdit.h"
  2. #include "../Misc/Util.h"
  3. #include <FL/Fl.H>
  4. #include <FL/fl_draw.H>
  5. #include <cstdlib>
  6. #include <cassert>
  7. #include <rtosc/rtosc.h>
  8. EnvelopeFreeEdit::EnvelopeFreeEdit(int x,int y, int w, int h, const char *label)
  9. :Fl_Box(x,y,w,h,label), Fl_Osc_Widget(this)
  10. {
  11. pair=NULL;
  12. currentpoint=-1;
  13. cpx=0;
  14. lastpoint=-1;
  15. }
  16. void EnvelopeFreeEdit::init(void)
  17. {
  18. oscRegister("Penvpoints");
  19. oscRegister("Penvdt");
  20. oscRegister("Penvval");
  21. oscRegister("Penvsustain");
  22. }
  23. void EnvelopeFreeEdit::OSC_raw(const char *msg)
  24. {
  25. const char *args = rtosc_argument_string(msg);
  26. if(strstr(msg,"Penvpoints") && !strcmp(args, "c")) {
  27. Penvpoints = rtosc_argument(msg, 0).i;
  28. } else if(strstr(msg,"Penvdt") && !strcmp(args, "b")) {
  29. rtosc_blob_t b = rtosc_argument(msg, 0).b;
  30. assert(b.len == MAX_ENVELOPE_POINTS);
  31. memcpy(Penvdt, b.data, MAX_ENVELOPE_POINTS);
  32. } else if(strstr(msg,"Penvval") && !strcmp(args, "b")) {
  33. rtosc_blob_t b = rtosc_argument(msg, 0).b;
  34. assert(b.len == MAX_ENVELOPE_POINTS);
  35. memcpy(Penvval, b.data, MAX_ENVELOPE_POINTS);
  36. } else if(strstr(msg,"Penvsustain") && !strcmp(args, "c")) {
  37. Penvsustain = rtosc_argument(msg, 0).i;
  38. }
  39. redraw();
  40. do_callback();
  41. }
  42. void EnvelopeFreeEdit::setpair(Fl_Box *pair_)
  43. {
  44. pair=pair_;
  45. }
  46. int EnvelopeFreeEdit::getpointx(int n) const
  47. {
  48. const int lx=w()-10;
  49. int npoints=Penvpoints;
  50. float sum=0;
  51. for(int i=1; i<npoints; ++i)
  52. sum+=getdt(i)+1;
  53. float sumbefore=0;//the sum of all points before the computed point
  54. for(int i=1; i<=n; ++i)
  55. sumbefore+=getdt(i)+1;
  56. return (int) (sumbefore/(float) sum*lx);
  57. }
  58. int EnvelopeFreeEdit::getpointy(int n) const
  59. {
  60. const int ly=h()-10;
  61. return (1.0-Penvval[n]/127.0)*ly;
  62. }
  63. int EnvelopeFreeEdit::getnearest(int x,int y) const
  64. {
  65. x-=5;y-=5;
  66. int nearestpoint=0;
  67. int nearestval=1000000;//a big value
  68. for(int i=0; i<Penvpoints; ++i){
  69. int distance=abs(x-getpointx(i))+abs(y-getpointy(i));
  70. if (distance<nearestval) {
  71. nearestpoint=i;
  72. nearestval=distance;
  73. }
  74. }
  75. return nearestpoint;
  76. }
  77. static float dt(char val)
  78. {
  79. return (powf(2.0f, val / 127.0f * 12.0f) - 1.0f) * 10.0f; //miliseconds
  80. }
  81. float EnvelopeFreeEdit::getdt(int i) const
  82. {
  83. return dt(Penvdt[i]);
  84. }
  85. void EnvelopeFreeEdit::draw(void)
  86. {
  87. int ox=x(),oy=y(),lx=w(),ly=h();
  88. //if (env->Pfreemode==0)
  89. // env->converttofree();
  90. const int npoints=Penvpoints;
  91. if (active_r()) fl_color(FL_BLACK);
  92. else fl_color(90,90,90);
  93. if (!active_r()) currentpoint=-1;
  94. fl_rectf(ox,oy,lx,ly);
  95. //Margins
  96. ox+=5;oy+=5;lx-=10;ly-=10;
  97. //draw the lines
  98. fl_color(FL_GRAY);
  99. fl_line_style(FL_SOLID);
  100. fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2);
  101. //draws the evelope points and lines
  102. Fl_Color alb=FL_WHITE;
  103. if (!active_r()) alb=fl_rgb_color(180,180,180);
  104. fl_color(alb);
  105. int oldxx=0,xx=0,oldyy=0,yy=getpointy(0);
  106. fl_rectf(ox-3,oy+yy-3,6,6);
  107. for (int i=1; i<npoints; ++i){
  108. oldxx=xx;oldyy=yy;
  109. xx=getpointx(i);yy=getpointy(i);
  110. if (i==currentpoint) fl_color(FL_RED);
  111. else fl_color(alb);
  112. fl_line(ox+oldxx,oy+oldyy,ox+xx,oy+yy);
  113. fl_rectf(ox+xx-3,oy+yy-3,6,6);
  114. }
  115. //draw the last moved point point (if exists)
  116. if (lastpoint>=0){
  117. fl_color(FL_CYAN);
  118. fl_rectf(ox+getpointx(lastpoint)-5,oy+getpointy(lastpoint)-5,10,10);
  119. }
  120. //draw the sustain position
  121. if(Penvsustain>0){
  122. fl_color(FL_YELLOW);
  123. xx=getpointx(Penvsustain);
  124. fl_line(ox+xx,oy+0,ox+xx,oy+ly);
  125. }
  126. //Show the envelope duration and the current line duration
  127. fl_font(FL_HELVETICA|FL_BOLD,10);
  128. float time=0.0;
  129. if (currentpoint<=0){
  130. fl_color(alb);
  131. for(int i=1; i<npoints; ++i)
  132. time+=getdt(i);
  133. } else {
  134. fl_color(255,0,0);
  135. time=getdt(currentpoint);
  136. }
  137. char tmpstr[20];
  138. if (time<1000.0)
  139. snprintf((char *)&tmpstr,20,"%.1fms",time);
  140. else
  141. snprintf((char *)&tmpstr,20,"%.2fs",time/1000.0);
  142. fl_draw(tmpstr,ox+lx-20,oy+ly-10,20,10,FL_ALIGN_RIGHT,NULL,0);
  143. }
  144. int EnvelopeFreeEdit::handle(int event)
  145. {
  146. const int x_=Fl::event_x()-x();
  147. const int y_=Fl::event_y()-y();
  148. if (event==FL_PUSH) {
  149. currentpoint=getnearest(x_,y_);
  150. cpx=x_;
  151. cpdt=Penvdt[currentpoint];
  152. lastpoint=currentpoint;
  153. redraw();
  154. if (pair)
  155. pair->redraw();
  156. }
  157. if (event==FL_RELEASE){
  158. currentpoint=-1;
  159. redraw();
  160. if (pair)
  161. pair->redraw();
  162. }
  163. if (event==FL_DRAG && currentpoint>=0){
  164. int ny=limit(127-(int) (y_*127.0/h()), 0, 127);
  165. Penvval[currentpoint]=ny;
  166. const int dx=(int)((x_-cpx)*0.1);
  167. const int newdt=limit(cpdt+dx,0,127);
  168. if(currentpoint!=0)
  169. Penvdt[currentpoint]=newdt;
  170. else
  171. Penvdt[currentpoint]=0;
  172. oscWrite(to_s("Penvdt")+to_s(currentpoint), "c", newdt);
  173. redraw();
  174. if(pair)
  175. pair->redraw();
  176. }
  177. return 1;
  178. }
  179. void EnvelopeFreeEdit::update(void)
  180. {
  181. oscWrite("Penvpoints");
  182. oscWrite("Penvdt");
  183. oscWrite("Penvval");
  184. oscWrite("Penvsustain");
  185. }