scide: avoid recursive calls to Main::instance
[supercollider.git] / server / scsynth / SC_Graph.cpp
blob6812a2f08bccc7e328ebfb39c31ac8ba50f28d3e
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_Graph.h"
23 #include "SC_GraphDef.h"
24 #include "SC_Unit.h"
25 #include "SC_UnitSpec.h"
26 #include "SC_UnitDef.h"
27 #include "SC_HiddenWorld.h"
28 #include "SC_WorldOptions.h"
29 #include "SC_Wire.h"
30 #include "SC_WireSpec.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include "SC_Prototypes.h"
34 #include "SC_Errors.h"
35 #include "Unroll.h"
37 void Unit_ChooseMulAddFunc(Unit* unit);
39 ////////////////////////////////////////////////////////////////////////////////
41 void Graph_FirstCalc(Graph *inGraph);
43 void Graph_Dtor(Graph *inGraph)
45 //scprintf("->Graph_Dtor %d\n", inGraph->mNode.mID);
46 World *world = inGraph->mNode.mWorld;
47 uint32 numUnits = inGraph->mNumUnits;
48 Unit** graphUnits = inGraph->mUnits;
49 if (inGraph->mNode.mCalcFunc != (NodeCalcFunc)Graph_FirstCalc) {
50 // the above test insures that dtors are not called if ctors have not been called.
51 for (uint32 i = 0; i<numUnits; ++i) {
52 Unit *unit = graphUnits[i];
53 UnitDtorFunc dtor = unit->mUnitDef->mUnitDtorFunc;
54 if (dtor) (dtor)(unit);
57 world->mNumUnits -= numUnits;
58 world->mNumGraphs --;
60 GraphDef* def = GRAPHDEF(inGraph);
61 if (--def->mRefCount <= 0) {
62 if (world->mRealTime) GraphDef_DeleteMsg(world, def);
63 else GraphDef_Free(def);
66 Node_Dtor(&inGraph->mNode);
67 //scprintf("<-Graph_Dtor\n");
70 ////////////////////////////////////////////////////////////////////////////////
72 int Graph_New(struct World *inWorld, struct GraphDef *inGraphDef, int32 inID,
73 struct sc_msg_iter* args, Graph** outGraph,bool argtype)//true for normal args , false for setn type args
75 Graph* graph;
76 int err = Node_New(inWorld, &inGraphDef->mNodeDef, inID, (Node**)&graph);
77 if (err) return err;
78 Graph_Ctor(inWorld, inGraphDef, graph, args,argtype);
79 *outGraph = graph;
80 return err;
84 void Graph_Ctor(World *inWorld, GraphDef *inGraphDef, Graph *graph, sc_msg_iter *msg,bool argtype)//true for normal args , false for setn type args
86 //scprintf("->Graph_Ctor\n");
88 // hit the memory allocator only once.
89 char *memory = (char*)graph + sizeof(Graph);
91 // allocate space for children
92 uint32 numUnits = inGraphDef->mNumUnitSpecs;
93 graph->mNumUnits = numUnits;
94 inWorld->mNumUnits += numUnits;
95 inWorld->mNumGraphs ++;
97 graph->mUnits = (Unit**)memory;
98 memory += inGraphDef->mUnitsAllocSize;
100 // set calc func
101 graph->mNode.mCalcFunc = (NodeCalcFunc)&Graph_FirstCalc;
103 // allocate wires
104 graph->mNumWires = inGraphDef->mNumWires;
105 graph->mWire = (Wire*)memory;
106 memory += inGraphDef->mWiresAllocSize;
108 graph->mNumCalcUnits = inGraphDef->mNumCalcUnits;
109 graph->mCalcUnits = (Unit**)memory;
110 memory += inGraphDef->mCalcUnitsAllocSize;
112 // initialize controls
113 uint32 numControls = inGraphDef->mNumControls;
114 graph->mNumControls = numControls;
115 graph->mControls = (float*)memory;
116 memory += inGraphDef->mControlAllocSize;
118 graph->mMapControls = (float**)memory;
119 memory += inGraphDef->mMapControlsAllocSize;
121 graph->mControlRates = (int*)memory;
122 memory += inGraphDef->mMapControlRatesAllocSize;
125 float* graphControls = graph->mControls;
126 float* initialControlValues = inGraphDef->mInitialControlValues;
127 float** graphMapControls = graph->mMapControls;
128 /* add */
129 int* graphControlRates = graph->mControlRates;
130 for (uint32 i=0; i<numControls; ++i, ++graphControls) {
131 *graphControls = initialControlValues[i];
132 graphMapControls[i] = graphControls;
133 /* add */
134 graphControlRates[i] = 0; // init to 0 for now... control bus is 1, audio is 2
138 // set controls
139 //if argtype == true -> normal args as always
140 //if argtype == false -> setn type args
141 if(argtype) {
142 while( msg->remain()>=8) {
143 int i = 0;
144 int loop = 0;
145 if (msg->nextTag('i') == 's') {
146 int32* name = msg->gets4();
147 int32 hash = Hash(name);
148 do {
149 switch (msg->nextTag('f') ) {
150 case 'f' :
151 case 'i' :
153 float32 value = msg->getf();
154 Graph_SetControl(graph, hash, name, i, value);
155 break;
157 case 's' :
159 const char* string = msg->gets();
160 if ( *string == 'c') {
161 int bus = sc_atoi(string+1);
162 Graph_MapControl(graph, hash, name, i, bus);
163 } else {
164 if (*string == 'a') {
165 int bus = sc_atoi(string+1);
166 Graph_MapAudioControl(graph, hash, name, i, bus);
169 break;
171 case ']':
172 msg->count++;
173 loop -= 1;
174 break;
175 case '[':
176 msg->count++;
177 loop += 1;
178 i -= 1;
179 break;
181 ++i;
183 while (loop);
184 } else {
185 int32 index = msg->geti();
186 do {
187 switch (msg->nextTag('f') ) {
188 case 'f' :
189 case 'i' :
191 float32 value = msg->getf();
192 Graph_SetControl(graph, index + i, value);
193 break;
195 case 's' :
197 const char* string = msg->gets();
198 if ( *string == 'c') {
199 int bus = sc_atoi(string+1);
200 Graph_MapControl(graph, index + i, bus);
201 } else {
202 if (*string == 'a') {
203 int bus = sc_atoi(string+1);
204 Graph_MapAudioControl(graph, index + i, bus);
207 break;
209 case ']':
210 msg->count++;
211 loop -= 1;
212 break;
213 case '[':
214 msg->count++;
215 loop += 1;
216 i -= 1;
217 break;
219 ++i;
221 while (loop);
229 // while( msg->remain()>=8) {
230 // int i = 0;
231 // int loop = 0;
232 // if (msg->nextTag('i') == 's') {
233 // int32* name = msg->gets4();
234 // int32 hash = Hash(name);
235 // if (msg->nextTag('f') == '[' ) {
236 // msg->count++;
237 // loop = 1;
238 // }
239 // do {
240 // if (msg->nextTag('f') == 's' ) {
241 // const char* string = msg->gets();
242 // if ( *string == 'c') {
243 // int bus = sc_atoi(string+1);
244 // Graph_MapControl(graph, hash, name, i, bus);
245 // }
246 // } else {
247 // if (msg->nextTag('f') == ']' ) {
248 // msg->count++;
249 // loop = 0;
250 // } else {
251 // float32 value = msg->getf();
252 // Graph_SetControl(graph, hash, name, i, value);
253 // }
254 // }
255 // ++i;
256 // }
257 // while (loop);
258 // } else {
259 // int32 index = msg->geti();
260 // if (msg->nextTag('f') == '[' ) {
261 // msg->count++;
262 // loop = 1;
263 // }
264 // do {
265 // if (msg->nextTag('f') == 's') {
266 // const char* string = msg->gets();
267 // if (*string == 'c') {
268 // int bus = sc_atoi(string+1);
269 // Graph_MapControl(graph, index + i, bus);
270 // }
271 // } else {
272 // if (msg->nextTag('f') == ']' ) {
273 // msg->count++;
274 // loop = 0;
275 // } else {
276 // float32 value = msg->getf();
277 // Graph_SetControl(graph, index + i, value);
278 // }
279 // }
280 // ++i;
281 // }
282 // while (loop);
283 // }
284 // }
286 // }
287 else{
289 while (msg->remain()) {
290 if (msg->nextTag('i') == 's') {
291 int32* name = msg->gets4();
292 int32 hash = Hash(name);
293 int32 n = msg->geti();
294 for (int i=0; msg->remain() && i<n; ++i) {
295 if (msg->nextTag('f') == 's') {
296 const char* string = msg->gets();
297 if (*string == 'c') {
298 int bus = sc_atoi(string+1);
299 Graph_MapControl(graph, hash, name, i, bus);
300 //Node_MapControl(node, hash, name, i, bus);
301 } else {
302 if (*string == 'a') {
303 int bus = sc_atoi(string+1);
304 Graph_MapAudioControl(graph, hash, name, i, bus);
307 } else {
308 float32 value = msg->getf();
309 Graph_SetControl(graph, hash, name, i, value);
310 //Node_SetControl(node, hash, name, i, value);
313 } else {
314 int32 index = msg->geti();
315 int32 n = msg->geti();
316 for (int i=0; msg->remain() && i<n; ++i) {
317 if (msg->nextTag('f') == 's') {
318 const char* string = msg->gets();
319 if (*string == 'c') {
320 int bus = sc_atoi(string+1);
321 Graph_MapControl(graph, index+i, bus);
322 //Node_MapControl(node, index+i, bus);
323 } else {
324 if (*string == 'a') {
325 int bus = sc_atoi(string+1);
326 Graph_MapAudioControl(graph, index + i, bus);
329 } else {
330 float32 value = msg->getf();
331 Graph_SetControl(graph, index+i, value);
332 //Node_SetControl(node, index+i, value);
339 // set up scalar values
340 Wire *graphWires = graph->mWire;
341 int numConstants = inGraphDef->mNumConstants;
343 float *constants = inGraphDef->mConstants;
344 Wire *wire = graphWires;
345 for (int i=0; i<numConstants; ++i, ++wire) {
346 wire->mFromUnit = 0;
347 wire->mCalcRate = calc_ScalarRate;
348 wire->mBuffer = &wire->mScalarValue;
349 wire->mScalarValue = constants[i];
353 graph->mSampleOffset = inWorld->mSampleOffset;
354 graph->mSubsampleOffset = inWorld->mSubsampleOffset;
355 graph->mRGen = inWorld->mRGen; // defaults to rgen zero.
357 graph->mLocalAudioBusUnit = NULL;
358 graph->mLocalControlBusUnit = NULL;
360 graph->localBufNum = 0;
361 graph->localMaxBufNum = 0; // this is set from synth
363 // initialize units
364 //scprintf("initialize units\n");
365 Unit** calcUnits = graph->mCalcUnits;
366 Unit** graphUnits = graph->mUnits;
367 int calcCtr=0;
369 float *bufspace = inWorld->hw->mWireBufSpace;
370 uint32 wireCtr = numConstants; // never more than numConstants + numOutputs
371 UnitSpec *unitSpec = inGraphDef->mUnitSpecs;
372 for (uint32 i=0; i<numUnits; ++i, ++unitSpec) {
373 // construct unit from spec
374 Unit *unit = Unit_New(inWorld, unitSpec, memory);
376 // set parent
377 unit->mParent = graph;
378 unit->mParentIndex = i;
380 graphUnits[i] = unit;
383 // hook up unit inputs
384 //scprintf("hook up unit inputs\n");
385 InputSpec *inputSpec = unitSpec->mInputSpec;
386 Wire** unitInput = unit->mInput;
387 float** unitInBuf = unit->mInBuf;
388 uint32 numInputs = unitSpec->mNumInputs;
389 for (uint32 j=0; j<numInputs; ++j, ++inputSpec) {
390 Wire *wire = graphWires + inputSpec->mWireIndex;
391 unitInput[j] = wire;
392 unitInBuf[j] = wire->mBuffer;
397 // hook up unit outputs
398 //scprintf("hook up unit outputs\n");
399 Wire** unitOutput = unit->mOutput;
400 float** unitOutBuf = unit->mOutBuf;
401 uint32 numOutputs = unitSpec->mNumOutputs;
402 Wire *wire = graphWires + wireCtr;
403 wireCtr += numOutputs;
404 int unitCalcRate = unit->mCalcRate;
405 if (unitCalcRate == calc_FullRate) {
406 OutputSpec *outputSpec = unitSpec->mOutputSpec;
407 for (uint32 j=0; j<numOutputs; ++j, ++wire, ++outputSpec) {
408 wire->mFromUnit = unit;
409 wire->mCalcRate = calc_FullRate;
410 wire->mBuffer = bufspace + outputSpec->mBufferIndex;
411 unitOutput[j] = wire;
412 unitOutBuf[j] = wire->mBuffer;
414 calcUnits[calcCtr++] = unit;
415 } else {
416 for (uint32 j=0; j<numOutputs; ++j, ++wire) {
417 wire->mFromUnit = unit;
418 wire->mCalcRate = unitCalcRate;
419 wire->mBuffer = &wire->mScalarValue;
420 unitOutput[j] = wire;
421 unitOutBuf[j] = wire->mBuffer;
423 if (unitCalcRate == calc_BufRate) {
424 calcUnits[calcCtr++] = unit;
430 inGraphDef->mRefCount ++ ;
433 void Graph_RemoveID(World* inWorld, Graph *inGraph)
435 if (!World_RemoveNode(inWorld, &inGraph->mNode)) {
436 int err = kSCErr_Failed; // shouldn't happen..
437 throw err;
440 HiddenWorld* hw = inWorld->hw;
441 int id = hw->mHiddenID = (hw->mHiddenID - 8) | 0x80000000;
442 inGraph->mNode.mID = id;
443 inGraph->mNode.mHash = Hash(id);
444 if (!World_AddNode(inWorld, &inGraph->mNode)) {
445 scprintf("mysterious failure in Graph_RemoveID\n");
446 Node_Delete(&inGraph->mNode);
447 // enums are uncatchable. must throw an int.
448 int err = kSCErr_Failed; // shouldn't happen..
449 throw err;
452 //inWorld->hw->mRecentID = id;
455 void Graph_FirstCalc(Graph *inGraph)
457 //scprintf("->Graph_FirstCalc\n");
458 uint32 numUnits = inGraph->mNumUnits;
459 Unit **units = inGraph->mUnits;
460 for (uint32 i=0; i<numUnits; ++i) {
461 Unit *unit = units[i];
462 // call constructor
463 (*unit->mUnitDef->mUnitCtorFunc)(unit);
465 //scprintf("<-Graph_FirstCalc\n");
467 inGraph->mNode.mCalcFunc = (NodeCalcFunc)&Graph_Calc;
468 // now do actual graph calculation
469 Graph_Calc(inGraph);
472 void Node_NullCalc(struct Node* /*inNode*/);
474 void Graph_NullFirstCalc(Graph *inGraph)
476 //scprintf("->Graph_FirstCalc\n");
477 uint32 numUnits = inGraph->mNumUnits;
478 Unit **units = inGraph->mUnits;
479 for (uint32 i=0; i<numUnits; ++i) {
480 Unit *unit = units[i];
481 // call constructor
482 (*unit->mUnitDef->mUnitCtorFunc)(unit);
484 //scprintf("<-Graph_FirstCalc\n");
486 inGraph->mNode.mCalcFunc = &Node_NullCalc;
489 inline void Graph_Calc_unit(Unit * unit)
491 (unit->mCalcFunc)(unit, unit->mBufLength);
494 void Graph_Calc(Graph *inGraph)
496 //scprintf("->Graph_Calc\n");
497 uint32 numCalcUnits = inGraph->mNumCalcUnits;
498 Unit **calcUnits = inGraph->mCalcUnits;
500 int unroll8 = numCalcUnits / 8;
501 int remain8 = numCalcUnits % 8;
502 int i = 0;
504 for (int j = 0; j!=unroll8; i += 8, ++j) {
505 Graph_Calc_unit(calcUnits[i]);
506 Graph_Calc_unit(calcUnits[i+1]);
507 Graph_Calc_unit(calcUnits[i+2]);
508 Graph_Calc_unit(calcUnits[i+3]);
509 Graph_Calc_unit(calcUnits[i+4]);
510 Graph_Calc_unit(calcUnits[i+5]);
511 Graph_Calc_unit(calcUnits[i+6]);
512 Graph_Calc_unit(calcUnits[i+7]);
515 int unroll4 = remain8 / 4;
516 int remain4 = remain8 % 4;
517 if (unroll4) {
518 Graph_Calc_unit(calcUnits[i]);
519 Graph_Calc_unit(calcUnits[i+1]);
520 Graph_Calc_unit(calcUnits[i+2]);
521 Graph_Calc_unit(calcUnits[i+3]);
522 i+=4;
525 int unroll2 = remain4 / 2;
526 int remain2 = remain4 % 2;
527 if (unroll2) {
528 Graph_Calc_unit(calcUnits[i]);
529 Graph_Calc_unit(calcUnits[i+1]);
530 i += 2;
533 if (remain2)
534 Graph_Calc_unit(calcUnits[i]);
536 //scprintf("<-Graph_Calc\n");
539 void Graph_CalcTrace(Graph *inGraph);
540 void Graph_CalcTrace(Graph *inGraph)
542 uint32 numCalcUnits = inGraph->mNumCalcUnits;
543 Unit **calcUnits = inGraph->mCalcUnits;
544 scprintf("\nTRACE %d %s #units: %d\n", inGraph->mNode.mID, inGraph->mNode.mDef->mName, numCalcUnits);
545 for (uint32 i=0; i<numCalcUnits; ++i) {
546 Unit *unit = calcUnits[i];
547 scprintf(" unit %d %s\n in ", i, (char*)unit->mUnitDef->mUnitDefName);
548 for (uint32 j=0; j<unit->mNumInputs; ++j) {
549 scprintf(" %g", ZIN0(j));
551 scprintf("\n");
552 (unit->mCalcFunc)(unit, unit->mBufLength);
553 scprintf(" out");
554 for (uint32 j=0; j<unit->mNumOutputs; ++j) {
555 scprintf(" %g", ZOUT0(j));
557 scprintf("\n");
559 inGraph->mNode.mCalcFunc = (NodeCalcFunc)&Graph_Calc;
562 void Graph_Trace(Graph *inGraph)
564 if (inGraph->mNode.mCalcFunc == (NodeCalcFunc)&Graph_Calc) {
565 inGraph->mNode.mCalcFunc = (NodeCalcFunc)&Graph_CalcTrace;
570 int Graph_GetControl(Graph* inGraph, uint32 inIndex, float& outValue)
572 if (inIndex >= GRAPHDEF(inGraph)->mNumControls) return kSCErr_IndexOutOfRange;
573 outValue = inGraph->mControls[inIndex];
574 return kSCErr_None;
577 int Graph_GetControl(Graph* inGraph, int32 inHash, int32 *inName, uint32 inIndex, float& outValue)
579 ParamSpecTable* table = GRAPH_PARAM_TABLE(inGraph);
580 ParamSpec *spec = table->Get(inHash, inName);
581 if (!spec) return kSCErr_IndexOutOfRange;
582 return Graph_GetControl(inGraph, spec->mIndex + inIndex, outValue);
585 void Graph_SetControl(Graph* inGraph, uint32 inIndex, float inValue)
587 if (inIndex >= GRAPHDEF(inGraph)->mNumControls) return;
588 inGraph->mControlRates[inIndex] = 0;
589 float *ptr = inGraph->mControls + inIndex;
590 inGraph->mMapControls[inIndex] = ptr; // unmap the control
591 *ptr = inValue;
594 void Graph_SetControl(Graph* inGraph, int32 inHash, int32 *inName, uint32 inIndex, float inValue)
596 ParamSpecTable* table = GRAPH_PARAM_TABLE(inGraph);
597 ParamSpec *spec = table->Get(inHash, inName);
598 if (spec) Graph_SetControl(inGraph, spec->mIndex + inIndex, inValue);
603 void Graph_MapControl(Graph* inGraph, int32 inHash, int32 *inName, uint32 inIndex, uint32 inBus)
605 ParamSpecTable* table = GRAPH_PARAM_TABLE(inGraph);
606 ParamSpec *spec = table->Get(inHash, inName);
607 if (spec) Graph_MapControl(inGraph, spec->mIndex + inIndex, inBus);
610 void Graph_MapControl(Graph* inGraph, uint32 inIndex, uint32 inBus)
612 if (inIndex >= GRAPHDEF(inGraph)->mNumControls) return;
613 World *world = inGraph->mNode.mWorld;
614 if (inBus >= 0x80000000) {
615 inGraph->mControlRates[inIndex] = 0;
616 inGraph->mMapControls[inIndex] = inGraph->mControls + inIndex;
617 } else if (inBus < world->mNumControlBusChannels) {
618 inGraph->mControlRates[inIndex] = 1;
619 inGraph->mMapControls[inIndex] = world->mControlBus + inBus;
623 void Graph_MapAudioControl(Graph* inGraph, int32 inHash, int32 *inName, uint32 inIndex, uint32 inBus)
625 ParamSpecTable* table = GRAPH_PARAM_TABLE(inGraph);
626 ParamSpec *spec = table->Get(inHash, inName);
627 if (spec) Graph_MapAudioControl(inGraph, spec->mIndex + inIndex, inBus);
630 void Graph_MapAudioControl(Graph* inGraph, uint32 inIndex, uint32 inBus)
632 if (inIndex >= GRAPHDEF(inGraph)->mNumControls) return;
633 World *world = inGraph->mNode.mWorld;
634 // inGraph->mControlRates[inIndex] = 2;
635 /* what is the below doing??? it is unmapping by looking for negative ints */
636 if (inBus >= 0x80000000) {
637 inGraph->mControlRates[inIndex] = 0;
638 inGraph->mMapControls[inIndex] = inGraph->mControls + inIndex;
639 } else if (inBus < world->mNumAudioBusChannels) {
640 inGraph->mControlRates[inIndex] = 2;
641 inGraph->mMapControls[inIndex] = world->mAudioBus + (inBus * world->mBufLength);