FFT: Prevent user from attempting hops smaller than SC's block size
[supercollider.git] / server / plugins / GrainUGens.cpp
blobb3b1d4ed3cde4787f380543163ca8a70f18d8419
1 /*
2 * JoshUGens.cpp
3 * xSC3plugins
5 * Created by Josh Parmenter on 2/4/05.
6 * Copyright 2005 __MyCompanyName__. All rights reserved.
8 */
9 /*
10 SuperCollider real time audio synthesis system
11 Copyright (c) 2002 James McCartney. All rights reserved.
12 http://www.audiosynth.com
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "SC_PlugIn.h"
32 #include "function_attributes.h"
34 static InterfaceTable *ft;
36 const int kMaxGrains = 64;
38 const int kMaxSynthGrains = 512;
40 struct GrainInG
42 double b1, y1, y2, curamp, winPos, winInc; // envelope
43 int counter, chan;
44 float pan1, pan2, winType;
47 struct GrainIn : public Unit
49 int mNumActive, m_channels, mMaxGrains;
50 float curtrig;
51 bool mFirst;
52 GrainInG *mGrains;
55 struct GrainSinG
57 double b1, y1, y2, curamp, winPos, winInc; // envelope
58 int counter, chan;
59 float pan1, pan2, winType;
60 int32 oscphase; // the phase of the osc inside this grain
61 int32 freq; // the freq of the osc inside this grain in phase inc
64 struct GrainSin : public Unit
66 int mNumActive, m_channels, mMaxGrains;
67 uint32 m_lomask;
68 float curtrig;
69 bool mFirst;
70 double m_cpstoinc, m_radtoinc;
71 GrainSinG *mGrains;
74 struct GrainFMG
76 int32 coscphase, moscphase; // the phase of the osc inside this grain
77 int32 mfreq; // the freq of the osc inside this grain in phase inc
78 double b1, y1, y2, curamp, winPos, winInc; // envelope
79 float deviation, carbase, pan1, pan2, winType;
80 int counter, chan;
84 struct GrainFM : public Unit
86 int mNumActive, m_channels, mMaxGrains;
87 uint32 m_lomask;
88 float curtrig;
89 bool mFirst;
90 double m_cpstoinc, m_radtoinc;
91 GrainFMG *mGrains;
94 struct GrainBufG
96 double phase, rate;
97 double b1, y1, y2, curamp, winPos, winInc;
98 float pan1, pan2, winType;
99 int counter, chan, bufnum, interp;
102 struct GrainBuf : public Unit
104 int mNumActive, m_channels, mMaxGrains;
105 float curtrig;
106 GrainBufG *mGrains;
109 struct WarpWinGrain
111 double phase, rate;
112 double winPos, winInc, b1, y1, y2, curamp; // tells the grain where to look in the winBuf for an amp value
113 int counter, bufnum, interp;
114 float winType;
117 struct Warp1 : public Unit
119 float m_fbufnum;
120 SndBuf* m_buf;
121 int mNumActive[16];
122 int mNextGrain[16];
123 WarpWinGrain mGrains[16][kMaxGrains];
126 ////////////////////////////////////////////////////////////////////////
128 extern "C"
131 void GrainIn_Ctor(GrainIn* unit);
132 void GrainIn_Dtor(GrainIn* unit);
133 void GrainIn_next_a(GrainIn *unit, int inNumSamples);
134 void GrainIn_next_k(GrainIn *unit, int inNumSamples);
136 void GrainSin_Ctor(GrainSin* unit);
137 void GrainSin_Dtor(GrainSin* unit);
138 void GrainSin_next_a(GrainSin *unit, int inNumSamples);
139 void GrainSin_next_k(GrainSin *unit, int inNumSamples);
141 void GrainFM_Ctor(GrainFM* unit);
142 void GrainFM_Dtor(GrainFM* unit);
143 void GrainFM_next_a(GrainFM *unit, int inNumSamples);
144 void GrainFM_next_k(GrainFM *unit, int inNumSamples);
146 void GrainBuf_Ctor(GrainBuf* unit);
147 void GrainBuf_Dtor(GrainBuf* unit);
149 void Warp1_next(Warp1 *unit, int inNumSamples);
150 void Warp1_Ctor(Warp1* unit);
153 ////////////////////////////////////////////////////////////////////////////////////////////////////////
154 //////////////////////////////// Granular UGens ////////////////////////////////////////////////////////
155 ////////////////////////////////////////////////////////////////////////////////////////////////////////
157 inline float GRAIN_IN_AT(Unit* unit, int index, int offset)
159 if (INRATE(index) == calc_FullRate) return IN(index)[offset];
160 if (INRATE(index) == calc_DemandRate) return DEMANDINPUT_A(index, offset + 1);
161 return IN0(index);
164 template <bool full_rate>
165 inline float grain_in_at(Unit* unit, int index, int offset)
167 if (full_rate)
168 return GRAIN_IN_AT(unit, index, offset);
170 if (INRATE(index) == calc_DemandRate)
171 return DEMANDINPUT_A(index, offset + 1);
172 else
173 return IN0(index);
176 inline double sc_gloop(double in, double hi)
178 // avoid the divide if possible
179 if (in >= hi) {
180 in -= hi;
181 if (in < hi) return in;
182 } else if (in < 0.) {
183 in += hi;
184 if (in >= 0.) return in;
185 } else return in;
187 return in - hi * floor(in/hi);
190 #define GRAIN_BUF \
191 const SndBuf *buf; \
192 if (bufnum >= world->mNumSndBufs) { \
193 int localBufNum = bufnum - world->mNumSndBufs; \
194 Graph *parent = unit->mParent; \
195 if(localBufNum <= parent->localBufNum) { \
196 buf = parent->mLocalSndBufs + localBufNum; \
197 } else { \
198 bufnum = 0; \
199 buf = world->mSndBufs + bufnum; \
201 } else { \
202 if (bufnum < 0) { bufnum = 0; } \
203 buf = world->mSndBufs + bufnum; \
205 LOCK_SNDBUF_SHARED(buf); \
206 const float *bufData __attribute__((__unused__)) = buf->data; \
207 uint32 bufChannels __attribute__((__unused__)) = buf->channels; \
208 uint32 bufSamples __attribute__((__unused__)) = buf->samples; \
209 uint32 bufFrames = buf->frames; \
210 int guardFrame __attribute__((__unused__)) = bufFrames - 2;
212 #define DECLARE_WINDOW \
213 double winPos, winInc, w, b1, y1, y2, y0; \
214 float amp; \
215 winPos = winInc = w = b1 = y1 = y2 = y0 = amp = 0.; \
216 SndBuf *window; \
217 const float *windowData __attribute__((__unused__)) = 0;\
218 uint32 windowSamples __attribute__((__unused__)) = 0; \
219 uint32 windowFrames __attribute__((__unused__)) = 0; \
220 int windowGuardFrame = 0;
223 #define CHECK_BUF \
224 if (!bufData) { \
225 unit->mDone = true; \
226 ClearUnitOutputs(unit, inNumSamples); \
227 return; \
230 #define GET_GRAIN_WIN_RELAXED(WINTYPE) \
231 do { \
232 assert(WINTYPE < unit->mWorld->mNumSndBufs); \
233 window = unit->mWorld->mSndBufs + (int)WINTYPE; \
234 windowData = window->data; \
235 windowSamples = window->samples; \
236 windowFrames = window->frames; \
237 windowGuardFrame = windowFrames - 1; \
238 } while (0);
240 #define GET_GRAIN_WIN(WINTYPE) \
241 do { \
242 if (WINTYPE >= unit->mWorld->mNumSndBufs) { \
243 Print("Envelope buffer out of range!\n"); \
244 return; \
246 GET_GRAIN_WIN_RELAXED(WINTYPE) \
247 } while (0);
249 #define GRAIN_LOOP_BODY_4 \
250 float amp = y1 * y1; \
251 phase = sc_gloop(phase, loopMax); \
252 int32 iphase = (int32)phase; \
253 float* table1 = bufData + iphase; \
254 float* table0 = table1 - 1; \
255 float* table2 = table1 + 1; \
256 float* table3 = table1 + 2; \
257 if (iphase == 0) { \
258 table0 += bufSamples; \
259 } else if (iphase >= guardFrame) { \
260 if (iphase == guardFrame) { \
261 table3 -= bufSamples; \
262 } else { \
263 table2 -= bufSamples; \
264 table3 -= bufSamples; \
267 float fracphase = phase - (double)iphase; \
268 float a = table0[0]; \
269 float b = table1[0]; \
270 float c = table2[0]; \
271 float d = table3[0]; \
272 float outval = amp * cubicinterp(fracphase, a, b, c, d) \
273 ZXP(out1) += outval; \
274 double y0 = b1 * y1 - y2; \
275 y2 = y1; \
276 y1 = y0;
278 #define GRAIN_LOOP_BODY_2 \
279 float amp = y1 * y1; \
280 phase = sc_gloop(phase, loopMax); \
281 int32 iphase = (int32)phase; \
282 float* table1 = bufData + iphase; \
283 float* table2 = table1 + 1; \
284 if (iphase > guardFrame) { \
285 table2 -= bufSamples; \
287 double fracphase = phase - (double)iphase; \
288 float b = table1[0]; \
289 float c = table2[0]; \
290 float outval = amp * (b + fracphase * (c - b)); \
291 ZXP(out1) += outval; \
292 double y0 = b1 * y1 - y2; \
293 y2 = y1; \
294 y1 = y0;
297 #define GRAIN_LOOP_BODY_1 \
298 float amp = y1 * y1; \
299 phase = sc_gloop(phase, loopMax); \
300 int32 iphase = (int32)phase; \
301 float outval = amp * bufData[iphase]; \
302 ZXP(out1) += outval; \
303 double y0 = b1 * y1 - y2; \
304 y2 = y1; \
305 y1 = y0;
307 #define BUF_GRAIN_AMP \
308 winPos += winInc; \
309 int iWinPos = (int)winPos; \
310 double winFrac = winPos - (double)iWinPos; \
311 float* winTable1 = windowData + iWinPos; \
312 float* winTable2 = winTable1 + 1; \
313 if (winPos > windowGuardFrame) { \
314 winTable2 -= windowSamples; \
316 amp = lininterp(winFrac, winTable1[0], winTable2[0]);
318 #define BUF_GRAIN_LOOP_BODY_4 \
319 phase = sc_gloop(phase, loopMax); \
320 int32 iphase = (int32)phase; \
321 float* table1 = bufData + iphase; \
322 float* table0 = table1 - 1; \
323 float* table2 = table1 + 1; \
324 float* table3 = table1 + 2; \
325 if (iphase == 0) { \
326 table0 += bufSamples; \
327 } else if (iphase >= guardFrame) { \
328 if (iphase == guardFrame) { \
329 table3 -= bufSamples; \
330 } else { \
331 table2 -= bufSamples; \
332 table3 -= bufSamples; \
335 float fracphase = phase - (double)iphase; \
336 float a = table0[0]; \
337 float b = table1[0]; \
338 float c = table2[0]; \
339 float d = table3[0]; \
340 float outval = amp * cubicinterp(fracphase, a, b, c, d); \
341 ZXP(out1) += outval;
343 #define BUF_GRAIN_LOOP_BODY_2 \
344 phase = sc_gloop(phase, loopMax); \
345 int32 iphase = (int32)phase; \
346 float* table1 = bufData + iphase; \
347 float* table2 = table1 + 1; \
348 if (iphase > guardFrame) { \
349 table2 -= bufSamples; \
351 float fracphase = phase - (double)iphase; \
352 float b = table1[0]; \
353 float c = table2[0]; \
354 float outval = amp * (b + fracphase * (c - b)); \
355 ZXP(out1) += outval;
357 // amp needs to be calculated by looking up values in window
359 #define BUF_GRAIN_LOOP_BODY_1 \
360 phase = sc_gloop(phase, loopMax); \
361 int32 iphase = (int32)phase; \
362 float outval = amp * bufData[iphase]; \
363 ZXP(out1) += outval;
366 #define SETUP_OUT \
367 uint32 numOutputs = unit->mNumOutputs; \
368 if (numOutputs > bufChannels) { \
369 unit->mDone = true; \
370 ClearUnitOutputs(unit, inNumSamples); \
371 return; \
373 float *out[16]; \
374 for (uint32 i=0; i<numOutputs; ++i) out[i] = ZOUT(i);
377 #define CALC_GRAIN_PAN \
378 float panangle, pan1, pan2; \
379 float *out1, *out2; \
380 if (numOutputs > 1) { \
381 if (numOutputs == 2) pan = pan * 0.5f; \
382 pan = sc_wrap(pan * 0.5f, 0.f, 1.f); \
383 float cpan = numOutputs * pan + 0.5f; \
384 float ipan = floor(cpan); \
385 float panfrac = cpan - ipan; \
386 panangle = panfrac * pi2_f; \
387 grain->chan = (int)ipan; \
388 if (grain->chan >= (int)numOutputs) \
389 grain->chan -= numOutputs; \
390 pan1 = grain->pan1 = cos(panangle); \
391 pan2 = grain->pan2 = sin(panangle); \
392 } else { \
393 grain->chan = 0; \
394 pan1 = grain->pan1 = 1.; \
395 pan2 = grain->pan2 = 0.; \
398 #define GET_GRAIN_INIT_AMP \
399 if(grain->winType < 0.){ \
400 w = pi / counter; \
401 b1 = grain->b1 = 2. * cos(w); \
402 y1 = sin(w); \
403 y2 = 0.; \
404 amp = y1 * y1; \
405 } else { \
406 amp = windowData[0]; \
407 winPos = grain->winPos = 0.f; \
408 winInc = grain->winInc = (double)windowSamples / counter; \
411 #define CALC_NEXT_GRAIN_AMP_INTERNAL \
412 do { \
413 y0 = b1 * y1 - y2; \
414 y2 = y1; \
415 y1 = y0; \
416 amp = y1 * y1; \
417 } while(0)
419 #define CALC_NEXT_GRAIN_AMP_CUSTOM \
420 do { \
421 winPos += winInc; \
422 int iWinPos = (int)winPos; \
423 double winFrac = winPos - (double)iWinPos; \
424 const float* winTable1 = windowData + iWinPos; \
425 const float* winTable2 = winTable1 + 1; \
426 if (!windowData) \
427 break; \
428 if (winPos > windowGuardFrame) \
429 winTable2 -= windowSamples; \
430 amp = lininterp(winFrac, winTable1[0], winTable2[0]); \
431 } while (0); \
432 if (!windowData) \
433 break; \
435 #define CALC_NEXT_GRAIN_AMP \
436 if(grain->winType < 0.) { \
437 CALC_NEXT_GRAIN_AMP_INTERNAL; \
438 } else { \
439 CALC_NEXT_GRAIN_AMP_CUSTOM; \
443 #define GET_GRAIN_AMP_PARAMS \
444 if(grain->winType < 0.){ \
445 b1 = grain->b1; \
446 y1 = grain->y1; \
447 y2 = grain->y2; \
448 amp = grain->curamp; \
449 } else { \
450 GET_GRAIN_WIN_RELAXED(grain->winType); \
451 if (!windowData) break; \
452 winPos = grain->winPos; \
453 winInc = grain->winInc; \
454 amp = grain->curamp; \
457 #define SAVE_GRAIN_AMP_PARAMS \
458 grain->y1 = y1; \
459 grain->y2 = y2; \
460 grain->winPos = winPos; \
461 grain->winInc = winInc; \
462 grain->curamp = amp; \
463 grain->counter -= nsmps;
465 #define WRAP_CHAN(offset) \
466 out1 = OUT(grain->chan) + offset; \
467 if(numOutputs > 1) { \
468 if((grain->chan + 1) >= (int)numOutputs) \
469 out2 = OUT(0) + offset; \
470 else \
471 out2 = OUT(grain->chan + 1) + offset; \
474 #define GET_PAN_PARAMS \
475 float pan1 = grain->pan1; \
476 uint32 chan1 = grain->chan; \
477 float *out1 = OUT(chan1); \
478 if(numOutputs > 1){ \
479 pan2 = grain->pan2; \
480 uint32 chan2 = chan1 + 1; \
481 if (chan2 >= numOutputs) chan2 = 0; \
482 out2 = OUT(chan2); \
486 //////////////////// InGrain ////////////////////
488 inline void GrainIn_next_play_active(GrainIn * unit, int inNumSamples)
490 const uint32 numOutputs = unit->mNumOutputs;
491 float *in = IN(2);
492 for (int i=0; i < unit->mNumActive; ) {
493 GrainInG *grain = unit->mGrains + i;
494 DECLARE_WINDOW
495 GET_GRAIN_AMP_PARAMS
496 // begin add //
498 float pan2 = 0.f;
499 float *out2;
501 GET_PAN_PARAMS
502 // end add //
503 int nsmps = sc_min(grain->counter, inNumSamples);
504 for (int j=0; j<nsmps; ++j) {
505 float outval = amp * in[j];
506 // begin change / add //
507 out1[j] += outval * pan1;
508 if(numOutputs > 1) out2[j] += outval * pan2;
509 // end change //
511 CALC_NEXT_GRAIN_AMP
514 SAVE_GRAIN_AMP_PARAMS
516 if (grain->counter <= 0)
517 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
518 else
519 ++i;
523 template <bool full_rate>
524 inline void GrainIn_next_start_new(GrainIn * unit, int inNumSamples, int position)
526 if (unit->mNumActive+1 >= unit->mMaxGrains) {
527 Print("Too many grains!\n");
528 return;
531 float winType = grain_in_at<full_rate>(unit, 4, position);
532 DECLARE_WINDOW
533 GET_GRAIN_WIN(winType)
534 if (winType >= 0 && (windowData == NULL))
535 return;
537 GrainInG *grain = unit->mGrains + unit->mNumActive++;
538 float winSize = grain_in_at<full_rate>(unit, 1, position);
539 double counter = winSize * SAMPLERATE;
540 counter = sc_max(4., counter);
541 grain->counter = (int)counter;
542 grain->winType = winType;
544 GET_GRAIN_INIT_AMP
546 const uint32 numOutputs = unit->mNumOutputs;
547 float *in = IN(2);
549 float *in1 = in + position;
550 // begin add //
551 float pan = grain_in_at<full_rate>(unit, 3, position);
553 CALC_GRAIN_PAN
555 WRAP_CHAN(position)
557 int nsmps = sc_min(grain->counter, inNumSamples - position);
558 for (int j=0; j<nsmps; ++j) {
559 float outval = amp * in1[j];
560 // begin add / change
561 out1[j] += outval * pan1;
562 if(numOutputs > 1) out2[j] += outval * pan2;
563 // end add / change
564 CALC_NEXT_GRAIN_AMP
567 SAVE_GRAIN_AMP_PARAMS
569 if (grain->counter <= 0)
570 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
573 void GrainIn_next_a(GrainIn *unit, int inNumSamples)
575 ClearUnitOutputs(unit, inNumSamples);
576 //begin add
577 // end add
579 GrainIn_next_play_active(unit, inNumSamples);
581 float *trig = IN(0);
582 for (int i=0; i<inNumSamples; ++i) {
583 if ((unit->curtrig <= 0) && (trig[i] > 0.0))
584 GrainIn_next_start_new<true>(unit, inNumSamples, i);
585 unit->curtrig = trig[i];
589 void GrainIn_next_k(GrainIn *unit, int inNumSamples)
591 ClearUnitOutputs(unit, inNumSamples);
592 if(unit->mFirst){
593 unit->mFirst = false;
594 float maxGrains = IN0(5);
595 unit->mMaxGrains = (int)maxGrains;
596 unit->mGrains = (GrainInG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainInG));
599 GrainIn_next_play_active(unit, inNumSamples);
601 float trig = IN0(0);
603 if ((unit->curtrig <= 0) && (trig > 0.0))
604 GrainIn_next_start_new<false>(unit, inNumSamples, 0);
605 unit->curtrig = trig;
609 void GrainIn_Ctor(GrainIn *unit)
611 if (INRATE(0) == calc_FullRate)
612 SETCALC(GrainIn_next_a);
613 else
614 SETCALC(GrainIn_next_k);
615 unit->mFirst = true;
616 unit->mNumActive = 0;
617 unit->curtrig = 0.f;
618 GrainIn_next_k(unit, 1);
621 void GrainIn_Dtor(GrainIn *unit)
623 RTFree(unit->mWorld, unit->mGrains);
626 inline void GrainSin_next_play_active(GrainSin * unit, int inNumSamples)
628 const unsigned int numOutputs = unit->mNumOutputs;
630 float *table0 = ft->mSineWavetable;
631 float *table1 = table0 + 1;
633 for (int i=0; i < unit->mNumActive; ) {
634 GrainSinG *grain = unit->mGrains + i;
635 DECLARE_WINDOW
636 GET_GRAIN_AMP_PARAMS
638 // begin add //
640 float pan2 = 0.f;
641 float *out2;
643 GET_PAN_PARAMS
645 // end add //
647 int32 thisfreq = grain->freq;
648 int32 oscphase = grain->oscphase;
650 int nsmps = sc_min(grain->counter, inNumSamples);
651 for (int j=0; j<nsmps; ++j) {
652 float outval = amp * lookupi1(table0, table1, oscphase, unit->m_lomask);
653 // begin change / add //
654 out1[j] += outval * pan1;
655 if(numOutputs > 1) out2[j] += outval * pan2;
656 // end change //
657 CALC_NEXT_GRAIN_AMP
659 oscphase += thisfreq;
662 SAVE_GRAIN_AMP_PARAMS
664 grain->oscphase = oscphase;
665 if (grain->counter <= 0)
666 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
667 else
668 ++i;
672 template <bool full_rate>
673 inline void GrainSin_next_start_new(GrainSin * unit, int inNumSamples, int position)
675 if (unit->mNumActive+1 >= unit->mMaxGrains) {
676 Print("Too many grains!\n");
677 return;
680 float winType = grain_in_at<full_rate>(unit, 4, position);
681 DECLARE_WINDOW
682 GET_GRAIN_WIN(winType)
683 if (winType >= 0 && (windowData == NULL))
684 return;
686 GrainSinG *grain = unit->mGrains + unit->mNumActive++;
687 float freq = grain_in_at<full_rate>(unit, 2, position);
688 float winSize = grain_in_at<full_rate>(unit, 1, position);
689 int32 thisfreq = grain->freq = (int32)(unit->m_cpstoinc * freq);
690 int32 oscphase = 0;
691 double counter = winSize * SAMPLERATE;
692 counter = sc_max(4., counter);
693 grain->counter = (int)counter;
694 grain->winType = winType;
696 GET_GRAIN_INIT_AMP
698 const uint32 numOutputs = unit->mNumOutputs;
700 float *table0 = ft->mSineWavetable;
701 float *table1 = table0 + 1;
703 // begin add //
704 float pan = grain_in_at<full_rate>(unit, 3, position);
706 CALC_GRAIN_PAN
708 WRAP_CHAN(position)
710 // end add //
712 int nsmps = sc_min(grain->counter, inNumSamples - position);
713 for (int j=0; j<nsmps; ++j) {
714 float outval = amp * lookupi1(table0, table1, oscphase, unit->m_lomask);
715 // begin add / change
716 out1[j] += outval * pan1;
717 if(numOutputs > 1) out2[j] += outval * pan2;
718 // end add / change
719 CALC_NEXT_GRAIN_AMP
721 oscphase += thisfreq;
723 grain->oscphase = oscphase;
725 SAVE_GRAIN_AMP_PARAMS
727 if (grain->counter <= 0)
728 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
731 void GrainSin_next_a(GrainSin *unit, int inNumSamples)
733 ClearUnitOutputs(unit, inNumSamples);
735 GrainSin_next_play_active(unit, inNumSamples);
737 float *trig = IN(0);
738 for (int i=0; i<inNumSamples; ++i) {
739 if ((unit->curtrig <= 0) && (trig[i] > 0.0))
740 GrainSin_next_start_new<true>(unit, inNumSamples, i);
741 unit->curtrig = trig[i];
745 void GrainSin_next_k(GrainSin *unit, int inNumSamples)
747 ClearUnitOutputs(unit, inNumSamples);
748 if(unit->mFirst){
749 unit->mFirst = false;
750 float maxGrains = IN0(5);
751 unit->mMaxGrains = (int)maxGrains;
752 unit->mGrains = (GrainSinG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainSinG));
755 GrainSin_next_play_active(unit, inNumSamples);
757 float trig = IN0(0);
760 if ((unit->curtrig <= 0) && (trig > 0.0))
761 GrainSin_next_start_new<false>(unit, inNumSamples, 0);
762 unit->curtrig = trig;
765 void GrainSin_Ctor(GrainSin *unit)
767 if (INRATE(0) == calc_FullRate)
768 SETCALC(GrainSin_next_a);
769 else
770 SETCALC(GrainSin_next_k);
771 int tableSizeSin = ft->mSineSize;
772 unit->m_lomask = (tableSizeSin - 1) << 3;
773 unit->m_radtoinc = tableSizeSin * (rtwopi * 65536.);
774 unit->m_cpstoinc = tableSizeSin * SAMPLEDUR * 65536.;
775 unit->curtrig = 0.f;
776 unit->mNumActive = 0;
777 unit->mFirst = true;
778 GrainSin_next_k(unit, 1);
781 void GrainSin_Dtor(GrainSin *unit)
783 RTFree(unit->mWorld, unit->mGrains);
787 inline void GrainFM_next_play_active(GrainFM *unit, int inNumSamples)
789 const uint32 numOutputs = unit->mNumOutputs;
790 // end add
792 float *table0 = ft->mSineWavetable;
793 float *table1 = table0 + 1;
795 for (int i=0; i < unit->mNumActive; ) {
796 GrainFMG *grain = unit->mGrains + i;
797 DECLARE_WINDOW
798 GET_GRAIN_AMP_PARAMS
800 int32 mfreq = grain->mfreq;
801 int32 moscphase = grain->moscphase;
802 int32 coscphase = grain->coscphase;
803 float deviation = grain->deviation;
804 float carbase = grain->carbase;
805 // begin add //
807 float pan2 = 0.f;
808 float *out2;
810 GET_PAN_PARAMS
812 // end add //
813 int nsmps = sc_min(grain->counter, inNumSamples);
814 for (int j=0; j<nsmps; ++j) {
815 float thismod = lookupi1(table0, table1, moscphase, unit->m_lomask) * deviation;
816 float outval = amp * lookupi1(table0, table1, coscphase, unit->m_lomask);
817 // begin change / add //
818 out1[j] += outval * pan1;
819 if(numOutputs > 1) out2[j] += outval * pan2;
820 // end change //
821 CALC_NEXT_GRAIN_AMP
823 int32 cfreq = (int32)(unit->m_cpstoinc * (carbase + thismod)); // needs to be calced in the loop!
824 coscphase += cfreq;
825 moscphase += mfreq;
826 } // need to save float carbase, int32 mfreq, float deviation
827 grain->coscphase = coscphase;
828 grain->moscphase = moscphase;
830 SAVE_GRAIN_AMP_PARAMS
832 if (grain->counter <= 0)
833 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
834 else
835 ++i;
839 template <bool full_rate>
840 inline void GrainFM_next_start_new(GrainFM * unit, int inNumSamples, int position)
842 if (unit->mNumActive+1 >= unit->mMaxGrains) {
843 Print("Too many grains!\n");
844 return;
847 float winType = grain_in_at<full_rate>(unit, 6, position);
848 DECLARE_WINDOW
849 GET_GRAIN_WIN(winType)
850 if (winType >= 0 && (windowData == NULL))
851 return;
853 GrainFMG *grain = unit->mGrains + unit->mNumActive++;
854 float winSize = GRAIN_IN_AT(unit, 1, position);
855 float carfreq = GRAIN_IN_AT(unit, 2, position);
856 float modfreq = GRAIN_IN_AT(unit, 3, position);
857 float index = GRAIN_IN_AT(unit, 4, position);
858 float deviation = grain->deviation = index * modfreq;
859 int32 mfreq = grain->mfreq = (int32)(unit->m_cpstoinc * modfreq);
860 grain->carbase = carfreq;
861 int32 coscphase = 0;
862 int32 moscphase = 0;
863 double counter = winSize * SAMPLERATE;
864 counter = sc_max(4., counter);
865 grain->counter = (int)counter;
866 grain->winType = winType; //GRAIN_IN_AT(unit, 6, i);
868 GET_GRAIN_INIT_AMP
869 const uint32 numOutputs = unit->mNumOutputs;
871 float *table0 = ft->mSineWavetable;
872 float *table1 = table0 + 1;
874 // begin add //
875 float pan = GRAIN_IN_AT(unit, 5, position);
877 CALC_GRAIN_PAN
879 WRAP_CHAN(position)
881 // end add //
882 int nsmps = sc_min(grain->counter, inNumSamples - position);
883 for (int j=0; j<nsmps; ++j) {
884 float thismod = lookupi1(table0, table1, moscphase, unit->m_lomask) * deviation;
885 float outval = amp * lookupi1(table0, table1, coscphase, unit->m_lomask);
886 // begin add / change
887 out1[j] += outval * pan1;
888 if(numOutputs > 1) out2[j] += outval * pan2;
889 // end add / change
890 CALC_NEXT_GRAIN_AMP
892 int32 cfreq = (int32)(unit->m_cpstoinc * (carfreq + thismod)); // needs to be calced in the loop!
893 coscphase += cfreq;
894 moscphase += mfreq;
895 } // need to save float carbase, int32 mfreq, float deviation
896 grain->coscphase = coscphase;
897 grain->moscphase = moscphase;
899 SAVE_GRAIN_AMP_PARAMS
901 if (grain->counter <= 0)
902 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
905 void GrainFM_next_a(GrainFM *unit, int inNumSamples)
907 ClearUnitOutputs(unit, inNumSamples);
909 GrainFM_next_play_active(unit, inNumSamples);
911 float *trig = IN(0);
912 for (int i=0; i<inNumSamples; ++i) {
913 if ((unit->curtrig <= 0) && (trig[i] > 0.0))
914 GrainFM_next_start_new<true>(unit, inNumSamples, i);
915 unit->curtrig = trig[i];
919 void GrainFM_next_k(GrainFM *unit, int inNumSamples)
921 ClearUnitOutputs(unit, inNumSamples);
923 if (unit->mFirst) {
924 unit->mFirst = false;
925 float maxGrains = IN0(7);
926 unit->mMaxGrains = (int)maxGrains;
927 unit->mGrains = (GrainFMG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainFMG));
930 GrainFM_next_play_active(unit, inNumSamples);
932 float trig = IN0(0);
933 if ((unit->curtrig <= 0) && (trig > 0.0))
934 GrainFM_next_start_new<false>(unit, inNumSamples, 0);
936 unit->curtrig = trig;
939 void GrainFM_Ctor(GrainFM *unit)
941 if (INRATE(0) == calc_FullRate)
942 SETCALC(GrainFM_next_a);
943 else
944 SETCALC(GrainFM_next_k);
945 int tableSizeSin = ft->mSineSize;
946 unit->m_lomask = (tableSizeSin - 1) << 3;
947 unit->m_radtoinc = tableSizeSin * (rtwopi * 65536.);
948 unit->m_cpstoinc = tableSizeSin * SAMPLEDUR * 65536.;
949 unit->curtrig = 0.f;
950 unit->mNumActive = 0;
951 unit->mFirst = true;
952 GrainFM_next_k(unit, 1);
955 void GrainFM_Dtor(GrainFM *unit)
957 RTFree(unit->mWorld, unit->mGrains);
960 #define GRAIN_BUF_LOOP_BODY_4_MONO \
961 phase = sc_gloop(phase, loopMax); \
962 int32 iphase = (int32)phase; \
963 const float* table1 = bufData + iphase; \
964 const float* table0 = table1 - 1; \
965 const float* table2 = table1 + 1; \
966 const float* table3 = table1 + 2; \
967 if (iphase == 0) { \
968 table0 += bufSamples; \
969 } else if (iphase >= guardFrame) { \
970 if (iphase == guardFrame) { \
971 table3 -= bufSamples; \
972 } else { \
973 table2 -= bufSamples; \
974 table3 -= bufSamples; \
977 float fracphase = phase - (double)iphase; \
978 float a = table0[0]; \
979 float b = table1[0]; \
980 float c = table2[0]; \
981 float d = table3[0]; \
982 float outval = amp * cubicinterp(fracphase, a, b, c, d); \
983 out1[j] += outval * pan1; \
985 #define GRAIN_BUF_LOOP_BODY_4_STEREO \
986 GRAIN_BUF_LOOP_BODY_4_MONO \
987 out2[j] += outval * pan2;
989 #define GRAIN_BUF_LOOP_BODY_2_MONO \
990 phase = sc_gloop(phase, loopMax); \
991 int32 iphase = (int32)phase; \
992 const float* table1 = bufData + iphase; \
993 const float* table2 = table1 + 1; \
994 if (iphase > guardFrame) { \
995 table2 -= bufSamples; \
997 float fracphase = phase - (double)iphase; \
998 float b = table1[0]; \
999 float c = table2[0]; \
1000 float outval = amp * (b + fracphase * (c - b)); \
1001 out1[j] += outval * pan1; \
1003 #define GRAIN_BUF_LOOP_BODY_2_STEREO \
1004 GRAIN_BUF_LOOP_BODY_2_MONO \
1005 out2[j] += outval * pan2;
1007 #define GRAIN_BUF_LOOP_BODY_1_MONO \
1008 phase = sc_gloop(phase, loopMax); \
1009 int32 iphase = (int32)phase; \
1010 float outval = amp * bufData[iphase]; \
1011 out1[j] += outval * pan1;
1013 #define GRAIN_BUF_LOOP_BODY_1_STEREO \
1014 GRAIN_BUF_LOOP_BODY_1_MONO \
1015 out2[j] += outval * pan2;
1018 #define GRAIN_BUF_PLAY_GRAIN(WINDOW) \
1019 do {\
1020 if (numOutputs == 1) \
1022 if (grain->interp >= 4) { \
1023 for (int j=0; j<nsmps; j++) { \
1024 GRAIN_BUF_LOOP_BODY_4_MONO \
1025 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1026 phase += rate; \
1028 } else if (grain->interp >= 2) { \
1029 for (int j=0; j<nsmps; j++) { \
1030 GRAIN_BUF_LOOP_BODY_2_MONO \
1031 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1032 phase += rate; \
1034 } else { \
1035 for (int j=0; j<nsmps; j++) { \
1036 GRAIN_BUF_LOOP_BODY_1_MONO \
1037 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1038 phase += rate; \
1041 } else { \
1042 if (grain->interp >= 4) { \
1043 for (int j=0; j<nsmps; j++) { \
1044 GRAIN_BUF_LOOP_BODY_4_STEREO \
1045 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1046 phase += rate; \
1048 } else if (grain->interp >= 2) { \
1049 for (int j=0; j<nsmps; j++) { \
1050 GRAIN_BUF_LOOP_BODY_2_STEREO \
1051 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1052 phase += rate; \
1054 } else { \
1055 for (int j=0; j<nsmps; j++) { \
1056 GRAIN_BUF_LOOP_BODY_1_STEREO \
1057 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1058 phase += rate; \
1062 } while (0)
1065 static inline bool GrainBuf_grain_cleanup(GrainBuf * unit, GrainBufG * grain)
1067 if (grain->counter <= 0)
1069 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
1070 return true;
1072 else
1073 return false;
1076 template <bool IsMono>
1077 static inline void GrainBuf_next_play_active(GrainBuf *unit, int inNumSamples)
1079 const uint32 numOutputs = IsMono ? 1 : unit->mNumOutputs;
1081 World *world = unit->mWorld;
1083 for (int i=0; i < unit->mNumActive; ) {
1084 GrainBufG *grain = unit->mGrains + i;
1085 uint32 bufnum = grain->bufnum;
1087 GRAIN_BUF
1089 if (!bufData) {
1090 grain->counter -= inNumSamples;
1091 if (!GrainBuf_grain_cleanup(unit, grain))
1092 ++i;
1093 continue;
1096 double loopMax = (double)bufFrames;
1097 double rate = grain->rate;
1098 double phase = grain->phase;
1100 DECLARE_WINDOW
1101 GET_GRAIN_AMP_PARAMS
1103 // begin add //
1104 float pan2 = 0.f;
1105 float *out2;
1106 GET_PAN_PARAMS
1107 // end add //
1108 int nsmps = sc_min(grain->counter, inNumSamples);
1110 if (grain->winType < 0.)
1111 GRAIN_BUF_PLAY_GRAIN(INTERNAL);
1112 else
1113 GRAIN_BUF_PLAY_GRAIN(CUSTOM);
1115 if (GrainBuf_grain_cleanup(unit, grain))
1116 continue;
1117 ++i;
1119 grain->phase = phase;
1121 SAVE_GRAIN_AMP_PARAMS
1125 template <bool full_rate, bool IsMono>
1126 static inline void GrainBuf_next_start_new(GrainBuf *unit, int inNumSamples, int position)
1128 World *world = unit->mWorld;
1130 if (unit->mNumActive+1 >= unit->mMaxGrains) {
1131 Print("Too many grains!\n");
1132 return;
1135 GrainBufG *grain = unit->mGrains + unit->mNumActive++;
1136 float winType = grain_in_at<full_rate>(unit, 7, position);
1137 DECLARE_WINDOW
1138 GET_GRAIN_WIN(winType)
1139 if (winType >= 0 && (windowData == NULL))
1140 return;
1142 int32 bufnum = grain_in_at<full_rate>(unit, 2, position);
1143 grain->bufnum = bufnum;
1145 GRAIN_BUF
1147 if ( (bufChannels != 1) || (!bufData) ) {
1148 GrainBuf_grain_cleanup(unit, grain);
1149 return;
1152 float bufSampleRate = buf->samplerate;
1153 float bufRateScale = bufSampleRate * SAMPLEDUR;
1154 double loopMax = (double)bufFrames;
1156 double counter = grain_in_at<full_rate>(unit, 1, position) * SAMPLERATE;
1157 counter = sc_max(4., counter);
1158 grain->counter = (int)counter;
1160 double rate = grain->rate = grain_in_at<full_rate>(unit, 3, position) * bufRateScale;
1161 double phase = grain_in_at<full_rate>(unit, 4, position) * bufFrames;
1162 grain->interp = (int)grain_in_at<full_rate>(unit, 5, position);
1163 grain->winType = winType;
1165 GET_GRAIN_INIT_AMP
1167 const uint32 numOutputs = IsMono ? 1 : unit->mNumOutputs;
1169 // begin add //
1170 float pan = grain_in_at<full_rate>(unit, 6, position);
1172 CALC_GRAIN_PAN
1174 WRAP_CHAN(position)
1176 // end add //
1178 int nsmps = sc_min(grain->counter, inNumSamples - position);
1180 if (grain->winType < 0.)
1181 GRAIN_BUF_PLAY_GRAIN(INTERNAL);
1182 else
1183 GRAIN_BUF_PLAY_GRAIN(CUSTOM);
1185 grain->phase = phase;
1187 SAVE_GRAIN_AMP_PARAMS
1189 GrainBuf_grain_cleanup(unit, grain);
1193 template <bool MultiChannel>
1194 static void GrainBuf_next_a(GrainBuf *unit, int inNumSamples)
1196 ClearUnitOutputs(unit, inNumSamples);
1198 GrainBuf_next_play_active<MultiChannel>(unit, inNumSamples);
1200 float *trig = IN(0);
1201 for (int i=0; i<inNumSamples; i++) {
1202 if ((trig[i] > 0) && (unit->curtrig <=0))
1203 GrainBuf_next_start_new<true, MultiChannel>(unit, inNumSamples, i);
1204 unit->curtrig = trig[i];
1208 template <bool MultiChannel>
1209 static void GrainBuf_next_k(GrainBuf * unit, int inNumSamples)
1211 ClearUnitOutputs(unit, inNumSamples);
1213 GrainBuf_next_play_active<MultiChannel>(unit, inNumSamples);
1215 float trig = IN0(0);
1216 if ((trig > 0) && (unit->curtrig <=0))
1217 GrainBuf_next_start_new<false, MultiChannel>(unit, inNumSamples, 0);
1218 unit->curtrig = trig;
1221 FLATTEN static void GrainBuf_next_k_1(GrainBuf * unit, int inNumSamples)
1223 GrainBuf_next_k<true>(unit, inNumSamples);
1226 FLATTEN static void GrainBuf_next_k_2(GrainBuf * unit, int inNumSamples)
1228 GrainBuf_next_k<false>(unit, inNumSamples);
1231 FLATTEN static void GrainBuf_next_a_1(GrainBuf * unit, int inNumSamples)
1233 GrainBuf_next_a<true>(unit, inNumSamples);
1236 FLATTEN static void GrainBuf_next_a_2(GrainBuf * unit, int inNumSamples)
1238 GrainBuf_next_a<false>(unit, inNumSamples);
1241 void GrainBuf_Ctor(GrainBuf *unit)
1243 unit->mNumActive = 0;
1244 unit->curtrig = 0.f;
1246 float maxGrains = IN0(8);
1247 unit->mMaxGrains = (int)maxGrains;
1248 unit->mGrains = (GrainBufG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainBufG));
1250 if (unit->mNumOutputs == 1) {
1251 if (INRATE(0) == calc_FullRate)
1252 SETCALC(GrainBuf_next_a_1);
1253 else
1254 SETCALC(GrainBuf_next_k_1);
1255 } else {
1256 if (INRATE(0) == calc_FullRate)
1257 SETCALC(GrainBuf_next_a_2);
1258 else
1259 SETCALC(GrainBuf_next_k_2);
1262 (unit->mCalcFunc)(unit, 1);
1265 void GrainBuf_Dtor(GrainBuf *unit)
1267 RTFree(unit->mWorld, unit->mGrains);
1271 #define BUF_GRAIN_LOOP_BODY_4_N \
1272 phase = sc_gloop(phase, loopMax); \
1273 int32 iphase = (int32)phase; \
1274 const float* table1 = bufData + iphase * bufChannels; \
1275 const float* table0 = table1 - bufChannels; \
1276 const float* table2 = table1 + bufChannels; \
1277 const float* table3 = table2 + bufChannels; \
1278 if (iphase == 0) { \
1279 table0 += bufSamples; \
1280 } else if (iphase >= guardFrame) { \
1281 if (iphase == guardFrame) { \
1282 table3 -= bufSamples; \
1283 } else { \
1284 table2 -= bufSamples; \
1285 table3 -= bufSamples; \
1288 float fracphase = phase - (double)iphase; \
1289 float a = table0[n]; \
1290 float b = table1[n]; \
1291 float c = table2[n]; \
1292 float d = table3[n]; \
1293 float outval = amp * cubicinterp(fracphase, a, b, c, d); \
1294 ZXP(out1) += outval; \
1296 #define BUF_GRAIN_LOOP_BODY_2_N \
1297 phase = sc_gloop(phase, loopMax); \
1298 int32 iphase = (int32)phase; \
1299 const float* table1 = bufData + iphase * bufChannels; \
1300 const float* table2 = table1 + bufChannels; \
1301 if (iphase > guardFrame) { \
1302 table2 -= bufSamples; \
1304 float fracphase = phase - (double)iphase; \
1305 float b = table1[n]; \
1306 float c = table2[n]; \
1307 float outval = amp * (b + fracphase * (c - b)); \
1308 ZXP(out1) += outval; \
1310 // amp needs to be calculated by looking up values in window
1312 #define BUF_GRAIN_LOOP_BODY_1_N \
1313 phase = sc_gloop(phase, loopMax); \
1314 int32 iphase = (int32)phase; \
1315 float outval = amp * bufData[iphase + n]; \
1316 ZXP(out1) += outval; \
1319 #define GET_WARP_WIN_RELAXED(WINTYPE) \
1320 do { \
1321 assert(WINTYPE < unit->mWorld->mNumSndBufs); \
1322 window = unit->mWorld->mSndBufs + (int)WINTYPE; \
1323 while (!TRY_ACQUIRE_SNDBUF_SHARED(window)) { \
1324 RELEASE_SNDBUF_SHARED(buf); \
1325 ACQUIRE_SNDBUF_SHARED(buf); \
1327 windowData = window->data; \
1328 if (windowData == NULL) \
1329 RELEASE_SNDBUF_SHARED(window); \
1330 windowSamples = window->samples; \
1331 windowFrames = window->frames; \
1332 windowGuardFrame = windowFrames - 1; \
1333 } while (0);
1335 #define GET_WARP_AMP_PARAMS \
1336 if(grain->winType < 0.){ \
1337 b1 = grain->b1; \
1338 y1 = grain->y1; \
1339 y2 = grain->y2; \
1340 amp = grain->curamp; \
1341 } else { \
1342 GET_WARP_WIN_RELAXED(grain->winType); \
1343 if (!windowData) break; \
1344 winPos = grain->winPos; \
1345 winInc = grain->winInc; \
1346 amp = grain->curamp; \
1350 void Warp1_next(Warp1 *unit, int inNumSamples)
1352 ClearUnitOutputs(unit, inNumSamples);
1354 GET_BUF
1355 SETUP_OUT
1356 CHECK_BUF
1358 for (uint32 n=0; n < numOutputs; n++) {
1359 int nextGrain = unit->mNextGrain[n];
1360 for (int i=0; i < unit->mNumActive[n]; ) {
1361 WarpWinGrain *grain = unit->mGrains[n] + i;
1363 double loopMax = (double)bufFrames;
1365 double rate = grain->rate;
1366 double phase = grain->phase;
1367 DECLARE_WINDOW
1368 GET_GRAIN_AMP_PARAMS
1369 float *out1 = out[n];
1370 int nsmps = sc_min(grain->counter, inNumSamples);
1371 if (grain->interp >= 4) {
1372 for (int j=0; j<nsmps; ++j) {
1373 BUF_GRAIN_LOOP_BODY_4_N
1374 CALC_NEXT_GRAIN_AMP
1375 phase += rate;
1377 } else if (grain->interp >= 2) {
1378 for (int j=0; j<nsmps; ++j) {
1379 BUF_GRAIN_LOOP_BODY_2_N
1380 CALC_NEXT_GRAIN_AMP
1381 phase += rate;
1383 } else {
1384 for (int j=0; j<nsmps; ++j) {
1385 BUF_GRAIN_LOOP_BODY_1_N
1386 CALC_NEXT_GRAIN_AMP
1387 phase += rate;
1391 grain->phase = phase;
1392 SAVE_GRAIN_AMP_PARAMS
1393 if (grain->counter <= 0)
1394 *grain = unit->mGrains[n][--unit->mNumActive[n]]; // remove grain
1395 else
1396 ++i;
1399 for (int i=0; i<inNumSamples; ++i) {
1400 --nextGrain;
1401 if (nextGrain == 0) {
1402 // start a grain
1403 if (unit->mNumActive[n]+1 >= kMaxGrains) break;
1404 // uint32 bufnum = (uint32)GRAIN_IN_AT(unit, 0, i);
1405 // if (bufnum >= numBufs) break;
1407 float bufSampleRate = buf->samplerate;
1408 float bufRateScale = bufSampleRate * SAMPLEDUR;
1409 double loopMax = (double)bufFrames;
1411 WarpWinGrain *grain = unit->mGrains[n] + unit->mNumActive[n]++;
1412 // grain->bufnum = bufnum;
1414 float overlaps = GRAIN_IN_AT(unit, 5, i);
1415 float counter = GRAIN_IN_AT(unit, 3, i) * SAMPLERATE;
1416 double winrandamt = unit->mParent->mRGen->frand2() * (double)GRAIN_IN_AT(unit, 6, i);
1417 counter = sc_max(4., floor(counter + (counter * winrandamt)));
1418 grain->counter = (int)counter;
1420 nextGrain = (int)(counter / overlaps);
1422 unit->mNextGrain[n] = nextGrain;
1424 float rate = grain->rate = GRAIN_IN_AT(unit, 2, i) * bufRateScale;
1425 float phase = GRAIN_IN_AT(unit, 1, i) * (float)bufFrames;
1426 grain->interp = (int)GRAIN_IN_AT(unit, 7, i);
1427 float winType = grain->winType = (int)GRAIN_IN_AT(unit, 4, i); // the buffer that holds the grain shape
1428 DECLARE_WINDOW
1430 if (winType >= unit->mWorld->mNumSndBufs) {
1431 Print("Envelope buffer out of range!\n");
1432 break;
1435 GET_GRAIN_WIN_RELAXED(winType)
1436 if (windowData || (winType < 0.)) {
1437 GET_GRAIN_INIT_AMP
1439 float *out1 = out[n] + i;
1441 int nsmps = sc_min(grain->counter, inNumSamples - i);
1442 if (grain->interp >= 4) {
1443 for (int j=0; j<nsmps; ++j) {
1444 BUF_GRAIN_LOOP_BODY_4_N
1445 CALC_NEXT_GRAIN_AMP
1446 phase += rate;
1448 } else if (grain->interp >= 2) {
1449 for (int j=0; j<nsmps; ++j) {
1450 BUF_GRAIN_LOOP_BODY_2_N
1451 CALC_NEXT_GRAIN_AMP
1452 phase += rate;
1454 } else {
1455 for (int j=0; j<nsmps; ++j) {
1456 BUF_GRAIN_LOOP_BODY_1_N
1457 CALC_NEXT_GRAIN_AMP
1458 phase += rate;
1462 grain->phase = phase;
1463 SAVE_GRAIN_AMP_PARAMS
1464 // end change
1465 if (grain->counter <= 0)
1466 *grain = unit->mGrains[n][--unit->mNumActive[n]]; // remove grain
1471 unit->mNextGrain[n] = nextGrain;
1475 void Warp1_Ctor(Warp1 *unit)
1477 SETCALC(Warp1_next);
1479 for(int i = 0; i < 16; i++){
1480 unit->mNumActive[i] = 0;
1481 unit->mNextGrain[i] = 1;
1484 ClearUnitOutputs(unit, 1);
1485 unit->m_fbufnum = -1e9f;
1489 ////////////////////////////////////////////////////////////////////////////////////////////////////////
1491 PluginLoad(Grain)
1493 ft = inTable;
1495 DefineDtorCantAliasUnit(GrainIn);
1496 DefineDtorCantAliasUnit(GrainSin);
1497 DefineDtorCantAliasUnit(GrainFM);
1498 DefineDtorCantAliasUnit(GrainBuf);
1499 DefineSimpleCantAliasUnit(Warp1);