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.

863 lines
26KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2013 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. #include <FL/fl_draw.H>
  19. #include <FL/Fl_Box.H>
  20. #include "Spatializer_Module.H"
  21. #include "dsp.h"
  22. #include "Module_Parameter_Editor.H"
  23. static const float max_distance = 15.0f;
  24. #include <math.h>
  25. class filter
  26. {
  27. protected:
  28. float _sample_rate;
  29. float _w;
  30. float _last_output;
  31. float _last_cutoff;
  32. float _amount_of_current;
  33. float _amount_of_last;
  34. bool _bypass;
  35. void recalculate ( float cutoff )
  36. {
  37. _last_cutoff = cutoff;
  38. if (_last_cutoff <= 10 )
  39. {
  40. _bypass = true;
  41. }
  42. else if (_last_cutoff > _sample_rate * 0.5f )
  43. {
  44. _bypass = true;
  45. }
  46. else
  47. {
  48. const float c = 2.0f - cosf(_w * _last_cutoff);
  49. _amount_of_last = c - sqrtf(c * c - 1.0f);
  50. _amount_of_current = 1 - _amount_of_last;
  51. _bypass = false;
  52. }
  53. }
  54. public:
  55. void sample_rate ( nframes_t srate )
  56. {
  57. _sample_rate = srate;
  58. _w = (2 * M_PI) / (float)srate;
  59. }
  60. filter ()
  61. {
  62. _last_output = 0;
  63. _last_cutoff = 0;
  64. _w = 0;
  65. _sample_rate = 0;
  66. _amount_of_current = 0;
  67. _amount_of_last = 0;
  68. _bypass = false;
  69. }
  70. void
  71. run_lowpass ( float *buf, float cutoff, nframes_t nframes )
  72. {
  73. if (cutoff != _last_cutoff)
  74. {
  75. recalculate( cutoff );
  76. }
  77. if ( !_bypass )
  78. {
  79. while ( nframes-- )
  80. {
  81. *buf = _last_output = (_amount_of_current * *buf + _amount_of_last * _last_output);
  82. buf++;
  83. }
  84. }
  85. }
  86. void
  87. run_highpass ( float *buf, float cutoff, nframes_t nframes )
  88. {
  89. if (cutoff != _last_cutoff)
  90. {
  91. recalculate( cutoff );
  92. }
  93. if ( !_bypass )
  94. {
  95. while ( nframes-- )
  96. {
  97. _last_output = ((_amount_of_current * *buf) + (_amount_of_last * _last_output));
  98. *buf = *buf - _last_output;
  99. buf++;
  100. }
  101. }
  102. }
  103. };
  104. class delay
  105. {
  106. unsigned int _sample_rate;
  107. float *_buffer;
  108. long _write_index;
  109. unsigned int _buffer_mask;
  110. float _max_delay;
  111. nframes_t _samples_since_motion;
  112. nframes_t _interpolation_delay_samples;
  113. float _interpolation_delay_coeff;
  114. public:
  115. void sample_rate ( float srate )
  116. {
  117. if ( _buffer )
  118. free( _buffer );
  119. unsigned int size, minsize;
  120. minsize = (unsigned long)(srate * _max_delay);
  121. size = 1;
  122. while (size < minsize)
  123. size <<= 1;
  124. _buffer = (float *)calloc(size, sizeof(float));
  125. _buffer_mask = size - 1;
  126. _sample_rate = srate;
  127. _write_index = 0;
  128. _interpolation_delay_samples = 0.2f * srate;
  129. _interpolation_delay_coeff = 1.0f / (float)_interpolation_delay_samples;
  130. }
  131. delay ( float max_delay )
  132. {
  133. _interpolation_delay_samples = 0;
  134. _interpolation_delay_coeff = 0;
  135. _samples_since_motion = 0;
  136. _max_delay = max_delay;
  137. _write_index = 0;
  138. _sample_rate = 0;
  139. _buffer = 0;
  140. _buffer_mask =0;
  141. }
  142. ~delay ( )
  143. {
  144. if ( _buffer )
  145. free( _buffer );
  146. }
  147. void run ( float *buf, float *delaybuf, float delay, nframes_t nframes )
  148. {
  149. const nframes_t min_delay_samples = 4;
  150. if ( delaybuf )
  151. {
  152. for (nframes_t i = 0; i < nframes; i++ )
  153. {
  154. float delay_samples = delaybuf[i] * _sample_rate;
  155. if ( delay_samples > _buffer_mask + 1 )
  156. delay_samples = _buffer_mask;
  157. else if ( delay_samples < min_delay_samples )
  158. delay_samples = min_delay_samples;
  159. long idelay_samples = (long)delay_samples;
  160. const float frac = delay_samples - idelay_samples;
  161. const long read_index = _write_index - idelay_samples;
  162. _buffer[_write_index++ & _buffer_mask] = buf[i];
  163. const float read = interpolate_cubic (frac,
  164. _buffer[(read_index-1) & _buffer_mask],
  165. _buffer[read_index & _buffer_mask],
  166. _buffer[(read_index+1) & _buffer_mask],
  167. _buffer[(read_index+2) & _buffer_mask]);
  168. buf[i] = read;
  169. }
  170. _samples_since_motion = 0;
  171. }
  172. else
  173. {
  174. float delay_samples = delay * _sample_rate;
  175. if ( delay_samples > _buffer_mask + 1 )
  176. delay_samples = _buffer_mask;
  177. else if ( delay_samples < min_delay_samples )
  178. delay_samples = min_delay_samples;
  179. long idelay_samples = (long)delay_samples;
  180. if ( _samples_since_motion >= _interpolation_delay_samples )
  181. {
  182. /* switch to non-interpolating mode */
  183. for (nframes_t i = 0; i < nframes; i++ )
  184. {
  185. const long read_index = _write_index - idelay_samples;
  186. _buffer[_write_index++ & _buffer_mask] = buf[i];
  187. const float read = _buffer[read_index & _buffer_mask];
  188. buf[i] = read;
  189. }
  190. }
  191. else
  192. {
  193. /* linearly interpolate our way to an integer sample delay */
  194. float frac = delay_samples - idelay_samples;
  195. const float scale = 1.0f - (_samples_since_motion * _interpolation_delay_coeff);
  196. for (nframes_t i = 0; i < nframes; i++ )
  197. {
  198. const long read_index = _write_index - idelay_samples;
  199. _buffer[_write_index++ & _buffer_mask] = buf[i];
  200. frac *= scale;
  201. const float read = interpolate_cubic (frac,
  202. _buffer[(read_index-1) & _buffer_mask],
  203. _buffer[read_index & _buffer_mask],
  204. _buffer[(read_index+1) & _buffer_mask],
  205. _buffer[(read_index+2) & _buffer_mask]);
  206. buf[i] = read;
  207. }
  208. _samples_since_motion += nframes;
  209. }
  210. }
  211. }
  212. };
  213. class ambisonic_panner
  214. {
  215. /* last values */
  216. float _x, _y, _z;
  217. /* for stereo */
  218. float _xr, _yr;
  219. static inline void spherical_to_cartesian (float a, float e, float &x, float &y, float &z )
  220. {
  221. a *= DEG2RAD;
  222. e *= DEG2RAD;
  223. z = sinf(e);
  224. const float ce = cosf(e);
  225. x = ce * cosf(-a);
  226. y = ce * sinf(-a);
  227. }
  228. public:
  229. ambisonic_panner ( )
  230. {
  231. _x = _y = _z = _xr = _yr = 1.0f;
  232. }
  233. void
  234. run_mono ( float *in,
  235. float *out_w, float *out_x, float *out_y, float *out_z,
  236. float a, float e,
  237. nframes_t nframes )
  238. {
  239. float x = _x;
  240. float y = _y;
  241. float z = _z;
  242. spherical_to_cartesian( a, e, _x, _y, _z );
  243. const float c = 1.0f / (float)nframes;
  244. /* calculate increment for linear interpolation */
  245. const float dx = (_x - x) * c;
  246. const float dy = (_y - y) * c;
  247. const float dz = (_z - z) * c;
  248. while ( nframes-- )
  249. {
  250. x += dx;
  251. y += dy;
  252. z += dz;
  253. const float t = *in++;
  254. *out_w++ = ONEOVERSQRT2 * t;
  255. *out_x++ = x * t;
  256. *out_y++ = y * t;
  257. *out_z++ = z * t;
  258. }
  259. }
  260. void
  261. run_stereo ( float *in_l, float *in_r,
  262. float *out_w, float *out_x, float *out_y, float *out_z,
  263. float a, float e, float w,
  264. nframes_t nframes )
  265. {
  266. float x = _x;
  267. float y = _y;
  268. float z = _z;
  269. float xr = _xr;
  270. float yr = _yr;
  271. w *= 0.5f;
  272. spherical_to_cartesian( a - w, e, _x, _y, _z );
  273. spherical_to_cartesian( a + w, e, _xr, _yr, _z );
  274. const float c = 1.0f / (float)nframes;
  275. /* calculate increment for linear interpolation */
  276. const float dx = (_x - x) * c;
  277. const float dy = (_y - y) * c;
  278. const float dz = (_z - z) * c;
  279. const float dxr = (_xr - xr) * c;
  280. const float dyr = (_yr - yr) * c;
  281. while ( nframes-- )
  282. {
  283. x += dx;
  284. y += dy;
  285. z += dz;
  286. xr += dxr;
  287. yr += dyr;
  288. const float L = *in_l++;
  289. const float R = *in_r++;
  290. const float LR = L + R;
  291. *out_w++ = ONEOVERSQRT2 * LR;
  292. *out_x++ = x * L + xr * R;
  293. *out_y++ = y * L + yr * R;
  294. *out_z++ = z * LR;
  295. }
  296. }
  297. };
  298. Spatializer_Module::Spatializer_Module ( ) : JACK_Module ( false )
  299. {
  300. is_default( false );
  301. _panner = 0;
  302. _early_panner = 0;
  303. {
  304. Port p( this, Port::INPUT, Port::CONTROL, "Azimuth" );
  305. p.hints.type = Port::Hints::LINEAR;
  306. p.hints.ranged = true;
  307. p.hints.minimum = -180.0f;
  308. p.hints.maximum = 180.0f;
  309. p.hints.default_value = 0.0f;
  310. p.connect_to( new float );
  311. p.control_value( p.hints.default_value );
  312. add_port( p );
  313. }
  314. {
  315. Port p( this, Port::INPUT, Port::CONTROL, "Elevation" );
  316. p.hints.type = Port::Hints::LINEAR;
  317. p.hints.ranged = true;
  318. p.hints.minimum = -90.0f;
  319. p.hints.maximum = 90.0f;
  320. p.hints.default_value = 0.0f;
  321. p.connect_to( new float );
  322. p.control_value( p.hints.default_value );
  323. add_port( p );
  324. }
  325. {
  326. Port p( this, Port::INPUT, Port::CONTROL, "Radius" );
  327. p.hints.type = Port::Hints::LINEAR;
  328. p.hints.ranged = true;
  329. p.hints.minimum = 0.0f;
  330. p.hints.maximum = max_distance;
  331. p.hints.default_value = 1.0f;
  332. p.connect_to( new float );
  333. p.control_value( p.hints.default_value );
  334. add_port( p );
  335. }
  336. {
  337. Port p( this, Port::INPUT, Port::CONTROL, "Highpass (Hz)" );
  338. p.hints.type = Port::Hints::LINEAR;
  339. p.hints.ranged = true;
  340. p.hints.minimum = 0.0f;
  341. p.hints.maximum = 600.0f;
  342. p.hints.default_value = 0.0f;
  343. p.hints.visible = false;
  344. p.connect_to( new float );
  345. p.control_value( p.hints.default_value );
  346. add_port( p );
  347. }
  348. {
  349. Port p( this, Port::INPUT, Port::CONTROL, "Width" );
  350. p.hints.type = Port::Hints::LINEAR;
  351. p.hints.ranged = true;
  352. p.hints.minimum = -90.0f;
  353. p.hints.maximum = 90.0f;
  354. p.hints.default_value = 90.0f;
  355. p.connect_to( new float );
  356. p.control_value( p.hints.default_value );
  357. add_port( p );
  358. }
  359. {
  360. Port p( this, Port::INPUT, Port::CONTROL, "Angle" );
  361. p.hints.type = Port::Hints::LINEAR;
  362. p.hints.ranged = true;
  363. p.hints.minimum = -180.0f;
  364. p.hints.maximum = +180.0f;
  365. p.hints.default_value = 0.0f;
  366. p.connect_to( new float );
  367. p.control_value( p.hints.default_value );
  368. add_port( p );
  369. }
  370. {
  371. Port p( this, Port::INPUT, Port::CONTROL, "Advanced Options" );
  372. p.hints.type = Port::Hints::BOOLEAN;
  373. p.hints.ranged = true;
  374. p.hints.minimum = 0.0f;
  375. p.hints.maximum = 1.0f;
  376. p.hints.default_value = 0.0f;
  377. p.connect_to( new float );
  378. p.control_value( p.hints.default_value );
  379. add_port( p );
  380. }
  381. {
  382. Port p( this, Port::INPUT, Port::CONTROL, "Speed of Sound" );
  383. p.hints.type = Port::Hints::BOOLEAN;
  384. p.hints.ranged = true;
  385. p.hints.minimum = 0.0f;
  386. p.hints.maximum = 1.0f;
  387. p.hints.default_value = 1.0f;
  388. p.hints.visible = false;
  389. p.connect_to( new float );
  390. p.control_value( p.hints.default_value );
  391. add_port( p );
  392. }
  393. {
  394. Port p( this, Port::INPUT, Port::CONTROL, "Late Gain (dB)" );
  395. p.hints.type = Port::Hints::LOGARITHMIC;
  396. p.hints.ranged = true;
  397. p.hints.minimum = -70.0f;
  398. p.hints.maximum = 6.0f;
  399. p.hints.default_value = 0.0f;
  400. p.hints.visible = false;
  401. p.connect_to( new float );
  402. p.control_value( p.hints.default_value );
  403. add_port( p );
  404. }
  405. {
  406. Port p( this, Port::INPUT, Port::CONTROL, "Early Gain (dB)" );
  407. p.hints.type = Port::Hints::LOGARITHMIC;
  408. p.hints.ranged = true;
  409. p.hints.minimum = -70.0f;
  410. p.hints.maximum = 6.0f;
  411. p.hints.default_value = 0.0f;
  412. p.hints.visible = false;
  413. p.connect_to( new float );
  414. p.control_value( p.hints.default_value );
  415. add_port( p );
  416. }
  417. log_create();
  418. _panner = new ambisonic_panner();
  419. _early_panner = new ambisonic_panner();
  420. labelsize(9);
  421. color( FL_DARK1 );
  422. copy_label( "Spatializer" );
  423. align(FL_ALIGN_LEFT|FL_ALIGN_TOP|FL_ALIGN_INSIDE);
  424. gain_smoothing.sample_rate( sample_rate() );
  425. late_gain_smoothing.sample_rate( sample_rate() );
  426. early_gain_smoothing.sample_rate( sample_rate() );
  427. delay_smoothing.cutoff( 0.5f );
  428. delay_smoothing.sample_rate( sample_rate() );
  429. }
  430. Spatializer_Module::~Spatializer_Module ( )
  431. {
  432. configure_inputs(0);
  433. delete _early_panner;
  434. delete _panner;
  435. for ( unsigned int i = 0; i < control_input.size(); i++ )
  436. delete (float*)control_input[i].buffer();
  437. }
  438. void
  439. Spatializer_Module::handle_sample_rate_change ( nframes_t n )
  440. {
  441. gain_smoothing.sample_rate( n );
  442. delay_smoothing.sample_rate( n );
  443. early_gain_smoothing.sample_rate( n );
  444. late_gain_smoothing.sample_rate( n );
  445. for ( unsigned int i = 0; i < audio_input.size(); i++ )
  446. {
  447. _lowpass[i]->sample_rate( n );
  448. _highpass[i]->sample_rate( n );
  449. _delay[i]->sample_rate( n );
  450. }
  451. }
  452. void
  453. Spatializer_Module::draw ( void )
  454. {
  455. int W = 5;
  456. child(0)->size( w() - W, h() );
  457. Module::draw_box(x(),y(),w() - W,h());
  458. Module::draw_label(x() + 4,y(),w() - W,h());
  459. Module *m = this;
  460. fl_color( fl_darker( FL_FOREGROUND_COLOR ) );
  461. int spacing, offset;
  462. int ni = aux_audio_output.size();
  463. spacing = h() / ni;
  464. offset = spacing / 2;
  465. for ( int i = ni; i--; )
  466. {
  467. int xi = offset + ( spacing * i );
  468. fl_rectf( m->x() + m->w() - W, m->y() + xi, W, 2 );
  469. }
  470. }
  471. void
  472. Spatializer_Module::process ( nframes_t nframes )
  473. {
  474. float azimuth = control_input[0].control_value();
  475. float elevation = control_input[1].control_value();
  476. float radius = control_input[2].control_value();
  477. float highpass_freq = control_input[3].control_value();
  478. float width = control_input[4].control_value();
  479. float angle = control_input[5].control_value();
  480. // bool more_options = control_input[6].control_value();
  481. bool speed_of_sound = control_input[7].control_value() > 0.5f;
  482. float late_gain = DB_CO( control_input[8].control_value() );
  483. float early_gain = DB_CO( control_input[9].control_value() );
  484. control_input[3].hints.visible = highpass_freq != 0.0f;
  485. float delay_seconds = 0.0f;
  486. if ( speed_of_sound && radius > 1.0f )
  487. delay_seconds = ( radius - 1.0f ) / 340.29f;
  488. /* direct sound follows inverse square law */
  489. /* but it's just the inverse as far as SPL goes */
  490. /* let's not go nuts... */
  491. if ( radius < 0.01f )
  492. radius = 0.01f;
  493. float gain = 1.0f / radius;
  494. /* float cutoff_frequency = gain * LOWPASS_FREQ; */
  495. sample_t gainbuf[nframes];
  496. sample_t delaybuf[nframes];
  497. bool use_gainbuf = false;
  498. bool use_delaybuf = delay_smoothing.apply( delaybuf, nframes, delay_seconds );
  499. for ( unsigned int i = 0; i < audio_input.size(); i++ )
  500. {
  501. sample_t *buf = (sample_t*) audio_input[i].buffer();
  502. /* frequency effects */
  503. _highpass[i]->run_highpass( buf, highpass_freq, nframes );
  504. /* send to late reverb */
  505. if ( i == 0 )
  506. buffer_copy( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), buf, nframes );
  507. else
  508. buffer_mix( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), buf, nframes );
  509. }
  510. {
  511. use_gainbuf = late_gain_smoothing.apply( gainbuf, nframes, late_gain );
  512. /* gain effects */
  513. if ( unlikely( use_gainbuf ) )
  514. buffer_apply_gain_buffer( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), gainbuf, nframes );
  515. else
  516. buffer_apply_gain( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), nframes, late_gain );
  517. }
  518. float early_angle = azimuth - angle;
  519. if ( early_angle > 180.0f )
  520. early_angle = -180 - ( early_angle - 180 );
  521. else if ( early_angle < -180.0f )
  522. early_angle = 180 - ( early_angle + 180 );
  523. /* send to early reverb */
  524. if ( audio_input.size() == 1 )
  525. {
  526. _early_panner->run_mono( (sample_t*)audio_input[0].buffer(),
  527. (sample_t*)aux_audio_output[1].jack_port()->buffer(nframes),
  528. (sample_t*)aux_audio_output[2].jack_port()->buffer(nframes),
  529. (sample_t*)aux_audio_output[3].jack_port()->buffer(nframes),
  530. (sample_t*)aux_audio_output[4].jack_port()->buffer(nframes),
  531. azimuth + angle,
  532. elevation,
  533. nframes );
  534. }
  535. else
  536. {
  537. _early_panner->run_stereo( (sample_t*)audio_input[0].buffer(),
  538. (sample_t*)audio_input[1].buffer(),
  539. (sample_t*)aux_audio_output[1].jack_port()->buffer(nframes),
  540. (sample_t*)aux_audio_output[2].jack_port()->buffer(nframes),
  541. (sample_t*)aux_audio_output[3].jack_port()->buffer(nframes),
  542. (sample_t*)aux_audio_output[4].jack_port()->buffer(nframes),
  543. azimuth + angle,
  544. elevation,
  545. width,
  546. nframes );
  547. }
  548. {
  549. use_gainbuf = early_gain_smoothing.apply( gainbuf, nframes, early_gain );
  550. for ( int i = 1; i < 5; i++ )
  551. {
  552. /* gain effects */
  553. if ( unlikely( use_gainbuf ) )
  554. buffer_apply_gain_buffer( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), gainbuf, nframes );
  555. else
  556. buffer_apply_gain( (sample_t*)aux_audio_output[i].jack_port()->buffer(nframes), nframes, early_gain );
  557. }
  558. }
  559. float corrected_angle = fabs( angle ) - (fabs( width ) * 0.5f);
  560. if ( corrected_angle < 0.0f )
  561. corrected_angle = 0.0f;
  562. float cutoff_frequency = ( 1.0f / ( 1.0f + corrected_angle ) ) * 300000.0f;
  563. use_gainbuf = gain_smoothing.apply( gainbuf, nframes, gain );
  564. for ( unsigned int i = 0; i < audio_input.size(); i++ )
  565. {
  566. /* gain effects */
  567. if ( unlikely( use_gainbuf ) )
  568. buffer_apply_gain_buffer( (sample_t*)audio_input[i].buffer(), gainbuf, nframes );
  569. else
  570. buffer_apply_gain( (sample_t*)audio_input[i].buffer(), nframes, gain );
  571. /* frequency effects */
  572. _lowpass[i]->run_lowpass( (sample_t*)audio_input[i].buffer(), cutoff_frequency, nframes );
  573. /* delay effects */
  574. if ( likely( speed_of_sound ) )
  575. {
  576. if ( unlikely( use_delaybuf ) )
  577. _delay[i]->run( (sample_t*)audio_input[i].buffer(), delaybuf, 0, nframes );
  578. else
  579. _delay[i]->run( (sample_t*)audio_input[i].buffer(), 0, delay_seconds, nframes );
  580. }
  581. }
  582. /* now do direct outputs */
  583. if ( audio_input.size() == 1 )
  584. {
  585. _panner->run_mono( (sample_t*)audio_input[0].buffer(),
  586. (sample_t*)audio_output[0].buffer(),
  587. (sample_t*)audio_output[1].buffer(),
  588. (sample_t*)audio_output[2].buffer(),
  589. (sample_t*)audio_output[3].buffer(),
  590. azimuth,
  591. elevation,
  592. nframes );
  593. }
  594. else
  595. {
  596. _panner->run_stereo( (sample_t*)audio_input[0].buffer(),
  597. (sample_t*)audio_input[1].buffer(),
  598. (sample_t*)audio_output[0].buffer(),
  599. (sample_t*)audio_output[1].buffer(),
  600. (sample_t*)audio_output[2].buffer(),
  601. (sample_t*)audio_output[3].buffer(),
  602. azimuth,
  603. elevation,
  604. width,
  605. nframes );
  606. }
  607. }
  608. void
  609. Spatializer_Module::handle_control_changed ( Port *p )
  610. {
  611. if ( p == &control_input[6] )
  612. {
  613. bool v = p->control_value();
  614. control_input[7].hints.visible = v;
  615. control_input[8].hints.visible = v;
  616. control_input[9].hints.visible = v;
  617. DMESSAGE( "reloading" );
  618. if ( _editor )
  619. _editor->reload();
  620. }
  621. }
  622. bool
  623. Spatializer_Module::configure_inputs ( int n )
  624. {
  625. output_connection_handle->show();
  626. output_connection_handle->tooltip( "Late Reverb" );
  627. output_connection2_handle->show();
  628. output_connection2_handle->tooltip( "Early Reverb" );
  629. int on = audio_input.size();
  630. if ( n > on )
  631. {
  632. for ( int i = n - on; i--; )
  633. {
  634. { filter *o = new filter();
  635. o->sample_rate( sample_rate() );
  636. _lowpass.push_back( o );
  637. }
  638. {
  639. filter *o = new filter();
  640. o->sample_rate( sample_rate() );
  641. _highpass.push_back( o );
  642. }
  643. {
  644. delay *o = new delay( max_distance / 340.29f );
  645. o->sample_rate( sample_rate() );
  646. _delay.push_back( o );
  647. }
  648. add_port( Port( this, Port::INPUT, Port::AUDIO ) );
  649. }
  650. }
  651. else if ( n < on )
  652. {
  653. for ( int i = on - n; i--; )
  654. {
  655. delete _lowpass.back();
  656. _lowpass.pop_back();
  657. delete _highpass.back();
  658. _highpass.pop_back();
  659. delete _delay.back();
  660. _delay.pop_back();
  661. audio_input.pop_back();
  662. }
  663. }
  664. // control_input[4].hints.visible = audio_input.size() == 2;
  665. control_input[4].hints.default_value = audio_input.size() == 2 ? 90.0f : 0.0f;
  666. if ( n == 0 )
  667. {
  668. remove_aux_audio_outputs();
  669. audio_output.clear();
  670. audio_input.clear();
  671. }
  672. else
  673. {
  674. if ( audio_output.size() != 4 )
  675. {
  676. for ( int i = 0; i < 4; i++ )
  677. {
  678. add_port( Port( this, Port::OUTPUT, Port::AUDIO ) );
  679. }
  680. }
  681. if ( aux_audio_output.size() != 5 )
  682. {
  683. add_aux_audio_output( "late reverb", 0 );
  684. add_aux_audio_output( "early reverb", 0 );
  685. add_aux_audio_output( "early reverb", 1 );
  686. add_aux_audio_output( "early reverb", 2 );
  687. add_aux_audio_output( "early reverb", 3 );
  688. }
  689. }
  690. _connection_handle_outputs[0][0] = 0;
  691. _connection_handle_outputs[0][1] = 1;
  692. _connection_handle_outputs[1][0] = 1;
  693. _connection_handle_outputs[1][1] = aux_audio_output.size();
  694. return true;
  695. }