1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #pragma once
22
23 #include "SC_PlugIn.h"
24 #include "SCComplex.h"
25
26 #include <string.h>
27
28 struct SCComplexBuf {
29 float dc, nyq;
30 SCComplex bin[1];
31 };
32
33 struct SCPolarBuf {
34 float dc, nyq;
35 SCPolar bin[1];
36 };
37
ToPolarApx(SndBuf * buf)38 static inline SCPolarBuf* ToPolarApx(SndBuf* buf) {
39 if (buf->coord == coord_Complex) {
40 SCComplexBuf* p = (SCComplexBuf*)buf->data;
41 int numbins = (buf->samples - 2) >> 1;
42 for (int i = 0; i < numbins; ++i) {
43 p->bin[i].ToPolarApxInPlace();
44 }
45 buf->coord = coord_Polar;
46 }
47
48 return (SCPolarBuf*)buf->data;
49 }
50
ToComplexApx(SndBuf * buf)51 static inline SCComplexBuf* ToComplexApx(SndBuf* buf) {
52 if (buf->coord == coord_Polar) {
53 SCPolarBuf* p = (SCPolarBuf*)buf->data;
54 int numbins = (buf->samples - 2) >> 1;
55 for (int i = 0; i < numbins; ++i) {
56 p->bin[i].ToComplexApxInPlace();
57 }
58 buf->coord = coord_Complex;
59 }
60 return (SCComplexBuf*)buf->data;
61 }
62
63 struct PV_Unit : Unit {};
64
65
66 #define sc_clipbuf(x, hi) ((x) >= (hi) ? 0 : ((x) < 0 ? 0 : (x)))
67
68 // for operation on one buffer
69 #define PV_GET_BUF \
70 float fbufnum = ZIN0(0); \
71 if (fbufnum < 0.f) { \
72 ZOUT0(0) = -1.f; \
73 return; \
74 } \
75 ZOUT0(0) = fbufnum; \
76 uint32 ibufnum = (uint32)fbufnum; \
77 World* world = unit->mWorld; \
78 SndBuf* buf; \
79 if (ibufnum >= world->mNumSndBufs) { \
80 int localBufNum = ibufnum - world->mNumSndBufs; \
81 Graph* parent = unit->mParent; \
82 if (localBufNum <= parent->localBufNum) { \
83 buf = parent->mLocalSndBufs + localBufNum; \
84 } else { \
85 buf = world->mSndBufs; \
86 } \
87 } else { \
88 buf = world->mSndBufs + ibufnum; \
89 } \
90 LOCK_SNDBUF(buf); \
91 int numbins = (buf->samples - 2) >> 1;
92
93
94 // for operation on two input buffers, result goes in first one.
95 #define PV_GET_BUF2 \
96 float fbufnum1 = ZIN0(0); \
97 float fbufnum2 = ZIN0(1); \
98 if (fbufnum1 < 0.f || fbufnum2 < 0.f) { \
99 ZOUT0(0) = -1.f; \
100 return; \
101 } \
102 ZOUT0(0) = fbufnum1; \
103 uint32 ibufnum1 = (int)fbufnum1; \
104 uint32 ibufnum2 = (int)fbufnum2; \
105 World* world = unit->mWorld; \
106 SndBuf* buf1; \
107 SndBuf* buf2; \
108 if (ibufnum1 >= world->mNumSndBufs) { \
109 int localBufNum = ibufnum1 - world->mNumSndBufs; \
110 Graph* parent = unit->mParent; \
111 if (localBufNum <= parent->localBufNum) { \
112 buf1 = parent->mLocalSndBufs + localBufNum; \
113 } else { \
114 buf1 = world->mSndBufs; \
115 } \
116 } else { \
117 buf1 = world->mSndBufs + ibufnum1; \
118 } \
119 if (ibufnum2 >= world->mNumSndBufs) { \
120 int localBufNum = ibufnum2 - world->mNumSndBufs; \
121 Graph* parent = unit->mParent; \
122 if (localBufNum <= parent->localBufNum) { \
123 buf2 = parent->mLocalSndBufs + localBufNum; \
124 } else { \
125 buf2 = world->mSndBufs; \
126 } \
127 } else { \
128 buf2 = world->mSndBufs + ibufnum2; \
129 } \
130 LOCK_SNDBUF2(buf1, buf2); \
131 if (buf1->samples != buf2->samples) \
132 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) \
140 return;
141
142 extern InterfaceTable* ft;
143