Programmable real-time audio signal processing application
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.

cmGrTksrFltk.cpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. #include <FL/Fl.H>
  2. #include <Fl/fl_draw.h>
  3. #include <FL/Fl_Widget.H>
  4. #include <FL/Fl_Double_Window.H>
  5. #include <Fl/Fl_Output.H>
  6. #include <Fl/Fl_Menu_Bar.H>
  7. #include <vector>
  8. #include "Fl_CbLinker.h"
  9. #include "cmGlobal.h"
  10. #include "cmFloatTypes.h"
  11. #include "cmRpt.h"
  12. #include "cmErr.h"
  13. #include "cmCtx.h"
  14. #include "cmMem.h"
  15. #include "cmMallocDebug.h"
  16. #include "cmLinkedHeap.h"
  17. #include "cmText.h"
  18. #include "cmThread.h"
  19. #include "cmPrefs.h"
  20. #include "cmSymTbl.h"
  21. #include "cmTime.h"
  22. #include "cmMidi.h"
  23. #include "cmMidiFile.h"
  24. #include "cmAudioFile.h"
  25. #include "cmAudioFileMgr.h"
  26. #include "cmTimeLine.h"
  27. #include "cmScore.h"
  28. #include "cmTakeSeqBldr.h"
  29. #include "cmGr.h"
  30. #include "cmGrDevCtx.h"
  31. #include "cmGrPlot.h"
  32. #include "cmGrPage.h"
  33. #include "cmGrFltk.h"
  34. #include "gvHashFunc.h"
  35. #include "cmGrTksrFltk.h"
  36. #include "cmGrPlotAudio.h"
  37. #include "cmdIf.h"
  38. cmGrTksrFltk::cmGrTksrFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menu, int x, int y, int w, int h)
  39. : cmGrPlotFltk(ctx,x,y,w,h),
  40. //_cmdIf(cp),
  41. _tksbH(cmTakeSeqBldrNullHandle),
  42. _menuBar(menu),
  43. _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId),
  44. //_objSecs(0),
  45. _objId(0)
  46. //_togFl(true)
  47. {
  48. cmErrSetup(&_err,&ctx->rpt,"cmGrTksrFltk");
  49. _createMenu();
  50. if( cmGrPageIsValid(pageHandle()) == false )
  51. return;
  52. initViews(1,1);
  53. unsigned vwIdx = 0;
  54. cmGrPgH_t pgH = pageHandle();
  55. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx);
  56. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  57. cmGrAxH_t axH = cmGrAxNullHandle;
  58. cmGrVExt_t limExt;
  59. _samplesMetricId = cmGrPageLabelFuncRegister( pgH, gvRoundHashValueFunc, this, "Round" );
  60. _secondsMetricId = cmGrPageLabelFuncRegister( pgH, gvMinSecMsHashValueFunc, this, "Min:Sec:Ms" );
  61. unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( pgH, gvMidiSciPitchValueFunc, this, "Pitch" );
  62. cmGrVExtSetD(&limExt,0,0,0,127);
  63. cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt );
  64. cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kTopGrFl | kBottomGrFl );
  65. axH = cmGrViewAxisHandle(vwH, kTopGrIdx);
  66. cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashMarkGrFl | kHashLabelGrFl ));
  67. axH = cmGrViewAxisHandle(vwH, kLeftGrIdx );
  68. cmGrAxisSetLabelFunc( axH, pitchLabelFuncId );
  69. cmGrViewSetLabelFunc( vwH, kLeftGrIdx, pitchLabelFuncId );
  70. axH = cmGrViewAxisHandle(vwH, kRightGrIdx);
  71. cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashLabelGrFl ));
  72. cmGrViewSetCfg( vwH, cmSetFlag(cmGrViewCfg(vwH),kSelectHorzGrFl) );
  73. }
  74. cmGrTksrFltk::~cmGrTksrFltk()
  75. {}
  76. void cmGrTksrFltk::setTksbHandle( void* v )
  77. {
  78. _tksbH.h = v;
  79. }
  80. void cmGrTksrFltk::refresh()
  81. {
  82. if( cmGrPlotClear( plotHandle() ) != kOkGrPlRC )
  83. {
  84. cmErrMsg(&_err,kClearPlotFailRC,"Plot clear failed.");
  85. return;
  86. }
  87. if( cmTakeSeqBldrIsValid(_tksbH) == false )
  88. return;
  89. // insert tksb events here
  90. cmTakeSeqBldrRendReset(_tksbH);
  91. cmTksbRend_t m;
  92. unsigned absSmpIdx = 0;
  93. double srate = cmTakeSeqBldrSampleRate(_tksbH);
  94. while( cmTakeSeqBldrRendNext(_tksbH,&m) )
  95. {
  96. m.evt.smpIdx = absSmpIdx;
  97. _insertEvent(&m,srate);
  98. absSmpIdx += m.offsetSmp;
  99. }
  100. }
  101. double cmGrTksrFltk::sampleRate() const
  102. {
  103. if( cmTakeSeqBldrIsValid(_tksbH) )
  104. return cmTakeSeqBldrSampleRate(_tksbH);
  105. return 0;
  106. }
  107. bool cmGrTksrFltk::on_plot_object( cmGrPlotCbArg_t* arg )
  108. {
  109. /*
  110. if( arg->selId==kStateChangeGrPlId && cmIsFlag(arg->deltaFlags,kSelectGrPlFl) )
  111. {
  112. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(arg->objH);
  113. unsigned state = cmGrPlotObjStateFlags(arg->objH);
  114. bool isSelectedFl = cmIsFlag( state, kSelectGrPlFl);
  115. if( sop != NULL )
  116. {
  117. //printf("SELECT:%i %i 0x%x\n",cmGrPlotObjId(arg->objH),isSelectedFl,state);
  118. if( sop->id==kTakeTksrId && sop->u.tlMarkerUid!=cmInvalidId )
  119. {
  120. if( isSelectedFl )
  121. cmTakeSeqBldrLoadTake(_tksbH,sop->u.tlMarkerUid,true);
  122. else
  123. cmTakeSeqBldrUnloadTake(_tksbH,sop->u.tlMarkerUid);
  124. setStatusText(cmTsPrintfS("%s", cmStringNullGuard(cmTakeSeqBldrScTrkTakeText(_tksbH,sop->u.tlMarkerUid))));
  125. }
  126. if( sop->id==kEventTksrId && sop->u.ep!=NULL && sop->u.ep->type==kBarEvtScId )
  127. {
  128. _lastBarPlotObjH = arg->objH;
  129. // callback to: kcApp::_ctl_cb(ctl_t* cp)
  130. callback()(this,user_data());
  131. }
  132. }
  133. }
  134. */
  135. return true;
  136. }
  137. void cmGrTksrFltk::_insertEvent( const cmTksbRend_t* m, double srate )
  138. {
  139. if( cmGrPageIsValid(pageHandle()) == false )
  140. return;
  141. cmGrPlH_t plH = plotHandle();
  142. cmGrPgH_t pgH = pageHandle();
  143. unsigned vwIdx = 0;
  144. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx );
  145. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  146. cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle;
  147. cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle;
  148. cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle;
  149. cmGrPlObjH_t objH = cmGrPlObjNullHandle;
  150. cmGrPlObjTypeId_t objTypeId = kRectGrPlId;
  151. cmReal_t x = m->evt.smpIdx / srate;
  152. cmReal_t y = 0;
  153. cmReal_t h = 1;
  154. cmReal_t w = m->durSmp / srate;
  155. const cmChar_t* label = NULL;
  156. unsigned flags = kNoDragGrPlFl;
  157. tksrId_t tid = kInvalidTksrId;
  158. if( cmMidiIsNoteOn(m->evt.status) )
  159. {
  160. tid = kNoteTksrId;
  161. y = m->evt.d0;
  162. label = cmMidiToSciPitch(m->evt.d0,NULL,0);
  163. }
  164. else
  165. {
  166. if( cmMidiIsPedalDown(m->evt.status,m->evt.d0,m->evt.d1) )
  167. {
  168. tid = kPedalTksrId;
  169. y = 120;
  170. label = cmMidiPedalLabel(m->evt.d0);
  171. flags |= kNoFillGrPlFl;
  172. }
  173. }
  174. if( tid == kInvalidTksrId )
  175. return;
  176. //printf("absSmpIdx:%f %f\n",x,w);
  177. // create the plot object to represent this event
  178. if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, NULL ) != kOkGrPlRC )
  179. {
  180. cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score event.", cmStringNullGuard(label));
  181. return;
  182. }
  183. // store the score event reference as custom data inside the plot object
  184. scObj_t scObj(tid,m->rid);
  185. cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj));
  186. switch( tid )
  187. {
  188. case kNoteTksrId:
  189. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) );
  190. cmGrPlotObjSetFontSize(objH,8);
  191. break;
  192. case kPedalTksrId:
  193. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kDeepPinkGrId );
  194. cmGrPlotObjSetFontSize(objH,8);
  195. break;
  196. default:
  197. break;
  198. }
  199. }
  200. #define cmMENU_TITLE "Rndr"
  201. void cmGrTksrFltk::_createMenu( )
  202. {
  203. int idx = _menuBar->add(cmMENU_TITLE,0,NULL,0,FL_SUBMENU);
  204. const char* titleArray[] = { "Pitch", "ScEvtIdx", "Delete", "Sustain", "Sostenuto", "Write", "Read" };
  205. bool onFl[] = { true, false, false, false, false, false, false };
  206. bool checkFl[] = { true, true, false, false, false, false, false };
  207. int i;
  208. for(i=0; i<kMenuItemCnt; ++i)
  209. {
  210. _menuArray[i].id = i;
  211. _menuArray[i].p = this;
  212. _menuBar->insert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, checkFl[i] ? FL_MENU_TOGGLE : 0 );
  213. if( onFl[i] )
  214. {
  215. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1;
  216. mip->set();
  217. }
  218. }
  219. _menuBar->redraw();
  220. }
  221. bool cmGrTksrFltk::_isMenuChecked( int id )
  222. {
  223. unsigned i;
  224. // locate the menu item assoc'd with id
  225. for(i=0; i<kMenuItemCnt; ++i)
  226. if( _menuArray[i].id == id )
  227. break;
  228. assert( i < kMenuItemCnt );
  229. int menuIdx;
  230. if(( menuIdx = _menuBar->find_index(cmMENU_TITLE)) == -1 )
  231. return false;
  232. // The menu items and _menuArray[] were initialized in the same order
  233. // therefore the offset from the base of both should be the same.
  234. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + menuIdx + i + 1;
  235. assert( (item_t*)mip->user_data() == _menuArray + i );
  236. return mip->value() != 0;
  237. }
  238. void cmGrTksrFltk::_setEventLabels()
  239. {
  240. enum { kPitchFl=0x01, kScEvtFl=0x02 };
  241. if( cmTakeSeqBldrIsValid( _tksbH ) == false )
  242. return;
  243. cmGrPlH_t plH = plotHandle();
  244. unsigned flags = 0;
  245. flags |= _isMenuChecked(kPitchMId) ? kPitchFl : 0;
  246. flags |= _isMenuChecked(kScEvtMId) ? kScEvtFl : 0;
  247. unsigned n = cmGrPlotObjectCount(plH);
  248. unsigned i;
  249. for(i=0; i<n; ++i)
  250. {
  251. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  252. if( cmGrPlotObjIsValid(poH) )
  253. {
  254. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  255. if( sop!=NULL && sop->id==kNoteTksrId && sop->u.rid!=cmInvalidId )
  256. {
  257. cmTksbRend_t r;
  258. if( cmTakeSeqBldrRendInfo( _tksbH, sop->u.rid, &r ) == kOkTsbRC )
  259. {
  260. int bufN = 255;
  261. cmChar_t buf[ bufN+1 ];
  262. buf[bufN] = 0;
  263. buf[0] = 0;
  264. if( cmIsFlag(flags,kPitchFl) && r.evt.status == kNoteOnMdId )
  265. snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(r.evt.d0,NULL,0));
  266. if( cmIsFlag(flags,kScEvtFl) && r.scEvtIdx != cmInvalidIdx )
  267. snprintf(buf+strlen(buf),bufN-strlen(buf),"sei:%i ",r.scEvtIdx);
  268. cmGrPlotObjSetLabel(poH, buf );
  269. }
  270. }
  271. }
  272. }
  273. }
  274. void cmGrTksrFltk::_s_deleteSelectedEle( void* arg, cmGrPlObjH_t oh )
  275. {
  276. if( cmIsFlag(cmGrPlotObjStateFlags(oh), kSelectGrPlFl) )
  277. {
  278. cmGrTksrFltk* p = (cmGrTksrFltk*)arg;
  279. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(oh);
  280. cmTakeSeqBldrRendDelete( p->_tksbH, sop->u.rid );
  281. }
  282. }
  283. void cmGrTksrFltk::_write()
  284. {
  285. const cmChar_t* fn = "/home/kevin/temp/kr/tksb/tksb0.js";
  286. if( cmTakeSeqBldrIsValid(_tksbH) == false )
  287. return;
  288. if( cmTakeSeqBldrWrite( _tksbH, fn ) != kOkTsbRC )
  289. cmErrMsg(&_err,kTksbFailRC,"Render write failed for '%s'.",cmStringNullGuard(fn));
  290. }
  291. void cmGrTksrFltk::_read()
  292. {
  293. const cmChar_t* fn = "/home/kevin/temp/kr/tksb/tksb0.js";
  294. if( cmTakeSeqBldrIsValid(_tksbH) == false )
  295. return;
  296. if( cmTakeSeqBldrRead( _tksbH, fn ) != kOkTsbRC )
  297. cmErrMsg(&_err,kTksbFailRC,"Render write failed for '%s'.",cmStringNullGuard(fn));
  298. }
  299. void cmGrTksrFltk::_insertPedal( unsigned long pedalMId )
  300. {
  301. if( cmTakeSeqBldrIsValid(_tksbH) == false )
  302. return;
  303. unsigned vwIdx = 0;
  304. cmGrPgH_t pgH = pageHandle();
  305. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx);
  306. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  307. double srate = cmTakeSeqBldrSampleRate(_tksbH);
  308. cmGrVPt_t pt0,pt1;
  309. unsigned rid;
  310. cmTksbEvent_t e;
  311. memset(&e,0,sizeof(e));
  312. cmGrSelectPoints( cvH, &pt0, &pt1 );
  313. unsigned durSmp = (pt1.x - pt0.x) * srate;
  314. e.status = kCtlMdId;
  315. switch( pedalMId )
  316. {
  317. case kSustainMId:
  318. e.d0 = kSustainCtlMdId;
  319. break;
  320. case kSostenutoMId:
  321. e.d0 = kSostenutoCtlMdId;
  322. break;
  323. }
  324. //printf("x0:%f x1:%f %i\n",pt0.x,pt1.x,durSmp);
  325. e.smpIdx = pt0.x * srate;
  326. e.d1 = 127;
  327. cmTakeSeqBldrRendInsert( _tksbH, &e, durSmp, &rid );
  328. e.smpIdx = pt1.x * srate;
  329. e.d1 = 0;
  330. cmTakeSeqBldrRendInsert( _tksbH, &e, 0, &rid );
  331. refresh();
  332. }
  333. void cmGrTksrFltk::_s_menuCallback(Fl_Widget* w, void* arg )
  334. {
  335. item_t* ip = (item_t*)arg;
  336. cmGrTksrFltk* p = ip->p;
  337. unsigned long id = ip->id;
  338. switch( id )
  339. {
  340. case kPitchMId:
  341. case kScEvtMId:
  342. p->_setEventLabels();
  343. p->redraw();
  344. break;
  345. case kDeleteMId:
  346. cmGrPlotObjCb(p->plotHandle(),_s_deleteSelectedEle,p);
  347. p->refresh();
  348. p->redraw();
  349. break;
  350. case kSustainMId:
  351. case kSostenutoMId:
  352. p->_insertPedal(id);
  353. p->refresh();
  354. p->redraw();
  355. break;
  356. case kWriteMId:
  357. p->_write();
  358. break;
  359. case kReadMId:
  360. p->_read();
  361. break;
  362. }
  363. }