FFT: Prevent user from attempting hops smaller than SC's block size
[supercollider.git] / server / plugins / IOUGens.cpp
blob0c29a139d3f22abd1aff0ef26d5422dc1e6006fc
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SC_PlugIn.h"
24 #ifdef SC_IPHONE
25 #include "SC_VFP11.h"
26 #endif
28 #ifdef SUPERNOVA
29 #include "nova-tt/spin_lock.hpp"
30 #include "nova-tt/rw_spinlock.hpp"
31 #endif
33 #ifdef NOVA_SIMD
34 #include "simd_memory.hpp"
35 #include "simd_mix.hpp"
36 #include "simd_binary_arithmetic.hpp"
38 #include "function_attributes.h"
39 using nova::slope_argument;
41 #endif
43 static InterfaceTable *ft;
45 //////////////////////////////////////////////////////////////////////////////////////////////////
47 struct IOUnit : public Unit
49 int32* m_busTouched;
50 float m_fbusChannel;
51 float *m_bus;
54 struct XOut : public IOUnit
56 float m_xfade;
59 struct OffsetOut : public IOUnit
61 float *m_saved;
62 bool m_empty;
65 struct AudioControl : public Unit
67 float *prevVal; // this will have to be a pointer later!
70 const int kMaxLags = 16;
72 struct LagControl : public IOUnit
74 float * m_b1;
75 float * m_y1;
79 struct LagIn : public IOUnit
81 float m_b1;
82 float m_y1[kMaxLags];
85 struct LocalIn : public Unit
87 float *m_bus;
88 int32 *m_busTouched;
89 float *m_realData;
92 extern "C"
94 void Control_Ctor(Unit *inUnit);
95 void Control_next_k(Unit *unit, int inNumSamples);
96 void Control_next_1(Unit *unit, int inNumSamples);
98 void AudioControl_Ctor(AudioControl *inUnit);
99 // void AudioControl_Dtor(AudioControl *inUnit);
100 void AudioControl_next_k(AudioControl *unit, int inNumSamples);
101 void AudioControl_next_1(AudioControl *unit, int inNumSamples);
103 void TrigControl_Ctor(Unit *inUnit);
104 void TrigControl_next_k(Unit *unit, int inNumSamples);
105 void TrigControl_next_1(Unit *unit, int inNumSamples);
107 void LagControl_Ctor(LagControl *inUnit);
108 void LagControl_next_k(LagControl *unit, int inNumSamples);
109 void LagControl_next_1(LagControl *unit, int inNumSamples);
111 void InTrig_Ctor(IOUnit *unit);
112 void InTrig_next_k(IOUnit *unit, int inNumSamples);
114 void In_Ctor(IOUnit *unit);
115 void In_next_a(IOUnit *unit, int inNumSamples);
116 void In_next_k(IOUnit *unit, int inNumSamples);
118 void LagIn_Ctor(LagIn *unit);
119 void LagIn_next_0(LagIn *unit, int inNumSamples);
120 void LagIn_next_k(LagIn *unit, int inNumSamples);
122 void InFeedback_Ctor(IOUnit *unit);
123 void InFeedback_next_a(IOUnit *unit, int inNumSamples);
125 void LocalIn_Ctor(LocalIn *unit);
126 void LocalIn_Dtor(LocalIn *unit);
127 void LocalIn_next_a(LocalIn *unit, int inNumSamples);
128 void LocalIn_next_k(LocalIn *unit, int inNumSamples);
130 void Out_Ctor(IOUnit *unit);
131 void Out_next_a(IOUnit *unit, int inNumSamples);
132 void Out_next_k(IOUnit *unit, int inNumSamples);
134 void XOut_Ctor(XOut *unit);
135 void XOut_next_a(XOut *unit, int inNumSamples);
136 void XOut_next_k(XOut *unit, int inNumSamples);
138 void ReplaceOut_Ctor(IOUnit *unit);
139 void ReplaceOut_next_a(IOUnit *unit, int inNumSamples);
140 void ReplaceOut_next_k(IOUnit *unit, int inNumSamples);
142 void OffsetOut_Ctor(OffsetOut *unit);
143 void OffsetOut_Dtor(OffsetOut* unit);
144 void OffsetOut_next_a(OffsetOut *unit, int inNumSamples);
146 void LocalOut_Ctor(IOUnit *unit);
147 void LocalOut_next_a(IOUnit *unit, int inNumSamples);
148 void LocalOut_next_k(IOUnit *unit, int inNumSamples);
152 //////////////////////////////////////////////////////////////////////////////////////////////////
154 void Control_next_k(Unit *unit, int inNumSamples)
156 uint32 numChannels = unit->mNumOutputs;
157 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
158 for (uint32 i=0; i<numChannels; ++i, mapin++) {
159 float *out = OUT(i);
160 *out = **mapin;
164 void Control_next_1(Unit *unit, int inNumSamples)
166 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
167 float *out = OUT(0);
168 *out = **mapin;
171 void Control_Ctor(Unit* unit)
173 if (unit->mNumOutputs == 1) {
174 SETCALC(Control_next_1);
175 Control_next_1(unit, 1);
176 } else {
177 SETCALC(Control_next_k);
178 Control_next_k(unit, 1);
182 //////////////////////////////////////////////////////////////////////////////////////////////////
184 void AudioControl_next_k(AudioControl *unit, int inNumSamples)
186 uint32 numChannels = unit->mNumOutputs;
187 float *prevVal = unit->prevVal;
188 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
189 for(uint32 i = 0; i < numChannels; ++i, mapin++){
190 float *out = OUT(i);
191 int *mapRatep;
192 int mapRate;
193 float nextVal, curVal, valSlope;
194 mapRatep = unit->mParent->mControlRates + unit->mSpecialIndex;
195 mapRate = mapRatep[i];
196 switch (mapRate) {
197 case 0 : {
198 for(int j = 0; j < inNumSamples; j++){
199 out[j] = *mapin[0];
201 } break;
202 case 1 : {
203 nextVal = *mapin[0];
204 curVal = prevVal[i];
205 valSlope = CALCSLOPE(nextVal, curVal);
206 for(int j = 0; j < inNumSamples; j++){
207 out[j] = curVal; // should be prevVal
208 curVal += valSlope;
210 unit->prevVal[i] = curVal;
211 } break;
212 case 2 : Copy(inNumSamples, out, *mapin);
213 break;
218 void AudioControl_next_1(AudioControl *unit, int inNumSamples)
220 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
221 float *out = OUT(0);
222 int *mapRatep;
223 int mapRate;
224 float nextVal, curVal, valSlope;
225 float* prevVal;
226 prevVal = unit->prevVal;
227 curVal = prevVal[0];
228 mapRatep = unit->mParent->mControlRates + unit->mSpecialIndex;
229 mapRate = mapRatep[0];
231 switch (mapRate) {
232 case 0 : {
233 for(int i = 0; i < inNumSamples; i++){
234 out[i] = *mapin[0];
236 } break;
237 case 1 : {
238 nextVal = *mapin[0];
239 valSlope = CALCSLOPE(nextVal, curVal);
240 for(int i = 0; i < inNumSamples; i++){
241 out[i] = curVal;
242 curVal += valSlope;
244 unit->prevVal[0] = curVal;
245 } break;
246 case 2 :
247 Copy(inNumSamples, out, *mapin);
248 break;
253 void AudioControl_Ctor(AudioControl* unit)
255 unit->prevVal = (float*)RTAlloc(unit->mWorld, unit->mNumOutputs * sizeof(float));
256 for(int i = 0; i < unit->mNumOutputs; i++){
257 unit->prevVal[i] = 0.0;
259 if (unit->mNumOutputs == 1) {
260 SETCALC(AudioControl_next_1);
261 AudioControl_next_1(unit, 1);
262 } else {
263 SETCALC(AudioControl_next_k);
264 AudioControl_next_k(unit, 1);
268 void AudioControl_Dtor(AudioControl* unit)
270 RTFree(unit->mWorld, unit->prevVal);
272 //////////////////////////////////////////////////////////////////////////////////////////////////
273 //////////////////////////////////////////////////////////////////////////////////////////////////
275 void TrigControl_next_k(Unit *unit, int inNumSamples)
277 uint32 numChannels = unit->mNumOutputs;
278 int specialIndex = unit->mSpecialIndex;
279 Graph *parent = unit->mParent;
280 float **mapin = parent->mMapControls + specialIndex;
281 float *control = parent->mControls + specialIndex;
282 World *world = unit->mWorld;
283 float *buses = world->mControlBus;
284 int32 *touched = world->mControlBusTouched;
285 int bufCount = world->mBufCounter;
286 for (uint32 i=0; i<numChannels; ++i, mapin++, control++) {
287 float *out = OUT(i);
288 // requires a bit of detective work to see what it has been mapped to.
289 if (*mapin == control) {
290 // read local control.
291 *out = *control;
292 } else {
293 // global control bus. look at time stamp.
294 int busindex = *mapin - buses;
295 if (touched[busindex] == bufCount) {
296 *out = buses[busindex];
297 } else {
298 *out = 0.f;
301 // must zero the control even if mapped - otherwise it triggers on unmap
302 *control = 0.f;
306 void TrigControl_next_1(Unit *unit, int inNumSamples)
308 int specialIndex = unit->mSpecialIndex;
309 Graph *parent = unit->mParent;
310 float **mapin = parent->mMapControls + specialIndex;
311 float *control = parent->mControls + specialIndex;
312 float *out = OUT(0);
313 // requires a bit of detective work to see what it has been mapped to.
314 if (*mapin == control) {
315 // read local control.
316 *out = *control;
317 } else {
318 // global control bus. look at time stamp.
319 World *world = unit->mWorld;
320 int busindex = *mapin - world->mControlBus;
321 if (world->mControlBusTouched[busindex] == world->mBufCounter) {
322 *out = **mapin;
323 } else {
324 *out = 0.f;
327 // must zero the control even if mapped - otherwise it triggers on unmap
328 *control = 0.f;
331 void TrigControl_Ctor(Unit* unit)
333 //Print("TrigControl_Ctor\n");
334 if (unit->mNumOutputs == 1) {
335 SETCALC(TrigControl_next_1);
336 } else {
337 SETCALC(TrigControl_next_k);
339 ClearUnitOutputs(unit, 1);
342 //////////////////////////////////////////////////////////////////////////////////////////////////
344 void LagControl_next_k(LagControl *unit, int inNumSamples)
346 uint32 numChannels = unit->mNumOutputs;
347 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
348 for (uint32 i=0; i<numChannels; ++i, mapin++) {
349 float *out = OUT(i);
350 float z = **mapin;
351 float x = z + unit->m_b1[i] * (unit->m_y1[i] - z);
352 *out = unit->m_y1[i] = zapgremlins(x);
356 void LagControl_next_1(LagControl *unit, int inNumSamples)
358 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
359 float *out = OUT(0);
360 float z = **mapin;
361 float x = z + unit->m_b1[0] * (unit->m_y1[0] - z);
362 *out = unit->m_y1[0] = zapgremlins(x);
365 void LagControl_Ctor(LagControl* unit)
367 int numChannels = unit->mNumInputs;
368 float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;
370 char * chunk = (char*)RTAlloc(unit->mWorld, numChannels * 2 * sizeof(float));
371 unit->m_y1 = (float*)chunk;
372 unit->m_b1 = unit->m_y1 + numChannels;
374 for (int i=0; i<numChannels; ++i, mapin++) {
375 unit->m_y1[i] = **mapin;
376 float lag = ZIN0(i);
377 unit->m_b1[i] = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate));
380 if (unit->mNumOutputs == 1) {
381 SETCALC(LagControl_next_1);
382 LagControl_next_1(unit, 1);
383 } else {
384 SETCALC(LagControl_next_k);
385 LagControl_next_k(unit, 1);
389 void LagControl_Dtor(LagControl* unit)
391 RTFree(unit->mWorld, unit->m_y1);
394 //////////////////////////////////////////////////////////////////////////////////////////////////
396 #ifdef NOVA_SIMD
397 FLATTEN void In_next_a_nova(IOUnit *unit, int inNumSamples)
399 World *world = unit->mWorld;
400 int bufLength = world->mBufLength;
401 int numChannels = unit->mNumOutputs;
403 float fbusChannel = ZIN0(0);
404 if (fbusChannel != unit->m_fbusChannel) {
405 unit->m_fbusChannel = fbusChannel;
406 int busChannel = (uint32)fbusChannel;
407 int lastChannel = busChannel + numChannels;
409 if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
410 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
411 unit->m_busTouched = world->mAudioBusTouched + busChannel;
415 float *in = unit->m_bus;
416 int32 *touched = unit->m_busTouched;
417 int32 bufCounter = unit->mWorld->mBufCounter;
419 for (int i=0; i<numChannels; ++i, in += bufLength) {
420 ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
421 float *out = OUT(i);
422 if (touched[i] == bufCounter)
423 nova::copyvec_simd(out, in, inNumSamples);
424 else
425 nova::zerovec_simd(out, inNumSamples);
426 RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
430 FLATTEN void In_next_a_nova_64(IOUnit *unit, int inNumSamples)
432 World *world = unit->mWorld;
433 int bufLength = world->mBufLength;
434 int numChannels = unit->mNumOutputs;
436 float fbusChannel = ZIN0(0);
437 if (fbusChannel != unit->m_fbusChannel) {
438 unit->m_fbusChannel = fbusChannel;
439 int busChannel = (uint32)fbusChannel;
440 int lastChannel = busChannel + numChannels;
442 if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
443 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
444 unit->m_busTouched = world->mAudioBusTouched + busChannel;
448 float *in = unit->m_bus;
449 int32 *touched = unit->m_busTouched;
450 int32 bufCounter = unit->mWorld->mBufCounter;
452 for (int i=0; i<numChannels; ++i, in += bufLength) {
453 ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
454 float *out = OUT(i);
455 if (touched[i] == bufCounter)
456 nova::copyvec_simd<64>(out, in);
457 else
458 nova::zerovec_simd<64>(out);
459 RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
463 #endif
465 void In_next_a(IOUnit *unit, int inNumSamples)
467 World *world = unit->mWorld;
468 int bufLength = world->mBufLength;
469 int numChannels = unit->mNumOutputs;
471 float fbusChannel = ZIN0(0);
472 if (fbusChannel != unit->m_fbusChannel) {
473 unit->m_fbusChannel = fbusChannel;
474 uint32 busChannel = (uint32)fbusChannel;
475 uint32 lastChannel = busChannel + numChannels;
477 if (!(lastChannel > world->mNumAudioBusChannels)) {
478 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
479 unit->m_busTouched = world->mAudioBusTouched + busChannel;
483 float *in = unit->m_bus;
484 int32 *touched = unit->m_busTouched;
485 int32 bufCounter = unit->mWorld->mBufCounter;
487 for (int i=0; i<numChannels; ++i, in += bufLength) {
488 ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
489 float *out = OUT(i);
490 if (touched[i] == bufCounter) Copy(inNumSamples, out, in);
491 else Fill(inNumSamples, out, 0.f);
492 RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
496 #ifdef IPHONE_VEC
497 void vIn_next_a(IOUnit *unit, int inNumSamples)
499 World *world = unit->mWorld;
500 int bufLength = world->mBufLength;
501 int numChannels = unit->mNumOutputs;
503 float fbusChannel = ZIN0(0);
504 if (fbusChannel != unit->m_fbusChannel) {
505 unit->m_fbusChannel = fbusChannel;
506 int busChannel = (uint32)fbusChannel;
507 int lastChannel = busChannel + numChannels;
509 if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
510 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
511 unit->m_busTouched = world->mAudioBusTouched + busChannel;
515 float *in = unit->m_bus;
516 int32 *touched = unit->m_busTouched;
517 int32 bufCounter = unit->mWorld->mBufCounter;
519 for (int i=0; i<numChannels; ++i, in += bufLength) {
520 ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
521 float *out = OUT(i);
522 if (touched[i] == bufCounter)
524 vcopy(out, in, inNumSamples);
526 else
528 vfill(out, 0.f, inNumSamples);
530 RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
533 #endif
535 void In_next_k(IOUnit *unit, int inNumSamples)
537 //Print("->In_next_k\n");
538 World *world = unit->mWorld;
539 uint32 numChannels = unit->mNumOutputs;
541 float fbusChannel = ZIN0(0);
542 if (fbusChannel != unit->m_fbusChannel) {
543 unit->m_fbusChannel = fbusChannel;
544 uint32 busChannel = (uint32)fbusChannel;
545 uint32 lastChannel = busChannel + numChannels;
547 if (!(lastChannel > world->mNumControlBusChannels)) {
548 unit->m_bus = world->mControlBus + busChannel;
552 float *in = unit->m_bus;
553 for (uint32 i=0; i<numChannels; ++i, in++) {
554 float *out = OUT(i);
555 *out = *in;
557 //Print("<-In_next_k\n");
560 void In_Ctor(IOUnit* unit)
562 //Print("->In_Ctor\n");
563 World *world = unit->mWorld;
564 unit->m_fbusChannel = -1.;
566 if (unit->mCalcRate == calc_FullRate) {
567 #ifdef NOVA_SIMD
568 if (BUFLENGTH == 64)
569 SETCALC(In_next_a_nova_64);
570 else if (!(BUFLENGTH & 15))
571 SETCALC(In_next_a_nova);
572 else
573 #endif
574 SETCALC(In_next_a);
575 unit->m_bus = world->mAudioBus;
576 unit->m_busTouched = world->mAudioBusTouched;
577 //#ifdef IPHONE_VEC
578 // vIn_next_a(unit, 1);
579 //#else
580 In_next_a(unit, 1);
581 //#endif
582 } else {
583 SETCALC(In_next_k);
584 unit->m_bus = world->mControlBus;
585 //unit->m_busTouched = world->mControlBusTouched;
586 In_next_k(unit, 1);
588 //Print("<-In_Ctor\n");
591 //////////////////////////////////////////////////////////////////////////////////////////////////
592 //////////////////////////////////////////////////////////////////////////////////////////////////
594 void LagIn_next_k(LagIn *unit, int inNumSamples)
596 //Print("->LagIn_next_k\n");
597 World *world = unit->mWorld;
598 int numChannels = unit->mNumOutputs;
600 float fbusChannel = ZIN0(0);
601 if (fbusChannel != unit->m_fbusChannel) {
602 unit->m_fbusChannel = fbusChannel;
603 uint32 busChannel = (uint32)fbusChannel;
604 uint32 lastChannel = busChannel + numChannels;
606 if (!(lastChannel > world->mNumControlBusChannels)) {
607 unit->m_bus = world->mControlBus + busChannel;
611 float *in = unit->m_bus;
612 float b1 = unit->m_b1;
613 float *y1 = unit->m_y1;
614 for (int i=0; i<numChannels; ++i, in++) {
615 float *out = OUT(i);
616 float z = *in;
617 float x = z + b1 * (y1[i] - z);
618 *out = y1[i] = zapgremlins(x);
620 //Print("<-In_next_k\n");
623 void LagIn_next_0(LagIn *unit, int inNumSamples)
625 //Print("->LagIn_next_k\n");
626 World *world = unit->mWorld;
627 int numChannels = unit->mNumOutputs;
629 float fbusChannel = ZIN0(0);
630 if (fbusChannel != unit->m_fbusChannel) {
631 unit->m_fbusChannel = fbusChannel;
632 uint32 busChannel = (uint32)fbusChannel;
633 uint32 lastChannel = busChannel + numChannels;
635 if (!(lastChannel > world->mNumControlBusChannels)) {
636 unit->m_bus = world->mControlBus + busChannel;
640 float *in = unit->m_bus;
641 float *y1 = unit->m_y1;
642 for (int i=0; i<numChannels; ++i, in++) {
643 float *out = OUT(i);
644 *out = y1[i] = *in;
646 //Print("<-In_next_k\n");
649 void LagIn_Ctor(LagIn* unit)
651 //Print("->LagIn_Ctor\n");
652 World *world = unit->mWorld;
653 unit->m_fbusChannel = -1.;
655 float lag = ZIN0(1);
656 unit->m_b1 = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate));
658 SETCALC(LagIn_next_k);
659 unit->m_bus = world->mControlBus;
660 //unit->m_busTouched = world->mControlBusTouched;
661 LagIn_next_0(unit, 1);
662 //Print("<-LagIn_Ctor\n");
665 //////////////////////////////////////////////////////////////////////////////////////////////////
666 //////////////////////////////////////////////////////////////////////////////////////////////////
668 void InFeedback_next_a(IOUnit *unit, int inNumSamples)
670 World *world = unit->mWorld;
671 int bufLength = world->mBufLength;
672 int numChannels = unit->mNumOutputs;
674 float fbusChannel = ZIN0(0);
675 if (fbusChannel != unit->m_fbusChannel) {
676 unit->m_fbusChannel = fbusChannel;
677 uint32 busChannel = (uint32)fbusChannel;
678 uint32 lastChannel = busChannel + numChannels;
680 if (!(lastChannel > world->mNumAudioBusChannels)) {
681 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
682 unit->m_busTouched = world->mAudioBusTouched + busChannel;
686 float *in = unit->m_bus;
687 int32 *touched = unit->m_busTouched;
688 int32 bufCounter = unit->mWorld->mBufCounter;
690 for (int i=0; i<numChannels; ++i, in += bufLength) {
691 ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
692 float *out = OUT(i);
693 int diff = bufCounter - touched[i];
694 if (diff == 1 || diff == 0) Copy(inNumSamples, out, in);
695 else Fill(inNumSamples, out, 0.f);
696 RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
701 void InFeedback_Ctor(IOUnit* unit)
703 //Print("->InFeedback_Ctor\n");
704 World *world = unit->mWorld;
705 unit->m_fbusChannel = -1.;
707 SETCALC(InFeedback_next_a);
708 unit->m_bus = world->mAudioBus;
709 unit->m_busTouched = world->mAudioBusTouched;
710 InFeedback_next_a(unit, 1);
711 //Print("<-InFeedback_Ctor\n");
714 //////////////////////////////////////////////////////////////////////////////////////////////////
716 void InTrig_next_k(IOUnit *unit, int inNumSamples)
718 World *world = unit->mWorld;
719 int numChannels = unit->mNumOutputs;
721 float fbusChannel = ZIN0(0);
722 if (fbusChannel != unit->m_fbusChannel) {
723 unit->m_fbusChannel = fbusChannel;
724 uint32 busChannel = (uint32)fbusChannel;
725 uint32 lastChannel = busChannel + numChannels;
727 if (!(lastChannel > world->mNumControlBusChannels)) {
728 unit->m_bus = world->mControlBus + busChannel;
729 unit->m_busTouched = world->mControlBusTouched + busChannel;
733 float *in = unit->m_bus;
734 int32 *touched = unit->m_busTouched;
735 int32 bufCounter = unit->mWorld->mBufCounter;
736 for (int i=0; i<numChannels; ++i, in++) {
737 float *out = OUT(i);
738 if (touched[i] == bufCounter) *out = *in;
739 else *out = 0.f;
743 void InTrig_Ctor(IOUnit* unit)
745 World *world = unit->mWorld;
746 unit->m_fbusChannel = -1.;
748 if (unit->mCalcRate == calc_FullRate) {
749 SETCALC(ClearUnitOutputs);
750 ClearUnitOutputs(unit, 1);
751 } else {
752 SETCALC(InTrig_next_k);
753 unit->m_bus = world->mControlBus;
754 unit->m_busTouched = world->mControlBusTouched;
755 InTrig_next_k(unit, 1);
759 //////////////////////////////////////////////////////////////////////////////////////////////////
762 void ReplaceOut_next_a(IOUnit *unit, int inNumSamples)
764 World *world = unit->mWorld;
765 int bufLength = world->mBufLength;
766 int numChannels = unit->mNumInputs - 1;
768 float fbusChannel = ZIN0(0);
769 if (fbusChannel != unit->m_fbusChannel) {
770 unit->m_fbusChannel = fbusChannel;
771 uint32 busChannel = (uint32)fbusChannel;
772 uint32 lastChannel = busChannel + numChannels;
774 if (!(lastChannel > world->mNumAudioBusChannels)) {
775 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
776 unit->m_busTouched = world->mAudioBusTouched + busChannel;
780 float *out = unit->m_bus;
781 int32 *touched = unit->m_busTouched;
782 int32 bufCounter = unit->mWorld->mBufCounter;
783 for (int i=0; i<numChannels; ++i, out+=bufLength) {
784 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
785 float *in = IN(i+1);
786 Copy(inNumSamples, out, in);
787 touched[i] = bufCounter;
788 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
792 void ReplaceOut_next_k(IOUnit *unit, int inNumSamples)
794 World *world = unit->mWorld;
795 int numChannels = unit->mNumInputs - 1;
797 float fbusChannel = ZIN0(0);
798 if (fbusChannel != unit->m_fbusChannel) {
799 unit->m_fbusChannel = fbusChannel;
800 uint32 busChannel = (uint32)fbusChannel;
801 uint32 lastChannel = busChannel + numChannels;
803 if (!(lastChannel > world->mNumControlBusChannels)) {
804 unit->m_bus = world->mControlBus + busChannel;
805 unit->m_busTouched = world->mControlBusTouched + busChannel;
809 float *out = unit->m_bus;
810 int32 *touched = unit->m_busTouched;
811 int32 bufCounter = unit->mWorld->mBufCounter;
812 for (int i=0; i<numChannels; ++i, out++) {
813 float *in = IN(i+1);
814 ACQUIRE_BUS_CONTROL((int32)fbusChannel + i);
815 *out = *in;
816 touched[i] = bufCounter;
817 RELEASE_BUS_CONTROL((int32)fbusChannel + i);
821 #ifdef NOVA_SIMD
822 FLATTEN void ReplaceOut_next_a_nova(IOUnit *unit, int inNumSamples)
824 World *world = unit->mWorld;
825 int bufLength = world->mBufLength;
826 int numChannels = unit->mNumInputs - 1;
828 float fbusChannel = ZIN0(0);
829 if (fbusChannel != unit->m_fbusChannel) {
830 unit->m_fbusChannel = fbusChannel;
831 uint32 busChannel = (uint32)fbusChannel;
832 uint32 lastChannel = busChannel + numChannels;
834 if (!(lastChannel > world->mNumAudioBusChannels)) {
835 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
836 unit->m_busTouched = world->mAudioBusTouched + busChannel;
840 float *out = unit->m_bus;
841 int32 *touched = unit->m_busTouched;
842 int32 bufCounter = unit->mWorld->mBufCounter;
843 for (int i=0; i<numChannels; ++i, out+=bufLength) {
844 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
845 float *in = IN(i+1);
846 nova::copyvec_simd(out, in, inNumSamples);
847 touched[i] = bufCounter;
848 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
852 FLATTEN void ReplaceOut_next_a_nova_64(IOUnit *unit, int inNumSamples)
854 World *world = unit->mWorld;
855 int bufLength = world->mBufLength;
856 int numChannels = unit->mNumInputs - 1;
858 float fbusChannel = ZIN0(0);
859 if (fbusChannel != unit->m_fbusChannel) {
860 unit->m_fbusChannel = fbusChannel;
861 uint32 busChannel = (uint32)fbusChannel;
862 uint32 lastChannel = busChannel + numChannels;
864 if (!(lastChannel > world->mNumAudioBusChannels)) {
865 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
866 unit->m_busTouched = world->mAudioBusTouched + busChannel;
870 float *out = unit->m_bus;
871 int32 *touched = unit->m_busTouched;
872 int32 bufCounter = unit->mWorld->mBufCounter;
873 for (int i=0; i<numChannels; ++i, out+=bufLength) {
874 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
875 float *in = IN(i+1);
876 nova::copyvec_simd<64>(out, in);
877 touched[i] = bufCounter;
878 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
882 #endif /* NOVA_SIMD */
884 void ReplaceOut_Ctor(IOUnit* unit)
886 World *world = unit->mWorld;
887 unit->m_fbusChannel = -1.;
889 if (unit->mCalcRate == calc_FullRate) {
890 #ifdef NOVA_SIMD
891 if (BUFLENGTH == 64)
892 SETCALC(ReplaceOut_next_a_nova_64);
893 else if (!(BUFLENGTH & 15))
894 SETCALC(ReplaceOut_next_a_nova);
895 else
896 #endif
897 SETCALC(ReplaceOut_next_a);
898 unit->m_bus = world->mAudioBus;
899 unit->m_busTouched = world->mAudioBusTouched;
900 } else {
901 SETCALC(ReplaceOut_next_k);
902 unit->m_bus = world->mControlBus;
903 unit->m_busTouched = world->mControlBusTouched;
907 //////////////////////////////////////////////////////////////////////////////////////////////////
909 void Out_next_a(IOUnit *unit, int inNumSamples)
911 //Print("Out_next_a %d\n", unit->mNumInputs);
912 World *world = unit->mWorld;
913 int bufLength = world->mBufLength;
914 int numChannels = unit->mNumInputs - 1;
916 float fbusChannel = ZIN0(0);
917 if (fbusChannel != unit->m_fbusChannel) {
918 unit->m_fbusChannel = fbusChannel;
919 uint32 busChannel = (uint32)fbusChannel;
920 uint32 lastChannel = busChannel + numChannels;
922 if (!(lastChannel > world->mNumAudioBusChannels)) {
923 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
924 unit->m_busTouched = world->mAudioBusTouched + busChannel;
928 float *out = unit->m_bus;
929 int32 *touched = unit->m_busTouched;
930 int32 bufCounter = unit->mWorld->mBufCounter;
931 for (int i=0; i<numChannels; ++i, out+=bufLength) {
932 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
933 float *in = IN(i+1);
934 if (touched[i] == bufCounter) Accum(inNumSamples, out, in);
935 else {
936 Copy(inNumSamples, out, in);
937 touched[i] = bufCounter;
939 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
940 //Print("out %d %g %g\n", i, in[0], out[0]);
946 #ifdef IPHONE_VEC
947 void vOut_next_a(IOUnit *unit, int inNumSamples)
949 //Print("Out_next_a %d\n", unit->mNumInputs);
950 World *world = unit->mWorld;
951 int bufLength = world->mBufLength;
952 int numChannels = unit->mNumInputs - 1;
954 float fbusChannel = ZIN0(0);
955 if (fbusChannel != unit->m_fbusChannel) {
956 unit->m_fbusChannel = fbusChannel;
957 int busChannel = (int)fbusChannel;
958 int lastChannel = busChannel + numChannels;
960 if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
961 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
962 unit->m_busTouched = world->mAudioBusTouched + busChannel;
966 float *out = unit->m_bus;
967 int32 *touched = unit->m_busTouched;
968 int32 bufCounter = unit->mWorld->mBufCounter;
969 for (int i=0; i<numChannels; ++i, out+=bufLength) {
970 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
971 float *in = IN(i+1);
972 if (touched[i] == bufCounter)
974 vadd(out, out, in, inNumSamples);
976 else
978 vcopy(out, in, inNumSamples);
979 touched[i] = bufCounter;
981 //Print("out %d %g %g\n", i, in[0], out[0]);
982 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
985 #endif
988 #ifdef NOVA_SIMD
989 FLATTEN void Out_next_a_nova(IOUnit *unit, int inNumSamples)
991 //Print("Out_next_a %d\n", unit->mNumInputs);
992 World *world = unit->mWorld;
993 int bufLength = world->mBufLength;
994 int numChannels = unit->mNumInputs - 1;
996 float fbusChannel = ZIN0(0);
997 if (fbusChannel != unit->m_fbusChannel) {
998 unit->m_fbusChannel = fbusChannel;
999 int busChannel = (int)fbusChannel;
1000 int lastChannel = busChannel + numChannels;
1002 if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
1003 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
1004 unit->m_busTouched = world->mAudioBusTouched + busChannel;
1008 float *out = unit->m_bus;
1009 int32 *touched = unit->m_busTouched;
1010 int32 bufCounter = unit->mWorld->mBufCounter;
1011 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1012 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1013 float *in = IN(i+1);
1014 if (touched[i] == bufCounter)
1015 nova::addvec_simd(out, in, inNumSamples);
1016 else {
1017 nova::copyvec_simd(out, in, inNumSamples);
1018 touched[i] = bufCounter;
1020 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1021 //Print("out %d %g %g\n", i, in[0], out[0]);
1025 FLATTEN void Out_next_a_nova_64(IOUnit *unit, int inNumSamples)
1027 //Print("Out_next_a %d\n", unit->mNumInputs);
1028 World *world = unit->mWorld;
1029 int bufLength = world->mBufLength;
1030 int numChannels = unit->mNumInputs - 1;
1032 float fbusChannel = ZIN0(0);
1033 if (fbusChannel != unit->m_fbusChannel) {
1034 unit->m_fbusChannel = fbusChannel;
1035 int busChannel = (int)fbusChannel;
1036 int lastChannel = busChannel + numChannels;
1038 if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
1039 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
1040 unit->m_busTouched = world->mAudioBusTouched + busChannel;
1044 float *out = unit->m_bus;
1045 int32 *touched = unit->m_busTouched;
1046 int32 bufCounter = unit->mWorld->mBufCounter;
1047 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1048 float *in = IN(i+1);
1049 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1050 if (touched[i] == bufCounter)
1051 nova::addvec_simd<64>(out, in);
1052 else {
1053 nova::copyvec_simd<64>(out, in);
1054 touched[i] = bufCounter;
1056 //Print("out %d %g %g\n", i, in[0], out[0]);
1057 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1060 #endif
1063 void Out_next_k(IOUnit *unit, int inNumSamples)
1065 World *world = unit->mWorld;
1066 int numChannels = unit->mNumInputs - 1;
1068 float fbusChannel = ZIN0(0);
1069 if (fbusChannel != unit->m_fbusChannel) {
1070 unit->m_fbusChannel = fbusChannel;
1071 uint32 busChannel = (uint32)fbusChannel;
1072 uint32 lastChannel = busChannel + numChannels;
1074 if (!(lastChannel > world->mNumControlBusChannels)) {
1075 unit->m_bus = world->mControlBus + busChannel;
1076 unit->m_busTouched = world->mControlBusTouched + busChannel;
1079 float *out = unit->m_bus;
1080 int32 *touched = unit->m_busTouched;
1081 int32 bufCounter = unit->mWorld->mBufCounter;
1082 for (int i=0; i<numChannels; ++i, out++) {
1083 float *in = IN(i+1);
1084 ACQUIRE_BUS_CONTROL((int32)fbusChannel + i);
1085 if (touched[i] == bufCounter)
1086 *out += *in;
1087 else {
1088 *out = *in;
1089 touched[i] = bufCounter;
1091 RELEASE_BUS_CONTROL((int32)fbusChannel + i);
1095 void Out_Ctor(IOUnit* unit)
1097 //Print("->Out_Ctor\n");
1098 World *world = unit->mWorld;
1099 unit->m_fbusChannel = -1.;
1101 if (unit->mCalcRate == calc_FullRate) {
1103 #if defined(NOVA_SIMD)
1104 if (BUFLENGTH == 64)
1105 SETCALC(Out_next_a_nova_64);
1106 else if (!(BUFLENGTH & 15))
1107 SETCALC(Out_next_a_nova);
1108 else
1109 SETCALC(Out_next_a);
1110 #else
1112 #ifdef IPHONE_VEC
1113 SETCALC(vOut_next_a);
1114 #else
1115 SETCALC(Out_next_a);
1116 #endif
1117 #endif
1118 unit->m_bus = world->mAudioBus;
1119 unit->m_busTouched = world->mAudioBusTouched;
1120 } else {
1121 SETCALC(Out_next_k);
1122 unit->m_bus = world->mControlBus;
1123 unit->m_busTouched = world->mControlBusTouched;
1125 //Print("<-Out_Ctor\n");
1128 //////////////////////////////////////////////////////////////////////////////////////////////////
1129 //////////////////////////////////////////////////////////////////////////////////////////////////
1131 void XOut_next_a(XOut *unit, int inNumSamples)
1133 World *world = unit->mWorld;
1134 int bufLength = world->mBufLength;
1135 int numChannels = unit->mNumInputs - 2;
1137 float fbusChannel = ZIN0(0);
1138 if (fbusChannel != unit->m_fbusChannel) {
1139 unit->m_fbusChannel = fbusChannel;
1140 uint32 busChannel = (uint32)fbusChannel;
1141 uint32 lastChannel = busChannel + numChannels;
1143 if (!(lastChannel > world->mNumAudioBusChannels)) {
1144 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
1145 unit->m_busTouched = world->mAudioBusTouched + busChannel;
1149 float next_xfade = ZIN0(1);
1150 float xfade0 = unit->m_xfade;
1151 float *out = unit->m_bus;
1152 int32 *touched = unit->m_busTouched;
1153 int32 bufCounter = unit->mWorld->mBufCounter;
1154 if (xfade0 != next_xfade) {
1155 float slope = CALCSLOPE(next_xfade, xfade0);
1156 for (int i=0; i<numChannels; ++i) {
1157 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1158 float xfade = xfade0;
1159 float *in = IN(i+2);
1160 if (touched[i] == bufCounter) {
1161 LOOP1(inNumSamples,
1162 float zin = *in;
1163 float zout = *out;
1164 *out = zout + xfade * (zin - zout);
1165 //if (xxi==0) Print("x %d %d %g %g %g %g\n", bufCounter, i, zin, zout, xfade, *out);
1166 xfade += slope;
1167 ++out; ++in;
1169 } else {
1170 LOOP1(inNumSamples,
1171 float zin = *in;
1172 *out = xfade * zin;
1173 xfade += slope;
1174 ++out; ++in;
1176 touched[i] = bufCounter;
1178 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1180 } else if (xfade0 == 1.f) {
1181 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1182 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1183 float *in = IN(i+2);
1184 Copy(inNumSamples, out, in);
1185 touched[i] = bufCounter;
1186 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1188 } else if (xfade0 == 0.f) {
1189 // do nothing.
1190 } else {
1191 for (int i=0; i<numChannels; ++i) {
1192 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1193 float *in = IN(i+2);
1194 if (touched[i] == bufCounter) {
1195 LOOP1(inNumSamples,
1196 float zin = *in;
1197 float zout = *out;
1198 *out = zout + xfade0 * (zin - zout);
1199 ++out; ++in;
1201 } else {
1202 LOOP1(inNumSamples,
1203 float zin = *in;
1204 *out = xfade0 * zin;
1205 ++out; ++in;
1207 touched[i] = bufCounter;
1209 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1212 unit->m_xfade = next_xfade;
1215 #ifdef NOVA_SIMD
1216 FLATTEN void XOut_next_a_nova(XOut *unit, int inNumSamples)
1218 World *world = unit->mWorld;
1219 int bufLength = world->mBufLength;
1220 int numChannels = unit->mNumInputs - 2;
1222 float fbusChannel = ZIN0(0);
1223 if (fbusChannel != unit->m_fbusChannel) {
1224 unit->m_fbusChannel = fbusChannel;
1225 uint32 busChannel = (uint32)fbusChannel;
1226 uint32 lastChannel = busChannel + numChannels;
1228 if (!(lastChannel > world->mNumAudioBusChannels)) {
1229 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
1230 unit->m_busTouched = world->mAudioBusTouched + busChannel;
1234 float next_xfade = ZIN0(1);
1235 float xfade0 = unit->m_xfade;
1236 float *out = unit->m_bus;
1237 int32 *touched = unit->m_busTouched;
1238 int32 bufCounter = unit->mWorld->mBufCounter;
1239 if (xfade0 != next_xfade) {
1240 float slope = CALCSLOPE(next_xfade, xfade0);
1241 for (int i=0; i<numChannels; ++i) {
1242 float xfade = xfade0;
1243 float *in = IN(i+2);
1244 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1245 if (touched[i] == bufCounter)
1246 nova::mix_vec_simd(out, out, slope_argument(1-xfade0, -slope), in, slope_argument(xfade0, slope), inNumSamples);
1247 else {
1248 nova::times_vec_simd(out, in, slope_argument(xfade, slope), inNumSamples);
1249 touched[i] = bufCounter;
1251 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1253 unit->m_xfade = next_xfade;
1254 } else if (xfade0 == 1.f) {
1255 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1256 float *in = IN(i+2);
1257 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1258 nova::copyvec_simd(out, in, inNumSamples);
1259 touched[i] = bufCounter;
1260 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1262 } else if (xfade0 == 0.f) {
1263 // do nothing.
1264 } else {
1265 for (int i=0; i<numChannels; ++i) {
1266 float *in = IN(i+2);
1267 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1268 if (touched[i] == bufCounter)
1269 nova::mix_vec_simd(out, out, 1-xfade0, in, xfade0, inNumSamples);
1270 else {
1271 nova::times_vec_simd(out, in, xfade0, inNumSamples);
1272 touched[i] = bufCounter;
1274 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1279 #endif
1283 void XOut_next_k(XOut *unit, int inNumSamples)
1285 World *world = unit->mWorld;
1286 int numChannels = unit->mNumInputs - 2;
1288 float fbusChannel = ZIN0(0);
1289 if (fbusChannel != unit->m_fbusChannel) {
1290 unit->m_fbusChannel = fbusChannel;
1291 uint32 busChannel = (uint32)fbusChannel;
1292 uint32 lastChannel = busChannel + numChannels;
1294 if (!(lastChannel > world->mNumControlBusChannels)) {
1295 unit->m_bus = world->mControlBus + busChannel;
1296 unit->m_busTouched = world->mControlBusTouched + busChannel;
1300 float xfade = ZIN0(1);
1301 float *out = unit->m_bus;
1302 int32 *touched = unit->m_busTouched;
1303 int32 bufCounter = unit->mWorld->mBufCounter;
1304 for (int i=0; i<numChannels; ++i, out++) {
1305 float *in = IN(i+2);
1306 ACQUIRE_BUS_CONTROL((int32)fbusChannel + i);
1307 if (touched[i] == bufCounter) {
1308 float zin = *in;
1309 float zout = *out;
1310 *out = zout + xfade * (zin - zout);
1311 } else {
1312 *out = xfade * *in;
1313 touched[i] = bufCounter;
1315 RELEASE_BUS_CONTROL((int32)fbusChannel + i);
1319 void XOut_Ctor(XOut* unit)
1321 //Print("->Out_Ctor\n");
1322 World *world = unit->mWorld;
1323 unit->m_fbusChannel = -1.;
1324 unit->m_xfade = ZIN0(1);
1325 if (unit->mCalcRate == calc_FullRate) {
1326 #ifdef NOVA_SIMD
1327 if (!(BUFLENGTH & 15))
1328 SETCALC(XOut_next_a_nova);
1329 #endif
1330 SETCALC(XOut_next_a);
1331 unit->m_bus = world->mAudioBus;
1332 unit->m_busTouched = world->mAudioBusTouched;
1333 } else {
1334 SETCALC(XOut_next_k);
1335 unit->m_bus = world->mControlBus;
1336 unit->m_busTouched = world->mControlBusTouched;
1338 //Print("<-Out_Ctor\n");
1341 //////////////////////////////////////////////////////////////////////////////////////////////////
1343 void OffsetOut_next_a(OffsetOut *unit, int inNumSamples)
1345 World *world = unit->mWorld;
1346 int bufLength = world->mBufLength;
1347 int numChannels = unit->mNumInputs - 1;
1349 float fbusChannel = ZIN0(0);
1350 if (fbusChannel != unit->m_fbusChannel) {
1351 unit->m_fbusChannel = fbusChannel;
1352 uint32 busChannel = (uint32)fbusChannel;
1353 uint32 lastChannel = busChannel + numChannels;
1355 if (!(lastChannel > world->mNumAudioBusChannels)) {
1356 unit->m_bus = world->mAudioBus + (busChannel * bufLength);
1357 unit->m_busTouched = world->mAudioBusTouched + busChannel;
1361 int32 offset = unit->mParent->mSampleOffset;
1362 int32 remain = BUFLENGTH - offset;
1364 float *out = unit->m_bus;
1365 float *saved = unit->m_saved;
1366 int32 *touched = unit->m_busTouched;
1367 int32 bufCounter = unit->mWorld->mBufCounter;
1368 for (int i=0; i<numChannels; ++i, out+=bufLength, saved += offset) {
1369 ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
1370 float *in = IN(i+1);
1371 //Print("out %d %d %d %d %d\n",
1372 // i, touched[i] == bufCounter, unit->m_empty,
1373 // offset, remain);
1375 if (touched[i] == bufCounter) {
1376 if (unit->m_empty) {
1377 //Print("touched offset %d\n", offset);
1378 } else {
1379 Accum(offset, out, saved);
1381 Accum(remain, out + offset, in);
1382 } else {
1383 if (unit->m_empty) {
1384 Clear(offset, out);
1385 //Print("untouched offset %d\n", offset);
1386 } else {
1387 Copy(offset, out, saved);
1389 Copy(remain, out + offset, in);
1390 touched[i] = bufCounter;
1392 Copy(offset, saved, in + remain);
1393 RELEASE_BUS_AUDIO((int32)fbusChannel + i);
1394 //Print("out %d %d %d %g %g\n", i, in[0], out[0]);
1396 unit->m_empty = false;
1399 void OffsetOut_Ctor(OffsetOut* unit)
1401 //Print("->Out_Ctor\n");
1402 World *world = unit->mWorld;
1403 unit->m_fbusChannel = -1.;
1405 SETCALC(OffsetOut_next_a);
1406 unit->m_bus = world->mAudioBus;
1407 unit->m_busTouched = world->mAudioBusTouched;
1408 int32 offset = unit->mParent->mSampleOffset;
1409 int numChannels = unit->mNumInputs - 1;
1411 unit->m_saved = (float*)RTAlloc(unit->mWorld, offset * numChannels * sizeof(float));
1412 unit->m_empty = true;
1413 //Print("<-Out_Ctor\n");
1416 void OffsetOut_Dtor(OffsetOut* unit)
1418 // Ctor may not have run, if unit was immediately created->paused->freed!
1419 if(unit->m_saved){
1420 World *world = unit->mWorld;
1421 int bufLength = world->mBufLength;
1422 int numChannels = unit->mNumInputs - 1;
1424 int32 offset = unit->mParent->mSampleOffset;
1425 int32 remain = BUFLENGTH - offset;
1427 float *out = unit->m_bus;
1428 float *saved = unit->m_saved;
1429 int32 *touched = unit->m_busTouched;
1430 int32 bufCounter = unit->mWorld->mBufCounter;
1431 for (int i=0; i<numChannels; ++i, out+=bufLength, saved += offset) {
1432 //Print("out %d %d %d %d %d\n",
1433 // i, touched[i] == bufCounter, unit->m_empty,
1434 // offset, remain);
1436 if (!unit->m_empty) {
1437 if (touched[i] == bufCounter) {
1438 Accum(offset, out, saved);
1439 } else {
1440 Copy(offset, out, saved);
1441 Clear(remain, out + offset);
1442 touched[i] = bufCounter;
1445 //Print("out %d %d %d %g %g\n", i, in[0], out[0]);
1448 RTFree(unit->mWorld, unit->m_saved);
1452 //////////////////////////////////////////////////////////////////////////////////////////////////
1454 void SharedIn_next_k(IOUnit *unit, int inNumSamples)
1456 //Print("->SharedIn_next_k\n");
1457 World *world = unit->mWorld;
1458 int numChannels = unit->mNumOutputs;
1460 float fbusChannel = ZIN0(0);
1461 if (fbusChannel != unit->m_fbusChannel) {
1462 unit->m_fbusChannel = fbusChannel;
1463 uint32 busChannel = (uint32)fbusChannel;
1464 uint32 lastChannel = busChannel + numChannels;
1466 if (!(lastChannel > world->mNumSharedControls)) {
1467 unit->m_bus = world->mSharedControls + busChannel;
1471 float *in = unit->m_bus;
1472 if (in) {
1473 for (int i=0; i<numChannels; ++i, in++) {
1474 float *out = OUT(i);
1475 *out = *in;
1477 } else {
1478 ClearUnitOutputs(unit, 1);
1480 //Print("<-SharedIn_next_k\n");
1483 void SharedIn_Ctor(IOUnit* unit)
1485 //Print("->SharedIn_Ctor\n");
1486 World *world = unit->mWorld;
1487 unit->m_fbusChannel = -1.;
1489 SETCALC(SharedIn_next_k);
1490 unit->m_bus = world->mSharedControls;
1491 SharedIn_next_k(unit, 1);
1493 //Print("<-SharedIn_Ctor\n");
1496 //////////////////////////////////////////////////////////////////////////////////////////////////
1497 //////////////////////////////////////////////////////////////////////////////////////////////////
1499 void SharedOut_next_k(IOUnit *unit, int inNumSamples)
1501 //Print("->SharedOut_next_k\n");
1502 World *world = unit->mWorld;
1503 int numChannels = unit->mNumInputs - 1;
1505 float fbusChannel = ZIN0(0);
1506 if (fbusChannel != unit->m_fbusChannel) {
1507 unit->m_fbusChannel = fbusChannel;
1508 uint32 busChannel = (uint32)fbusChannel;
1509 uint32 lastChannel = busChannel + numChannels;
1511 if (!(lastChannel > world->mNumSharedControls)) {
1512 unit->m_bus = world->mSharedControls + busChannel;
1516 float *out = unit->m_bus;
1517 if (out) {
1518 for (int i=1; i<numChannels+1; ++i, out++) {
1519 float *in = IN(i);
1520 *out = *in;
1523 //Print("<-SharedOut_next_k\n");
1526 void SharedOut_Ctor(IOUnit* unit)
1528 //Print("->SharedOut_Ctor\n");
1529 World *world = unit->mWorld;
1530 unit->m_fbusChannel = -1.;
1532 SETCALC(SharedOut_next_k);
1533 unit->m_bus = world->mSharedControls;
1534 SharedOut_next_k(unit, 1);
1536 //Print("<-SharedOut_Ctor\n");
1539 //////////////////////////////////////////////////////////////////////////////////////////////////
1541 void LocalIn_next_a(LocalIn *unit, int inNumSamples)
1543 World *world = unit->mWorld;
1544 int bufLength = world->mBufLength;
1545 int numChannels = unit->mNumOutputs;
1547 float *in = unit->m_bus;
1548 int32 *touched = unit->m_busTouched;
1549 int32 bufCounter = unit->mWorld->mBufCounter;
1551 for (int i=0; i<numChannels; ++i, in += bufLength) {
1552 float *out = OUT(i);
1553 int diff = bufCounter - touched[i];
1554 //Print("LocalIn %d %d %g\n", i, diff, in[0]);
1555 if (diff == 1 || diff == 0) Copy(inNumSamples, out, in);
1556 else Fill(inNumSamples, out, IN0(i));
1560 #ifdef NOVA_SIMD
1561 FLATTEN void LocalIn_next_a_nova(LocalIn *unit, int inNumSamples)
1563 World *world = unit->mWorld;
1564 int bufLength = world->mBufLength;
1565 int numChannels = unit->mNumOutputs;
1567 float *in = unit->m_bus;
1568 int32 *touched = unit->m_busTouched;
1569 int32 bufCounter = unit->mWorld->mBufCounter;
1571 for (int i=0; i<numChannels; ++i, in += bufLength) {
1572 float *out = OUT(i);
1573 int diff = bufCounter - touched[i];
1574 //Print("LocalIn %d %d %g\n", i, diff, in[0]);
1575 if (diff == 1 || diff == 0)
1576 nova::copyvec_simd(out, in, inNumSamples);
1577 else
1578 //nova::zerovec_simd(out, inNumSamples);
1579 Fill(inNumSamples, out, IN0(i));
1583 FLATTEN void LocalIn_next_a_nova_64(LocalIn *unit, int inNumSamples)
1585 World *world = unit->mWorld;
1586 int bufLength = world->mBufLength;
1587 int numChannels = unit->mNumOutputs;
1589 float *in = unit->m_bus;
1590 int32 *touched = unit->m_busTouched;
1591 int32 bufCounter = unit->mWorld->mBufCounter;
1592 for (int i=0; i<numChannels; ++i, in += bufLength) {
1593 float *out = OUT(i);
1594 int diff = bufCounter - touched[i];
1595 //Print("LocalIn %d %d %g\n", i, diff, in[0]);
1596 if (diff == 1 || diff == 0)
1597 nova::copyvec_simd<64>(out, in);
1598 else
1599 //nova::zerovec_simd<64>(out);
1600 Fill(inNumSamples, out, IN0(i));
1603 #endif
1606 void LocalIn_next_k(LocalIn *unit, int inNumSamples)
1608 uint32 numChannels = unit->mNumOutputs;
1610 float *in = unit->m_bus;
1611 int32 *touched = unit->m_busTouched;
1612 int32 bufCounter = unit->mWorld->mBufCounter;
1613 for (uint32 i=0; i<numChannels; ++i, in++) {
1614 int diff = bufCounter - touched[i];
1615 float *out = OUT(i);
1616 if (diff == 1 || diff == 0)
1617 *out = *in;
1618 else
1619 *out = IN0(i);
1623 void LocalIn_Ctor(LocalIn* unit)
1625 //Print("->LocalIn_Ctor\n");
1626 int numChannels = unit->mNumOutputs;
1628 World *world = unit->mWorld;
1630 int busDataSize = numChannels * BUFLENGTH;
1632 // align the buffer to 256 bytes so that we can use avx instructions
1633 unit->m_realData = (float*)RTAlloc(world, busDataSize * sizeof(float) + numChannels * sizeof(int32) + 32 * sizeof(float));
1634 size_t alignment = (size_t)unit->m_realData & 31;
1636 unit->m_bus = alignment ? (float*)(size_t(unit->m_realData + 32) & ~31)
1637 : unit->m_realData;
1639 unit->m_busTouched = (int32*)(unit->m_bus + busDataSize);
1640 for (int i=0; i<numChannels; ++i)
1641 unit->m_busTouched[i] = -1;
1643 if (unit->mCalcRate == calc_FullRate) {
1644 if (unit->mParent->mLocalAudioBusUnit)
1646 SETCALC(ClearUnitOutputs);
1647 ClearUnitOutputs(unit, 1);
1648 return;
1650 unit->mParent->mLocalAudioBusUnit = unit;
1651 #ifdef NOVA_SIMD
1652 if (BUFLENGTH == 64)
1653 SETCALC(LocalIn_next_a_nova_64);
1654 else if (!(BUFLENGTH & 15))
1655 SETCALC(LocalIn_next_a_nova);
1656 else
1657 #endif
1658 SETCALC(LocalIn_next_a);
1659 LocalIn_next_a(unit, 1);
1660 } else {
1661 if (unit->mParent->mLocalControlBusUnit)
1663 SETCALC(ClearUnitOutputs);
1664 ClearUnitOutputs(unit, 1);
1665 return;
1667 unit->mParent->mLocalControlBusUnit = unit;
1668 SETCALC(LocalIn_next_k);
1669 LocalIn_next_k(unit, 1);
1671 //Print("<-LocalIn_Ctor\n");
1674 void LocalIn_Dtor(LocalIn* unit)
1676 World *world = unit->mWorld;
1677 RTFree(world, unit->m_realData);
1680 //////////////////////////////////////////////////////////////////////////////////////////////////
1681 //////////////////////////////////////////////////////////////////////////////////////////////////
1683 void LocalOut_next_a(IOUnit *unit, int inNumSamples)
1685 //Print("LocalOut_next_a %d\n", unit->mNumInputs);
1686 World *world = unit->mWorld;
1687 int bufLength = world->mBufLength;
1688 int numChannels = unit->mNumInputs;
1690 LocalIn *localIn = (LocalIn*)unit->mParent->mLocalAudioBusUnit;
1691 if (!localIn || numChannels != localIn->mNumOutputs)
1693 ClearUnitOutputs(unit, inNumSamples);
1696 float *out = localIn->m_bus;
1697 int32 *touched = localIn->m_busTouched;
1699 int32 bufCounter = unit->mWorld->mBufCounter;
1700 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1701 float *in = IN(i);
1702 if (touched[i] == bufCounter) Accum(inNumSamples, out, in);
1703 else {
1704 Copy(inNumSamples, out, in);
1705 touched[i] = bufCounter;
1707 //Print("LocalOut %d %g %g\n", i, in[0], out[0]);
1711 #ifdef NOVA_SIMD
1712 FLATTEN void LocalOut_next_a_nova(IOUnit *unit, int inNumSamples)
1714 //Print("LocalOut_next_a %d\n", unit->mNumInputs);
1715 World *world = unit->mWorld;
1716 int bufLength = world->mBufLength;
1717 int numChannels = unit->mNumInputs;
1719 LocalIn *localIn = (LocalIn*)unit->mParent->mLocalAudioBusUnit;
1720 if (!localIn || numChannels != localIn->mNumOutputs)
1722 ClearUnitOutputs(unit, inNumSamples);
1725 float *out = localIn->m_bus;
1726 int32 *touched = localIn->m_busTouched;
1728 int32 bufCounter = unit->mWorld->mBufCounter;
1729 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1730 float *in = IN(i);
1731 if (touched[i] == bufCounter)
1732 nova::addvec_simd(out, in, inNumSamples);
1733 else {
1734 nova::copyvec_simd(out, in, inNumSamples);
1735 touched[i] = bufCounter;
1737 //Print("LocalOut %d %g %g\n", i, in[0], out[0]);
1741 void LocalOut_next_a_nova_64(IOUnit *unit, int inNumSamples)
1743 //Print("LocalOut_next_a %d\n", unit->mNumInputs);
1744 World *world = unit->mWorld;
1745 int bufLength = world->mBufLength;
1746 int numChannels = unit->mNumInputs;
1748 LocalIn *localIn = (LocalIn*)unit->mParent->mLocalAudioBusUnit;
1749 if (!localIn || numChannels != localIn->mNumOutputs)
1751 ClearUnitOutputs(unit, inNumSamples);
1754 float *out = localIn->m_bus;
1755 int32 *touched = localIn->m_busTouched;
1757 int32 bufCounter = unit->mWorld->mBufCounter;
1758 for (int i=0; i<numChannels; ++i, out+=bufLength) {
1759 float *in = IN(i);
1760 if (touched[i] == bufCounter)
1761 nova::addvec_simd<64>(out, in);
1762 else {
1763 nova::copyvec_simd<64>(out, in);
1764 touched[i] = bufCounter;
1766 //Print("LocalOut %d %g %g\n", i, in[0], out[0]);
1769 #endif
1772 void LocalOut_next_k(IOUnit *unit, int inNumSamples)
1774 int numChannels = unit->mNumInputs;
1776 LocalIn *localIn = (LocalIn*)unit->mParent->mLocalControlBusUnit;
1777 if (!localIn || numChannels != localIn->mNumOutputs)
1779 ClearUnitOutputs(unit, inNumSamples);
1782 float *out = localIn->m_bus;
1783 int32 *touched = localIn->m_busTouched;
1785 int32 bufCounter = unit->mWorld->mBufCounter;
1786 for (int i=0; i<numChannels; ++i, out++) {
1787 float *in = IN(i);
1788 if (touched[i] == bufCounter) *out += *in;
1789 else {
1790 *out = *in;
1791 touched[i] = bufCounter;
1796 void LocalOut_Ctor(IOUnit* unit)
1798 //Print("->LocalOut_Ctor\n");
1799 World *world = unit->mWorld;
1800 unit->m_fbusChannel = -1.;
1802 if (unit->mCalcRate == calc_FullRate) {
1804 #ifdef NOVA_SIMD
1805 if (BUFLENGTH == 64)
1806 SETCALC(LocalOut_next_a_nova_64);
1807 else if (!(BUFLENGTH & 15))
1808 SETCALC(LocalOut_next_a_nova);
1809 else
1810 #endif
1811 SETCALC(LocalOut_next_a);
1812 unit->m_bus = world->mAudioBus;
1813 unit->m_busTouched = world->mAudioBusTouched;
1814 } else {
1815 SETCALC(LocalOut_next_k);
1816 unit->m_bus = world->mControlBus;
1817 unit->m_busTouched = world->mControlBusTouched;
1819 //Print("<-LocalOut_Ctor\n");
1822 //////////////////////////////////////////////////////////////////////////////////////////////////
1823 //////////////////////////////////////////////////////////////////////////////////////////////////
1825 PluginLoad(IO)
1827 ft = inTable;
1829 DefineDtorUnit(OffsetOut);
1830 DefineDtorUnit(LocalIn);
1831 DefineSimpleUnit(XOut);
1832 DefineDtorUnit(LagControl);
1833 DefineDtorUnit(AudioControl);
1834 DefineUnit("Control", sizeof(Unit), (UnitCtorFunc)&Control_Ctor, 0, 0);
1835 DefineUnit("TrigControl", sizeof(Unit), (UnitCtorFunc)&TrigControl_Ctor, 0, 0);
1836 DefineUnit("ReplaceOut", sizeof(IOUnit), (UnitCtorFunc)&ReplaceOut_Ctor, 0, 0);
1837 DefineUnit("Out", sizeof(IOUnit), (UnitCtorFunc)&Out_Ctor, 0, 0);
1838 DefineUnit("LocalOut", sizeof(IOUnit), (UnitCtorFunc)&LocalOut_Ctor, 0, 0);
1839 DefineUnit("In", sizeof(IOUnit), (UnitCtorFunc)&In_Ctor, 0, 0);
1840 DefineUnit("LagIn", sizeof(IOUnit), (UnitCtorFunc)&LagIn_Ctor, 0, 0);
1841 DefineUnit("InFeedback", sizeof(IOUnit), (UnitCtorFunc)&InFeedback_Ctor, 0, 0);
1842 DefineUnit("InTrig", sizeof(IOUnit), (UnitCtorFunc)&InTrig_Ctor, 0, 0);
1844 DefineUnit("SharedOut", sizeof(IOUnit), (UnitCtorFunc)&SharedOut_Ctor, 0, 0);
1845 DefineUnit("SharedIn", sizeof(IOUnit), (UnitCtorFunc)&SharedIn_Ctor, 0, 0);