2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "SC_SndBuf.h"
28 typedef void (*UnitCtorFunc
)(struct Unit
* inUnit
);
29 typedef void (*UnitDtorFunc
)(struct Unit
* inUnit
);
31 typedef void (*UnitCalcFunc
)(struct Unit
*inThing
, int inNumSamples
);
33 struct SC_Unit_Extensions
{
40 struct UnitDef
*mUnitDef
;
41 struct Graph
*mParent
;
42 uint32 mNumInputs
, mNumOutputs
; // changed from uint16 for synthdef ver 2
44 int16 mSpecialIndex
; // used by unary and binary ops
47 struct Wire
**mInput
, **mOutput
;
49 SC_Unit_Extensions
* mExtensions
; //future proofing and backwards compatibility; used to be SC_Dimension struct pointer
50 float **mInBuf
, **mOutBuf
;
52 UnitCalcFunc mCalcFunc
;
56 typedef struct Unit Unit
;
59 kUnitDef_CantAliasInputsToOutputs
= 1
63 // Win32 headers (included by C std library headers) define IN and OUT macros
64 // for their own purposes.
69 // These return float* pointers to input and output buffers.
70 #define IN(index) (unit->mInBuf[index])
71 #define OUT(index) (unit->mOutBuf[index])
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])
77 // get the rate of the input.
78 #define INRATE(index) (unit->mInput[index]->mCalcRate)
80 // get the blocksize of the input
81 #define INBUFLENGTH(index) (unit->mInput[index]->mFromUnit->mBufLength)
83 // set the calculation function
84 #define SETCALC(func) (unit->mCalcFunc = (UnitCalcFunc)&func)
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)
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)
100 template <bool shared1
, bool shared2
>
103 buffer_lock2(const SndBuf
* buf1
, const SndBuf
* buf2
):
104 buf1_(buf1
), buf2_(buf2
)
136 buf1_
->lock
.lock_shared();
145 return buf2_
->lock
.try_lock();
147 return buf2_
->lock
.try_lock_shared();
156 buf1_
->lock
.unlock();
158 buf1_
->lock
.unlock_shared();
167 buf2_
->lock
.unlock();
169 buf2_
->lock
.unlock_shared();
172 const SndBuf
* buf1_
;
173 const SndBuf
* buf2_
;
176 template <bool shared
>
179 buffer_lock(const SndBuf
* buf
):
184 buf
->lock
.lock_shared();
192 if (!buf_
->isLocal
) {
194 buf_
->lock
.unlock_shared();
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()
208 #define LOCK_SNDBUF(buf) buffer_lock<false> lock_##buf(buf)
209 #define LOCK_SNDBUF_SHARED(buf) buffer_lock<true> lock_##buf(buf);
211 #define LOCK_SNDBUF2(buf1, buf2) buffer_lock2<false, false> lock_##buf1##_##buf2(buf1, buf2);
212 #define LOCK_SNDBUF2_SHARED(buf1, buf2) buffer_lock2<true, true> lock_##buf1##_##buf2(buf1, buf2);
213 #define LOCK_SNDBUF2_EXCLUSIVE_SHARED(buf1, buf2) buffer_lock2<false, true> lock_##buf1##_##buf2(buf1, buf2);
214 #define LOCK_SNDBUF2_SHARED_EXCLUSIVE(buf1, buf2) buffer_lock2<true, false> lock_##buf1##_##buf2(buf1, buf2);
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)
222 #define ACQUIRE_BUS_CONTROL(index) unit->mWorld->mControlBusLock->lock()
223 #define RELEASE_BUS_CONTROL(index) unit->mWorld->mControlBusLock->unlock()
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)
232 #define LOCK_SNDBUF(buf)
233 #define LOCK_SNDBUF_SHARED(buf)
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)
240 #define ACQUIRE_SNDBUF(buf)
241 #define ACQUIRE_SNDBUF_SHARED(buf)
242 #define RELEASE_SNDBUF(buf)
243 #define RELEASE_SNDBUF_SHARED(buf)
245 #define ACQUIRE_BUS_CONTROL(index)
246 #define RELEASE_BUS_CONTROL(index)
250 // macros to grab a Buffer reference from the buffer indicated by the UGen's FIRST input
252 float fbufnum = ZIN0(0); \
253 if (fbufnum < 0.f) { fbufnum = 0.f; } \
254 if (fbufnum != unit->m_fbufnum) { \
255 uint32 bufnum = (int)fbufnum; \
256 World *world = unit->mWorld; \
257 if (bufnum >= world->mNumSndBufs) { \
258 int localBufNum = bufnum - world->mNumSndBufs; \
259 Graph *parent = unit->mParent; \
260 if(localBufNum <= parent->localBufNum) { \
261 unit->m_buf = parent->mLocalSndBufs + localBufNum; \
264 unit->m_buf = world->mSndBufs + bufnum; \
267 unit->m_buf = world->mSndBufs + bufnum; \
269 unit->m_fbufnum = fbufnum; \
271 SndBuf *buf = unit->m_buf; \
273 float *bufData __attribute__((__unused__)) = buf->data; \
274 uint32 bufChannels __attribute__((__unused__)) = buf->channels; \
275 uint32 bufSamples __attribute__((__unused__)) = buf->samples; \
276 uint32 bufFrames = buf->frames; \
277 int mask __attribute__((__unused__)) = buf->mask; \
278 int guardFrame __attribute__((__unused__)) = bufFrames - 2;
280 #define GET_BUF_SHARED \
281 float fbufnum = ZIN0(0); \
282 if (fbufnum < 0.f) { fbufnum = 0.f; } \
283 if (fbufnum != unit->m_fbufnum) { \
284 uint32 bufnum = (int)fbufnum; \
285 World *world = unit->mWorld; \
286 if (bufnum >= world->mNumSndBufs) { \
287 int localBufNum = bufnum - world->mNumSndBufs; \
288 Graph *parent = unit->mParent; \
289 if(localBufNum <= parent->localBufNum) { \
290 unit->m_buf = parent->mLocalSndBufs + localBufNum; \
293 unit->m_buf = world->mSndBufs + bufnum; \
296 unit->m_buf = world->mSndBufs + bufnum; \
298 unit->m_fbufnum = fbufnum; \
300 const SndBuf *buf = unit->m_buf; \
301 LOCK_SNDBUF_SHARED(buf); \
302 const float *bufData __attribute__((__unused__)) = buf->data; \
303 uint32 bufChannels __attribute__((__unused__)) = buf->channels; \
304 uint32 bufSamples __attribute__((__unused__)) = buf->samples; \
305 uint32 bufFrames = buf->frames; \
306 int mask __attribute__((__unused__)) = buf->mask; \
307 int guardFrame __attribute__((__unused__)) = bufFrames - 2;
309 #define SIMPLE_GET_BUF \
310 float fbufnum = ZIN0(0); \
311 fbufnum = sc_max(0.f, fbufnum); \
312 if (fbufnum != unit->m_fbufnum) { \
313 uint32 bufnum = (int)fbufnum; \
314 World *world = unit->mWorld; \
315 if (bufnum >= world->mNumSndBufs) { \
316 int localBufNum = bufnum - world->mNumSndBufs; \
317 Graph *parent = unit->mParent; \
318 if(localBufNum <= parent->localBufNum) { \
319 unit->m_buf = parent->mLocalSndBufs + localBufNum; \
322 unit->m_buf = world->mSndBufs + bufnum; \
325 unit->m_buf = world->mSndBufs + bufnum; \
327 unit->m_fbufnum = fbufnum; \
329 SndBuf *buf = unit->m_buf; \
331 #define SIMPLE_GET_BUF_EXCLUSIVE \
335 #define SIMPLE_GET_BUF_SHARED \
337 LOCK_SNDBUF_SHARED(buf);
339 // macros to get pseudo-random number generator, and put its state in registers
341 RGen& rgen = *unit->mParent->mRGen; \
342 uint32 s1 = rgen.s1; \
343 uint32 s2 = rgen.s2; \
350 typedef void (*UnitCmdFunc
)(struct Unit
*unit
, struct sc_msg_iter
*args
);
351 typedef void (*PlugInCmdFunc
)(World
*inWorld
, void* inUserData
, struct sc_msg_iter
*args
, void *replyAddr
);