class library: SynthDef - replaceUGen fixes
[supercollider.git] / server / plugins / GrainUGens.cpp
blobc49b593f3fc06e17a9187e5477f96ed2c0764a9a
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 #if defined (__GNUC__) && !defined(__clang__)
33 #define inline_functions __attribute__ ((flatten))
34 #else
35 #define inline_functions
36 #endif
38 static InterfaceTable *ft;
40 const int kMaxGrains = 64;
42 const int kMaxSynthGrains = 512;
44 struct GrainInG
46 double b1, y1, y2, curamp, winPos, winInc; // envelope
47 int counter, chan;
48 float pan1, pan2, winType;
51 struct GrainIn : public Unit
53 int mNumActive, m_channels, mMaxGrains;
54 float curtrig;
55 bool mFirst;
56 GrainInG *mGrains;
59 struct GrainSinG
61 double b1, y1, y2, curamp, winPos, winInc; // envelope
62 int counter, chan;
63 float pan1, pan2, winType;
64 int32 oscphase; // the phase of the osc inside this grain
65 int32 freq; // the freq of the osc inside this grain in phase inc
68 struct GrainSin : public Unit
70 int mNumActive, m_channels, mMaxGrains;
71 uint32 m_lomask;
72 float curtrig;
73 bool mFirst;
74 double m_cpstoinc, m_radtoinc;
75 GrainSinG *mGrains;
78 struct GrainFMG
80 int32 coscphase, moscphase; // the phase of the osc inside this grain
81 int32 mfreq; // the freq of the osc inside this grain in phase inc
82 double b1, y1, y2, curamp, winPos, winInc; // envelope
83 float deviation, carbase, pan1, pan2, winType;
84 int counter, chan;
88 struct GrainFM : public Unit
90 int mNumActive, m_channels, mMaxGrains;
91 uint32 m_lomask;
92 float curtrig;
93 bool mFirst;
94 double m_cpstoinc, m_radtoinc;
95 GrainFMG *mGrains;
98 struct GrainBufG
100 double phase, rate;
101 double b1, y1, y2, curamp, winPos, winInc;
102 float pan1, pan2, winType;
103 int counter, chan, bufnum, interp;
106 struct GrainBuf : public Unit
108 int mNumActive, m_channels, mMaxGrains;
109 float curtrig;
110 GrainBufG *mGrains;
113 struct WarpWinGrain
115 double phase, rate;
116 double winPos, winInc, b1, y1, y2, curamp; // tells the grain where to look in the winBuf for an amp value
117 int counter, bufnum, interp;
118 float winType;
121 struct Warp1 : public Unit
123 float m_fbufnum;
124 SndBuf* m_buf;
125 int mNumActive[16];
126 int mNextGrain[16];
127 WarpWinGrain mGrains[16][kMaxGrains];
130 ////////////////////////////////////////////////////////////////////////
132 extern "C"
135 void GrainIn_Ctor(GrainIn* unit);
136 void GrainIn_Dtor(GrainIn* unit);
137 void GrainIn_next_a(GrainIn *unit, int inNumSamples);
138 void GrainIn_next_k(GrainIn *unit, int inNumSamples);
140 void GrainSin_Ctor(GrainSin* unit);
141 void GrainSin_Dtor(GrainSin* unit);
142 void GrainSin_next_a(GrainSin *unit, int inNumSamples);
143 void GrainSin_next_k(GrainSin *unit, int inNumSamples);
145 void GrainFM_Ctor(GrainFM* unit);
146 void GrainFM_Dtor(GrainFM* unit);
147 void GrainFM_next_a(GrainFM *unit, int inNumSamples);
148 void GrainFM_next_k(GrainFM *unit, int inNumSamples);
150 void GrainBuf_Ctor(GrainBuf* unit);
151 void GrainBuf_Dtor(GrainBuf* unit);
153 void Warp1_next(Warp1 *unit, int inNumSamples);
154 void Warp1_Ctor(Warp1* unit);
157 ////////////////////////////////////////////////////////////////////////////////////////////////////////
158 //////////////////////////////// Granular UGens ////////////////////////////////////////////////////////
159 ////////////////////////////////////////////////////////////////////////////////////////////////////////
161 inline float GRAIN_IN_AT(Unit* unit, int index, int offset)
163 if (INRATE(index) == calc_FullRate) return IN(index)[offset];
164 if (INRATE(index) == calc_DemandRate) return DEMANDINPUT_A(index, offset + 1);
165 return IN0(index);
168 template <bool full_rate>
169 inline float grain_in_at(Unit* unit, int index, int offset)
171 if (full_rate)
172 return GRAIN_IN_AT(unit, index, offset);
174 if (INRATE(index) == calc_DemandRate)
175 return DEMANDINPUT_A(index, offset + 1);
176 else
177 return IN0(index);
180 inline double sc_gloop(double in, double hi)
182 // avoid the divide if possible
183 if (in >= hi) {
184 in -= hi;
185 if (in < hi) return in;
186 } else if (in < 0.) {
187 in += hi;
188 if (in >= 0.) return in;
189 } else return in;
191 return in - hi * floor(in/hi);
194 #define GRAIN_BUF \
195 const SndBuf *buf; \
196 if (bufnum >= world->mNumSndBufs) { \
197 int localBufNum = bufnum - world->mNumSndBufs; \
198 Graph *parent = unit->mParent; \
199 if(localBufNum <= parent->localBufNum) { \
200 buf = parent->mLocalSndBufs + localBufNum; \
201 } else { \
202 bufnum = 0; \
203 buf = world->mSndBufs + bufnum; \
205 } else { \
206 if (bufnum < 0) { bufnum = 0; } \
207 buf = world->mSndBufs + bufnum; \
209 LOCK_SNDBUF_SHARED(buf); \
210 const float *bufData __attribute__((__unused__)) = buf->data; \
211 uint32 bufChannels __attribute__((__unused__)) = buf->channels; \
212 uint32 bufSamples __attribute__((__unused__)) = buf->samples; \
213 uint32 bufFrames = buf->frames; \
214 int guardFrame __attribute__((__unused__)) = bufFrames - 2;
216 #define DECLARE_WINDOW \
217 double winPos, winInc, w, b1, y1, y2, y0; \
218 float amp; \
219 winPos = winInc = w = b1 = y1 = y2 = y0 = amp = 0.; \
220 SndBuf *window; \
221 const float *windowData __attribute__((__unused__)) = 0;\
222 uint32 windowSamples __attribute__((__unused__)) = 0; \
223 uint32 windowFrames __attribute__((__unused__)) = 0; \
224 int windowGuardFrame = 0;
227 #define CHECK_BUF \
228 if (!bufData) { \
229 unit->mDone = true; \
230 ClearUnitOutputs(unit, inNumSamples); \
231 return; \
234 #define GET_GRAIN_WIN_RELAXED(WINTYPE) \
235 do { \
236 assert(WINTYPE < unit->mWorld->mNumSndBufs); \
237 window = unit->mWorld->mSndBufs + (int)WINTYPE; \
238 windowData = window->data; \
239 windowSamples = window->samples; \
240 windowFrames = window->frames; \
241 windowGuardFrame = windowFrames - 1; \
242 } while (0);
244 #define GET_GRAIN_WIN(WINTYPE) \
245 do { \
246 if (WINTYPE >= unit->mWorld->mNumSndBufs) { \
247 Print("Envelope buffer out of range!\n"); \
248 return; \
250 GET_GRAIN_WIN_RELAXED(WINTYPE) \
251 } while (0);
253 #define GRAIN_LOOP_BODY_4 \
254 float amp = y1 * y1; \
255 phase = sc_gloop(phase, loopMax); \
256 int32 iphase = (int32)phase; \
257 float* table1 = bufData + iphase; \
258 float* table0 = table1 - 1; \
259 float* table2 = table1 + 1; \
260 float* table3 = table1 + 2; \
261 if (iphase == 0) { \
262 table0 += bufSamples; \
263 } else if (iphase >= guardFrame) { \
264 if (iphase == guardFrame) { \
265 table3 -= bufSamples; \
266 } else { \
267 table2 -= bufSamples; \
268 table3 -= bufSamples; \
271 float fracphase = phase - (double)iphase; \
272 float a = table0[0]; \
273 float b = table1[0]; \
274 float c = table2[0]; \
275 float d = table3[0]; \
276 float outval = amp * cubicinterp(fracphase, a, b, c, d) \
277 ZXP(out1) += outval; \
278 double y0 = b1 * y1 - y2; \
279 y2 = y1; \
280 y1 = y0;
282 #define GRAIN_LOOP_BODY_2 \
283 float amp = y1 * y1; \
284 phase = sc_gloop(phase, loopMax); \
285 int32 iphase = (int32)phase; \
286 float* table1 = bufData + iphase; \
287 float* table2 = table1 + 1; \
288 if (iphase > guardFrame) { \
289 table2 -= bufSamples; \
291 double fracphase = phase - (double)iphase; \
292 float b = table1[0]; \
293 float c = table2[0]; \
294 float outval = amp * (b + fracphase * (c - b)); \
295 ZXP(out1) += outval; \
296 double y0 = b1 * y1 - y2; \
297 y2 = y1; \
298 y1 = y0;
301 #define GRAIN_LOOP_BODY_1 \
302 float amp = y1 * y1; \
303 phase = sc_gloop(phase, loopMax); \
304 int32 iphase = (int32)phase; \
305 float outval = amp * bufData[iphase]; \
306 ZXP(out1) += outval; \
307 double y0 = b1 * y1 - y2; \
308 y2 = y1; \
309 y1 = y0;
311 #define BUF_GRAIN_AMP \
312 winPos += winInc; \
313 int iWinPos = (int)winPos; \
314 double winFrac = winPos - (double)iWinPos; \
315 float* winTable1 = windowData + iWinPos; \
316 float* winTable2 = winTable1 + 1; \
317 if (winPos > windowGuardFrame) { \
318 winTable2 -= windowSamples; \
320 amp = lininterp(winFrac, winTable1[0], winTable2[0]);
322 #define BUF_GRAIN_LOOP_BODY_4 \
323 phase = sc_gloop(phase, loopMax); \
324 int32 iphase = (int32)phase; \
325 float* table1 = bufData + iphase; \
326 float* table0 = table1 - 1; \
327 float* table2 = table1 + 1; \
328 float* table3 = table1 + 2; \
329 if (iphase == 0) { \
330 table0 += bufSamples; \
331 } else if (iphase >= guardFrame) { \
332 if (iphase == guardFrame) { \
333 table3 -= bufSamples; \
334 } else { \
335 table2 -= bufSamples; \
336 table3 -= bufSamples; \
339 float fracphase = phase - (double)iphase; \
340 float a = table0[0]; \
341 float b = table1[0]; \
342 float c = table2[0]; \
343 float d = table3[0]; \
344 float outval = amp * cubicinterp(fracphase, a, b, c, d); \
345 ZXP(out1) += outval;
347 #define BUF_GRAIN_LOOP_BODY_2 \
348 phase = sc_gloop(phase, loopMax); \
349 int32 iphase = (int32)phase; \
350 float* table1 = bufData + iphase; \
351 float* table2 = table1 + 1; \
352 if (iphase > guardFrame) { \
353 table2 -= bufSamples; \
355 float fracphase = phase - (double)iphase; \
356 float b = table1[0]; \
357 float c = table2[0]; \
358 float outval = amp * (b + fracphase * (c - b)); \
359 ZXP(out1) += outval;
361 // amp needs to be calculated by looking up values in window
363 #define BUF_GRAIN_LOOP_BODY_1 \
364 phase = sc_gloop(phase, loopMax); \
365 int32 iphase = (int32)phase; \
366 float outval = amp * bufData[iphase]; \
367 ZXP(out1) += outval;
370 #define SETUP_OUT \
371 uint32 numOutputs = unit->mNumOutputs; \
372 if (numOutputs > bufChannels) { \
373 unit->mDone = true; \
374 ClearUnitOutputs(unit, inNumSamples); \
375 return; \
377 float *out[16]; \
378 for (uint32 i=0; i<numOutputs; ++i) out[i] = ZOUT(i);
381 #define CALC_GRAIN_PAN \
382 float panangle, pan1, pan2; \
383 float *out1, *out2; \
384 if (numOutputs > 1) { \
385 if (numOutputs == 2) pan = pan * 0.5f; \
386 pan = sc_wrap(pan * 0.5f, 0.f, 1.f); \
387 float cpan = numOutputs * pan + 0.5f; \
388 float ipan = floor(cpan); \
389 float panfrac = cpan - ipan; \
390 panangle = panfrac * pi2_f; \
391 grain->chan = (int)ipan; \
392 if (grain->chan >= (int)numOutputs) \
393 grain->chan -= numOutputs; \
394 pan1 = grain->pan1 = cos(panangle); \
395 pan2 = grain->pan2 = sin(panangle); \
396 } else { \
397 grain->chan = 0; \
398 pan1 = grain->pan1 = 1.; \
399 pan2 = grain->pan2 = 0.; \
402 #define GET_GRAIN_INIT_AMP \
403 if(grain->winType < 0.){ \
404 w = pi / counter; \
405 b1 = grain->b1 = 2. * cos(w); \
406 y1 = sin(w); \
407 y2 = 0.; \
408 amp = y1 * y1; \
409 } else { \
410 amp = windowData[0]; \
411 winPos = grain->winPos = 0.f; \
412 winInc = grain->winInc = (double)windowSamples / counter; \
415 #define CALC_NEXT_GRAIN_AMP_INTERNAL \
416 do { \
417 y0 = b1 * y1 - y2; \
418 y2 = y1; \
419 y1 = y0; \
420 amp = y1 * y1; \
421 } while(0)
423 #define CALC_NEXT_GRAIN_AMP_CUSTOM \
424 do { \
425 winPos += winInc; \
426 int iWinPos = (int)winPos; \
427 double winFrac = winPos - (double)iWinPos; \
428 const float* winTable1 = windowData + iWinPos; \
429 const float* winTable2 = winTable1 + 1; \
430 if (!windowData) \
431 break; \
432 if (winPos > windowGuardFrame) \
433 winTable2 -= windowSamples; \
434 amp = lininterp(winFrac, winTable1[0], winTable2[0]); \
435 } while (0); \
436 if (!windowData) \
437 break; \
439 #define CALC_NEXT_GRAIN_AMP \
440 if(grain->winType < 0.) { \
441 CALC_NEXT_GRAIN_AMP_INTERNAL; \
442 } else { \
443 CALC_NEXT_GRAIN_AMP_CUSTOM; \
447 #define GET_GRAIN_AMP_PARAMS \
448 if(grain->winType < 0.){ \
449 b1 = grain->b1; \
450 y1 = grain->y1; \
451 y2 = grain->y2; \
452 amp = grain->curamp; \
453 } else { \
454 GET_GRAIN_WIN_RELAXED(grain->winType); \
455 if (!windowData) break; \
456 winPos = grain->winPos; \
457 winInc = grain->winInc; \
458 amp = grain->curamp; \
461 #define SAVE_GRAIN_AMP_PARAMS \
462 grain->y1 = y1; \
463 grain->y2 = y2; \
464 grain->winPos = winPos; \
465 grain->winInc = winInc; \
466 grain->curamp = amp; \
467 grain->counter -= nsmps;
469 #define WRAP_CHAN(offset) \
470 out1 = OUT(grain->chan) + offset; \
471 if(numOutputs > 1) { \
472 if((grain->chan + 1) >= (int)numOutputs) \
473 out2 = OUT(0) + offset; \
474 else \
475 out2 = OUT(grain->chan + 1) + offset; \
478 #define GET_PAN_PARAMS \
479 float pan1 = grain->pan1; \
480 uint32 chan1 = grain->chan; \
481 float *out1 = OUT(chan1); \
482 if(numOutputs > 1){ \
483 pan2 = grain->pan2; \
484 uint32 chan2 = chan1 + 1; \
485 if (chan2 >= numOutputs) chan2 = 0; \
486 out2 = OUT(chan2); \
490 //////////////////// InGrain ////////////////////
492 inline void GrainIn_next_play_active(GrainIn * unit, int inNumSamples)
494 const uint32 numOutputs = unit->mNumOutputs;
495 float *in = IN(2);
496 for (int i=0; i < unit->mNumActive; ) {
497 GrainInG *grain = unit->mGrains + i;
498 DECLARE_WINDOW
499 GET_GRAIN_AMP_PARAMS
500 // begin add //
502 float pan2 = 0.f;
503 float *out2;
505 GET_PAN_PARAMS
506 // end add //
507 int nsmps = sc_min(grain->counter, inNumSamples);
508 for (int j=0; j<nsmps; ++j) {
509 float outval = amp * in[j];
510 // begin change / add //
511 out1[j] += outval * pan1;
512 if(numOutputs > 1) out2[j] += outval * pan2;
513 // end change //
515 CALC_NEXT_GRAIN_AMP
518 SAVE_GRAIN_AMP_PARAMS
520 if (grain->counter <= 0)
521 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
522 else
523 ++i;
527 template <bool full_rate>
528 inline void GrainIn_next_start_new(GrainIn * unit, int inNumSamples, int position)
530 if (unit->mNumActive+1 >= unit->mMaxGrains) {
531 Print("Too many grains!\n");
532 return;
535 float winType = grain_in_at<full_rate>(unit, 4, position);
536 DECLARE_WINDOW
537 GET_GRAIN_WIN(winType)
538 if (winType >= 0 && (windowData == NULL))
539 return;
541 GrainInG *grain = unit->mGrains + unit->mNumActive++;
542 float winSize = grain_in_at<full_rate>(unit, 1, position);
543 double counter = winSize * SAMPLERATE;
544 counter = sc_max(4., counter);
545 grain->counter = (int)counter;
546 grain->winType = winType;
548 GET_GRAIN_INIT_AMP
550 const uint32 numOutputs = unit->mNumOutputs;
551 float *in = IN(2);
553 float *in1 = in + position;
554 // begin add //
555 float pan = grain_in_at<full_rate>(unit, 3, position);
557 CALC_GRAIN_PAN
559 WRAP_CHAN(position)
561 int nsmps = sc_min(grain->counter, inNumSamples - position);
562 for (int j=0; j<nsmps; ++j) {
563 float outval = amp * in1[j];
564 // begin add / change
565 out1[j] += outval * pan1;
566 if(numOutputs > 1) out2[j] += outval * pan2;
567 // end add / change
568 CALC_NEXT_GRAIN_AMP
571 SAVE_GRAIN_AMP_PARAMS
573 if (grain->counter <= 0)
574 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
577 void GrainIn_next_a(GrainIn *unit, int inNumSamples)
579 ClearUnitOutputs(unit, inNumSamples);
580 //begin add
581 // end add
583 GrainIn_next_play_active(unit, inNumSamples);
585 float *trig = IN(0);
586 for (int i=0; i<inNumSamples; ++i) {
587 if ((unit->curtrig <= 0) && (trig[i] > 0.0))
588 GrainIn_next_start_new<true>(unit, inNumSamples, i);
589 unit->curtrig = trig[i];
593 void GrainIn_next_k(GrainIn *unit, int inNumSamples)
595 ClearUnitOutputs(unit, inNumSamples);
596 if(unit->mFirst){
597 unit->mFirst = false;
598 float maxGrains = IN0(5);
599 unit->mMaxGrains = (int)maxGrains;
600 unit->mGrains = (GrainInG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainInG));
603 GrainIn_next_play_active(unit, inNumSamples);
605 float trig = IN0(0);
607 if ((unit->curtrig <= 0) && (trig > 0.0))
608 GrainIn_next_start_new<false>(unit, inNumSamples, 0);
609 unit->curtrig = trig;
613 void GrainIn_Ctor(GrainIn *unit)
615 if (INRATE(0) == calc_FullRate)
616 SETCALC(GrainIn_next_a);
617 else
618 SETCALC(GrainIn_next_k);
619 unit->mFirst = true;
620 unit->mNumActive = 0;
621 unit->curtrig = 0.f;
622 GrainIn_next_k(unit, 1);
625 void GrainIn_Dtor(GrainIn *unit)
627 RTFree(unit->mWorld, unit->mGrains);
630 inline void GrainSin_next_play_active(GrainSin * unit, int inNumSamples)
632 const unsigned int numOutputs = unit->mNumOutputs;
634 float *table0 = ft->mSineWavetable;
635 float *table1 = table0 + 1;
637 for (int i=0; i < unit->mNumActive; ) {
638 GrainSinG *grain = unit->mGrains + i;
639 DECLARE_WINDOW
640 GET_GRAIN_AMP_PARAMS
642 // begin add //
644 float pan2 = 0.f;
645 float *out2;
647 GET_PAN_PARAMS
649 // end add //
651 int32 thisfreq = grain->freq;
652 int32 oscphase = grain->oscphase;
654 int nsmps = sc_min(grain->counter, inNumSamples);
655 for (int j=0; j<nsmps; ++j) {
656 float outval = amp * lookupi1(table0, table1, oscphase, unit->m_lomask);
657 // begin change / add //
658 out1[j] += outval * pan1;
659 if(numOutputs > 1) out2[j] += outval * pan2;
660 // end change //
661 CALC_NEXT_GRAIN_AMP
663 oscphase += thisfreq;
666 SAVE_GRAIN_AMP_PARAMS
668 grain->oscphase = oscphase;
669 if (grain->counter <= 0)
670 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
671 else
672 ++i;
676 template <bool full_rate>
677 inline void GrainSin_next_start_new(GrainSin * unit, int inNumSamples, int position)
679 if (unit->mNumActive+1 >= unit->mMaxGrains) {
680 Print("Too many grains!\n");
681 return;
684 float winType = grain_in_at<full_rate>(unit, 4, position);
685 DECLARE_WINDOW
686 GET_GRAIN_WIN(winType)
687 if (winType >= 0 && (windowData == NULL))
688 return;
690 GrainSinG *grain = unit->mGrains + unit->mNumActive++;
691 float freq = grain_in_at<full_rate>(unit, 2, position);
692 float winSize = grain_in_at<full_rate>(unit, 1, position);
693 int32 thisfreq = grain->freq = (int32)(unit->m_cpstoinc * freq);
694 int32 oscphase = 0;
695 double counter = winSize * SAMPLERATE;
696 counter = sc_max(4., counter);
697 grain->counter = (int)counter;
698 grain->winType = winType;
700 GET_GRAIN_INIT_AMP
702 const uint32 numOutputs = unit->mNumOutputs;
704 float *table0 = ft->mSineWavetable;
705 float *table1 = table0 + 1;
707 // begin add //
708 float pan = grain_in_at<full_rate>(unit, 3, position);
710 CALC_GRAIN_PAN
712 WRAP_CHAN(position)
714 // end add //
716 int nsmps = sc_min(grain->counter, inNumSamples - position);
717 for (int j=0; j<nsmps; ++j) {
718 float outval = amp * lookupi1(table0, table1, oscphase, unit->m_lomask);
719 // begin add / change
720 out1[j] += outval * pan1;
721 if(numOutputs > 1) out2[j] += outval * pan2;
722 // end add / change
723 CALC_NEXT_GRAIN_AMP
725 oscphase += thisfreq;
727 grain->oscphase = oscphase;
729 SAVE_GRAIN_AMP_PARAMS
731 if (grain->counter <= 0)
732 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
735 void GrainSin_next_a(GrainSin *unit, int inNumSamples)
737 ClearUnitOutputs(unit, inNumSamples);
739 GrainSin_next_play_active(unit, inNumSamples);
741 float *trig = IN(0);
742 for (int i=0; i<inNumSamples; ++i) {
743 if ((unit->curtrig <= 0) && (trig[i] > 0.0))
744 GrainSin_next_start_new<true>(unit, inNumSamples, i);
745 unit->curtrig = trig[i];
749 void GrainSin_next_k(GrainSin *unit, int inNumSamples)
751 ClearUnitOutputs(unit, inNumSamples);
752 if(unit->mFirst){
753 unit->mFirst = false;
754 float maxGrains = IN0(5);
755 unit->mMaxGrains = (int)maxGrains;
756 unit->mGrains = (GrainSinG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainSinG));
759 GrainSin_next_play_active(unit, inNumSamples);
761 float trig = IN0(0);
764 if ((unit->curtrig <= 0) && (trig > 0.0))
765 GrainSin_next_start_new<false>(unit, inNumSamples, 0);
766 unit->curtrig = trig;
769 void GrainSin_Ctor(GrainSin *unit)
771 if (INRATE(0) == calc_FullRate)
772 SETCALC(GrainSin_next_a);
773 else
774 SETCALC(GrainSin_next_k);
775 int tableSizeSin = ft->mSineSize;
776 unit->m_lomask = (tableSizeSin - 1) << 3;
777 unit->m_radtoinc = tableSizeSin * (rtwopi * 65536.);
778 unit->m_cpstoinc = tableSizeSin * SAMPLEDUR * 65536.;
779 unit->curtrig = 0.f;
780 unit->mNumActive = 0;
781 unit->mFirst = true;
782 GrainSin_next_k(unit, 1);
785 void GrainSin_Dtor(GrainSin *unit)
787 RTFree(unit->mWorld, unit->mGrains);
791 inline void GrainFM_next_play_active(GrainFM *unit, int inNumSamples)
793 const uint32 numOutputs = unit->mNumOutputs;
794 // end add
796 float *table0 = ft->mSineWavetable;
797 float *table1 = table0 + 1;
799 for (int i=0; i < unit->mNumActive; ) {
800 GrainFMG *grain = unit->mGrains + i;
801 DECLARE_WINDOW
802 GET_GRAIN_AMP_PARAMS
804 int32 mfreq = grain->mfreq;
805 int32 moscphase = grain->moscphase;
806 int32 coscphase = grain->coscphase;
807 float deviation = grain->deviation;
808 float carbase = grain->carbase;
809 // begin add //
811 float pan2 = 0.f;
812 float *out2;
814 GET_PAN_PARAMS
816 // end add //
817 int nsmps = sc_min(grain->counter, inNumSamples);
818 for (int j=0; j<nsmps; ++j) {
819 float thismod = lookupi1(table0, table1, moscphase, unit->m_lomask) * deviation;
820 float outval = amp * lookupi1(table0, table1, coscphase, unit->m_lomask);
821 // begin change / add //
822 out1[j] += outval * pan1;
823 if(numOutputs > 1) out2[j] += outval * pan2;
824 // end change //
825 CALC_NEXT_GRAIN_AMP
827 int32 cfreq = (int32)(unit->m_cpstoinc * (carbase + thismod)); // needs to be calced in the loop!
828 coscphase += cfreq;
829 moscphase += mfreq;
830 } // need to save float carbase, int32 mfreq, float deviation
831 grain->coscphase = coscphase;
832 grain->moscphase = moscphase;
834 SAVE_GRAIN_AMP_PARAMS
836 if (grain->counter <= 0)
837 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
838 else
839 ++i;
843 template <bool full_rate>
844 inline void GrainFM_next_start_new(GrainFM * unit, int inNumSamples, int position)
846 if (unit->mNumActive+1 >= unit->mMaxGrains) {
847 Print("Too many grains!\n");
848 return;
851 float winType = grain_in_at<full_rate>(unit, 6, position);
852 DECLARE_WINDOW
853 GET_GRAIN_WIN(winType)
854 if (winType >= 0 && (windowData == NULL))
855 return;
857 GrainFMG *grain = unit->mGrains + unit->mNumActive++;
858 float winSize = GRAIN_IN_AT(unit, 1, position);
859 float carfreq = GRAIN_IN_AT(unit, 2, position);
860 float modfreq = GRAIN_IN_AT(unit, 3, position);
861 float index = GRAIN_IN_AT(unit, 4, position);
862 float deviation = grain->deviation = index * modfreq;
863 int32 mfreq = grain->mfreq = (int32)(unit->m_cpstoinc * modfreq);
864 grain->carbase = carfreq;
865 int32 coscphase = 0;
866 int32 moscphase = 0;
867 double counter = winSize * SAMPLERATE;
868 counter = sc_max(4., counter);
869 grain->counter = (int)counter;
870 grain->winType = winType; //GRAIN_IN_AT(unit, 6, i);
872 GET_GRAIN_INIT_AMP
873 const uint32 numOutputs = unit->mNumOutputs;
875 float *table0 = ft->mSineWavetable;
876 float *table1 = table0 + 1;
878 // begin add //
879 float pan = GRAIN_IN_AT(unit, 5, position);
881 CALC_GRAIN_PAN
883 WRAP_CHAN(position)
885 // end add //
886 int nsmps = sc_min(grain->counter, inNumSamples - position);
887 for (int j=0; j<nsmps; ++j) {
888 float thismod = lookupi1(table0, table1, moscphase, unit->m_lomask) * deviation;
889 float outval = amp * lookupi1(table0, table1, coscphase, unit->m_lomask);
890 // begin add / change
891 out1[j] += outval * pan1;
892 if(numOutputs > 1) out2[j] += outval * pan2;
893 // end add / change
894 CALC_NEXT_GRAIN_AMP
896 int32 cfreq = (int32)(unit->m_cpstoinc * (carfreq + thismod)); // needs to be calced in the loop!
897 coscphase += cfreq;
898 moscphase += mfreq;
899 } // need to save float carbase, int32 mfreq, float deviation
900 grain->coscphase = coscphase;
901 grain->moscphase = moscphase;
903 SAVE_GRAIN_AMP_PARAMS
905 if (grain->counter <= 0)
906 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
909 void GrainFM_next_a(GrainFM *unit, int inNumSamples)
911 ClearUnitOutputs(unit, inNumSamples);
913 GrainFM_next_play_active(unit, inNumSamples);
915 float *trig = IN(0);
916 for (int i=0; i<inNumSamples; ++i) {
917 if ((unit->curtrig <= 0) && (trig[i] > 0.0))
918 GrainFM_next_start_new<true>(unit, inNumSamples, i);
919 unit->curtrig = trig[i];
923 void GrainFM_next_k(GrainFM *unit, int inNumSamples)
925 ClearUnitOutputs(unit, inNumSamples);
927 if (unit->mFirst) {
928 unit->mFirst = false;
929 float maxGrains = IN0(7);
930 unit->mMaxGrains = (int)maxGrains;
931 unit->mGrains = (GrainFMG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainFMG));
934 GrainFM_next_play_active(unit, inNumSamples);
936 float trig = IN0(0);
937 if ((unit->curtrig <= 0) && (trig > 0.0))
938 GrainFM_next_start_new<false>(unit, inNumSamples, 0);
940 unit->curtrig = trig;
943 void GrainFM_Ctor(GrainFM *unit)
945 if (INRATE(0) == calc_FullRate)
946 SETCALC(GrainFM_next_a);
947 else
948 SETCALC(GrainFM_next_k);
949 int tableSizeSin = ft->mSineSize;
950 unit->m_lomask = (tableSizeSin - 1) << 3;
951 unit->m_radtoinc = tableSizeSin * (rtwopi * 65536.);
952 unit->m_cpstoinc = tableSizeSin * SAMPLEDUR * 65536.;
953 unit->curtrig = 0.f;
954 unit->mNumActive = 0;
955 unit->mFirst = true;
956 GrainFM_next_k(unit, 1);
959 void GrainFM_Dtor(GrainFM *unit)
961 RTFree(unit->mWorld, unit->mGrains);
964 #define GRAIN_BUF_LOOP_BODY_4_MONO \
965 phase = sc_gloop(phase, loopMax); \
966 int32 iphase = (int32)phase; \
967 const float* table1 = bufData + iphase; \
968 const float* table0 = table1 - 1; \
969 const float* table2 = table1 + 1; \
970 const float* table3 = table1 + 2; \
971 if (iphase == 0) { \
972 table0 += bufSamples; \
973 } else if (iphase >= guardFrame) { \
974 if (iphase == guardFrame) { \
975 table3 -= bufSamples; \
976 } else { \
977 table2 -= bufSamples; \
978 table3 -= bufSamples; \
981 float fracphase = phase - (double)iphase; \
982 float a = table0[0]; \
983 float b = table1[0]; \
984 float c = table2[0]; \
985 float d = table3[0]; \
986 float outval = amp * cubicinterp(fracphase, a, b, c, d); \
987 out1[j] += outval * pan1; \
989 #define GRAIN_BUF_LOOP_BODY_4_STEREO \
990 GRAIN_BUF_LOOP_BODY_4_MONO \
991 out2[j] += outval * pan2;
993 #define GRAIN_BUF_LOOP_BODY_2_MONO \
994 phase = sc_gloop(phase, loopMax); \
995 int32 iphase = (int32)phase; \
996 const float* table1 = bufData + iphase; \
997 const float* table2 = table1 + 1; \
998 if (iphase > guardFrame) { \
999 table2 -= bufSamples; \
1001 float fracphase = phase - (double)iphase; \
1002 float b = table1[0]; \
1003 float c = table2[0]; \
1004 float outval = amp * (b + fracphase * (c - b)); \
1005 out1[j] += outval * pan1; \
1007 #define GRAIN_BUF_LOOP_BODY_2_STEREO \
1008 GRAIN_BUF_LOOP_BODY_2_MONO \
1009 out2[j] += outval * pan2;
1011 #define GRAIN_BUF_LOOP_BODY_1_MONO \
1012 phase = sc_gloop(phase, loopMax); \
1013 int32 iphase = (int32)phase; \
1014 float outval = amp * bufData[iphase]; \
1015 out1[j] += outval * pan1;
1017 #define GRAIN_BUF_LOOP_BODY_1_STEREO \
1018 GRAIN_BUF_LOOP_BODY_1_MONO \
1019 out2[j] += outval * pan2;
1022 #define GRAIN_BUF_PLAY_GRAIN(WINDOW) \
1023 do {\
1024 if (numOutputs == 1) \
1026 if (grain->interp >= 4) { \
1027 for (int j=0; j<nsmps; j++) { \
1028 GRAIN_BUF_LOOP_BODY_4_MONO \
1029 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1030 phase += rate; \
1032 } else if (grain->interp >= 2) { \
1033 for (int j=0; j<nsmps; j++) { \
1034 GRAIN_BUF_LOOP_BODY_2_MONO \
1035 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1036 phase += rate; \
1038 } else { \
1039 for (int j=0; j<nsmps; j++) { \
1040 GRAIN_BUF_LOOP_BODY_1_MONO \
1041 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1042 phase += rate; \
1045 } else { \
1046 if (grain->interp >= 4) { \
1047 for (int j=0; j<nsmps; j++) { \
1048 GRAIN_BUF_LOOP_BODY_4_STEREO \
1049 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1050 phase += rate; \
1052 } else if (grain->interp >= 2) { \
1053 for (int j=0; j<nsmps; j++) { \
1054 GRAIN_BUF_LOOP_BODY_2_STEREO \
1055 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1056 phase += rate; \
1058 } else { \
1059 for (int j=0; j<nsmps; j++) { \
1060 GRAIN_BUF_LOOP_BODY_1_STEREO \
1061 CALC_NEXT_GRAIN_AMP_##WINDOW; \
1062 phase += rate; \
1066 } while (0)
1069 static inline bool GrainBuf_grain_cleanup(GrainBuf * unit, GrainBufG * grain)
1071 if (grain->counter <= 0)
1073 *grain = unit->mGrains[--unit->mNumActive]; // remove grain
1074 return true;
1076 else
1077 return false;
1080 template <bool IsMono>
1081 static inline void GrainBuf_next_play_active(GrainBuf *unit, int inNumSamples)
1083 const uint32 numOutputs = IsMono ? 1 : unit->mNumOutputs;
1085 World *world = unit->mWorld;
1087 for (int i=0; i < unit->mNumActive; ) {
1088 GrainBufG *grain = unit->mGrains + i;
1089 uint32 bufnum = grain->bufnum;
1091 GRAIN_BUF
1093 if (!bufData) {
1094 grain->counter -= inNumSamples;
1095 if (!GrainBuf_grain_cleanup(unit, grain))
1096 ++i;
1097 continue;
1100 double loopMax = (double)bufFrames;
1101 double rate = grain->rate;
1102 double phase = grain->phase;
1104 DECLARE_WINDOW
1105 GET_GRAIN_AMP_PARAMS
1107 // begin add //
1108 float pan2 = 0.f;
1109 float *out2;
1110 GET_PAN_PARAMS
1111 // end add //
1112 int nsmps = sc_min(grain->counter, inNumSamples);
1114 if (grain->winType < 0.)
1115 GRAIN_BUF_PLAY_GRAIN(INTERNAL);
1116 else
1117 GRAIN_BUF_PLAY_GRAIN(CUSTOM);
1119 if (GrainBuf_grain_cleanup(unit, grain))
1120 continue;
1121 ++i;
1123 grain->phase = phase;
1125 SAVE_GRAIN_AMP_PARAMS
1129 template <bool full_rate, bool IsMono>
1130 static inline void GrainBuf_next_start_new(GrainBuf *unit, int inNumSamples, int position)
1132 World *world = unit->mWorld;
1134 if (unit->mNumActive+1 >= unit->mMaxGrains) {
1135 Print("Too many grains!\n");
1136 return;
1139 GrainBufG *grain = unit->mGrains + unit->mNumActive++;
1140 float winType = grain_in_at<full_rate>(unit, 7, position);
1141 DECLARE_WINDOW
1142 GET_GRAIN_WIN(winType)
1143 if (winType >= 0 && (windowData == NULL))
1144 return;
1146 int32 bufnum = grain_in_at<full_rate>(unit, 2, position);
1147 grain->bufnum = bufnum;
1149 GRAIN_BUF
1151 if ( (bufChannels != 1) || (!bufData) ) {
1152 GrainBuf_grain_cleanup(unit, grain);
1153 return;
1156 float bufSampleRate = buf->samplerate;
1157 float bufRateScale = bufSampleRate * SAMPLEDUR;
1158 double loopMax = (double)bufFrames;
1160 double counter = grain_in_at<full_rate>(unit, 1, position) * SAMPLERATE;
1161 counter = sc_max(4., counter);
1162 grain->counter = (int)counter;
1164 double rate = grain->rate = grain_in_at<full_rate>(unit, 3, position) * bufRateScale;
1165 double phase = grain_in_at<full_rate>(unit, 4, position) * bufFrames;
1166 grain->interp = (int)grain_in_at<full_rate>(unit, 5, position);
1167 grain->winType = winType;
1169 GET_GRAIN_INIT_AMP
1171 const uint32 numOutputs = IsMono ? 1 : unit->mNumOutputs;
1173 // begin add //
1174 float pan = grain_in_at<full_rate>(unit, 6, position);
1176 CALC_GRAIN_PAN
1178 WRAP_CHAN(position)
1180 // end add //
1182 int nsmps = sc_min(grain->counter, inNumSamples - position);
1184 if (grain->winType < 0.)
1185 GRAIN_BUF_PLAY_GRAIN(INTERNAL);
1186 else
1187 GRAIN_BUF_PLAY_GRAIN(CUSTOM);
1189 grain->phase = phase;
1191 SAVE_GRAIN_AMP_PARAMS
1193 GrainBuf_grain_cleanup(unit, grain);
1197 template <bool MultiChannel>
1198 static void GrainBuf_next_a(GrainBuf *unit, int inNumSamples)
1200 ClearUnitOutputs(unit, inNumSamples);
1202 GrainBuf_next_play_active<MultiChannel>(unit, inNumSamples);
1204 float *trig = IN(0);
1205 for (int i=0; i<inNumSamples; i++) {
1206 if ((trig[i] > 0) && (unit->curtrig <=0))
1207 GrainBuf_next_start_new<true, MultiChannel>(unit, inNumSamples, i);
1208 unit->curtrig = trig[i];
1212 template <bool MultiChannel>
1213 static void GrainBuf_next_k(GrainBuf * unit, int inNumSamples)
1215 ClearUnitOutputs(unit, inNumSamples);
1217 GrainBuf_next_play_active<MultiChannel>(unit, inNumSamples);
1219 float trig = IN0(0);
1220 if ((trig > 0) && (unit->curtrig <=0))
1221 GrainBuf_next_start_new<false, MultiChannel>(unit, inNumSamples, 0);
1222 unit->curtrig = trig;
1225 inline_functions static void GrainBuf_next_k_1(GrainBuf * unit, int inNumSamples)
1227 GrainBuf_next_k<true>(unit, inNumSamples);
1230 inline_functions static void GrainBuf_next_k_2(GrainBuf * unit, int inNumSamples)
1232 GrainBuf_next_k<false>(unit, inNumSamples);
1235 inline_functions static void GrainBuf_next_a_1(GrainBuf * unit, int inNumSamples)
1237 GrainBuf_next_a<true>(unit, inNumSamples);
1240 inline_functions static void GrainBuf_next_a_2(GrainBuf * unit, int inNumSamples)
1242 GrainBuf_next_a<false>(unit, inNumSamples);
1245 void GrainBuf_Ctor(GrainBuf *unit)
1247 unit->mNumActive = 0;
1248 unit->curtrig = 0.f;
1250 float maxGrains = IN0(8);
1251 unit->mMaxGrains = (int)maxGrains;
1252 unit->mGrains = (GrainBufG*)RTAlloc(unit->mWorld, unit->mMaxGrains * sizeof(GrainBufG));
1254 if (unit->mNumOutputs == 1) {
1255 if (INRATE(0) == calc_FullRate)
1256 SETCALC(GrainBuf_next_a_1);
1257 else
1258 SETCALC(GrainBuf_next_k_1);
1259 } else {
1260 if (INRATE(0) == calc_FullRate)
1261 SETCALC(GrainBuf_next_a_2);
1262 else
1263 SETCALC(GrainBuf_next_k_2);
1266 (unit->mCalcFunc)(unit, 1);
1269 void GrainBuf_Dtor(GrainBuf *unit)
1271 RTFree(unit->mWorld, unit->mGrains);
1275 #define BUF_GRAIN_LOOP_BODY_4_N \
1276 phase = sc_gloop(phase, loopMax); \
1277 int32 iphase = (int32)phase; \
1278 const float* table1 = bufData + iphase * bufChannels; \
1279 const float* table0 = table1 - bufChannels; \
1280 const float* table2 = table1 + bufChannels; \
1281 const float* table3 = table2 + bufChannels; \
1282 if (iphase == 0) { \
1283 table0 += bufSamples; \
1284 } else if (iphase >= guardFrame) { \
1285 if (iphase == guardFrame) { \
1286 table3 -= bufSamples; \
1287 } else { \
1288 table2 -= bufSamples; \
1289 table3 -= bufSamples; \
1292 float fracphase = phase - (double)iphase; \
1293 float a = table0[n]; \
1294 float b = table1[n]; \
1295 float c = table2[n]; \
1296 float d = table3[n]; \
1297 float outval = amp * cubicinterp(fracphase, a, b, c, d); \
1298 ZXP(out1) += outval; \
1300 #define BUF_GRAIN_LOOP_BODY_2_N \
1301 phase = sc_gloop(phase, loopMax); \
1302 int32 iphase = (int32)phase; \
1303 const float* table1 = bufData + iphase * bufChannels; \
1304 const float* table2 = table1 + bufChannels; \
1305 if (iphase > guardFrame) { \
1306 table2 -= bufSamples; \
1308 float fracphase = phase - (double)iphase; \
1309 float b = table1[n]; \
1310 float c = table2[n]; \
1311 float outval = amp * (b + fracphase * (c - b)); \
1312 ZXP(out1) += outval; \
1314 // amp needs to be calculated by looking up values in window
1316 #define BUF_GRAIN_LOOP_BODY_1_N \
1317 phase = sc_gloop(phase, loopMax); \
1318 int32 iphase = (int32)phase; \
1319 float outval = amp * bufData[iphase + n]; \
1320 ZXP(out1) += outval; \
1323 #define GET_WARP_WIN_RELAXED(WINTYPE) \
1324 do { \
1325 assert(WINTYPE < unit->mWorld->mNumSndBufs); \
1326 window = unit->mWorld->mSndBufs + (int)WINTYPE; \
1327 while (!TRY_ACQUIRE_SNDBUF_SHARED(window)) { \
1328 RELEASE_SNDBUF_SHARED(buf); \
1329 ACQUIRE_SNDBUF_SHARED(buf); \
1331 windowData = window->data; \
1332 if (windowData == NULL) \
1333 RELEASE_SNDBUF_SHARED(window); \
1334 windowSamples = window->samples; \
1335 windowFrames = window->frames; \
1336 windowGuardFrame = windowFrames - 1; \
1337 } while (0);
1339 #define GET_WARP_AMP_PARAMS \
1340 if(grain->winType < 0.){ \
1341 b1 = grain->b1; \
1342 y1 = grain->y1; \
1343 y2 = grain->y2; \
1344 amp = grain->curamp; \
1345 } else { \
1346 GET_WARP_WIN_RELAXED(grain->winType); \
1347 if (!windowData) break; \
1348 winPos = grain->winPos; \
1349 winInc = grain->winInc; \
1350 amp = grain->curamp; \
1354 void Warp1_next(Warp1 *unit, int inNumSamples)
1356 ClearUnitOutputs(unit, inNumSamples);
1358 GET_BUF
1359 SETUP_OUT
1360 CHECK_BUF
1362 for (uint32 n=0; n < numOutputs; n++) {
1363 int nextGrain = unit->mNextGrain[n];
1364 for (int i=0; i < unit->mNumActive[n]; ) {
1365 WarpWinGrain *grain = unit->mGrains[n] + i;
1367 double loopMax = (double)bufFrames;
1369 double rate = grain->rate;
1370 double phase = grain->phase;
1371 DECLARE_WINDOW
1372 GET_GRAIN_AMP_PARAMS
1373 float *out1 = out[n];
1374 int nsmps = sc_min(grain->counter, inNumSamples);
1375 if (grain->interp >= 4) {
1376 for (int j=0; j<nsmps; ++j) {
1377 BUF_GRAIN_LOOP_BODY_4_N
1378 CALC_NEXT_GRAIN_AMP
1379 phase += rate;
1381 } else if (grain->interp >= 2) {
1382 for (int j=0; j<nsmps; ++j) {
1383 BUF_GRAIN_LOOP_BODY_2_N
1384 CALC_NEXT_GRAIN_AMP
1385 phase += rate;
1387 } else {
1388 for (int j=0; j<nsmps; ++j) {
1389 BUF_GRAIN_LOOP_BODY_1_N
1390 CALC_NEXT_GRAIN_AMP
1391 phase += rate;
1395 grain->phase = phase;
1396 SAVE_GRAIN_AMP_PARAMS
1397 if (grain->counter <= 0)
1398 *grain = unit->mGrains[n][--unit->mNumActive[n]]; // remove grain
1399 else
1400 ++i;
1403 for (int i=0; i<inNumSamples; ++i) {
1404 --nextGrain;
1405 if (nextGrain == 0) {
1406 // start a grain
1407 if (unit->mNumActive[n]+1 >= kMaxGrains) break;
1408 // uint32 bufnum = (uint32)GRAIN_IN_AT(unit, 0, i);
1409 // if (bufnum >= numBufs) break;
1411 float bufSampleRate = buf->samplerate;
1412 float bufRateScale = bufSampleRate * SAMPLEDUR;
1413 double loopMax = (double)bufFrames;
1415 WarpWinGrain *grain = unit->mGrains[n] + unit->mNumActive[n]++;
1416 // grain->bufnum = bufnum;
1418 float overlaps = GRAIN_IN_AT(unit, 5, i);
1419 float counter = GRAIN_IN_AT(unit, 3, i) * SAMPLERATE;
1420 double winrandamt = unit->mParent->mRGen->frand2() * (double)GRAIN_IN_AT(unit, 6, i);
1421 counter = sc_max(4., floor(counter + (counter * winrandamt)));
1422 grain->counter = (int)counter;
1424 nextGrain = (int)(counter / overlaps);
1426 unit->mNextGrain[n] = nextGrain;
1428 float rate = grain->rate = GRAIN_IN_AT(unit, 2, i) * bufRateScale;
1429 float phase = GRAIN_IN_AT(unit, 1, i) * (float)bufFrames;
1430 grain->interp = (int)GRAIN_IN_AT(unit, 7, i);
1431 float winType = grain->winType = (int)GRAIN_IN_AT(unit, 4, i); // the buffer that holds the grain shape
1432 DECLARE_WINDOW
1434 if (winType >= unit->mWorld->mNumSndBufs) {
1435 Print("Envelope buffer out of range!\n");
1436 break;
1439 GET_GRAIN_WIN_RELAXED(winType)
1440 if (windowData || (winType < 0.)) {
1441 GET_GRAIN_INIT_AMP
1443 float *out1 = out[n] + i;
1445 int nsmps = sc_min(grain->counter, inNumSamples - i);
1446 if (grain->interp >= 4) {
1447 for (int j=0; j<nsmps; ++j) {
1448 BUF_GRAIN_LOOP_BODY_4_N
1449 CALC_NEXT_GRAIN_AMP
1450 phase += rate;
1452 } else if (grain->interp >= 2) {
1453 for (int j=0; j<nsmps; ++j) {
1454 BUF_GRAIN_LOOP_BODY_2_N
1455 CALC_NEXT_GRAIN_AMP
1456 phase += rate;
1458 } else {
1459 for (int j=0; j<nsmps; ++j) {
1460 BUF_GRAIN_LOOP_BODY_1_N
1461 CALC_NEXT_GRAIN_AMP
1462 phase += rate;
1466 grain->phase = phase;
1467 SAVE_GRAIN_AMP_PARAMS
1468 // end change
1469 if (grain->counter <= 0)
1470 *grain = unit->mGrains[n][--unit->mNumActive[n]]; // remove grain
1475 unit->mNextGrain[n] = nextGrain;
1479 void Warp1_Ctor(Warp1 *unit)
1481 SETCALC(Warp1_next);
1483 for(int i = 0; i < 16; i++){
1484 unit->mNumActive[i] = 0;
1485 unit->mNextGrain[i] = 1;
1488 ClearUnitOutputs(unit, 1);
1489 unit->m_fbufnum = -1e9f;
1493 ////////////////////////////////////////////////////////////////////////////////////////////////////////
1495 PluginLoad(Grain)
1497 ft = inTable;
1499 DefineDtorCantAliasUnit(GrainIn);
1500 DefineDtorCantAliasUnit(GrainSin);
1501 DefineDtorCantAliasUnit(GrainFM);
1502 DefineDtorCantAliasUnit(GrainBuf);
1503 DefineSimpleCantAliasUnit(Warp1);