common: prevent buffer overflow
[supercollider.git] / server / scsynth / SC_GraphDef.cpp
blob03e73d0710c33d1d53b0757d786ff292d6a0094a
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 "clz.h"
23 #include "SC_Graph.h"
24 #include "SC_GraphDef.h"
25 #include "SC_Wire.h"
26 #include "SC_WireSpec.h"
27 #include "SC_UnitSpec.h"
28 #include "SC_UnitDef.h"
29 #include "SC_HiddenWorld.h"
30 #ifndef _MSC_VER
31 #include <dirent.h>
32 #endif //_MSC_VER
33 #include "ReadWriteMacros.h"
34 #include "SC_Prototypes.h"
35 #include "SC_CoreAudio.h"
36 #include "SC_DirUtils.h"
38 #ifdef _WIN32
39 #include "SC_Win32Utils.h"
40 #endif
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <sstream>
45 #include <stdexcept>
46 #include <string>
48 extern Malloc gMalloc;
50 int32 GetHash(ParamSpec* inParamSpec)
52 return inParamSpec->mHash;
55 int32* GetKey(ParamSpec* inParamSpec)
57 return inParamSpec->mName;
61 void ReadName(char*& buffer, int32* name);
62 void ReadName(char*& buffer, int32* name)
64 uint32 namelen = readUInt8(buffer);
65 if (namelen >= kSCNameByteLen) {
66 std::ostringstream os;
67 os << "name too long (> " << kSCNameByteLen - 1 << " chars): "
68 << std::string(buffer, namelen);
69 throw std::runtime_error(os.str());
71 memset(name, 0, kSCNameByteLen);
72 readData(buffer, (char*)name, namelen);
75 void ReadNodeDefName(char*& buffer, int32* name);
76 void ReadNodeDefName(char*& buffer, int32* name)
78 uint32 namelen = readUInt8(buffer);
79 if (namelen >= kSCNodeDefNameByteLen) {
80 std::ostringstream os;
81 os << "node definition name too long (> " << kSCNodeDefNameByteLen - 1 << " chars): "
82 << std::string(buffer, namelen);
83 throw std::runtime_error(os.str());
85 memset(name, 0, kSCNodeDefNameByteLen);
86 readData(buffer, (char*)name, namelen);
89 void ParamSpec_Read(ParamSpec* inParamSpec, char*& buffer);
90 void ParamSpec_Read(ParamSpec* inParamSpec, char*& buffer)
92 ReadName(buffer, inParamSpec->mName);
93 inParamSpec->mIndex = readInt16_be(buffer);
94 inParamSpec->mHash = Hash(inParamSpec->mName);
97 void InputSpec_Read(InputSpec* inInputSpec, char*& buffer);
98 void InputSpec_Read(InputSpec* inInputSpec, char*& buffer)
100 inInputSpec->mFromUnitIndex = (int16)readInt16_be(buffer);
101 inInputSpec->mFromOutputIndex = (int16)readInt16_be(buffer);
103 inInputSpec->mWireIndex = -1;
106 void OutputSpec_Read(OutputSpec* inOutputSpec, char*& buffer);
107 void OutputSpec_Read(OutputSpec* inOutputSpec, char*& buffer)
109 inOutputSpec->mCalcRate = readInt8(buffer);
111 inOutputSpec->mWireIndex = -1;
112 inOutputSpec->mBufferIndex = -1;
113 inOutputSpec->mNumConsumers = 0;
116 void UnitSpec_Read(UnitSpec* inUnitSpec, char*& buffer);
117 void UnitSpec_Read(UnitSpec* inUnitSpec, char*& buffer)
119 int32 name[kSCNameLen];
120 ReadName(buffer, name);
122 inUnitSpec->mUnitDef = GetUnitDef(name);
123 if (!inUnitSpec->mUnitDef) {
124 char str[256];
125 sprintf(str, "UGen '%s' not installed.", (char*)name);
126 throw std::runtime_error(str);
127 return;
129 inUnitSpec->mCalcRate = readInt8(buffer);
131 inUnitSpec->mNumInputs = readInt16_be(buffer);
132 inUnitSpec->mNumOutputs = readInt16_be(buffer);
133 inUnitSpec->mSpecialIndex = readInt16_be(buffer);
134 inUnitSpec->mInputSpec = (InputSpec*)malloc(sizeof(InputSpec) * inUnitSpec->mNumInputs);
135 inUnitSpec->mOutputSpec = (OutputSpec*)malloc(sizeof(OutputSpec) * inUnitSpec->mNumOutputs);
136 for (uint32 i=0; i<inUnitSpec->mNumInputs; ++i) {
137 InputSpec_Read(inUnitSpec->mInputSpec + i, buffer);
139 for (uint32 i=0; i<inUnitSpec->mNumOutputs; ++i) {
140 OutputSpec_Read(inUnitSpec->mOutputSpec + i, buffer);
142 int numPorts = inUnitSpec->mNumInputs + inUnitSpec->mNumOutputs;
143 inUnitSpec->mAllocSize = inUnitSpec->mUnitDef->mAllocSize + numPorts * (sizeof(Wire*) + sizeof(float*));
146 GraphDef* GraphDef_Read(World *inWorld, char*& buffer, GraphDef* inList, int32 inVersion);
148 GraphDef* GraphDefLib_Read(World *inWorld, char* buffer, GraphDef* inList);
149 GraphDef* GraphDefLib_Read(World *inWorld, char* buffer, GraphDef* inList)
151 int32 magic = readInt32_be(buffer);
152 if (magic != (('S'<<24)|('C'<<16)|('g'<<8)|'f') /*'SCgf'*/) return inList;
154 int32 version = readInt32_be(buffer);
155 if (version > 1) return inList;
157 uint32 numDefs = readInt16_be(buffer);
159 for (uint32 i=0; i<numDefs; ++i) {
160 inList = GraphDef_Read(inWorld, buffer, inList, version);
162 return inList;
166 void ChooseMulAddFunc(GraphDef *graphDef, UnitSpec* unitSpec);
167 void DoBufferColoring(World *inWorld, GraphDef *inGraphDef);
169 void GraphDef_ReadVariant(World *inWorld, char*& buffer, GraphDef* inGraphDef, GraphDef* inVariant)
171 memcpy(inVariant, inGraphDef, sizeof(GraphDef));
173 inVariant->mNumVariants = 0;
174 inVariant->mVariants = 0;
176 ReadName(buffer, inVariant->mNodeDef.mName);
177 inVariant->mNodeDef.mHash = Hash(inVariant->mNodeDef.mName);
179 inVariant->mInitialControlValues = (float32*)malloc(sizeof(float32) * inGraphDef->mNumControls);
180 for (uint32 i=0; i<inGraphDef->mNumControls; ++i) {
181 inVariant->mInitialControlValues[i] = readFloat_be(buffer);
185 GraphDef* GraphDef_Read(World *inWorld, char*& buffer, GraphDef* inList, int32 inVersion)
187 int32 name[kSCNodeDefNameLen];
188 ReadNodeDefName(buffer, name);
190 GraphDef* graphDef = (GraphDef*)calloc(1, sizeof(GraphDef));
192 graphDef->mOriginal = graphDef;
194 graphDef->mNodeDef.mAllocSize = sizeof(Graph);
196 memcpy((char*)graphDef->mNodeDef.mName, (char*)name, kSCNodeDefNameByteLen);
198 graphDef->mNodeDef.mHash = Hash(graphDef->mNodeDef.mName);
200 graphDef->mNumConstants = readInt16_be(buffer);
201 graphDef->mConstants = (float*)malloc(graphDef->mNumConstants * sizeof(float));
202 for (uint32 i=0; i<graphDef->mNumConstants; ++i) {
203 graphDef->mConstants[i] = readFloat_be(buffer);
206 graphDef->mNumControls = readInt16_be(buffer);
207 graphDef->mInitialControlValues = (float32*)malloc(sizeof(float32) * graphDef->mNumControls);
208 for (uint32 i=0; i<graphDef->mNumControls; ++i) {
209 graphDef->mInitialControlValues[i] = readFloat_be(buffer);
212 graphDef->mNumParamSpecs = readInt16_be(buffer);
213 if (graphDef->mNumParamSpecs) {
214 int hashTableSize = NEXTPOWEROFTWO(graphDef->mNumParamSpecs);
215 graphDef->mParamSpecTable = new ParamSpecTable(&gMalloc, hashTableSize, false);
216 graphDef->mParamSpecs = (ParamSpec*)malloc(graphDef->mNumParamSpecs * sizeof(ParamSpec));
217 for (uint32 i=0; i<graphDef->mNumParamSpecs; ++i) {
218 ParamSpec *paramSpec = graphDef->mParamSpecs + i;
219 ParamSpec_Read(paramSpec, buffer);
220 graphDef->mParamSpecTable->Add(paramSpec);
222 } else {
223 // empty table to eliminate test in Graph_SetControl
224 graphDef->mParamSpecTable = new ParamSpecTable(&gMalloc, 4, false);
225 graphDef->mParamSpecs = 0;
228 graphDef->mNumWires = graphDef->mNumConstants;
229 graphDef->mNumUnitSpecs = readInt16_be(buffer);
230 graphDef->mUnitSpecs = (UnitSpec*)malloc(sizeof(UnitSpec) * graphDef->mNumUnitSpecs);
231 graphDef->mNumCalcUnits = 0;
232 for (uint32 i=0; i<graphDef->mNumUnitSpecs; ++i) {
233 UnitSpec *unitSpec = graphDef->mUnitSpecs + i;
234 UnitSpec_Read(unitSpec, buffer);
236 switch (unitSpec->mCalcRate)
238 case calc_ScalarRate :
239 unitSpec->mRateInfo = &inWorld->mBufRate;
240 break;
241 case calc_BufRate :
242 graphDef->mNumCalcUnits++;
243 unitSpec->mRateInfo = &inWorld->mBufRate;
244 break;
245 case calc_FullRate :
246 graphDef->mNumCalcUnits++;
247 unitSpec->mRateInfo = &inWorld->mFullRate;
248 break;
249 case calc_DemandRate :
250 unitSpec->mRateInfo = &inWorld->mBufRate;
251 break;
254 graphDef->mNodeDef.mAllocSize += unitSpec->mAllocSize;
255 graphDef->mNumWires += unitSpec->mNumOutputs;
258 DoBufferColoring(inWorld, graphDef);
260 graphDef->mWiresAllocSize = graphDef->mNumWires * sizeof(Wire);
261 graphDef->mUnitsAllocSize = graphDef->mNumUnitSpecs * sizeof(Unit*);
262 graphDef->mCalcUnitsAllocSize = graphDef->mNumCalcUnits * sizeof(Unit*);
264 graphDef->mNodeDef.mAllocSize += graphDef->mWiresAllocSize;
265 graphDef->mNodeDef.mAllocSize += graphDef->mUnitsAllocSize;
266 graphDef->mNodeDef.mAllocSize += graphDef->mCalcUnitsAllocSize;
268 graphDef->mControlAllocSize = graphDef->mNumControls * sizeof(float);
269 graphDef->mNodeDef.mAllocSize += graphDef->mControlAllocSize;
271 graphDef->mMapControlsAllocSize = graphDef->mNumControls * sizeof(float*);
272 graphDef->mNodeDef.mAllocSize += graphDef->mMapControlsAllocSize;
274 graphDef->mMapControlRatesAllocSize = graphDef->mNumControls * sizeof(int*);
275 graphDef->mNodeDef.mAllocSize += graphDef->mMapControlRatesAllocSize;
278 graphDef->mNext = inList;
279 graphDef->mRefCount = 1;
281 if (inVersion >= 1) {
282 graphDef->mNumVariants = readInt16_be(buffer);
283 if (graphDef->mNumVariants) {
284 graphDef->mVariants = (GraphDef*)calloc(graphDef->mNumVariants, sizeof(GraphDef));
285 for (uint32 i=0; i<graphDef->mNumVariants; ++i) {
286 GraphDef_ReadVariant(inWorld, buffer, graphDef, graphDef->mVariants + i);
291 return graphDef;
295 void GraphDef_Define(World *inWorld, GraphDef *inList)
297 GraphDef *graphDef = inList;
298 while (graphDef) {
299 GraphDef *next = graphDef->mNext;
301 GraphDef* previousDef = World_GetGraphDef(inWorld, graphDef->mNodeDef.mName);
302 if (previousDef) {
303 World_RemoveGraphDef(inWorld, previousDef);
304 if (--previousDef->mRefCount == 0) {
305 GraphDef_DeleteMsg(inWorld, previousDef);
308 World_AddGraphDef(inWorld, graphDef);
309 graphDef->mNext = 0;
310 graphDef = next;
314 void GraphDef_Remove(World *inWorld, int32 *inName)
316 GraphDef* graphDef = World_GetGraphDef(inWorld, inName);
317 if (graphDef) {
318 World_RemoveGraphDef(inWorld, graphDef);
319 if (--graphDef->mRefCount == 0) {
320 GraphDef_DeleteMsg(inWorld, graphDef);
325 void GraphDef_DeleteMsg(World *inWorld, GraphDef *inDef)
327 DeleteGraphDefMsg msg;
328 msg.mDef = inDef;
329 inWorld->hw->mDeleteGraphDefs.Write(msg);
332 GraphDef* GraphDef_Recv(World *inWorld, char *buffer, GraphDef *inList)
335 try {
336 inList = GraphDefLib_Read(inWorld, buffer, inList);
337 } catch (std::exception& exc) {
338 scprintf("exception in GraphDef_Recv: %s\n", exc.what());
339 } catch (...) {
340 scprintf("unknown exception in GraphDef_Recv\n");
343 return inList;
346 GraphDef* GraphDef_LoadGlob(World *inWorld, const char *pattern, GraphDef *inList)
348 SC_GlobHandle* glob = sc_Glob(pattern);
349 if (!glob) return inList;
351 const char* filename;
352 while ((filename = sc_GlobNext(glob)) != 0) {
353 int len = strlen(filename);
354 if (strncmp(filename+len-9, ".scsyndef", 9)==0) {
355 inList = GraphDef_Load(inWorld, filename, inList);
357 // why? <sk>
358 GraphDef_Load(inWorld, filename, inList);
361 sc_GlobFree(glob);
362 return inList;
365 GraphDef* GraphDef_Load(World *inWorld, const char *filename, GraphDef *inList)
367 FILE *file = fopen(filename, "rb");
369 if (!file) {
370 scprintf("*** ERROR: can't fopen '%s'\n", filename);
371 return inList;
374 fseek(file, 0, SEEK_END);
375 int size = ftell(file);
376 char *buffer = (char*)malloc(size);
377 if (!buffer) {
378 scprintf("*** ERROR: can't malloc buffer size %d\n", size);
379 fclose(file);
380 return inList;
382 fseek(file, 0, SEEK_SET);
384 size_t readSize = fread(buffer, 1, size, file);
385 fclose(file);
387 if (readSize!= size) {
388 scprintf("*** ERROR: invalid fread\n", size);
389 free(buffer);
390 return inList;
393 try {
394 inList = GraphDefLib_Read(inWorld, buffer, inList);
395 } catch (std::exception& exc) {
396 scprintf("exception in GrafDef_Load: %s\n", exc.what());
397 scprintf("while reading file '%s'\n", filename);
398 } catch (...) {
399 scprintf("unknown exception in GrafDef_Load\n");
400 scprintf("while reading file '%s'\n", filename);
403 free(buffer);
405 return inList;
408 GraphDef* GraphDef_LoadDir(World *inWorld, char *dirname, GraphDef *inList)
410 SC_DirHandle *dir = sc_OpenDir(dirname);
411 if (!dir) {
412 scprintf("*** ERROR: open directory failed '%s'\n", dirname);
413 return inList;
416 for (;;) {
417 char diritem[MAXPATHLEN];
418 bool skipItem = false;
419 bool validItem = sc_ReadDir(dir, dirname, diritem, skipItem);
420 if (!validItem) break;
421 if (skipItem) continue;
423 if (sc_DirectoryExists(diritem)) {
424 inList = GraphDef_LoadDir(inWorld, diritem, inList);
425 } else {
426 int dnamelen = strlen(diritem);
427 if (strncmp(diritem+dnamelen-9, ".scsyndef", 9) == 0) {
428 inList = GraphDef_Load(inWorld, diritem, inList);
433 sc_CloseDir(dir);
434 return inList;
437 void UnitSpec_Free(UnitSpec *inUnitSpec);
438 void UnitSpec_Free(UnitSpec *inUnitSpec)
440 free(inUnitSpec->mInputSpec);
441 free(inUnitSpec->mOutputSpec);
444 void GraphDef_Free(GraphDef *inGraphDef)
446 if (inGraphDef != inGraphDef->mOriginal) return;
448 for (uint32 i=0; i<inGraphDef->mNumUnitSpecs; ++i) {
449 UnitSpec_Free(inGraphDef->mUnitSpecs + i);
451 for (uint32 i=0; i<inGraphDef->mNumVariants; ++i) {
452 free(inGraphDef->mVariants[i].mInitialControlValues);
454 delete inGraphDef->mParamSpecTable;
455 free(inGraphDef->mParamSpecs);
456 free(inGraphDef->mInitialControlValues);
457 free(inGraphDef->mConstants);
458 free(inGraphDef->mUnitSpecs);
459 free(inGraphDef->mVariants);
460 free(inGraphDef);
463 void NodeDef_Dump(NodeDef *inNodeDef)
465 scprintf("mName '%s'\n", (char*)inNodeDef->mName);
466 scprintf("mHash %d\n", inNodeDef->mHash);
467 scprintf("mAllocSize %lu\n", inNodeDef->mAllocSize);
470 void GraphDef_Dump(GraphDef *inGraphDef)
472 NodeDef_Dump(&inGraphDef->mNodeDef);
474 scprintf("mNumControls %d\n", inGraphDef->mNumControls);
475 scprintf("mNumWires %d\n", inGraphDef->mNumWires);
476 scprintf("mNumUnitSpecs %d\n", inGraphDef->mNumUnitSpecs);
477 scprintf("mNumWireBufs %d\n", inGraphDef->mNumWireBufs);
479 for (uint32 i=0; i<inGraphDef->mNumControls; ++i) {
480 scprintf(" %d mInitialControlValues %g\n", i, inGraphDef->mInitialControlValues[i]);
483 for (uint32 i=0; i<inGraphDef->mNumWires; ++i) {
484 //WireSpec_Dump(inGraphDef->mWireSpec + i);
486 for (uint32 i=0; i<inGraphDef->mNumUnitSpecs; ++i) {
487 //UnitSpec_Dump(inGraphDef->mUnitSpecs + i);
492 SynthBufferAllocator
494 var nextBufIndex = 0;
495 var stack;
496 var refs;
498 *new {
499 ^super.new.init
501 init {
502 refs = Bag.new;
504 alloc { arg count;
505 var bufNumber;
506 if (stack.size > 0, {
507 bufNumber = stack.pop
509 bufNumber = nextBufIndex;
510 nextBufIndex = nextBufIndex + 1;
512 refs.add(bufNumber, count);
513 ^bufNumber
515 release { arg bufNumber;
516 refs.remove(bufNumber);
517 if (refs.includes(bufNumber).not, { stack = stack.add(bufNumber) });
519 numBufs { ^nextBufIndex }
523 struct BufColorAllocator
525 int16 *refs;
526 int16 *stack;
527 int16 stackPtr;
528 int16 nextIndex;
529 int16 refsMaxSize;
530 int16 stackMaxSize;
532 BufColorAllocator();
533 ~BufColorAllocator();
535 int alloc(int count);
536 bool release(int inIndex);
537 int NumBufs() { return nextIndex; }
540 inline BufColorAllocator::BufColorAllocator()
542 refsMaxSize = 32;
543 stackMaxSize = 32;
544 refs = (int16*)calloc(refsMaxSize, sizeof(int16));
545 stack = (int16*)calloc(stackMaxSize, sizeof(int16));
546 stackPtr = 0;
547 nextIndex = 0;
550 inline BufColorAllocator::~BufColorAllocator()
552 free(refs);
553 free(stack);
556 inline int BufColorAllocator::alloc(int count)
558 int outIndex;
559 if (stackPtr) {
560 outIndex = stack[--stackPtr];
561 } else {
562 outIndex = nextIndex++;
564 if (outIndex >= refsMaxSize) {
565 refs = (int16*)realloc(refs, refsMaxSize*2*sizeof(int16));
566 memset(refs + refsMaxSize, 0, refsMaxSize*sizeof(int16));
567 refsMaxSize *= 2;
569 refs[outIndex] = count;
570 return outIndex;
573 inline bool BufColorAllocator::release(int inIndex)
575 if (refs[inIndex] == 0) return false;
576 if (--refs[inIndex] == 0) {
577 if (stackPtr >= stackMaxSize) {
578 stack = (int16*)realloc(stack, stackMaxSize*2*sizeof(int16));
579 memset(stack + stackMaxSize, 0, stackMaxSize*sizeof(int16));
580 stackMaxSize *= 2;
582 stack[stackPtr++] = inIndex;
584 return true;
587 void ReleaseInputBuffers(GraphDef *inGraphDef, UnitSpec *unitSpec, BufColorAllocator& bufColor)
589 //scprintf("ReleaseInputBuffers %s numinputs %d\n", unitSpec->mUnitDef->mUnitDefName, unitSpec->mNumInputs);
590 for (int i=unitSpec->mNumInputs-1; i>=0; --i) {
591 InputSpec *inputSpec = unitSpec->mInputSpec + i;
592 if (inputSpec->mFromUnitIndex >= 0) {
593 UnitSpec *outUnit = inGraphDef->mUnitSpecs + inputSpec->mFromUnitIndex;
594 OutputSpec *outputSpec = outUnit->mOutputSpec + inputSpec->mFromOutputIndex;
595 inputSpec->mWireIndex = outputSpec->mWireIndex;
596 if (outputSpec->mCalcRate == calc_FullRate) {
597 if (!bufColor.release(outputSpec->mBufferIndex)) {
598 scprintf("buffer coloring error: tried to release output with zero count\n");
599 scprintf("output: %d %s %d\n", inputSpec->mFromUnitIndex,
600 outUnit->mUnitDef->mUnitDefName, inputSpec->mFromOutputIndex);
601 scprintf("input: %s %d\n", unitSpec->mUnitDef->mUnitDefName, i);
602 throw std::runtime_error("buffer coloring error.");
605 } else {
606 inputSpec->mWireIndex = inputSpec->mFromOutputIndex;
611 void AllocOutputBuffers(UnitSpec *unitSpec, BufColorAllocator& bufColor, int& wireIndexCtr)
613 //scprintf("AllocOutputBuffers %s numoutputs %d\n", unitSpec->mUnitDef->mUnitDefName, unitSpec->mNumOutputs);
614 for (uint32 i=0; i<unitSpec->mNumOutputs; ++i) {
615 OutputSpec *outputSpec = unitSpec->mOutputSpec + i;
616 outputSpec->mWireIndex = wireIndexCtr++;
617 if (outputSpec->mCalcRate == calc_FullRate) {
618 int bufIndex = bufColor.alloc(outputSpec->mNumConsumers);
619 outputSpec->mBufferIndex = bufIndex;
624 void DoBufferColoring(World *inWorld, GraphDef *inGraphDef)
626 // count consumers of outputs
627 for (uint32 j=0; j<inGraphDef->mNumUnitSpecs; ++j) {
628 UnitSpec *unitSpec = inGraphDef->mUnitSpecs + j;
629 for (uint32 i=0; i<unitSpec->mNumInputs; ++i) {
630 InputSpec *inputSpec = unitSpec->mInputSpec + i;
631 if (inputSpec->mFromUnitIndex >= 0) {
632 UnitSpec *outUnit = inGraphDef->mUnitSpecs + inputSpec->mFromUnitIndex;
633 OutputSpec *outputSpec = outUnit->mOutputSpec + inputSpec->mFromOutputIndex;
634 outputSpec->mNumConsumers ++;
639 // buffer coloring
641 BufColorAllocator bufColor;
642 int wireIndexCtr = inGraphDef->mNumConstants;
643 for (uint32 j=0; j<inGraphDef->mNumUnitSpecs; ++j) {
644 UnitSpec *unitSpec = inGraphDef->mUnitSpecs + j;
645 if (unitSpec->mUnitDef->mFlags & kUnitDef_CantAliasInputsToOutputs) {
646 // set wire index, alloc outputs
647 AllocOutputBuffers(unitSpec, bufColor, wireIndexCtr);
648 // set wire index, release inputs
649 ReleaseInputBuffers(inGraphDef, unitSpec, bufColor);
650 } else {
651 // set wire index, release inputs
652 ReleaseInputBuffers(inGraphDef, unitSpec, bufColor);
653 // set wire index, alloc outputs
654 AllocOutputBuffers(unitSpec, bufColor, wireIndexCtr);
658 inGraphDef->mNumWireBufs = bufColor.NumBufs();
659 if (inWorld->mRunning)
661 // cannot reallocate interconnect buffers while running audio.
662 if (inGraphDef->mNumWireBufs > inWorld->hw->mMaxWireBufs) {
663 throw std::runtime_error("exceeded number of interconnect buffers.");
665 } else {
666 inWorld->hw->mMaxWireBufs = sc_max(inWorld->hw->mMaxWireBufs, inGraphDef->mNumWireBufs);
670 // multiply buf indices by buf length for proper offset
671 int bufLength = inWorld->mBufLength;
672 for (uint32 j=0; j<inGraphDef->mNumUnitSpecs; ++j) {
673 UnitSpec *unitSpec = inGraphDef->mUnitSpecs + j;
674 for (uint32 i=0; i<unitSpec->mNumOutputs; ++i) {
675 OutputSpec *outputSpec = unitSpec->mOutputSpec + i;
676 if (outputSpec->mCalcRate == calc_FullRate) {
677 outputSpec->mBufferIndex *= bufLength;