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.

474 lines
11KB

  1. #include "mscHack.hpp"
  2. #include "window.hpp"
  3. //-----------------------------------------------------
  4. // Procedure: constructor
  5. //-----------------------------------------------------
  6. void EnvelopeData::Init( int mode, int range, bool bGate, float fsegsize )
  7. {
  8. m_bInitialized = false;
  9. m_Mode = mode;
  10. m_Range = range;
  11. m_bGateMode = bGate;
  12. m_fsegsize = fsegsize;
  13. for( int hd = 0; hd < ENVELOPE_HANDLES; hd++ )
  14. m_HandleVal[ hd ] = 0.5f;
  15. recalcLine( -1 );
  16. setMode( m_Mode );
  17. m_bInitialized = true;
  18. }
  19. //-----------------------------------------------------
  20. // Procedure: Preset
  21. //-----------------------------------------------------
  22. void EnvelopeData::Preset( int preset )
  23. {
  24. int i;
  25. float a, div;
  26. if( preset < 0 || preset >= EnvelopeData::nPRESETS )
  27. return;
  28. switch( preset )
  29. {
  30. case EnvelopeData::PRESET_CLEAR:
  31. resetValAll( 0.0f );
  32. break;
  33. case EnvelopeData::PRESET_SET:
  34. resetValAll( 1.0f );
  35. break;
  36. case EnvelopeData::PRESET_HALF:
  37. resetValAll( 0.5f );
  38. break;
  39. case EnvelopeData::PRESET_SIN:
  40. div = (float)(ENVELOPE_HANDLES - 1) / (PI * 2.0f);
  41. for( i = 0; i < ENVELOPE_HANDLES; i++ )
  42. {
  43. a = ( 1.0f + sinf( (float)i / div ) ) / 2.0f;
  44. setVal( i, a );
  45. }
  46. break;
  47. case EnvelopeData::PRESET_COS:
  48. div = (float)(ENVELOPE_HANDLES - 1) / (PI * 2.0f);
  49. for( i = 0; i < ENVELOPE_HANDLES; i++ )
  50. {
  51. a = ( 1.0f + cosf( (float)i / div ) ) / 2.0f;
  52. setVal( i, a );
  53. }
  54. break;
  55. case EnvelopeData::PRESET_COS_HALF:
  56. div = (float)(ENVELOPE_HANDLES - 1) / (PI * 1.0f);
  57. for( i = 0; i < ENVELOPE_HANDLES; i++ )
  58. {
  59. a = ( 1.0f + cosf( (float)i / div ) ) / 2.0f;
  60. setVal( i, a );
  61. }
  62. break;
  63. case EnvelopeData::PRESET_TRI_FULL:
  64. div = 1.0f / 16.0f;
  65. a = 0;
  66. for( i = 0; i < ENVELOPE_HANDLES; i++ )
  67. {
  68. setVal( i, a );
  69. a += div;
  70. }
  71. break;
  72. case EnvelopeData::PRESET_TRI_HALF:
  73. div = 1.0f / 8.0f;
  74. a = 0;
  75. for( i = 0; i < ENVELOPE_HANDLES; i++ )
  76. {
  77. setVal( i, a );
  78. a += div;
  79. if( i == 8 )
  80. a = 0.0f;
  81. }
  82. break;
  83. case EnvelopeData::PRESET_SQR:
  84. a = 0;
  85. for( i = 0; i < ENVELOPE_HANDLES; i++ )
  86. {
  87. setVal( i, a );
  88. if( i == 8 )
  89. a = 1.0f;
  90. }
  91. break;
  92. default:
  93. break;
  94. }
  95. }
  96. //-----------------------------------------------------
  97. // Procedure: getActualVal
  98. //-----------------------------------------------------
  99. float EnvelopeData::getActualVal( float inval )
  100. {
  101. float val = 0.0f;
  102. switch( m_Range )
  103. {
  104. case EnvelopeData_Ranges::RANGE_0to5:
  105. val = inval * 5.0f;
  106. break;
  107. case EnvelopeData_Ranges::RANGE_n5to5:
  108. val = ( ( inval * 2 ) - 1.0 ) * 5.0f;
  109. break;
  110. case EnvelopeData_Ranges::RANGE_0to10:
  111. val = inval * 10.0f;
  112. break;
  113. case EnvelopeData_Ranges::RANGE_n10to10:
  114. val = ( ( inval * 2 ) - 1.0 ) * 10.0f;
  115. break;
  116. case EnvelopeData_Ranges::RANGE_0to1:
  117. val = inval;
  118. break;
  119. case EnvelopeData_Ranges::RANGE_n1to1:
  120. val = ( ( inval * 2 ) - 1.0 );
  121. break;
  122. case EnvelopeData_Ranges::RANGE_Audio:
  123. val = ( ( inval * 2 ) - 1.0 ) * AUDIO_MAX;
  124. break;
  125. }
  126. return val;
  127. }
  128. //-----------------------------------------------------
  129. // Function: line_from_points
  130. //
  131. //-----------------------------------------------------
  132. void EnvelopeData::line_from_points( float x1, float y1, float x2, float y2, fLine *L )
  133. {
  134. float m;
  135. float xdiff, ydiff;
  136. if( !L )
  137. return;
  138. memset( L, 0, sizeof( fLine ) );
  139. L->bSet = true;
  140. xdiff = x2 - x1;
  141. xdiff = fabs( xdiff );
  142. ydiff = y2 - y1;
  143. ydiff = fabs( ydiff );
  144. // line is vertical
  145. if( xdiff < 0.000000001 )
  146. {
  147. L->fx = x1;
  148. L->bVert = true;
  149. return;
  150. }
  151. else if( ydiff < 0.000000001 )
  152. {
  153. L->fy = y1;
  154. L->bHorz = true;
  155. return;
  156. }
  157. //normal line
  158. m = (y2 - y1) / (x2 - x1);
  159. // point slope form
  160. //y = mx + b
  161. L->fmx = m;
  162. L->fb = y1 - (m * x1);
  163. }
  164. //-----------------------------------------------------
  165. // Procedure: valfromline
  166. //-----------------------------------------------------
  167. float EnvelopeData::valfromline( int handle, float x )
  168. {
  169. fLine *L;
  170. if( m_bGateMode )
  171. return getActualVal( m_HandleVal[ handle ] );
  172. L = &m_Lines[ handle ];
  173. if( L->bHorz )
  174. return getActualVal( L->fy );
  175. return getActualVal( (x * L->fmx) + L->fb );
  176. }
  177. //-----------------------------------------------------
  178. // Procedure: recalcLine
  179. //-----------------------------------------------------
  180. void EnvelopeData::recalcLine( int handle )
  181. {
  182. float fx1, fx2, fy1, fy2;
  183. int i;
  184. // calc all lines
  185. if( handle == -1 )
  186. {
  187. for( int h = 0; h < ENVELOPE_DIVISIONS; h++ )
  188. {
  189. for( int delta = -1; delta < 1; delta++ )
  190. {
  191. i = ( h + delta ) & 0xF;
  192. fx1 = (m_fsegsize * i);
  193. fx2 = fx1 + m_fsegsize;
  194. fy1 = m_HandleVal[ i ];
  195. fy2 = m_HandleVal[ i + 1 ];
  196. line_from_points( fx1, fy1, fx2, fy2, &m_Lines[ i ] );
  197. }
  198. }
  199. }
  200. // calc line before and line after handle
  201. else
  202. {
  203. for( int delta = -1; delta < 1; delta++ )
  204. {
  205. i = ( handle + delta ) & 0xF;
  206. fx1 = (m_fsegsize * i);
  207. fx2 = fx1 + m_fsegsize;
  208. fy1 = m_HandleVal[ i ];
  209. fy2 = m_HandleVal[ i + 1 ];
  210. line_from_points( fx1, fy1, fx2, fy2, &m_Lines[ i ] );
  211. }
  212. }
  213. }
  214. //-----------------------------------------------------
  215. // Procedure: resetVal
  216. //-----------------------------------------------------
  217. void EnvelopeData::resetValAll( float val )
  218. {
  219. if( !m_bInitialized )
  220. return;
  221. for( int i = 0; i < ENVELOPE_HANDLES; i++ )
  222. {
  223. m_HandleVal[ i ] = val;
  224. }
  225. recalcLine( -1 );
  226. }
  227. //-----------------------------------------------------
  228. // Procedure: setVal
  229. //-----------------------------------------------------
  230. void EnvelopeData::setVal( int handle, float val )
  231. {
  232. if( !m_bInitialized )
  233. return;
  234. m_HandleVal[ handle ] = val;
  235. recalcLine( handle );
  236. }
  237. //-----------------------------------------------------
  238. // Procedure: setMode
  239. //-----------------------------------------------------
  240. void EnvelopeData::setMode( int Mode )
  241. {
  242. if( !m_bInitialized )
  243. return;
  244. switch( Mode )
  245. {
  246. case MODE_LOOP:
  247. m_Clock.state = STATE_RUN;
  248. break;
  249. case MODE_REVERSE:
  250. m_Clock.state = STATE_RUN_REV;
  251. break;
  252. case MODE_ONESHOT:
  253. m_Clock.fpos = 0;
  254. m_Clock.state = STATE_WAIT_TRIG;
  255. break;
  256. case MODE_TWOSHOT:
  257. m_Clock.fpos = 0;
  258. m_Clock.state = STATE_WAIT_TRIG;
  259. break;
  260. case MODE_PINGPONG:
  261. if( m_Clock.state == STATE_WAIT_TRIG )
  262. m_Clock.state = STATE_RUN;
  263. else if( m_Clock.state == STATE_WAIT_TRIG_REV )
  264. m_Clock.state = STATE_RUN_REV;
  265. break;
  266. default:
  267. return;
  268. }
  269. m_Clock.prevstate = m_Clock.state;
  270. m_Mode = Mode;
  271. }
  272. //-----------------------------------------------------
  273. // Procedure: setDataAll
  274. //-----------------------------------------------------
  275. void EnvelopeData::setDataAll( int *pint )
  276. {
  277. int j, count = 0;
  278. if( !m_bInitialized || !pint )
  279. {
  280. return;
  281. }
  282. for( j = 0; j < ENVELOPE_HANDLES; j++ )
  283. {
  284. m_HandleVal[ j ] = clamp( (float)pint[ count++ ] / 10000.0f, 0.0f, 1.0f );
  285. }
  286. // recalc all lines
  287. recalcLine( -1 );
  288. }
  289. //-----------------------------------------------------
  290. // Procedure: getDataAll
  291. //-----------------------------------------------------
  292. void EnvelopeData::getDataAll( int *pint )
  293. {
  294. int j, count = 0;
  295. if( !m_bInitialized || !pint )
  296. {
  297. return;
  298. }
  299. for( j = 0; j < ENVELOPE_HANDLES; j++ )
  300. {
  301. pint[ count++ ] = (int)( m_HandleVal[ j ] * 10000.0 );
  302. }
  303. }
  304. //-----------------------------------------------------
  305. // Procedure: process_state
  306. //-----------------------------------------------------
  307. bool EnvelopeData::process_state( bool bTrig, bool bHold )
  308. {
  309. switch( m_Clock.state )
  310. {
  311. case STATE_RUN:
  312. case STATE_RUN_REV:
  313. if( bHold )
  314. {
  315. m_Clock.prevstate = m_Clock.state;
  316. m_Clock.state = STATE_HOLD;
  317. break;
  318. }
  319. // run reverse
  320. if( m_Clock.state == STATE_RUN_REV )
  321. {
  322. m_Clock.fpos -= m_Clock.syncInc;
  323. if( m_Clock.fpos <= 0.0f )
  324. {
  325. switch( m_Mode )
  326. {
  327. case MODE_TWOSHOT:
  328. m_Clock.fpos = 0;
  329. m_Clock.state = STATE_WAIT_TRIG;
  330. break;
  331. case MODE_PINGPONG:
  332. m_Clock.fpos = -m_Clock.fpos;
  333. m_Clock.state = STATE_RUN;
  334. break;
  335. case MODE_REVERSE:
  336. default:
  337. m_Clock.fpos += engineGetSampleRate();
  338. }
  339. }
  340. }
  341. // run forward
  342. else
  343. {
  344. m_Clock.fpos += m_Clock.syncInc;
  345. if( m_Clock.fpos >= engineGetSampleRate() )
  346. {
  347. switch( m_Mode )
  348. {
  349. case MODE_ONESHOT:
  350. m_Clock.fpos = engineGetSampleRate() - 1.0f;;
  351. m_Clock.state = STATE_WAIT_TRIG;
  352. break;
  353. case MODE_TWOSHOT:
  354. m_Clock.fpos = engineGetSampleRate() - 1.0f;
  355. m_Clock.state = STATE_WAIT_TRIG_REV;
  356. break;
  357. case MODE_PINGPONG:
  358. m_Clock.fpos -= (m_Clock.fpos - engineGetSampleRate()) * 2.0f;
  359. m_Clock.state = STATE_RUN_REV;
  360. break;
  361. case MODE_LOOP:
  362. default:
  363. m_Clock.fpos -= engineGetSampleRate();
  364. }
  365. }
  366. }
  367. break;
  368. case STATE_WAIT_TRIG:
  369. if( bTrig )
  370. {
  371. m_Clock.fpos = 0;
  372. m_Clock.state = STATE_RUN;
  373. }
  374. break;
  375. case STATE_WAIT_TRIG_REV:
  376. if( bTrig )
  377. {
  378. m_Clock.fpos = engineGetSampleRate();
  379. m_Clock.state = STATE_RUN_REV;
  380. }
  381. break;
  382. case STATE_HOLD:
  383. if( !bHold )
  384. {
  385. m_Clock.state = m_Clock.prevstate;
  386. break;
  387. }
  388. break;
  389. }
  390. return true;
  391. }
  392. //-----------------------------------------------------
  393. // Procedure: procStep
  394. //-----------------------------------------------------
  395. float EnvelopeData::procStep( bool bTrig, bool bHold )
  396. {
  397. int handle;
  398. if( !m_bInitialized )
  399. return 0.0f;
  400. process_state( bTrig, bHold );
  401. m_fIndicator = m_Clock.fpos / engineGetSampleRate();
  402. handle = (int)( m_Clock.fpos / ( engineGetSampleRate() / (float)ENVELOPE_DIVISIONS ) );
  403. return valfromline( handle, m_fIndicator * m_fsegsize * (float)ENVELOPE_DIVISIONS );
  404. }