1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
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.
10 
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.
15 
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
19 */
20 
21 #pragma once
22 
23 // TODO next time this is updated, change SC_PlugIn.hpp `in`, `zin`, etc. to take uint32s
24 // TODO next time this is updated, change SC_PlugIn.hpp `numInputs`, `numOutputs` to have correct
25 // return type
26 static const int sc_api_version = 3;
27 
28 #include "SC_Types.h"
29 #include "SC_SndBuf.h"
30 #include "SC_Unit.h"
31 #include "SC_BufGen.h"
32 #include "SC_FifoMsg.h"
33 #include "SC_fftlib.h"
34 #include "SC_Export.h"
35 
36 typedef struct SF_INFO SF_INFO;
37 
38 struct World;
39 
40 typedef bool (*AsyncStageFn)(World* inWorld, void* cmdData);
41 typedef void (*AsyncFreeFn)(World* inWorld, void* cmdData);
42 
43 struct ScopeBufferHnd {
44     void* internalData;
45     float* data;
46     uint32 channels;
47     uint32 maxFrames;
48 
channel_dataScopeBufferHnd49     float* channel_data(uint32 channel) { return data + (channel * maxFrames); }
50 
51     operator bool() { return internalData != 0; }
52 };
53 
54 struct InterfaceTable {
55     unsigned int mSineSize;
56     float32* mSineWavetable;
57     float32* mSine;
58     float32* mCosecant;
59 
60     // call printf for debugging. should not use in finished code.
61     int (*fPrint)(const char* fmt, ...);
62 
63     // get a seed for a random number generator
64     int32 (*fRanSeed)();
65 
66     // define a unit def
67     bool (*fDefineUnit)(const char* inUnitClassName, size_t inAllocSize, UnitCtorFunc inCtor, UnitDtorFunc inDtor,
68                         uint32 inFlags);
69 
70     // define a command  /cmd
71     bool (*fDefinePlugInCmd)(const char* inCmdName, PlugInCmdFunc inFunc, void* inUserData);
72 
73     // define a command for a unit generator  /u_cmd
74     bool (*fDefineUnitCmd)(const char* inUnitClassName, const char* inCmdName, UnitCmdFunc inFunc);
75 
76     // define a buf gen
77     bool (*fDefineBufGen)(const char* inName, BufGenFunc inFunc);
78 
79     // clear all of the unit's outputs.
80     void (*fClearUnitOutputs)(Unit* inUnit, int inNumSamples);
81 
82     // non real time memory allocation
83     void* (*fNRTAlloc)(size_t inSize);
84     void* (*fNRTRealloc)(void* inPtr, size_t inSize);
85     void (*fNRTFree)(void* inPtr);
86 
87     // real time memory allocation
88     void* (*fRTAlloc)(World* inWorld, size_t inSize);
89     void* (*fRTRealloc)(World* inWorld, void* inPtr, size_t inSize);
90     void (*fRTFree)(World* inWorld, void* inPtr);
91 
92     // call to set a Node to run or not.
93     void (*fNodeRun)(struct Node* node, int run);
94 
95     // call to stop a Graph after the next buffer.
96     void (*fNodeEnd)(struct Node* graph);
97 
98     // send a trigger from a Node to clients
99     void (*fSendTrigger)(struct Node* inNode, int triggerID, float value);
100 
101     // send a reply message from a Node to clients
102     void (*fSendNodeReply)(struct Node* inNode, int replyID, const char* cmdName, int numArgs, const float* values);
103 
104     // sending messages between real time and non real time levels.
105     bool (*fSendMsgFromRT)(World* inWorld, struct FifoMsg& inMsg);
106     bool (*fSendMsgToRT)(World* inWorld, struct FifoMsg& inMsg);
107 
108     // libsndfile support
109     int (*fSndFileFormatInfoFromStrings)(SF_INFO* info, const char* headerFormatString, const char* sampleFormatString);
110 
111     // get nodes by id
112     struct Node* (*fGetNode)(World* inWorld, int inID);
113     struct Graph* (*fGetGraph)(World* inWorld, int inID);
114 
115     void (*fNRTLock)(World* inWorld);
116     void (*fNRTUnlock)(World* inWorld);
117 
118     bool mUnused0;
119 
120     void (*fGroup_DeleteAll)(struct Group* group);
121     void (*fDoneAction)(int doneAction, struct Unit* unit);
122 
123     int (*fDoAsynchronousCommand)(
124         World* inWorld, void* replyAddr, const char* cmdName, void* cmdData,
125         AsyncStageFn stage2, // stage2 is non real time
126         AsyncStageFn stage3, // stage3 is real time - completion msg performed if stage3 returns true
127         AsyncStageFn stage4, // stage4 is non real time - sends done if stage4 returns true
128         AsyncFreeFn cleanup, int completionMsgSize, void* completionMsgData);
129 
130 
131     // fBufAlloc should only be called within a BufGenFunc
132     int (*fBufAlloc)(SndBuf* inBuf, int inChannels, int inFrames, double inSampleRate);
133 
134     // To initialise a specific FFT, ensure your input and output buffers exist. Internal data structures
135     // will be allocated using the alloc object,
136     // Both "fullsize" and "winsize" should be powers of two (this is not checked internally).
137     struct scfft* (*fSCfftCreate)(size_t fullsize, size_t winsize, SCFFT_WindowFunction wintype, float* indata,
138                                   float* outdata, SCFFT_Direction forward, SCFFT_Allocator& alloc);
139 
140     void (*fSCfftDoFFT)(scfft* f);
141     void (*fSCfftDoIFFT)(scfft* f);
142 
143     // destroy any resources held internally.
144     void (*fSCfftDestroy)(scfft* f, SCFFT_Allocator& alloc);
145 
146     // Get scope buffer. Returns the maximum number of possile frames.
147     bool (*fGetScopeBuffer)(World* inWorld, int index, int channels, int maxFrames, ScopeBufferHnd&);
148     void (*fPushScopeBuffer)(World* inWorld, ScopeBufferHnd&, int frames);
149     void (*fReleaseScopeBuffer)(World* inWorld, ScopeBufferHnd&);
150 };
151 
152 typedef struct InterfaceTable InterfaceTable;
153 
154 #define Print (*ft->fPrint)
155 #define RanSeed (*ft->fRanSeed)
156 #define NodeEnd (*ft->fNodeEnd)
157 #define NodeRun (*ft->fNodeRun)
158 #define DefineUnit (*ft->fDefineUnit)
159 #define DefinePlugInCmd (*ft->fDefinePlugInCmd)
160 #define DefineUnitCmd (*ft->fDefineUnitCmd)
161 #define DefineBufGen (*ft->fDefineBufGen)
162 #define ClearUnitOutputs (*ft->fClearUnitOutputs)
163 #define SendTrigger (*ft->fSendTrigger)
164 #define SendNodeReply (*ft->fSendNodeReply)
165 #define SendMsgFromRT (*ft->fSendMsgFromRT)
166 #define SendMsgToRT (*ft->fSendMsgToRT)
167 #define DoneAction (*ft->fDoneAction)
168 
169 #define NRTAlloc (*ft->fNRTAlloc)
170 #define NRTRealloc (*ft->fNRTRealloc)
171 #define NRTFree (*ft->fNRTFree)
172 
173 #define RTAlloc (*ft->fRTAlloc)
174 #define RTRealloc (*ft->fRTRealloc)
175 #define RTFree (*ft->fRTFree)
176 
177 #define SC_GetNode (*ft->fGetNode)
178 #define SC_GetGraph (*ft->fGetGraph)
179 
180 #define NRTLock (*ft->fNRTLock)
181 #define NRTUnlock (*ft->fNRTUnlock)
182 
183 #define BufAlloc (*ft->fBufAlloc)
184 
185 #define GroupDeleteAll (*ft->fGroup_DeleteAll)
186 
187 #define SndFileFormatInfoFromStrings (*ft->fSndFileFormatInfoFromStrings)
188 
189 #define DoAsynchronousCommand (*ft->fDoAsynchronousCommand)
190 
191 #define DefineSimpleUnit(name) (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, 0, 0);
192 
193 #define DefineDtorUnit(name)                                                                                           \
194     (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, (UnitDtorFunc)&name##_Dtor, 0);
195 
196 #define DefineSimpleCantAliasUnit(name)                                                                                \
197     (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, 0, kUnitDef_CantAliasInputsToOutputs);
198 
199 #define DefineDtorCantAliasUnit(name)                                                                                  \
200     (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, (UnitDtorFunc)&name##_Dtor,                    \
201                        kUnitDef_CantAliasInputsToOutputs);
202 
203 typedef enum { sc_server_scsynth = 0, sc_server_supernova = 1 } SC_ServerType;
204 
205 #ifdef STATIC_PLUGINS
206 #    define PluginLoad(name) void name##_Load(InterfaceTable* inTable)
207 #else
208 #    ifdef SUPERNOVA
209 #        define SUPERNOVA_CHECK                                                                                        \
210             C_LINKAGE SC_API_EXPORT int server_type(void) { return sc_server_supernova; }
211 #    else
212 #        define SUPERNOVA_CHECK                                                                                        \
213             C_LINKAGE SC_API_EXPORT int server_type(void) { return sc_server_scsynth; }
214 #    endif
215 
216 #    define PluginLoad(name)                                                                                           \
217         C_LINKAGE SC_API_EXPORT int api_version(void) { return sc_api_version; }                                       \
218         SUPERNOVA_CHECK                                                                                                \
219         C_LINKAGE SC_API_EXPORT void load(InterfaceTable* inTable)
220 #endif
221 
222 #define scfft_create (*ft->fSCfftCreate)
223 #define scfft_dofft (*ft->fSCfftDoFFT)
224 #define scfft_doifft (*ft->fSCfftDoIFFT)
225 #define scfft_destroy (*ft->fSCfftDestroy)
226 
227 
228 class SCWorld_Allocator : public SCFFT_Allocator {
229     InterfaceTable* ft;
230     World* world;
231 
232 public:
SCWorld_Allocator(InterfaceTable * ft,World * world)233     SCWorld_Allocator(InterfaceTable* ft, World* world): ft(ft), world(world) {}
234 
alloc(size_t size)235     virtual void* alloc(size_t size) { return RTAlloc(world, size); }
236 
free(void * ptr)237     virtual void free(void* ptr) { RTFree(world, ptr); }
238 };
239