Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
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.

738 lines
22KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2009 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. /* Filter module. Can host LADPSA Plugins, or can be inherited from to make internal
  19. modules with special features and appearance. */
  20. #include "const.h"
  21. #include "Plugin_Module.H"
  22. #include <Fl/fl_draw.H>
  23. #include <FL/Fl_Group.H>
  24. #include "util/debug.h"
  25. #include <string.h>
  26. #define HAVE_LIBLRDF 1
  27. #include "LADSPAInfo.h"
  28. #include <vector>
  29. #include <string>
  30. #include <ladspa.h>
  31. #include <stdlib.h>
  32. #include <math.h>
  33. #include "Engine/Engine.H"
  34. static LADSPAInfo *ladspainfo;
  35. Thread* Plugin_Module::plugin_discover_thread;
  36. /* keep this out of the header to avoid spreading ladspa.h dependency */
  37. struct Plugin_Module::ImplementationData
  38. {
  39. const LADSPA_Descriptor *descriptor;
  40. // std::vector<LADSPA_Data*> m_LADSPABufVec;
  41. std::vector<LADSPA_Handle> handle;
  42. };
  43. Plugin_Module::Plugin_Module ( ) : Module( 50, 35, name() )
  44. {
  45. init();
  46. end();
  47. log_create();
  48. }
  49. Plugin_Module::~Plugin_Module ( )
  50. {
  51. log_destroy();
  52. plugin_instances( 0 );
  53. }
  54. void
  55. Plugin_Module::get ( Log_Entry &e ) const
  56. {
  57. // char s[512];
  58. // snprintf( s, sizeof( s ), "ladspa:%lu", _idata->descriptor->UniqueID );
  59. e.add( ":plugin_id", _idata->descriptor->UniqueID );
  60. Module::get( e );
  61. }
  62. void
  63. Plugin_Module::set ( Log_Entry &e )
  64. {
  65. for ( int i = 0; i < e.size(); ++i )
  66. {
  67. const char *s, *v;
  68. e.get( i, &s, &v );
  69. if ( ! strcmp( s, ":plugin_id" ) )
  70. {
  71. load( (unsigned long) atoll ( v ) );
  72. }
  73. }
  74. Module::set( e );
  75. }
  76. #include <FL/Fl_Menu_Button.H>
  77. void
  78. Plugin_Module::add_plugins_to_menu ( Fl_Menu_Button *menu )
  79. {
  80. Plugin_Module::Plugin_Info *pia = Plugin_Module::get_all_plugins();
  81. char path[1024];
  82. for ( Plugin_Module::Plugin_Info *pi = pia; pi->path; ++pi )
  83. {
  84. snprintf( path, sizeof( path ), "%s/%s", "Plugin", pi->path );
  85. menu->add(path, 0, NULL, new unsigned long( pi->id ), 0 );
  86. }
  87. delete[] pia;
  88. }
  89. /* allow the user to pick a plugin */
  90. Plugin_Module *
  91. Plugin_Module::pick_plugin ( void )
  92. {
  93. /**************/
  94. /* build menu */
  95. /**************/
  96. Fl_Menu_Button *menu = new Fl_Menu_Button( 0, 0, 400, 400 );
  97. menu->type( Fl_Menu_Button::POPUP3 );
  98. Plugin_Module::Plugin_Info *pia = Plugin_Module::get_all_plugins();
  99. for ( Plugin_Module::Plugin_Info *pi = pia; pi->path; ++pi )
  100. {
  101. menu->add(pi->path, 0, NULL, pi, 0 );
  102. }
  103. menu->popup();
  104. if ( menu->value() <= 0 )
  105. return NULL;
  106. /************************/
  107. /* load selected plugin */
  108. /************************/
  109. Plugin_Module::Plugin_Info *pi = (Plugin_Module::Plugin_Info*)menu->menu()[ menu->value() ].user_data();
  110. if ( ! pi )
  111. return NULL;
  112. Plugin_Module *m = new Plugin_Module();
  113. m->load( pi->id );
  114. delete[] pia;
  115. return m;
  116. }
  117. void
  118. Plugin_Module::init ( void )
  119. {
  120. _idata = new Plugin_Module::ImplementationData();
  121. _idata->handle.clear();
  122. _active = false;
  123. _crosswire = false;
  124. align( (Fl_Align)FL_ALIGN_CENTER | FL_ALIGN_INSIDE );
  125. color( (Fl_Color)fl_color_average( FL_BLUE, FL_GREEN, 0.5f ) );
  126. int tw, th, tx, ty;
  127. bbox( tx, ty, tw, th );
  128. }
  129. #include "FL/test_press.H"
  130. int
  131. Plugin_Module::handle ( int m )
  132. {
  133. switch ( m )
  134. {
  135. case FL_ENTER:
  136. case FL_LEAVE:
  137. redraw();
  138. return 1;
  139. break;
  140. default:
  141. return Module::handle( m );
  142. }
  143. return 0;
  144. }
  145. /* There are two possible adaptations that can be made at Plugin_Module input to account for a mismatch
  146. between channel configurations.
  147. The two scenarios are as follows.
  148. 1. The preceding module has fewer outputs than this module has inputs. If
  149. the preceding module has 1 output (MONO) then it will be duplicated
  150. for this module's addition inputs. If the preceding module has more
  151. than one output, then the chain is in error.
  152. 2. The preceding module has more outputs than this module has inputs
  153. If this module has 1 output (MONO) then it will create the required number of
  154. instances of its plugin.
  155. Stereo plugins are never run with more than one instance. Mono
  156. plugins will have their outputs brought up to stereo for plugins with
  157. stereo input.
  158. */
  159. int
  160. Plugin_Module::can_support_inputs ( int n )
  161. {
  162. /* this is the simple case */
  163. if ( plugin_ins() == n )
  164. return plugin_outs();
  165. /* e.g. MONO going into STEREO */
  166. /* we'll duplicate our inputs */
  167. else if ( n < plugin_ins() &&
  168. 1 == n )
  169. {
  170. return plugin_outs();
  171. }
  172. /* e.g. STEREO going into MONO */
  173. /* we'll run multiple instances of the plugin */
  174. else if ( n > plugin_ins() &&
  175. ( plugin_ins() == 1 && plugin_outs() == 1 ) )
  176. {
  177. return n;
  178. }
  179. return -1;
  180. }
  181. bool
  182. Plugin_Module::configure_inputs( int n )
  183. {
  184. int inst = _idata->handle.size();
  185. if ( ninputs() != n )
  186. {
  187. _crosswire = false;
  188. if ( n != ninputs() )
  189. {
  190. if ( 1 == n && plugin_ins() > 1 )
  191. {
  192. DMESSAGE( "Cross-wiring plugin inputs" );
  193. _crosswire = true;
  194. audio_input.clear();
  195. for ( int i = n; i--; )
  196. audio_input.push_back( Port( this, Port::INPUT, Port::AUDIO ) );
  197. }
  198. else if ( n >= plugin_ins() &&
  199. ( plugin_ins() == 1 && plugin_outs() == 1 ) )
  200. {
  201. DMESSAGE( "Running multiple instances of plugin" );
  202. audio_input.clear();
  203. audio_output.clear();
  204. for ( int i = n; i--; )
  205. {
  206. add_port( Port( this, Port::INPUT, Port::AUDIO ) );
  207. add_port( Port( this, Port::OUTPUT, Port::AUDIO ) );
  208. }
  209. inst = n;
  210. }
  211. else if ( n == plugin_ins() )
  212. {
  213. DMESSAGE( "Plugin input configuration is a perfect match" );
  214. }
  215. else
  216. {
  217. DMESSAGE( "Unsupported input configuration" );
  218. return false;
  219. }
  220. }
  221. }
  222. if ( _active )
  223. deactivate();
  224. if ( plugin_instances( inst ) )
  225. instances( inst );
  226. else
  227. return false;
  228. if ( ! _active )
  229. activate();
  230. return true;
  231. }
  232. void *
  233. Plugin_Module::discover_thread ( void * v )
  234. {
  235. THREAD_ASSERT( Plugin_Discover );
  236. DMESSAGE( "Discovering plugins in the background" );
  237. ladspainfo = new LADSPAInfo();
  238. return NULL;
  239. }
  240. /* Spawn a background thread for plugin discovery */
  241. void
  242. Plugin_Module::spawn_discover_thread ( void )
  243. {
  244. if ( plugin_discover_thread )
  245. {
  246. FATAL( "Plugin discovery thread is already running or has completed" );
  247. }
  248. plugin_discover_thread = new Thread( "Plugin_Discover" );
  249. plugin_discover_thread->clone( &Plugin_Module::discover_thread, NULL );
  250. }
  251. /* return a list of available plugins */
  252. Plugin_Module::Plugin_Info *
  253. Plugin_Module::get_all_plugins ( void )
  254. {
  255. if ( !ladspainfo )
  256. {
  257. if ( ! plugin_discover_thread )
  258. ladspainfo = new LADSPAInfo();
  259. else
  260. plugin_discover_thread->join();
  261. }
  262. std::vector<LADSPAInfo::PluginEntry> plugins = ladspainfo->GetMenuList();
  263. Plugin_Info* pi = new Plugin_Info[plugins.size() + 1];
  264. int j = 0;
  265. for (std::vector<LADSPAInfo::PluginEntry>::iterator i=plugins.begin();
  266. i!=plugins.end(); i++, j++)
  267. {
  268. pi[j].path = i->Name.c_str();
  269. pi[j].id = i->UniqueID;
  270. }
  271. return pi;
  272. }
  273. bool
  274. Plugin_Module::plugin_instances ( unsigned int n )
  275. {
  276. if ( _idata->handle.size() > n )
  277. {
  278. for ( int i = _idata->handle.size() - n; i--; )
  279. {
  280. DMESSAGE( "Destroying plugin instance" );
  281. LADSPA_Handle h = _idata->handle.back();
  282. if ( _idata->descriptor->deactivate )
  283. _idata->descriptor->deactivate( h );
  284. if ( _idata->descriptor->cleanup )
  285. _idata->descriptor->cleanup( h );
  286. _idata->handle.pop_back();
  287. }
  288. }
  289. else if ( _idata->handle.size() < n )
  290. {
  291. for ( int i = n - _idata->handle.size(); i--; )
  292. {
  293. LADSPA_Handle h;
  294. DMESSAGE( "Instantiating plugin..." );
  295. if ( ! (h = _idata->descriptor->instantiate( _idata->descriptor, Engine::sample_rate() ) ) )
  296. {
  297. WARNING( "Failed to instantiate plugin" );
  298. return false;
  299. }
  300. DMESSAGE( "Instantiated: %p", h );
  301. _idata->handle.push_back( h );
  302. DMESSAGE( "Connecting control ports..." );
  303. int ij = 0;
  304. int oj = 0;
  305. for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k )
  306. {
  307. if ( LADSPA_IS_PORT_CONTROL( _idata->descriptor->PortDescriptors[k] ) )
  308. {
  309. if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[k] ) )
  310. _idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_input[ij++].buffer() );
  311. else if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[k] ) )
  312. _idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_output[oj++].buffer() );
  313. }
  314. }
  315. // connect ports to magic bogus value to aid debugging.
  316. for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k )
  317. if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[k] ) )
  318. _idata->descriptor->connect_port( h, k, (LADSPA_Data*)0x42 );
  319. }
  320. }
  321. return true;
  322. }
  323. bool
  324. Plugin_Module::load ( unsigned long id )
  325. {
  326. if ( !ladspainfo )
  327. {
  328. if ( ! plugin_discover_thread )
  329. ladspainfo = new LADSPAInfo();
  330. else
  331. plugin_discover_thread->join();
  332. }
  333. _idata->descriptor = ladspainfo->GetDescriptorByID( id );
  334. label( _idata->descriptor->Name );
  335. _plugin_ins = _plugin_outs = 0;
  336. if ( _idata->descriptor )
  337. {
  338. if ( LADSPA_IS_INPLACE_BROKEN( _idata->descriptor->Properties ) )
  339. {
  340. WARNING( "Cannot use this plugin because it is incapable of processing audio in-place" );
  341. return false;
  342. }
  343. else if ( ! LADSPA_IS_HARD_RT_CAPABLE( _idata->descriptor->Properties ) )
  344. {
  345. WARNING( "Cannot use this plugin because it is incapable of hard real-time operation" );
  346. return false;
  347. }
  348. MESSAGE( "Name: %s", _idata->descriptor->Name );
  349. for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i )
  350. {
  351. if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[i] ) )
  352. {
  353. if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[i] ) )
  354. {
  355. add_port( Port( this, Port::INPUT, Port::AUDIO, _idata->descriptor->PortNames[ i ] ) );
  356. _plugin_ins++;
  357. }
  358. else if (LADSPA_IS_PORT_OUTPUT(_idata->descriptor->PortDescriptors[i]))
  359. {
  360. _plugin_outs++;
  361. add_port( Port( this, Port::OUTPUT, Port::AUDIO, _idata->descriptor->PortNames[ i ] ) );
  362. }
  363. }
  364. }
  365. MESSAGE( "Plugin has %i inputs and %i outputs", _plugin_ins, _plugin_outs);
  366. for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i )
  367. {
  368. if ( LADSPA_IS_PORT_CONTROL( _idata->descriptor->PortDescriptors[i] ) )
  369. {
  370. Port::Direction d = Port::INPUT;
  371. if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[i] ) )
  372. {
  373. d = Port::INPUT;
  374. }
  375. else if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[i] ) )
  376. {
  377. d = Port::OUTPUT;
  378. }
  379. Port p( this, d, Port::CONTROL, _idata->descriptor->PortNames[ i ] );
  380. LADSPA_PortRangeHintDescriptor hd = _idata->descriptor->PortRangeHints[i].HintDescriptor;
  381. if ( LADSPA_IS_HINT_BOUNDED_BELOW(hd) )
  382. {
  383. p.hints.ranged = true;
  384. p.hints.minimum = _idata->descriptor->PortRangeHints[i].LowerBound;
  385. }
  386. if ( LADSPA_IS_HINT_BOUNDED_ABOVE(hd) )
  387. {
  388. p.hints.ranged = true;
  389. p.hints.maximum = _idata->descriptor->PortRangeHints[i].UpperBound;
  390. }
  391. if ( LADSPA_IS_HINT_HAS_DEFAULT(hd) )
  392. {
  393. float Max=1.0f, Min=-1.0f, Default=0.0f;
  394. int Port=i;
  395. // Get the bounding hints for the port
  396. LADSPA_PortRangeHintDescriptor HintDesc=_idata->descriptor->PortRangeHints[Port].HintDescriptor;
  397. if (LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc))
  398. {
  399. Min=_idata->descriptor->PortRangeHints[Port].LowerBound;
  400. if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc))
  401. {
  402. Min*=Engine::sample_rate();
  403. }
  404. }
  405. if (LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc))
  406. {
  407. Max=_idata->descriptor->PortRangeHints[Port].UpperBound;
  408. if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc))
  409. {
  410. Max*=Engine::sample_rate();
  411. }
  412. }
  413. #ifdef LADSPA_VERSION
  414. // We've got a version of the header that supports port defaults
  415. if (LADSPA_IS_HINT_HAS_DEFAULT(HintDesc)) {
  416. // LADSPA_HINT_DEFAULT_0 is assumed anyway, so we don't check for it
  417. if (LADSPA_IS_HINT_DEFAULT_1(HintDesc)) {
  418. Default = 1.0f;
  419. } else if (LADSPA_IS_HINT_DEFAULT_100(HintDesc)) {
  420. Default = 100.0f;
  421. } else if (LADSPA_IS_HINT_DEFAULT_440(HintDesc)) {
  422. Default = 440.0f;
  423. } else {
  424. // These hints may be affected by SAMPLERATE, LOGARITHMIC and INTEGER
  425. if (LADSPA_IS_HINT_DEFAULT_MINIMUM(HintDesc) &&
  426. LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc)) {
  427. Default=_idata->descriptor->PortRangeHints[Port].LowerBound;
  428. } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(HintDesc) &&
  429. LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc)) {
  430. Default=_idata->descriptor->PortRangeHints[Port].UpperBound;
  431. } else if (LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc) &&
  432. LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc)) {
  433. // These hints require both upper and lower bounds
  434. float lp = 0.0f, up = 0.0f;
  435. float min = _idata->descriptor->PortRangeHints[Port].LowerBound;
  436. float max = _idata->descriptor->PortRangeHints[Port].UpperBound;
  437. if (LADSPA_IS_HINT_DEFAULT_LOW(HintDesc)) {
  438. lp = 0.75f;
  439. up = 0.25f;
  440. } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(HintDesc)) {
  441. lp = 0.5f;
  442. up = 0.5f;
  443. } else if (LADSPA_IS_HINT_DEFAULT_HIGH(HintDesc)) {
  444. lp = 0.25f;
  445. up = 0.75f;
  446. }
  447. if (LADSPA_IS_HINT_LOGARITHMIC(HintDesc)) {
  448. p.hints.type = Port::Hints::LOGARITHMIC;
  449. if (min==0.0f || max==0.0f) {
  450. // Zero at either end means zero no matter
  451. // where hint is at, since:
  452. // log(n->0) -> Infinity
  453. Default = 0.0f;
  454. } else {
  455. // Catch negatives
  456. bool neg_min = min < 0.0f ? true : false;
  457. bool neg_max = max < 0.0f ? true : false;
  458. if (!neg_min && !neg_max) {
  459. Default = exp(::log(min) * lp + ::log(max) * up);
  460. } else if (neg_min && neg_max) {
  461. Default = -exp(::log(-min) * lp + ::log(-max) * up);
  462. } else {
  463. // Logarithmic range has asymptote
  464. // so just use linear scale
  465. Default = min * lp + max * up;
  466. }
  467. }
  468. } else {
  469. Default = min * lp + max * up;
  470. }
  471. }
  472. if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc)) {
  473. Default *= Engine::sample_rate();
  474. }
  475. if (LADSPA_IS_HINT_INTEGER(HintDesc)) {
  476. if ( p.hints.ranged &&
  477. 0 == p.hints.minimum &&
  478. 1 == p.hints.maximum )
  479. p.hints.type = Port::Hints::BOOLEAN;
  480. else
  481. p.hints.type = Port::Hints::INTEGER;
  482. Default = floorf(Default);
  483. }
  484. if (LADSPA_IS_HINT_TOGGLED(HintDesc)){
  485. p.hints.type = Port::Hints::BOOLEAN;
  486. }
  487. }
  488. }
  489. #else
  490. Default = 0.0f;
  491. #endif
  492. p.hints.default_value = Default;
  493. }
  494. float *control_value = new float;
  495. *control_value = p.hints.default_value;
  496. p.connect_to( control_value );
  497. add_port( p );
  498. DMESSAGE( "Plugin has control port \"%s\" (default: %f)", _idata->descriptor->PortNames[ i ], p.hints.default_value );
  499. }
  500. }
  501. }
  502. else
  503. {
  504. WARNING( "Failed to load plugin" );
  505. return false;
  506. }
  507. return plugin_instances( 1 );
  508. }
  509. void
  510. Plugin_Module::set_input_buffer ( int n, void *buf )
  511. {
  512. LADSPA_Handle h;
  513. if ( instances() > 1 )
  514. {
  515. h = _idata->handle[n];
  516. n = 0;
  517. }
  518. else
  519. h = _idata->handle[0];
  520. for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i )
  521. if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[i] ) &&
  522. LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[i] ) )
  523. if ( n-- == 0 )
  524. _idata->descriptor->connect_port( h, i, (LADSPA_Data*)buf );
  525. }
  526. void
  527. Plugin_Module::set_output_buffer ( int n, void *buf )
  528. {
  529. LADSPA_Handle h;
  530. if ( instances() > 1 )
  531. {
  532. h = _idata->handle[n];
  533. n = 0;
  534. }
  535. else
  536. h = _idata->handle[0];
  537. for ( unsigned int i = 0; i < _idata->descriptor->PortCount; ++i )
  538. if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[i] ) &&
  539. LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[i] ) )
  540. if ( n-- == 0 )
  541. _idata->descriptor->connect_port( h, i, (LADSPA_Data*)buf );
  542. }
  543. void
  544. Plugin_Module::activate ( void )
  545. {
  546. if ( _active )
  547. FATAL( "Attempt to activate already active plugin" );
  548. if ( _idata->descriptor->activate )
  549. for ( unsigned int i = 0; i < _idata->handle.size(); ++i )
  550. _idata->descriptor->activate( _idata->handle[i] );
  551. _active = true;
  552. }
  553. void
  554. Plugin_Module::deactivate( void )
  555. {
  556. if ( _idata->descriptor->deactivate )
  557. for ( unsigned int i = 0; i < _idata->handle.size(); ++i )
  558. _idata->descriptor->activate( _idata->handle[i] );
  559. _active = false;
  560. }
  561. void
  562. Plugin_Module::handle_port_connection_change ( void )
  563. {
  564. // DMESSAGE( "Connecting audio ports" );
  565. if ( _crosswire )
  566. {
  567. for ( int i = 0; i < plugin_ins(); ++i )
  568. set_input_buffer( i, audio_input[0].buffer() );
  569. }
  570. else
  571. {
  572. for ( unsigned int i = 0; i < audio_input.size(); ++i )
  573. set_input_buffer( i, audio_input[i].buffer() );
  574. }
  575. for ( unsigned int i = 0; i < audio_output.size(); ++i )
  576. set_output_buffer( i, audio_output[i].buffer() );
  577. }
  578. void
  579. Plugin_Module::process ( )
  580. {
  581. handle_port_connection_change();
  582. if ( _active )
  583. for ( unsigned int i = 0; i < _idata->handle.size(); ++i )
  584. {
  585. volatile int n = i;
  586. _idata->descriptor->run( _idata->handle[n], nframes() );
  587. }
  588. }