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"
33 #include "ReadWriteMacros.h"
34 #include "SC_Prototypes.h"
35 #include "SC_CoreAudio.h"
36 #include "SC_DirUtils.h"
39 #include "SC_Win32Utils.h"
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
= readInt32_be(buffer
);
94 inParamSpec
->mHash
= Hash(inParamSpec
->mName
);
97 void ParamSpec_ReadVer1(ParamSpec
* inParamSpec
, char*& buffer
);
98 void ParamSpec_ReadVer1(ParamSpec
* inParamSpec
, char*& buffer
)
100 ReadName(buffer
, inParamSpec
->mName
);
101 inParamSpec
->mIndex
= readInt16_be(buffer
);
102 inParamSpec
->mHash
= Hash(inParamSpec
->mName
);
105 void InputSpec_Read(InputSpec
* inInputSpec
, char*& buffer
);
106 void InputSpec_Read(InputSpec
* inInputSpec
, char*& buffer
)
108 inInputSpec
->mFromUnitIndex
= readInt32_be(buffer
);
109 inInputSpec
->mFromOutputIndex
= readInt32_be(buffer
);
111 inInputSpec
->mWireIndex
= -1;
114 void InputSpec_ReadVer1(InputSpec
* inInputSpec
, char*& buffer
);
115 void InputSpec_ReadVer1(InputSpec
* inInputSpec
, char*& buffer
)
117 inInputSpec
->mFromUnitIndex
= (int16
)readInt16_be(buffer
);
118 inInputSpec
->mFromOutputIndex
= (int16
)readInt16_be(buffer
);
120 inInputSpec
->mWireIndex
= -1;
123 void OutputSpec_Read(OutputSpec
* inOutputSpec
, char*& buffer
);
124 void OutputSpec_Read(OutputSpec
* inOutputSpec
, char*& buffer
)
126 inOutputSpec
->mCalcRate
= readInt8(buffer
);
127 inOutputSpec
->mWireIndex
= -1;
128 inOutputSpec
->mBufferIndex
= -1;
129 inOutputSpec
->mNumConsumers
= 0;
132 void UnitSpec_Read(UnitSpec
* inUnitSpec
, char*& buffer
);
133 void UnitSpec_Read(UnitSpec
* inUnitSpec
, char*& buffer
)
135 int32 name
[kSCNameLen
];
136 ReadName(buffer
, name
);
138 inUnitSpec
->mUnitDef
= GetUnitDef(name
);
139 if (!inUnitSpec
->mUnitDef
) {
141 sprintf(str
, "UGen '%s' not installed.", (char*)name
);
142 throw std::runtime_error(str
);
145 inUnitSpec
->mCalcRate
= readInt8(buffer
);
147 inUnitSpec
->mNumInputs
= readInt32_be(buffer
);
148 inUnitSpec
->mNumOutputs
= readInt32_be(buffer
);
149 inUnitSpec
->mSpecialIndex
= readInt16_be(buffer
);
150 inUnitSpec
->mInputSpec
= (InputSpec
*)malloc(sizeof(InputSpec
) * inUnitSpec
->mNumInputs
);
151 inUnitSpec
->mOutputSpec
= (OutputSpec
*)malloc(sizeof(OutputSpec
) * inUnitSpec
->mNumOutputs
);
152 for (uint32 i
=0; i
<inUnitSpec
->mNumInputs
; ++i
) {
153 InputSpec_Read(inUnitSpec
->mInputSpec
+ i
, buffer
);
155 for (uint32 i
=0; i
<inUnitSpec
->mNumOutputs
; ++i
) {
156 OutputSpec_Read(inUnitSpec
->mOutputSpec
+ i
, buffer
);
158 uint64 numPorts
= inUnitSpec
->mNumInputs
+ inUnitSpec
->mNumOutputs
;
159 inUnitSpec
->mAllocSize
= inUnitSpec
->mUnitDef
->mAllocSize
+ numPorts
* (sizeof(Wire
*) + sizeof(float*));
162 void UnitSpec_ReadVer1(UnitSpec
* inUnitSpec
, char*& buffer
);
163 void UnitSpec_ReadVer1(UnitSpec
* inUnitSpec
, char*& buffer
)
165 int32 name
[kSCNameLen
];
166 ReadName(buffer
, name
);
168 inUnitSpec
->mUnitDef
= GetUnitDef(name
);
169 if (!inUnitSpec
->mUnitDef
) {
171 sprintf(str
, "UGen '%s' not installed.", (char*)name
);
172 throw std::runtime_error(str
);
175 inUnitSpec
->mCalcRate
= readInt8(buffer
);
177 inUnitSpec
->mNumInputs
= readInt16_be(buffer
);
178 inUnitSpec
->mNumOutputs
= readInt16_be(buffer
);
179 inUnitSpec
->mSpecialIndex
= readInt16_be(buffer
);
180 inUnitSpec
->mInputSpec
= (InputSpec
*)malloc(sizeof(InputSpec
) * inUnitSpec
->mNumInputs
);
181 inUnitSpec
->mOutputSpec
= (OutputSpec
*)malloc(sizeof(OutputSpec
) * inUnitSpec
->mNumOutputs
);
182 for (uint32 i
=0; i
<inUnitSpec
->mNumInputs
; ++i
) {
183 InputSpec_ReadVer1(inUnitSpec
->mInputSpec
+ i
, buffer
);
185 for (uint32 i
=0; i
<inUnitSpec
->mNumOutputs
; ++i
) {
186 OutputSpec_Read(inUnitSpec
->mOutputSpec
+ i
, buffer
);
188 uint64 numPorts
= inUnitSpec
->mNumInputs
+ inUnitSpec
->mNumOutputs
;
189 inUnitSpec
->mAllocSize
= inUnitSpec
->mUnitDef
->mAllocSize
+ numPorts
* (sizeof(Wire
*) + sizeof(float*));
192 GraphDef
* GraphDef_Read(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
);
193 GraphDef
* GraphDef_ReadVer1(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
);
195 GraphDef
* GraphDefLib_Read(World
*inWorld
, char* buffer
, GraphDef
* inList
);
196 GraphDef
* GraphDefLib_Read(World
*inWorld
, char* buffer
, GraphDef
* inList
)
198 int32 magic
= readInt32_be(buffer
);
199 if (magic
!= (('S'<<24)|('C'<<16)|('g'<<8)|'f') /*'SCgf'*/) return inList
;
201 int32 version
= readInt32_be(buffer
);
206 numDefs
= readInt16_be(buffer
);
208 for (i
=0; i
<numDefs
; ++i
) {
209 inList
= GraphDef_Read(inWorld
, buffer
, inList
, version
);
215 numDefs
= readInt16_be(buffer
);
217 for (i
=0; i
<numDefs
; ++i
) {
218 inList
= GraphDef_ReadVer1(inWorld
, buffer
, inList
, version
); // handles 1 and 0
231 void ChooseMulAddFunc(GraphDef
*graphDef
, UnitSpec
* unitSpec
);
232 void DoBufferColoring(World
*inWorld
, GraphDef
*inGraphDef
);
234 void GraphDef_ReadVariant(World
*inWorld
, char*& buffer
, GraphDef
* inGraphDef
, GraphDef
* inVariant
)
236 memcpy(inVariant
, inGraphDef
, sizeof(GraphDef
));
238 inVariant
->mNumVariants
= 0;
239 inVariant
->mVariants
= 0;
241 ReadName(buffer
, inVariant
->mNodeDef
.mName
);
242 inVariant
->mNodeDef
.mHash
= Hash(inVariant
->mNodeDef
.mName
);
244 inVariant
->mInitialControlValues
= (float32
*)malloc(sizeof(float32
) * inGraphDef
->mNumControls
);
245 for (uint32 i
=0; i
<inGraphDef
->mNumControls
; ++i
) {
246 inVariant
->mInitialControlValues
[i
] = readFloat_be(buffer
);
251 GraphDef
* GraphDef_Read(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
)
253 int32 name
[kSCNodeDefNameLen
];
254 ReadNodeDefName(buffer
, name
);
256 GraphDef
* graphDef
= (GraphDef
*)calloc(1, sizeof(GraphDef
));
258 graphDef
->mOriginal
= graphDef
;
260 graphDef
->mNodeDef
.mAllocSize
= sizeof(Graph
);
262 memcpy((char*)graphDef
->mNodeDef
.mName
, (char*)name
, kSCNodeDefNameByteLen
);
264 graphDef
->mNodeDef
.mHash
= Hash(graphDef
->mNodeDef
.mName
);
266 graphDef
->mNumConstants
= readInt32_be(buffer
);
268 graphDef
->mConstants
= (float*)malloc(graphDef
->mNumConstants
* sizeof(float));
269 for (uint32 i
=0; i
<graphDef
->mNumConstants
; ++i
) {
270 graphDef
->mConstants
[i
] = readFloat_be(buffer
);
273 graphDef
->mNumControls
= readInt32_be(buffer
);
274 graphDef
->mInitialControlValues
= (float32
*)malloc(sizeof(float32
) * graphDef
->mNumControls
);
275 for (uint32 i
=0; i
<graphDef
->mNumControls
; ++i
) {
276 graphDef
->mInitialControlValues
[i
] = readFloat_be(buffer
);
279 graphDef
->mNumParamSpecs
= readInt32_be(buffer
);
280 if (graphDef
->mNumParamSpecs
) {
281 int hashTableSize
= NEXTPOWEROFTWO(graphDef
->mNumParamSpecs
);
282 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, hashTableSize
, false);
283 graphDef
->mParamSpecs
= (ParamSpec
*)malloc(graphDef
->mNumParamSpecs
* sizeof(ParamSpec
));
284 for (uint32 i
=0; i
<graphDef
->mNumParamSpecs
; ++i
) {
285 ParamSpec
*paramSpec
= graphDef
->mParamSpecs
+ i
;
286 ParamSpec_Read(paramSpec
, buffer
);
287 graphDef
->mParamSpecTable
->Add(paramSpec
);
290 // empty table to eliminate test in Graph_SetControl
291 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, 4, false);
292 graphDef
->mParamSpecs
= 0;
295 graphDef
->mNumWires
= graphDef
->mNumConstants
;
296 graphDef
->mNumUnitSpecs
= readInt32_be(buffer
);
297 graphDef
->mUnitSpecs
= (UnitSpec
*)malloc(sizeof(UnitSpec
) * graphDef
->mNumUnitSpecs
);
298 graphDef
->mNumCalcUnits
= 0;
299 for (uint32 i
=0; i
<graphDef
->mNumUnitSpecs
; ++i
) {
300 UnitSpec
*unitSpec
= graphDef
->mUnitSpecs
+ i
;
301 UnitSpec_Read(unitSpec
, buffer
);
303 switch (unitSpec
->mCalcRate
)
305 case calc_ScalarRate
:
306 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
309 graphDef
->mNumCalcUnits
++;
310 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
313 graphDef
->mNumCalcUnits
++;
314 unitSpec
->mRateInfo
= &inWorld
->mFullRate
;
316 case calc_DemandRate
:
317 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
321 graphDef
->mNodeDef
.mAllocSize
+= unitSpec
->mAllocSize
;
322 graphDef
->mNumWires
+= unitSpec
->mNumOutputs
;
325 DoBufferColoring(inWorld
, graphDef
);
327 graphDef
->mWiresAllocSize
= graphDef
->mNumWires
* sizeof(Wire
);
328 graphDef
->mUnitsAllocSize
= graphDef
->mNumUnitSpecs
* sizeof(Unit
*);
329 graphDef
->mCalcUnitsAllocSize
= graphDef
->mNumCalcUnits
* sizeof(Unit
*);
331 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mWiresAllocSize
;
332 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mUnitsAllocSize
;
333 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mCalcUnitsAllocSize
;
335 graphDef
->mControlAllocSize
= graphDef
->mNumControls
* sizeof(float);
336 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mControlAllocSize
;
338 graphDef
->mMapControlsAllocSize
= graphDef
->mNumControls
* sizeof(float*);
339 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlsAllocSize
;
341 graphDef
->mMapControlRatesAllocSize
= graphDef
->mNumControls
* sizeof(int*);
342 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlRatesAllocSize
;
345 graphDef
->mNext
= inList
;
346 graphDef
->mRefCount
= 1;
348 graphDef
->mNumVariants
= readInt16_be(buffer
);
349 if (graphDef
->mNumVariants
) {
350 graphDef
->mVariants
= (GraphDef
*)calloc(graphDef
->mNumVariants
, sizeof(GraphDef
));
351 for (uint32 i
=0; i
<graphDef
->mNumVariants
; ++i
) {
352 GraphDef_ReadVariant(inWorld
, buffer
, graphDef
, graphDef
->mVariants
+ i
);
360 GraphDef
* GraphDef_ReadVer1(World
*inWorld
, char*& buffer
, GraphDef
* inList
, int32 inVersion
)
362 int32 name
[kSCNodeDefNameLen
];
363 ReadNodeDefName(buffer
, name
);
365 GraphDef
* graphDef
= (GraphDef
*)calloc(1, sizeof(GraphDef
));
367 graphDef
->mOriginal
= graphDef
;
369 graphDef
->mNodeDef
.mAllocSize
= sizeof(Graph
);
371 memcpy((char*)graphDef
->mNodeDef
.mName
, (char*)name
, kSCNodeDefNameByteLen
);
373 graphDef
->mNodeDef
.mHash
= Hash(graphDef
->mNodeDef
.mName
);
375 graphDef
->mNumConstants
= readInt16_be(buffer
);
376 graphDef
->mConstants
= (float*)malloc(graphDef
->mNumConstants
* sizeof(float));
377 for (uint32 i
=0; i
<graphDef
->mNumConstants
; ++i
) {
378 graphDef
->mConstants
[i
] = readFloat_be(buffer
);
381 graphDef
->mNumControls
= readInt16_be(buffer
);
382 graphDef
->mInitialControlValues
= (float32
*)malloc(sizeof(float32
) * graphDef
->mNumControls
);
383 for (uint32 i
=0; i
<graphDef
->mNumControls
; ++i
) {
384 graphDef
->mInitialControlValues
[i
] = readFloat_be(buffer
);
387 graphDef
->mNumParamSpecs
= readInt16_be(buffer
);
388 if (graphDef
->mNumParamSpecs
) {
389 int hashTableSize
= NEXTPOWEROFTWO(graphDef
->mNumParamSpecs
);
390 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, hashTableSize
, false);
391 graphDef
->mParamSpecs
= (ParamSpec
*)malloc(graphDef
->mNumParamSpecs
* sizeof(ParamSpec
));
392 for (uint32 i
=0; i
<graphDef
->mNumParamSpecs
; ++i
) {
393 ParamSpec
*paramSpec
= graphDef
->mParamSpecs
+ i
;
394 ParamSpec_ReadVer1(paramSpec
, buffer
);
395 graphDef
->mParamSpecTable
->Add(paramSpec
);
398 // empty table to eliminate test in Graph_SetControl
399 graphDef
->mParamSpecTable
= new ParamSpecTable(&gMalloc
, 4, false);
400 graphDef
->mParamSpecs
= 0;
403 graphDef
->mNumWires
= graphDef
->mNumConstants
;
404 graphDef
->mNumUnitSpecs
= readInt16_be(buffer
);
405 graphDef
->mUnitSpecs
= (UnitSpec
*)malloc(sizeof(UnitSpec
) * graphDef
->mNumUnitSpecs
);
406 graphDef
->mNumCalcUnits
= 0;
407 for (uint32 i
=0; i
<graphDef
->mNumUnitSpecs
; ++i
) {
408 UnitSpec
*unitSpec
= graphDef
->mUnitSpecs
+ i
;
409 UnitSpec_ReadVer1(unitSpec
, buffer
);
411 switch (unitSpec
->mCalcRate
)
413 case calc_ScalarRate
:
414 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
417 graphDef
->mNumCalcUnits
++;
418 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
421 graphDef
->mNumCalcUnits
++;
422 unitSpec
->mRateInfo
= &inWorld
->mFullRate
;
424 case calc_DemandRate
:
425 unitSpec
->mRateInfo
= &inWorld
->mBufRate
;
429 graphDef
->mNodeDef
.mAllocSize
+= unitSpec
->mAllocSize
;
430 graphDef
->mNumWires
+= unitSpec
->mNumOutputs
;
433 DoBufferColoring(inWorld
, graphDef
);
435 graphDef
->mWiresAllocSize
= graphDef
->mNumWires
* sizeof(Wire
);
436 graphDef
->mUnitsAllocSize
= graphDef
->mNumUnitSpecs
* sizeof(Unit
*);
437 graphDef
->mCalcUnitsAllocSize
= graphDef
->mNumCalcUnits
* sizeof(Unit
*);
439 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mWiresAllocSize
;
440 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mUnitsAllocSize
;
441 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mCalcUnitsAllocSize
;
443 graphDef
->mControlAllocSize
= graphDef
->mNumControls
* sizeof(float);
444 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mControlAllocSize
;
446 graphDef
->mMapControlsAllocSize
= graphDef
->mNumControls
* sizeof(float*);
447 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlsAllocSize
;
449 graphDef
->mMapControlRatesAllocSize
= graphDef
->mNumControls
* sizeof(int*);
450 graphDef
->mNodeDef
.mAllocSize
+= graphDef
->mMapControlRatesAllocSize
;
453 graphDef
->mNext
= inList
;
454 graphDef
->mRefCount
= 1;
456 if (inVersion
>= 1) {
457 graphDef
->mNumVariants
= readInt16_be(buffer
);
458 if (graphDef
->mNumVariants
) {
459 graphDef
->mVariants
= (GraphDef
*)calloc(graphDef
->mNumVariants
, sizeof(GraphDef
));
460 for (uint32 i
=0; i
<graphDef
->mNumVariants
; ++i
) {
461 GraphDef_ReadVariant(inWorld
, buffer
, graphDef
, graphDef
->mVariants
+ i
);
470 void GraphDef_Define(World
*inWorld
, GraphDef
*inList
)
472 GraphDef
*graphDef
= inList
;
474 GraphDef
*next
= graphDef
->mNext
;
476 GraphDef
* previousDef
= World_GetGraphDef(inWorld
, graphDef
->mNodeDef
.mName
);
478 World_RemoveGraphDef(inWorld
, previousDef
);
479 if (--previousDef
->mRefCount
== 0) {
480 GraphDef_DeleteMsg(inWorld
, previousDef
);
483 World_AddGraphDef(inWorld
, graphDef
);
489 void GraphDef_Remove(World
*inWorld
, int32
*inName
)
491 GraphDef
* graphDef
= World_GetGraphDef(inWorld
, inName
);
493 World_RemoveGraphDef(inWorld
, graphDef
);
494 if (--graphDef
->mRefCount
== 0) {
495 GraphDef_DeleteMsg(inWorld
, graphDef
);
500 void GraphDef_DeleteMsg(World
*inWorld
, GraphDef
*inDef
)
502 DeleteGraphDefMsg msg
;
504 inWorld
->hw
->mDeleteGraphDefs
.Write(msg
);
507 GraphDef
* GraphDef_Recv(World
*inWorld
, char *buffer
, GraphDef
*inList
)
511 inList
= GraphDefLib_Read(inWorld
, buffer
, inList
);
512 } catch (std::exception
& exc
) {
513 scprintf("exception in GraphDef_Recv: %s\n", exc
.what());
515 scprintf("unknown exception in GraphDef_Recv\n");
521 GraphDef
* GraphDef_LoadGlob(World
*inWorld
, const char *pattern
, GraphDef
*inList
)
523 SC_GlobHandle
* glob
= sc_Glob(pattern
);
524 if (!glob
) return inList
;
526 const char* filename
;
527 while ((filename
= sc_GlobNext(glob
)) != 0) {
528 int len
= strlen(filename
);
529 if (strncmp(filename
+len
-9, ".scsyndef", 9)==0) {
530 inList
= GraphDef_Load(inWorld
, filename
, inList
);
533 GraphDef_Load(inWorld
, filename
, inList
);
540 GraphDef
* GraphDef_Load(World
*inWorld
, const char *filename
, GraphDef
*inList
)
542 FILE *file
= fopen(filename
, "rb");
545 scprintf("*** ERROR: can't fopen '%s'\n", filename
);
549 fseek(file
, 0, SEEK_END
);
550 int size
= ftell(file
);
551 char *buffer
= (char*)malloc(size
);
553 scprintf("*** ERROR: can't malloc buffer size %d\n", size
);
557 fseek(file
, 0, SEEK_SET
);
559 size_t readSize
= fread(buffer
, 1, size
, file
);
562 if (readSize
!= size
) {
563 scprintf("*** ERROR: invalid fread\n", size
);
569 inList
= GraphDefLib_Read(inWorld
, buffer
, inList
);
570 } catch (std::exception
& exc
) {
571 scprintf("exception in GrafDef_Load: %s\n", exc
.what());
572 scprintf("while reading file '%s'\n", filename
);
574 scprintf("unknown exception in GrafDef_Load\n");
575 scprintf("while reading file '%s'\n", filename
);
583 GraphDef
* GraphDef_LoadDir(World
*inWorld
, char *dirname
, GraphDef
*inList
)
585 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
587 scprintf("*** ERROR: open directory failed '%s'\n", dirname
);
592 char diritem
[MAXPATHLEN
];
593 bool skipItem
= false;
594 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
595 if (!validItem
) break;
596 if (skipItem
) continue;
598 if (sc_DirectoryExists(diritem
)) {
599 inList
= GraphDef_LoadDir(inWorld
, diritem
, inList
);
601 int dnamelen
= strlen(diritem
);
602 if (strncmp(diritem
+dnamelen
-9, ".scsyndef", 9) == 0) {
603 inList
= GraphDef_Load(inWorld
, diritem
, inList
);
612 void UnitSpec_Free(UnitSpec
*inUnitSpec
);
613 void UnitSpec_Free(UnitSpec
*inUnitSpec
)
615 free(inUnitSpec
->mInputSpec
);
616 free(inUnitSpec
->mOutputSpec
);
619 void GraphDef_Free(GraphDef
*inGraphDef
)
621 if (inGraphDef
!= inGraphDef
->mOriginal
) return;
623 for (uint32 i
=0; i
<inGraphDef
->mNumUnitSpecs
; ++i
) {
624 UnitSpec_Free(inGraphDef
->mUnitSpecs
+ i
);
626 for (uint32 i
=0; i
<inGraphDef
->mNumVariants
; ++i
) {
627 free(inGraphDef
->mVariants
[i
].mInitialControlValues
);
629 delete inGraphDef
->mParamSpecTable
;
630 free(inGraphDef
->mParamSpecs
);
631 free(inGraphDef
->mInitialControlValues
);
632 free(inGraphDef
->mConstants
);
633 free(inGraphDef
->mUnitSpecs
);
634 free(inGraphDef
->mVariants
);
638 void NodeDef_Dump(NodeDef
*inNodeDef
)
640 scprintf("mName '%s'\n", (char*)inNodeDef
->mName
);
641 scprintf("mHash %d\n", inNodeDef
->mHash
);
642 scprintf("mAllocSize %lu\n", inNodeDef
->mAllocSize
);
645 void GraphDef_Dump(GraphDef
*inGraphDef
)
647 NodeDef_Dump(&inGraphDef
->mNodeDef
);
649 scprintf("mNumControls %d\n", inGraphDef
->mNumControls
);
650 scprintf("mNumWires %d\n", inGraphDef
->mNumWires
);
651 scprintf("mNumUnitSpecs %d\n", inGraphDef
->mNumUnitSpecs
);
652 scprintf("mNumWireBufs %d\n", inGraphDef
->mNumWireBufs
);
654 for (uint32 i
=0; i
<inGraphDef
->mNumControls
; ++i
) {
655 scprintf(" %d mInitialControlValues %g\n", i
, inGraphDef
->mInitialControlValues
[i
]);
658 for (uint32 i
=0; i
<inGraphDef
->mNumWires
; ++i
) {
659 //WireSpec_Dump(inGraphDef->mWireSpec + i);
661 for (uint32 i
=0; i
<inGraphDef
->mNumUnitSpecs
; ++i
) {
662 //UnitSpec_Dump(inGraphDef->mUnitSpecs + i);
669 var nextBufIndex = 0;
681 if (stack.size > 0, {
682 bufNumber = stack.pop
684 bufNumber = nextBufIndex;
685 nextBufIndex = nextBufIndex + 1;
687 refs.add(bufNumber, count);
690 release { arg bufNumber;
691 refs.remove(bufNumber);
692 if (refs.includes(bufNumber).not, { stack = stack.add(bufNumber) });
694 numBufs { ^nextBufIndex }
698 struct BufColorAllocator
708 ~BufColorAllocator();
710 uint32
alloc(uint32 count
);
711 bool release(int inIndex
);
712 int NumBufs() { return nextIndex
; }
715 inline BufColorAllocator::BufColorAllocator()
719 refs
= (int16
*)calloc(refsMaxSize
, sizeof(int16
));
720 stack
= (int16
*)calloc(stackMaxSize
, sizeof(int16
));
725 inline BufColorAllocator::~BufColorAllocator()
731 inline uint32
BufColorAllocator::alloc(uint32 count
)
735 outIndex
= stack
[--stackPtr
];
737 outIndex
= nextIndex
++;
739 if (outIndex
>= refsMaxSize
) {
740 refs
= (int16
*)realloc(refs
, refsMaxSize
*2*sizeof(int16
));
741 memset(refs
+ refsMaxSize
, 0, refsMaxSize
*sizeof(int16
));
744 refs
[outIndex
] = count
;
748 inline bool BufColorAllocator::release(int inIndex
)
750 if (refs
[inIndex
] == 0) return false;
751 if (--refs
[inIndex
] == 0) {
752 if (stackPtr
>= stackMaxSize
) {
753 stack
= (int16
*)realloc(stack
, stackMaxSize
*2*sizeof(int16
));
754 memset(stack
+ stackMaxSize
, 0, stackMaxSize
*sizeof(int16
));
757 stack
[stackPtr
++] = inIndex
;
762 static void ReleaseInputBuffers(GraphDef
*inGraphDef
, UnitSpec
*unitSpec
, BufColorAllocator
& bufColor
)
764 for (int64 i
=(int64
)(unitSpec
->mNumInputs
)-1; i
>=0; --i
) {
765 InputSpec
*inputSpec
= unitSpec
->mInputSpec
+ i
;
766 if (inputSpec
->mFromUnitIndex
>= 0) {
767 UnitSpec
*outUnit
= inGraphDef
->mUnitSpecs
+ inputSpec
->mFromUnitIndex
;
768 OutputSpec
*outputSpec
= outUnit
->mOutputSpec
+ inputSpec
->mFromOutputIndex
;
769 inputSpec
->mWireIndex
= outputSpec
->mWireIndex
;
770 if (outputSpec
->mCalcRate
== calc_FullRate
) {
772 if (unitSpec
->mCalcRate
== calc_DemandRate
)
773 // we never release any input buffers of demand-rate ugens
776 if (!bufColor
.release(outputSpec
->mBufferIndex
)) {
777 scprintf("buffer coloring error: tried to release output with zero count\n");
778 scprintf("output: %d %s %d\n", inputSpec
->mFromUnitIndex
,
779 outUnit
->mUnitDef
->mUnitDefName
, inputSpec
->mFromOutputIndex
);
780 scprintf("input: %s %d\n", unitSpec
->mUnitDef
->mUnitDefName
, i
);
781 throw std::runtime_error("buffer coloring error.");
785 inputSpec
->mWireIndex
= inputSpec
->mFromOutputIndex
;
790 static void AllocOutputBuffers(UnitSpec
*unitSpec
, BufColorAllocator
& bufColor
, int32
& wireIndexCtr
)
792 //scprintf("AllocOutputBuffers %s numoutputs %d\n", unitSpec->mUnitDef->mUnitDefName, unitSpec->mNumOutputs);
793 for (uint32 i
=0; i
<unitSpec
->mNumOutputs
; ++i
) {
794 OutputSpec
*outputSpec
= unitSpec
->mOutputSpec
+ i
;
795 outputSpec
->mWireIndex
= wireIndexCtr
++;
796 if (outputSpec
->mCalcRate
== calc_FullRate
) {
797 uint32 bufIndex
= bufColor
.alloc(outputSpec
->mNumConsumers
);
798 outputSpec
->mBufferIndex
= bufIndex
;
803 void DoBufferColoring(World
*inWorld
, GraphDef
*inGraphDef
)
805 // count consumers of outputs
806 for (uint32 j
=0; j
<inGraphDef
->mNumUnitSpecs
; ++j
) {
807 UnitSpec
*unitSpec
= inGraphDef
->mUnitSpecs
+ j
;
808 for (uint32 i
=0; i
<unitSpec
->mNumInputs
; ++i
) {
809 InputSpec
*inputSpec
= unitSpec
->mInputSpec
+ i
;
810 if (inputSpec
->mFromUnitIndex
>= 0) {
811 UnitSpec
*outUnit
= inGraphDef
->mUnitSpecs
+ inputSpec
->mFromUnitIndex
;
812 OutputSpec
*outputSpec
= outUnit
->mOutputSpec
+ inputSpec
->mFromOutputIndex
;
813 outputSpec
->mNumConsumers
++;
820 BufColorAllocator bufColor
;
821 int32 wireIndexCtr
= inGraphDef
->mNumConstants
; // mNumConstants is a uint32, but limited to int32 in OSC
822 for (uint32 j
=0; j
<inGraphDef
->mNumUnitSpecs
; ++j
) {
823 UnitSpec
*unitSpec
= inGraphDef
->mUnitSpecs
+ j
;
824 if (unitSpec
->mUnitDef
->mFlags
& kUnitDef_CantAliasInputsToOutputs
) {
825 // set wire index, alloc outputs
826 AllocOutputBuffers(unitSpec
, bufColor
, wireIndexCtr
);
827 // set wire index, release inputs
828 ReleaseInputBuffers(inGraphDef
, unitSpec
, bufColor
);
830 // set wire index, release inputs
831 ReleaseInputBuffers(inGraphDef
, unitSpec
, bufColor
);
832 // set wire index, alloc outputs
833 AllocOutputBuffers(unitSpec
, bufColor
, wireIndexCtr
);
837 inGraphDef
->mNumWireBufs
= bufColor
.NumBufs();
838 if (inWorld
->mRunning
)
840 // cannot reallocate interconnect buffers while running audio.
841 if (inGraphDef
->mNumWireBufs
> inWorld
->hw
->mMaxWireBufs
) {
842 throw std::runtime_error("exceeded number of interconnect buffers.");
845 inWorld
->hw
->mMaxWireBufs
= sc_max(inWorld
->hw
->mMaxWireBufs
, inGraphDef
->mNumWireBufs
);
849 // multiply buf indices by buf length for proper offset
850 int bufLength
= inWorld
->mBufLength
;
851 for (uint32 j
=0; j
<inGraphDef
->mNumUnitSpecs
; ++j
) {
852 UnitSpec
*unitSpec
= inGraphDef
->mUnitSpecs
+ j
;
853 for (uint32 i
=0; i
<unitSpec
->mNumOutputs
; ++i
) {
854 OutputSpec
*outputSpec
= unitSpec
->mOutputSpec
+ i
;
855 if (outputSpec
->mCalcRate
== calc_FullRate
) {
856 outputSpec
->mBufferIndex
*= bufLength
;