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
24 #include "SC_GraphDef.h"
26 #include "SC_WireSpec.h"
27 #include "SC_UnitSpec.h"
28 #include "SC_UnitDef.h"
29 #include "SC_HiddenWorld.h"
30 #include "SC_WorldOptions.h"
34 #include "ReadWriteMacros.h"
35 #include "SC_Prototypes.h"
36 #include "SC_CoreAudio.h"
37 #include "SC_DirUtils.h"
40 #include "SC_Win32Utils.h"
49 extern Malloc gMalloc
;
51 int32
GetHash(ParamSpec
* inParamSpec
)
53 return inParamSpec
->mHash
;
56 int32
* GetKey(ParamSpec
* inParamSpec
)
58 return inParamSpec
->mName
;
62 void ReadName(char*& buffer
, int32
* name
);
63 void ReadName(char*& buffer
, int32
* name
)
65 uint32 namelen
= readUInt8(buffer
);
66 if (namelen
>= kSCNameByteLen
) {
67 std::ostringstream os
;
68 os
<< "name too long (> " << kSCNameByteLen
- 1 << " chars): "
69 << std::string(buffer
, namelen
);
70 throw std::runtime_error(os
.str());
72 memset(name
, 0, kSCNameByteLen
);
73 readData(buffer
, (char*)name
, namelen
);
76 void ReadNodeDefName(char*& buffer
, int32
* name
);
77 void ReadNodeDefName(char*& buffer
, int32
* name
)
79 uint32 namelen
= readUInt8(buffer
);
80 if (namelen
>= kSCNodeDefNameByteLen
) {
81 std::ostringstream os
;
82 os
<< "node definition name too long (> " << kSCNodeDefNameByteLen
- 1 << " chars): "
83 << std::string(buffer
, namelen
);
84 throw std::runtime_error(os
.str());
86 memset(name
, 0, kSCNodeDefNameByteLen
);
87 readData(buffer
, (char*)name
, namelen
);
90 void ParamSpec_Read(ParamSpec
* inParamSpec
, char*& buffer
);
91 void ParamSpec_Read(ParamSpec
* inParamSpec
, char*& buffer
)
93 ReadName(buffer
, inParamSpec
->mName
);
94 inParamSpec
->mIndex
= readInt32_be(buffer
);
95 inParamSpec
->mHash
= Hash(inParamSpec
->mName
);
98 void ParamSpec_ReadVer1(ParamSpec
* inParamSpec
, char*& buffer
);
99 void ParamSpec_ReadVer1(ParamSpec
* inParamSpec
, char*& buffer
)
101 ReadName(buffer
, inParamSpec
->mName
);
102 inParamSpec
->mIndex
= readInt16_be(buffer
);
103 inParamSpec
->mHash
= Hash(inParamSpec
->mName
);
106 void InputSpec_Read(InputSpec
* inInputSpec
, char*& buffer
);
107 void InputSpec_Read(InputSpec
* inInputSpec
, char*& buffer
)
109 inInputSpec
->mFromUnitIndex
= readInt32_be(buffer
);
110 inInputSpec
->mFromOutputIndex
= readInt32_be(buffer
);
112 inInputSpec
->mWireIndex
= -1;
115 void InputSpec_ReadVer1(InputSpec
* inInputSpec
, char*& buffer
);
116 void InputSpec_ReadVer1(InputSpec
* inInputSpec
, char*& buffer
)
118 inInputSpec
->mFromUnitIndex
= (int16
)readInt16_be(buffer
);
119 inInputSpec
->mFromOutputIndex
= (int16
)readInt16_be(buffer
);
121 inInputSpec
->mWireIndex
= -1;
124 void OutputSpec_Read(OutputSpec
* inOutputSpec
, char*& buffer
);
125 void OutputSpec_Read(OutputSpec
* inOutputSpec
, char*& buffer
)
127 inOutputSpec
->mCalcRate
= readInt8(buffer
);
128 inOutputSpec
->mWireIndex
= -1;
129 inOutputSpec
->mBufferIndex
= -1;
130 inOutputSpec
->mNumConsumers
= 0;
133 void UnitSpec_Read(UnitSpec
* inUnitSpec
, char*& buffer
);
134 void UnitSpec_Read(UnitSpec
* inUnitSpec
, char*& buffer
)
136 int32 name
[kSCNameLen
];
137 ReadName(buffer
, name
);
139 inUnitSpec
->mUnitDef
= GetUnitDef(name
);
140 if (!inUnitSpec
->mUnitDef
) {
142 sprintf(str
, "UGen '%s' not installed.", (char*)name
);
143 throw std::runtime_error(str
);
146 inUnitSpec
->mCalcRate
= readInt8(buffer
);
148 inUnitSpec
->mNumInputs
= readInt32_be(buffer
);
149 inUnitSpec
->mNumOutputs
= readInt32_be(buffer
);
150 inUnitSpec
->mSpecialIndex
= readInt16_be(buffer
);
151 inUnitSpec
->mInputSpec
= (InputSpec
*)malloc(sizeof(InputSpec
) * inUnitSpec
->mNumInputs
);
152 inUnitSpec
->mOutputSpec
= (OutputSpec
*)malloc(sizeof(OutputSpec
) * inUnitSpec
->mNumOutputs
);
153 for (uint32 i
=0; i
<inUnitSpec
->mNumInputs
; ++i
) {
154 InputSpec_Read(inUnitSpec
->mInputSpec
+ i
, buffer
);
156 for (uint32 i
=0; i
<inUnitSpec
->mNumOutputs
; ++i
) {
157 OutputSpec_Read(inUnitSpec
->mOutputSpec
+ i
, buffer
);
159 uint64 numPorts
= inUnitSpec
->mNumInputs
+ inUnitSpec
->mNumOutputs
;
160 inUnitSpec
->mAllocSize
= inUnitSpec
->mUnitDef
->mAllocSize
+ numPorts
* (sizeof(Wire
*) + sizeof(float*));
163 void UnitSpec_ReadVer1(UnitSpec
* inUnitSpec
, char*& buffer
);
164 void UnitSpec_ReadVer1(UnitSpec
* inUnitSpec
, char*& buffer
)
166 int32 name
[kSCNameLen
];
167 ReadName(buffer
, name
);
169 inUnitSpec
->mUnitDef
= GetUnitDef(name
);
170 if (!inUnitSpec
->mUnitDef
) {
172 sprintf(str
, "UGen '%s' not installed.", (char*)name
);
173 throw std::runtime_error(str
);
176 inUnitSpec
->mCalcRate
= readInt8(buffer
);
178 inUnitSpec
->mNumInputs
= readInt16_be(buffer
);
179 inUnitSpec
->mNumOutputs
= readInt16_be(buffer
);
180 inUnitSpec
->mSpecialIndex
= readInt16_be(buffer
);
181 inUnitSpec
->mInputSpec
= (InputSpec
*)malloc(sizeof(InputSpec
) * inUnitSpec
->mNumInputs
);
182 inUnitSpec
->mOutputSpec
= (OutputSpec
*)malloc(sizeof(OutputSpec
) * inUnitSpec
->mNumOutputs
);
183 for (uint32 i
=0; i
<inUnitSpec
->mNumInputs
; ++i
) {
184 InputSpec_ReadVer1(inUnitSpec
->mInputSpec
+ i
, buffer
);
186 for (uint32 i
=0; i
<inUnitSpec
->mNumOutputs
; ++i
) {
187 OutputSpec_Read(inUnitSpec
->mOutputSpec
+ i
, buffer
);
189 uint64 numPorts
= inUnitSpec
->mNumInputs
+ inUnitSpec
->mNumOutputs
;
190 inUnitSpec
->mAllocSize
= inUnitSpec
->mUnitDef
->mAllocSize
+ numPorts
* (sizeof(Wire
*) + sizeof(float*));
193 GraphDef
* GraphDef_Read(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
);
194 GraphDef
* GraphDef_ReadVer1(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
);
196 GraphDef
* GraphDefLib_Read(World
*inWorld
, char* buffer
, GraphDef
* inList
);
197 GraphDef
* GraphDefLib_Read(World
*inWorld
, char* buffer
, GraphDef
* inList
)
199 int32 magic
= readInt32_be(buffer
);
200 if (magic
!= (('S'<<24)|('C'<<16)|('g'<<8)|'f') /*'SCgf'*/) return inList
;
202 int32 version
= readInt32_be(buffer
);
207 numDefs
= readInt16_be(buffer
);
209 for (i
=0; i
<numDefs
; ++i
) {
210 inList
= GraphDef_Read(inWorld
, buffer
, inList
, version
);
216 numDefs
= readInt16_be(buffer
);
218 for (i
=0; i
<numDefs
; ++i
) {
219 inList
= GraphDef_ReadVer1(inWorld
, buffer
, inList
, version
); // handles 1 and 0
232 void ChooseMulAddFunc(GraphDef
*graphDef
, UnitSpec
* unitSpec
);
233 void DoBufferColoring(World
*inWorld
, GraphDef
*inGraphDef
);
235 void GraphDef_ReadVariant(World
*inWorld
, char*& buffer
, GraphDef
* inGraphDef
, GraphDef
* inVariant
)
237 memcpy(inVariant
, inGraphDef
, sizeof(GraphDef
));
239 inVariant
->mNumVariants
= 0;
240 inVariant
->mVariants
= 0;
242 ReadName(buffer
, inVariant
->mNodeDef
.mName
);
243 inVariant
->mNodeDef
.mHash
= Hash(inVariant
->mNodeDef
.mName
);
245 inVariant
->mInitialControlValues
= (float32
*)malloc(sizeof(float32
) * inGraphDef
->mNumControls
);
246 for (uint32 i
=0; i
<inGraphDef
->mNumControls
; ++i
) {
247 inVariant
->mInitialControlValues
[i
] = readFloat_be(buffer
);
252 GraphDef
* GraphDef_Read(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
)
254 int32 name
[kSCNodeDefNameLen
];
255 ReadNodeDefName(buffer
, name
);
257 GraphDef
* graphDef
= (GraphDef
*)calloc(1, sizeof(GraphDef
));
259 graphDef
->mOriginal
= graphDef
;
261 graphDef
->mNodeDef
.mAllocSize
= sizeof(Graph
);
263 memcpy((char*)graphDef
->mNodeDef
.mName
, (char*)name
, kSCNodeDefNameByteLen
);
265 graphDef
->mNodeDef
.mHash
= Hash(graphDef
->mNodeDef
.mName
);
267 graphDef
->mNumConstants
= readInt32_be(buffer
);
269 graphDef
->mConstants
= (float*)malloc(graphDef
->mNumConstants
* sizeof(float));
270 for (uint32 i
=0; i
<graphDef
->mNumConstants
; ++i
) {
271 graphDef
->mConstants
[i
] = readFloat_be(buffer
);
274 graphDef
->mNumControls
= readInt32_be(buffer
);
275 graphDef
->mInitialControlValues
= (float32
*)malloc(sizeof(float32
) * graphDef
->mNumControls
);
276 for (uint32 i
=0; i
<graphDef
->mNumControls
; ++i
) {
277 graphDef
->mInitialControlValues
[i
] = readFloat_be(buffer
);
280 graphDef
->mNumParamSpecs
= readInt32_be(buffer
);
281 if (graphDef
->mNumParamSpecs
) {
282 int hashTableSize
= NEXTPOWEROFTWO(graphDef
->mNumParamSpecs
);
283 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, hashTableSize
, false);
284 graphDef
->mParamSpecs
= (ParamSpec
*)malloc(graphDef
->mNumParamSpecs
* sizeof(ParamSpec
));
285 for (uint32 i
=0; i
<graphDef
->mNumParamSpecs
; ++i
) {
286 ParamSpec
*paramSpec
= graphDef
->mParamSpecs
+ i
;
287 ParamSpec_Read(paramSpec
, buffer
);
288 graphDef
->mParamSpecTable
->Add(paramSpec
);
291 // empty table to eliminate test in Graph_SetControl
292 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, 4, false);
293 graphDef
->mParamSpecs
= 0;
296 graphDef
->mNumWires
= graphDef
->mNumConstants
;
297 graphDef
->mNumUnitSpecs
= readInt32_be(buffer
);
298 graphDef
->mUnitSpecs
= (UnitSpec
*)malloc(sizeof(UnitSpec
) * graphDef
->mNumUnitSpecs
);
299 graphDef
->mNumCalcUnits
= 0;
300 for (uint32 i
=0; i
<graphDef
->mNumUnitSpecs
; ++i
) {
301 UnitSpec
*unitSpec
= graphDef
->mUnitSpecs
+ i
;
302 UnitSpec_Read(unitSpec
, buffer
);
304 switch (unitSpec
->mCalcRate
)
306 case calc_ScalarRate
:
307 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
310 graphDef
->mNumCalcUnits
++;
311 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
314 graphDef
->mNumCalcUnits
++;
315 unitSpec
->mRateInfo
= &inWorld
->mFullRate
;
317 case calc_DemandRate
:
318 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
322 graphDef
->mNodeDef
.mAllocSize
+= unitSpec
->mAllocSize
;
323 graphDef
->mNumWires
+= unitSpec
->mNumOutputs
;
326 DoBufferColoring(inWorld
, graphDef
);
328 graphDef
->mWiresAllocSize
= graphDef
->mNumWires
* sizeof(Wire
);
329 graphDef
->mUnitsAllocSize
= graphDef
->mNumUnitSpecs
* sizeof(Unit
*);
330 graphDef
->mCalcUnitsAllocSize
= graphDef
->mNumCalcUnits
* sizeof(Unit
*);
332 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mWiresAllocSize
;
333 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mUnitsAllocSize
;
334 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mCalcUnitsAllocSize
;
336 graphDef
->mControlAllocSize
= graphDef
->mNumControls
* sizeof(float);
337 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mControlAllocSize
;
339 graphDef
->mMapControlsAllocSize
= graphDef
->mNumControls
* sizeof(float*);
340 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlsAllocSize
;
342 graphDef
->mMapControlRatesAllocSize
= graphDef
->mNumControls
* sizeof(int*);
343 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlRatesAllocSize
;
346 graphDef
->mNext
= inList
;
347 graphDef
->mRefCount
= 1;
349 graphDef
->mNumVariants
= readInt16_be(buffer
);
350 if (graphDef
->mNumVariants
) {
351 graphDef
->mVariants
= (GraphDef
*)calloc(graphDef
->mNumVariants
, sizeof(GraphDef
));
352 for (uint32 i
=0; i
<graphDef
->mNumVariants
; ++i
) {
353 GraphDef_ReadVariant(inWorld
, buffer
, graphDef
, graphDef
->mVariants
+ i
);
361 GraphDef
* GraphDef_ReadVer1(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
)
363 int32 name
[kSCNodeDefNameLen
];
364 ReadNodeDefName(buffer
, name
);
366 GraphDef
* graphDef
= (GraphDef
*)calloc(1, sizeof(GraphDef
));
368 graphDef
->mOriginal
= graphDef
;
370 graphDef
->mNodeDef
.mAllocSize
= sizeof(Graph
);
372 memcpy((char*)graphDef
->mNodeDef
.mName
, (char*)name
, kSCNodeDefNameByteLen
);
374 graphDef
->mNodeDef
.mHash
= Hash(graphDef
->mNodeDef
.mName
);
376 graphDef
->mNumConstants
= readInt16_be(buffer
);
377 graphDef
->mConstants
= (float*)malloc(graphDef
->mNumConstants
* sizeof(float));
378 for (uint32 i
=0; i
<graphDef
->mNumConstants
; ++i
) {
379 graphDef
->mConstants
[i
] = readFloat_be(buffer
);
382 graphDef
->mNumControls
= readInt16_be(buffer
);
383 graphDef
->mInitialControlValues
= (float32
*)malloc(sizeof(float32
) * graphDef
->mNumControls
);
384 for (uint32 i
=0; i
<graphDef
->mNumControls
; ++i
) {
385 graphDef
->mInitialControlValues
[i
] = readFloat_be(buffer
);
388 graphDef
->mNumParamSpecs
= readInt16_be(buffer
);
389 if (graphDef
->mNumParamSpecs
) {
390 int hashTableSize
= NEXTPOWEROFTWO(graphDef
->mNumParamSpecs
);
391 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, hashTableSize
, false);
392 graphDef
->mParamSpecs
= (ParamSpec
*)malloc(graphDef
->mNumParamSpecs
* sizeof(ParamSpec
));
393 for (uint32 i
=0; i
<graphDef
->mNumParamSpecs
; ++i
) {
394 ParamSpec
*paramSpec
= graphDef
->mParamSpecs
+ i
;
395 ParamSpec_ReadVer1(paramSpec
, buffer
);
396 graphDef
->mParamSpecTable
->Add(paramSpec
);
399 // empty table to eliminate test in Graph_SetControl
400 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, 4, false);
401 graphDef
->mParamSpecs
= 0;
404 graphDef
->mNumWires
= graphDef
->mNumConstants
;
405 graphDef
->mNumUnitSpecs
= readInt16_be(buffer
);
406 graphDef
->mUnitSpecs
= (UnitSpec
*)malloc(sizeof(UnitSpec
) * graphDef
->mNumUnitSpecs
);
407 graphDef
->mNumCalcUnits
= 0;
408 for (uint32 i
=0; i
<graphDef
->mNumUnitSpecs
; ++i
) {
409 UnitSpec
*unitSpec
= graphDef
->mUnitSpecs
+ i
;
410 UnitSpec_ReadVer1(unitSpec
, buffer
);
412 switch (unitSpec
->mCalcRate
)
414 case calc_ScalarRate
:
415 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
418 graphDef
->mNumCalcUnits
++;
419 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
422 graphDef
->mNumCalcUnits
++;
423 unitSpec
->mRateInfo
= &inWorld
->mFullRate
;
425 case calc_DemandRate
:
426 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
430 graphDef
->mNodeDef
.mAllocSize
+= unitSpec
->mAllocSize
;
431 graphDef
->mNumWires
+= unitSpec
->mNumOutputs
;
434 DoBufferColoring(inWorld
, graphDef
);
436 graphDef
->mWiresAllocSize
= graphDef
->mNumWires
* sizeof(Wire
);
437 graphDef
->mUnitsAllocSize
= graphDef
->mNumUnitSpecs
* sizeof(Unit
*);
438 graphDef
->mCalcUnitsAllocSize
= graphDef
->mNumCalcUnits
* sizeof(Unit
*);
440 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mWiresAllocSize
;
441 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mUnitsAllocSize
;
442 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mCalcUnitsAllocSize
;
444 graphDef
->mControlAllocSize
= graphDef
->mNumControls
* sizeof(float);
445 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mControlAllocSize
;
447 graphDef
->mMapControlsAllocSize
= graphDef
->mNumControls
* sizeof(float*);
448 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlsAllocSize
;
450 graphDef
->mMapControlRatesAllocSize
= graphDef
->mNumControls
* sizeof(int*);
451 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlRatesAllocSize
;
454 graphDef
->mNext
= inList
;
455 graphDef
->mRefCount
= 1;
457 if (inVersion
>= 1) {
458 graphDef
->mNumVariants
= readInt16_be(buffer
);
459 if (graphDef
->mNumVariants
) {
460 graphDef
->mVariants
= (GraphDef
*)calloc(graphDef
->mNumVariants
, sizeof(GraphDef
));
461 for (uint32 i
=0; i
<graphDef
->mNumVariants
; ++i
) {
462 GraphDef_ReadVariant(inWorld
, buffer
, graphDef
, graphDef
->mVariants
+ i
);
471 void GraphDef_Define(World
*inWorld
, GraphDef
*inList
)
473 GraphDef
*graphDef
= inList
;
475 GraphDef
*next
= graphDef
->mNext
;
477 GraphDef
* previousDef
= World_GetGraphDef(inWorld
, graphDef
->mNodeDef
.mName
);
479 World_RemoveGraphDef(inWorld
, previousDef
);
480 if (--previousDef
->mRefCount
== 0) {
481 GraphDef_DeleteMsg(inWorld
, previousDef
);
484 World_AddGraphDef(inWorld
, graphDef
);
490 void GraphDef_Remove(World
*inWorld
, int32
*inName
)
492 GraphDef
* graphDef
= World_GetGraphDef(inWorld
, inName
);
494 World_RemoveGraphDef(inWorld
, graphDef
);
495 if (--graphDef
->mRefCount
== 0) {
496 GraphDef_DeleteMsg(inWorld
, graphDef
);
501 void GraphDef_DeleteMsg(World
*inWorld
, GraphDef
*inDef
)
503 DeleteGraphDefMsg msg
;
505 inWorld
->hw
->mDeleteGraphDefs
.Write(msg
);
507 small_scpacket packet
;
508 packet
.adds("/d_removed");
512 packet
.adds((char*)inDef
->mNodeDef
.mName
);
514 ReplyAddress
*users
= inWorld
->hw
->mUsers
;
515 int numUsers
= inWorld
->hw
->mNumUsers
;
516 for (int i
=0; i
<numUsers
; ++i
) {
517 SendReply(users
+i
, packet
.data(), packet
.size());
521 GraphDef
* GraphDef_Recv(World
*inWorld
, char *buffer
, GraphDef
*inList
)
525 inList
= GraphDefLib_Read(inWorld
, buffer
, inList
);
526 } catch (std::exception
& exc
) {
527 scprintf("exception in GraphDef_Recv: %s\n", exc
.what());
529 scprintf("unknown exception in GraphDef_Recv\n");
535 GraphDef
* GraphDef_LoadGlob(World
*inWorld
, const char *pattern
, GraphDef
*inList
)
537 SC_GlobHandle
* glob
= sc_Glob(pattern
);
538 if (!glob
) return inList
;
540 const char* filename
;
541 while ((filename
= sc_GlobNext(glob
)) != 0) {
542 int len
= strlen(filename
);
543 if (strncmp(filename
+len
-9, ".scsyndef", 9)==0) {
544 inList
= GraphDef_Load(inWorld
, filename
, inList
);
547 GraphDef_Load(inWorld
, filename
, inList
);
554 GraphDef
* GraphDef_Load(World
*inWorld
, const char *filename
, GraphDef
*inList
)
556 FILE *file
= fopen(filename
, "rb");
559 scprintf("*** ERROR: can't fopen '%s'\n", filename
);
563 fseek(file
, 0, SEEK_END
);
564 int size
= ftell(file
);
565 char *buffer
= (char*)malloc(size
);
567 scprintf("*** ERROR: can't malloc buffer size %d\n", size
);
571 fseek(file
, 0, SEEK_SET
);
573 size_t readSize
= fread(buffer
, 1, size
, file
);
576 if (readSize
!= size
) {
577 scprintf("*** ERROR: invalid fread\n", size
);
583 inList
= GraphDefLib_Read(inWorld
, buffer
, inList
);
584 } catch (std::exception
& exc
) {
585 scprintf("exception in GrafDef_Load: %s\n", exc
.what());
586 scprintf("while reading file '%s'\n", filename
);
588 scprintf("unknown exception in GrafDef_Load\n");
589 scprintf("while reading file '%s'\n", filename
);
597 GraphDef
* GraphDef_LoadDir(World
*inWorld
, char *dirname
, GraphDef
*inList
)
599 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
601 scprintf("*** ERROR: open directory failed '%s'\n", dirname
);
606 char diritem
[MAXPATHLEN
];
607 bool skipItem
= false;
608 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
609 if (!validItem
) break;
610 if (skipItem
) continue;
612 if (sc_DirectoryExists(diritem
)) {
613 inList
= GraphDef_LoadDir(inWorld
, diritem
, inList
);
615 int dnamelen
= strlen(diritem
);
616 if (strncmp(diritem
+dnamelen
-9, ".scsyndef", 9) == 0) {
617 inList
= GraphDef_Load(inWorld
, diritem
, inList
);
626 void UnitSpec_Free(UnitSpec
*inUnitSpec
);
627 void UnitSpec_Free(UnitSpec
*inUnitSpec
)
629 free(inUnitSpec
->mInputSpec
);
630 free(inUnitSpec
->mOutputSpec
);
633 void GraphDef_Free(GraphDef
*inGraphDef
)
635 if (inGraphDef
!= inGraphDef
->mOriginal
) return;
637 for (uint32 i
=0; i
<inGraphDef
->mNumUnitSpecs
; ++i
) {
638 UnitSpec_Free(inGraphDef
->mUnitSpecs
+ i
);
640 for (uint32 i
=0; i
<inGraphDef
->mNumVariants
; ++i
) {
641 free(inGraphDef
->mVariants
[i
].mInitialControlValues
);
643 delete inGraphDef
->mParamSpecTable
;
644 free(inGraphDef
->mParamSpecs
);
645 free(inGraphDef
->mInitialControlValues
);
646 free(inGraphDef
->mConstants
);
647 free(inGraphDef
->mUnitSpecs
);
648 free(inGraphDef
->mVariants
);
652 void NodeDef_Dump(NodeDef
*inNodeDef
)
654 scprintf("mName '%s'\n", (char*)inNodeDef
->mName
);
655 scprintf("mHash %d\n", inNodeDef
->mHash
);
656 scprintf("mAllocSize %lu\n", inNodeDef
->mAllocSize
);
659 void GraphDef_Dump(GraphDef
*inGraphDef
)
661 NodeDef_Dump(&inGraphDef
->mNodeDef
);
663 scprintf("mNumControls %d\n", inGraphDef
->mNumControls
);
664 scprintf("mNumWires %d\n", inGraphDef
->mNumWires
);
665 scprintf("mNumUnitSpecs %d\n", inGraphDef
->mNumUnitSpecs
);
666 scprintf("mNumWireBufs %d\n", inGraphDef
->mNumWireBufs
);
668 for (uint32 i
=0; i
<inGraphDef
->mNumControls
; ++i
) {
669 scprintf(" %d mInitialControlValues %g\n", i
, inGraphDef
->mInitialControlValues
[i
]);
672 for (uint32 i
=0; i
<inGraphDef
->mNumWires
; ++i
) {
673 //WireSpec_Dump(inGraphDef->mWireSpec + i);
675 for (uint32 i
=0; i
<inGraphDef
->mNumUnitSpecs
; ++i
) {
676 //UnitSpec_Dump(inGraphDef->mUnitSpecs + i);
683 var nextBufIndex = 0;
695 if (stack.size > 0, {
696 bufNumber = stack.pop
698 bufNumber = nextBufIndex;
699 nextBufIndex = nextBufIndex + 1;
701 refs.add(bufNumber, count);
704 release { arg bufNumber;
705 refs.remove(bufNumber);
706 if (refs.includes(bufNumber).not, { stack = stack.add(bufNumber) });
708 numBufs { ^nextBufIndex }
712 struct BufColorAllocator
722 ~BufColorAllocator();
724 uint32
alloc(uint32 count
);
725 bool release(int inIndex
);
726 int NumBufs() { return nextIndex
; }
729 inline BufColorAllocator::BufColorAllocator()
733 refs
= (int16
*)calloc(refsMaxSize
, sizeof(int16
));
734 stack
= (int16
*)calloc(stackMaxSize
, sizeof(int16
));
739 inline BufColorAllocator::~BufColorAllocator()
745 inline uint32
BufColorAllocator::alloc(uint32 count
)
749 outIndex
= stack
[--stackPtr
];
751 outIndex
= nextIndex
++;
753 if (outIndex
>= refsMaxSize
) {
754 refs
= (int16
*)realloc(refs
, refsMaxSize
*2*sizeof(int16
));
755 memset(refs
+ refsMaxSize
, 0, refsMaxSize
*sizeof(int16
));
758 refs
[outIndex
] = count
;
762 inline bool BufColorAllocator::release(int inIndex
)
764 if (refs
[inIndex
] == 0) return false;
765 if (--refs
[inIndex
] == 0) {
766 if (stackPtr
>= stackMaxSize
) {
767 stack
= (int16
*)realloc(stack
, stackMaxSize
*2*sizeof(int16
));
768 memset(stack
+ stackMaxSize
, 0, stackMaxSize
*sizeof(int16
));
771 stack
[stackPtr
++] = inIndex
;
776 static void ReleaseInputBuffers(GraphDef
*inGraphDef
, UnitSpec
*unitSpec
, BufColorAllocator
& bufColor
)
778 for (int64 i
=(int64
)(unitSpec
->mNumInputs
)-1; i
>=0; --i
) {
779 InputSpec
*inputSpec
= unitSpec
->mInputSpec
+ i
;
780 if (inputSpec
->mFromUnitIndex
>= 0) {
781 UnitSpec
*outUnit
= inGraphDef
->mUnitSpecs
+ inputSpec
->mFromUnitIndex
;
782 OutputSpec
*outputSpec
= outUnit
->mOutputSpec
+ inputSpec
->mFromOutputIndex
;
783 inputSpec
->mWireIndex
= outputSpec
->mWireIndex
;
784 if (outputSpec
->mCalcRate
== calc_FullRate
) {
786 if (unitSpec
->mCalcRate
== calc_DemandRate
)
787 // we never release any input buffers of demand-rate ugens
790 if (!bufColor
.release(outputSpec
->mBufferIndex
)) {
791 scprintf("buffer coloring error: tried to release output with zero count\n");
792 scprintf("output: %d %s %d\n", inputSpec
->mFromUnitIndex
,
793 outUnit
->mUnitDef
->mUnitDefName
, inputSpec
->mFromOutputIndex
);
794 scprintf("input: %s %d\n", unitSpec
->mUnitDef
->mUnitDefName
, i
);
795 throw std::runtime_error("buffer coloring error.");
799 inputSpec
->mWireIndex
= inputSpec
->mFromOutputIndex
;
804 static void AllocOutputBuffers(UnitSpec
*unitSpec
, BufColorAllocator
& bufColor
, int32
& wireIndexCtr
)
806 //scprintf("AllocOutputBuffers %s numoutputs %d\n", unitSpec->mUnitDef->mUnitDefName, unitSpec->mNumOutputs);
807 for (uint32 i
=0; i
<unitSpec
->mNumOutputs
; ++i
) {
808 OutputSpec
*outputSpec
= unitSpec
->mOutputSpec
+ i
;
809 outputSpec
->mWireIndex
= wireIndexCtr
++;
810 if (outputSpec
->mCalcRate
== calc_FullRate
) {
811 uint32 bufIndex
= bufColor
.alloc(outputSpec
->mNumConsumers
);
812 outputSpec
->mBufferIndex
= bufIndex
;
817 void DoBufferColoring(World
*inWorld
, GraphDef
*inGraphDef
)
819 // count consumers of outputs
820 for (uint32 j
=0; j
<inGraphDef
->mNumUnitSpecs
; ++j
) {
821 UnitSpec
*unitSpec
= inGraphDef
->mUnitSpecs
+ j
;
822 for (uint32 i
=0; i
<unitSpec
->mNumInputs
; ++i
) {
823 InputSpec
*inputSpec
= unitSpec
->mInputSpec
+ i
;
824 if (inputSpec
->mFromUnitIndex
>= 0) {
825 UnitSpec
*outUnit
= inGraphDef
->mUnitSpecs
+ inputSpec
->mFromUnitIndex
;
826 OutputSpec
*outputSpec
= outUnit
->mOutputSpec
+ inputSpec
->mFromOutputIndex
;
827 outputSpec
->mNumConsumers
++;
834 BufColorAllocator bufColor
;
835 int32 wireIndexCtr
= inGraphDef
->mNumConstants
; // mNumConstants is a uint32, but limited to int32 in OSC
836 for (uint32 j
=0; j
<inGraphDef
->mNumUnitSpecs
; ++j
) {
837 UnitSpec
*unitSpec
= inGraphDef
->mUnitSpecs
+ j
;
838 if (unitSpec
->mUnitDef
->mFlags
& kUnitDef_CantAliasInputsToOutputs
) {
839 // set wire index, alloc outputs
840 AllocOutputBuffers(unitSpec
, bufColor
, wireIndexCtr
);
841 // set wire index, release inputs
842 ReleaseInputBuffers(inGraphDef
, unitSpec
, bufColor
);
844 // set wire index, release inputs
845 ReleaseInputBuffers(inGraphDef
, unitSpec
, bufColor
);
846 // set wire index, alloc outputs
847 AllocOutputBuffers(unitSpec
, bufColor
, wireIndexCtr
);
851 inGraphDef
->mNumWireBufs
= bufColor
.NumBufs();
852 if (inWorld
->mRunning
)
854 // cannot reallocate interconnect buffers while running audio.
855 if (inGraphDef
->mNumWireBufs
> inWorld
->hw
->mMaxWireBufs
) {
856 throw std::runtime_error("exceeded number of interconnect buffers.");
859 inWorld
->hw
->mMaxWireBufs
= sc_max(inWorld
->hw
->mMaxWireBufs
, inGraphDef
->mNumWireBufs
);
863 // multiply buf indices by buf length for proper offset
864 int bufLength
= inWorld
->mBufLength
;
865 for (uint32 j
=0; j
<inGraphDef
->mNumUnitSpecs
; ++j
) {
866 UnitSpec
*unitSpec
= inGraphDef
->mUnitSpecs
+ j
;
867 for (uint32 i
=0; i
<unitSpec
->mNumOutputs
; ++i
) {
868 OutputSpec
*outputSpec
= unitSpec
->mOutputSpec
+ i
;
869 if (outputSpec
->mCalcRate
== calc_FullRate
) {
870 outputSpec
->mBufferIndex
*= bufLength
;