├── .gitignore ├── LICENSE.md ├── README.md ├── dev ├── ErrorMessage.hpp ├── FFT_UGens.h ├── Hash.h ├── SCComplex.h ├── SC_Alloca.h ├── SC_BoundsMacros.h ├── SC_BufGen.h ├── SC_Complex.h ├── SC_Constants.h ├── SC_DemandUnit.h ├── SC_Endian.h ├── SC_Export.h ├── SC_FifoMsg.h ├── SC_Graph.h ├── SC_InlineBinaryOp.h ├── SC_InlineUnaryOp.h ├── SC_InterfaceTable.h ├── SC_LanguageClient.h ├── SC_Node.h ├── SC_OSC_Commands.h ├── SC_PlugIn.h ├── SC_PlugIn.hpp ├── SC_RGen.h ├── SC_Rate.h ├── SC_Reply.h ├── SC_SndBuf.h ├── SC_StringBuffer.h ├── SC_Types.h ├── SC_Unit.h ├── SC_Wire.h ├── SC_World.h ├── SC_WorldOptions.h ├── SC_fftlib.h ├── SC_sndfile_stub.h ├── ScopeBuffer.h ├── Unroll.h ├── clz.h ├── function_attributes.h ├── minimal-host │ ├── Makefile │ └── main.cpp ├── sc_msg_iter.h ├── sndfile.h ├── stdint.h └── wintime.h ├── example ├── .gitignore ├── ExampleUGens.nim ├── ExampleUGens.nims ├── ExampleUGens.sc ├── README.md └── example.scd ├── scnim.nim ├── scnim.nimble └── scnim ├── Alloca.nim ├── BoundsMacros.nim ├── BufGen.nim ├── DemandUnit.nim ├── Endian.nim ├── Export.nim ├── FifoMsg.nim ├── Graph.nim ├── Hash.nim ├── InlineBinaryOp.nim ├── InlineUnaryOp.nim ├── InterfaceTable.nim ├── Node.nim ├── PlugIn.nim ├── RGen.nim ├── Rate.nim ├── ScopeBuffer.nim ├── SndBuf.nim ├── Types.nim ├── Unit.nim ├── Unroll.nim ├── Wire.nim ├── World.nim ├── clz.nim ├── fftlib.nim ├── msg_iter.nim ├── ptrmath.nim └── sndfile_stub.nim /.gitignore: -------------------------------------------------------------------------------- 1 | nimcache 2 | 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Carlo Capocasa 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | scnim - Writing SuperCollider UGens using Nim 3 | ============================================= 4 | 5 | Introduction 6 | ------------ 7 | 8 | *Nim* is an exciting new programming language. It is about as easy to work with as ruby, but it compiles to very efficient C code. 9 | 10 | It also uses itself as a pre-processor, so you can generate huge blobs of efficient code without having to do a lot of copying and pasting by hand. 11 | 12 | This seems to make it ideally suitable for writing realtime signal processing code, and, by extension, SuperCollider plugins. 13 | 14 | This is a proof of concept that shows to see how well it holds up in practice- and it works really well! 15 | 16 | How to use it 17 | ------------- 18 | 19 | Installation 20 | 21 | nimble install scnim 22 | 23 | This is what a simple SuperCollider plugin looks like written with scnim. 24 | 25 | # ExampleUGens.nim 26 | import scnim 27 | 28 | proc api_version(): int {.cdecl,exportc,dynlib.} = 29 | return sc_api_version; 30 | 31 | proc server_type(): ServerType {.cdecl,exportc,dynlib.}= 32 | return when defined(SUPERNOVA): sc_server_supernova else: sc_server_scsynth 33 | 34 | var ft: ptr InterfaceTable 35 | 36 | type 37 | Example = object of Unit 38 | 39 | proc next(unit: ptr Example, numSamples: cint) {.cdecl,exportc,dynlib.} = 40 | var 41 | input = unit.mInBuf[] 42 | output = unit.mOutBuf[] 43 | 44 | for i in 0..numSamples: 45 | output[i] = input[i] 46 | 47 | proc ctor(unit: ptr Example) {.cdecl,exportc,dynlib.} = 48 | unit.mCalcFunc = cast[UnitCalcFunc](next) 49 | 50 | proc load(inTable: ptr InterfaceTable) {.cdecl,exportc,dynlib.} = 51 | ft = inTable; 52 | discard ft.fDefineUnit("Example", sizeof(Example), cast[UnitCtorFunc](ctor), nil, 0'u32) 53 | 54 | This gets compiled into an intermediate C++ file that links up with SuperCollider like a normal UGen does, using the following command: 55 | 56 | nim --gc=none --app=lib --out=ExampleUGens.so cpp ExampleUGens.nim 57 | 58 | The example can also be found in the `examples` directory- see `examples/README.md` to compile and use the example on SuperCollier. 59 | 60 | Most of the code is boilerplate- have a look at the `next` procedure to develop your code. 61 | 62 | Realtime considerations 63 | ----------------------- 64 | 65 | The same considerations apply when developing realtime code with Nim as with C++. Don't use features that allocate their own memory, prefer primitive types, keep it simple. 66 | 67 | Nim normally uses a garbage collector, a system to automatically frees up that kind of memory. For UGen development, it is turned off using the `-gc=none` switch above. As a neat side effect, the compiler will warn you about using "garbage collected memory", so if you're not sure which feature you can use, you can just try it and see if you get any warnings. 68 | 69 | Theoretically, Nim SuperCollider plugins should be just as fast as C code, and occasionally faster when delivering optimizations. From looking at the generated code, I can say this is most likely true. 70 | 71 | Status 72 | ------ 73 | 74 | The code works and it's fast, so the proof of concept was a success! 75 | 76 | The basics are present, so it can already be used to develop simple UGens by copying the example directory- but most more involved UGen features are still missing though. 77 | 78 | Most of all, Nim-Code is usually considered "safe", which means that if your program compiles, it won't crash. This isn't the case yet for scnim- Nim is really good at creating language features, so it should be quite possible to hide away all the gritty details behind a very clean interface without sacrificing performance- but we haven't figured out yet how to do that. 79 | 80 | Development 81 | ----------- 82 | 83 | Most SuperCollider plugin headers were already automatically translated to nim, they require manual adapting though. This has been done for the basic features in the example above, but not yet for 84 | 85 | - Buffers 86 | - Demand UGens 87 | - Plugin commands 88 | - Async commands 89 | - Generator commands 90 | - Supernova support 91 | 92 | Nim does automatic dead code elimination if you add the `--deadCodeElim=on` switch to the compile command above. Still, when the features are implemented, some code cleanup and possibly optimization should be performed before declaring this stable. 93 | 94 | Nim is cross-platform, so in principle, this will work on Windows, Linux and OSX. It has only been tested on Linux so far, so compile instructions need to be added for other platforms. 95 | 96 | Some tooling to add dependencies would be helpful, possibly adapting `cmake`. 97 | 98 | Contributions 99 | ------------- 100 | 101 | All contributions are welcome, large and small! 102 | 103 | (c) 2018 Carlo Capocasa. MIT License. 104 | 105 | -------------------------------------------------------------------------------- /dev/ErrorMessage.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file ErrorMessage.hpp 3 | * 4 | * \brief Error message generation. 5 | * 6 | * This header provides generation of complex error messages and warnings for scsynth/supernova. 7 | * The messages currently provided are: 8 | * - API version mismatch 9 | * - API version not found 10 | * 11 | * $Author: Brian Heim $ 12 | * 13 | * \version 1.0 14 | * 15 | * $Date: 2017-08-22 $ 16 | * 17 | * $Contact: brianlheim@gmail.com $ 18 | * 19 | * Created on: 2017-08-22 20 | * 21 | * Original revision by Brian Heim, 2017-08-22 22 | */ 23 | /* 24 | * Copyright (C) Brian Heim, 2017. All rights reserved. 25 | * 26 | * This program is free software; you can redistribute it and/or 27 | * modify it under the terms of the GNU General Public License as 28 | * published by the Free Software Foundation; either version 2 of the 29 | * License, or (at your option) any later version. 30 | * 31 | * This program is distributed in the hope that it will be useful, but 32 | * WITHOUT ANY WARRANTY; without even the implied warranty of 33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34 | * General Public License for more details. 35 | * 36 | * You should have received a copy of the GNU General Public License 37 | * along with this program; if not, write to the Free Software 38 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 39 | * 02110-1301 USA 40 | */ 41 | 42 | #ifndef COMMON_SERVER_ERRORMESSAGE_H_INCLUDED 43 | #define COMMON_SERVER_ERRORMESSAGE_H_INCLUDED 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | namespace scsynth { 51 | 52 | namespace ErrorMessage { 53 | 54 | /// String used to indent all messages. 55 | std::string const indent = " "; 56 | 57 | /** \brief Formats a helpful multiline error string in the case of a plugin API mismatch. 58 | * 59 | * Extra lines are added to help clarify problems caused by the recent upgrade to API 60 | * version 3 in SuperCollider 3.9. 61 | * 62 | * \param utf8Filename the filename of the plugin represented as a UTF-8 string. 63 | * \param expectedVersion the API version of this server 64 | * \param actualVersion the API version reported by the plugin 65 | * \returns A multiline string with info about how to correct the error. 66 | */ 67 | std::string apiVersionMismatch(std::string const& utf8Filename, int const expectedVersion, int const actualVersion) 68 | { 69 | using namespace std; 70 | assert(expectedVersion != actualVersion); 71 | 72 | // both 1 and 2 were introduced in 3.6 73 | static map const scVersionForAPIVersion = { 74 | {1, "3.6.0"}, 75 | {2, "3.6.0"}, 76 | {3, "3.9.0"} 77 | }; 78 | 79 | stringstream message; 80 | message << "ERROR: API version mismatch: " << utf8Filename << "\n"; 81 | 82 | try { 83 | // actualVersion+1: the version that broke compatibility 84 | string const& scVersion = scVersionForAPIVersion.at(actualVersion+1); 85 | message << indent << "This plugin is not compatible with SuperCollider >=" 86 | << scVersion << "\n"; 87 | message << indent 88 | << "The plugin has not been loaded; please find or compile a newer version.\n"; 89 | } catch (std::out_of_range const& exception) { 90 | message << indent << "This plugin uses an unknown version of the interface.\n"; 91 | message << indent << "You may need to update SuperCollider in order to use it.\n"; 92 | } 93 | 94 | // if it looks like sc3-plugins, give specific info to help 95 | if (utf8Filename.find("SC3plugins") != string::npos) { 96 | message << indent << "Releases of sc3-plugins can be downloaded from " 97 | << "https://github.com/supercollider/sc3-plugins/releases\n"; 98 | } 99 | 100 | message << indent << "(Plugin's API version: " << actualVersion << ". Expected: " 101 | << expectedVersion << ")\n"; 102 | 103 | return message.str(); 104 | } 105 | 106 | /** \brief Formats a helpful error string in the case that the API version function wasn't found. 107 | * 108 | * \param utf8Filename the filename of the plugin represented as a UTF-8 string. 109 | */ 110 | std::string apiVersionNotFound(std::string const& utf8Filename) 111 | { 112 | return "ERROR: API version not found: " + utf8Filename + "\n" 113 | + indent + "This file may not be a SuperCollider plugin.\n"; 114 | } 115 | 116 | } // namespace ErrorMessage 117 | 118 | } // namespace scsynth 119 | 120 | #endif // COMMON_SERVER_ERRORMESSAGE_H_INCLUDED 121 | -------------------------------------------------------------------------------- /dev/FFT_UGens.h: -------------------------------------------------------------------------------- 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 | #ifndef FFT_UGENS_H 22 | #define FFT_UGENS_H 23 | 24 | #include "SC_PlugIn.h" 25 | #include "SCComplex.h" 26 | 27 | #include 28 | 29 | struct SCComplexBuf 30 | { 31 | float dc, nyq; 32 | SCComplex bin[1]; 33 | }; 34 | 35 | struct SCPolarBuf 36 | { 37 | float dc, nyq; 38 | SCPolar bin[1]; 39 | }; 40 | 41 | static inline SCPolarBuf* ToPolarApx(SndBuf *buf) 42 | { 43 | if (buf->coord == coord_Complex) { 44 | SCComplexBuf* p = (SCComplexBuf*)buf->data; 45 | int numbins = (buf->samples - 2) >> 1; 46 | for (int i=0; ibin[i].ToPolarApxInPlace(); 48 | } 49 | buf->coord = coord_Polar; 50 | } 51 | 52 | return (SCPolarBuf*)buf->data; 53 | } 54 | 55 | static inline SCComplexBuf* ToComplexApx(SndBuf *buf) 56 | { 57 | if (buf->coord == coord_Polar) { 58 | SCPolarBuf* p = (SCPolarBuf*)buf->data; 59 | int numbins = (buf->samples - 2) >> 1; 60 | for (int i=0; ibin[i].ToComplexApxInPlace(); 62 | } 63 | buf->coord = coord_Complex; 64 | } 65 | return (SCComplexBuf*)buf->data; 66 | } 67 | 68 | struct PV_Unit : Unit 69 | { 70 | }; 71 | 72 | 73 | #define sc_clipbuf(x, hi) ((x) >= (hi) ? 0 : ((x) < 0 ? 0 : (x))) 74 | 75 | // for operation on one buffer 76 | #define PV_GET_BUF \ 77 | float fbufnum = ZIN0(0); \ 78 | if (fbufnum < 0.f) { ZOUT0(0) = -1.f; return; } \ 79 | ZOUT0(0) = fbufnum; \ 80 | uint32 ibufnum = (uint32)fbufnum; \ 81 | World *world = unit->mWorld; \ 82 | SndBuf *buf; \ 83 | if (ibufnum >= world->mNumSndBufs) { \ 84 | int localBufNum = ibufnum - world->mNumSndBufs; \ 85 | Graph *parent = unit->mParent; \ 86 | if(localBufNum <= parent->localBufNum) { \ 87 | buf = parent->mLocalSndBufs + localBufNum; \ 88 | } else { \ 89 | buf = world->mSndBufs; \ 90 | } \ 91 | } else { \ 92 | buf = world->mSndBufs + ibufnum; \ 93 | } \ 94 | LOCK_SNDBUF(buf); \ 95 | int numbins = (buf->samples - 2) >> 1; \ 96 | 97 | 98 | // for operation on two input buffers, result goes in first one. 99 | #define PV_GET_BUF2 \ 100 | float fbufnum1 = ZIN0(0); \ 101 | float fbufnum2 = ZIN0(1); \ 102 | if (fbufnum1 < 0.f || fbufnum2 < 0.f) { ZOUT0(0) = -1.f; return; } \ 103 | ZOUT0(0) = fbufnum1; \ 104 | uint32 ibufnum1 = (int)fbufnum1; \ 105 | uint32 ibufnum2 = (int)fbufnum2; \ 106 | World *world = unit->mWorld; \ 107 | SndBuf *buf1; \ 108 | SndBuf *buf2; \ 109 | if (ibufnum1 >= world->mNumSndBufs) { \ 110 | int localBufNum = ibufnum1 - world->mNumSndBufs; \ 111 | Graph *parent = unit->mParent; \ 112 | if(localBufNum <= parent->localBufNum) { \ 113 | buf1 = parent->mLocalSndBufs + localBufNum; \ 114 | } else { \ 115 | buf1 = world->mSndBufs; \ 116 | } \ 117 | } else { \ 118 | buf1 = world->mSndBufs + ibufnum1; \ 119 | } \ 120 | if (ibufnum2 >= world->mNumSndBufs) { \ 121 | int localBufNum = ibufnum2 - world->mNumSndBufs; \ 122 | Graph *parent = unit->mParent; \ 123 | if(localBufNum <= parent->localBufNum) { \ 124 | buf2 = parent->mLocalSndBufs + localBufNum; \ 125 | } else { \ 126 | buf2 = world->mSndBufs; \ 127 | } \ 128 | } else { \ 129 | buf2 = world->mSndBufs + ibufnum2; \ 130 | } \ 131 | LOCK_SNDBUF2(buf1, buf2); \ 132 | if (buf1->samples != buf2->samples) return; \ 133 | int numbins = (buf1->samples - 2) >> 1; 134 | 135 | #define MAKE_TEMP_BUF \ 136 | if (!unit->m_tempbuf) { \ 137 | unit->m_tempbuf = (float*)RTAlloc(unit->mWorld, buf->samples * sizeof(float)); \ 138 | unit->m_numbins = numbins; \ 139 | } else if (numbins != unit->m_numbins) return; 140 | 141 | extern InterfaceTable *ft; 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /dev/Hash.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _Hash_ 23 | #define _Hash_ 24 | 25 | #include "SC_Types.h" 26 | #include "SC_Endian.h" 27 | 28 | // These hash functions are among the best there are in terms of both speed and quality. 29 | // A good hash function makes a lot of difference. 30 | // I have not used Bob Jenkins own hash function because the keys I use are relatively short. 31 | 32 | 33 | // hash function for a string 34 | inline int32 Hash(const char *inKey) 35 | { 36 | // the one-at-a-time hash. 37 | // a very good hash function. ref: a web page by Bob Jenkins. 38 | // http://www.burtleburtle.net/bob/hash/doobs.html 39 | int32 hash = 0; 40 | while (*inKey) { 41 | hash += *inKey++; 42 | hash += hash << 10; 43 | hash ^= hash >> 6; 44 | } 45 | hash += hash << 3; 46 | hash ^= hash >> 11; 47 | hash += hash << 15; 48 | return hash; 49 | } 50 | 51 | // hash function for a string that also returns the length 52 | inline int32 Hash(const char *inKey, size_t *outLength) 53 | { 54 | // the one-at-a-time hash. 55 | // a very good hash function. ref: a web page by Bob Jenkins. 56 | const char *origKey = inKey; 57 | int32 hash = 0; 58 | while (*inKey) { 59 | hash += *inKey++; 60 | hash += hash << 10; 61 | hash ^= hash >> 6; 62 | } 63 | hash += hash << 3; 64 | hash ^= hash >> 11; 65 | hash += hash << 15; 66 | *outLength = inKey - origKey; 67 | return hash; 68 | } 69 | 70 | // hash function for an array of char 71 | inline int32 Hash(const char *inKey, int32 inLength) 72 | { 73 | // the one-at-a-time hash. 74 | // a very good hash function. ref: a web page by Bob Jenkins. 75 | int32 hash = 0; 76 | for (int i=0; i> 6; 80 | } 81 | hash += hash << 3; 82 | hash ^= hash >> 11; 83 | hash += hash << 15; 84 | return hash; 85 | } 86 | 87 | // hash function for integers 88 | inline int32 Hash(int32 inKey) 89 | { 90 | // Thomas Wang's integer hash. 91 | // http://www.concentric.net/~Ttwang/tech/inthash.htm 92 | // a faster hash for integers. also very good. 93 | uint32 hash = (uint32)inKey; 94 | hash += ~(hash << 15); 95 | hash ^= hash >> 10; 96 | hash += hash << 3; 97 | hash ^= hash >> 6; 98 | hash += ~(hash << 11); 99 | hash ^= hash >> 16; 100 | return (int32)hash; 101 | } 102 | 103 | inline int64 Hash64(int64 inKey) 104 | { 105 | // Thomas Wang's 64 bit integer hash. 106 | uint64 hash = (uint64)inKey; 107 | hash += ~(hash << 32); 108 | hash ^= (hash >> 22); 109 | hash += ~(hash << 13); 110 | hash ^= (hash >> 8); 111 | hash += (hash << 3); 112 | hash ^= (hash >> 15); 113 | hash += ~(hash << 27); 114 | hash ^= (hash >> 31); 115 | return (int64)hash; 116 | } 117 | 118 | inline int32 Hash(const int32 *inKey, int32 inLength) 119 | { 120 | // one-at-a-time hashing of a string of int32's. 121 | // uses Thomas Wang's integer hash for the combining step. 122 | int32 hash = 0; 123 | for (int i=0; i /* std::abs */ 25 | #include /* std::abs */ 26 | #include 27 | 28 | #define sc_abs(a) std::abs(a) 29 | #define sc_max(a,b) (((a) > (b)) ? (a) : (b)) 30 | #define sc_min(a,b) (((a) < (b)) ? (a) : (b)) 31 | 32 | template 33 | inline T sc_clip(T x, U lo, V hi) 34 | { 35 | return std::max(std::min(x, (T)hi), (T)lo); 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /dev/SC_BufGen.h: -------------------------------------------------------------------------------- 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 | #ifndef _BufGen_ 22 | #define _BufGen_ 23 | 24 | #include "SC_Types.h" 25 | 26 | typedef void (*BufGenFunc)(struct World *world, struct SndBuf *buf, struct sc_msg_iter *msg); 27 | 28 | struct BufGen 29 | { 30 | int32 mBufGenName[kSCNameLen]; 31 | int32 mHash; 32 | 33 | BufGenFunc mBufGenFunc; 34 | }; 35 | 36 | //C2NIM extern "C" { 37 | //C2NIM bool BufGen_Create(const char *inName, BufGenFunc inFunc); 38 | //C2NIM } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /dev/SC_Complex.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_Complex_ 23 | #define _SC_Complex_ 24 | 25 | #include 26 | 27 | #include "SC_Types.h" 28 | #include "SC_Constants.h" 29 | #include "float.h" 30 | 31 | #ifdef _MSC_VER 32 | // hypotf is c99, but not c++ 33 | #define hypotf _hypotf 34 | #endif 35 | 36 | //////////////////////////////////////////////////////////////////////////////// 37 | 38 | namespace detail { 39 | 40 | const int kSineSize = 8192; 41 | const int kSineMask = kSineSize - 1; 42 | const double kSinePhaseScale = kSineSize / twopi; 43 | const int32 kPolarLUTSize = 2049; 44 | const int32 kPolarLUTSize2 = kPolarLUTSize >> 1; 45 | 46 | 47 | /* each object file that is including this header will have separate lookup tables */ 48 | namespace { 49 | 50 | float gMagLUT[kPolarLUTSize]; 51 | float gPhaseLUT[kPolarLUTSize]; 52 | float gSine[kSineSize+1]; 53 | 54 | static bool initTables(void) 55 | { 56 | double sineIndexToPhase = twopi / kSineSize; 57 | for (int i=0; i <= kSineSize; ++i) { 58 | double phase = i * sineIndexToPhase; 59 | float32 d = sin(phase); 60 | gSine[i] = d; 61 | } 62 | 63 | double rPolarLUTSize2 = 1. / kPolarLUTSize2; 64 | for (int i=0; i < kPolarLUTSize; ++i) { 65 | double slope = (i - kPolarLUTSize2) * rPolarLUTSize2; 66 | double angle = atan(slope); 67 | gPhaseLUT[i] = (float)angle; 68 | gMagLUT[i] = (float)(1.f / cos(angle)); 69 | } 70 | 71 | return true; 72 | } 73 | 74 | bool dummy = initTables(); 75 | 76 | } 77 | 78 | struct Polar; 79 | 80 | 81 | struct Complex 82 | { 83 | Complex() {} 84 | Complex(float r, float i) : real(r), imag(i) {} 85 | void Set(float r, float i) { real = r; imag = i; } 86 | 87 | Complex& operator=(Complex b) { real = b.real; imag = b.imag; return *this; } 88 | Complex& operator=(float b) { real = b; imag = 0.; return *this; } 89 | 90 | Polar ToPolar(); 91 | 92 | /** 93 | * Converts cartesian to polar representation, using lookup tables. 94 | * Note: in this implementation the phase values returned lie in the range [-pi/4, 7pi/4] 95 | * rather than the more conventional [0, 2pi] or [-pi, pi]. 96 | */ 97 | Polar ToPolarApx(); 98 | 99 | void ToPolarInPlace(); 100 | 101 | void ToPolarApxInPlace(); 102 | 103 | float real, imag; 104 | }; 105 | 106 | struct Polar 107 | { 108 | Polar() {} 109 | Polar(float m, float p) : mag(m), phase(p) {} 110 | void Set(float m, float p) { mag = m; phase = p; } 111 | 112 | Complex ToComplex() 113 | { 114 | return Complex(mag * std::cos(phase), mag * std::sin(phase)); 115 | } 116 | 117 | Complex ToComplexApx() 118 | { 119 | uint32 sinindex = (int32)(kSinePhaseScale * phase) & kSineMask; 120 | uint32 cosindex = (sinindex + (kSineSize>>2)) & kSineMask; 121 | return Complex(mag * gSine[cosindex], mag * gSine[sinindex]); 122 | } 123 | 124 | void ToComplexInPlace() 125 | { 126 | Complex complx = ToComplex(); 127 | mag = complx.real; 128 | phase = complx.imag; 129 | } 130 | 131 | void ToComplexApxInPlace() 132 | { 133 | Complex complx = ToComplexApx(); 134 | mag = complx.real; 135 | phase = complx.imag; 136 | } 137 | 138 | float mag, phase; 139 | }; 140 | 141 | inline Polar Complex::ToPolar() 142 | { 143 | return Polar(hypotf(imag, real), std::atan2(imag, real)); 144 | } 145 | 146 | inline Polar Complex::ToPolarApx() 147 | { 148 | int32 index; 149 | float absreal = fabs(real); 150 | float absimag = fabs(imag); 151 | float mag, phase, slope; 152 | if (absreal > absimag) { 153 | slope = imag/real; 154 | index = (int32)(kPolarLUTSize2 + kPolarLUTSize2 * slope); 155 | mag = gMagLUT[index] * absreal; 156 | phase = gPhaseLUT[index]; 157 | if (real > 0) { 158 | return Polar(mag, phase); 159 | } else { 160 | return Polar(mag, (float)(pi + phase)); 161 | } 162 | } else if (absimag > 0) { 163 | slope = real/imag; 164 | index = (int32)(kPolarLUTSize2 + kPolarLUTSize2 * slope); 165 | mag = gMagLUT[index] * absimag; 166 | phase = gPhaseLUT[index]; 167 | if (imag > 0) { 168 | return Polar(mag, (float)(pi2 - phase)); 169 | } else { 170 | return Polar(mag, (float)(pi32 - phase)); 171 | } 172 | } else return Polar(0, 0); 173 | } 174 | 175 | inline void Complex::ToPolarInPlace() 176 | { 177 | Polar polar = ToPolar(); 178 | real = polar.mag; 179 | imag = polar.phase; 180 | } 181 | 182 | inline void Complex::ToPolarApxInPlace() 183 | { 184 | Polar polar = ToPolarApx(); 185 | real = polar.mag; 186 | imag = polar.phase; 187 | } 188 | 189 | } 190 | 191 | using detail::Polar; 192 | using detail::Complex; 193 | 194 | struct ComplexFT 195 | { 196 | float dc, nyq; 197 | Complex complex[1]; 198 | }; 199 | 200 | struct PolarFT 201 | { 202 | float dc, nyq; 203 | Polar polar[1]; 204 | }; 205 | 206 | void ToComplex(Polar in, Complex& out); 207 | 208 | inline Complex operator+(Complex a, Complex b) { return Complex(a.real + b.real, a.imag + b.imag); } 209 | inline Complex operator+(Complex a, float b) { return Complex(a.real + b, a.imag); } 210 | inline Complex operator+(float a, Complex b) { return Complex(a + b.real, b.imag); } 211 | 212 | inline Complex& operator+=(Complex& a, const Complex& b) { a.real += b.real, a.imag += b.imag; return a; } 213 | inline Complex& operator+=(Complex& a, float b) { a.real += b; return a; } 214 | 215 | inline Complex operator-(Complex a, Complex b) { return Complex(a.real - b.real, a.imag - b.imag); } 216 | inline Complex operator-(Complex a, float b) { return Complex(a.real - b, a.imag); } 217 | inline Complex operator-(float a, Complex b) { return Complex(a - b.real, b.imag); } 218 | 219 | inline Complex operator-=(Complex a, Complex b) { a.real -= b.real, a.imag -= b.imag; return a; } 220 | inline Complex operator-=(Complex a, float b) { a.real -= b; return a; } 221 | 222 | inline Complex operator*(Complex a, Complex b) 223 | { 224 | return Complex(a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real); 225 | } 226 | 227 | inline Complex operator*(Complex a, float b) 228 | { 229 | return Complex(a.real * b, a.imag * b); 230 | } 231 | 232 | inline Complex operator*(float a, Complex b) 233 | { 234 | return Complex(b.real * a, b.imag * a); 235 | } 236 | 237 | inline Complex operator*=(Complex a, Complex b) 238 | { 239 | a.Set( 240 | a.real * b.real - a.imag * b.imag, 241 | a.real * b.imag + a.imag * b.real 242 | ); 243 | return a; 244 | } 245 | 246 | inline Complex operator*=(Complex a, float b) 247 | { 248 | a.real *= b; 249 | a.imag *= b; 250 | return a; 251 | } 252 | 253 | 254 | inline Polar operator*(Polar a, float b) 255 | { 256 | return Polar(a.mag * b, a.phase); 257 | } 258 | 259 | inline Polar operator*(float a, Polar b) 260 | { 261 | return Polar(a * b.mag, b.phase); 262 | } 263 | 264 | inline Polar operator*=(Polar a, float b) 265 | { 266 | a.mag *= b; 267 | return a; 268 | } 269 | 270 | #endif 271 | -------------------------------------------------------------------------------- /dev/SC_Constants.h: -------------------------------------------------------------------------------- 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 | #ifndef _SC_Constants_ 22 | #define _SC_Constants_ 23 | 24 | #include 25 | 26 | #ifndef __FP__ 27 | const double pi = std::acos(-1.); 28 | #else 29 | const double sc_pi = std::acos(-1.); 30 | #define pi sc_pi // hack to avoid osx warning about deprecated pi 31 | #endif 32 | const double pi2 = pi * .5; 33 | const double pi32 = pi * 1.5; 34 | const double twopi = pi * 2.; 35 | const double rtwopi = 1. / twopi; 36 | const double log001 = std::log(0.001); 37 | const double log01 = std::log(0.01); 38 | const double log1 = std::log(0.1); 39 | const double rlog2 = 1./std::log(2.); 40 | const double sqrt2 = std::sqrt(2.); 41 | const double rsqrt2 = 1. / sqrt2; 42 | 43 | const float pi_f = std::acos(-1.f); 44 | const float pi2_f = pi_f * 0.5f; 45 | const float pi32_f = pi_f * 1.5f; 46 | const float twopi_f = pi_f * 2.f; 47 | const float sqrt2_f = std::sqrt(2.f); 48 | const float rsqrt2_f= 1.f/std::sqrt(2.f); 49 | 50 | // used to truncate precision 51 | const float truncFloat = (float)(3. * std::pow(2.0,22)); 52 | const double truncDouble = 3. * std::pow(2.0,51); 53 | 54 | const float kBadValue = 1e20f; // used in the secant table for values very close to 1/0 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /dev/SC_DemandUnit.h: -------------------------------------------------------------------------------- 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 | #ifndef _SC_DemandUnit_ 22 | #define _SC_DemandUnit_ 23 | 24 | /*C2Nim 25 | 26 | #include "SC_Unit.h" 27 | #include "SC_Wire.h" 28 | 29 | // demand rate unit support. 30 | 31 | inline bool IsDemandInput(Unit* unit, int index) 32 | { 33 | Unit* fromUnit = unit->mInput[index]->mFromUnit; 34 | return fromUnit && fromUnit->mCalcRate == calc_DemandRate; 35 | } 36 | 37 | inline float DemandInput(Unit* unit, int index) 38 | { 39 | Unit* fromUnit = unit->mInput[index]->mFromUnit; 40 | if (fromUnit && fromUnit->mCalcRate == calc_DemandRate) 41 | (fromUnit->mCalcFunc)(fromUnit, 1); 42 | return IN0(index); 43 | } 44 | 45 | // support for audio rate input to demand UGens 46 | // offset comes in as inNumSamples, so is in the range 1..size ! inNumSamples = 0 has a special meaning (reset). 47 | // it is converted to a buffer index here. 48 | 49 | inline float DemandInputA(Unit* unit, int index, int offset) 50 | { 51 | Unit* fromUnit = unit->mInput[index]->mFromUnit; 52 | if(!fromUnit) { return IN0(index); } 53 | if (fromUnit->mCalcRate == calc_DemandRate) { 54 | (fromUnit->mCalcFunc)(fromUnit, offset); 55 | return IN0(index); 56 | } else if (fromUnit->mCalcRate == calc_FullRate) { 57 | return IN(index)[offset - 1]; 58 | } else { 59 | return IN0(index); 60 | } 61 | } 62 | 63 | inline void ResetInput(Unit* unit, int index) 64 | { 65 | Unit* fromUnit = unit->mInput[index]->mFromUnit; 66 | if (fromUnit && fromUnit->mCalcRate == calc_DemandRate) 67 | (fromUnit->mCalcFunc)(fromUnit, 0); 68 | } 69 | 70 | #define ISDEMANDINPUT(index) IsDemandInput(unit, (index)) 71 | #define DEMANDINPUT(index) DemandInput(unit, (index)) 72 | #define DEMANDINPUT_A(index, offset) DemandInputA(unit, (index), (offset)) 73 | #define RESETINPUT(index) ResetInput(unit, (index)) 74 | 75 | */ 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /dev/SC_Endian.h: -------------------------------------------------------------------------------- 1 | 2 | # define LITTLE_ENDIAN 1234 3 | # define BIG_ENDIAN 4321 4 | # define BYTE_ORDER LITTLE_ENDIAN 5 | 6 | 7 | static inline unsigned int sc_htonl(unsigned int x) 8 | { 9 | #if BYTE_ORDER == LITTLE_ENDIAN 10 | unsigned char *s = (unsigned char *)&x; 11 | return (unsigned int)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); 12 | #else 13 | return x; 14 | #endif 15 | } 16 | 17 | static inline unsigned short sc_htons(unsigned short x) 18 | { 19 | #if BYTE_ORDER == LITTLE_ENDIAN 20 | unsigned char *s = (unsigned char *) &x; 21 | return (unsigned short)(s[0] << 8 | s[1]); 22 | #else 23 | return x; 24 | #endif 25 | } 26 | 27 | static inline unsigned int sc_ntohl(unsigned int x) 28 | { 29 | return sc_htonl(x); 30 | } 31 | 32 | static inline unsigned short sc_ntohs(unsigned short x) 33 | { 34 | return sc_htons(x); 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /dev/SC_Export.h: -------------------------------------------------------------------------------- 1 | /* 2 | SuperCollider real time audio synthesis system 3 | Copyright (c) 2010 Tim Blechmann. All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /*C2NIM 21 | 22 | #ifndef _SC_EXPORTS_ 23 | #define _SC_EXPORTS_ 24 | 25 | #if defined _WIN32 || defined __CYGWIN__ 26 | # define SC_API_IMPORT __declspec(dllimport) 27 | # define SC_API_EXPORT __declspec(dllexport) 28 | #else 29 | # if __GNUC__ >= 4 30 | # define SC_API_IMPORT __attribute__ ((visibility("default"))) 31 | # define SC_API_EXPORT __attribute__ ((visibility("default"))) 32 | # else 33 | # define SC_API_IMPORT 34 | # define SC_API_EXPORT 35 | # endif 36 | #endif 37 | 38 | #ifdef __cplusplus 39 | # define C_LINKAGE extern "C" 40 | #else 41 | # define C_LINKAGE 42 | #endif 43 | 44 | #ifdef BUILDING_SCSYNTH // if scsynth is being built, instead of used 45 | # define SCSYNTH_DLLEXPORT_C C_LINKAGE SC_API_EXPORT 46 | # define SCSYNTH_DLLEXPORT SC_API_EXPORT 47 | #elif defined(USING_SCSYNTH) 48 | # define SCSYNTH_DLLEXPORT_C C_LINKAGE SC_API_IMPORT 49 | # define SCSYNTH_DLLEXPORT SC_API_IMPORT 50 | #else 51 | # define SCSYNTH_DLLEXPORT_C C_LINKAGE 52 | # define SCSYNTH_DLLEXPORT 53 | #endif 54 | 55 | #ifdef BUILDING_SCLANG // if sclang is being built, instead of used 56 | # define SCLANG_DLLEXPORT_C C_LINKAGE SC_API_EXPORT 57 | # define SCLANG_DLLEXPORT SC_API_EXPORT 58 | #elif defined(USING_SCSYNTH) 59 | # define SCLANG_DLLEXPORT_C C_LINKAGE SC_API_IMPORT 60 | # define SCLANG_DLLEXPORT SC_API_IMPORT 61 | #else 62 | # define SCLANG_DLLEXPORT_C C_LINKAGE 63 | # define SCLANG_DLLEXPORT 64 | #endif 65 | 66 | #endif 67 | */ 68 | 69 | -------------------------------------------------------------------------------- /dev/SC_FifoMsg.h: -------------------------------------------------------------------------------- 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 | #ifndef _FifoMsg_ 22 | #define _FifoMsg_ 23 | 24 | typedef void (*FifoMsgFunc)(struct FifoMsg*); 25 | 26 | struct FifoMsg 27 | { 28 | FifoMsg() : mPerformFunc(0), mFreeFunc(0), mData(0), mWorld(0) {} 29 | 30 | void Set(struct World *inWorld, FifoMsgFunc inPerform, FifoMsgFunc inFree, void* inData); 31 | void Perform(); 32 | void Free(); 33 | 34 | FifoMsgFunc mPerformFunc; 35 | FifoMsgFunc mFreeFunc; 36 | void* mData; 37 | struct World *mWorld; 38 | }; 39 | 40 | inline void FifoMsg::Set(World *inWorld, FifoMsgFunc inPerform, FifoMsgFunc inFree, void* inData) 41 | { 42 | mWorld = inWorld; 43 | mPerformFunc = inPerform; 44 | mFreeFunc = inFree; 45 | mData = inData; 46 | } 47 | 48 | inline void FifoMsg::Perform() 49 | { 50 | if (mPerformFunc) (mPerformFunc)(this); 51 | } 52 | 53 | inline void FifoMsg::Free() 54 | { 55 | if (mFreeFunc) (mFreeFunc)(this); 56 | } 57 | 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /dev/SC_Graph.h: -------------------------------------------------------------------------------- 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 | #ifndef _SC_Graph_ 22 | #define _SC_Graph_ 23 | 24 | #include "SC_Node.h" 25 | #include "SC_Rate.h" 26 | #include "SC_SndBuf.h" 27 | 28 | /* 29 | changes to this struct likely also mean that a change is needed for 30 | static const int sc_api_version = x; 31 | value in SC_InterfaceTable.h file. 32 | */ 33 | struct Graph 34 | { 35 | Node mNode; 36 | 37 | uint32 mNumWires; 38 | struct Wire *mWire; 39 | 40 | uint32 mNumControls; 41 | float *mControls; 42 | float **mMapControls; 43 | int32 *mAudioBusOffsets; 44 | 45 | // try this for setting the rate of a control 46 | int *mControlRates; 47 | 48 | uint32 mNumUnits; 49 | struct Unit **mUnits; 50 | 51 | uint32 mNumCalcUnits; 52 | struct Unit **mCalcUnits; // excludes i-rate units. 53 | 54 | int mSampleOffset; 55 | struct RGen* mRGen; 56 | 57 | struct Unit *mLocalAudioBusUnit; 58 | struct Unit *mLocalControlBusUnit; 59 | 60 | float mSubsampleOffset; 61 | 62 | SndBuf *mLocalSndBufs; 63 | int localBufNum; 64 | int localMaxBufNum; 65 | }; 66 | typedef struct Graph Graph; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /dev/SC_InlineBinaryOp.h: -------------------------------------------------------------------------------- 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 | #ifndef _BinaryOpUGen_ 22 | #define _BinaryOpUGen_ 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /dev/SC_InlineUnaryOp.h: -------------------------------------------------------------------------------- 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 | #ifndef _UnaryOpUGen_ 22 | #define _UnaryOpUGen_ 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /dev/SC_InterfaceTable.h: -------------------------------------------------------------------------------- 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 | #ifndef _SC_SynthInterfaceTable_ 22 | #define _SC_SynthInterfaceTable_ 23 | 24 | static const int sc_api_version = 3; 25 | 26 | #include "SC_Types.h" 27 | #include "SC_SndBuf.h" 28 | #include "SC_Unit.h" 29 | #include "SC_BufGen.h" 30 | #include "SC_FifoMsg.h" 31 | #include "SC_fftlib.h" 32 | #include "SC_Export.h" 33 | 34 | typedef struct SF_INFO SF_INFO ; 35 | 36 | struct World; 37 | 38 | typedef bool (*AsyncStageFn)(World *inWorld, void* cmdData); 39 | typedef void (*AsyncFreeFn)(World *inWorld, void* cmdData); 40 | 41 | /*C2NIM 42 | struct ScopeBufferHnd 43 | { 44 | void *internalData; 45 | float *data; 46 | uint32 channels; 47 | uint32 maxFrames; 48 | 49 | float *channel_data( uint32 channel ) { 50 | return data + (channel * maxFrames); 51 | } 52 | 53 | operator bool () 54 | { 55 | return internalData != 0; 56 | } 57 | }; 58 | */ 59 | 60 | struct InterfaceTable 61 | { 62 | unsigned int mSineSize; 63 | float32 *mSineWavetable; 64 | float32 *mSine; 65 | float32 *mCosecant; 66 | 67 | // call printf for debugging. should not use in finished code. 68 | int (*fPrint)(const char *fmt, ...); 69 | 70 | // get a seed for a random number generator 71 | int32 (*fRanSeed)(); 72 | 73 | // define a unit def 74 | bool (*fDefineUnit)(const char *inUnitClassName, size_t inAllocSize, 75 | UnitCtorFunc inCtor, UnitDtorFunc inDtor, uint32 inFlags); 76 | 77 | // define a command /cmd 78 | bool (*fDefinePlugInCmd)(const char *inCmdName, PlugInCmdFunc inFunc, void* inUserData); 79 | 80 | // define a command for a unit generator /u_cmd 81 | bool (*fDefineUnitCmd)(const char *inUnitClassName, const char *inCmdName, UnitCmdFunc inFunc); 82 | 83 | // define a buf gen 84 | bool (*fDefineBufGen)(const char *inName, BufGenFunc inFunc); 85 | 86 | // clear all of the unit's outputs. 87 | void (*fClearUnitOutputs)(Unit *inUnit, int inNumSamples); 88 | 89 | // non real time memory allocation 90 | void* (*fNRTAlloc)(size_t inSize); 91 | void* (*fNRTRealloc)(void *inPtr, size_t inSize); 92 | void (*fNRTFree)(void *inPtr); 93 | 94 | // real time memory allocation 95 | void* (*fRTAlloc)(World *inWorld, size_t inSize); 96 | void* (*fRTRealloc)(World *inWorld, void *inPtr, size_t inSize); 97 | void (*fRTFree)(World *inWorld, void *inPtr); 98 | 99 | // call to set a Node to run or not. 100 | void (*fNodeRun)(struct Node* node, int run); 101 | 102 | // call to stop a Graph after the next buffer. 103 | void (*fNodeEnd)(struct Node* graph); 104 | 105 | // send a trigger from a Node to clients 106 | void (*fSendTrigger)(struct Node* inNode, int triggerID, float value); 107 | 108 | // send a reply message from a Node to clients 109 | void (*fSendNodeReply)(struct Node* inNode, int replyID, const char* cmdName, int numArgs, const float* values); 110 | 111 | // sending messages between real time and non real time levels. 112 | bool (*fSendMsgFromRT)(World *inWorld, struct FifoMsg inMsg); 113 | bool (*fSendMsgToRT)(World *inWorld, struct FifoMsg inMsg); 114 | 115 | // libsndfile support 116 | int (*fSndFileFormatInfoFromStrings)(SF_INFO *info, 117 | const char *headerFormatString, const char *sampleFormatString); 118 | 119 | // get nodes by id 120 | struct Node* (*fGetNode)(World *inWorld, int inID); 121 | struct Graph* (*fGetGraph)(World *inWorld, int inID); 122 | 123 | void (*fNRTLock)(World *inWorld); 124 | void (*fNRTUnlock)(World *inWorld); 125 | 126 | bool mUnused0; 127 | 128 | void (*fGroup_DeleteAll)(struct Group* group); 129 | void (*fDoneAction)(int doneAction, struct Unit *unit); 130 | 131 | int (*fDoAsynchronousCommand) 132 | ( 133 | World *inWorld, 134 | void* replyAddr, 135 | const char* cmdName, 136 | void *cmdData, 137 | AsyncStageFn stage2, // stage2 is non real time 138 | AsyncStageFn stage3, // stage3 is real time - completion msg performed if stage3 returns true 139 | AsyncStageFn stage4, // stage4 is non real time - sends done if stage4 returns true 140 | AsyncFreeFn cleanup, 141 | int completionMsgSize, 142 | void* completionMsgData 143 | ); 144 | 145 | 146 | // fBufAlloc should only be called within a BufGenFunc 147 | int (*fBufAlloc)(SndBuf *inBuf, int inChannels, int inFrames, double inSampleRate); 148 | 149 | // To initialise a specific FFT, ensure your input and output buffers exist. Internal data structures 150 | // will be allocated using the alloc object, 151 | // Both "fullsize" and "winsize" should be powers of two (this is not checked internally). 152 | struct scfft * (*fSCfftCreate)(size_t fullsize, size_t winsize, SCFFT_WindowFunction wintype, 153 | float *indata, float *outdata, SCFFT_Direction forward, SCFFT_Allocator alloc); 154 | 155 | void (*fSCfftDoFFT)(scfft *f); 156 | void (*fSCfftDoIFFT)(scfft *f); 157 | 158 | // destroy any resources held internally. 159 | void (*fSCfftDestroy)(scfft *f, SCFFT_Allocator alloc); 160 | 161 | // Get scope buffer. Returns the maximum number of possile frames. 162 | bool (*fGetScopeBuffer)(World *inWorld, int index, int channels, int maxFrames, ScopeBufferHnd ); 163 | void (*fPushScopeBuffer)(World *inWorld, ScopeBufferHnd , int frames); 164 | void (*fReleaseScopeBuffer)(World *inWorld, ScopeBufferHnd ); 165 | }; 166 | 167 | typedef struct InterfaceTable InterfaceTable; 168 | 169 | #define Print (*ft->fPrint) 170 | #define RanSeed (*ft->fRanSeed) 171 | #define NodeEnd (*ft->fNodeEnd) 172 | #define NodeRun (*ft->fNodeRun) 173 | #define DefineUnit (*ft->fDefineUnit) 174 | #define DefinePlugInCmd (*ft->fDefinePlugInCmd) 175 | #define DefineUnitCmd (*ft->fDefineUnitCmd) 176 | #define DefineBufGen (*ft->fDefineBufGen) 177 | #define ClearUnitOutputs (*ft->fClearUnitOutputs) 178 | #define SendTrigger (*ft->fSendTrigger) 179 | #define SendNodeReply (*ft->fSendNodeReply) 180 | #define SendMsgFromRT (*ft->fSendMsgFromRT) 181 | #define SendMsgToRT (*ft->fSendMsgToRT) 182 | #define DoneAction (*ft->fDoneAction) 183 | 184 | #define NRTAlloc (*ft->fNRTAlloc) 185 | #define NRTRealloc (*ft->fNRTRealloc) 186 | #define NRTFree (*ft->fNRTFree) 187 | 188 | #define RTAlloc (*ft->fRTAlloc) 189 | #define RTRealloc (*ft->fRTRealloc) 190 | #define RTFree (*ft->fRTFree) 191 | 192 | #define SC_GetNode (*ft->fGetNode) 193 | #define SC_GetGraph (*ft->fGetGraph) 194 | 195 | #define NRTLock (*ft->fNRTLock) 196 | #define NRTUnlock (*ft->fNRTUnlock) 197 | 198 | #define BufAlloc (*ft->fBufAlloc) 199 | 200 | #define GroupDeleteAll (*ft->fGroup_DeleteAll) 201 | 202 | #define SndFileFormatInfoFromStrings (*ft->fSndFileFormatInfoFromStrings) 203 | 204 | #define DoAsynchronousCommand (*ft->fDoAsynchronousCommand) 205 | 206 | /*C2NIM 207 | 208 | #define DefineSimpleUnit(name) \ 209 | (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, 0, 0); 210 | 211 | #define DefineDtorUnit(name) \ 212 | (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, \ 213 | (UnitDtorFunc)&name##_Dtor, 0); 214 | 215 | #define DefineSimpleCantAliasUnit(name) \ 216 | (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, 0, kUnitDef_CantAliasInputsToOutputs); 217 | 218 | #define DefineDtorCantAliasUnit(name) \ 219 | (*ft->fDefineUnit)(#name, sizeof(name), (UnitCtorFunc)&name##_Ctor, \ 220 | (UnitDtorFunc)&name##_Dtor, kUnitDef_CantAliasInputsToOutputs); 221 | */ 222 | 223 | typedef enum { 224 | sc_server_scsynth = 0, 225 | sc_server_supernova = 1 226 | } SC_ServerType; 227 | 228 | /*C2NIM 229 | #ifdef STATIC_PLUGINS 230 | #define PluginLoad(name) void name##_Load(InterfaceTable *inTable) 231 | #else 232 | #ifdef SUPERNOVA 233 | #define SUPERNOVA_CHECK C_LINKAGE SC_API_EXPORT int server_type(void) { return sc_server_supernova; } 234 | #else 235 | #define SUPERNOVA_CHECK C_LINKAGE SC_API_EXPORT int server_type(void) { return sc_server_scsynth; } 236 | #endif 237 | 238 | #define PluginLoad(name) \ 239 | C_LINKAGE SC_API_EXPORT int api_version(void) { return sc_api_version; } \ 240 | SUPERNOVA_CHECK \ 241 | C_LINKAGE SC_API_EXPORT void load(InterfaceTable *inTable) 242 | #endif 243 | */ 244 | 245 | #define scfft_create (*ft->fSCfftCreate) 246 | #define scfft_dofft (*ft->fSCfftDoFFT) 247 | #define scfft_doifft (*ft->fSCfftDoIFFT) 248 | #define scfft_destroy (*ft->fSCfftDestroy) 249 | 250 | /*C2NIM 251 | class SCWorld_Allocator: public SCFFT_Allocator 252 | { 253 | InterfaceTable * ft; 254 | World * world; 255 | 256 | public: 257 | SCWorld_Allocator(InterfaceTable * ft, World * world): 258 | ft(ft), world(world) 259 | {} 260 | 261 | virtual void* alloc(size_t size) 262 | { 263 | return RTAlloc(world, size); 264 | } 265 | 266 | virtual void free(void* ptr) 267 | { 268 | RTFree(world, ptr); 269 | } 270 | }; 271 | */ 272 | 273 | #endif 274 | -------------------------------------------------------------------------------- /dev/SC_LanguageClient.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- 2 | Abstract interpreter interface. 3 | Copyright (c) 2003 2004 stefan kersten. 4 | Copyright (c) 2013 tim blechmann. 5 | 6 | ==================================================================== 7 | 8 | SuperCollider real time audio synthesis system 9 | Copyright (c) 2002 James McCartney. All rights reserved. 10 | http://www.audiosynth.com 11 | 12 | This program is free software; you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as published by 14 | the Free Software Foundation; either version 2 of the License, or 15 | (at your option) any later version. 16 | 17 | This program is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with this program; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 25 | */ 26 | 27 | #ifndef SC_LANGUAGECLIENT_H_INCLUDED 28 | #define SC_LANGUAGECLIENT_H_INCLUDED 29 | 30 | #include "SC_Export.h" 31 | #include 32 | #include 33 | 34 | // ===================================================================== 35 | // SC_LanguageClient - abstract sclang client. 36 | // ===================================================================== 37 | 38 | SCLANG_DLLEXPORT class SC_LanguageClient * createLanguageClient(const char * name); 39 | SCLANG_DLLEXPORT void destroyLanguageClient(class SC_LanguageClient *); 40 | 41 | class SCLANG_DLLEXPORT SC_LanguageClient 42 | { 43 | public: 44 | struct Options 45 | { 46 | Options() 47 | : mMemSpace(2*1024*1024), 48 | mMemGrow(256*1024), 49 | mPort(57120), 50 | mRuntimeDir(0) 51 | { } 52 | 53 | int mMemSpace; // memory space in bytes 54 | int mMemGrow; // memory growth in bytes 55 | int mPort; // network port number 56 | char* mRuntimeDir; // runtime directory 57 | }; 58 | 59 | protected: 60 | // create singleton instance 61 | SC_LanguageClient(const char* name); 62 | virtual ~SC_LanguageClient(); 63 | friend void destroyLanguageClient(class SC_LanguageClient *); 64 | 65 | public: 66 | // singleton instance access locking 67 | static void lockInstance(); 68 | static void unlockInstance(); 69 | 70 | // return the singleton instance 71 | static SC_LanguageClient* instance(); 72 | static SC_LanguageClient* lockedInstance() { lockInstance(); return instance(); } 73 | 74 | // initialize language runtime 75 | void initRuntime(const Options& opt=Options()); 76 | void shutdownRuntime(); 77 | 78 | // return application name 79 | const char* getName() const; 80 | 81 | // library startup/shutdown 82 | bool isLibraryCompiled(); 83 | void compileLibrary(bool standalone); 84 | void shutdownLibrary(); 85 | void recompileLibrary(bool standalone); 86 | 87 | // interpreter access 88 | void lock(); 89 | bool trylock(); 90 | void unlock(); 91 | 92 | struct VMGlobals* getVMGlobals(); 93 | 94 | void setCmdLine(const char* buf, size_t size); 95 | void setCmdLine(const char* str); 96 | void setCmdLinef(const char* fmt, ...); 97 | void runLibrary(const char* methodName); 98 | void interpretCmdLine(); 99 | void interpretPrintCmdLine(); 100 | void executeFile(const char* fileName); 101 | void runMain(); 102 | void stopMain(); 103 | 104 | // post file access 105 | FILE* getPostFile(); 106 | void setPostFile(FILE* file); 107 | 108 | // run (in case of a terminal client) 109 | virtual int run(int argc, char** argv); 110 | 111 | // post buffer output (subclass responsibility) 112 | // should be thread-save. 113 | virtual void postText(const char* str, size_t len) = 0; 114 | virtual void postFlush(const char* str, size_t len) = 0; 115 | virtual void postError(const char* str, size_t len) = 0; 116 | // flush post buffer contents to screen. 117 | // only called from the main language thread. 118 | virtual void flush() = 0; 119 | 120 | // command line argument handling utilities 121 | static void snprintMemArg(char* dst, size_t size, int arg); 122 | static bool parseMemArg(const char* arg, int* res); 123 | static bool parsePortArg(const char* arg, int* res); 124 | 125 | // AppClock driver 126 | // to be called from client mainloop. 127 | void tick(); 128 | // AppClock driver. WARNING: Must be called locked! 129 | // Returns whether there is anything scheduled, 130 | // and writes the scheduled absolute time, if any, into nextTime. 131 | bool tickLocked( double * nextTime ); 132 | 133 | protected: 134 | // language notifications, subclasses can override 135 | 136 | // called after language runtime has been initialized 137 | virtual void onInitRuntime(); 138 | // called after the library has been compiled 139 | virtual void onLibraryStartup(); 140 | // called before the library is shut down 141 | virtual void onLibraryShutdown(); 142 | // called after the interpreter has been started 143 | virtual void onInterpStartup(); 144 | 145 | void runLibrary(struct PyrSymbol* pyrSymbol); 146 | 147 | private: 148 | friend void closeAllGUIScreens(); 149 | friend void initGUIPrimitives(); 150 | friend void initGUI(); 151 | 152 | private: 153 | class HiddenLanguageClient * mHiddenClient; 154 | }; 155 | 156 | // ===================================================================== 157 | // library functions 158 | // ===================================================================== 159 | 160 | extern void setPostFile(FILE* file); 161 | extern "C" int vpost(const char *fmt, va_list vargs); 162 | extern void post(const char *fmt, ...); 163 | extern void postfl(const char *fmt, ...); 164 | extern void postText(const char *text, long length); 165 | extern void postChar(char c); 166 | extern void error(const char *fmt, ...); 167 | extern void flushPostBuf(); 168 | 169 | #endif // SC_LANGUAGECLIENT_H_INCLUDED 170 | -------------------------------------------------------------------------------- /dev/SC_Node.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_Node_ 23 | #define _SC_Node_ 24 | 25 | #include "SC_Types.h" 26 | 27 | typedef void (*NodeCalcFunc)(struct Node *inNode); 28 | 29 | struct Node 30 | { 31 | int32 mID; 32 | int32 mHash; 33 | 34 | struct World *mWorld; 35 | struct NodeDef *mDef; 36 | NodeCalcFunc mCalcFunc; 37 | 38 | struct Node *mPrev, *mNext; 39 | struct Group *mParent; 40 | 41 | int32 mIsGroup; 42 | }; 43 | typedef struct Node Node; 44 | 45 | enum { kNode_Go, kNode_End, kNode_On, kNode_Off, kNode_Move, kNode_Info }; 46 | 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /dev/SC_OSC_Commands.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_OSC_Commands_ 23 | #define _SC_OSC_Commands_ 24 | 25 | // command numbers: 26 | enum { 27 | cmd_none = 0, 28 | 29 | cmd_notify = 1, 30 | cmd_status = 2, 31 | cmd_quit = 3, 32 | cmd_cmd = 4, 33 | 34 | cmd_d_recv = 5, 35 | cmd_d_load = 6, 36 | cmd_d_loadDir = 7, 37 | cmd_d_freeAll = 8, 38 | 39 | cmd_s_new = 9, 40 | 41 | cmd_n_trace = 10, 42 | cmd_n_free = 11, 43 | cmd_n_run = 12, 44 | cmd_n_cmd = 13, 45 | cmd_n_map = 14, 46 | cmd_n_set = 15, 47 | cmd_n_setn = 16, 48 | cmd_n_fill = 17, 49 | cmd_n_before = 18, 50 | cmd_n_after = 19, 51 | 52 | cmd_u_cmd = 20, 53 | 54 | cmd_g_new = 21, 55 | cmd_g_head = 22, 56 | cmd_g_tail = 23, 57 | cmd_g_freeAll = 24, 58 | 59 | cmd_c_set = 25, 60 | cmd_c_setn = 26, 61 | cmd_c_fill = 27, 62 | 63 | cmd_b_alloc = 28, 64 | cmd_b_allocRead = 29, 65 | cmd_b_read = 30, 66 | cmd_b_write = 31, 67 | cmd_b_free = 32, 68 | cmd_b_close = 33, 69 | cmd_b_zero = 34, 70 | cmd_b_set = 35, 71 | cmd_b_setn = 36, 72 | cmd_b_fill = 37, 73 | cmd_b_gen = 38, 74 | 75 | cmd_dumpOSC = 39, 76 | 77 | cmd_c_get = 40, 78 | cmd_c_getn = 41, 79 | cmd_b_get = 42, 80 | cmd_b_getn = 43, 81 | cmd_s_get = 44, 82 | cmd_s_getn = 45, 83 | 84 | cmd_n_query = 46, 85 | cmd_b_query = 47, 86 | 87 | cmd_n_mapn = 48, 88 | cmd_s_noid = 49, 89 | 90 | cmd_g_deepFree = 50, 91 | cmd_clearSched = 51, 92 | 93 | cmd_sync = 52, 94 | 95 | cmd_d_free = 53, 96 | 97 | cmd_b_allocReadChannel = 54, 98 | cmd_b_readChannel = 55, 99 | 100 | cmd_g_dumpTree = 56, 101 | cmd_g_queryTree = 57, 102 | 103 | cmd_error = 58, 104 | 105 | cmd_s_newargs = 59, 106 | 107 | cmd_n_mapa = 60, 108 | cmd_n_mapan = 61, 109 | cmd_n_order = 62, 110 | 111 | cmd_p_new = 63, 112 | 113 | cmd_version = 64, 114 | 115 | NUMBER_OF_COMMANDS = 65 116 | }; 117 | 118 | #endif /* _SC_OSC_Commands_ */ 119 | -------------------------------------------------------------------------------- /dev/SC_PlugIn.h: -------------------------------------------------------------------------------- 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 | #ifndef SC_PLUGIN_H 22 | #define SC_PLUGIN_H 23 | 24 | #include "SC_World.h" 25 | #include "SC_Graph.h" 26 | #include "SC_Unit.h" 27 | #include "SC_Wire.h" 28 | #include "SC_InterfaceTable.h" 29 | #include "Unroll.h" 30 | #include "SC_InlineUnaryOp.h" 31 | #include "SC_InlineBinaryOp.h" 32 | #include "SC_BoundsMacros.h" 33 | #include "SC_RGen.h" 34 | #include "SC_DemandUnit.h" 35 | #include "clz.h" 36 | #include "sc_msg_iter.h" 37 | #include 38 | #include "SC_Alloca.h" 39 | 40 | #endif /* SC_PLUGIN_H */ 41 | -------------------------------------------------------------------------------- /dev/SC_PlugIn.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SuperCollider real time audio synthesis system 3 | * Copyright (c) 2002 James McCartney. All rights reserved. 4 | * Copyright (c) 2011 Tim Blechmann 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 | #ifndef SC_PLUGIN_HPP 22 | #define SC_PLUGIN_HPP 23 | 24 | #include 25 | 26 | #include "SC_PlugIn.h" 27 | #include "function_attributes.h" 28 | 29 | #include 30 | 31 | /// c++ wrapper for Unit struct 32 | class SCUnit: 33 | public Unit 34 | { 35 | public: 36 | ///@{ 37 | /// generic signal wrappers 38 | template 39 | struct ScalarSignal 40 | { 41 | explicit ScalarSignal(FloatType value): 42 | value(value) 43 | {} 44 | 45 | FloatType consume() const 46 | { 47 | return value; 48 | } 49 | 50 | FloatType value; 51 | }; 52 | 53 | template 54 | struct SlopeSignal 55 | { 56 | SlopeSignal(FloatType value, FloatType slope): 57 | value(value), slope(slope) 58 | {} 59 | 60 | FloatType consume() 61 | { 62 | FloatType ret = value; 63 | value += slope; 64 | return ret; 65 | } 66 | 67 | FloatType value, slope; 68 | }; 69 | 70 | template 71 | struct AudioSignal 72 | { 73 | explicit AudioSignal(const FloatType * pointer): 74 | pointer(pointer) 75 | {} 76 | 77 | FloatType consume() 78 | { 79 | return *pointer++; 80 | } 81 | 82 | const FloatType * pointer; 83 | }; 84 | 85 | template 86 | inline ScalarSignal makeScalar(FloatType value) const 87 | { 88 | return ScalarSignal(value); 89 | } 90 | 91 | template 92 | inline SlopeSignal makeSlope(FloatType next, FloatType last) const 93 | { 94 | return SlopeSignal(last, calcSlope(next, last)); 95 | } 96 | 97 | inline AudioSignal makeSignal(int index) const 98 | { 99 | const float * input = in(index); 100 | return AudioSignal(input); 101 | } 102 | ///@} 103 | 104 | /// get input signal at index 105 | const float * in(int index) const 106 | { 107 | assert( index < mNumInputs ); 108 | const Unit * unit = this; 109 | return IN(index); 110 | } 111 | 112 | /// get input signal at index (to be used with ZXP) 113 | const float * zin(int index) const 114 | { 115 | assert( index < mNumInputs ); 116 | const Unit * unit = this; 117 | return ZIN(index); 118 | } 119 | 120 | /// get first sample of input signal 121 | const float in0(int index) const 122 | { 123 | assert( index < mNumInputs ); 124 | const Unit * unit = this; 125 | return IN0(index); 126 | } 127 | 128 | /// get output signal at index 129 | float * out(int index) const 130 | { 131 | assert( index < mNumOutputs ); 132 | const Unit * unit = this; 133 | return OUT(index); 134 | } 135 | 136 | /// get output signal at index (to be used with ZXP) 137 | float * zout(int index) const 138 | { 139 | assert( index < mNumOutputs ); 140 | const Unit * unit = this; 141 | return ZOUT(index); 142 | } 143 | 144 | /// get reference to first sample of output signal 145 | float & out0(int index) const 146 | { 147 | assert( index < mNumOutputs ); 148 | const Unit * unit = this; 149 | return OUT0(index); 150 | } 151 | 152 | /// get rate of input signal 153 | int inRate(int index) const 154 | { 155 | assert( index < mNumInputs ); 156 | const Unit * unit = this; 157 | return INRATE(index); 158 | } 159 | 160 | /// get number of inputs 161 | int numInputs() const 162 | { 163 | return mNumInputs; 164 | } 165 | 166 | /// get number of outputs 167 | int numOutputs() const 168 | { 169 | return mNumOutputs; 170 | } 171 | 172 | /// test if input signal at index is scalar rate 173 | bool isScalarRateIn(int index) const 174 | { 175 | assert( index < mNumInputs ); 176 | return inRate(index) == calc_ScalarRate; 177 | } 178 | 179 | /// test if input signal at index is demand rate 180 | bool isDemandRateIn(int index) const 181 | { 182 | assert( index < mNumInputs ); 183 | return inRate(index) == calc_DemandRate; 184 | } 185 | 186 | /// test if input signal at index is control rate 187 | bool isControlRateIn(int index) const 188 | { 189 | assert( index < mNumInputs ); 190 | return inRate(index) == calc_BufRate; 191 | } 192 | 193 | /// test if input signal at index is audio rate 194 | bool isAudioRateIn(int index) const 195 | { 196 | assert( index < mNumInputs ); 197 | return inRate(index) == calc_FullRate; 198 | } 199 | 200 | /// get the blocksize of the input 201 | int inBufferSize(int index) const 202 | { 203 | assert( index < mNumInputs ); 204 | const Unit * unit = this; 205 | return INBUFLENGTH(index); 206 | } 207 | 208 | /// get sample rate of ugen 209 | double sampleRate() const 210 | { 211 | const Unit * unit = this; 212 | return SAMPLERATE; 213 | } 214 | 215 | /// get sample duration 216 | double sampleDur() const 217 | { 218 | const Unit * unit = this; 219 | return SAMPLEDUR; 220 | } 221 | 222 | /// get buffer size of ugen 223 | int bufferSize() const 224 | { 225 | return mBufLength; 226 | } 227 | 228 | /// get control rate 229 | double controlRate() const 230 | { 231 | const Unit * unit = this; 232 | return BUFRATE; 233 | } 234 | 235 | /// get duration of a control block 236 | double controlDur() const 237 | { 238 | const Unit * unit = this; 239 | return BUFDUR; 240 | } 241 | 242 | /// get sampling rate of audio signal 243 | double fullSampleRate() const 244 | { 245 | const Unit * unit = this; 246 | return FULLRATE; 247 | } 248 | 249 | /// get buffer size of audio signals 250 | int fullBufferSize() const 251 | { 252 | const Unit * unit = this; 253 | return FULLBUFLENGTH; 254 | } 255 | 256 | /// calculate slope value 257 | template 258 | FloatType calcSlope(FloatType next, FloatType prev) const 259 | { 260 | const Unit * unit = this; 261 | return CALCSLOPE(next, prev); 262 | } 263 | 264 | template 265 | static UnitCalcFunc make_calc_function(void) 266 | { 267 | return &run_member_function; 268 | } 269 | 270 | /// set calc function & compute initial sample 271 | template 272 | void set_calc_function(void) 273 | { 274 | mCalcFunc = make_calc_function(); 275 | (mCalcFunc)(this, 1); 276 | } 277 | 278 | /// set calc function & compute initial sample 279 | template 280 | void set_vector_calc_function(void) 281 | { 282 | mCalcFunc = make_calc_function(); 283 | make_calc_function()(this, 1); 284 | } 285 | /// @} 286 | 287 | private: 288 | template 289 | HOT static void run_member_function(struct Unit * unit, int inNumSamples) 290 | { 291 | UnitType * realUnit = static_cast(unit); 292 | ((realUnit)->*(PointerToMember))(inNumSamples); 293 | } 294 | }; 295 | 296 | /// define Ctor/Dtor functions for a class 297 | #define DEFINE_XTORS(CLASSNAME) \ 298 | void CLASSNAME##_Ctor(CLASSNAME * unit) \ 299 | { \ 300 | new(unit) CLASSNAME(); \ 301 | } \ 302 | \ 303 | void CLASSNAME##_Dtor(CLASSNAME * unit) \ 304 | { \ 305 | unit->~CLASSNAME(); \ 306 | } 307 | 308 | namespace detail { 309 | 310 | template 311 | void constructClass( Unit * unit ) { new( static_cast(unit) ) UGenClass(); } 312 | template 313 | void destroyClass( Unit * unit ) { static_cast(unit)->~UGenClass(); } 314 | 315 | } 316 | 317 | template 318 | void registerUnit( InterfaceTable * ft, const char * name ) 319 | { 320 | UnitCtorFunc ctor = detail::constructClass; 321 | UnitDtorFunc dtor = std::is_trivially_destructible::value ? nullptr 322 | : detail::destroyClass; 323 | 324 | (*ft->fDefineUnit)( name, sizeof(Unit), ctor, dtor, 0 ); 325 | } 326 | 327 | 328 | #endif /* SC_PLUGIN_HPP */ 329 | -------------------------------------------------------------------------------- /dev/SC_RGen.h: -------------------------------------------------------------------------------- 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 | //----------------------------------------------------------------------------// 22 | // Ran088: L'Ecuyer's 1996 three-component Tausworthe generator "taus88" 23 | //----------------------------------------------------------------------------// 24 | // 25 | // Returns an integer random number uniformly distributed within [0,4294967295] 26 | // 27 | // The period length is approximately 2^88 (which is 3*10^26). 28 | // This generator is very fast and passes all standard statistical tests. 29 | // 30 | // Reference: 31 | // (1) P. L'Ecuyer, Maximally equidistributed combined Tausworthe generators, 32 | // Mathematics of Computation, 65, 203-213 (1996), see Figure 4. 33 | // (2) recommended in: 34 | // P. L'Ecuyer, Random number generation, chapter 4 of the 35 | // Handbook on Simulation, Ed. Jerry Banks, Wiley, 1997. 36 | // 37 | //----------------------------------------------------------------------------// 38 | 39 | //----------------------------------------------------------------------------// 40 | // I chose this random number generator for the following reasons: 41 | // fast. 42 | // easier and faster to seed than other high quality rng's such as Mersenne Twister. 43 | // the internal state is only 12 bytes. 44 | // the period is long enough for music/audio. 45 | // possible to code in altivec in future if needed. 46 | // - James McCartney 47 | //----------------------------------------------------------------------------// 48 | 49 | #ifndef _SC_RGen_ 50 | #define _SC_RGen_ 51 | 52 | #include "SC_Endian.h" 53 | #include "SC_Types.h" 54 | #include "SC_BoundsMacros.h" 55 | #include "Hash.h" 56 | #include 57 | 58 | struct RGen 59 | { 60 | void init(uint32 seed); 61 | 62 | uint32 trand(); 63 | 64 | int32 irand(int32 scale); 65 | int32 irand2(int32 scale); 66 | int32 ilinrand(int32 scale); 67 | int32 ibilinrand(int32 scale); 68 | 69 | float fcoin(); 70 | float frand(); 71 | float frand2(); 72 | float frand0(); 73 | float frand8(); 74 | float flinrand(); 75 | float fbilinrand(); 76 | float fsum3rand(); 77 | double drand(); 78 | double drand2(double scale); 79 | double linrand(double scale); 80 | double bilinrand(double scale); 81 | double exprandrng(double lo, double hi); 82 | double exprand(double scale); 83 | double biexprand(double scale); 84 | double sum3rand(double scale); 85 | 86 | uint32 s1, s2, s3; // random generator state 87 | }; 88 | 89 | inline void RGen::init(uint32 seed) 90 | { 91 | // humans tend to use small seeds - mess up the bits 92 | seed = (uint32)Hash((int)seed); 93 | 94 | // initialize seeds using the given seed value taking care of 95 | // the requirements. The constants below are arbitrary otherwise 96 | s1 = 1243598713U ^ seed; if (s1 < 2) s1 = 1243598713U; 97 | s2 = 3093459404U ^ seed; if (s2 < 8) s2 = 3093459404U; 98 | s3 = 1821928721U ^ seed; if (s3 < 16) s3 = 1821928721U; 99 | } 100 | 101 | inline uint32 trand( uint32& s1, uint32& s2, uint32& s3 ) 102 | { 103 | // This function is provided for speed in inner loops where the 104 | // state variables are loaded into registers. 105 | // Thus updating the instance variables can 106 | // be postponed until the end of the loop. 107 | s1 = ((s1 & (uint32)-2) << 12) ^ (((s1 << 13) ^ s1) >> 19); 108 | s2 = ((s2 & (uint32)-8) << 4) ^ (((s2 << 2) ^ s2) >> 25); 109 | s3 = ((s3 & (uint32)-16) << 17) ^ (((s3 << 3) ^ s3) >> 11); 110 | return s1 ^ s2 ^ s3; 111 | } 112 | 113 | inline uint32 RGen::trand() 114 | { 115 | // generate a random 32 bit number 116 | 117 | 118 | //C2NIM return ::trand(s1, s2, s3); 119 | 120 | //C2NIM 121 | s1 = ((s1 & (uint32)-2) << 12) ^ (((s1 << 13) ^ s1) >> 19); 122 | s2 = ((s2 & (uint32)-8) << 4) ^ (((s2 << 2) ^ s2) >> 25); 123 | s3 = ((s3 & (uint32)-16) << 17) ^ (((s3 << 3) ^ s3) >> 11); 124 | return s1 ^ s2 ^ s3; 125 | } 126 | 127 | inline double RGen::drand() 128 | { 129 | // return a double from 0.0 to 0.999... 130 | #if BYTE_ORDER == BIG_ENDIAN 131 | union { struct { uint32 hi, lo; } i; double f; } du; 132 | #else 133 | union { struct { uint32 lo, hi; } i; double f; } du; 134 | #endif 135 | du.i.hi = 0x41300000; 136 | du.i.lo = trand(); 137 | return du.f - 1048576.; 138 | } 139 | 140 | inline float RGen::frand() 141 | { 142 | // return a float from 0.0 to 0.999... 143 | union { uint32 i; float f; } u; // union for floating point conversion of result 144 | u.i = 0x3F800000 | (trand() >> 9); 145 | return u.f - 1.f; 146 | } 147 | 148 | inline float RGen::frand0() 149 | { 150 | // return a float from +1.0 to +1.999... 151 | union { uint32 i; float f; } u; // union for floating point conversion of result 152 | u.i = 0x3F800000 | (trand() >> 9); 153 | return u.f; 154 | } 155 | 156 | inline float RGen::frand2() 157 | { 158 | // return a float from -1.0 to +0.999... 159 | union { uint32 i; float f; } u; // union for floating point conversion of result 160 | u.i = 0x40000000 | (trand() >> 9); 161 | return u.f - 3.f; 162 | } 163 | 164 | inline float RGen::frand8() 165 | { 166 | // return a float from -0.125 to +0.124999... 167 | union { uint32 i; float f; } u; // union for floating point conversion of result 168 | u.i = 0x3E800000 | (trand() >> 9); 169 | return u.f - 0.375f; 170 | } 171 | 172 | inline float RGen::fcoin() 173 | { 174 | // only return one of the two values -1.0 or +1.0 175 | union { uint32 i; float f; } u; // union for floating point conversion of result 176 | u.i = 0x3F800000 | (0x80000000 & trand()); 177 | return u.f; 178 | } 179 | 180 | inline float RGen::flinrand() 181 | { 182 | float a = frand(); 183 | float b = frand(); 184 | return sc_min(a,b); 185 | } 186 | 187 | inline float RGen::fbilinrand() 188 | { 189 | float a = frand(); 190 | float b = frand(); 191 | return a - b; 192 | } 193 | 194 | inline float RGen::fsum3rand() 195 | { 196 | // larry polansky's poor man's gaussian generator 197 | return (frand() + frand() + frand() - 1.5) * 0.666666667; 198 | } 199 | 200 | 201 | inline int32 RGen::irand(int32 scale) 202 | { 203 | // return an int from 0 to scale - 1 204 | return (int32)floor(scale * drand()); 205 | } 206 | 207 | inline int32 RGen::irand2(int32 scale) 208 | { 209 | // return a int from -scale to +scale 210 | return (int32)floor((2. * scale + 1.) * drand() - scale); 211 | } 212 | 213 | inline int32 RGen::ilinrand(int32 scale) 214 | { 215 | int32 a = irand(scale); 216 | int32 b = irand(scale); 217 | return sc_min(a,b); 218 | } 219 | 220 | inline double RGen::linrand(double scale) 221 | { 222 | double a = drand(); 223 | double b = drand(); 224 | return sc_min(a,b) * scale; 225 | } 226 | 227 | inline int32 RGen::ibilinrand(int32 scale) 228 | { 229 | int32 a = irand(scale); 230 | int32 b = irand(scale); 231 | return a - b; 232 | } 233 | 234 | inline double RGen::bilinrand(double scale) 235 | { 236 | double a = drand(); 237 | double b = drand(); 238 | return (a - b) * scale; 239 | } 240 | 241 | inline double RGen::exprandrng(double lo, double hi) 242 | { 243 | return lo * exp(log(hi / lo) * drand()); 244 | } 245 | 246 | inline double RGen::exprand(double scale) 247 | { 248 | double z; 249 | while ((z = drand()) == 0.0) {} 250 | return -log(z) * scale; 251 | } 252 | 253 | inline double RGen::biexprand(double scale) 254 | { 255 | double z; 256 | while ((z = drand2(1.)) == 0.0 || z == -1.0) {} 257 | if (z > 0.0) z = log(z); 258 | else z = -log(-z); 259 | return z * scale; 260 | } 261 | 262 | inline double RGen::sum3rand(double scale) 263 | { 264 | // larry polansky's poor man's gaussian generator 265 | return (drand() + drand() + drand() - 1.5) * 0.666666667 * scale; 266 | } 267 | 268 | inline double drand( uint32& s1, uint32& s2, uint32& s3 ) 269 | { 270 | union { struct { uint32 hi, lo; } i; double f; } u; 271 | u.i.hi = 0x41300000; 272 | u.i.lo = trand(s1,s2,s3); 273 | return u.f - 1048576.; 274 | } 275 | 276 | inline float frand( uint32& s1, uint32& s2, uint32& s3 ) 277 | { 278 | // return a float from 0.0 to 0.999... 279 | union { uint32 i; float f; } u; 280 | u.i = 0x3F800000 | (trand(s1,s2,s3) >> 9); 281 | return u.f - 1.f; 282 | } 283 | 284 | inline float frand0( uint32& s1, uint32& s2, uint32& s3 ) 285 | { 286 | // return a float from +1.0 to +1.999... 287 | union { uint32 i; float f; } u; 288 | u.i = 0x3F800000 | (trand(s1,s2,s3) >> 9); 289 | return u.f; 290 | } 291 | 292 | inline float frand2( uint32& s1, uint32& s2, uint32& s3 ) 293 | { 294 | // return a float from -1.0 to +0.999... 295 | union { uint32 i; float f; } u; 296 | u.i = 0x40000000 | (trand(s1,s2,s3) >> 9); 297 | return u.f - 3.f; 298 | } 299 | 300 | inline float frand8( uint32& s1, uint32& s2, uint32& s3 ) 301 | { 302 | // return a float from -0.125 to +0.124999... 303 | union { uint32 i; float f; } u; 304 | u.i = 0x3E800000 | (trand(s1,s2,s3) >> 9); 305 | return u.f - 0.375f; 306 | } 307 | 308 | inline float fcoin( uint32& s1, uint32& s2, uint32& s3 ) 309 | { 310 | // only return one of the two values -1.0 or +1.0 311 | union { uint32 i; float f; } u; 312 | u.i = 0x3F800000 | (0x80000000 & trand(s1,s2,s3)); 313 | return u.f; 314 | } 315 | 316 | 317 | 318 | #endif 319 | 320 | -------------------------------------------------------------------------------- /dev/SC_Rate.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _Rate_ 23 | #define _Rate_ 24 | 25 | enum { calc_ScalarRate, calc_BufRate, calc_FullRate, calc_DemandRate }; 26 | 27 | struct Rate 28 | { 29 | double mSampleRate; // samples per second 30 | double mSampleDur; // seconds per sample 31 | double mBufDuration; // seconds per buffer 32 | double mBufRate; // buffers per second 33 | double mSlopeFactor; // 1. / NumSamples 34 | double mRadiansPerSample; // 2pi / SampleRate 35 | int mBufLength; // length of the buffer 36 | // second order filter loops are often unrolled by 3 37 | int mFilterLoops, mFilterRemain; 38 | double mFilterSlope; 39 | }; 40 | typedef struct Rate Rate; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /dev/SC_Reply.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_Reply_ 23 | #define _SC_Reply_ 24 | 25 | struct ReplyAddress; 26 | typedef void (*ReplyFunc)(struct ReplyAddress *inReplyAddr, char* inBuf, int inSize); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /dev/SC_SndBuf.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | typedef struct SNDFILE_tag SNDFILE; 5 | 6 | #ifndef C2NIM 7 | 8 | #ifdef SUPERNOVA 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __SSE2__ 14 | #include 15 | #endif 16 | 17 | 18 | class rw_spinlock 19 | { 20 | static const uint32_t unlocked_state = 0; 21 | static const uint32_t locked_state = 0x80000000; 22 | static const uint32_t reader_mask = 0x7fffffff; 23 | 24 | //C2NIM #ifdef __SSE2__ 25 | static inline void pause() { _mm_pause(); } 26 | //C2NIM #else 27 | //C2NIM static inline void pause() { } 28 | //C2NIM #endif 29 | 30 | public: 31 | struct unique_lock 32 | { 33 | explicit unique_lock(rw_spinlock & sl) : sl_(sl) { sl_.lock(); } 34 | ~unique_lock() { sl_.unlock(); } 35 | 36 | private: 37 | rw_spinlock & sl_; 38 | }; 39 | 40 | typedef unique_lock unique_lock; 41 | 42 | struct shared_lock 43 | { 44 | explicit shared_lock(rw_spinlock & sl): sl_(sl) { sl_.lock_shared(); } 45 | ~shared_lock() { sl_.unlock_shared(); } 46 | 47 | private: 48 | rw_spinlock & sl_; 49 | }; 50 | 51 | rw_spinlock() = default; 52 | 53 | //C2NIM rw_spinlock(rw_spinlock const & rhs) = delete; 54 | //C2NIM rw_spinlock & operator=(rw_spinlock const & rhs) = delete; 55 | //C2NIM rw_spinlock(rw_spinlock && rhs) = delete; 56 | //C2NIM rw_spinlock & operator=(rw_spinlock & rhs) = delete; 57 | 58 | ~rw_spinlock() { assert(state == unlocked_state); } 59 | 60 | void lock() 61 | { 62 | for (;;) { 63 | while( state.load(std::memory_order_relaxed) != unlocked_state ) 64 | pause(); 65 | 66 | uint32_t expected = unlocked_state; 67 | if( state.compare_exchange_weak(expected, locked_state, std::memory_order_acquire) ) 68 | break; 69 | } 70 | } 71 | 72 | bool try_lock() 73 | { 74 | uint32_t expected = unlocked_state; 75 | if( state.compare_exchange_strong(expected, locked_state, std::memory_order_acquire) ) 76 | return true; 77 | else 78 | return false; 79 | } 80 | 81 | void unlock() 82 | { 83 | assert( state.load(std::memory_order_relaxed) == locked_state) ; 84 | state.store( unlocked_state, std::memory_order_release ); 85 | } 86 | 87 | void lock_shared() 88 | { 89 | for(;;) { 90 | /* with the mask, the cas will fail, locked exclusively */ 91 | uint32_t current_state = state.load( std::memory_order_acquire ) & reader_mask; 92 | const uint32_t next_state = current_state + 1; 93 | 94 | if( state.compare_exchange_weak(current_state, next_state, std::memory_order_acquire) ) 95 | break; 96 | pause(); 97 | } 98 | } 99 | 100 | bool try_lock_shared() 101 | { 102 | /* with the mask, the cas will fail, locked exclusively */ 103 | uint32_t current_state = state.load(std::memory_order_acquire) & reader_mask; 104 | const uint32_t next_state = current_state + 1; 105 | 106 | if( state.compare_exchange_strong(current_state, next_state, std::memory_order_acquire) ) 107 | return true; 108 | else 109 | return false; 110 | } 111 | 112 | void unlock_shared() 113 | { 114 | for(;;) { 115 | uint32_t current_state = state.load(std::memory_order_relaxed); /* we don't need the reader_mask */ 116 | const uint32_t next_state = current_state - 1; 117 | 118 | if( state.compare_exchange_weak(current_state, uint32_t(next_state)) ) 119 | break; 120 | pause(); 121 | } 122 | } 123 | 124 | private: 125 | //C2NIM std::atomic state {unlocked_state}; 126 | std::atomic state[1]; 127 | }; 128 | 129 | #endif 130 | 131 | #endif 132 | 133 | struct SndBuf 134 | { 135 | double samplerate; 136 | double sampledur; // = 1/ samplerate 137 | float *data; 138 | int channels; 139 | int samples; 140 | int frames; 141 | int mask; // for delay lines 142 | int mask1; // for interpolating oscillators. 143 | int coord; // used by fft ugens 144 | SNDFILE *sndfile; // used by disk i/o 145 | // SF_INFO fileinfo; // used by disk i/o 146 | //C2NIM #ifdef SUPERNOVA 147 | //C2NIM bool isLocal; 148 | //C2NIM mutable rw_spinlock lock; 149 | //C2NIM #endif 150 | }; 151 | 152 | typedef struct SndBuf SndBuf; 153 | 154 | struct SndBufUpdates 155 | { 156 | int reads; 157 | int writes; 158 | }; 159 | typedef struct SndBufUpdates SndBufUpdates; 160 | 161 | enum { coord_None, coord_Complex, coord_Polar }; 162 | 163 | inline float PhaseFrac(uint32_t inPhase) 164 | { 165 | union { uint32_t itemp; float ftemp; } u; 166 | u.itemp = 0x3F800000 | (0x007FFF80 & ((inPhase)<<7)); 167 | return u.ftemp - 1.f; 168 | } 169 | 170 | inline float PhaseFrac1(uint32_t inPhase) 171 | { 172 | union { uint32_t itemp; float ftemp; } u; 173 | u.itemp = 0x3F800000 | (0x007FFF80 & ((inPhase)<<7)); 174 | return u.ftemp; 175 | } 176 | 177 | inline float lookup(const float *table, int32_t phase, int32_t mask) 178 | { 179 | return table[(phase >> 16) & mask]; 180 | } 181 | 182 | 183 | #define xlobits 14 184 | #define xlobits1 13 185 | 186 | inline float lookupi(const float *table, uint32_t phase, uint32_t mask) 187 | { 188 | float frac = PhaseFrac(phase); 189 | const float *tbl = table + ((phase >> 16) & mask); 190 | float a = tbl[0]; 191 | float b = tbl[1]; 192 | return a + frac * (b - a); 193 | } 194 | 195 | inline float lookupi2(const float *table, uint32_t phase, uint32_t mask) 196 | { 197 | float frac = PhaseFrac1(phase); 198 | const float *tbl = table + ((phase >> 16) & mask); 199 | float a = tbl[0]; 200 | float b = tbl[1]; 201 | return a + frac * b; 202 | } 203 | 204 | inline float lookupi1(const float* table0, const float* table1, uint32_t pphase, int32_t lomask) 205 | { 206 | float pfrac = PhaseFrac1(pphase); 207 | uint32_t index = ((pphase >> xlobits1) & lomask); 208 | float val1 = *(const float*)((const char*)table0 + index); 209 | float val2 = *(const float*)((const char*)table1 + index); 210 | return val1 + val2 * pfrac; 211 | } 212 | 213 | 214 | inline float lininterp(float x, float a, float b) 215 | { 216 | return a + x * (b - a); 217 | } 218 | 219 | inline float cubicinterp(float x, float y0, float y1, float y2, float y3) 220 | { 221 | // 4-point, 3rd-order Hermite (x-form) 222 | float c0 = y1; 223 | float c1 = 0.5f * (y2 - y0); 224 | float c2 = y0 - 2.5f * y1 + 2.f * y2 - 0.5f * y3; 225 | float c3 = 0.5f * (y3 - y0) + 1.5f * (y1 - y2); 226 | 227 | return ((c3 * x + c2) * x + c1) * x + c0; 228 | } 229 | 230 | 231 | -------------------------------------------------------------------------------- /dev/SC_StringBuffer.h: -------------------------------------------------------------------------------- 1 | // emacs: -*- c++ -*- 2 | // file: SC_StringBuffer.h 3 | // copyright: 2003 stefan kersten 4 | // cvs: $Id$ 5 | 6 | // This program is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU General Public License as 8 | // published by the Free Software Foundation; either version 2 of the 9 | // License, or (at your option) any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, but 12 | // WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | // 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 19 | // USA 20 | 21 | #ifndef SC_STRINGBUFFER_H_INCLUDED 22 | #define SC_STRINGBUFFER_H_INCLUDED 23 | 24 | #include 25 | #include 26 | 27 | // ===================================================================== 28 | // SC_StringBuffer - Autogrowing string buffer. 29 | // ===================================================================== 30 | 31 | class SC_StringBuffer 32 | { 33 | public: 34 | SC_StringBuffer(size_t initialSize=0); 35 | SC_StringBuffer(const SC_StringBuffer& other); 36 | ~SC_StringBuffer(); 37 | 38 | size_t getCapacity() const { return mCapacity; } 39 | size_t getSize() const { return mPtr - mData; } 40 | size_t getRemaining() const { return mCapacity - getSize(); } 41 | char* getData() const { return mData; } 42 | 43 | bool isEmpty() const { return getSize() == 0; } 44 | 45 | void finish() { append('\0'); } 46 | void reset() { mPtr = mData; } 47 | void append(const char* src, size_t len); 48 | void append(char c); 49 | void append(const char* str); 50 | void vappendf(const char* fmt, va_list vargs); 51 | void appendf(const char* fmt, ...); 52 | 53 | protected: 54 | enum { 55 | kGrowAlign = 256, 56 | kGrowMask = kGrowAlign - 1 57 | }; 58 | 59 | void growBy(size_t request); 60 | 61 | private: 62 | size_t mCapacity; 63 | char* mPtr; 64 | char* mData; 65 | }; 66 | 67 | #endif // SC_STRINGBUFFER_H_INCLUDED 68 | -------------------------------------------------------------------------------- /dev/SC_Types.h: -------------------------------------------------------------------------------- 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 | #ifndef _SC_Types_ 22 | #define _SC_Types_ 23 | 24 | #include 25 | #include 26 | 27 | #ifndef C2NIM 28 | 29 | #if !defined(__cplusplus) 30 | # include 31 | #endif // __cplusplus 32 | 33 | #endif 34 | 35 | typedef int SCErr; 36 | 37 | #ifndef C2NIM 38 | typedef int64_t int64; 39 | typedef uint64_t uint64; 40 | 41 | typedef int32_t int32; 42 | typedef uint32_t uint32; 43 | 44 | typedef int16_t int16; 45 | typedef uint16_t uint16; 46 | 47 | typedef int8_t int8; 48 | typedef uint8_t uint8; 49 | #endif; 50 | 51 | typedef float float32; 52 | typedef double float64; 53 | 54 | typedef union { 55 | uint32 u; 56 | int32 i; 57 | float32 f; 58 | } elem32; 59 | 60 | typedef union { 61 | uint64 u; 62 | int64 i; 63 | float64 f; 64 | } elem64; 65 | 66 | const unsigned int kSCNameLen = 8; 67 | const unsigned int kSCNameByteLen = 8 * sizeof(int32); 68 | 69 | #ifdef C2NIM 70 | #define sc_typeof_cast(x) x 71 | #endif 72 | 73 | 74 | #ifndef C2NIM 75 | 76 | #ifdef __GXX_EXPERIMENTAL_CXX0X__ 77 | #define sc_typeof_cast(x) (decltype(x)) 78 | #elif defined(__GNUC__) 79 | #define sc_typeof_cast(x) (__typeof__(x)) 80 | #else 81 | #define sc_typeof_cast(x) /* (typeof(x)) */ 82 | #endif 83 | #endif 84 | 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /dev/SC_Unit.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_Unit_ 23 | #define _SC_Unit_ 24 | 25 | #include "SC_Types.h" 26 | #include "SC_SndBuf.h" 27 | 28 | typedef void (*UnitCtorFunc)(struct Unit* inUnit); 29 | typedef void (*UnitDtorFunc)(struct Unit* inUnit); 30 | 31 | typedef void (*UnitCalcFunc)(struct Unit *inThing, int inNumSamples); 32 | 33 | struct SC_Unit_Extensions { 34 | float * todo; 35 | }; 36 | 37 | struct Unit 38 | { 39 | struct World *mWorld; 40 | struct UnitDef *mUnitDef; 41 | struct Graph *mParent; 42 | uint32 mNumInputs, mNumOutputs; // changed from uint16 for synthdef ver 2 43 | int16 mCalcRate; 44 | int16 mSpecialIndex; // used by unary and binary ops 45 | int16 mParentIndex; 46 | int16 mDone; 47 | struct Wire **mInput, **mOutput; 48 | struct Rate *mRate; 49 | SC_Unit_Extensions* mExtensions; //future proofing and backwards compatibility; used to be SC_Dimension struct pointer 50 | float **mInBuf, **mOutBuf; 51 | 52 | UnitCalcFunc mCalcFunc; 53 | int mBufLength; 54 | }; 55 | 56 | typedef struct Unit Unit; 57 | 58 | enum { 59 | kUnitDef_CantAliasInputsToOutputs = 1 60 | }; 61 | 62 | #ifdef _WIN32 63 | // Win32 headers (included by C std library headers) define IN and OUT macros 64 | // for their own purposes. 65 | #undef IN 66 | #undef OUT 67 | #endif 68 | 69 | // These return float* pointers to input and output buffers. 70 | #define IN(index) (unit->mInBuf[index]) 71 | #define OUT(index) (unit->mOutBuf[index]) 72 | 73 | // These return a float value. Used for control rate inputs and outputs. 74 | #define IN0(index) (IN(index)[0]) 75 | #define OUT0(index) (OUT(index)[0]) 76 | 77 | // get the rate of the input. 78 | #define INRATE(index) (unit->mInput[index]->mCalcRate) 79 | 80 | // get the blocksize of the input 81 | #define INBUFLENGTH(index) (unit->mInput[index]->mFromUnit->mBufLength) 82 | 83 | // set the calculation function 84 | #define SETCALC(func) (unit->mCalcFunc = (UnitCalcFunc)&func) 85 | 86 | // calculate a slope for control rate interpolation to audio rate. 87 | # #define CALCSLOPE(next,prev) ((next - prev) * sc_typeof_cast(next)unit->mRate->mSlopeFactor) 88 | 89 | // get useful values 90 | #define SAMPLERATE (unit->mRate->mSampleRate) 91 | #define SAMPLEDUR (unit->mRate->mSampleDur) 92 | #define BUFLENGTH (unit->mBufLength) 93 | #define BUFRATE (unit->mRate->mBufRate) 94 | #define BUFDUR (unit->mRate->mBufDuration) 95 | #define FULLRATE (unit->mWorld->mFullRate.mSampleRate) 96 | #define FULLBUFLENGTH (unit->mWorld->mFullRate.mBufLength) 97 | 98 | #ifdef SUPERNOVA 99 | 100 | template 101 | struct buffer_lock2 102 | { 103 | buffer_lock2(const SndBuf * buf1, const SndBuf * buf2): 104 | buf1_(buf1), buf2_(buf2) 105 | { 106 | if (buf1 == buf2) { 107 | lock1(); 108 | return; 109 | } 110 | 111 | for(;;) { 112 | lock1(); 113 | 114 | if (lock2()) 115 | return; 116 | unlock1(); 117 | } 118 | } 119 | 120 | ~buffer_lock2(void) 121 | { 122 | unlock1(); 123 | if (buf1_ != buf2_) 124 | unlock2(); 125 | } 126 | 127 | private: 128 | void lock1(void) 129 | { 130 | if (buf1_->isLocal) 131 | return; 132 | 133 | if (!shared1) 134 | buf1_->lock.lock(); 135 | else 136 | buf1_->lock.lock_shared(); 137 | } 138 | 139 | bool lock2(void) 140 | { 141 | if (buf2_->isLocal) 142 | return true; 143 | 144 | if (!shared2) 145 | return buf2_->lock.try_lock(); 146 | else 147 | return buf2_->lock.try_lock_shared(); 148 | } 149 | 150 | void unlock1(void) 151 | { 152 | if (buf1_->isLocal) 153 | return; 154 | 155 | if (!shared1) 156 | buf1_->lock.unlock(); 157 | else 158 | buf1_->lock.unlock_shared(); 159 | } 160 | 161 | void unlock2(void) 162 | { 163 | if (buf2_->isLocal) 164 | return; 165 | 166 | if (!shared2) 167 | buf2_->lock.unlock(); 168 | else 169 | buf2_->lock.unlock_shared(); 170 | } 171 | 172 | const SndBuf * buf1_; 173 | const SndBuf * buf2_; 174 | }; 175 | 176 | template 177 | struct buffer_lock 178 | { 179 | buffer_lock(const SndBuf * buf): 180 | buf_(buf) 181 | { 182 | if (!buf->isLocal) { 183 | if (shared) 184 | buf->lock.lock_shared(); 185 | else 186 | buf->lock.lock(); 187 | } 188 | } 189 | 190 | ~buffer_lock(void) 191 | { 192 | if (!buf_->isLocal) { 193 | if (shared) 194 | buf_->lock.unlock_shared(); 195 | else 196 | buf_->lock.unlock(); 197 | } 198 | } 199 | 200 | const SndBuf * buf_; 201 | }; 202 | 203 | #define ACQUIRE_BUS_AUDIO(index) unit->mWorld->mAudioBusLocks[index].lock() 204 | #define ACQUIRE_BUS_AUDIO_SHARED(index) unit->mWorld->mAudioBusLocks[index].lock_shared() 205 | #define RELEASE_BUS_AUDIO(index) unit->mWorld->mAudioBusLocks[index].unlock() 206 | #define RELEASE_BUS_AUDIO_SHARED(index) unit->mWorld->mAudioBusLocks[index].unlock_shared() 207 | 208 | #C2NIM #define LOCK_SNDBUF(buf) buffer_lock lock_##buf(buf) 209 | #C2NIM #define LOCK_SNDBUF_SHARED(buf) buffer_lock lock_##buf(buf); 210 | 211 | #C2NIM #define LOCK_SNDBUF2(buf1, buf2) buffer_lock2 lock_##buf1##_##buf2(buf1, buf2); 212 | #C2NIM #define LOCK_SNDBUF2_SHARED(buf1, buf2) buffer_lock2 lock_##buf1##_##buf2(buf1, buf2); 213 | #C2NIM #define LOCK_SNDBUF2_EXCLUSIVE_SHARED(buf1, buf2) buffer_lock2 lock_##buf1##_##buf2(buf1, buf2); 214 | #C2NIM #define LOCK_SNDBUF2_SHARED_EXCLUSIVE(buf1, buf2) buffer_lock2 lock_##buf1##_##buf2(buf1, buf2); 215 | 216 | #define ACQUIRE_SNDBUF(buf) do { if (!buf->isLocal) buf->lock.lock(); } while (false) 217 | #define ACQUIRE_SNDBUF_SHARED(buf) do { if (!buf->isLocal) buf->lock.lock_shared(); } while (false) 218 | #define RELEASE_SNDBUF(buf) do { if (!buf->isLocal) buf->lock.unlock(); } while (false) 219 | #define RELEASE_SNDBUF_SHARED(buf) do { if (!buf->isLocal) buf->lock.unlock_shared(); } while (false) 220 | 221 | 222 | #define ACQUIRE_BUS_CONTROL(index) unit->mWorld->mControlBusLock->lock() 223 | #define RELEASE_BUS_CONTROL(index) unit->mWorld->mControlBusLock->unlock() 224 | 225 | #else 226 | 227 | #define ACQUIRE_BUS_AUDIO(index) 228 | #define ACQUIRE_BUS_AUDIO_SHARED(index) 229 | #define RELEASE_BUS_AUDIO(index) 230 | #define RELEASE_BUS_AUDIO_SHARED(index) 231 | 232 | #define LOCK_SNDBUF(buf) 233 | #define LOCK_SNDBUF_SHARED(buf) 234 | 235 | #define LOCK_SNDBUF2(buf1, buf2) 236 | #define LOCK_SNDBUF2_SHARED(buf1, buf2) 237 | #define LOCK_SNDBUF2_EXCLUSIVE_SHARED(buf1, buf2) 238 | #define LOCK_SNDBUF2_SHARED_EXCLUSIVE(buf1, buf2) 239 | 240 | #define ACQUIRE_SNDBUF(buf) 241 | #define ACQUIRE_SNDBUF_SHARED(buf) 242 | #define RELEASE_SNDBUF(buf) 243 | #define RELEASE_SNDBUF_SHARED(buf) 244 | 245 | #define ACQUIRE_BUS_CONTROL(index) 246 | #define RELEASE_BUS_CONTROL(index) 247 | 248 | #endif 249 | 250 | /* 251 | 252 | C2NIM 253 | 254 | // macros to grab a Buffer reference from the buffer indicated by the UGen's FIRST input 255 | #define GET_BUF \ 256 | float fbufnum = ZIN0(0); \ 257 | if (fbufnum < 0.f) { fbufnum = 0.f; } \ 258 | if (fbufnum != unit->m_fbufnum) { \ 259 | uint32 bufnum = (int)fbufnum; \ 260 | World *world = unit->mWorld; \ 261 | if (bufnum >= world->mNumSndBufs) { \ 262 | int localBufNum = bufnum - world->mNumSndBufs; \ 263 | Graph *parent = unit->mParent; \ 264 | if(localBufNum <= parent->localBufNum) { \ 265 | unit->m_buf = parent->mLocalSndBufs + localBufNum; \ 266 | } else { \ 267 | bufnum = 0; \ 268 | unit->m_buf = world->mSndBufs + bufnum; \ 269 | } \ 270 | } else { \ 271 | unit->m_buf = world->mSndBufs + bufnum; \ 272 | } \ 273 | unit->m_fbufnum = fbufnum; \ 274 | } \ 275 | SndBuf *buf = unit->m_buf; \ 276 | LOCK_SNDBUF(buf); \ 277 | float *bufData __attribute__((__unused__)) = buf->data; \ 278 | float *bufData __attribute__((__unused__)) = buf->data; \ 279 | uint32 bufChannels __attribute__((__unused__)) = buf->channels; \ 280 | uint32 bufSamples __attribute__((__unused__)) = buf->samples; \ 281 | uint32 bufFrames = buf->frames; \ 282 | int mask __attribute__((__unused__)) = buf->mask; \ 283 | int guardFrame __attribute__((__unused__)) = bufFrames - 2; 284 | 285 | #define GET_BUF_SHARED \ 286 | float fbufnum = ZIN0(0); \ 287 | if (fbufnum < 0.f) { fbufnum = 0.f; } \ 288 | if (fbufnum != unit->m_fbufnum) { \ 289 | uint32 bufnum = (int)fbufnum; \ 290 | World *world = unit->mWorld; \ 291 | if (bufnum >= world->mNumSndBufs) { \ 292 | int localBufNum = bufnum - world->mNumSndBufs; \ 293 | Graph *parent = unit->mParent; \ 294 | if(localBufNum <= parent->localBufNum) { \ 295 | unit->m_buf = parent->mLocalSndBufs + localBufNum; \ 296 | } else { \ 297 | bufnum = 0; \ 298 | unit->m_buf = world->mSndBufs + bufnum; \ 299 | } \ 300 | } else { \ 301 | unit->m_buf = world->mSndBufs + bufnum; \ 302 | } \ 303 | unit->m_fbufnum = fbufnum; \ 304 | } \ 305 | const SndBuf *buf = unit->m_buf; \ 306 | LOCK_SNDBUF_SHARED(buf); \ 307 | const float *bufData __attribute__((__unused__)) = buf->data; \ 308 | uint32 bufChannels __attribute__((__unused__)) = buf->channels; \ 309 | uint32 bufSamples __attribute__((__unused__)) = buf->samples; \ 310 | uint32 bufFrames = buf->frames; \ 311 | int mask __attribute__((__unused__)) = buf->mask; \ 312 | int guardFrame __attribute__((__unused__)) = bufFrames - 2; 313 | 314 | #define SIMPLE_GET_BUF \ 315 | float fbufnum = ZIN0(0); \ 316 | fbufnum = sc_max(0.f, fbufnum); \ 317 | if (fbufnum != unit->m_fbufnum) { \ 318 | uint32 bufnum = (int)fbufnum; \ 319 | World *world = unit->mWorld; \ 320 | if (bufnum >= world->mNumSndBufs) { \ 321 | int localBufNum = bufnum - world->mNumSndBufs; \ 322 | Graph *parent = unit->mParent; \ 323 | if(localBufNum <= parent->localBufNum) { \ 324 | unit->m_buf = parent->mLocalSndBufs + localBufNum; \ 325 | } else { \ 326 | bufnum = 0; \ 327 | unit->m_buf = world->mSndBufs + bufnum; \ 328 | } \ 329 | } else { \ 330 | unit->m_buf = world->mSndBufs + bufnum; \ 331 | } \ 332 | unit->m_fbufnum = fbufnum; \ 333 | } \ 334 | SndBuf *buf = unit->m_buf; \ 335 | 336 | #define SIMPLE_GET_BUF_EXCLUSIVE \ 337 | SIMPLE_GET_BUF; \ 338 | LOCK_SNDBUF(buf); 339 | 340 | #define SIMPLE_GET_BUF_SHARED \ 341 | SIMPLE_GET_BUF; \ 342 | LOCK_SNDBUF_SHARED(buf); 343 | 344 | // macros to get pseudo-random number generator, and put its state in registers 345 | #define RGET \ 346 | RGen& rgen = *unit->mParent->mRGen; \ 347 | uint32 s1 = rgen.s1; \ 348 | uint32 s2 = rgen.s2; \ 349 | uint32 s3 = rgen.s3; 350 | #define RPUT \ 351 | rgen.s1 = s1; \ 352 | rgen.s2 = s2; \ 353 | rgen.s3 = s3; 354 | C2NIM */ 355 | 356 | typedef void (*UnitCmdFunc)(struct Unit *unit, struct sc_msg_iter *args); 357 | typedef void (*PlugInCmdFunc)(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr); 358 | 359 | #endif 360 | -------------------------------------------------------------------------------- /dev/SC_Wire.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_Wire_ 23 | #define _SC_Wire_ 24 | 25 | #include "SC_Types.h" 26 | 27 | struct Wire 28 | { 29 | struct Unit *mFromUnit; 30 | int32 mCalcRate; 31 | float32 *mBuffer; 32 | float32 mScalarValue; 33 | }; 34 | typedef struct Wire Wire; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /dev/SC_World.h: -------------------------------------------------------------------------------- 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 | 22 | 23 | #include "SC_Types.h" 24 | #include "SC_Rate.h" 25 | #include "SC_SndBuf.h" 26 | #include "SC_RGen.h" 27 | 28 | #ifdef SUPERNOVA 29 | namespace nova 30 | { 31 | class spin_lock; 32 | class padded_rw_spinlock; 33 | } 34 | #endif 35 | 36 | struct World 37 | { 38 | // a pointer to private implementation, not available to plug-ins. 39 | struct HiddenWorld *hw; 40 | 41 | // a pointer to the table of function pointers that implement the plug-ins' 42 | // interface to the server. 43 | struct InterfaceTable *ft; 44 | 45 | // data accessible to plug-ins : 46 | double mSampleRate; 47 | int mBufLength; 48 | int mBufCounter; 49 | 50 | uint32 mNumAudioBusChannels; 51 | uint32 mNumControlBusChannels; 52 | uint32 mNumInputs; 53 | uint32 mNumOutputs; 54 | 55 | // vector of samples for all audio busses 56 | float *mAudioBus; 57 | 58 | // vector of samples for all control busses 59 | float *mControlBus; 60 | 61 | // these tell if a bus has been written to during a control period 62 | // if the value is equal to mBufCounter then the buss has been touched 63 | // this control period. 64 | int32 *mAudioBusTouched; 65 | int32 *mControlBusTouched; 66 | 67 | uint32 mNumSndBufs; 68 | SndBuf *mSndBufs; 69 | SndBuf *mSndBufsNonRealTimeMirror; 70 | SndBufUpdates *mSndBufUpdates; 71 | 72 | struct Group *mTopGroup; 73 | 74 | Rate mFullRate, mBufRate; 75 | 76 | uint32 mNumRGens; 77 | RGen *mRGen; 78 | 79 | uint32 mNumUnits, mNumGraphs, mNumGroups; 80 | int mSampleOffset; // offset in the buffer of current event time. 81 | 82 | void * mNRTLock; 83 | 84 | uint32 mNumSharedControls; 85 | float *mSharedControls; 86 | 87 | bool mRealTime; 88 | bool mRunning; 89 | int mDumpOSC; 90 | 91 | void* mDriverLock; 92 | 93 | float mSubsampleOffset; // subsample accurate offset in the buffer of current event time. 94 | 95 | int mVerbosity; 96 | int mErrorNotification; 97 | int mLocalErrorNotification; 98 | 99 | bool mRendezvous; // Allow user to disable Rendezvous 100 | 101 | const char* mRestrictedPath; // OSC commands to read/write data can only do it within this path, if specified 102 | 103 | /*C2NIM 104 | #ifdef SUPERNOVA 105 | nova::padded_rw_spinlock * mAudioBusLocks; 106 | nova::spin_lock * mControlBusLock; 107 | #endif 108 | */ 109 | 110 | }; 111 | 112 | inline SndBuf* World_GetBuf(struct World *inWorld, uint32 index) 113 | { 114 | if (index > inWorld->mNumSndBufs) index = 0; 115 | return inWorld->mSndBufs + index; 116 | } 117 | 118 | inline SndBuf* World_GetNRTBuf(struct World *inWorld, uint32 index) 119 | { 120 | if (index > inWorld->mNumSndBufs) index = 0; 121 | return inWorld->mSndBufsNonRealTimeMirror + index; 122 | } 123 | 124 | typedef void (*LoadPlugInFunc)(struct InterfaceTable *); 125 | typedef void (*UnLoadPlugInFunc)(); 126 | -------------------------------------------------------------------------------- /dev/SC_WorldOptions.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _SC_WorldOptions_ 23 | #define _SC_WorldOptions_ 24 | 25 | #include 26 | #include "SC_Reply.h" 27 | #include "SC_Types.h" 28 | #include "SC_Export.h" 29 | 30 | typedef int (*PrintFunc)(const char *format, va_list ap); 31 | 32 | struct WorldOptions 33 | { 34 | const char* mPassword; 35 | uint32 mNumBuffers; 36 | uint32 mMaxLogins; 37 | uint32 mMaxNodes; 38 | uint32 mMaxGraphDefs; 39 | uint32 mMaxWireBufs; 40 | uint32 mNumAudioBusChannels; 41 | uint32 mNumInputBusChannels; 42 | uint32 mNumOutputBusChannels; 43 | uint32 mNumControlBusChannels; 44 | uint32 mBufLength; 45 | uint32 mRealTimeMemorySize; 46 | 47 | int mNumSharedControls; 48 | float *mSharedControls; 49 | 50 | bool mRealTime; 51 | bool mMemoryLocking; 52 | 53 | const char *mNonRealTimeCmdFilename; 54 | const char *mNonRealTimeInputFilename; 55 | const char *mNonRealTimeOutputFilename; 56 | const char *mNonRealTimeOutputHeaderFormat; 57 | const char *mNonRealTimeOutputSampleFormat; 58 | 59 | uint32 mPreferredSampleRate; 60 | uint32 mNumRGens; 61 | 62 | uint32 mPreferredHardwareBufferFrameSize; 63 | 64 | uint32 mLoadGraphDefs; 65 | 66 | const char *mInputStreamsEnabled; 67 | const char *mOutputStreamsEnabled; 68 | const char *mInDeviceName; 69 | 70 | int mVerbosity; 71 | 72 | bool mRendezvous; 73 | 74 | const char *mUGensPluginPath; 75 | 76 | const char *mOutDeviceName; 77 | 78 | const char *mRestrictedPath; 79 | 80 | int mSharedMemoryID; 81 | }; 82 | 83 | const struct WorldOptions kDefaultWorldOptions = 84 | { 85 | 0,1024,64,1024,1024,64,1024,8,8,16384,64,8192, 0,0, 1, 0, 0,0,0,0,0 86 | #if defined(_WIN32) 87 | ,44100 88 | #else 89 | ,0 90 | #endif 91 | ,64, 0, 1 92 | ,0, 0, 0 93 | ,0 94 | ,1 95 | ,0 96 | ,0 97 | ,0 98 | ,0 99 | }; 100 | 101 | struct SndBuf; 102 | 103 | SCSYNTH_DLLEXPORT_C void SetPrintFunc(PrintFunc func); 104 | SCSYNTH_DLLEXPORT_C struct World* World_New(struct WorldOptions *inOptions); 105 | SCSYNTH_DLLEXPORT_C void World_Cleanup(struct World *inWorld, bool unload_plugins = false); 106 | SCSYNTH_DLLEXPORT_C void World_NonRealTimeSynthesis(struct World *inWorld, struct WorldOptions *inOptions); 107 | SCSYNTH_DLLEXPORT_C int World_OpenUDP(struct World *inWorld, const char *bindTo, int inPort); 108 | SCSYNTH_DLLEXPORT_C int World_OpenTCP(struct World *inWorld, const char *bindTo, int inPort, int inMaxConnections, int inBacklog); 109 | SCSYNTH_DLLEXPORT_C void World_WaitForQuit(struct World *inWorld, bool unload_plugins = false); 110 | SCSYNTH_DLLEXPORT_C bool World_SendPacket(struct World *inWorld, int inSize, char *inData, ReplyFunc inFunc); 111 | SCSYNTH_DLLEXPORT_C bool World_SendPacketWithContext(struct World *inWorld, int inSize, char *inData, ReplyFunc inFunc, void *inContext); 112 | SCSYNTH_DLLEXPORT_C int World_CopySndBuf(struct World *world, uint32 index, struct SndBuf *outBuf, bool onlyIfChanged, bool *didChange); 113 | SCSYNTH_DLLEXPORT_C int scprintf(const char *fmt, ...); 114 | 115 | #endif // _SC_WorldOptions_ 116 | -------------------------------------------------------------------------------- /dev/SC_fftlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | SC_fftlib.h 3 | An interface to abstract over different FFT libraries, for SuperCollider 3. 4 | Copyright (c) 2008 Dan Stowell. All rights reserved. 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 | 22 | #ifndef _SC_fftlib_ 23 | #define _SC_fftlib_ 24 | 25 | #include 26 | 27 | // These specify the min & max FFT sizes expected (used when creating windows, also allocating some other arrays). 28 | #define SC_FFT_MINSIZE 8 29 | #define SC_FFT_LOG2_MINSIZE 3 30 | #define SC_FFT_MAXSIZE 32768 31 | #define SC_FFT_LOG2_MAXSIZE 15 32 | 33 | 34 | // Note that things like *fftWindow actually allow for other sizes, to be created on user request. 35 | #define SC_FFT_ABSOLUTE_MAXSIZE 262144 36 | #define SC_FFT_LOG2_ABSOLUTE_MAXSIZE 18 37 | #define SC_FFT_LOG2_ABSOLUTE_MAXSIZE_PLUS1 19 38 | 39 | struct scfft; 40 | 41 | class SCFFT_Allocator 42 | { 43 | public: 44 | virtual void* alloc(size_t size) = 0; 45 | virtual void free(void* ptr) = 0; 46 | }; 47 | 48 | enum SCFFT_Direction 49 | { 50 | kForward = 1, 51 | kBackward = 0 52 | }; 53 | 54 | // These values are referred to from SC lang as well as in the following code - do not rearrange! 55 | enum SCFFT_WindowFunction 56 | { 57 | kRectWindow = -1, 58 | kSineWindow = 0, 59 | kHannWindow = 1 60 | }; 61 | 62 | //////////////////////////////////////////////////////////////////////////////////////////////////// 63 | // Functions 64 | 65 | // To initialise a specific FFT, ensure your input and output buffers exist. Internal data structures 66 | // will be allocated using the alloc object, 67 | // Both "fullsize" and "winsize" should be powers of two (this is not checked internally). 68 | scfft * scfft_create(size_t fullsize, size_t winsize, SCFFT_WindowFunction wintype, 69 | float *indata, float *outdata, SCFFT_Direction forward, SCFFT_Allocator & alloc); 70 | 71 | // These two will take data from indata, use trbuf to process it, and put their results in outdata. 72 | void scfft_dofft(scfft *f); 73 | void scfft_doifft(scfft *f); 74 | 75 | // destroy any resources held internally. 76 | void scfft_destroy(scfft *f, SCFFT_Allocator & alloc); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /dev/SC_sndfile_stub.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 1999-2009 Erik de Castro Lopo 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify 5 | ** it under the terms of the GNU Lesser General Public License as published by 6 | ** the Free Software Foundation; either version 2.1 of the License, or 7 | ** (at your option) any later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU Lesser General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU Lesser General Public License 15 | ** along with this program; if not, write to the Free Software 16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | 19 | /* 20 | ** SC_sndfile_stub.h -- stub of libsndfile definitions, used to preserve binary compatibility when libsndfile unavailable 21 | ** taken from sndfile.h 22 | **/ 23 | 24 | 25 | 26 | /* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ 27 | 28 | typedef struct SNDFILE_tag SNDFILE ; 29 | 30 | 31 | //C2VIM #if (defined (_MSCVER) || defined (_MSC_VER)) 32 | //C2VIM typedef __int64_t sf_count_t ; 33 | //C2vim #define SF_COUNT_MAX 0x7fffffffffffffffi64 34 | //C2vim #else 35 | typedef int sf_count_t ; 36 | #define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL 37 | //C2VIM#endif 38 | 39 | 40 | /* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in. 41 | ** On write, the SF_INFO structure is filled in by the user and passed into 42 | ** sf_open_write (). 43 | */ 44 | 45 | struct SF_INFO 46 | { sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ 47 | int samplerate ; 48 | int channels ; 49 | int format ; 50 | int sections ; 51 | int seekable ; 52 | } ; 53 | 54 | typedef struct SF_INFO SF_INFO ; 55 | 56 | 57 | -------------------------------------------------------------------------------- /dev/ScopeBuffer.h: -------------------------------------------------------------------------------- 1 | 2 | // From InterfaceTable 3 | // 4 | class ScopeBufferHnd 5 | { 6 | void *internalData; 7 | float *data; 8 | uint32 channels; 9 | uint32 maxFrames; 10 | 11 | float *channel_data( uint32 channel ) { 12 | return data + (channel * maxFrames); 13 | } 14 | 15 | operator bool () 16 | { 17 | return internalData != 0; 18 | } 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /dev/Unroll.h: -------------------------------------------------------------------------------- 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 | /* 22 | 23 | These macros allow one to write code which can be compiled optimally depending on 24 | what loop constructs the compiler can best generate code. 25 | 26 | */ 27 | 28 | #ifndef _Unroll_ 29 | #define _Unroll_ 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /dev/clz.h: -------------------------------------------------------------------------------- 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 | 22 | count leading zeroes function and those that can be derived from it 23 | 24 | */ 25 | 26 | 27 | #ifndef _CLZ_ 28 | #define _CLZ_ 29 | 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /dev/function_attributes.h: -------------------------------------------------------------------------------- 1 | /* 2 | SuperCollider real time audio synthesis system 3 | Copyright (c) 2011 Tim Blechmann. All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef FUNCTION_ATTRIBUTES_H 21 | #define FUNCTION_ATTRIBUTES_H 22 | 23 | #ifdef __GNUC__ 24 | 25 | #ifdef _WIN32 26 | #undef PURE 27 | #endif 28 | 29 | #define CONST_FUNCTION __attribute__((const)) 30 | #define PURE __attribute__((pure)) 31 | 32 | #define MALLOC __attribute__((malloc)) 33 | #define ASSUME_ALIGNED(Alignment) __attribute__((assume_aligned(Alignment))) 34 | #define HOT __attribute__((hot)) 35 | #define COLD __attribute__((cold)) 36 | #define FLATTEN __attribute__((flatten)) 37 | 38 | #endif 39 | 40 | #ifdef __clang__ 41 | #undef HOT 42 | #undef FLATTEN 43 | #undef ASSUME_ALIGNED 44 | #endif 45 | 46 | #ifdef __PATHCC__ 47 | #undef HOT 48 | #undef FLATTEN 49 | #endif 50 | 51 | 52 | #ifdef _MSC_VER 53 | #ifndef PURE 54 | #define PURE /*PURE*/ 55 | #endif 56 | 57 | #ifndef CONST_FUNCTION 58 | #define CONST_FUNCTION /*CONST_FUNCTION*/ 59 | #endif 60 | #endif 61 | 62 | #ifndef MALLOC 63 | #define MALLOC /*MALLOC*/ 64 | #endif 65 | 66 | #ifndef HOT 67 | #define HOT /*HOT*/ 68 | #endif 69 | 70 | #ifndef COLD 71 | #define COLD /*COLD*/ 72 | #endif 73 | 74 | #ifndef FLATTEN 75 | #define FLATTEN /*FLATTEN*/ 76 | #endif 77 | 78 | #ifndef ASSUME_ALIGNED 79 | #define ASSUME_ALIGNED(Alignment) /* assume aligned Alignment */ 80 | #endif 81 | 82 | // provide c99-style __restrict__ 83 | #if defined(__GNUC__) || defined(__CLANG__) 84 | // __restrict__ defined 85 | #else 86 | #define __restrict__ /* __restrict */ 87 | #endif 88 | 89 | // force inlining in release mode 90 | #ifndef NDEBUG 91 | #define force_inline inline 92 | #else 93 | 94 | #if defined(__GNUC__) 95 | #define force_inline inline __attribute__((always_inline)) 96 | #elif defined(_MSVER) 97 | #define force_inline __forceinline 98 | #else 99 | #define force_inline inline 100 | #endif 101 | 102 | #endif 103 | 104 | 105 | 106 | #endif /* FUNCTION_ATTRIBUTES_H */ 107 | -------------------------------------------------------------------------------- /dev/minimal-host/Makefile: -------------------------------------------------------------------------------- 1 | 2 | src=/home/carlo/supercollider 3 | 4 | all: main 5 | 6 | main: main.cpp 7 | g++ -I $(src)/include/common -I $(src)/include/lang -I $(src)/include/plugin_interface -I $(src)/include/server main.cpp -ldl -o min 8 | 9 | clean: 10 | rm -f min 11 | 12 | -------------------------------------------------------------------------------- /dev/minimal-host/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | bool defu(const char *inName, size_t inAllocSize, UnitCtorFunc inCtor, UnitDtorFunc inDtor, uint32 inFlags) 13 | { 14 | std::ofstream log("/tmp/main.log", std::ios_base::app | std::ios_base::out); 15 | 16 | std::time_t result = std::time(nullptr); 17 | log << "ctor " << std::asctime(std::localtime(&result)) << ""; 18 | 19 | printf("main.cpp: defu\n"); 20 | std::cout << "foo"; 21 | return true; 22 | } 23 | 24 | bool defu2(const char *inName, size_t inAllocSize, uint32 inFlags) 25 | { 26 | std::ofstream log("/tmp/main.log", std::ios_base::app | std::ios_base::out); 27 | 28 | std::time_t result = std::time(nullptr); 29 | log << "ctor " << std::asctime(std::localtime(&result)) << ""; 30 | 31 | printf("main.cpp: defu2\n"); 32 | std::cout << "foo"; 33 | return true; 34 | } 35 | 36 | bool defu3(const char *inName, UnitCtorFunc inCtor, size_t inAllocSize, uint32 inFlags) 37 | { 38 | std::ofstream log("/tmp/main.log", std::ios_base::app | std::ios_base::out); 39 | 40 | std::time_t result = std::time(nullptr); 41 | log << "ctor " << std::asctime(std::localtime(&result)) << ""; 42 | 43 | printf("main.cpp: defu3\n"); 44 | std::cout << "foo"; 45 | return true; 46 | } 47 | 48 | 49 | void defum() 50 | { 51 | std::ofstream log("/tmp/main.log", std::ios_base::app | std::ios_base::out); 52 | 53 | std::time_t result = std::time(nullptr); 54 | log << "ctor " << std::asctime(std::localtime(&result)) << ""; 55 | 56 | printf("main.cpp: defum\n"); 57 | std::cout << "foo"; 58 | } 59 | 60 | int main() { 61 | void *handle; 62 | 63 | handle = dlopen ("/home/carlo/OscarUGens/OscarUGens.so", RTLD_NOW); 64 | void *ptr = dlsym(handle, "load"); 65 | if (!ptr) { 66 | std::string c = dlerror(); 67 | printf("main.cpp: dlsym load err '%s'\n", c); 68 | dlclose(handle); 69 | return false; 70 | } 71 | 72 | LoadPlugInFunc loadFunc = (LoadPlugInFunc)ptr; 73 | 74 | printf("main.cpp: loadFunc address: %i\n", loadFunc); 75 | 76 | InterfaceTable ft; 77 | ft.fDefineUnit = &defu; 78 | printf("main.cpp: InterfaceTable address: %i\n", &ft); 79 | printf("main.cpp: fDefineUnit address: %i\n", ft.fDefineUnit); 80 | 81 | //printf("main.cpp: exec direct first\n"); 82 | //ctor(); 83 | 84 | printf("main.cpp: exec dynamically loaded\n"); 85 | (*loadFunc)(&ft); 86 | 87 | //printf("main.cpp: exec direct second\n"); 88 | //defu(); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /dev/sc_msg_iter.h: -------------------------------------------------------------------------------- 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 | 22 | #ifndef _sc_msg_iter_ 23 | #define _sc_msg_iter_ 24 | 25 | #include "SC_Endian.h" 26 | #include "SC_Types.h" 27 | #include 28 | 29 | #[ 30 | 31 | // return the ptr to the byte after the OSC string. 32 | inline const char* OSCstrskip(const char *str) 33 | { 34 | // while (str[3]) { str += 4; } 35 | // return str + 4; 36 | do { str += 4; } while (str[-1]); 37 | return str; 38 | } 39 | 40 | // returns the number of bytes (including padding) for an OSC string. 41 | inline size_t OSCstrlen(const char *strin) 42 | { 43 | return OSCstrskip(strin) - strin; 44 | } 45 | 46 | // returns a float, converting an int if necessary 47 | inline float32 OSCfloat(const char* inData) 48 | { 49 | elem32 elem; 50 | elem.u = sc_ntohl(*(uint32*)inData); 51 | return elem.f; 52 | } 53 | 54 | inline int32 OSCint(const char* inData) 55 | { 56 | return (int32)sc_ntohl(*(uint32*)inData); 57 | } 58 | 59 | inline int64 OSCtime(const char* inData) 60 | { 61 | return ((int64)sc_ntohl(*(uint32*)inData) << 32) + (sc_ntohl(*(uint32*)(inData + 4))); 62 | } 63 | 64 | inline float64 OSCdouble(const char* inData) 65 | { 66 | elem64 slot; 67 | slot.i = ((int64)sc_ntohl(*(uint32*)inData) << 32) + (sc_ntohl(*(uint32*)(inData + 4))); 68 | return slot.f; 69 | } 70 | 71 | ]# 72 | 73 | struct sc_msg_iter 74 | { 75 | const char *data, *rdpos, *endpos, *tags; 76 | int size, count; 77 | 78 | sc_msg_iter(); 79 | sc_msg_iter(int inSize, const char* inData); 80 | void init(int inSize, const char* inData); 81 | int64 gett(int64 defaultValue = 1); 82 | int32 geti(int32 defaultValue = 0); 83 | float32 getf(float32 defaultValue = 0.f); 84 | float64 getd(float64 defaultValue = 0.f); 85 | const char *gets(const char* defaultValue = 0); 86 | int32 *gets4(char* defaultValue = 0); 87 | size_t getbsize(); 88 | void getb(char* outData, size_t inSize); 89 | void skipb(); 90 | size_t remain() { return endpos - rdpos; } 91 | 92 | char nextTag(char defaultTag = 'f') { return tags ? tags[count] : defaultTag; } 93 | }; 94 | 95 | /*C2NIM 96 | inline sc_msg_iter::sc_msg_iter() 97 | { 98 | } 99 | 100 | inline sc_msg_iter::sc_msg_iter(int inSize, const char* inData) 101 | { 102 | init(inSize, inData); 103 | } 104 | 105 | inline void sc_msg_iter::init(int inSize, const char* inData) 106 | { 107 | data = inData; 108 | size = inSize; 109 | endpos = data + size; 110 | count = 0; 111 | if (data[0] == ',') { 112 | tags = data+1; 113 | rdpos = OSCstrskip(data); 114 | } else { 115 | tags = 0; 116 | rdpos = data; 117 | } 118 | } 119 | 120 | inline int64 sc_msg_iter::gett(int64 defaultValue) 121 | { 122 | int64 value; 123 | if (remain() <= 0) return defaultValue; 124 | if (tags) { 125 | if (tags[count] == 't') { 126 | value = OSCtime(rdpos); 127 | rdpos += sizeof(int64); 128 | } else { 129 | value = defaultValue; 130 | } 131 | } else { 132 | value = OSCtime(rdpos); 133 | rdpos += sizeof(int64); 134 | } 135 | count++; 136 | return value; 137 | } 138 | 139 | inline int32 sc_msg_iter::geti(int32 defaultValue) 140 | { 141 | int value; 142 | if (remain() <= 0) return defaultValue; 143 | if (tags) { 144 | if (tags[count] == 'i') { 145 | value = OSCint(rdpos); 146 | rdpos += sizeof(int32); 147 | } else if (tags[count] == 'f') { 148 | value = (int32)OSCfloat(rdpos); 149 | rdpos += sizeof(float32); 150 | } else if (tags[count] == 's') { 151 | value = defaultValue; 152 | rdpos = OSCstrskip(rdpos); 153 | } else if (tags[count] == 'b') { 154 | value = defaultValue; 155 | skipb(); 156 | } else { 157 | value = defaultValue; 158 | } 159 | } else { 160 | value = (int)OSCint(rdpos); 161 | rdpos += sizeof(int32); 162 | } 163 | count ++; 164 | return value; 165 | } 166 | 167 | inline float32 sc_msg_iter::getf(float32 defaultValue) 168 | { 169 | float32 value; 170 | if (remain() <= 0) return defaultValue; 171 | if (tags) { 172 | if (tags[count] == 'f') { 173 | value = OSCfloat(rdpos); 174 | rdpos += sizeof(float32); 175 | } else if (tags[count] == 'd') { 176 | value = static_cast(OSCdouble(rdpos)); 177 | rdpos += sizeof(float64); 178 | } else if (tags[count] == 'i') { 179 | value = static_cast(OSCint(rdpos)); 180 | rdpos += sizeof(int32); 181 | } else if (tags[count] == 's') { 182 | value = defaultValue; 183 | rdpos = OSCstrskip(rdpos); 184 | } else if (tags[count] == 'b') { 185 | value = defaultValue; 186 | skipb(); 187 | } else { 188 | value = defaultValue; 189 | } 190 | } else { 191 | value = OSCfloat(rdpos); 192 | rdpos += sizeof(float32); 193 | } 194 | count ++; 195 | return value; 196 | } 197 | 198 | inline float64 sc_msg_iter::getd(float64 defaultValue) 199 | { 200 | float64 value; 201 | if (remain() <= 0) return defaultValue; 202 | if (tags) { 203 | if (tags[count] == 'f') { 204 | value = (float64)OSCfloat(rdpos); 205 | rdpos += sizeof(float32); 206 | } else if (tags[count] == 'd') { 207 | value = OSCdouble(rdpos); 208 | rdpos += sizeof(float64); 209 | } else if (tags[count] == 'i') { 210 | value = (float64)OSCint(rdpos); 211 | rdpos += sizeof(int32); 212 | } else if (tags[count] == 's') { 213 | value = defaultValue; 214 | rdpos = OSCstrskip(rdpos); 215 | } else if (tags[count] == 'b') { 216 | value = defaultValue; 217 | skipb(); 218 | } else { 219 | value = defaultValue; 220 | } 221 | } else { 222 | value = OSCdouble(rdpos); 223 | rdpos += sizeof(float64); 224 | } 225 | count ++; 226 | return value; 227 | } 228 | 229 | 230 | inline const char* sc_msg_iter::gets(const char* defaultValue) 231 | { 232 | const char* value; 233 | if (remain() <= 0) return 0; 234 | if (tags) { 235 | if (tags[count] == 's') { 236 | value = rdpos; 237 | rdpos = OSCstrskip(rdpos); 238 | } else { 239 | value = defaultValue; 240 | } 241 | } else { 242 | value = rdpos; 243 | rdpos = OSCstrskip(rdpos); 244 | } 245 | count ++; 246 | return value; 247 | } 248 | 249 | inline int32* sc_msg_iter::gets4(char* defaultValue) 250 | { 251 | int32* value; 252 | if (remain() <= 0) return 0; 253 | if (tags) { 254 | if (tags[count] == 's') { 255 | value = (int32*)rdpos; 256 | rdpos = OSCstrskip(rdpos); 257 | } else { 258 | value = (int32*)defaultValue; 259 | } 260 | } else { 261 | value = (int32*)rdpos; 262 | rdpos = OSCstrskip(rdpos); 263 | } 264 | count ++; 265 | return value; 266 | } 267 | 268 | inline size_t sc_msg_iter::getbsize() 269 | { 270 | size_t len = 0; 271 | if (remain() <= 0) return 0; 272 | if (tags) { 273 | if (tags[count] == 'b') 274 | len = OSCint(rdpos); 275 | else if (tags[count] == 'm') 276 | len = 4; 277 | } 278 | return len; 279 | } 280 | 281 | inline void sc_msg_iter::getb(char* outArray, size_t size) 282 | { 283 | size_t len = 0; 284 | if (tags[count] == 'b') { 285 | len = OSCint(rdpos); 286 | if (size < len) return; 287 | rdpos += sizeof(int32); 288 | } else if (tags[count] == 'm') { 289 | len = 4; 290 | if (size < len) return; 291 | } 292 | size_t len4 = (len + 3) & (size_t)-4; 293 | memcpy(outArray, rdpos, size); 294 | rdpos += len4; 295 | count ++; 296 | } 297 | 298 | inline void sc_msg_iter::skipb() 299 | { 300 | size_t len = 0; 301 | if (tags[count] == 'b') 302 | { 303 | len = OSCint(rdpos); 304 | rdpos += sizeof(int32); 305 | } else if (tags[count] == 'm') 306 | len = 4; 307 | size_t len4 = (len + 3) & (size_t)-4; 308 | rdpos += len4; 309 | count ++; 310 | } 311 | */ 312 | #endif 313 | -------------------------------------------------------------------------------- /dev/stdint.h: -------------------------------------------------------------------------------- 1 | 2 | #define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* Exact integral types. */ 9 | 10 | /* Signed. */ 11 | #include 12 | 13 | /* Unsigned. */ 14 | #include 15 | 16 | 17 | /* Small types. */ 18 | 19 | /* Signed. */ 20 | typedef signed char int_least8_t; 21 | typedef short int int_least16_t; 22 | typedef int int_least32_t; 23 | #if __WORDSIZE == 64 24 | typedef long int int_least64_t; 25 | #else 26 | //-__extension__ 27 | typedef long long int int_least64_t; 28 | #endif 29 | 30 | /* Unsigned. */ 31 | typedef unsigned char uint_least8_t; 32 | typedef unsigned short int uint_least16_t; 33 | typedef unsigned int uint_least32_t; 34 | #if __WORDSIZE == 64 35 | typedef unsigned long int uint_least64_t; 36 | #else 37 | //-__extension__ 38 | typedef unsigned long long int uint_least64_t; 39 | #endif 40 | 41 | 42 | /* Fast types. */ 43 | 44 | /* Signed. */ 45 | typedef signed char int_fast8_t; 46 | #if __WORDSIZE == 64 47 | typedef long int int_fast16_t; 48 | typedef long int int_fast32_t; 49 | typedef long int int_fast64_t; 50 | #else 51 | typedef int int_fast16_t; 52 | typedef int int_fast32_t; 53 | //-__extension__ 54 | typedef long long int int_fast64_t; 55 | #endif 56 | 57 | /* Unsigned. */ 58 | typedef unsigned char uint_fast8_t; 59 | #if __WORDSIZE == 64 60 | typedef unsigned long int uint_fast16_t; 61 | typedef unsigned long int uint_fast32_t; 62 | typedef unsigned long int uint_fast64_t; 63 | #else 64 | typedef unsigned int uint_fast16_t; 65 | typedef unsigned int uint_fast32_t; 66 | //-__extension__ 67 | typedef unsigned long long int uint_fast64_t; 68 | #endif 69 | 70 | 71 | /* Types for `void *' pointers. */ 72 | #if __WORDSIZE == 64 73 | # ifndef __intptr_t_defined 74 | typedef long int intptr_t; 75 | # define __intptr_t_defined 76 | # endif 77 | typedef unsigned long int uintptr_t; 78 | #else 79 | # ifndef __intptr_t_defined 80 | typedef int intptr_t; 81 | # define __intptr_t_defined 82 | # endif 83 | typedef unsigned int uintptr_t; 84 | #endif 85 | 86 | 87 | /* Largest integral types. */ 88 | typedef __intmax_t intmax_t; 89 | typedef __uintmax_t uintmax_t; 90 | 91 | 92 | //-# if __WORDSIZE == 64 93 | //-# define __INT64_C(c) c ## L 94 | //-# define __UINT64_C(c) c ## UL 95 | //-# else 96 | //-# define __INT64_C(c) c ## LL 97 | //-# define __UINT64_C(c) c ## ULL 98 | //-# endif 99 | 100 | /* Limits of integral types. */ 101 | 102 | /* Minimum of signed integral types. */ 103 | # define INT8_MIN (-128) 104 | # define INT16_MIN (-32767-1) 105 | # define INT32_MIN (-2147483647-1) 106 | # define INT64_MIN (-__INT64_C(9223372036854775807)-1) 107 | /* Maximum of signed integral types. */ 108 | # define INT8_MAX (127) 109 | # define INT16_MAX (32767) 110 | # define INT32_MAX (2147483647) 111 | # define INT64_MAX (__INT64_C(9223372036854775807)) 112 | 113 | /* Maximum of unsigned integral types. */ 114 | # define UINT8_MAX (255) 115 | # define UINT16_MAX (65535) 116 | # define UINT32_MAX (4294967295U) 117 | //-# define UINT64_MAX (__UINT64_C(18446744073709551615)) 118 | 119 | 120 | /* Minimum of signed integral types having a minimum size. */ 121 | # define INT_LEAST8_MIN (-128) 122 | # define INT_LEAST16_MIN (-32767-1) 123 | # define INT_LEAST32_MIN (-2147483647-1) 124 | # define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1) 125 | /* Maximum of signed integral types having a minimum size. */ 126 | # define INT_LEAST8_MAX (127) 127 | # define INT_LEAST16_MAX (32767) 128 | # define INT_LEAST32_MAX (2147483647) 129 | # define INT_LEAST64_MAX (__INT64_C(9223372036854775807)) 130 | 131 | /* Maximum of unsigned integral types having a minimum size. */ 132 | # define UINT_LEAST8_MAX (255) 133 | # define UINT_LEAST16_MAX (65535) 134 | # define UINT_LEAST32_MAX (4294967295U) 135 | //-# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615)) 136 | 137 | 138 | /* Minimum of fast signed integral types having a minimum size. */ 139 | # define INT_FAST8_MIN (-128) 140 | # if __WORDSIZE == 64 141 | # define INT_FAST16_MIN (-9223372036854775807L-1) 142 | # define INT_FAST32_MIN (-9223372036854775807L-1) 143 | # else 144 | # define INT_FAST16_MIN (-2147483647-1) 145 | # define INT_FAST32_MIN (-2147483647-1) 146 | # endif 147 | //-# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1) 148 | /* Maximum of fast signed integral types having a minimum size. */ 149 | # define INT_FAST8_MAX (127) 150 | # if __WORDSIZE == 64 151 | # define INT_FAST16_MAX (9223372036854775807L) 152 | # define INT_FAST32_MAX (9223372036854775807L) 153 | # else 154 | # define INT_FAST16_MAX (2147483647) 155 | # define INT_FAST32_MAX (2147483647) 156 | # endif 157 | # define INT_FAST64_MAX (__INT64_C(9223372036854775807)) 158 | 159 | /* Maximum of fast unsigned integral types having a minimum size. */ 160 | # define UINT_FAST8_MAX (255) 161 | # if __WORDSIZE == 64 162 | //-# define UINT_FAST16_MAX (18446744073709551615UL) 163 | //-# define UINT_FAST32_MAX (18446744073709551615UL) 164 | # else 165 | # define UINT_FAST16_MAX (4294967295U) 166 | # define UINT_FAST32_MAX (4294967295U) 167 | # endif 168 | //-# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615)) 169 | 170 | 171 | /* Values to test for integral types holding `void *' pointer. */ 172 | # if __WORDSIZE == 64 173 | # define INTPTR_MIN (-9223372036854775807L-1) 174 | # define INTPTR_MAX (9223372036854775807L) 175 | //-# define UINTPTR_MAX (18446744073709551615UL) 176 | # else 177 | # define INTPTR_MIN (-2147483647-1) 178 | # define INTPTR_MAX (2147483647) 179 | # define UINTPTR_MAX (4294967295U) 180 | # endif 181 | 182 | 183 | /* Minimum for largest signed integral type. */ 184 | # define INTMAX_MIN (-__INT64_C(9223372036854775807)-1) 185 | /* Maximum for largest signed integral type. */ 186 | # define INTMAX_MAX (__INT64_C(9223372036854775807)) 187 | 188 | /* Maximum for largest unsigned integral type. */ 189 | //-# define UINTMAX_MAX (__UINT64_C(18446744073709551615)) 190 | 191 | 192 | /* Limits of other integer types. */ 193 | 194 | /* Limits of `ptrdiff_t' type. */ 195 | # if __WORDSIZE == 64 196 | # define PTRDIFF_MIN (-9223372036854775807L-1) 197 | # define PTRDIFF_MAX (9223372036854775807L) 198 | # else 199 | # if __WORDSIZE32_PTRDIFF_LONG 200 | # define PTRDIFF_MIN (-2147483647L-1) 201 | # define PTRDIFF_MAX (2147483647L) 202 | # else 203 | # define PTRDIFF_MIN (-2147483647-1) 204 | # define PTRDIFF_MAX (2147483647) 205 | # endif 206 | # endif 207 | 208 | /* Limits of `sig_atomic_t'. */ 209 | # define SIG_ATOMIC_MIN (-2147483647-1) 210 | # define SIG_ATOMIC_MAX (2147483647) 211 | 212 | /* Limit of `size_t' type. */ 213 | # if __WORDSIZE == 64 214 | //-# define SIZE_MAX (18446744073709551615UL) 215 | # else 216 | # if __WORDSIZE32_SIZE_ULONG 217 | # define SIZE_MAX (4294967295UL) 218 | # else 219 | # define SIZE_MAX (4294967295U) 220 | # endif 221 | # endif 222 | 223 | /* Limits of `wchar_t'. */ 224 | # ifndef WCHAR_MIN 225 | /* These constants might also be defined in . */ 226 | # define WCHAR_MIN __WCHAR_MIN 227 | # define WCHAR_MAX __WCHAR_MAX 228 | # endif 229 | 230 | /* Limits of `wint_t'. */ 231 | # define WINT_MIN (0u) 232 | # define WINT_MAX (4294967295u) 233 | 234 | /* Signed. */ 235 | # define INT8_C(c) c 236 | # define INT16_C(c) c 237 | # define INT32_C(c) c 238 | //-# if __WORDSIZE == 64 239 | //-# define INT64_C(c) c ## L 240 | //-# else 241 | //-# define INT64_C(c) c ## LL 242 | //-# endif 243 | 244 | /* Unsigned. */ 245 | # define UINT8_C(c) c 246 | # define UINT16_C(c) c 247 | //-# define UINT32_C(c) c ## U 248 | # if __WORDSIZE == 64 249 | //-# define UINT64_C(c) c ## UL 250 | # else 251 | //-# define UINT64_C(c) c ## ULL 252 | # endif 253 | 254 | /* Maximal type. */ 255 | //-# if __WORDSIZE == 64 256 | //-# define INTMAX_C(c) c ## L 257 | //-# define UINTMAX_C(c) c ## UL 258 | //-# else 259 | //-# define INTMAX_C(c) c ## LL 260 | //-# define UINTMAX_C(c) c ## ULL 261 | //-# endif 262 | 263 | #if __GLIBC_USE (IEC_60559_BFP_EXT) 264 | 265 | # define INT8_WIDTH 8 266 | # define UINT8_WIDTH 8 267 | # define INT16_WIDTH 16 268 | # define UINT16_WIDTH 16 269 | # define INT32_WIDTH 32 270 | # define UINT32_WIDTH 32 271 | # define INT64_WIDTH 64 272 | # define UINT64_WIDTH 64 273 | 274 | # define INT_LEAST8_WIDTH 8 275 | # define UINT_LEAST8_WIDTH 8 276 | # define INT_LEAST16_WIDTH 16 277 | # define UINT_LEAST16_WIDTH 16 278 | # define INT_LEAST32_WIDTH 32 279 | # define UINT_LEAST32_WIDTH 32 280 | # define INT_LEAST64_WIDTH 64 281 | # define UINT_LEAST64_WIDTH 64 282 | 283 | # define INT_FAST8_WIDTH 8 284 | # define UINT_FAST8_WIDTH 8 285 | # define INT_FAST16_WIDTH __WORDSIZE 286 | # define UINT_FAST16_WIDTH __WORDSIZE 287 | # define INT_FAST32_WIDTH __WORDSIZE 288 | # define UINT_FAST32_WIDTH __WORDSIZE 289 | # define INT_FAST64_WIDTH 64 290 | # define UINT_FAST64_WIDTH 64 291 | 292 | # define INTPTR_WIDTH __WORDSIZE 293 | # define UINTPTR_WIDTH __WORDSIZE 294 | 295 | # define INTMAX_WIDTH 64 296 | # define UINTMAX_WIDTH 64 297 | 298 | # define PTRDIFF_WIDTH __WORDSIZE 299 | # define SIG_ATOMIC_WIDTH 32 300 | # define SIZE_WIDTH __WORDSIZE 301 | # define WCHAR_WIDTH 32 302 | # define WINT_WIDTH 32 303 | 304 | #endif 305 | 306 | -------------------------------------------------------------------------------- /dev/wintime.h: -------------------------------------------------------------------------------- 1 | #ifndef WINTIME_H 2 | #define WINTIME_H 3 | 4 | #include // for timeval struct 5 | #include 6 | 7 | /* 8 | Implementation as per: 9 | The Open Group Base Specifications, Issue 6 10 | IEEE Std 1003.1, 2004 Edition 11 | 12 | The timezone pointer arg is ignored. Errors are ignored. 13 | */ 14 | inline int gettimeofday(struct timeval* p, void* tz /* IGNORED */) 15 | { 16 | union { 17 | long long ns100; /*time since 1 Jan 1601 in 100ns units */ 18 | FILETIME ft; 19 | } now; 20 | 21 | GetSystemTimeAsFileTime(&(now.ft)); 22 | p->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL); 23 | p->tv_sec = (long)((now.ns100 - (116444736000000000LL)) / 10000000LL); 24 | return 0; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | ExampleUGens.so 2 | 3 | -------------------------------------------------------------------------------- /example/ExampleUGens.nim: -------------------------------------------------------------------------------- 1 | 2 | import scnim 3 | 4 | proc api_version(): int {.cdecl,exportc,dynlib.} = 5 | return sc_api_version; 6 | 7 | proc server_type(): ServerType {.cdecl,exportc,dynlib.}= 8 | return when defined(SUPERNOVA): sc_server_supernova else: sc_server_scsynth 9 | 10 | var ft: ptr InterfaceTable 11 | 12 | type 13 | Example = object of Unit 14 | 15 | proc next(unit: ptr Example, numSamples: cint) {.cdecl,exportc,dynlib.} = 16 | var 17 | input = unit.mInBuf[] 18 | output = unit.mOutBuf[] 19 | 20 | for i in 0..numSamples: 21 | output[i] = input[i] 22 | 23 | proc ctor(unit: ptr Example) {.cdecl,exportc,dynlib.} = 24 | unit.mCalcFunc = cast[UnitCalcFunc](next) 25 | 26 | proc load(inTable: ptr InterfaceTable) {.cdecl,exportc,dynlib.} = 27 | ft = inTable; 28 | discard ft.fDefineUnit("Example", sizeof(Example), cast[UnitCtorFunc](ctor), nil, 0'u32) 29 | 30 | -------------------------------------------------------------------------------- /example/ExampleUGens.nims: -------------------------------------------------------------------------------- 1 | 2 | switch("deadCodeElim", "on") 3 | switch("gc", "none") 4 | switch("out", "ExampleUGens.so") 5 | switch("app", "lib") 6 | 7 | task build, "build": 8 | setCommand("cpp") 9 | 10 | -------------------------------------------------------------------------------- /example/ExampleUGens.sc: -------------------------------------------------------------------------------- 1 | Example : PureUGen { 2 | *ar { 3 | arg in; 4 | ^this.multiNew('audio', in) 5 | } 6 | *kr { 7 | arg in; 8 | ^this.multiNew('control', in) 9 | } 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | 2 | Example UGens 3 | ============= 4 | 5 | An example UGen written in the Nim programming language to serve as a starting point. 6 | 7 | This program copies the first input to the first output 8 | 9 | Build 10 | ----- 11 | 12 | *Install dependencies* 13 | 14 | - Install the [Nim compiler](https://nim-lang.org) 15 | 16 | - Install scnim 17 | 18 | nimble install scnim 19 | 20 | *Build* 21 | 22 | nim build ExampleUGens.nim 23 | 24 | *Install* 25 | 26 | After building, copy the entire folder to your SuperCollider extensions 27 | 28 | # Linux 29 | cp -R $(pwd) ~/.local/share/SuperCollider/Extensions 30 | 31 | *Run* 32 | 33 | Open `example.scd` in a SuperCollider IDE and run it 34 | 35 | License 36 | ------- 37 | Copyright (c) 2018 Example. Licensed under the GNU General Public License 2.0 or later. 38 | 39 | -------------------------------------------------------------------------------- /example/example.scd: -------------------------------------------------------------------------------- 1 | 2 | (fork {s.bootSync; 3 | x.free;x={ 4 | var input, output; 5 | input = DC.ar(1.234); 6 | input.poll(2, "input"); 7 | output = Example.ar(input); 8 | output.poll(2, "output"); 9 | }.play; 10 | }) 11 | 12 | -------------------------------------------------------------------------------- /scnim.nim: -------------------------------------------------------------------------------- 1 | 2 | include scnim/PlugIn 3 | 4 | -------------------------------------------------------------------------------- /scnim.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "0.0.1" 4 | author = "Carlo Capocasa" 5 | description = "Develop SuperCollider UGens in Nim" 6 | license = "MIT" 7 | 8 | skipDirs = @["example", "dev"] 9 | -------------------------------------------------------------------------------- /scnim/Alloca.nim: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scnim/BoundsMacros.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | template sc_abs*(a: untyped): untyped = 4 | abs(a) 5 | 6 | template sc_max*(a, b: untyped): untyped = 7 | (if ((a) > (b)): (a) else: (b)) 8 | 9 | template sc_min*(a, b: untyped): untyped = 10 | (if ((a) < (b)): (a) else: (b)) 11 | 12 | proc sc_clip*[T; U; V](x: T; lo: U; hi: V): T {.inline.} = 13 | return max(min(x, cast[T](hi)), cast[T](lo)) 14 | -------------------------------------------------------------------------------- /scnim/BufGen.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Types, World, SndBuf, msg_iter 5 | 6 | type 7 | BufGenFunc* = proc (world: ptr World; buf: ptr SndBuf; msg: ptr msg_iter) 8 | BufGen* {.bycopy.} = object 9 | #mBufGenName*: array[kSCNameLen, int32] 10 | mBufGenName*: array[8, int32] 11 | mHash*: int32 12 | mBufGenFunc*: BufGenFunc 13 | 14 | 15 | 16 | #proc BufGen_Create*(inName: cstring; inFunc: BufGenFunc): bool 17 | -------------------------------------------------------------------------------- /scnim/DemandUnit.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /scnim/Endian.nim: -------------------------------------------------------------------------------- 1 | const 2 | LITTLE_ENDIAN* = 1234 3 | BIG_ENDIAN* = 4321 4 | BYTE_ORDER* = LITTLE_ENDIAN 5 | #[ 6 | proc sc_htonl*(x: cuint): cuint {.inline.} = 7 | when BYTE_ORDER == LITTLE_ENDIAN: 8 | var s: ptr cuchar = cast[ptr cuchar](addr(x)) 9 | return cast[cuint]((s[0] shl 24 or s[1] shl 16 or s[2] shl 8 or s[3])) 10 | else: 11 | return x 12 | 13 | proc sc_htons*(x: cushort): cushort {.inline.} = 14 | when BYTE_ORDER == LITTLE_ENDIAN: 15 | var s: ptr cuchar = cast[ptr cuchar](addr(x)) 16 | return cast[cushort]((s[0] shl 8 or s[1])) 17 | else: 18 | return x 19 | 20 | proc sc_ntohl*(x: cuint): cuint {.inline.} = 21 | return sc_htonl(x) 22 | 23 | proc sc_ntohs*(x: cushort): cushort {.inline.} = 24 | return sc_htons(x) 25 | ]# 26 | 27 | -------------------------------------------------------------------------------- /scnim/Export.nim: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scnim/FifoMsg.nim: -------------------------------------------------------------------------------- 1 | 2 | import 3 | World 4 | 5 | type 6 | FifoMsgFunc* = proc (a2: ptr FifoMsg) 7 | FifoMsg* {.bycopy.} = object 8 | mPerformFunc*: FifoMsgFunc 9 | mFreeFunc*: FifoMsgFunc 10 | mData*: pointer 11 | 12 | 13 | proc constructFifoMsg*(): FifoMsg {.constructor.} = 14 | discard 15 | 16 | #proc Set*(this: var FifoMsg; inWorld: ptr World; inPerform: FifoMsgFunc; 17 | # inFree: FifoMsgFunc; inData: pointer) 18 | #proc Perform*(this: var FifoMsg) 19 | #proc Free*(this: var FifoMsg) 20 | var mWorld*: ptr World 21 | 22 | #[ 23 | proc Set*(this: var FifoMsg; inWorld: ptr World; inPerform: FifoMsgFunc; inFree: FifoMsgFunc; inData: pointer) {.inline} = 24 | mWorld = inWorld 25 | mPerformFunc = inPerform 26 | mFreeFunc = inFree 27 | mData = inData 28 | 29 | proc Perform*(this: var FifoMsg) {.inline.} = 30 | if mPerformFunc: (mPerformFunc)(this) 31 | 32 | proc Free*(this: var FifoMsg) {.inline.} = 33 | if mFreeFunc: (mFreeFunc)(this) 34 | ]# 35 | 36 | -------------------------------------------------------------------------------- /scnim/Graph.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Node, Rate, SndBuf, Wire, Unit, RGen 5 | 6 | 7 | type 8 | Graph* {.bycopy.} = object 9 | mNode*: Node 10 | mNumWires*: uint32 11 | mNumControls*: uint32 12 | mControls*: ptr cfloat 13 | mMapControls*: ptr ptr cfloat 14 | mAudioBusOffsets*: ptr int32 15 | mControlRates*: ptr cint 16 | mNumUnits*: uint32 17 | mNumCalcUnits*: uint32 18 | mSampleOffset*: cint 19 | mSubsampleOffset*: cfloat 20 | mLocalSndBufs*: ptr SndBuf 21 | localBufNum*: cint 22 | localMaxBufNum*: cint 23 | 24 | 25 | var mWire*: ptr Unit.Wire 26 | 27 | var mUnits*: ptr ptr Unit 28 | 29 | var mCalcUnits*: ptr ptr Unit 30 | 31 | var mRGen*: ptr RGen 32 | 33 | var mLocalAudioBusUnit*: ptr Unit 34 | 35 | var mLocalControlBusUnit*: ptr Unit 36 | 37 | -------------------------------------------------------------------------------- /scnim/Hash.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Types, Endian 5 | 6 | #[ 7 | 8 | proc Hash*(inKey: cstring): int32 {.inline.} = 9 | var hash: int32 = 0 10 | while inKey[]: 11 | inc(hash, inc(inKey)[]) 12 | inc(hash, hash shl 10) 13 | hash = hash xor hash shr 6 14 | 15 | inc(hash, hash shl 3) 16 | hash = hash xor hash shr 11 17 | inc(hash, hash shl 15) 18 | return hash 19 | 20 | 21 | proc Hash*(inKey: cstring; outLength: ptr csize): int32 {.inline.} = 22 | var origKey: cstring = inKey 23 | var hash: int32 = 0 24 | while inKey[]: 25 | inc(hash, inc(inKey)[]) 26 | inc(hash, hash shl 10) 27 | hash = hash xor hash shr 6 28 | 29 | inc(hash, hash shl 3) 30 | hash = hash xor hash shr 11 31 | inc(hash, hash shl 15) 32 | outLength[] = inKey - origKey 33 | return hash 34 | 35 | 36 | proc Hash*(inKey: cstring; inLength: int32): int32 {.inline.} = 37 | var hash: int32 = 0 38 | var i: cint = 0 39 | while i < inLength: 40 | inc(hash, inc(inKey)[]) 41 | inc(hash, hash shl 10) 42 | hash = hash xor hash shr 6 43 | inc(i) 44 | 45 | inc(hash, hash shl 3) 46 | hash = hash xor hash shr 11 47 | inc(hash, hash shl 15) 48 | return hash 49 | 50 | 51 | proc Hash*(inKey: int32): int32 {.inline.} = 52 | var hash: uint32 = cast[uint32](inKey) 53 | inc(hash, not (hash shl 15)) 54 | hash = hash xor hash shr 10 55 | inc(hash, hash shl 3) 56 | hash = hash xor hash shr 6 57 | inc(hash, not (hash shl 11)) 58 | hash = hash xor hash shr 16 59 | return cast[int32](hash) 60 | 61 | proc Hash64*(inKey: int64): int64 {.inline.} = 62 | var hash: uint64 = cast[uint64](inKey) 63 | inc(hash, not (hash shl 32)) 64 | hash = hash xor (hash shr 22) 65 | inc(hash, not (hash shl 13)) 66 | hash = hash xor (hash shr 8) 67 | inc(hash, (hash shl 3)) 68 | hash = hash xor (hash shr 15) 69 | inc(hash, not (hash shl 27)) 70 | hash = hash xor (hash shr 31) 71 | return cast[int64](hash) 72 | 73 | proc Hash*(inKey: ptr int32; inLength: int32): int32 {.inline.} = 74 | var hash: int32 = 0 75 | var i: cint = 0 76 | while i < inLength: 77 | hash = Hash(hash + inc(inKey)[]) 78 | inc(i) 79 | 80 | return hash 81 | 82 | when BYTE_ORDER == LITTLE_ENDIAN: 83 | var kLASTCHAR*: int32 = 0xFF000000 84 | else: 85 | var kLASTCHAR*: int32 = 0x000000FF 86 | proc Hash*(inKey: ptr int32): int32 {.inline.} = 87 | var hash: int32 = 0 88 | var c: int32 89 | while true: 90 | c = inc(inKey)[] 91 | hash = Hash(hash + c) 92 | if not (c and kLASTCHAR): break 93 | return hash 94 | 95 | ]# 96 | 97 | -------------------------------------------------------------------------------- /scnim/InlineBinaryOp.nim: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scnim/InlineUnaryOp.nim: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scnim/InterfaceTable.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | var sc_api_version: cint = 3 4 | 5 | export sc_api_version 6 | 7 | import 8 | Types, SndBuf, Unit, BufGen, FifoMsg, fftlib, Export, Node, sndfile_stub, World 9 | 10 | type 11 | scfft = object 12 | 13 | AsyncStageFn* = proc (inWorld: ptr World; cmdData: pointer): bool {.cdecl.} 14 | AsyncFreeFn* = proc (inWorld: ptr World; cmdData: pointer) {.cdecl.} 15 | 16 | include 17 | ScopeBuffer 18 | 19 | type 20 | InterfaceTable* {.bycopy} = object 21 | mSineSize*: cuint 22 | mSineWavetable*: ptr Types.float32 23 | mSine*: ptr Types.float32 24 | mCosecant*: ptr Types.float32 25 | fPrint*: proc (fmt: cstring): cint {.cdecl,varargs.} 26 | fRanSeed*: proc (): int32 {.cdecl.} 27 | fDefineUnit*: proc (inUnitClassName: cstring; inAllocSize: csize; 28 | inCtor: UnitCtorFunc; inDtor: UnitDtorFunc; inFlags: uint32): bool {.cdecl.} 29 | fDefinePlugInCmd*: proc (inCmdName: cstring; inFunc: PlugInCmdFunc; 30 | inUserData: pointer): bool {.cdecl.} 31 | fDefineUnitCmd*: proc (inUnitClassName: cstring; inCmdName: cstring; 32 | inFunc: UnitCmdFunc): bool {.cdecl.} 33 | fDefineBufGen*: proc (inName: cstring; inFunc: BufGenFunc): bool {.cdecl.} 34 | fClearUnitOutputs*: proc (inUnit: ptr Unit; inNumSamples: cint) {.cdecl.} 35 | fNRTAlloc*: proc (inSize: csize): pointer {.cdecl.} 36 | fNRTRealloc*: proc (inPtr: pointer; inSize: csize): pointer {.cdecl.} 37 | fNRTFree*: proc (inPtr: pointer) {.cdecl.} 38 | fRTAlloc*: proc (inWorld: ptr World; inSize: csize): pointer {.cdecl.} 39 | fRTRealloc*: proc (inWorld: ptr World; inPtr: pointer; inSize: csize): pointer {.cdecl.} 40 | fRTFree*: proc (inWorld: ptr World; inPtr: pointer) {.cdecl.} 41 | fNodeRun*: proc (node: ptr Node; run: cint) {.cdecl.} 42 | fNodeEnd*: proc (graph: ptr Node) {.cdecl.} 43 | fSendTrigger*: proc (inNode: ptr Node; triggerID: cint; value: cfloat) {.cdecl.} 44 | fSendNodeReply*: proc (inNode: ptr Node; replyID: cint; cmdName: cstring; 45 | numArgs: cint; values: ptr cfloat) {.cdecl.} 46 | fSendMsgFromRT*: proc (inWorld: ptr World; inMsg: FifoMsg): bool {.cdecl.} 47 | fSendMsgToRT*: proc (inWorld: ptr World; inMsg: FifoMsg): bool {.cdecl.} 48 | fSndFileFormatInfoFromStrings*: proc (info: ptr SF_INFO; 49 | headerFormatString: cstring; 50 | sampleFormatString: cstring): cint {.cdecl.} 51 | fGetNode*: proc (inWorld: ptr World; inID: cint): ptr Node {.cdecl.} 52 | fGetGraph*: proc (inWorld: ptr World; inID: cint): ptr Graph {.cdecl.} 53 | fNRTLock*: proc (inWorld: ptr World) {.cdecl.} 54 | fNRTUnlock*: proc (inWorld: ptr World) {.cdecl.} 55 | mUnused0*: bool 56 | fGroup_DeleteAll*: proc (group: ptr Group) {.cdecl.} 57 | fDoneAction*: proc (doneAction: cint; unit: ptr Unit) {.cdecl.} 58 | fDoAsynchronousCommand*: proc (inWorld: ptr World; replyAddr: pointer; 59 | cmdName: cstring; cmdData: pointer; 60 | stage2: AsyncStageFn; stage3: AsyncStageFn; 61 | stage4: AsyncStageFn; cleanup: AsyncFreeFn; 62 | completionMsgSize: cint; 63 | completionMsgData: pointer): cint {.cdecl.} 64 | fBufAlloc*: proc (inBuf: ptr SndBuf; inChannels: cint; inFrames: cint; 65 | inSampleRate: cdouble): cint {.cdecl.} 66 | fSCfftCreate*: proc (fullsize: csize; winsize: csize; 67 | wintype: SCFFT_WindowFunction; indata: ptr cfloat; 68 | outdata: ptr cfloat; forward: SCFFT_Direction; 69 | alloc: SCFFT_Allocator): ptr scfft {.cdecl.} 70 | fSCfftDoFFT*: proc (f: ptr scfft) {.cdecl.} 71 | fSCfftDoIFFT*: proc (f: ptr scfft) {.cdecl.} 72 | fSCfftDestroy*: proc (f: ptr scfft; alloc: SCFFT_Allocator) {.cdecl.} 73 | fGetScopeBuffer*: proc (inWorld: ptr World; index: cint; channels: cint; 74 | maxFrames: cint; a6: ScopeBufferHnd): bool {.cdecl.} 75 | fPushScopeBuffer*: proc (inWorld: ptr World; a3: ScopeBufferHnd; frames: cint) {.cdecl.} 76 | fReleaseScopeBuffer*: proc (inWorld: ptr World; a3: ScopeBufferHnd) {.cdecl.} 77 | 78 | #[ 79 | const 80 | Print* = (ft.fPrint[]) 81 | RanSeed* = (ft.fRanSeed[]) 82 | NodeEnd* = (ft.fNodeEnd[]) 83 | NodeRun* = (ft.fNodeRun[]) 84 | DefineUnit* = (ft.fDefineUnit[]) 85 | DefinePlugInCmd* = (ft.fDefinePlugInCmd[]) 86 | DefineUnitCmd* = (ft.fDefineUnitCmd[]) 87 | DefineBufGen* = (ft.fDefineBufGen[]) 88 | ClearUnitOutputs* = (ft.fClearUnitOutputs[]) 89 | SendTrigger* = (ft.fSendTrigger[]) 90 | SendNodeReply* = (ft.fSendNodeReply[]) 91 | SendMsgFromRT* = (ft.fSendMsgFromRT[]) 92 | SendMsgToRT* = (ft.fSendMsgToRT[]) 93 | DoneAction* = (ft.fDoneAction[]) 94 | NRTAlloc* = (ft.fNRTAlloc[]) 95 | NRTRealloc* = (ft.fNRTRealloc[]) 96 | NRTFree* = (ft.fNRTFree[]) 97 | RTAlloc* = (ft.fRTAlloc[]) 98 | RTRealloc* = (ft.fRTRealloc[]) 99 | RTFree* = (ft.fRTFree[]) 100 | GetNode* = (ft.fGetNode[]) 101 | GetGraph* = (ft.fGetGraph[]) 102 | NRTLock* = (ft.fNRTLock[]) 103 | NRTUnlock* = (ft.fNRTUnlock[]) 104 | BufAlloc* = (ft.fBufAlloc[]) 105 | GroupDeleteAll* = (ft.fGroup_DeleteAll[]) 106 | SndFileFormatInfoFromStrings* = (ft.fSndFileFormatInfoFromStrings[]) 107 | DoAsynchronousCommand* = (ft.fDoAsynchronousCommand[]) 108 | ]# 109 | 110 | type 111 | ServerType* = enum 112 | sc_server_scsynth = 0, sc_server_supernova = 1 113 | 114 | 115 | #[ 116 | const 117 | scfft_create* = (ft.fSCfftCreate[]) 118 | scfft_dofft* = (ft.fSCfftDoFFT[]) 119 | scfft_doifft* = (ft.fSCfftDoIFFT[]) 120 | scfft_destroy* = (ft.fSCfftDestroy[]) 121 | ]# 122 | 123 | -------------------------------------------------------------------------------- /scnim/Node.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Types, World 5 | 6 | type 7 | NodeDef* = object 8 | NodeCalcFunc* = proc (inNode: ptr Node) 9 | Node* {.bycopy.} = object 10 | mID*: int32 11 | mHash*: int32 12 | mCalcFunc*: NodeCalcFunc 13 | mIsGroup*: int32 14 | 15 | 16 | var mWorld*: ptr World 17 | 18 | var mDef*: ptr NodeDef 19 | 20 | var 21 | mPrev*: ptr Node 22 | mNext*: ptr Node 23 | 24 | var mParent*: ptr Group 25 | 26 | 27 | const 28 | kNode_Go* = 0 29 | kNode_End* = 1 30 | kNode_On* = 2 31 | kNode_Off* = 3 32 | kNode_Move* = 4 33 | kNode_Info* = 5 34 | -------------------------------------------------------------------------------- /scnim/PlugIn.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | World, Graph, Unit, Wire, InterfaceTable, Unroll, InlineUnaryOp, InlineBinaryOp, 5 | BoundsMacros, RGen, DemandUnit, clz, msg_iter, Alloca, 6 | 7 | Types,SndBuf,ptrmath 8 | 9 | export 10 | Types, Unit, SndBuf, msg_iter, InterfaceTable, ptrmath 11 | 12 | -------------------------------------------------------------------------------- /scnim/RGen.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Endian, Types, BoundsMacros, Hash 5 | 6 | type 7 | RGen* {.bycopy.} = object 8 | s1*: uint32 9 | s2*: uint32 10 | s3*: uint32 11 | 12 | 13 | #[ 14 | 15 | proc init*(this: var RGen; seed: uint32) 16 | proc trand*(this: var RGen): uint32 17 | proc irand*(this: var RGen; scale: int32): int32 18 | proc irand2*(this: var RGen; scale: int32): int32 19 | proc ilinrand*(this: var RGen; scale: int32): int32 20 | proc ibilinrand*(this: var RGen; scale: int32): int32 21 | proc fcoin*(this: var RGen): cfloat 22 | proc frand*(this: var RGen): cfloat 23 | proc frand2*(this: var RGen): cfloat 24 | proc frand0*(this: var RGen): cfloat 25 | proc frand8*(this: var RGen): cfloat 26 | proc flinrand*(this: var RGen): cfloat 27 | proc fbilinrand*(this: var RGen): cfloat 28 | proc fsum3rand*(this: var RGen): cfloat 29 | proc drand*(this: var RGen): cdouble 30 | proc drand2*(this: var RGen; scale: cdouble): cdouble 31 | proc linrand*(this: var RGen; scale: cdouble): cdouble 32 | proc bilinrand*(this: var RGen; scale: cdouble): cdouble 33 | proc exprandrng*(this: var RGen; lo: cdouble; hi: cdouble): cdouble 34 | proc exprand*(this: var RGen; scale: cdouble): cdouble 35 | proc biexprand*(this: var RGen; scale: cdouble): cdouble 36 | proc sum3rand*(this: var RGen; scale: cdouble): cdouble 37 | 38 | proc init*(this: var RGen; seed: uint32) {.inline.} = 39 | seed = cast[uint32](Hash(cast[cint](seed))) 40 | s1 = 1243598713 xor seed 41 | if s1 < 2: s1 = 1243598713 42 | s2 = 3093459404'i64 xor seed 43 | if s2 < 8: s2 = 3093459404'i64 44 | s3 = 1821928721 xor seed 45 | if s3 < 16: s3 = 1821928721 46 | 47 | proc trand*(s1: var uint32; s2: var uint32; s3: var uint32): uint32 {.inline.} = 48 | 49 | 50 | s1 = ((s1 and (uint32) - 2) shl 12) xor (((s1 shl 13) xor s1) shr 19) 51 | s2 = ((s2 and (uint32) - 8) shl 4) xor (((s2 shl 2) xor s2) shr 25) 52 | s3 = ((s3 and (uint32) - 16) shl 17) xor (((s3 shl 3) xor s3) shr 11) 53 | return s1 xor s2 xor s3 54 | 55 | proc trand*(this: var RGen): uint32 {.inline.} = 56 | 57 | 58 | s1 = ((s1 and (uint32) - 2) shl 12) xor (((s1 shl 13) xor s1) shr 19) 59 | s2 = ((s2 and (uint32) - 8) shl 4) xor (((s2 shl 2) xor s2) shr 25) 60 | s3 = ((s3 and (uint32) - 16) shl 17) xor (((s3 shl 3) xor s3) shr 11) 61 | return s1 xor s2 xor s3 62 | 63 | proc drand*(this: var RGen): cdouble {.inline.} = 64 | when BYTE_ORDER == BIG_ENDIAN: 65 | type 66 | INNER_C_STRUCT_1115050212 {.bycopy.} = object 67 | hi: uint32 68 | lo: uint32 69 | 70 | var du: tuple[i: INNER_C_STRUCT_1115050212, f: cdouble] 71 | else: 72 | type 73 | INNER_C_STRUCT_2676224610 {.bycopy.} = object 74 | lo: uint32 75 | hi: uint32 76 | 77 | var du: tuple[i: INNER_C_STRUCT_2676224610, f: cdouble] 78 | 79 | du.i.hi = 0x41300000 80 | du.i.lo = trand() 81 | return du.f - 1048576.0 82 | 83 | proc frand*(this: var RGen): cfloat {.inline.} = 84 | var u: tuple[i: uint32, f: cfloat] 85 | u.i = 0x3F800000 or (trand() shr 9) 86 | return u.f - 1.0 87 | 88 | proc frand0*(this: var RGen): cfloat {.inline.} = 89 | var u: tuple[i: uint32, f: cfloat] 90 | u.i = 0x3F800000 or (trand() shr 9) 91 | return u.f 92 | 93 | proc frand2*(this: var RGen): cfloat {.inline.} = 94 | var u: tuple[i: uint32, f: cfloat] 95 | u.i = 0x40000000 or (trand() shr 9) 96 | return u.f - 3.0 97 | 98 | proc frand8*(this: var RGen): cfloat {.inline.} = 99 | var u: tuple[i: uint32, f: cfloat] 100 | u.i = 0x3E800000 or (trand() shr 9) 101 | return u.f - 0.375 102 | 103 | proc fcoin*(this: var RGen): cfloat {.inline.} = 104 | var u: tuple[i: uint32, f: cfloat] 105 | u.i = 0x3F800000 or (0x80000000 and trand()) 106 | return u.f 107 | 108 | proc flinrand*(this: var RGen): cfloat {.inline.} = 109 | var a: cfloat = frand() 110 | var b: cfloat = frand() 111 | return sc_min(a, b) 112 | 113 | proc fbilinrand*(this: var RGen): cfloat {.inline.} = 114 | var a: cfloat = frand() 115 | var b: cfloat = frand() 116 | return a - b 117 | 118 | proc fsum3rand*(this: var RGen): cfloat {.inline.} = 119 | return (frand() + frand() + frand() - 1.5) * 0.666666667 120 | 121 | proc irand*(this: var RGen; scale: int32): int32 {.inline.} = 122 | return cast[int32](floor(scale * drand())) 123 | 124 | proc irand2*(this: var RGen; scale: int32): int32 {.inline.} = 125 | return cast[int32](floor((2.0 * scale + 1.0) * drand() - scale)) 126 | 127 | proc ilinrand*(this: var RGen; scale: int32): int32 {.inline.} = 128 | var a: int32 = irand(scale) 129 | var b: int32 = irand(scale) 130 | return sc_min(a, b) 131 | 132 | proc linrand*(this: var RGen; scale: cdouble): cdouble {.inline.} = 133 | var a: cdouble = drand() 134 | var b: cdouble = drand() 135 | return sc_min(a, b) * scale 136 | 137 | proc ibilinrand*(this: var RGen; scale: int32): int32 {.inline.} = 138 | var a: int32 = irand(scale) 139 | var b: int32 = irand(scale) 140 | return a - b 141 | 142 | proc bilinrand*(this: var RGen; scale: cdouble): cdouble {.inline.} = 143 | var a: cdouble = drand() 144 | var b: cdouble = drand() 145 | return (a - b) * scale 146 | 147 | proc exprandrng*(this: var RGen; lo: cdouble; hi: cdouble): cdouble {.inline.} = 148 | return lo * exp(log(hi div lo) * drand()) 149 | 150 | proc exprand*(this: var RGen; scale: cdouble): cdouble {.inline.} = 151 | var z: cdouble 152 | while (z = drand()) == 0.0: discard 153 | return -(log(z) * scale) 154 | 155 | proc biexprand*(this: var RGen; scale: cdouble): cdouble {.inline.} = 156 | var z: cdouble 157 | while (z = drand2(1.0)) == 0.0 or z == -1.0: discard 158 | if z > 0.0: z = log(z) 159 | else: z = -log(-z) 160 | return z * scale 161 | 162 | proc sum3rand*(this: var RGen; scale: cdouble): cdouble {.inline.} = 163 | return (drand() + drand() + drand() - 1.5) * 0.666666667 * scale 164 | 165 | proc drand*(s1: var uint32; s2: var uint32; s3: var uint32): cdouble {.inline.} = 166 | type 167 | INNER_C_STRUCT_969760104 {.bycopy.} = object 168 | hi: uint32 169 | lo: uint32 170 | 171 | var u: tuple[i: INNER_C_STRUCT_969760104, f: cdouble] 172 | u.i.hi = 0x41300000 173 | u.i.lo = trand(s1, s2, s3) 174 | return u.f - 1048576.0 175 | 176 | proc frand*(s1: var uint32; s2: var uint32; s3: var uint32): cfloat {.inline.} = 177 | var u: tuple[i: uint32, f: cfloat] 178 | u.i = 0x3F800000 or (trand(s1, s2, s3) shr 9) 179 | return u.f - 1.0 180 | 181 | proc frand0*(s1: var uint32; s2: var uint32; s3: var uint32): cfloat {.inline.} = 182 | var u: tuple[i: uint32, f: cfloat] 183 | u.i = 0x3F800000 or (trand(s1, s2, s3) shr 9) 184 | return u.f 185 | 186 | proc frand2*(s1: var uint32; s2: var uint32; s3: var uint32): cfloat {.inline.} = 187 | var u: tuple[i: uint32, f: cfloat] 188 | u.i = 0x40000000 or (trand(s1, s2, s3) shr 9) 189 | return u.f - 3.0 190 | 191 | proc frand8*(s1: var uint32; s2: var uint32; s3: var uint32): cfloat {.inline.} = 192 | var u: tuple[i: uint32, f: cfloat] 193 | u.i = 0x3E800000 or (trand(s1, s2, s3) shr 9) 194 | return u.f - 0.375 195 | 196 | proc fcoin*(s1: var uint32; s2: var uint32; s3: var uint32): cfloat {.inline.} = 197 | var u: tuple[i: uint32, f: cfloat] 198 | u.i = 0x3F800000 or (0x80000000 and trand(s1, s2, s3)) 199 | return u.f 200 | 201 | ]# 202 | 203 | -------------------------------------------------------------------------------- /scnim/Rate.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | const 4 | calc_ScalarRate* = 0 5 | calc_BufRate* = 1 6 | calc_FullRate* = 2 7 | calc_DemandRate* = 3 8 | 9 | type 10 | Rate* {.bycopy.} = object 11 | mSampleRate*: cdouble 12 | mSampleDur*: cdouble 13 | mBufDuration*: cdouble 14 | mBufRate*: cdouble 15 | mSlopeFactor*: cdouble 16 | mRadiansPerSample*: cdouble 17 | mBufLength*: cint 18 | mFilterLoops*: cint 19 | mFilterRemain*: cint 20 | mFilterSlope*: cdouble 21 | 22 | -------------------------------------------------------------------------------- /scnim/ScopeBuffer.nim: -------------------------------------------------------------------------------- 1 | ## From InterfaceTable 2 | ## 3 | 4 | type 5 | ScopeBufferHnd* {.bycopy.} = object 6 | internalData*: pointer 7 | data*: ptr cfloat 8 | channels*: uint32 9 | maxFrames*: uint32 10 | 11 | 12 | #proc channel_data*(this: var ScopeBufferHnd; channel: uint32): ptr cfloat = 13 | # return data + (channel * maxFrames) 14 | 15 | #converter `bool`*(this: var ScopeBufferHnd): bool = 16 | # return internalData != 0 17 | -------------------------------------------------------------------------------- /scnim/SndBuf.nim: -------------------------------------------------------------------------------- 1 | 2 | type 3 | SNDFILEag = object 4 | SNDFILE* = SNDFILEag 5 | SndBuf* {.bycopy.} = object 6 | samplerate*: cdouble 7 | sampledur*: cdouble 8 | data*: ptr cfloat 9 | channels*: cint 10 | samples*: cint 11 | frames*: cint 12 | mask*: cint 13 | mask1*: cint 14 | coord*: cint 15 | sndfile*: ptr SNDFILE 16 | 17 | SndBufUpdates* {.bycopy.} = object 18 | reads*: cint 19 | writes*: cint 20 | 21 | 22 | const 23 | coord_None* = 0 24 | coord_Complex* = 1 25 | coord_Polar* = 2 26 | 27 | proc PhaseFrac*(inPhase: uint32): cfloat {.inline.} = 28 | var u: tuple[itemp: uint32, ftemp: cfloat] 29 | u.itemp = 0x3F800000'u32 or (0x007FFF80'u32 and ((inPhase) shl 7)) 30 | return u.ftemp - 1.0 31 | 32 | proc PhaseFrac1*(inPhase: uint32): cfloat {.inline.} = 33 | var u: tuple[itemp: uint32, ftemp: cfloat] 34 | u.itemp = 0x3F800000'u32 or (0x007FFF80'u32 and ((inPhase) shl 7)) 35 | return u.ftemp 36 | 37 | proc lookup*(table: ptr cfloat; phase: int32; mask: int32): cfloat {.inline.} = 38 | #[todo 39 | return table[(phase shr 16) and mask] 40 | ]# 41 | return 0; 42 | 43 | const 44 | xlobits* = 14 45 | xlobits1* = 13 46 | 47 | proc lookupi*(table: ptr cfloat; phase: uint32; mask: uint32): cfloat {.inline.} = 48 | #[todo 49 | var frac: cfloat = PhaseFrac(phase) 50 | var tbl: ptr cfloat = table + ((phase shr 16) and mask) 51 | var a: cfloat = tbl[0] 52 | var b: cfloat = tbl[1] 53 | return a + frac * (b - a) 54 | ]# 55 | return 0; 56 | 57 | proc lookupi2*(table: ptr cfloat; phase: uint32; mask: uint32): cfloat {.inline.} = 58 | #[todo 59 | var frac: cfloat = PhaseFrac1(phase) 60 | var tbl: ptr cfloat = table + ((phase shr 16) and mask) 61 | var a: cfloat = tbl[0] 62 | var b: cfloat = tbl[1] 63 | return a + frac * b 64 | ]# 65 | return 0; 66 | 67 | proc lookupi1*(table0: ptr cfloat; table1: ptr cfloat; pphase: uint32; lomask: int32): cfloat {. 68 | inline.} = 69 | #[todo 70 | var pfrac: cfloat = PhaseFrac1(pphase) 71 | var index: uint32 = ((pphase shr xlobits1) and lomask) 72 | var val1: cfloat = cast[ptr cfloat]((cast[cstring](table0) + index))[] 73 | var val2: cfloat = cast[ptr cfloat]((cast[cstring](table1) + index))[] 74 | return val1 + val2 * pfrac 75 | ]# 76 | return 0; 77 | 78 | proc lininterp*(x: cfloat; a: cfloat; b: cfloat): cfloat {.inline.} = 79 | #[todo 80 | return a + x * (b - a) 81 | ]# 82 | return 0; 83 | 84 | proc cubicinterp*(x: cfloat; y0: cfloat; y1: cfloat; y2: cfloat; y3: cfloat): cfloat {. 85 | inline.} = 86 | #[todo 87 | var c0: cfloat = y1 88 | var c1: cfloat = 0.5 * (y2 - y0) 89 | var c2: cfloat = y0 - 2.5 * y1 + 2.0 * y2 - 0.5 * y3 90 | var c3: cfloat = 0.5 * (y3 - y0) + 1.5 * (y1 - y2) 91 | return ((c3 * x + c2) * x + c1) * x + c0 92 | ]# 93 | return 0; 94 | -------------------------------------------------------------------------------- /scnim/Types.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | type 4 | SCErr* = cint 5 | float32* = cfloat 6 | float64* = cdouble 7 | elem32* {.bycopy.} = object {.union.} 8 | u*: uint32 9 | i*: int32 10 | f*: float32 11 | 12 | elem64* {.bycopy.} = object {.union.} 13 | u*: uint64 14 | i*: int64 15 | f*: float64 16 | 17 | 18 | var kSCNameLen*: cuint = 8 19 | 20 | var kSCNameByteLen*: cuint = 8 * sizeof((int32)) 21 | 22 | template sc_typeof_cast*(x: untyped): untyped = 23 | x 24 | -------------------------------------------------------------------------------- /scnim/Unit.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Types, SndBuf 5 | 6 | type 7 | msg_iter = object 8 | World = object 9 | UnitDef* = object 10 | Graph* = object 11 | Wire* = object 12 | Rate* = object 13 | UnitCtorFunc* = proc (inUnit: ptr Unit) {.cdecl.} 14 | UnitDtorFunc* = proc (inUnit: ptr Unit) {.cdecl.} 15 | UnitCalcFunc* = proc (inThing: ptr Unit; inNumSamples: cint) {.cdecl} 16 | Unit_Extensions* {.bycopy.} = object 17 | todo*: ptr cfloat 18 | 19 | Unit* {.bycopy,inheritable,pure.} = object 20 | mWorld*: ptr World 21 | mUnitDef*: ptr UnitDef 22 | mParent*: ptr Graph 23 | mNumInputs*: uint32 24 | mNumOutputs*: uint32 25 | mCalcRate*: int16 26 | mSpecialIndex*: int16 27 | mParentIndex*: int16 28 | mDone*: int16 29 | mInput: ptr ptr Wire 30 | mOutput: ptr ptr Wire 31 | mRate: ptr Rate 32 | mExtensions*: ptr Unit_Extensions 33 | mInBuf*: ptr ptr cfloat 34 | mOutBuf*: ptr ptr cfloat 35 | mCalcFunc*: proc (inThing: ptr Unit; inNumSamples: cint) {.cdecl.} 36 | mBufLength*: cint 37 | 38 | 39 | var mWorld*: ptr World 40 | 41 | var mUnitDef*: ptr UnitDef 42 | 43 | var mParent*: ptr Graph 44 | 45 | var 46 | mInput*: ptr ptr Wire 47 | mOutput*: ptr ptr Wire 48 | 49 | var mRate*: ptr Rate 50 | 51 | 52 | const 53 | kUnitDef_CantAliasInputsToOutputs* = 1 54 | 55 | #when defined(_WIN32): 56 | 57 | template IN*(index: untyped): untyped = 58 | (unit.mInBuf[index]) 59 | 60 | template OUT*(index: untyped): untyped = 61 | (unit.mOutBuf[index]) 62 | 63 | 64 | template IN0*(index: untyped): untyped = 65 | (IN(index)[0]) 66 | 67 | template OUT0*(index: untyped): untyped = 68 | (OUT(index)[0]) 69 | 70 | 71 | template INRATE*(index: untyped): untyped = 72 | (unit.mInput[index].mCalcRate) 73 | 74 | 75 | template INBUFLENGTH*(index: untyped): untyped = 76 | (unit.mInput[index].mFromUnit.mBufLength) 77 | 78 | 79 | template SETCALC*(`func`: untyped): untyped = 80 | (unit.mCalcFunc = (UnitCalcFunc) and `func`) 81 | 82 | 83 | #[ 84 | const 85 | SAMPLERATE* = (unit.mRate.mSampleRate) 86 | SAMPLEDUR* = (unit.mRate.mSampleDur) 87 | BUFLENGTH* = (unit.mBufLength) 88 | BUFRATE* = (unit.mRate.mBufRate) 89 | BUFDUR* = (unit.mRate.mBufDuration) 90 | FULLRATE* = (unit.mWorld.mFullRate.mSampleRate) 91 | FULLBUFLENGTH* = (unit.mWorld.mFullRate.mBufLength) 92 | ]# 93 | 94 | when defined(SUPERNOVA): 95 | type 96 | buffer_lock2* {.bycopy.}[shared1: static[bool]; shared2: static[bool]] = object 97 | buf1U*: ptr SndBuf 98 | buf2U*: ptr SndBuf 99 | 100 | proc constructbuffer_lock2*[shared1: static[bool]; shared2: static[bool]]( 101 | buf1: ptr SndBuf; buf2: ptr SndBuf): buffer_lock2[shared1, shared2] {.constructor.} = 102 | if buf1 == buf2: 103 | lock1() 104 | return 105 | while true: 106 | lock1() 107 | if lock2(): return 108 | unlock1() 109 | 110 | proc destroybuffer_lock2*[shared1: static[bool]; shared2: static[bool]]( 111 | this: var buffer_lock2[shared1, shared2]) {.destructor.} = 112 | unlock1() 113 | if buf1U != buf2U: unlock2() 114 | 115 | proc lock1*[shared1: static[bool]; shared2: static[bool]]( 116 | this: var buffer_lock2[shared1, shared2]) = 117 | if buf1U.isLocal: return 118 | 119 | if not shared1: buf1U.lock.lock() 120 | else: buf1U.lock.lock_shared() 121 | 122 | proc lock2*[shared1: static[bool]; shared2: static[bool]]( 123 | this: var buffer_lock2[shared1, shared2]): bool = 124 | if buf2U.isLocal: return true 125 | 126 | if not shared2: return buf2U.lock.try_lock() 127 | else: return buf2U.lock.try_lock_shared() 128 | 129 | proc unlock1*[shared1: static[bool]; shared2: static[bool]]( 130 | this: var buffer_lock2[shared1, shared2]) = 131 | if buf1U.isLocal: return 132 | 133 | if not shared1: buf1U.lock.unlock() 134 | else: buf1U.lock.unlock_shared() 135 | 136 | proc unlock2*[shared1: static[bool]; shared2: static[bool]]( 137 | this: var buffer_lock2[shared1, shared2]) = 138 | if buf2U.isLocal: return 139 | 140 | if not shared2: buf2U.lock.unlock() 141 | else: buf2U.lock.unlock_shared() 142 | 143 | type 144 | buffer_lock* {.bycopy.}[shared: static[bool]] = object 145 | bufU*: ptr SndBuf 146 | 147 | proc constructbuffer_lock*[shared: static[bool]](buf: ptr SndBuf): buffer_lock[ 148 | shared] {.constructor.} = 149 | if not buf.isLocal: 150 | if shared: buf.lock.lock_shared() 151 | else: buf.lock.lock() 152 | 153 | proc destroybuffer_lock*[shared: static[bool]](this: var buffer_lock[shared]) {. 154 | destructor.} = 155 | if not bufU.isLocal: 156 | if shared: bufU.lock.unlock_shared() 157 | else: bufU.lock.unlock() 158 | 159 | template ACQUIRE_BUS_AUDIO*(index: untyped): untyped = 160 | unit.mWorld.mAudioBusLocks[index].lock() 161 | 162 | template ACQUIRE_BUS_AUDIO_SHARED*(index: untyped): untyped = 163 | unit.mWorld.mAudioBusLocks[index].lock_shared() 164 | 165 | template RELEASE_BUS_AUDIO*(index: untyped): untyped = 166 | unit.mWorld.mAudioBusLocks[index].unlock() 167 | 168 | template RELEASE_BUS_AUDIO_SHARED*(index: untyped): untyped = 169 | unit.mWorld.mAudioBusLocks[index].unlock_shared() 170 | 171 | template ACQUIRE_SNDBUF*(buf: untyped): void = 172 | while true: 173 | if not buf.isLocal: buf.lock.lock() 174 | if not false: break 175 | 176 | template ACQUIRE_SNDBUF_SHARED*(buf: untyped): void = 177 | while true: 178 | if not buf.isLocal: buf.lock.lock_shared() 179 | if not false: break 180 | 181 | template RELEASE_SNDBUF*(buf: untyped): void = 182 | while true: 183 | if not buf.isLocal: buf.lock.unlock() 184 | if not false: break 185 | 186 | template RELEASE_SNDBUF_SHARED*(buf: untyped): void = 187 | while true: 188 | if not buf.isLocal: buf.lock.unlock_shared() 189 | if not false: break 190 | 191 | template ACQUIRE_BUS_CONTROL*(index: untyped): untyped = 192 | unit.mWorld.mControlBusLock.lock() 193 | 194 | template RELEASE_BUS_CONTROL*(index: untyped): untyped = 195 | unit.mWorld.mControlBusLock.unlock() 196 | 197 | else: 198 | template ACQUIRE_BUS_AUDIO*(index: untyped): void = 199 | nil 200 | 201 | template ACQUIRE_BUS_AUDIO_SHARED*(index: untyped): void = 202 | nil 203 | 204 | template RELEASE_BUS_AUDIO*(index: untyped): void = 205 | nil 206 | 207 | template RELEASE_BUS_AUDIO_SHARED*(index: untyped): void = 208 | nil 209 | 210 | template LOCK_SNDBUF*(buf: untyped): void = 211 | nil 212 | 213 | template LOCK_SNDBUF_SHARED*(buf: untyped): void = 214 | nil 215 | 216 | template LOCK_SNDBUF2*(buf1, buf2: untyped): void = 217 | nil 218 | 219 | template LOCK_SNDBUF2_SHARED*(buf1, buf2: untyped): void = 220 | nil 221 | 222 | template LOCK_SNDBUF2_EXCLUSIVE_SHARED*(buf1, buf2: untyped): void = 223 | nil 224 | 225 | template LOCK_SNDBUF2_SHARED_EXCLUSIVE*(buf1, buf2: untyped): void = 226 | nil 227 | 228 | template ACQUIRE_SNDBUF*(buf: untyped): void = 229 | nil 230 | 231 | template ACQUIRE_SNDBUF_SHARED*(buf: untyped): void = 232 | nil 233 | 234 | template RELEASE_SNDBUF*(buf: untyped): void = 235 | nil 236 | 237 | template RELEASE_SNDBUF_SHARED*(buf: untyped): void = 238 | nil 239 | 240 | template ACQUIRE_BUS_CONTROL*(index: untyped): void = 241 | nil 242 | 243 | template RELEASE_BUS_CONTROL*(index: untyped): void = 244 | nil 245 | 246 | 247 | type 248 | UnitCmdFunc* = proc (unit: ptr Unit; args: ptr msg_iter) {.cdecl.} 249 | PlugInCmdFunc* = proc (inWorld: ptr World; inUserData: pointer; args: ptr msg_iter; 250 | replyAddr: pointer) {.cdecl.} 251 | -------------------------------------------------------------------------------- /scnim/Unroll.nim: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scnim/Wire.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Types, Unit 5 | 6 | type 7 | Wire* {.bycopy.} = object 8 | mCalcRate*: int32 9 | mBuffer*: ptr Types.float32 10 | mScalarValue*: Types.float32 11 | 12 | 13 | var mFromUnit*: ptr Unit 14 | 15 | -------------------------------------------------------------------------------- /scnim/World.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Types, Rate, SndBuf, RGen 5 | 6 | when defined(SUPERNOVA): 7 | discard "forward decl of spin_lock" 8 | discard "forward decl of padded_rw_spinlock" 9 | type 10 | Group* = object 11 | InterfaceTable* = object 12 | HiddenWorld* = object 13 | World* {.bycopy.} = object 14 | mSampleRate*: cdouble 15 | mBufLength*: cint 16 | mBufCounter*: cint 17 | mNumAudioBusChannels*: uint32 18 | mNumControlBusChannels*: uint32 19 | mNumInputs*: uint32 20 | mNumOutputs*: uint32 21 | mAudioBus*: ptr cfloat 22 | mControlBus*: ptr cfloat 23 | mAudioBusTouched*: ptr int32 24 | mControlBusTouched*: ptr int32 25 | mNumSndBufs*: uint32 26 | mSndBufs*: ptr SndBuf 27 | mSndBufsNonRealTimeMirror*: ptr SndBuf 28 | mSndBufUpdates*: ptr SndBufUpdates 29 | mFullRate*: Rate 30 | mBufRate*: Rate 31 | mNumRGens*: uint32 32 | mRGen*: ptr RGen 33 | mNumUnits*: uint32 34 | mNumGraphs*: uint32 35 | mNumGroups*: uint32 36 | mSampleOffset*: cint 37 | mNRTLock*: pointer 38 | mNumSharedControls*: uint32 39 | mSharedControls*: ptr cfloat 40 | mRealTime*: bool 41 | mRunning*: bool 42 | mDumpOSC*: cint 43 | mDriverLock*: pointer 44 | mSubsampleOffset*: cfloat 45 | mVerbosity*: cint 46 | mErrorNotification*: cint 47 | mLocalErrorNotification*: cint 48 | mRendezvous*: bool 49 | mRestrictedPath*: cstring 50 | 51 | 52 | var hw*: ptr HiddenWorld 53 | 54 | var ft*: ptr InterfaceTable 55 | 56 | var mTopGroup*: ptr Group 57 | 58 | proc World_GetBuf*(inWorld: ptr World; index: uint32): ptr SndBuf {.inline.} = 59 | let b = cast[uint32](inWorld.mNumSndBufs) 60 | let i = if index > b: 0'u32 else: index 61 | return cast[ptr SndBuf](b + i) 62 | 63 | proc World_GetNRTBuf*(inWorld: ptr World; index: uint32): ptr SndBuf {.inline.} = 64 | let b = cast[uint32](inWorld.mNumSndBufs) 65 | let i = if index > b: 0'u32 else: index 66 | let c = cast[uint32](inWorld.mSndBufsNonRealTimeMirror) 67 | return cast[ptr SndBuf](c + i) 68 | 69 | type 70 | LoadPlugInFunc* = proc (a2: ptr InterfaceTable) 71 | UnLoadPlugInFunc* = proc () 72 | -------------------------------------------------------------------------------- /scnim/clz.nim: -------------------------------------------------------------------------------- 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 | ## 22 | ## count leading zeroes function and those that can be derived from it 23 | ## 24 | ## 25 | -------------------------------------------------------------------------------- /scnim/fftlib.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | const 5 | FFT_MINSIZE* = 8 6 | FFT_LOG2_MINSIZE* = 3 7 | FFT_MAXSIZE* = 32768 8 | FFT_LOG2_MAXSIZE* = 15 9 | 10 | 11 | const 12 | FFT_ABSOLUTE_MAXSIZE* = 262144 13 | FFT_LOG2_ABSOLUTE_MAXSIZE* = 18 14 | FFT_LOG2_ABSOLUTE_MAXSIZE_PLUS1* = 19 15 | 16 | #discard "forward decl of scfft" 17 | type 18 | scfft = object 19 | SCFFT_Allocator* {.bycopy.} = object 20 | 21 | 22 | #proc alloc*(this: var SCFFT_Allocator; size: csize): pointer 23 | #proc free*(this: var SCFFT_Allocator; `ptr`: pointer) 24 | 25 | type 26 | SCFFT_Direction* = enum 27 | kBackward = 0, kForward = 1 28 | 29 | 30 | 31 | type 32 | SCFFT_WindowFunction* = enum 33 | kRectWindow = -1, kSineWindow = 0, kHannWindow = 1 34 | 35 | 36 | 37 | #proc scfft_create*(fullsize: csize; winsize: csize; wintype: SCFFT_WindowFunction; 38 | # indata: ptr cfloat; outdata: ptr cfloat; forward: SCFFT_Direction; 39 | # alloc: var SCFFT_Allocator): ptr scfft 40 | 41 | #proc scfft_dofft*(f: ptr scfft) 42 | #proc scfft_doifft*(f: ptr scfft) 43 | 44 | #proc scfft_destroy*(f: ptr scfft; alloc: var SCFFT_Allocator) 45 | -------------------------------------------------------------------------------- /scnim/msg_iter.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | import 4 | Endian, Types 5 | 6 | #[ 7 | proc OSCstrskip*(str: cstring): cstring {.inline.} = 8 | while true: 9 | inc(str, 4) 10 | if not str[-1]: break 11 | return str 12 | 13 | 14 | proc OSCstrlen*(strin: cstring): csize {.inline.} = 15 | return OSCstrskip(strin) - strin 16 | 17 | 18 | proc OSCfloat*(inData: cstring): float32 {.inline.} = 19 | var elem: elem32 20 | elem.u = ntohl(cast[ptr uint32](inData)[]) 21 | return elem.f 22 | 23 | proc OSCint*(inData: cstring): int32 {.inline.} = 24 | return cast[int32](ntohl(cast[ptr uint32](inData)[])) 25 | 26 | proc OSCtime*(inData: cstring): int64 {.inline.} = 27 | return (cast[int64](ntohl(cast[ptr uint32](inData)[])) shl 32) + 28 | (ntohl(cast[ptr uint32]((inData + 4))[])) 29 | 30 | proc OSCdouble*(inData: cstring): float64 {.inline.} = 31 | var slot: elem64 32 | slot.i = (cast[int64](ntohl(cast[ptr uint32](inData)[])) shl 32) + 33 | (ntohl(cast[ptr uint32]((inData + 4))[])) 34 | return slot.f 35 | 36 | ]# 37 | 38 | type 39 | msg_iter* {.bycopy.} = object 40 | data*: cstring 41 | rdpos*: cstring 42 | endpos*: cstring 43 | tags*: cstring 44 | size*: cint 45 | count*: cint 46 | 47 | 48 | #proc constructsc_msg_iter*(): msg_iter {.constructor.} 49 | #proc constructsc_msg_iter*(inSize: cint; inData: cstring): msg_iter {.constructor.} 50 | #proc init*(this: var msg_iter; inSize: cint; inData: cstring) 51 | #proc gett*(this: var msg_iter; defaultValue: int64 = 1): int64 52 | #proc geti*(this: var msg_iter; defaultValue: int32 = 0): int32 53 | #proc getf*(this: var msg_iter; defaultValue: Types.float32 = 0.0): Types.float32 54 | #proc getd*(this: var msg_iter; defaultValue: Types.float64 = 0.0): Types.float64 55 | #proc gets*(this: var msg_iter; defaultValue: cstring = ""): cstring 56 | #proc gets4*(this: var msg_iter; defaultValue: cstring = ""): ptr int32 57 | #proc getbsize*(this: var msg_iter): csize 58 | #proc getb*(this: var msg_iter; outData: cstring; inSize: csize) 59 | #proc skipb*(this: var msg_iter) 60 | 61 | #proc remain*(this: var msg_iter): csize = 62 | # return endpos - rdpos 63 | 64 | #proc nextTag*(this: var msg_iter; defaultTag: char = 'f'): char = 65 | # return if tags: tags[count] else: defaultTag 66 | 67 | 68 | -------------------------------------------------------------------------------- /scnim/ptrmath.nim: -------------------------------------------------------------------------------- 1 | # Jehan @ http://forum.nim-lang.org/t/1188/1 2 | template `+`*[T](p: ptr T, off: int): ptr T = 3 | cast[ptr type(p[])](cast[ByteAddress](p) +% off * sizeof(p[])) 4 | 5 | template `+=`*[T](p: ptr T, off: int) = 6 | p = p + off 7 | 8 | template `-`*[T](p: ptr T, off: int): ptr T = 9 | cast[ptr type(p[])](cast[ByteAddress](p) -% off * sizeof(p[])) 10 | 11 | template `-=`*[T](p: ptr T, off: int) = 12 | p = p - off 13 | 14 | template `[]`*[T](p: ptr T, off: int): T = 15 | (p + off)[] 16 | 17 | template `[]=`*[T](p: ptr T, off: int, val: T) = 18 | (p + off)[] = val 19 | -------------------------------------------------------------------------------- /scnim/sndfile_stub.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | type 4 | SNDFILE_tag = object 5 | SNDFILE* = SNDFILE_tag 6 | 7 | 8 | type 9 | sf_count_t* = cint 10 | 11 | const 12 | SF_COUNT_MAX* = 0x7FFFFFFFFFFFFFFF'i64 13 | 14 | 15 | type 16 | SF_INFO* {.bycopy.} = object 17 | frames*: sf_count_t 18 | samplerate*: cint 19 | channels*: cint 20 | format*: cint 21 | sections*: cint 22 | seekable*: cint 23 | 24 | --------------------------------------------------------------------------------